added ChanUser.c and basic cache system
[NeonServV5.git] / IRCParser.c
1
2 #include "IRCParser.h"
3 #include "UserNode.h"
4 #include "ChanNode.h"
5 #include "ChanUser.h"
6 #include "IRCEvents.h"
7 #include "ClientSocket.h"
8
9 struct irc_cmd *irc_commands = NULL;
10
11 static void parse_line(struct ClientSocket *client, char *line);
12 static void register_irc_function(char *command, irc_cmd_t *func);
13 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
14
15 int parse_lines(struct ClientSocket *client, char *lines, int len) {
16     int i, used = 0;
17     char *line = lines;
18     for(i = 0; i < len; i++) {
19         if(lines[i] == '\r') //just zero it out :D
20             lines[i] = 0;
21         if(lines[i] == '\n') {
22             lines[i] = 0;
23             parse_line(client, line);
24             line = lines+(i+1);
25             used = i+1;
26         }
27     }
28     return used;
29 }
30
31 static void parse_line(struct ClientSocket *client, char *line) {
32     int argc = 0;
33     char *argv[MAXNUMPARAMS];
34     printf("[recv %lu] %s\n", (unsigned long) strlen(line), line);
35     if(line[0] == ':')
36         line++;
37     else
38         argv[argc++] = NULL;
39     while(*line) {
40         //skip leading spaces
41         while (*line == ' ')
42             *line++ = 0;
43         if (*line == ':') {
44            //the rest is a single parameter
45            argv[argc++] = line + 1;
46         }
47         argv[argc++] = line;
48         if (argc >= MAXNUMPARAMS)
49             break;
50         while (*line != ' ' && *line)
51             line++;
52     }
53     if(argc >= 2) {
54         parse_raw(client, argv[0], argv[1], argv+2, argc-2);
55     }
56 }
57
58 static void register_irc_function(char *command, irc_cmd_t *func) {
59     struct irc_cmd *irc_cmd = malloc(sizeof(*irc_cmd));
60     if (!irc_cmd)
61     {
62         perror("malloc() failed");
63         return;
64     }
65     irc_cmd->cmd = command;
66     irc_cmd->func = func;
67     irc_cmd->next = irc_commands;
68     irc_commands = irc_cmd;
69 }
70
71 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc) {
72     struct irc_cmd *irc_cmd;
73     int ret = 0;
74     for(irc_cmd = irc_commands; irc_cmd; irc_cmd = irc_cmd->next) {
75         if(!stricmp(irc_cmd->cmd, cmd)) {
76             ret = irc_cmd->func(client, from, argv, argc);
77             break;
78         }
79     }
80     if(!ret) {
81         //fprintf(stderr,"PARSE ERROR: %s", cmd); commented out right now - we're still developing and this is very spammy
82     }
83 }
84
85 static IRC_CMD(raw_001) {
86     client->flags |= SOCKET_FLAG_READY;
87     putsock(client, "JOIN #pktest");
88     return 1;
89 }
90
91 static IRC_CMD(raw_join) {
92     if(from == NULL || argc < 1) return 0;
93     struct UserNode *user = getUserByMask(from);
94     if(user == NULL) {
95         user = addUserMask(from);
96     }
97     struct ChanNode *chan = getChanByName(argv[0]);
98     if(chan == NULL) {
99         chan = addChannel(argv[0]);
100         //request member list
101         //TODO!
102     } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
103         struct ChanUser *chanuser = addChanUser(chan, user);
104         event_join(chanuser);
105     }
106     return 1;
107 }
108
109 static IRC_CMD(raw_part) {
110     if(from == NULL || argc < 2) return 0;
111     struct UserNode *user = getUserByMask(from);
112     if(user == NULL) return 0;
113     struct ChanNode *chan = getChanByName(argv[0]);
114     if(chan == NULL) return 0;
115     if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
116         struct ChanUser *chanuser = getChanUser(user, chan);
117         delChanUser(chanuser, 0); //we need to free the chanuser manually!
118         event_part(chanuser, argv[1]);
119         free(chanuser);
120         if(user->flags & USERFLAG_ISBOT) {
121             //check if theres another bot in the channel - otherwise free it
122             
123         }
124     }
125     if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) {
126         //remove the user
127         delUser(user, 1);
128     }
129     
130     return 1;
131 }
132
133 static IRC_CMD(raw_quit) {
134     if(from == NULL || argc < 2) return 0;
135     struct UserNode *user = getUserByMask(from);
136     if(user == NULL) return 0;
137     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
138     event_quit(user, argv[1]);
139     if(user->flags & USERFLAG_ISBOT) {
140         //check if there are other bots in the users channel - otherwise free them
141         
142     }
143     delUser(user, 1); //now we fully free the user
144     return 1;
145 }
146
147 static IRC_CMD(raw_kick) {
148     if(from == NULL || argc < 3) return 0;
149     struct UserNode *user = getUserByMask(from);
150     struct UserNode *target = getUserByNick(argv[1]);
151     if(user == NULL || target == NULL) return 0;
152     struct ChanNode *chan = getChanByName(argv[0]);
153     if(chan == NULL) return 0;
154     if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
155         struct ChanUser *chanuser = getChanUser(target, chan);
156         delChanUser(chanuser, 0); //we need to free the chanuser manually!
157         event_kick(user, chanuser, argv[1]);
158         free(chanuser);
159         if(target->flags & USERFLAG_ISBOT) {
160             //check if theres another bot in the channel - otherwise free it
161             
162         }
163     }
164     if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) {
165         //remove the user
166         delUser(user, 1);
167     }
168     return 1;
169 }
170
171 static IRC_CMD(raw_ping) {
172     if(argc == 0) return 0;
173     putsock(client, "PONG :%s", argv[0]);
174     return 1;
175 }
176
177 void parser_init() {
178     //all the raws we receive...
179     register_irc_function("001", raw_001);
180     register_irc_function("KICK", raw_kick);
181     register_irc_function("JOIN", raw_join);
182     register_irc_function("PART", raw_part);
183     register_irc_function("QUIT", raw_quit);
184     register_irc_function("PING", raw_ping);
185 }