Mercurial > pidgin
diff plugins/icq/icqevent.c @ 1309:0a766047b4fd
[gaim-migrate @ 1319]
Yay, new icqlib
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Tue, 19 Dec 2000 10:08:29 +0000 |
parents | |
children | 4c510ca3563f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqevent.c Tue Dec 19 10:08:29 2000 +0000 @@ -0,0 +1,475 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + * $Id: icqevent.c 1319 2000-12-19 10:08:29Z warmenhoven $ + * + * $Log$ + * Revision 1.1 2000/12/19 10:08:29 warmenhoven + * Yay, new icqlib + * + * Revision 1.2 2000/06/15 18:54:09 bills + * added time attribute and handleEvent function pointer to icq_Event, + * renamed icq_ChatEvent to icq_ChatRequestEvent, renamed icq_FileEvent to + * icq_FileRequestEvent, added icq_URLEvent and related methods + * + * Revision 1.1 2000/06/15 15:27:39 bills + * committed for safekeeping - this code will soon replace stdpackets.c and + * greatly simplify tcphandle.c, as well as reducing code duplication in many + * places. it provides a much more flexible framework for managing events + * and parsing and creating packets + * +*/ + +#include <stdlib.h> + +#include "icqevent.h" +#include "icqbyteorder.h" + +#ifdef EVENT_DEBUG +#include <string.h> +#include <stdio.h> +#endif + +#define new_event(x, y) y * x = ( y * )malloc(sizeof(y)) + +/* generic Event - 'header' for each tcp packet */ + +void icq_EventInit(icq_Event *p, int type, int subtype, unsigned long uin, + int version) +{ + if (!p) + return; + + p->uin=uin; + p->version=version; + p->type=type; + p->subtype=subtype; + p->direction=ICQ_EVENT_OUTGOING; +} + +icq_Packet *icq_EventCreatePacket(icq_Event *pbase) +{ + icq_Packet *p=icq_PacketNew(); + + /* create header for tcp packet */ + icq_PacketAppend32(p, pbase->uin); + icq_PacketAppend16(p, pbase->version); + icq_PacketAppend16(p, pbase->subtype); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend32(p, pbase->uin); + icq_PacketAppend32(p, pbase->type); + + return p; +} + +void icq_EventParsePacket(icq_Event *pevent, icq_Packet *p) +{ + /* parse header of tcp packet */ + icq_PacketBegin(p); + (void)icq_PacketRead32(p); /* uin */ + pevent->version=icq_PacketRead16(p); /* max supported tcp version */ + pevent->subtype=icq_PacketRead16(p); /* event subtype */ + (void)icq_PacketRead16(p); /* 0x0000 */ + pevent->uin=icq_PacketRead32(p); /* uin */ + pevent->type=icq_PacketRead16(p); /* event type */ +} + +/* Message Event - extends generic Event */ + +icq_MessageEvent *icq_CreateMessageEvent(int subtype, unsigned long uin, + const char *message) +{ + new_event(p, icq_MessageEvent); + icq_Event *pbase=(icq_Event *)p; + icq_MessageEventInit(p, ICQ_TCP_MSG_MSG, subtype, uin, + ICQ_TCP_MSG_REAL, message); + + pbase->createPacket=icq_MessageCreatePacket; + +#ifdef EVENT_DEBUG + pbase->eventName=icq_MessageEventName; + pbase->eventDump=icq_MessageEventDump; +#endif + + return p; +} + +void icq_MessageEventInit(icq_MessageEvent *p, int type, int subtype, + unsigned long uin, int msgtype, const char *message) +{ + icq_EventInit((icq_Event *)p, type, subtype, uin, ICQ_TCP_VER); + p->type=msgtype; + p->message=(char *)message; + p->status=0; /* FIXME */ +} + +icq_Packet *icq_MessageCreatePacket(icq_Event *pbase, icq_TCPLink *plink) +{ + icq_MessageEvent *pevent=(icq_MessageEvent *)pbase; + + /* create header */ + icq_Packet *p=icq_EventCreatePacket(pbase); + + /* append data specific to message event */ + icq_PacketAppendString(p, (char*)pevent->message); + icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr); + /* FIXME: should be RealIp */ + icq_PacketAppend32(p, htonl(plink->icqlink->icq_OurIP)); + icq_PacketAppend32(p, plink->socket_address.sin_port); + icq_PacketAppend8(p, 0x04); + icq_PacketAppend16(p, pevent->status); + icq_PacketAppend16(p, pevent->type); + + return p; +} + +void icq_MessageParsePacket(icq_Event *pbase, icq_Packet *p) +{ + icq_MessageEvent *pevent=(icq_MessageEvent *)pbase; + + /* parse message event data from packet */ + pevent->message=(char *)icq_PacketReadString(p); /* message text */ + (void)icq_PacketRead32(p); /* remote ip */ + (void)icq_PacketRead32(p); /* remote real ip */ + (void)icq_PacketRead32(p); /* remote message port */ + (void)icq_PacketRead8(p); /* tcp flag */ + pevent->status=icq_PacketRead16(p); /* remote user status */ + pevent->type=icq_PacketRead16(p); /* message type */ +} + +#ifdef EVENT_DEBUG +const char *icq_MessageEventName(icq_Event *p) +{ + if (p->type==ICQ_EVENT_MESSAGE) + return "message"; + else if (p->type==ICQ_EVENT_ACK) + return "message ack"; + + return "message cancel"; +} + +const char *icq_MessageEventDump(icq_Event *p) +{ + static char buf[255]; + icq_MessageEvent *pevent=(icq_MessageEvent *)p; + + sprintf(buf, ", type=%x, message=\"%10s...\", status=%x", + pevent->type, pevent->message, pevent->status); + + return buf; +} +#endif + +/* URL Event - extends message Event */ + +icq_URLEvent *icq_CreateURLEvent(int subtype, unsigned long uin, + const char *message, const char *url) +{ + char *str=(char *)malloc(strlen(message)+strlen(url)+2); + icq_Event *pbase; + icq_URLEvent *p; + + strcpy((char*)str, message); + *(str+strlen(message))=0xFE; + strcpy((char*)(str+strlen(message)+1), url); + + /* TODO: make sure create message event copies message */ + pbase=(icq_Event *)icq_CreateMessageEvent(subtype, uin, str); + p=(icq_URLEvent *)pbase; + + free(str); + + *(p->message+strlen(message))=0x00; + p->url=p->message+strlen(message)+1; + + pbase->createPacket=icq_URLCreatePacket; + +#ifdef EVENT_DEBUG + pbase->eventName=icq_URLEventName; + pbase->eventDump=icq_URLEventDump; +#endif + + return p; + +} + +icq_Packet *icq_URLCreatePacket(icq_Event *pbase, icq_TCPLink *plink) +{ + icq_URLEvent *pevent=(icq_URLEvent *)pbase; + icq_Packet *p; + + /* hack message string to include url */ + *(pevent->message+strlen(pevent->message))=0xFE; + + /* create packet */ + p=icq_MessageCreatePacket(pbase, plink); + + /* hack message string to seperate url */ + *(pevent->message+strlen(pevent->message))=0x00; + + return p; +} + +void icq_URLParsePacket(icq_Event *pbase, icq_Packet *p) +{ + char *pfe; + icq_URLEvent *pevent=(icq_URLEvent *)pbase; + + /* TODO: make sure messageparsepacket allocates message string + * and add a delete event function */ + icq_MessageParsePacket(pbase, p); + + /* hack message string to seperate url */ + pfe=strchr(pevent->message, '\xFE'); + *pfe=0; + + /* set url */ + pevent->url=pfe+1; + +} + +#ifdef EVENT_DEBUG +const char *icq_URLEventName(icq_Event *p) +{ + if (p->type==ICQ_EVENT_MESSAGE) + return "url"; + else if (p->type==ICQ_EVENT_ACK) + return "url ack"; + + return "url cancel"; +} + +const char *icq_URLEventDump(icq_Event *p) +{ + static char buf[255]; + icq_MessageEvent *pevent=(icq_MessageEvent *)p; + + sprintf(buf, ", type=%x, message=\"%10s...\", url=\"%10s...\" status=%x", + pevent->type, pevent->message, pevent->url, pevent->status); + + return buf; +} +#endif + + +/* Chat Request Event - extends Message Event */ + +icq_ChatRequestEvent *icq_ChatRequestEventNew(int subtype, + unsigned long uin, const char *message, int port) +{ + new_event(p, icq_ChatRequestEvent); + icq_Event *pbase=(icq_Event *)p; + icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_CHAT, subtype, + uin, ICQ_TCP_MSG_REAL, message); + p->port=port; + + pbase->createPacket=icq_ChatRequestCreatePacket; + +#ifdef EVENT_DEBUG + pbase->eventName=icq_ChatRequestEventName; + pbase->eventDump=icq_ChatRequestEventDump; +#endif + + return p; +} + +icq_Packet *icq_ChatRequestCreatePacket(icq_Event *pbase, + icq_TCPLink *plink) +{ + icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase; + + /* create header and message data */ + icq_Packet *p=icq_MessageCreatePacket(pbase, plink); + + /* append data specific to chat event */ + icq_PacketAppendString(p, 0); + icq_PacketAppend32(p, htonl(pevent->port)); + icq_PacketAppend32(p, htoicql(pevent->port)); + + return p; +} + +void icq_ChatParsePacket(icq_Event *pbase, icq_Packet *p) +{ + icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase; + int port; + + /* parse header and message event data */ + icq_MessageParsePacket(pbase, p); + + /* parse chat event data */ + (void)icq_PacketReadString(p); /* null string */ + port=icq_PacketRead32(p); /* chat listen port, network order */ + (void)icq_PacketRead32(p); /* chat listen port, intel order */ + + pevent->port=ntohl(port); +} + +#ifdef EVENT_DEBUG +const char *icq_ChatRequestEventName(icq_Event *p) +{ + if (p->type==ICQ_EVENT_MESSAGE) + return "chat request"; + else if (p->type==ICQ_EVENT_ACK) { + icq_MessageEvent *pevent=(icq_MessageEvent *)p; + if (pevent->status==ICQ_TCP_STATUS_REFUSE) + return "chat request refuse"; + else + return "chat request ack"; + } else if (p->type==ICQ_EVENT_CANCEL) + return "chat request cancel"; + + return "unknown chat request"; +} + +const char *icq_ChatRequestEventDump(icq_Event *p) +{ + static char buf[255]; + static char buf2[255]; + icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)p; + + strcpy(buf, icq_MessageEventDump(p)); + sprintf(buf2, ", port=%d", pevent->port); + strcat(buf, buf2); + + return buf; +} +#endif + +/* File Request Event - builds on Message Event */ + +icq_FileRequestEvent *icq_FileRequestEventNew(int subtype, + unsigned long uin, const char *message, const char *filename, + unsigned long filesize) +{ + new_event(p, icq_FileRequestEvent); + icq_Event *pbase=(icq_Event *)p; + icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_FILE, subtype, + uin, ICQ_TCP_MSG_REAL, message); + p->filename=filename; + p->filesize=filesize; + + pbase->createPacket=icq_FileRequestCreatePacket; + +#ifdef EVENT_DEBUG + pbase->eventName=icq_FileRequestEventName; + pbase->eventDump=icq_FileRequestEventDump; +#endif + + return p; +} + +icq_Packet *icq_FileRequestCreatePacket(icq_Event *pbase, + icq_TCPLink *plink) +{ + icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase; + + /* create header and message data */ + icq_Packet *p=icq_MessageCreatePacket(pbase, plink); + + /* append file event data */ + icq_PacketAppend32(p, htonl(pevent->port)); + icq_PacketAppendString(p, pevent->filename); + icq_PacketAppend32(p, pevent->filesize); + icq_PacketAppend32(p, htoicql(pevent->port)); + + return p; +} + +void icq_FileParsePacket(icq_Event *pbase, icq_Packet *p) +{ + icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase; + int port; + + /* parse header and message data */ + icq_MessageParsePacket(pbase, p); + + /* parse file event data */ + port=icq_PacketRead32(p); /* file listen port, network */ + pevent->filename=icq_PacketReadString(p); /* filename text */ + pevent->filesize=icq_PacketRead32(p); /* total size */ + (void)icq_PacketRead32(p); /* file listen port, intel */ + + pevent->port=ntohl(port); +} + +#ifdef EVENT_DEBUG +const char *icq_FileRequestEventName(icq_Event *p) +{ + if (p->type==ICQ_EVENT_MESSAGE) + return "file request"; + else if (p->type==ICQ_EVENT_ACK) { + icq_MessageEvent *pevent=(icq_MessageEvent *)p; + if (pevent->status==ICQ_TCP_STATUS_REFUSE) + return "file request refuse"; + else + return "file request ack"; + } else if (p->type==ICQ_EVENT_CANCEL) + return "file request cancel"; + + return "unknown file request"; +} + +const char *icq_FileRequestEventDump(icq_Event *p) +{ + static char buf[255]; + static char buf2[255]; + icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)p; + + strcpy(buf, icq_MessageEventDump(p)); + sprintf(buf2, ", port=%d, filename=\"%s\", filesize=%ld", pevent->port, + pevent->filename, pevent->filesize); + strcat(buf, buf2); + + return buf; +} +#endif + +/* main packet parser */ + +icq_Event *icq_ParsePacket(icq_Packet *p) +{ + /* FIXME */ + icq_Event *pevent=(icq_Event *)malloc(sizeof(icq_FileRequestEvent)); + pevent->direction=ICQ_EVENT_INCOMING; + pevent->time=time(0); + + icq_EventParsePacket(pevent, p); + + switch(pevent->type) { + + case ICQ_TCP_MSG_MSG: + icq_MessageParsePacket(pevent, p); + break; + case ICQ_TCP_MSG_URL: + icq_URLParsePacket(pevent, p); + break; + case ICQ_TCP_MSG_CHAT: + icq_ChatParsePacket(pevent, p); + break; + case ICQ_TCP_MSG_FILE: + icq_FileParsePacket(pevent, p); + break; + default: + /* FIXME: log */ + free(pevent); + pevent=0; + break; + } + + /* FIXME: ensure no bytes are remaining */ + + return pevent; +} + +#ifdef EVENT_DEBUG +const char *icq_EventDump(icq_Event *pevent) +{ + static char buf[255]; + + sprintf("%s event sent to uin %ld { %s }", (pevent->eventName)(pevent), + pevent->uin, (pevent->eventDump)(pevent) ); + + return buf; +} +#endif