Mercurial > pidgin.yaz
annotate plugins/icq/icqevent.c @ 1522:31c0850f9340
[gaim-migrate @ 1532]
this should fix a segfault or two
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Thu, 01 Mar 2001 10:05:18 +0000 |
parents | 4c510ca3563f |
children | 8ed70631ed15 |
rev | line source |
---|---|
1309 | 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | |
3 /* | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
4 * $Id: icqevent.c 1442 2001-01-28 01:52:27Z warmenhoven $ |
1309 | 5 * |
6 * $Log$ | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
7 * Revision 1.2 2001/01/28 01:52:27 warmenhoven |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
8 * icqlib 1.1.5 |
1309 | 9 * |
10 * Revision 1.2 2000/06/15 18:54:09 bills | |
11 * added time attribute and handleEvent function pointer to icq_Event, | |
12 * renamed icq_ChatEvent to icq_ChatRequestEvent, renamed icq_FileEvent to | |
13 * icq_FileRequestEvent, added icq_URLEvent and related methods | |
14 * | |
15 * Revision 1.1 2000/06/15 15:27:39 bills | |
16 * committed for safekeeping - this code will soon replace stdpackets.c and | |
17 * greatly simplify tcphandle.c, as well as reducing code duplication in many | |
18 * places. it provides a much more flexible framework for managing events | |
19 * and parsing and creating packets | |
20 * | |
21 */ | |
22 | |
23 #include <stdlib.h> | |
24 | |
25 #include "icqevent.h" | |
26 #include "icqbyteorder.h" | |
27 | |
28 #ifdef EVENT_DEBUG | |
29 #include <string.h> | |
30 #include <stdio.h> | |
31 #endif | |
32 | |
33 #define new_event(x, y) y * x = ( y * )malloc(sizeof(y)) | |
34 | |
35 /* generic Event - 'header' for each tcp packet */ | |
36 | |
37 void icq_EventInit(icq_Event *p, int type, int subtype, unsigned long uin, | |
38 int version) | |
39 { | |
40 if (!p) | |
41 return; | |
42 | |
43 p->uin=uin; | |
44 p->version=version; | |
45 p->type=type; | |
46 p->subtype=subtype; | |
47 p->direction=ICQ_EVENT_OUTGOING; | |
48 } | |
49 | |
50 icq_Packet *icq_EventCreatePacket(icq_Event *pbase) | |
51 { | |
52 icq_Packet *p=icq_PacketNew(); | |
53 | |
54 /* create header for tcp packet */ | |
55 icq_PacketAppend32(p, pbase->uin); | |
56 icq_PacketAppend16(p, pbase->version); | |
57 icq_PacketAppend16(p, pbase->subtype); | |
58 icq_PacketAppend16(p, 0x0000); | |
59 icq_PacketAppend32(p, pbase->uin); | |
60 icq_PacketAppend32(p, pbase->type); | |
61 | |
62 return p; | |
63 } | |
64 | |
65 void icq_EventParsePacket(icq_Event *pevent, icq_Packet *p) | |
66 { | |
67 /* parse header of tcp packet */ | |
68 icq_PacketBegin(p); | |
69 (void)icq_PacketRead32(p); /* uin */ | |
70 pevent->version=icq_PacketRead16(p); /* max supported tcp version */ | |
71 pevent->subtype=icq_PacketRead16(p); /* event subtype */ | |
72 (void)icq_PacketRead16(p); /* 0x0000 */ | |
73 pevent->uin=icq_PacketRead32(p); /* uin */ | |
74 pevent->type=icq_PacketRead16(p); /* event type */ | |
75 } | |
76 | |
77 /* Message Event - extends generic Event */ | |
78 | |
79 icq_MessageEvent *icq_CreateMessageEvent(int subtype, unsigned long uin, | |
80 const char *message) | |
81 { | |
82 new_event(p, icq_MessageEvent); | |
83 icq_Event *pbase=(icq_Event *)p; | |
84 icq_MessageEventInit(p, ICQ_TCP_MSG_MSG, subtype, uin, | |
85 ICQ_TCP_MSG_REAL, message); | |
86 | |
87 pbase->createPacket=icq_MessageCreatePacket; | |
88 | |
89 #ifdef EVENT_DEBUG | |
90 pbase->eventName=icq_MessageEventName; | |
91 pbase->eventDump=icq_MessageEventDump; | |
92 #endif | |
93 | |
94 return p; | |
95 } | |
96 | |
97 void icq_MessageEventInit(icq_MessageEvent *p, int type, int subtype, | |
98 unsigned long uin, int msgtype, const char *message) | |
99 { | |
100 icq_EventInit((icq_Event *)p, type, subtype, uin, ICQ_TCP_VER); | |
101 p->type=msgtype; | |
102 p->message=(char *)message; | |
103 p->status=0; /* FIXME */ | |
104 } | |
105 | |
106 icq_Packet *icq_MessageCreatePacket(icq_Event *pbase, icq_TCPLink *plink) | |
107 { | |
108 icq_MessageEvent *pevent=(icq_MessageEvent *)pbase; | |
109 | |
110 /* create header */ | |
111 icq_Packet *p=icq_EventCreatePacket(pbase); | |
112 | |
113 /* append data specific to message event */ | |
114 icq_PacketAppendString(p, (char*)pevent->message); | |
115 icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr); | |
116 /* FIXME: should be RealIp */ | |
117 icq_PacketAppend32(p, htonl(plink->icqlink->icq_OurIP)); | |
118 icq_PacketAppend32(p, plink->socket_address.sin_port); | |
119 icq_PacketAppend8(p, 0x04); | |
120 icq_PacketAppend16(p, pevent->status); | |
121 icq_PacketAppend16(p, pevent->type); | |
122 | |
123 return p; | |
124 } | |
125 | |
126 void icq_MessageParsePacket(icq_Event *pbase, icq_Packet *p) | |
127 { | |
128 icq_MessageEvent *pevent=(icq_MessageEvent *)pbase; | |
129 | |
130 /* parse message event data from packet */ | |
131 pevent->message=(char *)icq_PacketReadString(p); /* message text */ | |
132 (void)icq_PacketRead32(p); /* remote ip */ | |
133 (void)icq_PacketRead32(p); /* remote real ip */ | |
134 (void)icq_PacketRead32(p); /* remote message port */ | |
135 (void)icq_PacketRead8(p); /* tcp flag */ | |
136 pevent->status=icq_PacketRead16(p); /* remote user status */ | |
137 pevent->type=icq_PacketRead16(p); /* message type */ | |
138 } | |
139 | |
140 #ifdef EVENT_DEBUG | |
141 const char *icq_MessageEventName(icq_Event *p) | |
142 { | |
143 if (p->type==ICQ_EVENT_MESSAGE) | |
144 return "message"; | |
145 else if (p->type==ICQ_EVENT_ACK) | |
146 return "message ack"; | |
147 | |
148 return "message cancel"; | |
149 } | |
150 | |
151 const char *icq_MessageEventDump(icq_Event *p) | |
152 { | |
153 static char buf[255]; | |
154 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
155 | |
156 sprintf(buf, ", type=%x, message=\"%10s...\", status=%x", | |
157 pevent->type, pevent->message, pevent->status); | |
158 | |
159 return buf; | |
160 } | |
161 #endif | |
162 | |
163 /* URL Event - extends message Event */ | |
164 | |
165 icq_URLEvent *icq_CreateURLEvent(int subtype, unsigned long uin, | |
166 const char *message, const char *url) | |
167 { | |
168 char *str=(char *)malloc(strlen(message)+strlen(url)+2); | |
169 icq_Event *pbase; | |
170 icq_URLEvent *p; | |
171 | |
172 strcpy((char*)str, message); | |
173 *(str+strlen(message))=0xFE; | |
174 strcpy((char*)(str+strlen(message)+1), url); | |
175 | |
176 /* TODO: make sure create message event copies message */ | |
177 pbase=(icq_Event *)icq_CreateMessageEvent(subtype, uin, str); | |
178 p=(icq_URLEvent *)pbase; | |
179 | |
180 free(str); | |
181 | |
182 *(p->message+strlen(message))=0x00; | |
183 p->url=p->message+strlen(message)+1; | |
184 | |
185 pbase->createPacket=icq_URLCreatePacket; | |
186 | |
187 #ifdef EVENT_DEBUG | |
188 pbase->eventName=icq_URLEventName; | |
189 pbase->eventDump=icq_URLEventDump; | |
190 #endif | |
191 | |
192 return p; | |
193 | |
194 } | |
195 | |
196 icq_Packet *icq_URLCreatePacket(icq_Event *pbase, icq_TCPLink *plink) | |
197 { | |
198 icq_URLEvent *pevent=(icq_URLEvent *)pbase; | |
199 icq_Packet *p; | |
200 | |
201 /* hack message string to include url */ | |
202 *(pevent->message+strlen(pevent->message))=0xFE; | |
203 | |
204 /* create packet */ | |
205 p=icq_MessageCreatePacket(pbase, plink); | |
206 | |
207 /* hack message string to seperate url */ | |
208 *(pevent->message+strlen(pevent->message))=0x00; | |
209 | |
210 return p; | |
211 } | |
212 | |
213 void icq_URLParsePacket(icq_Event *pbase, icq_Packet *p) | |
214 { | |
215 char *pfe; | |
216 icq_URLEvent *pevent=(icq_URLEvent *)pbase; | |
217 | |
218 /* TODO: make sure messageparsepacket allocates message string | |
219 * and add a delete event function */ | |
220 icq_MessageParsePacket(pbase, p); | |
221 | |
222 /* hack message string to seperate url */ | |
223 pfe=strchr(pevent->message, '\xFE'); | |
224 *pfe=0; | |
225 | |
226 /* set url */ | |
227 pevent->url=pfe+1; | |
228 | |
229 } | |
230 | |
231 #ifdef EVENT_DEBUG | |
232 const char *icq_URLEventName(icq_Event *p) | |
233 { | |
234 if (p->type==ICQ_EVENT_MESSAGE) | |
235 return "url"; | |
236 else if (p->type==ICQ_EVENT_ACK) | |
237 return "url ack"; | |
238 | |
239 return "url cancel"; | |
240 } | |
241 | |
242 const char *icq_URLEventDump(icq_Event *p) | |
243 { | |
244 static char buf[255]; | |
245 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
246 | |
247 sprintf(buf, ", type=%x, message=\"%10s...\", url=\"%10s...\" status=%x", | |
248 pevent->type, pevent->message, pevent->url, pevent->status); | |
249 | |
250 return buf; | |
251 } | |
252 #endif | |
253 | |
254 | |
255 /* Chat Request Event - extends Message Event */ | |
256 | |
257 icq_ChatRequestEvent *icq_ChatRequestEventNew(int subtype, | |
258 unsigned long uin, const char *message, int port) | |
259 { | |
260 new_event(p, icq_ChatRequestEvent); | |
261 icq_Event *pbase=(icq_Event *)p; | |
262 icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_CHAT, subtype, | |
263 uin, ICQ_TCP_MSG_REAL, message); | |
264 p->port=port; | |
265 | |
266 pbase->createPacket=icq_ChatRequestCreatePacket; | |
267 | |
268 #ifdef EVENT_DEBUG | |
269 pbase->eventName=icq_ChatRequestEventName; | |
270 pbase->eventDump=icq_ChatRequestEventDump; | |
271 #endif | |
272 | |
273 return p; | |
274 } | |
275 | |
276 icq_Packet *icq_ChatRequestCreatePacket(icq_Event *pbase, | |
277 icq_TCPLink *plink) | |
278 { | |
279 icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase; | |
280 | |
281 /* create header and message data */ | |
282 icq_Packet *p=icq_MessageCreatePacket(pbase, plink); | |
283 | |
284 /* append data specific to chat event */ | |
285 icq_PacketAppendString(p, 0); | |
286 icq_PacketAppend32(p, htonl(pevent->port)); | |
287 icq_PacketAppend32(p, htoicql(pevent->port)); | |
288 | |
289 return p; | |
290 } | |
291 | |
292 void icq_ChatParsePacket(icq_Event *pbase, icq_Packet *p) | |
293 { | |
294 icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase; | |
295 int port; | |
296 | |
297 /* parse header and message event data */ | |
298 icq_MessageParsePacket(pbase, p); | |
299 | |
300 /* parse chat event data */ | |
301 (void)icq_PacketReadString(p); /* null string */ | |
302 port=icq_PacketRead32(p); /* chat listen port, network order */ | |
303 (void)icq_PacketRead32(p); /* chat listen port, intel order */ | |
304 | |
305 pevent->port=ntohl(port); | |
306 } | |
307 | |
308 #ifdef EVENT_DEBUG | |
309 const char *icq_ChatRequestEventName(icq_Event *p) | |
310 { | |
311 if (p->type==ICQ_EVENT_MESSAGE) | |
312 return "chat request"; | |
313 else if (p->type==ICQ_EVENT_ACK) { | |
314 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
315 if (pevent->status==ICQ_TCP_STATUS_REFUSE) | |
316 return "chat request refuse"; | |
317 else | |
318 return "chat request ack"; | |
319 } else if (p->type==ICQ_EVENT_CANCEL) | |
320 return "chat request cancel"; | |
321 | |
322 return "unknown chat request"; | |
323 } | |
324 | |
325 const char *icq_ChatRequestEventDump(icq_Event *p) | |
326 { | |
327 static char buf[255]; | |
328 static char buf2[255]; | |
329 icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)p; | |
330 | |
331 strcpy(buf, icq_MessageEventDump(p)); | |
332 sprintf(buf2, ", port=%d", pevent->port); | |
333 strcat(buf, buf2); | |
334 | |
335 return buf; | |
336 } | |
337 #endif | |
338 | |
339 /* File Request Event - builds on Message Event */ | |
340 | |
341 icq_FileRequestEvent *icq_FileRequestEventNew(int subtype, | |
342 unsigned long uin, const char *message, const char *filename, | |
343 unsigned long filesize) | |
344 { | |
345 new_event(p, icq_FileRequestEvent); | |
346 icq_Event *pbase=(icq_Event *)p; | |
347 icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_FILE, subtype, | |
348 uin, ICQ_TCP_MSG_REAL, message); | |
349 p->filename=filename; | |
350 p->filesize=filesize; | |
351 | |
352 pbase->createPacket=icq_FileRequestCreatePacket; | |
353 | |
354 #ifdef EVENT_DEBUG | |
355 pbase->eventName=icq_FileRequestEventName; | |
356 pbase->eventDump=icq_FileRequestEventDump; | |
357 #endif | |
358 | |
359 return p; | |
360 } | |
361 | |
362 icq_Packet *icq_FileRequestCreatePacket(icq_Event *pbase, | |
363 icq_TCPLink *plink) | |
364 { | |
365 icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase; | |
366 | |
367 /* create header and message data */ | |
368 icq_Packet *p=icq_MessageCreatePacket(pbase, plink); | |
369 | |
370 /* append file event data */ | |
371 icq_PacketAppend32(p, htonl(pevent->port)); | |
372 icq_PacketAppendString(p, pevent->filename); | |
373 icq_PacketAppend32(p, pevent->filesize); | |
374 icq_PacketAppend32(p, htoicql(pevent->port)); | |
375 | |
376 return p; | |
377 } | |
378 | |
379 void icq_FileParsePacket(icq_Event *pbase, icq_Packet *p) | |
380 { | |
381 icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase; | |
382 int port; | |
383 | |
384 /* parse header and message data */ | |
385 icq_MessageParsePacket(pbase, p); | |
386 | |
387 /* parse file event data */ | |
388 port=icq_PacketRead32(p); /* file listen port, network */ | |
389 pevent->filename=icq_PacketReadString(p); /* filename text */ | |
390 pevent->filesize=icq_PacketRead32(p); /* total size */ | |
391 (void)icq_PacketRead32(p); /* file listen port, intel */ | |
392 | |
393 pevent->port=ntohl(port); | |
394 } | |
395 | |
396 #ifdef EVENT_DEBUG | |
397 const char *icq_FileRequestEventName(icq_Event *p) | |
398 { | |
399 if (p->type==ICQ_EVENT_MESSAGE) | |
400 return "file request"; | |
401 else if (p->type==ICQ_EVENT_ACK) { | |
402 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
403 if (pevent->status==ICQ_TCP_STATUS_REFUSE) | |
404 return "file request refuse"; | |
405 else | |
406 return "file request ack"; | |
407 } else if (p->type==ICQ_EVENT_CANCEL) | |
408 return "file request cancel"; | |
409 | |
410 return "unknown file request"; | |
411 } | |
412 | |
413 const char *icq_FileRequestEventDump(icq_Event *p) | |
414 { | |
415 static char buf[255]; | |
416 static char buf2[255]; | |
417 icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)p; | |
418 | |
419 strcpy(buf, icq_MessageEventDump(p)); | |
420 sprintf(buf2, ", port=%d, filename=\"%s\", filesize=%ld", pevent->port, | |
421 pevent->filename, pevent->filesize); | |
422 strcat(buf, buf2); | |
423 | |
424 return buf; | |
425 } | |
426 #endif | |
427 | |
428 /* main packet parser */ | |
429 | |
430 icq_Event *icq_ParsePacket(icq_Packet *p) | |
431 { | |
432 /* FIXME */ | |
433 icq_Event *pevent=(icq_Event *)malloc(sizeof(icq_FileRequestEvent)); | |
434 pevent->direction=ICQ_EVENT_INCOMING; | |
435 pevent->time=time(0); | |
436 | |
437 icq_EventParsePacket(pevent, p); | |
438 | |
439 switch(pevent->type) { | |
440 | |
441 case ICQ_TCP_MSG_MSG: | |
442 icq_MessageParsePacket(pevent, p); | |
443 break; | |
444 case ICQ_TCP_MSG_URL: | |
445 icq_URLParsePacket(pevent, p); | |
446 break; | |
447 case ICQ_TCP_MSG_CHAT: | |
448 icq_ChatParsePacket(pevent, p); | |
449 break; | |
450 case ICQ_TCP_MSG_FILE: | |
451 icq_FileParsePacket(pevent, p); | |
452 break; | |
453 default: | |
454 /* FIXME: log */ | |
455 free(pevent); | |
456 pevent=0; | |
457 break; | |
458 } | |
459 | |
460 /* FIXME: ensure no bytes are remaining */ | |
461 | |
462 return pevent; | |
463 } | |
464 | |
465 #ifdef EVENT_DEBUG | |
466 const char *icq_EventDump(icq_Event *pevent) | |
467 { | |
468 static char buf[255]; | |
469 | |
470 sprintf("%s event sent to uin %ld { %s }", (pevent->eventName)(pevent), | |
471 pevent->uin, (pevent->eventDump)(pevent) ); | |
472 | |
473 return buf; | |
474 } | |
475 #endif |