From 80c6a2a928f5ff98f19df4210599342294025903 Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sat, 23 Apr 2005 14:27:52 +0000 Subject: [PATCH] added first part of channel handling --- mbtask/taskchat.c | 203 ++++++++++++++++++++++++++++++++++++++++++++-- mbtask/taskibc.c | 100 ++++++++++++++++++++++- mbtask/taskibc.h | 2 + 3 files changed, 293 insertions(+), 12 deletions(-) diff --git a/mbtask/taskchat.c b/mbtask/taskchat.c index 0f42849d..bb013443 100644 --- a/mbtask/taskchat.c +++ b/mbtask/taskchat.c @@ -36,7 +36,9 @@ #include "taskibc.h" +#ifndef USE_EXPERIMENT #define MAXCHANNELS 10 /* Maximum chat channels */ +#endif #define MAXMESSAGES 100 /* Maximum ringbuffer for messages */ @@ -52,7 +54,11 @@ typedef struct _ch_user_rec { char name[10]; /* Unix name */ char nick[10]; /* Nickname */ time_t connected; /* Time connected */ +#ifdef USE_EXPERIMENT + char channel[21]; /* Connected channel */ +#else int channel; /* Connected channel or -1 */ +#endif int pointer; /* Message pointer */ unsigned chatting : 1; /* Is chatting in a channel */ unsigned chanop : 1; /* Is a chanop */ @@ -80,6 +86,7 @@ typedef struct _chatmsg { /* * List of channels */ +#ifndef USE_EXPERIMENT typedef struct _channel_rec { char name[21]; /* Channel name */ char topic[55]; /* Channel topic */ @@ -88,6 +95,7 @@ typedef struct _channel_rec { time_t created; /* Creation time */ unsigned active : 1; /* Channel active */ } _channel; +#endif @@ -106,7 +114,9 @@ typedef struct _banned { */ _chat_messages chat_messages[MAXMESSAGES]; _chat_users chat_users[MAXCLIENT]; +#ifndef USE_EXPERIMENT _channel chat_channels[MAXCHANNELS]; +#endif int buffer_head = 0; /* Messages buffer head */ @@ -115,14 +125,20 @@ extern int s_bbsopen; /* The BBS open status */ #ifdef USE_EXPERIMENT extern srv_list *servers; /* Connected servers */ extern usr_list *users; /* Connected users */ +extern chn_list *channels; /* Connected channels */ extern int usrchg; +extern int chnchg; #endif /* * Prototypes */ +#ifdef USE_EXPERIMENT +void chat_msg(char *, char *, char *); +#else void chat_msg(int, char *, char *); +#endif void chat_dump(void); void system_msg(pid_t, char *); void chat_help(pid_t); @@ -147,6 +163,7 @@ void chat_dump(void) chat_users[i].chatting?"True ":"False", chat_users[i].sysop?"True ":"False"); } first = TRUE; +#ifndef USE_EXPERIMENT for (i = 0; i < MAXCHANNELS; i++) if (chat_channels[i].owner) { if (first) { @@ -157,6 +174,7 @@ void chat_dump(void) Syslog('c', "%-20s %5d %3d %s", chat_channels[i].name, chat_channels[i].owner, chat_channels[i].users, chat_channels[i].active?"True":"False"); } +#endif } @@ -232,10 +250,42 @@ void chat_help(pid_t pid) */ int join(pid_t pid, char *channel, int sysop) { - int i, j; - char buf[81]; + int j; + char buf[81]; +#ifdef USE_EXPERIMENT + chn_list *tmp; +#else + int i; +#endif Syslog('-', "Join pid %d to channel %s", pid, channel); + +#ifdef USE_EXPERIMENT + if (channels) { + for (tmp = channels; tmp; tmp = tmp->next) { + if (strcmp(tmp->name, channel) == 0) { + tmp->users++; + for (j = 0; j < MAXCLIENT; j++) { + if (chat_users[j].pid == pid) { + strncpy(chat_users[j].channel, channel, 20); + chat_users[j].chatting = TRUE; + Syslog('-', "Added user %d to channel %s", j, channel); + chat_dump(); + sprintf(buf, "%s has joined channel #%s, now %d users", chat_users[j].nick, channel, tmp->users); + chat_msg(channel, NULL, buf); + + /* + * The sysop channel is private to the system, no broadcast + */ + if (strcasecmp(channel, "sysop")) + send_all("JOIN %s@%s %s\r\n", chat_users[j].nick, CFG.myfqdn, channel); + return TRUE; + } + } + } + } + } +#else for (i = 0; i < MAXCHANNELS; i++) { if (strcasecmp(chat_channels[i].name, channel) == 0) { /* @@ -255,6 +305,7 @@ int join(pid_t pid, char *channel, int sysop) } } } +#endif /* * A new channel must be created, but only the sysop may create the "sysop" channel @@ -268,6 +319,22 @@ int join(pid_t pid, char *channel, int sysop) /* * No matching channel found, add a new channel. */ +#ifdef USE_EXPERIMENT + for (j = 0; j < MAXCLIENT; j++) { + if (chat_users[j].pid == pid) { + if (add_channel(&channels, channel, chat_users[j].nick, CFG.myfqdn) == 0) { + strncpy(chat_users[j].channel, channel, 20); + chat_users[j].chatting = TRUE; + Syslog('-', "Added user %d to channel %s", j, channel); + sprintf(buf, "Created channel #%s", channel); + chat_msg(channel, NULL, buf); + chat_dump(); + send_all("JOIN %s@%s %s\r\n", chat_users[j].nick, CFG.myfqdn, channel); + return TRUE; + } + } + } +#else for (i = 0; i < MAXCHANNELS; i++) { if (chat_channels[i].active == FALSE) { /* @@ -295,6 +362,7 @@ int join(pid_t pid, char *channel, int sysop) return TRUE; } } +#endif /* * No matching or free channels @@ -312,11 +380,52 @@ int join(pid_t pid, char *channel, int sysop) */ int part(pid_t pid, char *reason) { - int i; - char buf[81]; + int i; + char buf[81]; +#ifdef USE_EXPERIMENT + chn_list *tmp; +#endif Syslog('-', "Part pid %d from channel, reason %s", pid, reason); +#ifdef USE_EXPERIMENT + for (i = 0; i < MAXCLIENT; i++) { + if ((chat_users[i].pid == pid) && chat_users[i].chatting) { + for (tmp = channels; tmp; tmp = tmp->next) { + if (strcmp(tmp->name, chat_users[i].channel) == 0) { + tmp->users--; + chnchg = TRUE; + + /* + * Inform other users + */ + if (reason != NULL) + chat_msg(chat_users[i].channel, chat_users[i].nick, reason); + sprintf(buf, "%s has left channel #%s, %d users left", chat_users[i].nick, tmp->name, tmp->users); + chat_msg(chat_users[i].channel, NULL, buf); + if (strcmp(tmp->name, (char *)"sysop")) + send_all("PART %s@%s %s\r\n", chat_users[i].nick, CFG.myfqdn, tmp->name); + + /* + * Clean channel + */ + Syslog('-', "Nick %s leaves channel %s", chat_users[i].nick, tmp->name); + if (tmp->users == 0) { + /* + * Last user in channel, remove channel + */ + Syslog('-', "Remove channel %s, no more users left", tmp->name); + del_channel(&channels, tmp->name); + } + chat_users[i].channel[0] = '\0'; + chat_users[i].chatting = FALSE; + chat_dump(); + return TRUE; + } + } + } + } +#else for (i = 0; i < MAXCLIENT; i++) { if ((chat_users[i].pid == pid) && chat_users[i].chatting) { chat_channels[chat_users[i].channel].users--; @@ -347,6 +456,8 @@ int part(pid_t pid, char *reason) return TRUE; } } +#endif + Syslog('-', "No channel found"); return FALSE; } @@ -355,13 +466,15 @@ int part(pid_t pid, char *reason) void chat_init(void) { +#ifndef USE_EXPERIMENT int i; - - memset(&chat_users, 0, sizeof(chat_users)); + for (i = 0; i < MAXCLIENT; i++) chat_users[i].channel = -1; - memset(&chat_messages, 0, sizeof(chat_messages)); memset(&chat_channels, 0, sizeof(chat_channels)); +#endif + memset(&chat_users, 0, sizeof(chat_users)); + memset(&chat_messages, 0, sizeof(chat_messages)); } @@ -376,7 +489,11 @@ void chat_cleanuser(pid_t pid) /* * Send message into channel */ +#ifdef USE_EXPERIMENT +void chat_msg(char *channel, char *nick, char *msg) +#else void chat_msg(int channel, char *nick, char *msg) +#endif { int i; char buf[128], *logm; @@ -389,19 +506,27 @@ void chat_msg(int channel, char *nick, char *msg) if (CFG.iAutoLog && strlen(CFG.chat_log)) { logm = calloc(PATH_MAX, sizeof(char)); sprintf(logm, "%s/log/%s", getenv("MBSE_ROOT"), CFG.chat_log); +#ifdef USE_EXPERIMENT + ulog(logm, (char *)"+", channel, (char *)"-1", buf); +#else ulog(logm, (char *)"+", chat_channels[channel].name, (char *)"-1", buf); +#endif free(logm); } buf[79] = '\0'; for (i = 0; i < MAXCLIENT; i++) { +#ifdef USE_EXPERIMENT + if ((strcmp(chat_users[i].channel, channel) == 0) && chat_users[i].chatting) { +#else if ((chat_users[i].channel == channel) && chat_users[i].chatting) { +#endif system_msg(chat_users[i].pid, buf); } } #ifdef USE_EXPERIMENT - send_all("%s\r\n", buf); + send_all("MSG %s\r\n", buf); #endif } @@ -451,7 +576,11 @@ char *chat_connect(char *data) strncpy(chat_users[i].name, nick, 9); chat_users[i].connected = time(NULL); chat_users[i].pointer = buffer_head; +#ifdef USE_EXPERIMENT + chat_users[i].channel[0] = '\0'; +#else chat_users[i].channel = -1; +#endif chat_users[i].sysop = sys; Syslog('-', "Connected user %s (%s) with chatserver, slot %d, sysop %s", realname, pid, i, sys ? "True":"False"); @@ -515,7 +644,11 @@ char *chat_close(char *data) #endif Syslog('-', "Closing chat for pid %s, slot %d", pid, i); memset(&chat_users[i], 0, sizeof(_chat_users)); +#ifdef USE_EXPERIMENT + chat_users[i].channel[0] = '\0'; +#else chat_users[i].channel = -1; +#endif sprintf(buf, "100:0;"); return buf; } @@ -535,6 +668,7 @@ char *chat_put(char *data) #ifdef USE_EXPERIMENT int found; usr_list *tmp; + chn_list *tmpc; #endif Syslog('-', "CPUT:%s", data); @@ -584,7 +718,11 @@ char *chat_put(char *data) if ((cmd == NULL) || (cmd[0] != '#') || (strcmp(cmd, "#") == 0)) { sprintf(buf, "** Try /join #channel"); system_msg(chat_users[i].pid, buf); +#ifdef USE_EXPERIMENT + } else if (strlen(chat_users[i].channel)) { +#else } else if (chat_users[i].channel != -1) { +#endif sprintf(buf, "** Cannot join while in a channel"); system_msg(chat_users[i].pid, buf); } else { @@ -595,6 +733,18 @@ char *chat_put(char *data) goto ack; } else if (strncasecmp(msg, "/list", 5) == 0) { first = TRUE; +#ifdef USE_EXPERIMENT + for (tmpc = channels; tmpc; tmpc = tmpc->next) { + if (first) { + sprintf(buf, "Cnt Channel name Channel topic"); + system_msg(chat_users[i].pid, buf); + sprintf(buf, "--- -------------------- ------------------------------------------------------"); + system_msg(chat_users[i].pid, buf); + } + first = FALSE; + sprintf(buf, "%3d %-20s %-54s", tmpc->users, tmpc->name, tmpc->topic); + system_msg(chat_users[i].pid, buf); +#else for (j = 0; j < MAXCHANNELS; j++) { if (chat_channels[j].owner && chat_channels[j].active) { if (first) { @@ -607,6 +757,7 @@ char *chat_put(char *data) sprintf(buf, "%3d %-20s %-54s", chat_channels[j].users, chat_channels[j].name, chat_channels[j].topic); system_msg(chat_users[i].pid, buf); } +#endif } if (first) { sprintf(buf, "No active channels to list"); @@ -614,12 +765,20 @@ char *chat_put(char *data) } goto ack; } else if (strncasecmp(msg, "/names", 6) == 0) { +#ifdef USE_EXPERIMENT + if (strlen(chat_users[i].channel)) { +#else if (chat_users[i].channel != -1) { +#endif sprintf(buf, "Present in this channel:"); system_msg(chat_users[i].pid, buf); count = 0; for (j = 0; j < MAXCLIENT; j++) { +#ifdef USE_EXPERIMENT + if ((strcmp(chat_users[j].channel, chat_users[i].channel) == 0) && chat_users[j].pid) { +#else if ((chat_users[j].channel == chat_users[i].channel) && chat_users[j].pid) { +#endif sprintf(buf, "%s %s", chat_users[j].nick, chat_users[j].chanop ?"(chanop)": chat_users[j].sysop ?"(sysop)":""); system_msg(chat_users[i].pid, buf); @@ -685,11 +844,32 @@ char *chat_put(char *data) chat_dump(); goto ack; } else if (strncasecmp(msg, "/topic", 6) == 0) { +#ifdef USE_EXPERIMENT + if (strlen(chat_users[i].channel)) { + for (tmpc = channels; tmpc; tmpc = tmpc->next) { + if (strcmp(chat_users[i].channel, tmpc->name)) { + if ((strcmp(chat_users[i].name, tmpc->owner) == 0) || (strcmp(chat_users[i].nick, tmpc->owner) == 0)) { + cmd = strtok(msg, " \0"); + cmd = strtok(NULL, "\0"); + if ((cmd == NULL) || (strlen(cmd) == 0) || (strlen(cmd) > 54)) { + sprintf(buf, "** Topic must be between 1 and 54 characters"); + } else { + strncpy(tmpc->topic, cmd, 54); + sprintf(buf, "Topic set to \"%s\"", cmd); + send_all("TOPIC %s %s\r\n", tmpc->name, tmpc->topic); + } + } else { + sprintf(buf, "** You are not the channel owner"); + } + break; + } + } +#else if (chat_users[i].channel != -1) { if (chat_channels[chat_users[i].channel].owner == chat_users[i].pid) { cmd = strtok(msg, " \0"); cmd = strtok(NULL, "\0"); - if ((cmd == NULL) || (strlen(cmd) == 0) || (strlen(cmd) > 36)) { + if ((cmd == NULL) || (strlen(cmd) == 0) || (strlen(cmd) > 54)) { sprintf(buf, "** Topic must be between 1 and 54 characters"); } else { strncpy(chat_channels[chat_users[i].channel].topic, cmd, 54); @@ -698,6 +878,7 @@ char *chat_put(char *data) } else { sprintf(buf, "** You are not the channel owner"); } +#endif } else { sprintf(buf, "** Not in a channel"); } @@ -714,7 +895,11 @@ char *chat_put(char *data) goto ack; } } +#ifdef USE_EXPERIMENT + if (strlen(chat_users[i].channel) == 0) { +#else if (chat_users[i].channel == -1) { +#endif /* * Trying messages while not in a channel */ diff --git a/mbtask/taskibc.c b/mbtask/taskibc.c index 44718b07..4566ca65 100644 --- a/mbtask/taskibc.c +++ b/mbtask/taskibc.c @@ -47,6 +47,7 @@ time_t now; /* Current time */ ncs_list *ncsl = NULL; /* Neighbours list */ srv_list *servers = NULL; /* Active servers */ usr_list *users = NULL; /* Active users */ +chn_list *channels = NULL; /* Active channels */ int ls; /* Listen socket */ struct sockaddr_in myaddr_in; /* Listen socket address */ struct sockaddr_in clientaddr_in; /* Remote socket address */ @@ -54,7 +55,7 @@ int changed = FALSE; /* Databases changed */ char crbuf[512]; /* Chat receive buffer */ int srvchg = FALSE; /* Is serverlist changed */ int usrchg = FALSE; /* Is userlist changed */ - +int chnchg = FALSE; /* Is channellist changed */ pthread_mutex_t b_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -76,7 +77,6 @@ static char *ncsstate[] = { void fill_ncslist(ncs_list **, char *, char *, char *); void dump_ncslist(void); void tidy_servers(srv_list **); -void del_userbyserver(usr_list **, char *); void add_server(srv_list **, char *, int, char *, char *, char *, char *); void del_server(srv_list **, char *); void del_router(srv_list **, char *); @@ -141,8 +141,9 @@ void dump_ncslist(void) ncs_list *tmp; srv_list *srv; usr_list *usrp; + chn_list *chnp; - if (!changed && !srvchg && !usrchg) + if (!changed && !srvchg && !usrchg && !chnchg) return; Syslog('r', "Server State Del Pwd Srv Next action"); @@ -175,8 +176,22 @@ void dump_ncslist(void) } } + if (chnchg) { + if (channels) { + Syslog('+', "IBC: Channel Owner Topic Usr Created"); + Syslog('+', "IBC: -------------------- --------- ----------------------------------- --- --------------------"); + for (chnp = channels; chnp; chnp = chnp->next) { + Syslog('+', "IBC: %-20s %-9s %-35s %3d %s", chnp->name, chnp->owner, chnp->topic, + chnp->users, rfcdate(chnp->created)); + } + } else { + Syslog('+', "IBC: Channels list is empty"); + } + } + srvchg = FALSE; usrchg = FALSE; + chnchg = FALSE; changed = FALSE; } @@ -303,6 +318,85 @@ void del_user(usr_list **fap, char *server, char *name) +/* + * Add channel with owner. + */ +int add_channel(chn_list **fap, char *name, char *owner, char *server) +{ + chn_list *tmp, *ta; + int rc; + + Syslog('r', "add_channel %s %s %s", name, owner, server); + + for (ta = *fap; ta; ta = ta->next) { + if ((strcmp(ta->name, name) == 0) && (strcmp(ta->owner, owner) == 0) && (strcmp(ta->server, server) == 0)) { + Syslog('-', "IBC: add_channel(%s %s %s), already registered", name, owner, server); + return 1; + } + } + + if ((rc = pthread_mutex_lock(&b_mutex))) + Syslog('!', "add_channel() mutex_lock failed rc=%d", rc); + + tmp = (chn_list *)malloc(sizeof(chn_list)); + memset(tmp, 0, sizeof(chn_list)); + tmp->next = NULL; + strncpy(tmp->name, name, 20); + strncpy(tmp->owner, owner, 9); + strncpy(tmp->server, server, 63); + tmp->users = 1; + tmp->created = now; + + if (*fap == NULL) { + *fap = tmp; + } else { + for (ta = *fap; ta; ta = ta->next) + if (ta->next == NULL) { + ta->next = (chn_list *)tmp; + break; + } + } + + if ((rc = pthread_mutex_unlock(&b_mutex))) + Syslog('!', "add_channel() mutex_unlock failed rc=%d", rc); + + chnchg = TRUE; + return 0; +} + + + +void del_channel(chn_list **fap, char *name) +{ + chn_list **tmp, *tmpa; + int rc; + + Syslog('r', "del_channel %s", name); + + if (*fap == NULL) + return; + + if ((rc = pthread_mutex_lock(&b_mutex))) + Syslog('!', "del_channel() mutex_lock failed rc=%d", rc); + + tmp = fap; + while (*tmp) { + if (strcmp((*tmp)->name, name) == 0) { + tmpa = *tmp; + *tmp=(*tmp)->next; + free(tmpa); + chnchg = TRUE; + } else { + tmp = &((*tmp)->next); + } + } + + if ((rc = pthread_mutex_unlock(&b_mutex))) + Syslog('!', "del_channel() mutex_unlock failed rc=%d", rc); +} + + + void add_server(srv_list **fdp, char *name, int hops, char *prod, char *vers, char *fullname, char *router) { srv_list *tmp, *ta; diff --git a/mbtask/taskibc.h b/mbtask/taskibc.h index 96264131..7c8d3936 100644 --- a/mbtask/taskibc.h +++ b/mbtask/taskibc.h @@ -79,6 +79,8 @@ typedef struct _chn_list { int add_user(usr_list **, char *, char *, char *); void del_user(usr_list **, char *, char *); +int add_channel(chn_list **, char *, char *, char *); +void del_channel(chn_list **, char *); void send_all(const char *, ...); void *ibc_thread(void *);