From b3330a3915ac73d3074551ef7e69cc8aeb54e6b7 Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 11 Aug 2011 04:28:19 +0200 Subject: [PATCH] added ChanUser.c and basic cache system --- ChanNode.c | 37 +++++++++++++++-- ChanNode.h | 3 ++ ChanUser.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ChanUser.h | 7 ++++ IRCEvents.h | 1 + IRCParser.c | 71 ++++++++++++++++++++++++++++++++- UserNode.c | 8 ++++ UserNode.h | 2 +- 8 files changed, 235 insertions(+), 6 deletions(-) create mode 100644 ChanUser.c diff --git a/ChanNode.c b/ChanNode.c index e4e59de..7707124 100644 --- a/ChanNode.c +++ b/ChanNode.c @@ -64,10 +64,41 @@ struct ChanNode* getChanByName(const char *name) { //case insensitive return NULL; } -struct ChanNode* addChannel(const char *chan) { - return NULL; //to be continued +struct ChanNode* addChannel(const char *name) { + int chanListIndex = get_chanlist_entry(name[1]); + if(chanListIndex == -1 || !is_valid_chan(name)) + return NULL; + struct ChanNode *chan = malloc(sizeof(*chan)); + if (!chan) + { + perror("malloc() failed"); + return NULL; + } + strcpy(chan->name, name); + chan->user = NULL; + chan->topic[0] = 0; + chan->flags = 0; + chan->next = chanList[chanListIndex]; + chanList[chanListIndex] = chan; + return chan; } void delChannel(struct ChanNode* chan, int freeChan) { - //to be continued + int chanListIndex = get_chanlist_entry(chan->name[1]); + if(chanListIndex == -1) return; + struct ChanNode *cchan, *last_chan = NULL; + for(cchan = chanList[chanListIndex]; cchan; cchan = cchan->next) { + if(cchan == chan) { + if(last_chan) + last_chan->next = chan->next; + else + chanList[chanListIndex] = chan->next; + break; + } else + last_chan = cchan; + } + if(freeChan) + free(chan); + else + chan->next = NULL; } diff --git a/ChanNode.h b/ChanNode.h index 127d7b5..edf5f53 100644 --- a/ChanNode.h +++ b/ChanNode.h @@ -4,10 +4,13 @@ struct ChanUser; +#define CHANFLAG_RECEIVED_USERLIST 0x01; + struct ChanNode { char name[CHANNELLEN+1]; char topic[TOPICLEN+1]; struct ChanUser *user; + char flags; struct ChanNode *next; }; diff --git a/ChanUser.c b/ChanUser.c new file mode 100644 index 0000000..a4cf9de --- /dev/null +++ b/ChanUser.c @@ -0,0 +1,112 @@ + +#include "ChanUser.h" +#include "ChanNode.h" +#include "UserNode.h" + +struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user) { + struct ChanUser *chanuser = malloc(sizeof(*chan)); + if (!chanuser) + { + perror("malloc() failed"); + return NULL; + } + chanuser->user = user; + chanuser->chan = chan; + + chanuser->next_user = chan->user; + chan->user = chanuser; + + chanuser->next_chan = user->channel; + user->channel = chanuser; + + return chanuser; +} + +int isUserOnChan(struct UserNode *user, struct ChanNode *chan) { + struct ChanUser *chanuser; + for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) { + if(chanuser->chan == chan) + return 1; + } + return 0; +} + +struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan) { + struct ChanUser *chanuser; + for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) { + if(chanuser->chan == chan) + return chanuser; + } + return NULL; +} + +struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last) { + if(last == NULL) + return chan->user; + else + return last->next_user; +} + +struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last) { + if(last == NULL) + return user->channel; + else + return last->next_chan; +} + +void delChanUser(struct ChanUser *chanuser, int freeChanUser) { + struct ChanUser *cchanuser, *last; + //remove it from the user's channel-list + last = NULL; + for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) { + if(cchanuser == chanuser) { + if(last) + last->next_chan = chanuser->next_chan; + else + chanuser->user->channel = chanuser->next_chan; + break; + } else + last = cchanuser; + } + + //remove it from the channel's user-list + last = NULL; + for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) { + if(cchanuser == chanuser) { + if(last) + last->next_user = chanuser->next_user; + else + chanuser->chan->user = chanuser->next_user; + break; + } else + last = cchanuser; + } + + if(freeChanUser) + free(chanuser); + else { + chanuser->next_chan = NULL; + chanuser->next_user = NULL; + } +} + +void quitChanUser(struct ChanUser *chanuser, int freeChanUser) { + struct ChanUser *cchanuser, *last = NULL; + last = NULL; + for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) { + if(cchanuser == chanuser) { + if(last) + last->next_user = chanuser->next_user; + else + chanuser->chan->user = chanuser->next_user; + break; + } else + last = cchanuser; + } + + if(freeChanUser) + free(chanuser); + else + chanuser->next_user = NULL; +} + diff --git a/ChanUser.h b/ChanUser.h index 8ca5b2b..71aba8c 100644 --- a/ChanUser.h +++ b/ChanUser.h @@ -19,4 +19,11 @@ struct ChanUser { struct ChanUser *next_chan; }; +struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user); +int isUserOnChan(struct UserNode *user, struct ChanNode *chan); +struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan); +struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last); +struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last); +void delChanUser(struct ChanUser *chanuser, int freeChanUser); + #endif \ No newline at end of file diff --git a/IRCEvents.h b/IRCEvents.h index a8047ee..01e480c 100644 --- a/IRCEvents.h +++ b/IRCEvents.h @@ -9,6 +9,7 @@ int event_join(struct ChanUser *chanuser); int event_part(struct ChanUser *chanuser, char *reason); int event_quit(struct UserNode *user, char *reason); +int event_kick(struct UserNode *user, struct ChanUser *target, char *reason); int event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message); int event_privmsg(struct UserNode *user, struct UserNode *target, char *message); diff --git a/IRCParser.c b/IRCParser.c index 30ecfc6..ed71d39 100644 --- a/IRCParser.c +++ b/IRCParser.c @@ -97,13 +97,77 @@ static IRC_CMD(raw_join) { struct ChanNode *chan = getChanByName(argv[0]); if(chan == NULL) { chan = addChannel(argv[0]); - + //request member list + //TODO! + } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { + struct ChanUser *chanuser = addChanUser(chan, user); + event_join(chanuser); + } + return 1; +} + +static IRC_CMD(raw_part) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) return 0; + struct ChanNode *chan = getChanByName(argv[0]); + if(chan == NULL) return 0; + if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { + struct ChanUser *chanuser = getChanUser(user, chan); + delChanUser(chanuser, 0); //we need to free the chanuser manually! + event_part(chanuser, argv[1]); + free(chanuser); + if(user->flags & USERFLAG_ISBOT) { + //check if theres another bot in the channel - otherwise free it + + } + } + if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) { + //remove the user + delUser(user, 1); } - putsock(client, "PRIVMSG #pktest :hi"); return 1; } +static IRC_CMD(raw_quit) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) return 0; + delUser(user, 0); //a little bit crazy, but we want to delete the user on the channel's userlists - but not the users channel list + event_quit(user, argv[1]); + if(user->flags & USERFLAG_ISBOT) { + //check if there are other bots in the users channel - otherwise free them + + } + delUser(user, 1); //now we fully free the user + return 1; +} + +static IRC_CMD(raw_kick) { + if(from == NULL || argc < 3) return 0; + struct UserNode *user = getUserByMask(from); + struct UserNode *target = getUserByNick(argv[1]); + if(user == NULL || target == NULL) return 0; + struct ChanNode *chan = getChanByName(argv[0]); + if(chan == NULL) return 0; + if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { + struct ChanUser *chanuser = getChanUser(target, chan); + delChanUser(chanuser, 0); //we need to free the chanuser manually! + event_kick(user, chanuser, argv[1]); + free(chanuser); + if(target->flags & USERFLAG_ISBOT) { + //check if theres another bot in the channel - otherwise free it + + } + } + if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) { + //remove the user + delUser(user, 1); + } + return 1; +} + static IRC_CMD(raw_ping) { if(argc == 0) return 0; putsock(client, "PONG :%s", argv[0]); @@ -113,6 +177,9 @@ static IRC_CMD(raw_ping) { void parser_init() { //all the raws we receive... register_irc_function("001", raw_001); + register_irc_function("KICK", raw_kick); register_irc_function("JOIN", raw_join); + register_irc_function("PART", raw_part); + register_irc_function("QUIT", raw_quit); register_irc_function("PING", raw_ping); } diff --git a/UserNode.c b/UserNode.c index 3c0add1..7c06d54 100644 --- a/UserNode.c +++ b/UserNode.c @@ -1,4 +1,5 @@ #include "UserNode.h" +#include "ChanUser.h" static struct UserNode **userList; @@ -165,6 +166,13 @@ void delUser(struct UserNode* user, int freeUser) { } else last_user = cuser; } + if(user->channel) { + struct ChanUser *chanUser, *next; + for(chanUser = user->channel; chanUser; chanUser = next) { + next = chanUser->next_chan; + quitChanUser(chanUser, freeUser); + } + } if(freeUser) free(user); else diff --git a/UserNode.h b/UserNode.h index d63fede..0037e34 100644 --- a/UserNode.h +++ b/UserNode.h @@ -26,4 +26,4 @@ struct UserNode* addUserMask(const char *mask); int renameUser(struct UserNode* user, const char *new_nick); void delUser(struct UserNode* user, int freeUser); -#endif \ No newline at end of file +#endif -- 2.20.1