2086
|
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
2
|
|
3 /*
|
|
4 * $Id: tcphandle.c 2096 2001-07-31 01:00:39Z warmenhoven $
|
|
5 *
|
|
6 * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and
|
|
7 * Bill Soudan <soudan@kde.org>
|
|
8 *
|
|
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.
|
|
13 *
|
|
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.
|
|
18 *
|
|
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.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 #include <stdlib.h>
|
|
26
|
|
27 #include "icqlib.h"
|
|
28
|
|
29 #include "tcp.h"
|
|
30 #include "stdpackets.h"
|
|
31
|
|
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);
|
|
43
|
|
44 void icq_TCPProcessPacket(icq_Packet *p, icq_TCPLink *plink)
|
|
45 {
|
|
46 DWORD uin;
|
|
47 WORD version;
|
|
48 WORD command;
|
|
49 WORD type;
|
|
50 WORD status;
|
|
51 DWORD command_type;
|
|
52 DWORD filesize = 0;
|
|
53 DWORD port = 0;
|
|
54
|
|
55 const char *message;
|
|
56 const char *filename = 0;
|
|
57
|
|
58 icq_PacketBegin(p);
|
|
59 (void)icq_PacketRead32(p);
|
|
60 version=icq_PacketRead16(p);
|
|
61 command=icq_PacketRead16(p);
|
|
62 (void)icq_PacketRead16(p);
|
|
63
|
|
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);
|
|
73
|
|
74 switch(type & ~ICQ_TCP_MASS_MASK)
|
|
75 {
|
|
76 case ICQ_TCP_MSG_MSG:
|
|
77 case ICQ_TCP_MSG_URL:
|
|
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);
|
|
85 break;
|
|
86
|
|
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);
|
|
93 break;
|
|
94
|
|
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);
|
|
102 break;
|
|
103
|
|
104 default:
|
|
105 icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message packet, type %x\n", type);
|
|
106 }
|
|
107
|
|
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);
|
|
114 #endif
|
|
115
|
|
116 switch(command)
|
|
117 {
|
|
118 case ICQ_TCP_MESSAGE:
|
|
119 switch(type & ~ICQ_TCP_MASS_MASK)
|
|
120 {
|
|
121 case ICQ_TCP_MSG_MSG:
|
|
122 icq_TCPOnMessageReceived(plink->icqlink, uin, message, p->id, plink);
|
|
123 break;
|
|
124
|
|
125 case ICQ_TCP_MSG_URL:
|
|
126 icq_TCPOnURLReceived(plink->icqlink, uin, message, p->id);
|
|
127 break;
|
|
128
|
|
129 case ICQ_TCP_MSG_CHAT:
|
|
130 icq_TCPOnChatReqReceived(plink->icqlink, uin, message, p->id);
|
|
131 break;
|
|
132
|
|
133 case ICQ_TCP_MSG_FILE:
|
|
134 icq_TCPOnFileReqReceived(plink->icqlink, uin, message, filename, filesize, p->id);
|
|
135 break;
|
|
136
|
|
137 case ICQ_TCP_MSG_CONTACTLIST:
|
|
138 icq_TCPOnContactListReceived(plink->icqlink, uin, message, p->id);
|
|
139 break;
|
|
140
|
|
141 default:
|
|
142 icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message type %d!\n", type);
|
|
143 break;
|
|
144 }
|
|
145 break;
|
|
146
|
|
147 case ICQ_TCP_ACK:
|
|
148 invoke_callback(plink->icqlink, icq_RequestNotify)
|
|
149 (plink->icqlink, p->id, ICQ_NOTIFY_ACK, status, (void *)message);
|
|
150 switch(type)
|
|
151 {
|
|
152 case ICQ_TCP_MSG_CHAT:
|
|
153 icq_HandleChatAck(plink, p, port);
|
|
154 break;
|
|
155
|
|
156 case ICQ_TCP_MSG_FILE:
|
|
157 icq_HandleFileAck(plink, p, port);
|
|
158 break;
|
|
159
|
|
160 case ICQ_TCP_MSG_MSG:
|
|
161 case ICQ_TCP_MSG_URL:
|
|
162 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "received ack %d\n",
|
|
163 p->id);
|
|
164 break;
|
|
165
|
|
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);
|
|
175 break;
|
|
176 }
|
|
177 invoke_callback(plink->icqlink, icq_RequestNotify)
|
|
178 (plink->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, NULL);
|
|
179 break;
|
|
180
|
|
181 case ICQ_TCP_CANCEL:
|
|
182 /* icq_TCPProcessCancel(p); */
|
|
183 break;
|
|
184
|
|
185 default:
|
|
186 icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING,
|
|
187 "unknown packet command %d!\n", command);
|
|
188 }
|
|
189 }
|
|
190
|
|
191 void icq_TCPProcessCancel(icq_Packet *p)
|
|
192 {
|
|
193 (void)p;
|
|
194
|
|
195 /*
|
|
196 find packet in queue
|
|
197 call notification function
|
|
198 remove packet from queue
|
|
199 */
|
|
200 }
|
|
201
|
|
202 int icq_TCPProcessHello(icq_Packet *p, icq_TCPLink *plink)
|
|
203 {
|
|
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 */
|
|
213
|
|
214 icq_PacketBegin(p);
|
|
215
|
|
216 code=icq_PacketRead8(p);
|
|
217 version=icq_PacketRead32(p);
|
|
218
|
|
219 if (!(p->length>=26 && code==ICQ_TCP_HELLO))
|
|
220 {
|
|
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));
|
|
225
|
|
226 icq_TCPLinkClose(plink);
|
|
227 return 0;
|
|
228 }
|
|
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);
|
|
235
|
|
236 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE,
|
|
237 "hello packet received from %lu { version=%d }\n", remote_uin, version);
|
|
238
|
|
239 plink->remote_version=version;
|
|
240 plink->remote_uin=remote_uin;
|
|
241 plink->flags=flags;
|
|
242 plink->mode&=~TCP_LINK_MODE_HELLOWAIT;
|
|
243
|
|
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);
|
|
247
|
|
248 return 1;
|
|
249 }
|
|
250
|
|
251 void icq_TCPOnMessageReceived(icq_Link *icqlink, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink)
|
|
252 {
|
|
253 char data[ICQ_MAX_MESSAGE_SIZE];
|
|
254
|
|
255 /* use the current system time for time received */
|
|
256 time_t t=time(0);
|
|
257 struct tm *ptime=localtime(&t);
|
|
258 icq_Packet *pack;
|
|
259
|
|
260 #ifdef TCP_PACKET_TRACE
|
|
261 printf("tcp message packet received from %lu { sequence=%x }\n",
|
|
262 uin, (int)id);
|
|
263 #endif
|
|
264
|
|
265 strncpy(data,message,sizeof(data));
|
|
266 data[sizeof(data)-1]='\0';
|
|
267 icq_RusConv("wk",data);
|
|
268
|
|
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);
|
|
271
|
|
272 /*
|
|
273 icq_TCPLink *preallink=icq_FindTCPLink(icqlink, uin, TCP_LINK_MESSAGE);
|
|
274 if(plink != preallink)
|
|
275 invoke_callback(icqlink,icq_SpoofedMessage)(uin, ...)
|
|
276 */
|
|
277
|
|
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);
|
|
284 #endif
|
|
285 icq_PacketDelete(pack);
|
|
286 }
|
|
287
|
|
288 void icq_TCPOnURLReceived(icq_Link *icqlink, DWORD uin, const char *message, DWORD id)
|
|
289 {
|
|
290 /* use the current system time for time received */
|
|
291 time_t t=time(0);
|
|
292 struct tm *ptime=localtime(&t);
|
|
293 icq_Packet *pack;
|
|
294 char *pfe;
|
|
295 icq_TCPLink *plink=icq_FindTCPLink(icqlink, uin, TCP_LINK_MESSAGE);
|
|
296
|
|
297 #ifdef TCP_PACKET_TRACE
|
|
298 printf("tcp url packet received from %lu { sequence=%lx }\n",
|
|
299 uin, id);
|
|
300 #endif /*TCP_PACKET_TRACE*/
|
|
301
|
|
302 /* the URL is split from the description by 0xFE */
|
|
303 pfe=strchr(message, '\xFE');
|
|
304 *pfe=0;
|
|
305 icq_RusConv("wk", (char*)message);
|
|
306
|
|
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,
|
|
309 pfe+1, message);
|
|
310
|
|
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);
|
|
317 #endif
|
|
318 icq_PacketDelete(pack);
|
|
319 }
|
|
320
|
|
321 void icq_TCPOnContactListReceived(icq_Link *icqlink, DWORD uin, const char *message, DWORD id)
|
|
322 {
|
|
323 /* use the current system time for time received */
|
|
324 time_t t=time(0);
|
|
325 struct tm *ptime=localtime(&t);
|
|
326 icq_Packet *pack;
|
|
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);
|
|
332
|
|
333 #ifdef TCP_PACKET_TRACE
|
|
334 printf("tcp contactlist packet received from %lu { sequence=%lx }\n", uin, id);
|
|
335 #endif /* TCP_PACKET_TRACE */
|
|
336
|
|
337 /* split message */
|
|
338 for (i = 1, k = 0; i < (nr - 1); k++)
|
|
339 {
|
|
340 contact_uin[k] = icq_ListAt(strList, i);
|
|
341 contact_nick[k] = icq_ListAt(strList, i + 1);
|
|
342 i += 2;
|
|
343 }
|
|
344
|
|
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);
|
|
348
|
|
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);
|
|
357
|
|
358 free(contact_nick);
|
|
359 free(contact_uin);
|
|
360 icq_ListDelete(strList, free);
|
|
361 }
|