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