added ChanUser.c and basic cache system
authorpk910 <philipp@zoelle1.de>
Thu, 11 Aug 2011 02:28:19 +0000 (04:28 +0200)
committerpk910 <philipp@zoelle1.de>
Thu, 11 Aug 2011 02:28:19 +0000 (04:28 +0200)
ChanNode.c
ChanNode.h
ChanUser.c [new file with mode: 0644]
ChanUser.h
IRCEvents.h
IRCParser.c
UserNode.c
UserNode.h

index e4e59de01cb8ed2402d19d0f20bcac1b3d7b29f5..77071243119f886af200ca12f2579d538cdd65be 100644 (file)
@@ -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;
 }
index 127d7b560a0f3c7f68e155f174ef53db4238e42a..edf5f53c4653f09b8f005505ae3d165dac8cb932 100644 (file)
@@ -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 (file)
index 0000000..a4cf9de
--- /dev/null
@@ -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;
+}
+
index 8ca5b2bf00bbc7fe1ee8b80a2bf2dbdb07d6ff98..71aba8c4705e0bce0a12524f4a9c1e40f636cb7c 100644 (file)
@@ -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
index a8047ee7cee6fa4f8c356d5147260275c633c51e..01e480c9f2607436cebe842a1803f3d64ea0fc5c 100644 (file)
@@ -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);
 
index 30ecfc6c44e5b7ad9edabec1d57ee07904367143..ed71d391ca30f4991c4306f620b715c157e9f777 100644 (file)
@@ -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);
 }
index 3c0add192e517a821ac28749487c7b192de019b1..7c06d545cd16957fc35cfae802a082e538cbb01c 100644 (file)
@@ -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
index d63fede63bd998dee4da88671f89ff7c477a5cb3..0037e3444854bf893d08fc817461142063b1c651 100644 (file)
@@ -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