1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
4 * $Id: tcphandle.c 2096 2001-07-31 01:00:39Z warmenhoven $
6 * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and
7 * Bill Soudan <soudan@kde.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include "stdpackets.h"
32 void icq_TCPOnMessageReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
, DWORD id
, icq_TCPLink
*plink
);
33 void icq_TCPOnURLReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
, DWORD id
);
34 void icq_TCPOnContactListReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
, DWORD id
);
35 void icq_TCPOnChatReqReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
, DWORD id
);
36 void icq_TCPOnFileReqReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
,
37 const char *filename
, unsigned long filesize
, DWORD id
);
38 void icq_TCPProcessAck(icq_Link
*icqlink
, icq_Packet
*p
);
39 void icq_HandleChatAck(icq_TCPLink
*plink
, icq_Packet
*p
, int port
);
40 void icq_HandleChatHello(icq_TCPLink
*plink
);
41 void icq_HandleFileHello(icq_TCPLink
*plink
);
42 void icq_HandleFileAck(icq_TCPLink
*plink
, icq_Packet
*p
, int port
);
44 void icq_TCPProcessPacket(icq_Packet
*p
, icq_TCPLink
*plink
)
56 const char *filename
= 0;
59 (void)icq_PacketRead32(p
);
60 version
=icq_PacketRead16(p
);
61 command
=icq_PacketRead16(p
);
62 (void)icq_PacketRead16(p
);
64 uin
=icq_PacketRead32(p
);
65 type
=icq_PacketRead16(p
);
66 message
=icq_PacketReadString(p
);
67 (void)icq_PacketRead32(p
);
68 (void)icq_PacketRead32(p
);
69 (void)icq_PacketRead32(p
);
70 (void)icq_PacketRead8(p
);
71 status
=icq_PacketRead16(p
);
72 command_type
=icq_PacketRead16(p
);
74 switch(type
& ~ICQ_TCP_MASS_MASK
)
78 case ICQ_TCP_MSG_CONTACTLIST
:
79 case ICQ_TCP_MSG_READAWAY
:
80 case ICQ_TCP_MSG_READNA
:
81 case ICQ_TCP_MSG_READDND
:
82 case ICQ_TCP_MSG_READOCCUPIED
:
83 case ICQ_TCP_MSG_READFFC
:
84 p
->id
=icq_PacketRead32(p
);
87 case ICQ_TCP_MSG_CHAT
:
88 (void)icq_PacketReadString(p
);
89 (void)icq_PacketRead16(p
);
90 (void)icq_PacketRead16(p
);
91 port
=icq_PacketRead32(p
);
92 p
->id
=icq_PacketRead32(p
);
95 case ICQ_TCP_MSG_FILE
:
96 (void)icq_PacketRead16(p
);
97 (void)icq_PacketRead16(p
);
98 filename
=icq_PacketReadString(p
);
99 filesize
=icq_PacketRead32(p
);
100 port
=icq_PacketRead32(p
);
101 p
->id
=icq_PacketRead32(p
);
105 icq_FmtLog(plink
->icqlink
, ICQ_LOG_WARNING
, "unknown message packet, type %x\n", type
);
108 #ifdef TCP_PROCESS_TRACE
109 printf("packet processed from uin: %lu:\n", uin
);
110 printf(" command: %x\ttype: %x\n", command
, type
);
111 printf(" status: %x\tcommand_type: %x\n", status
, (int)command_type
);
112 printf(" message %s\n", message
);
113 printf(" id: %x\n", (int)p
->id
);
118 case ICQ_TCP_MESSAGE
:
119 switch(type
& ~ICQ_TCP_MASS_MASK
)
121 case ICQ_TCP_MSG_MSG
:
122 icq_TCPOnMessageReceived(plink
->icqlink
, uin
, message
, p
->id
, plink
);
125 case ICQ_TCP_MSG_URL
:
126 icq_TCPOnURLReceived(plink
->icqlink
, uin
, message
, p
->id
);
129 case ICQ_TCP_MSG_CHAT
:
130 icq_TCPOnChatReqReceived(plink
->icqlink
, uin
, message
, p
->id
);
133 case ICQ_TCP_MSG_FILE
:
134 icq_TCPOnFileReqReceived(plink
->icqlink
, uin
, message
, filename
, filesize
, p
->id
);
137 case ICQ_TCP_MSG_CONTACTLIST
:
138 icq_TCPOnContactListReceived(plink
->icqlink
, uin
, message
, p
->id
);
142 icq_FmtLog(plink
->icqlink
, ICQ_LOG_WARNING
, "unknown message type %d!\n", type
);
148 invoke_callback(plink
->icqlink
, icq_RequestNotify
)
149 (plink
->icqlink
, p
->id
, ICQ_NOTIFY_ACK
, status
, (void *)message
);
152 case ICQ_TCP_MSG_CHAT
:
153 icq_HandleChatAck(plink
, p
, port
);
156 case ICQ_TCP_MSG_FILE
:
157 icq_HandleFileAck(plink
, p
, port
);
160 case ICQ_TCP_MSG_MSG
:
161 case ICQ_TCP_MSG_URL
:
162 icq_FmtLog(plink
->icqlink
, ICQ_LOG_MESSAGE
, "received ack %d\n",
166 case ICQ_TCP_MSG_READAWAY
:
167 case ICQ_TCP_MSG_READNA
:
168 case ICQ_TCP_MSG_READDND
:
169 case ICQ_TCP_MSG_READOCCUPIED
:
170 case ICQ_TCP_MSG_READFFC
:
171 icq_FmtLog(plink
->icqlink
, ICQ_LOG_MESSAGE
,
172 "received away msg, seq %d\n", p
->id
);
173 invoke_callback(plink
->icqlink
, icq_RecvAwayMsg
)
174 (plink
->icqlink
, p
->id
, message
);
177 invoke_callback(plink
->icqlink
, icq_RequestNotify
)
178 (plink
->icqlink
, p
->id
, ICQ_NOTIFY_SUCCESS
, 0, NULL
);
182 /* icq_TCPProcessCancel(p); */
186 icq_FmtLog(plink
->icqlink
, ICQ_LOG_WARNING
,
187 "unknown packet command %d!\n", command
);
191 void icq_TCPProcessCancel(icq_Packet
*p
)
197 call notification function
198 remove packet from queue
202 int icq_TCPProcessHello(icq_Packet
*p
, icq_TCPLink
*plink
)
204 /* TCP Hello packet */
205 BYTE code
; /* 0xFF - init packet code */
206 DWORD version
; /* tcp version */
207 DWORD remote_port
; /* remote message listen port */
208 DWORD remote_uin
; /* remote uin */
209 DWORD remote_ip
; /* remote IP as seen by ICQ server */
210 DWORD remote_real_ip
; /* remote IP as seen by client */
211 BYTE flags
; /* tcp flags */
212 DWORD remote_other_port
; /* remote chat or file listen port */
216 code
=icq_PacketRead8(p
);
217 version
=icq_PacketRead32(p
);
219 if (!(p
->length
>=26 && code
==ICQ_TCP_HELLO
))
221 icq_FmtLog(plink
->icqlink
, ICQ_LOG_WARNING
,
222 "malformed hello packet received from %s:%d, closing link\n",
223 inet_ntoa(*((struct in_addr
*)(&(plink
->remote_address
.sin_addr
)))),
224 ntohs(plink
->remote_address
.sin_port
));
226 icq_TCPLinkClose(plink
);
229 remote_port
=icq_PacketRead32(p
);
230 remote_uin
=icq_PacketRead32(p
);
231 remote_ip
=icq_PacketRead32(p
);
232 remote_real_ip
=icq_PacketRead32(p
);
233 flags
=icq_PacketRead8(p
);
234 remote_other_port
=icq_PacketRead32(p
);
236 icq_FmtLog(plink
->icqlink
, ICQ_LOG_MESSAGE
,
237 "hello packet received from %lu { version=%d }\n", remote_uin
, version
);
239 plink
->remote_version
=version
;
240 plink
->remote_uin
=remote_uin
;
242 plink
->mode
&=~TCP_LINK_MODE_HELLOWAIT
;
244 /* file and chat sessions require additional handling */
245 if(plink
->type
==TCP_LINK_CHAT
) icq_HandleChatHello(plink
);
246 if(plink
->type
==TCP_LINK_FILE
) icq_HandleFileHello(plink
);
251 void icq_TCPOnMessageReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
, DWORD id
, icq_TCPLink
*plink
)
253 char data
[ICQ_MAX_MESSAGE_SIZE
];
255 /* use the current system time for time received */
257 struct tm
*ptime
=localtime(&t
);
260 #ifdef TCP_PACKET_TRACE
261 printf("tcp message packet received from %lu { sequence=%x }\n",
265 strncpy(data
,message
,sizeof(data
));
266 data
[sizeof(data
)-1]='\0';
267 icq_RusConv("wk",data
);
269 invoke_callback(icqlink
,icq_RecvMessage
)(icqlink
, uin
, ptime
->tm_hour
,
270 ptime
->tm_min
, ptime
->tm_mday
, ptime
->tm_mon
+1, ptime
->tm_year
+1900, data
);
273 icq_TCPLink *preallink=icq_FindTCPLink(icqlink, uin, TCP_LINK_MESSAGE);
274 if(plink != preallink)
275 invoke_callback(icqlink,icq_SpoofedMessage)(uin, ...)
278 /* send an acknowledgement to the remote client */
279 pack
=icq_TCPCreateMessageAck(plink
,0);
280 icq_PacketAppend32(pack
, id
);
281 icq_PacketSend(pack
, plink
->socket
);
282 #ifdef TCP_PACKET_TRACE
283 printf("tcp message ack sent to uin %lu { sequence=%lx }\n", uin
, id
);
285 icq_PacketDelete(pack
);
288 void icq_TCPOnURLReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
, DWORD id
)
290 /* use the current system time for time received */
292 struct tm
*ptime
=localtime(&t
);
295 icq_TCPLink
*plink
=icq_FindTCPLink(icqlink
, uin
, TCP_LINK_MESSAGE
);
297 #ifdef TCP_PACKET_TRACE
298 printf("tcp url packet received from %lu { sequence=%lx }\n",
300 #endif /*TCP_PACKET_TRACE*/
302 /* the URL is split from the description by 0xFE */
303 pfe
=strchr(message
, '\xFE');
305 icq_RusConv("wk", (char*)message
);
307 invoke_callback(icqlink
,icq_RecvURL
)(icqlink
, uin
, ptime
->tm_hour
,
308 ptime
->tm_min
, ptime
->tm_mday
, ptime
->tm_mon
+1, ptime
->tm_year
+1900,
311 /* send an acknowledgement to the remote client */
312 pack
=icq_TCPCreateURLAck(plink
,0);
313 icq_PacketAppend32(pack
, id
);
314 icq_PacketSend(pack
, plink
->socket
);
315 #ifdef TCP_PACKET_TRACE
316 printf("tcp message ack sent to %lu { sequence=%lx }\n", uin
, id
);
318 icq_PacketDelete(pack
);
321 void icq_TCPOnContactListReceived(icq_Link
*icqlink
, DWORD uin
, const char *message
, DWORD id
)
323 /* use the current system time for time received */
325 struct tm
*ptime
=localtime(&t
);
327 icq_List
*strList
= icq_ListNew();
328 int i
, k
, nr
= icq_SplitFields(strList
, message
);
329 const char **contact_uin
= (const char **)malloc((nr
- 2) /2);
330 const char **contact_nick
= (const char **)malloc((nr
- 2) /2);
331 icq_TCPLink
*plink
=icq_FindTCPLink(icqlink
, uin
, TCP_LINK_MESSAGE
);
333 #ifdef TCP_PACKET_TRACE
334 printf("tcp contactlist packet received from %lu { sequence=%lx }\n", uin
, id
);
335 #endif /* TCP_PACKET_TRACE */
338 for (i
= 1, k
= 0; i
< (nr
- 1); k
++)
340 contact_uin
[k
] = icq_ListAt(strList
, i
);
341 contact_nick
[k
] = icq_ListAt(strList
, i
+ 1);
345 invoke_callback(icqlink
,icq_RecvContactList
)(icqlink
, uin
,
346 ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_mday
, ptime
->tm_mon
+1,
347 ptime
->tm_year
+1900, k
, contact_uin
, contact_nick
);
349 /* send an acknowledement to the remote client */
350 pack
=icq_TCPCreateContactListAck(plink
, 0);
351 icq_PacketAppend32(pack
, id
);
352 icq_PacketSend(pack
, plink
->socket
);
353 #ifdef TCP_PACKET_TRACE
354 printf("tcp message ack sent to %lu { sequence=%lx }\n", uin
, id
);
355 #endif /* TCP_PACKE_TRACE */
356 icq_PacketDelete(pack
);
360 icq_ListDelete(strList
, free
);