Mercurial > pidgin
annotate plugins/icq/icqevent.c @ 1684:89c19002e73d
[gaim-migrate @ 1694]
stop getting booted by gabber people
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Thu, 05 Apr 2001 01:04:10 +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 |
