Mercurial > pidgin
diff src/protocols/icq/tcphandle.c @ 2086:424a40f12a6c
[gaim-migrate @ 2096]
moving protocols from plugins/ to src/protocols. making it so that you can select which protocols are compiled statically.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Tue, 31 Jul 2001 01:00:39 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/icq/tcphandle.c Tue Jul 31 01:00:39 2001 +0000 @@ -0,0 +1,361 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + * $Id: tcphandle.c 2096 2001-07-31 01:00:39Z warmenhoven $ + * + * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and + * Bill Soudan <soudan@kde.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <stdlib.h> + +#include "icqlib.h" + +#include "tcp.h" +#include "stdpackets.h" + +void icq_TCPOnMessageReceived(icq_Link *icqlink, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink); +void icq_TCPOnURLReceived(icq_Link *icqlink, DWORD uin, const char *message, DWORD id); +void icq_TCPOnContactListReceived(icq_Link *icqlink, DWORD uin, const char *message, DWORD id); +void icq_TCPOnChatReqReceived(icq_Link *icqlink, DWORD uin, const char *message, DWORD id); +void icq_TCPOnFileReqReceived(icq_Link *icqlink, DWORD uin, const char *message, + const char *filename, unsigned long filesize, DWORD id); +void icq_TCPProcessAck(icq_Link *icqlink, 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: + case ICQ_TCP_MSG_READAWAY: + case ICQ_TCP_MSG_READNA: + case ICQ_TCP_MSG_READDND: + case ICQ_TCP_MSG_READOCCUPIED: + case ICQ_TCP_MSG_READFFC: + 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: + invoke_callback(plink->icqlink, icq_RequestNotify) + (plink->icqlink, p->id, ICQ_NOTIFY_ACK, status, (void *)message); + 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: + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "received ack %d\n", + p->id); + break; + + case ICQ_TCP_MSG_READAWAY: + case ICQ_TCP_MSG_READNA: + case ICQ_TCP_MSG_READDND: + case ICQ_TCP_MSG_READOCCUPIED: + case ICQ_TCP_MSG_READFFC: + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "received away msg, seq %d\n", p->id); + invoke_callback(plink->icqlink, icq_RecvAwayMsg) + (plink->icqlink, p->id, message); + break; + } + invoke_callback(plink->icqlink, icq_RequestNotify) + (plink->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, NULL); + 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(icq_Link *icqlink, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink) +{ + char data[ICQ_MAX_MESSAGE_SIZE]; + + /* use the current system time for time received */ + time_t t=time(0); + struct tm *ptime=localtime(&t); + icq_Packet *pack; + +#ifdef TCP_PACKET_TRACE + printf("tcp message packet received from %lu { sequence=%x }\n", + uin, (int)id); +#endif + + strncpy(data,message,sizeof(data)); + data[sizeof(data)-1]='\0'; + icq_RusConv("wk",data); + + invoke_callback(icqlink,icq_RecvMessage)(icqlink, uin, ptime->tm_hour, + ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, data); + + /* + icq_TCPLink *preallink=icq_FindTCPLink(icqlink, uin, TCP_LINK_MESSAGE); + if(plink != preallink) + invoke_callback(icqlink,icq_SpoofedMessage)(uin, ...) + */ + + /* 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(icq_Link *icqlink, DWORD uin, const char *message, DWORD id) +{ + /* 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(icqlink, uin, TCP_LINK_MESSAGE); + +#ifdef TCP_PACKET_TRACE + printf("tcp url packet received from %lu { sequence=%lx }\n", + uin, id); +#endif /*TCP_PACKET_TRACE*/ + + /* the URL is split from the description by 0xFE */ + pfe=strchr(message, '\xFE'); + *pfe=0; + icq_RusConv("wk", (char*)message); + + invoke_callback(icqlink,icq_RecvURL)(icqlink, 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(icq_Link *icqlink, DWORD uin, const char *message, DWORD id) +{ + /* use the current system time for time received */ + time_t t=time(0); + struct tm *ptime=localtime(&t); + icq_Packet *pack; + icq_List *strList = icq_ListNew(); + int i, k, nr = icq_SplitFields(strList, message); + const char **contact_uin = (const char **)malloc((nr - 2) /2); + const char **contact_nick = (const char **)malloc((nr - 2) /2); + icq_TCPLink *plink=icq_FindTCPLink(icqlink, uin, TCP_LINK_MESSAGE); + +#ifdef TCP_PACKET_TRACE + printf("tcp contactlist packet received from %lu { sequence=%lx }\n", uin, id); +#endif /* TCP_PACKET_TRACE */ + + /* split message */ + for (i = 1, k = 0; i < (nr - 1); k++) + { + contact_uin[k] = icq_ListAt(strList, i); + contact_nick[k] = icq_ListAt(strList, i + 1); + i += 2; + } + + invoke_callback(icqlink,icq_RecvContactList)(icqlink, uin, + ptime->tm_hour, ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1, + ptime->tm_year+1900, k, contact_uin, 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); + + free(contact_nick); + free(contact_uin); + icq_ListDelete(strList, free); +}