added a data parameter to get_userlist that gets passed to the callback
[NeonServV5.git] / WHOHandler.c
1
2 #include "WHOHandler.h"
3 #include "ChanNode.h"
4 #include "UserNode.h"
5
6 #define WHOQUEUETYPE_ISONQUEUE 0x01
7 #define WHOQUEUETYPE_USERLIST  0x02
8
9 struct WHOQueueEntry {
10     char type;
11     struct ClientSocket *client;
12     struct ChanNode *chan;
13     struct UserNode *user;
14     struct WHOQueueEntry *next;
15     userlist_callback_t *callback;
16     void *data;
17 };
18
19 static struct WHOQueueEntry *first_entry = NULL, *last_entry = NULL;
20
21 static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
22     struct WHOQueueEntry *entry = malloc(sizeof(*entry));
23     if (!entry)
24     {
25         perror("malloc() failed");
26         return NULL;
27     }
28     entry->next = NULL;
29     entry->client = client;
30     if(last_entry)
31         last_entry->next = entry;
32     if(!first_entry)
33         first_entry = entry;
34     return entry;
35 }
36
37 static struct WHOQueueEntry* getNextWHOQueueEntry(struct ClientSocket *client, int freeEntry) {
38     if(!first_entry) return NULL;
39     struct WHOQueueEntry *entry;
40     for(entry = first_entry; entry; entry = entry->next) {
41         if(entry->client == client)
42             break;
43     }
44     if(entry == NULL) return NULL;
45     if(freeEntry) {
46         first_entry = first_entry->next;
47         if(last_entry == first_entry)
48             last_entry = NULL;
49     }
50     return entry;
51 }
52
53 void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data) {
54     struct ClientSocket *bot;
55     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
56         if(isUserOnChan(bot->user, chan))
57             break;
58     }
59     if(bot == NULL) return;
60     struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
61     entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST;
62     entry->chan = chan;
63     entry->callback = callback;
64     entry->data = data;
65     //WHO ".$channel->getName().",".$id." d%tuhnaf,".$id
66     putsock(bot, "WHO %s,%d %%tuhnaf,%d", chan->name, entry->type, entry->type);
67 }
68
69 void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc) {
70     int i;
71     if(argc < 2) return;
72     int type = atoi(argv[1]);
73     if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
74     struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 0);
75     if(entry == NULL || entry->type != type) return;
76     if(type & WHOQUEUETYPE_USERLIST) {
77         if(argc < 7) return;
78         //:OGN2.OnlineGamesNet.net 354 skynet 1 pk910 2001:41d0:2:1d3b::babe skynet H@ pk910
79         struct ChanNode *chan = entry->chan;
80         //add the user toe the channel if he isn't added, yet and update its user data
81         struct UserNode *user = getUserByNick(argv[4]);
82         if(user == NULL) {
83             user = addUser(argv[4]);
84         }
85         //parse flags
86         int userflags = 0;
87         int chanuserflags = 0;
88         for(i = 0; i < strlen(argv[5]); i++) {
89             switch (argv[5][i]) {
90                 case '@':
91                     chanuserflags |= CHANUSERFLAG_OPPED;
92                     break;
93                 case '+':
94                     chanuserflags |= CHANUSERFLAG_VOICED;
95                     break;
96                 case '*':
97                     userflags |= USERFLAG_ISIRCOP;
98                     break;
99                 default:
100                     break;
101             }
102         }
103         user->flags = (user->flags & ~USERFLAG_ISIRCOP) | userflags;
104         if(!isUserOnChan(user, chan)) {
105             struct ChanUser *chanuser = addChanUser(chan, user);
106             chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
107         }
108         if(!*user->ident)
109             strcpy(user->ident, argv[2]);
110         if(!*user->host)
111             strcpy(user->host, argv[3]);
112         if(!(user->flags & USERFLAG_ISAUTHED) && strcmp(argv[6], "0")) {
113             strcpy(user->auth, argv[6]);
114             user->flags |= USERFLAG_ISAUTHED;
115         }
116     }
117 }
118
119 void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc) {
120     if(argc < 2) return;
121     char *typestr = strstr(argv[1], ",") + 1;
122     int type = atoi(typestr);
123     if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
124     struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 1);
125     if(entry == NULL || entry->type != type) return;
126     if(type & WHOQUEUETYPE_USERLIST) {
127         //:OGN2.OnlineGamesNet.net 315 skynet #pk910,1 :End of /WHO list.
128         entry->chan->flags |= CHANFLAG_RECEIVED_USERLIST;
129         entry->callback(client, entry->chan, entry->data);
130     }
131     free(entry);
132 }