diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..64e0b29 --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +# $Id$ +# Application Makefile (C) 2002-2004 The UbixOS Project + +#Compiler +CC = gcc +CXX = g++ + +#Linker +LD = ld + +#Binary File Name +BINARY = tuvebridge + +#Delete Program +REMOVE = rm -f + +#Objects +OBJS = main.o socket.o + +LIBRARIES = -lthr -L/usr/local/lib/mysql -lmysqlclient +CFLAGS = -Wall -W -ggdb +INCLUDES = -I/usr/local/include + +# Link The Binary +$(BINARY) : $(OBJS) + $(CC) $(CFLAGS) -o $@ $(LIBRARIES) $(OBJS) + +# Compile the source files +.cc.o: + $(CXX) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +.cc.s: + $(CXX) $(CFLAGS) $(INCLUDES) -S -o $@ $< + +.c.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +.c.s: + $(CC) $(CFLAGS) $(INCLUDES) -S -o $@ $< + +.S.o: + $(CC) $(CLFAGS) $(INCLUDES) -c -o $@ $< + +# Clean Up The junk +clean: + $(REMOVE) $(OBJS) $(BINARY) *.core diff --git a/main.c b/main.c new file mode 100644 index 0000000..0e13faa --- /dev/null +++ b/main.c @@ -0,0 +1,225 @@ +/* + Tuved Server + (C) 2007 Christopher Olsen + + $Id$ +*/ + +#include +#include +#include +#include + +#include "tuvebot.h" + +FILE *logFile = 0x0; +int logLevel = 1; +int highSock = 0x0; +int joinChan = 0x0; +time_t startTime; + +void usage(); +int botProcessData(char *data); + +int main(int argc,char **argv) { + int ch; + int doFork = 0x1; + int readSocks = 0x0; + int t = 0x0; + fd_set readSet; + char data[1024]; + struct timeval timeout = {30,0}; + + /* Get our start time */ + startTime = time(NULL); + + while ((ch = getopt(argc,argv,"sl:nd:")) != -1) { + switch (ch) { + case 's': + logFile = stdout; + break; + case 'l': + logFile = fopen(optarg,"a"); + break; + case 'n': + doFork = 0; + break; + case 'd': + logLevel = atoi(optarg); + if (logLevel < 1) + logLevel = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + + /* Prepare log file */ + if (logFile == 0x0) + logFile = fopen(LOG_FILE,"a"); + + /* Fork into background unless specified not to do so */ + if (doFork == 1) + if (fork() != 0x0) + exit(1); + + writeLog(0,"TUveBOT Starting: %i\n",startTime); + + dbInit(); + + srandom(time(NULL)); + + pthread_t threads[NUM_THREADS]; + + pthread_create(&threads[t], NULL, botCMD_Thread, (void *)t); + t = 1; + pthread_create(&threads[t], NULL, botSCHD_Thread, (void *)t); + + pthread_mutex_init(&chanMutex, NULL); + + sConnect(SERVER_HOST,SERVER_PORT); + + + while (1) { + + /* Build our readSet */ + sGetConnections(&readSet); + + readSocks = select(highSock+1,&readSet,0x0,0x0,&timeout); + + if (readSocks < 0) { + perror("select failed"); + exit(0x1); + } + + if (FD_ISSET(mySocket,&readSet) != 0x0) { + memset(&data,0x0,1024); + if (sReadSocket(&data,1024) == -1) { + writeLog(0,"Socket Died!\n"); + sConnect(SERVER_HOST,SERVER_PORT); + //exit(1); + } + else { + botProcessData(data); + } + } + + /* Flush the log file */ + fflush(logFile); + } + + return(0); + } + +void usage() { + printf("%s\n","usage: tuved -n -s [-l logfile] [-d debuglevel]"); + exit(1); + } + + +int writeLog(int level,char const * __restrict fmt, ...) { + int ret; + va_list ap; + + if (level > logLevel) + return(0x0); + + va_start(ap, fmt); + ret = vfprintf(logFile, fmt, ap); + va_end(ap); + + return(ret); + } + +int botProcessMsg(char *data) { + char *nick; + char *chan; + char *cmdData; + char *str_tok = 0x0; + botChanList_t *tmpChan; + int i; + + nick = strtok_r(data,":",&str_tok); + chan = strtok_r(NULL,":",&str_tok); + cmdData = strtok_r(NULL,"\n",&str_tok); + + if ((!strcasecmp(nick,"MrOlsen")) && (!strcasecmp(chan,"PRIVMSG"))) { + printf("cmdData: [%s]\n",cmdData); + sWriteSocket("%s\n",cmdData); + } + else if (!strcasecmp(nick,"MrOlsen") && !strcasecmp(cmdData,".ss")) { + tmpChan = botFindChan(chan); + for (i = tmpChan->sCur;i < tmpChan->sCount;i++) { + sWriteSocket("MSG %s:Time: %i,VID: %i\n",chan,tmpChan->schedule[i][0],tmpChan->schedule[i][1]); + } + } + return(0x0); + } + +int botProcessData(char *dataFresh) { + char *cmd = 0x0; + char *cmdData = 0x0; + char *str_tok = 0x0; + char *data = 0x0; + char *data2 = 0x0; + char *data_tok = 0x0; + + data = strtok_r(dataFresh,"\n",&data_tok); + data2 = strtok_r(NULL,"\n",&data_tok); + + Head: + + if (data == 0x0) { + data = data2; + data2 = strtok_r(NULL,"\n",&data_tok); + } + + cmd = data; + + if (strstr(cmd,":")) { + cmd = strtok_r(data,":",&str_tok); + cmdData = strtok_r(NULL,"\n",&str_tok); + str_tok = 0x0; + writeLog(3,"DATA: (%s)CMD: [%s], Data: [%s]\n",data,cmd,cmdData); + } + else + writeLog(3,"DATA: (%s)CMD: [%s]\n",data,cmd); + + if (cmd == 0x0) + return(0x0); + + if (strstr(cmd,"PING")) { + sWriteSocket("PONG!\n"); + } + else if (!strcmp(cmd,"IDENT")) { + sWriteSocket("MSG TUveD:.tv login tuvebot 5558585\n"); + joinChan = 1; + } + else if (!strcmp(cmd,"MSG")) + botProcessMsg(cmdData); + else if (!strcmp(cmd,"TOPIC")) + botStoreTopic(cmdData); + else if (!strcmp(cmd,"CURPOS")) + botSetCurSong(cmdData); + else if (!strcmp(cmd,"MODE")) + botSetMode(cmdData); + else if (!strcmp(cmd,"JOIN")) + botDoJoin(cmdData); + else if (!strcmp(cmd,"EMOTE")) + botDoEmote(cmdData); + else if (!strcmp(cmd,"LOGIN")) + botDoLogin(cmdData); + else { + writeLog(0,"Unknown Command: [%s]\n",cmd); + } + + if (data2 != 0x0) { + data = 0x0; + goto Head; + } + + return(0x0); + } diff --git a/socket.c b/socket.c new file mode 100644 index 0000000..4023220 --- /dev/null +++ b/socket.c @@ -0,0 +1,100 @@ +/* + tuvebot - Socket Code + (C) 2007 Christopher Olsen + + $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tuvebot.h" + +int mySocket = 0x0; +int connected = 0x0; + +int sConnect(const char *host,int port) { + struct sockaddr_in rmAddr; // remote address information + struct hostent *hp; + int att; + + connected = 0; + + for (att = 1;att < 10;att++) { + if (mySocket != 0x0) + close(mySocket); + + if ((mySocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + perror("socket"); + exit(1); + } + + writeLog(0,"Connecting to: %s, port %i, socket %i, attempt: %i\n",host,port,mySocket,att); + + hp = gethostbyname(host); + + bzero(&rmAddr,sizeof(struct sockaddr_in)); + + //memcpy(&(rmAddr.sin_addr.s_addr),*(hp->h_addr_list),sizeof(struct in_addr)); + bcopy((char *)hp->h_addr,(char *)&rmAddr.sin_addr.s_addr,hp->h_length); + + rmAddr.sin_family = AF_INET; // host byte order + rmAddr.sin_port = htons(port); // short, network byte order + memset(rmAddr.sin_zero, '\0', sizeof rmAddr.sin_zero); + + if (connect(mySocket,&rmAddr,sizeof(rmAddr)) == 0x0) + break; + + writeLog(1,"Error Connecting: %i.\n",errno); + sleep(5); + } + + writeLog(2,"my Socket: [%i]\n",mySocket); + + sWriteSocket("IDENT TUveBOT:1234567\n"); + + return(0x0); + } + +ssize_t sReadSocket(void *buffer,size_t length) { + ssize_t recLen = 0x0; + + recLen = read(mySocket,buffer,length); + if (recLen == 0x0) + return(-1); + + return(recLen); + } + +int sWriteSocket(char const * __restrict fmt, ...) { + char data[1024]; + int len = 0x0; + va_list ap; + + va_start(ap,fmt); + len = vsnprintf(data,1023,fmt,ap); + va_end(ap); + + data[len++] = '\n'; + + send(mySocket,data,len,MSG_NOSIGNAL); + return(0x0); + } + +int sGetConnections(fd_set *readset) { + + FD_ZERO(readset); + + FD_SET(mySocket,readset); + + highSock = mySocket + 1; + + return(0x0); + } + diff --git a/tuvebridge.h b/tuvebridge.h new file mode 100644 index 0000000..f7df5a2 --- /dev/null +++ b/tuvebridge.h @@ -0,0 +1,127 @@ +/* + (c) 2007 Christopher Olsen + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SERVER_HOST "127.0.0.1" //"Ivorytower.UbixOnline.com" +#define SERVER_PORT 9999 + +#define NUM_THREADS 2 +#define MYPORT 9999 // the port users will be connecting to +#define BACKLOG 10 // how many pending connections queue will hold +#define LOG_FILE "./logs/tuvebot.log" +#define PING_INTERVAL 20 +#define MAX_PING 2 +#define MAX_COUNT 2 +#define MAX_TOPIC_LEN 128 +#define MAX_CHAN_LEN 32 +#define VERSION "v0.40" +#define MYSQL_HOST_NAME "localhost" +#define MYSQL_USERNAME "tuve" +#define MYSQL_PASSWORD "5558585" +#define MYSQL_DB_NAME "tuve" + +/* Cannel Modes */ +#define CHAN_MODES 8 // Count Of Channel Modes +#define CHAN_RANDOM 0 // Random Videos +#define CHAN_QUEUE 1 // Users Queues +#define CHAN_TIME 2 // Video Time Limit +#define CHAN_RATING 3 // Video Parental Rating +#define CHAN_CLASS 4 // Video Classs +#define CHAN_LIVE 5 // Channel Is In Live Stream Mode +#define CHAN_EXCLUSIVE 6 // Channel Is In Exclusive Mode +#define CHAN_NOADS 7 // Channel Has No Advertisements + +typedef struct botChanList { + struct botChanList *prev; + struct botChanList *next; + int modes[CHAN_MODES]; + char topic[MAX_TOPIC_LEN]; + char channel[MAX_CHAN_LEN]; + short updated; + short sM; + unsigned int schedule[10][3]; + int sCount; + int sCur; + int cid; + } botChanList_t; + +typedef struct myConnections { + struct myConnections *prev; + struct myConnections *next; + int fd; + int recLen; + char data[1024]; + char host[128]; + time_t signedOn; + } myConnections_t; + +/* + Global variables very not safe + */ + +extern int mySocket; +extern int connected; +extern pthread_mutex_t chanMutex; +extern botChanList_t *chans; + +extern int highSock; +extern FILE *logFile; +extern time_t startTime; +extern int joinChan; + +/* Socket Functions */ +int sConnect(const char *host,int port); +ssize_t sReadSocket(void *buffer,size_t length); +int sGetConnections(fd_set *readset); +int sWriteSocket(char const * __restrict fmt, ...); + +/* Log Functions */ +int writeLog(int level,char const * __restrict, ...); + +/* Channel Functions */ +int tuveChanList(myConnections_t *userConnection); +int tuveChanPart(const char *channel,myConnections_t *userConnection); +int tuveChanJoin(const char *channel,myConnections_t *userConnection); +int tuveAddChan(const char *channel,myConnections_t *userConnection); +int tuveAddToChanList(const char *channel,myConnections_t *userConnection); +int tuveSendAllInChan(const char *channel,myConnections_t *userConnection,char *output); +int tuveDelUserChans(myConnections_t *userConnection,char *msg); +int tuveRemoveFromChanList(const char *channel,myConnections_t *userConnection); +int tuveSetTopic(myConnections_t *userConnection,char *chan,char *topic); +int tuveSendAllInUsersChans(myConnections_t *userConnection,char *output); +int tuveDelChan(const char *channel,myConnections_t *userConnection); +int tuveKick(char *by,char *chan,char *nick,char *msg); +int tuveBan(const char *channel,const char *nick); +int tuveUnBan(const char *channel,const char *nick); +int tuveVerifyBan(const char *channel,const char *nick); + +/* Bot Functions */ +void *tuveBotThread(void *threadid); +int tuveBotCMD(myConnections_t *userConnection,char *chan,char *data); +int tuveBotSetSong(char *chan,char *playTime,char *file,char *title); +int tuveBotNoSong(char *chan); + +/* Database Functions */ +int dbInit(); +MYSQL_RES *dbQuery(const char *query,short type); + +/* Bot Functions */ +int botJoinChans(); +int botStoreTopic(char *data); +void *botCMD_Thread(void *threadid); +void *botSCHD_Thread(void *threadid); +botChanList_t *botFindChan(char *channel); +botChanList_t *botAddChan(char *channel); +int botDoLogin(char *cmdData);