Mercurial > pidgin.yaz
view plugins/icq/tcphandle.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 |
line wrap: on
line source
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* $Id: tcphandle.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ Revision 1.3 2001/01/28 01:52:27 warmenhoven icqlib 1.1.5 Revision 1.16 2001/01/24 05:11:14 bills applied patch from Robin Ericsson <lobbin@localhost.nu> which implements receiving contact lists. See new icq_RecvContactList callback. Revision 1.15 2001/01/17 01:31:47 bills Rework chat and file interfaces; implement socket notifications. Revision 1.14 2000/12/06 05:15:45 denis Handling for mass TCP messages has been added based on patch by Konstantin Klyagin <konst@konst.org.ua> Revision 1.13 2000/08/13 19:44:41 denis Cyrillic recoding on received URL description added. Revision 1.12 2000/07/09 22:19:35 bills added new *Close functions, use *Close functions instead of *Delete where correct, and misc cleanup Revision 1.11 2000/06/25 16:36:16 denis '\n' was added at the end of log messages. Revision 1.10 2000/05/04 15:57:20 bills Reworked file transfer notification, small bugfixes, and cleanups. Revision 1.9 2000/05/03 18:29:15 denis Callbacks have been moved to the ICQLINK structure. Revision 1.8 2000/04/05 14:37:02 denis Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 compatibility. Revision 1.7 2000/01/20 20:06:00 bills removed debugging printfs Revision 1.6 2000/01/20 19:59:15 bills first implementation of sending file requests Revision 1.5 1999/11/30 09:51:42 bills more file xfer logic added Revision 1.4 1999/11/11 15:10:30 guruz - Added Base for Webpager Messages. Please type "make fixme" - Removed Segfault when kicq is started the first time Revision 1.3 1999/10/01 02:28:51 bills icq_TCPProcessHello returns something now :) Revision 1.2 1999/10/01 00:49:20 lord some compilation problems are fixed. Revision 1.1 1999/09/29 19:47:21 bills reworked chat/file handling. fixed chat. (it's been broke since I put non-blocking connects in) Revision 1.15 1999/07/16 15:45:59 denis Cleaned up. Revision 1.14 1999/07/16 12:10:10 denis tcp_packet* functions renamed to icq_Packet* Cleaned up. Revision 1.13 1999/07/12 15:13:41 cproch - added definition of ICQLINK to hold session-specific global variabled applications which have more than one connection are now possible - changed nearly every function defintion to support ICQLINK parameter Revision 1.12 1999/06/30 13:51:25 bills cleanups Revision 1.11 1999/05/03 21:41:30 bills initial file xfer support added- untested Revision 1.10 1999/04/29 09:36:06 denis Cleanups, warning removed Revision 1.9 1999/04/17 19:40:33 bills reworked code to use icq_TCPLinks instead of icq_ContactItem entries. modified ProcessChatPacket to negotiate both sending and receiving chat requests properly. Revision 1.8 1999/04/14 15:12:02 denis Cleanups for "strict" compiling (-ansi -pedantic) icq_ContactItem parameter added to function icq_TCPOnMessageReceived() Segfault fixed on spoofed messages. */ #include <stdlib.h> #include <time.h> #ifndef _WIN32 #include <unistd.h> #endif #include "icqtypes.h" #include "icq.h" #include "icqlib.h" #include "tcp.h" #include "stdpackets.h" #include "tcplink.h" void icq_TCPOnMessageReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink); void icq_TCPOnURLReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); void icq_TCPOnContactListReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); void icq_TCPOnChatReqReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); void icq_TCPOnFileReqReceived(ICQLINK *link, DWORD uin, const char *message, const char *filename, unsigned long filesize, DWORD id); void icq_TCPProcessAck(ICQLINK *link, icq_Packet *p); void icq_HandleChatAck(icq_TCPLink *plink, icq_Packet *p, int port); void icq_HandleChatHello(icq_TCPLink *plink); void icq_HandleFileHello(icq_TCPLink *plink); void icq_HandleFileAck(icq_TCPLink *plink, icq_Packet *p, int port); void icq_TCPProcessPacket(icq_Packet *p, icq_TCPLink *plink) { DWORD uin; WORD version; WORD command; WORD type; WORD status; DWORD command_type; DWORD filesize = 0; DWORD port = 0; const char *message; const char *filename = 0; icq_PacketBegin(p); (void)icq_PacketRead32(p); version=icq_PacketRead16(p); command=icq_PacketRead16(p); (void)icq_PacketRead16(p); uin=icq_PacketRead32(p); type=icq_PacketRead16(p); message=icq_PacketReadString(p); (void)icq_PacketRead32(p); (void)icq_PacketRead32(p); (void)icq_PacketRead32(p); (void)icq_PacketRead8(p); status=icq_PacketRead16(p); command_type=icq_PacketRead16(p); switch(type & ~ICQ_TCP_MASS_MASK) { case ICQ_TCP_MSG_MSG: case ICQ_TCP_MSG_URL: case ICQ_TCP_MSG_CONTACTLIST: p->id=icq_PacketRead32(p); break; case ICQ_TCP_MSG_CHAT: (void)icq_PacketReadString(p); (void)icq_PacketRead16(p); (void)icq_PacketRead16(p); port=icq_PacketRead32(p); p->id=icq_PacketRead32(p); break; case ICQ_TCP_MSG_FILE: (void)icq_PacketRead16(p); (void)icq_PacketRead16(p); filename=icq_PacketReadString(p); filesize=icq_PacketRead32(p); port=icq_PacketRead32(p); p->id=icq_PacketRead32(p); break; default: icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message packet, type %x\n", type); } #ifdef TCP_PROCESS_TRACE printf("packet processed from uin: %lu:\n", uin); printf(" command: %x\ttype: %x\n", command, type); printf(" status: %x\tcommand_type: %x\n", status, (int)command_type); printf(" message %s\n", message); printf(" id: %x\n", (int)p->id); #endif switch(command) { case ICQ_TCP_MESSAGE: switch(type & ~ICQ_TCP_MASS_MASK) { case ICQ_TCP_MSG_MSG: icq_TCPOnMessageReceived(plink->icqlink, uin, message, p->id, plink); break; case ICQ_TCP_MSG_URL: icq_TCPOnURLReceived(plink->icqlink, uin, message, p->id); break; case ICQ_TCP_MSG_CHAT: icq_TCPOnChatReqReceived(plink->icqlink, uin, message, p->id); break; case ICQ_TCP_MSG_FILE: icq_TCPOnFileReqReceived(plink->icqlink, uin, message, filename, filesize, p->id); break; case ICQ_TCP_MSG_CONTACTLIST: icq_TCPOnContactListReceived(plink->icqlink, uin, message, p->id); break; default: icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message type %d!\n", type); break; } break; case ICQ_TCP_ACK: switch(type) { case ICQ_TCP_MSG_CHAT: icq_HandleChatAck(plink, p, port); break; case ICQ_TCP_MSG_FILE: icq_HandleFileAck(plink, p, port); break; case ICQ_TCP_MSG_MSG: case ICQ_TCP_MSG_URL: if(plink->icqlink->icq_RequestNotify) { icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "received ack %d\n", p->id); invoke_callback(plink->icqlink, icq_RequestNotify) (plink->icqlink, p->id, ICQ_NOTIFY_ACK, status, (void *)message); invoke_callback(plink->icqlink, icq_RequestNotify) (plink->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, NULL); } break; } break; case ICQ_TCP_CANCEL: /* icq_TCPProcessCancel(p); */ break; default: icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown packet command %d!\n", command); } } void icq_TCPProcessCancel(icq_Packet *p) { (void)p; /* find packet in queue call notification function remove packet from queue */ } int icq_TCPProcessHello(icq_Packet *p, icq_TCPLink *plink) { /* TCP Hello packet */ BYTE code; /* 0xFF - init packet code */ DWORD version; /* tcp version */ DWORD remote_port; /* remote message listen port */ DWORD remote_uin; /* remote uin */ DWORD remote_ip; /* remote IP as seen by ICQ server */ DWORD remote_real_ip; /* remote IP as seen by client */ BYTE flags; /* tcp flags */ DWORD remote_other_port; /* remote chat or file listen port */ icq_PacketBegin(p); code=icq_PacketRead8(p); version=icq_PacketRead32(p); if (!(p->length>=26 && code==ICQ_TCP_HELLO)) { icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "malformed hello packet received from %s:%d, closing link\n", inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), ntohs(plink->remote_address.sin_port)); icq_TCPLinkClose(plink); return 0; } remote_port=icq_PacketRead32(p); remote_uin=icq_PacketRead32(p); remote_ip=icq_PacketRead32(p); remote_real_ip=icq_PacketRead32(p); flags=icq_PacketRead8(p); remote_other_port=icq_PacketRead32(p); icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "hello packet received from %lu { version=%d }\n", remote_uin, version); plink->remote_version=version; plink->remote_uin=remote_uin; plink->flags=flags; plink->mode&=~TCP_LINK_MODE_HELLOWAIT; /* file and chat sessions require additional handling */ if(plink->type==TCP_LINK_CHAT) icq_HandleChatHello(plink); if(plink->type==TCP_LINK_FILE) icq_HandleFileHello(plink); return 1; } void icq_TCPOnMessageReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink) { char data[512] ; #ifdef TCP_PACKET_TRACE printf("tcp message packet received from %lu { sequence=%x }\n", uin, (int)id); #endif if(link->icq_RecvMessage) { /* use the current system time for time received */ time_t t=time(0); struct tm *ptime=localtime(&t); icq_Packet *pack; icq_TCPLink *preallink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE); strncpy(data,message,512) ; icq_RusConv("wk",data) ; (*link->icq_RecvMessage)(link, uin, ptime->tm_hour, ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, data); if(plink != preallink) { /* if(icq_SpoofedMessage) (*icq_SpoofedMessage(uin, ...));*/ } if(plink) { /* send an acknowledgement to the remote client */ pack=icq_TCPCreateMessageAck(plink,0); icq_PacketAppend32(pack, id); icq_PacketSend(pack, plink->socket); #ifdef TCP_PACKET_TRACE printf("tcp message ack sent to uin %lu { sequence=%lx }\n", uin, id); #endif icq_PacketDelete(pack); } } } void icq_TCPOnURLReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id) { #ifdef TCP_PACKET_TRACE printf("tcp url packet received from %lu { sequence=%lx }\n", uin, id); #endif /*TCP_PACKET_TRACE*/ if(link->icq_RecvURL) { /* use the current system time for time received */ time_t t=time(0); struct tm *ptime=localtime(&t); icq_Packet *pack; char *pfe; icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE); /* the URL is split from the description by 0xFE */ pfe=strchr(message, '\xFE'); *pfe=0; icq_RusConv("wk", (char*)message); (*link->icq_RecvURL)(link, uin, ptime->tm_hour, ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, pfe+1, message); /* send an acknowledgement to the remote client */ pack=icq_TCPCreateURLAck(plink,0); icq_PacketAppend32(pack, id); icq_PacketSend(pack, plink->socket); #ifdef TCP_PACKET_TRACE printf("tcp message ack sent to %lu { sequence=%lx }\n", uin, id); #endif icq_PacketDelete(pack); } } void icq_TCPOnContactListReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id) { #ifdef TCP_PACKET_TRACE printf("tcp contactlist packet received from %lu { sequence=%lx }\n", uin, id); #endif /* TCP_PACKET_TRACE */ if (link->icq_RecvContactList) { /* use the current system time for time received */ time_t t=time(0); struct tm *ptime=localtime(&t); icq_Packet *pack; list *strList = list_new(); int i, k, nr = icq_SplitFields(strList, message); char *contact_uin[(nr - 2) /2], *contact_nick[(nr - 2) /2]; icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE); /* split message */ for (i = 1, k = 0; i < (nr - 1); k++) { contact_uin[k] = list_at(strList, i); contact_nick[k] = list_at(strList, i + 1); i += 2; } (*link->icq_RecvContactList)(link, uin, k, (const char **) contact_uin, (const char **) contact_nick); /* send an acknowledement to the remote client */ pack=icq_TCPCreateContactListAck(plink, 0); icq_PacketAppend32(pack, id); icq_PacketSend(pack, plink->socket); #ifdef TCP_PACKET_TRACE printf("tcp message ack sent to %lu { sequence=%lx }\n", uin, id); #endif /* TCP_PACKE_TRACE */ icq_PacketDelete(pack); list_delete(strList, free); } }