| |
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| |
2 /* |
| |
3 $Id: tcp.c 1162 2000-11-28 02:22:42Z warmenhoven $ |
| |
4 $Log$ |
| |
5 Revision 1.1 2000/11/28 02:22:42 warmenhoven |
| |
6 icq. whoop de doo |
| |
7 |
| |
8 Revision 1.36 2000/07/09 22:19:35 bills |
| |
9 added new *Close functions, use *Close functions instead of *Delete |
| |
10 where correct, and misc cleanup |
| |
11 |
| |
12 Revision 1.35 2000/06/15 01:52:16 bills |
| |
13 added Cancel and Refuse functions for chat and file reqs, changed packet |
| |
14 sending code to use new icq_TCPLinkSendSeq function to elimitane duplicate |
| |
15 code, removed *Seq functions, renamed chat req functions |
| |
16 |
| |
17 Revision 1.34 2000/05/04 15:57:20 bills |
| |
18 Reworked file transfer notification, small bugfixes, and cleanups. |
| |
19 |
| |
20 Revision 1.33 2000/04/10 18:11:45 denis |
| |
21 ANSI cleanups. |
| |
22 |
| |
23 Revision 1.32 2000/04/10 16:36:04 denis |
| |
24 Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> |
| |
25 |
| |
26 Revision 1.31 2000/04/06 16:38:04 denis |
| |
27 icq_*Send*Seq() functions with specified sequence number were added. |
| |
28 |
| |
29 Revision 1.30 2000/04/05 14:37:02 denis |
| |
30 Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 |
| |
31 compatibility. |
| |
32 |
| |
33 Revision 1.29 2000/02/15 04:02:41 bills |
| |
34 warning cleanup |
| |
35 |
| |
36 Revision 1.28 2000/02/15 03:58:20 bills |
| |
37 use new icq_ChatRusConv_n function in icq_TCPSendChatData, |
| |
38 new icq_TCPSendChatData_n function |
| |
39 |
| |
40 Revision 1.27 2000/02/07 02:40:23 bills |
| |
41 new code for SOCKS connections, more cyrillic translations |
| |
42 |
| |
43 Revision 1.26 2000/01/20 19:59:15 bills |
| |
44 first implementation of sending file requests |
| |
45 |
| |
46 Revision 1.25 2000/01/16 21:28:24 bills |
| |
47 renamed icq_TCPAcceptFileReq to icq_AcceptFileRequest, moved file request |
| |
48 functions to new file session code |
| |
49 |
| |
50 Revision 1.24 2000/01/16 03:59:10 bills |
| |
51 reworked list code so list_nodes don't need to be inside item structures, |
| |
52 removed strlist code and replaced with generic list calls |
| |
53 |
| |
54 Revision 1.23 1999/12/27 16:10:04 bills |
| |
55 fixed buy in icq_TCPAcceptFileReq, added icq_TCPFileSetSpeed |
| |
56 |
| |
57 Revision 1.22 1999/12/21 00:29:59 bills |
| |
58 moved _process_packet logic into tcplink::icq_TCPLinkProcessReceived, |
| |
59 removed unnecessary icq_TCPSendFile??Packet functions |
| |
60 |
| |
61 Revision 1.21 1999/12/14 03:31:48 bills |
| |
62 fixed double delete bug in _handle_ready_sockets, added code to implement |
| |
63 connect timeout |
| |
64 |
| |
65 Revision 1.20 1999/11/30 09:44:31 bills |
| |
66 added file session logic |
| |
67 |
| |
68 Revision 1.19 1999/09/29 20:07:12 bills |
| |
69 cleanups, moved connect logic from _handle_ready_sockets to |
| |
70 icq_TCPLinkOnConnect, tcp_link->icq_TCPLink |
| |
71 |
| |
72 Revision 1.18 1999/09/29 17:08:48 denis |
| |
73 Cleanups. |
| |
74 |
| |
75 Revision 1.17 1999/07/18 20:19:56 bills |
| |
76 added better log messages |
| |
77 |
| |
78 Revision 1.16 1999/07/16 15:45:56 denis |
| |
79 Cleaned up. |
| |
80 |
| |
81 Revision 1.15 1999/07/16 12:14:13 denis |
| |
82 tcp_packet* functions renamed to icq_Packet* |
| |
83 Cleaned up. |
| |
84 |
| |
85 Revision 1.14 1999/07/12 15:13:34 cproch |
| |
86 - added definition of ICQLINK to hold session-specific global variabled |
| |
87 applications which have more than one connection are now possible |
| |
88 - changed nearly every function defintion to support ICQLINK parameter |
| |
89 |
| |
90 Revision 1.13 1999/07/03 06:33:49 lord |
| |
91 . byte order conversion macros added |
| |
92 . some compilation warnings removed |
| |
93 |
| |
94 Revision 1.12 1999/06/30 13:52:22 bills |
| |
95 implemented non-blocking connects |
| |
96 |
| |
97 Revision 1.11 1999/05/03 21:41:26 bills |
| |
98 initial file xfer support added- untested |
| |
99 |
| |
100 Revision 1.10 1999/04/29 09:35:41 denis |
| |
101 Cleanups, warning removed |
| |
102 |
| |
103 Revision 1.9 1999/04/17 19:30:50 bills |
| |
104 _major_ restructuring. all tcp sockets (including listening sockets) are |
| |
105 kept in global linked list, icq_TCPLinks. accept and listen functions |
| |
106 moved to tcplink.c. changed return values of Send* functions to DWORD. |
| |
107 |
| |
108 Revision 1.8 1999/04/14 14:57:05 denis |
| |
109 Cleanups for "strict" compiling (-ansi -pedantic) |
| |
110 Parameter port added to function icq_TCPCreateListeningSocket() |
| |
111 |
| |
112 */ |
| |
113 |
| |
114 /* |
| |
115 Peer-to-peer ICQ protocol implementation |
| |
116 |
| |
117 Uses version 2 of the ICQ protocol |
| |
118 |
| |
119 Thanks to Douglas F. McLaughlin and many others for |
| |
120 packet details (see tcp02.txt) |
| |
121 |
| |
122 */ |
| |
123 |
| |
124 #include <stdlib.h> |
| |
125 |
| |
126 #ifndef _WIN32 |
| |
127 #include <unistd.h> |
| |
128 #endif |
| |
129 |
| |
130 #include <fcntl.h> |
| |
131 #include <stdarg.h> |
| |
132 #include <errno.h> |
| |
133 |
| |
134 #include <sys/types.h> |
| |
135 |
| |
136 #ifdef _WIN32 |
| |
137 #include <winsock.h> |
| |
138 #else |
| |
139 #include <sys/socket.h> |
| |
140 #endif |
| |
141 |
| |
142 #include <sys/stat.h> |
| |
143 |
| |
144 #ifndef _WIN32 |
| |
145 #include <sys/time.h> |
| |
146 #endif |
| |
147 |
| |
148 #include "icqtypes.h" |
| |
149 #include "icqlib.h" |
| |
150 |
| |
151 #include "tcp.h" |
| |
152 #include "stdpackets.h" |
| |
153 #include "list.h" |
| |
154 #include "tcplink.h" |
| |
155 #include "chatsession.h" |
| |
156 #include "filesession.h" |
| |
157 |
| |
158 /** |
| |
159 Initializes structures necessary for TCP use. Not required by user |
| |
160 programs. |
| |
161 |
| |
162 \return true on error |
| |
163 */ |
| |
164 |
| |
165 int icq_TCPInit(ICQLINK *link) |
| |
166 { |
| |
167 icq_TCPLink *plink; |
| |
168 |
| |
169 /* allocate lists */ |
| |
170 link->icq_TCPLinks=list_new(); |
| |
171 link->icq_ChatSessions=list_new(); |
| |
172 link->icq_FileSessions=list_new(); |
| |
173 |
| |
174 /* only the main listening socket gets created upon initialization - |
| |
175 * the other two are created when necessary */ |
| |
176 plink=icq_TCPLinkNew( link ); |
| |
177 icq_TCPLinkListen(plink); |
| |
178 link->icq_TCPSrvPort=ntohs(plink->socket_address.sin_port); |
| |
179 |
| |
180 /* reset tcp sequence number */ |
| |
181 link->icq_TCPSequence=0xfffffffe; |
| |
182 |
| |
183 return 0; |
| |
184 } |
| |
185 |
| |
186 void icq_TCPDone(ICQLINK *link) |
| |
187 { |
| |
188 /* close and deallocate all tcp links, this will also close any attached |
| |
189 * file or chat sessions */ |
| |
190 list_delete(link->icq_TCPLinks, icq_TCPLinkDelete); |
| |
191 list_delete(link->icq_ChatSessions, icq_ChatSessionDelete); |
| |
192 list_delete(link->icq_FileSessions, icq_FileSessionDelete); |
| |
193 } |
| |
194 |
| |
195 /* helper function for icq_TCPMain */ |
| |
196 int _generate_fds(void *p, va_list data) |
| |
197 { |
| |
198 icq_TCPLink *plink=(icq_TCPLink *)p; |
| |
199 ICQLINK *icqlink = plink->icqlink; |
| |
200 |
| |
201 (void)data; |
| |
202 |
| |
203 if(plink->socket>-1) |
| |
204 { |
| |
205 int socket=plink->socket; |
| |
206 |
| |
207 FD_SET(socket, &icqlink->TCP_readfds); |
| |
208 |
| |
209 /* we only care about writing if socket is trying to connect */ |
| |
210 if(plink->mode & TCP_LINK_MODE_CONNECTING) |
| |
211 { |
| |
212 if(plink->mode & (TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_CONNSTATUS)) |
| |
213 FD_SET(socket, &icqlink->TCP_readfds); |
| |
214 else |
| |
215 FD_SET(socket, &icqlink->TCP_writefds); |
| |
216 } |
| |
217 |
| |
218 if(socket+1>icqlink->TCP_maxfd) |
| |
219 icqlink->TCP_maxfd=socket+1; |
| |
220 } |
| |
221 |
| |
222 return 0; /* traverse the entire list */ |
| |
223 } |
| |
224 |
| |
225 /* helper function for icq_TCPMain */ |
| |
226 int _handle_ready_sockets(void *p, va_list data) |
| |
227 { |
| |
228 icq_TCPLink *plink=(icq_TCPLink *)p; |
| |
229 ICQLINK *icqlink = plink->icqlink; |
| |
230 int socket=plink->socket; |
| |
231 |
| |
232 (void)data; |
| |
233 |
| |
234 /* handle connecting sockets */ |
| |
235 if (plink->mode & TCP_LINK_MODE_CONNECTING) |
| |
236 { |
| |
237 if(socket>-1 && (FD_ISSET(socket, &icqlink->TCP_writefds) || FD_ISSET(socket, &icqlink->TCP_readfds))) |
| |
238 { |
| |
239 icq_TCPLinkOnConnect(plink); |
| |
240 return 0; |
| |
241 } |
| |
242 |
| |
243 if((time(0L) - plink->connect_time) > TCP_LINK_CONNECT_TIMEOUT) |
| |
244 { |
| |
245 icq_TCPLinkClose(plink); |
| |
246 return 0; |
| |
247 } |
| |
248 } |
| |
249 |
| |
250 /* handle ready for read sockets- either a connection is waiting on * |
| |
251 * the listen sockets or data is ready to be read */ |
| |
252 if(socket>-1 && FD_ISSET(socket, &icqlink->TCP_readfds)) |
| |
253 { |
| |
254 if(plink->mode & TCP_LINK_MODE_LISTEN) |
| |
255 (void)icq_TCPLinkAccept(plink); |
| |
256 else { |
| |
257 |
| |
258 int result=icq_TCPLinkOnDataReceived(plink); |
| |
259 |
| |
260 /* close the link if there was a receive error or if * |
| |
261 * the remote end has closed the connection */ |
| |
262 if (result < 1) |
| |
263 icq_TCPLinkClose(plink); |
| |
264 |
| |
265 } |
| |
266 } |
| |
267 |
| |
268 return 0; /* traverse the entire list */ |
| |
269 } |
| |
270 |
| |
271 /* helper function for icq_TCPMain */ |
| |
272 int _process_links(void *p, va_list data) |
| |
273 { |
| |
274 icq_TCPLink *plink=(icq_TCPLink *)p; |
| |
275 |
| |
276 (void)data; |
| |
277 |
| |
278 /* receive any packets watiting on the link */ |
| |
279 icq_TCPLinkProcessReceived(plink); |
| |
280 |
| |
281 /* if this a currently sending file link, send data! */ |
| |
282 if(plink->type==TCP_LINK_FILE) { |
| |
283 icq_FileSession *psession=plink->session; |
| |
284 if(psession && psession->status==FILE_STATUS_SENDING) |
| |
285 icq_FileSessionSendData(psession); |
| |
286 } |
| |
287 |
| |
288 return 0; /* traverse entire list */ |
| |
289 } |
| |
290 |
| |
291 void icq_TCPMain(ICQLINK *link) |
| |
292 { |
| |
293 struct timeval tv; |
| |
294 |
| |
295 tv.tv_sec = 0; |
| |
296 tv.tv_usec = 0; |
| |
297 |
| |
298 link->TCP_maxfd = 0; |
| |
299 FD_ZERO(&link->TCP_readfds); |
| |
300 FD_ZERO(&link->TCP_writefds); |
| |
301 |
| |
302 /* generate the fd sets for all open tcp links */ |
| |
303 (void)list_traverse(link->icq_TCPLinks, _generate_fds); |
| |
304 |
| |
305 /* determine which sockets require maintenance */ |
| |
306 select(link->TCP_maxfd, &link->TCP_readfds, &link->TCP_writefds, 0, &tv); |
| |
307 |
| |
308 /* call icq_TCPLinkOnDataReceived for any sockets with ready data, |
| |
309 * send all packets on send queue if socket has connected, and |
| |
310 * accept() from any listening sockets with pending connections */ |
| |
311 (void)list_traverse(link->icq_TCPLinks, _handle_ready_sockets, 0, 0); |
| |
312 |
| |
313 /* process all packets waiting for each TCPLink */ |
| |
314 (void)list_traverse(link->icq_TCPLinks, _process_links, 0, 0); |
| |
315 } |
| |
316 |
| |
317 icq_TCPLink *icq_TCPCheckLink(ICQLINK *link, DWORD uin, int type) |
| |
318 { |
| |
319 icq_TCPLink *plink=icq_FindTCPLink(link, uin, type); |
| |
320 |
| |
321 if(!plink) |
| |
322 { |
| |
323 plink=icq_TCPLinkNew( link ); |
| |
324 if(type==TCP_LINK_MESSAGE) |
| |
325 icq_TCPLinkConnect(plink, uin, 0); |
| |
326 } |
| |
327 |
| |
328 return plink; |
| |
329 |
| |
330 } |
| |
331 |
| |
332 DWORD icq_TCPSendMessage(ICQLINK *link, DWORD uin, const char *message) |
| |
333 { |
| |
334 icq_TCPLink *plink; |
| |
335 icq_Packet *p; |
| |
336 DWORD sequence; |
| |
337 char data[512] ; |
| |
338 |
| |
339 strncpy(data,message,512) ; |
| |
340 icq_RusConv("kw", data) ; |
| |
341 |
| |
342 plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
343 |
| |
344 /* create and send the message packet */ |
| |
345 p=icq_TCPCreateMessagePacket(plink, (unsigned char *)data); |
| |
346 sequence=icq_TCPLinkSendSeq(plink, p, 0); |
| |
347 |
| |
348 #ifdef TCP_PACKET_TRACE |
| |
349 printf("message packet sent to uin %lu { sequence=%lx }\n", uin, p->id); |
| |
350 #endif |
| |
351 |
| |
352 return sequence; |
| |
353 } |
| |
354 |
| |
355 DWORD icq_TCPSendURL(ICQLINK *link, DWORD uin, const char *message, const char *url) |
| |
356 { |
| |
357 icq_TCPLink *plink; |
| |
358 icq_Packet *p; |
| |
359 DWORD sequence; |
| |
360 char data[512]; |
| |
361 |
| |
362 plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
363 |
| |
364 strncpy(data, message, 512); |
| |
365 data[511] = '\0'; |
| |
366 icq_RusConv("kw", data); |
| |
367 |
| |
368 /* create and send the url packet */ |
| |
369 p=icq_TCPCreateURLPacket(plink, data, url); |
| |
370 sequence=icq_TCPLinkSendSeq(plink, p, 0); |
| |
371 |
| |
372 #ifdef TCP_PACKET_TRACE |
| |
373 printf("url packet queued for uin %lu { sequence=%lx }\n", uin, p->id); |
| |
374 #endif |
| |
375 |
| |
376 return sequence; |
| |
377 } |
| |
378 |
| |
379 DWORD icq_SendChatRequest(ICQLINK *link, DWORD uin, const char *message) |
| |
380 { |
| |
381 icq_TCPLink *plink; |
| |
382 icq_Packet *p; |
| |
383 DWORD sequence; |
| |
384 char data[512]; |
| |
385 |
| |
386 plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
387 |
| |
388 strncpy(data, message, 512); |
| |
389 data[511] = '\0'; |
| |
390 icq_RusConv("kw", data); |
| |
391 |
| |
392 /* create and send the url packet */ |
| |
393 p=icq_TCPCreateChatReqPacket(plink, (unsigned char *)data); |
| |
394 sequence=icq_TCPLinkSendSeq(plink, p, 0); |
| |
395 |
| |
396 #ifdef TCP_PACKET_TRACE |
| |
397 printf("chat req packet sent to uin %lu { sequence=%lx }\n", uin, p->id); |
| |
398 #endif |
| |
399 |
| |
400 return sequence; |
| |
401 } |
| |
402 |
| |
403 unsigned long icq_SendFileRequest(ICQLINK *link, unsigned long uin, |
| |
404 const char *message, char **files) |
| |
405 { |
| |
406 icq_TCPLink *plink; |
| |
407 icq_FileSession *pfile; |
| |
408 icq_Packet *p; |
| |
409 unsigned long sequence; |
| |
410 char filename[64]; |
| |
411 char data[512]; |
| |
412 |
| |
413 plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
414 |
| |
415 /* create the file session, this will be linked to the incoming icq_TCPLink |
| |
416 * in icq_HandleFileAck */ |
| |
417 pfile=icq_FileSessionNew(link); |
| |
418 pfile->remote_uin=uin; |
| |
419 pfile->files=files; |
| |
420 pfile->direction=FILE_STATUS_SENDING; |
| |
421 |
| |
422 /* count the number and size of the files */ |
| |
423 pfile->total_files=0; |
| |
424 while(*files) { |
| |
425 struct stat file_status; |
| |
426 |
| |
427 if(stat(*files, &file_status)==0) { |
| |
428 pfile->total_files++; |
| |
429 pfile->total_bytes+=file_status.st_size; |
| |
430 } |
| |
431 files++; |
| |
432 } |
| |
433 |
| |
434 strncpy(filename, *(pfile->files), 64); |
| |
435 |
| |
436 strncpy(data, message, 512); |
| |
437 data[511] = '\0'; |
| |
438 icq_RusConv("kw", data); |
| |
439 |
| |
440 /* create and send the file req packet */ |
| |
441 p=icq_TCPCreateFileReqPacket(plink, (char *)data, filename, |
| |
442 pfile->total_bytes); |
| |
443 sequence=icq_TCPLinkSendSeq(plink, p, 0); |
| |
444 pfile->id=sequence; |
| |
445 |
| |
446 #ifdef TCP_PACKET_TRACE |
| |
447 printf("file req packet sent to uin %lu { sequence=%lx }\n", uin, p->id); |
| |
448 #endif |
| |
449 |
| |
450 return sequence; |
| |
451 } |
| |
452 |
| |
453 void icq_AcceptChatRequest(ICQLINK *link, DWORD uin, unsigned long sequence) |
| |
454 { |
| |
455 icq_TCPLink *pmessage, *plisten; |
| |
456 icq_ChatSession *pchat; |
| |
457 icq_Packet *p; |
| |
458 |
| |
459 pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
460 |
| |
461 /* create the chat listening socket if necessary */ |
| |
462 if(!(plisten=icq_FindTCPLink(link, 0, TCP_LINK_CHAT))) |
| |
463 { |
| |
464 plisten=icq_TCPLinkNew( link ); |
| |
465 plisten->type=TCP_LINK_CHAT; |
| |
466 icq_TCPLinkListen(plisten); |
| |
467 } |
| |
468 |
| |
469 /* create the chat session, this will be linked to the incoming icq_TCPLink |
| |
470 * in TCPProcessHello */ |
| |
471 pchat=icq_ChatSessionNew(link); |
| |
472 pchat->id=sequence; |
| |
473 pchat->remote_uin=uin; |
| |
474 |
| |
475 /* create and send the ack packet */ |
| |
476 p=icq_TCPCreateChatReqAck(pmessage, |
| |
477 ntohs(plisten->socket_address.sin_port)); |
| |
478 (void)icq_TCPLinkSendSeq(pmessage, p, sequence); |
| |
479 |
| |
480 #ifdef TCP_PACKET_TRACE |
| |
481 printf("chat req ack sent to uin %lu { sequence=%lx }\n", uin, sequence); |
| |
482 #endif |
| |
483 } |
| |
484 |
| |
485 void icq_TCPSendChatData(ICQLINK *link, DWORD uin, const char *data) |
| |
486 { |
| |
487 icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT); |
| |
488 char data1[512]; |
| |
489 int data1_len; |
| |
490 |
| |
491 if(!plink) |
| |
492 return; |
| |
493 |
| |
494 strncpy(data1,data,512) ; |
| |
495 data1[511] = '\0'; |
| |
496 data1_len = strlen(data); |
| |
497 icq_ChatRusConv_n("kw", data1, data1_len); |
| |
498 |
| |
499 send(plink->socket, data1, data1_len, 0); |
| |
500 |
| |
501 } |
| |
502 |
| |
503 void icq_TCPSendChatData_n(ICQLINK *link, DWORD uin, const char *data, int len) |
| |
504 { |
| |
505 icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT); |
| |
506 char *data1; |
| |
507 |
| |
508 if(!plink) |
| |
509 return; |
| |
510 |
| |
511 data1 = (char *)malloc(len); |
| |
512 memcpy(data1, data, len); |
| |
513 icq_ChatRusConv_n("kw", data1, len); |
| |
514 |
| |
515 send(plink->socket, data1, len, 0); |
| |
516 |
| |
517 } |
| |
518 |
| |
519 void icq_TCPCloseChat(ICQLINK *link, unsigned long uin) |
| |
520 { |
| |
521 icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT); |
| |
522 |
| |
523 if(plink) |
| |
524 icq_TCPLinkClose(plink); |
| |
525 |
| |
526 } |
| |
527 |
| |
528 icq_FileSession *icq_AcceptFileRequest(ICQLINK *link, DWORD uin, |
| |
529 unsigned long sequence) |
| |
530 { |
| |
531 icq_TCPLink *pmessage, *plisten; |
| |
532 icq_FileSession *pfile; |
| |
533 icq_Packet *p; |
| |
534 |
| |
535 pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
536 |
| |
537 /* create the file listening socket if necessary */ |
| |
538 if(!(plisten=icq_FindTCPLink(link, 0, TCP_LINK_FILE))) |
| |
539 { |
| |
540 plisten=icq_TCPLinkNew( link ); |
| |
541 plisten->type=TCP_LINK_FILE; |
| |
542 icq_TCPLinkListen(plisten); |
| |
543 } |
| |
544 |
| |
545 /* create the file session, this will be linked to the incoming icq_TCPLink |
| |
546 * in TCPProcessHello */ |
| |
547 pfile=icq_FileSessionNew(link); |
| |
548 pfile->id=sequence; |
| |
549 pfile->remote_uin=uin; |
| |
550 pfile->direction=FILE_STATUS_RECEIVING; |
| |
551 icq_FileSessionSetStatus(pfile, FILE_STATUS_LISTENING); |
| |
552 |
| |
553 /* create and send the ack packet */ |
| |
554 p=icq_TCPCreateFileReqAck(pmessage, |
| |
555 ntohs(plisten->socket_address.sin_port)); |
| |
556 (void)icq_TCPLinkSendSeq(pmessage, p, sequence); |
| |
557 |
| |
558 #ifdef TCP_PACKET_TRACE |
| |
559 printf("file req ack sent to uin %lu { sequence=%lx }\n", uin, sequence); |
| |
560 #endif |
| |
561 |
| |
562 return pfile; |
| |
563 |
| |
564 } |
| |
565 |
| |
566 void icq_RefuseFileRequest(ICQLINK *link, DWORD uin, |
| |
567 unsigned long sequence, const char *reason) |
| |
568 { |
| |
569 icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
570 icq_Packet *p; |
| |
571 |
| |
572 /* create and send the refuse packet */ |
| |
573 p=icq_TCPCreateFileReqRefuse(pmessage, |
| |
574 ntohs(pmessage->socket_address.sin_port), reason); |
| |
575 (void)icq_TCPLinkSendSeq(pmessage, p, sequence); |
| |
576 |
| |
577 #ifdef TCP_PACKET_TRACE |
| |
578 printf("file req refuse sent to uin %lu { sequence=%lx, reason=\"%s\" }\n", |
| |
579 uin, sequence, reason); |
| |
580 #endif |
| |
581 |
| |
582 } |
| |
583 |
| |
584 void icq_CancelFileRequest(ICQLINK *link, DWORD uin, unsigned long sequence) |
| |
585 { |
| |
586 icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
587 icq_FileSession *psession=icq_FindFileSession(link, uin, sequence); |
| |
588 icq_Packet *p; |
| |
589 |
| |
590 if (psession) |
| |
591 icq_FileSessionClose(psession); |
| |
592 |
| |
593 /* create and send the cancel packet */ |
| |
594 p=icq_TCPCreateFileReqCancel(pmessage, |
| |
595 ntohs(pmessage->socket_address.sin_port)); |
| |
596 (void)icq_TCPLinkSendSeq(pmessage, p, sequence); |
| |
597 #ifdef TCP_PACKET_TRACE |
| |
598 printf("file req cancel sent to uin %lu { sequence=%lx }\n", uin, sequence); |
| |
599 #endif |
| |
600 |
| |
601 } |
| |
602 |
| |
603 void icq_RefuseChatRequest(ICQLINK *link, DWORD uin, |
| |
604 unsigned long sequence, const char *reason) |
| |
605 { |
| |
606 icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
607 icq_Packet *p; |
| |
608 |
| |
609 /* create and send the refuse packet */ |
| |
610 p=icq_TCPCreateChatReqRefuse(pmessage, |
| |
611 ntohs(pmessage->socket_address.sin_port), reason); |
| |
612 (void)icq_TCPLinkSendSeq(pmessage, p, sequence); |
| |
613 |
| |
614 #ifdef TCP_PACKET_TRACE |
| |
615 printf("chat req refuse sent to uin %lu { sequence=%lx, reason=\"%s\" }\n", |
| |
616 uin, sequence, reason); |
| |
617 #endif |
| |
618 |
| |
619 } |
| |
620 |
| |
621 void icq_CancelChatRequest(ICQLINK *link, DWORD uin, unsigned long sequence) |
| |
622 { |
| |
623 icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); |
| |
624 icq_FileSession *psession=icq_FindFileSession(link, uin, sequence); |
| |
625 icq_Packet *p; |
| |
626 |
| |
627 if (psession) |
| |
628 icq_FileSessionClose(psession); |
| |
629 |
| |
630 /* create and send the cancel packet */ |
| |
631 p=icq_TCPCreateChatReqCancel(pmessage, |
| |
632 ntohs(pmessage->socket_address.sin_port)); |
| |
633 (void)icq_TCPLinkSendSeq(pmessage, p, sequence); |
| |
634 |
| |
635 #ifdef TCP_PACKET_TRACE |
| |
636 printf("chat req cancel sent to uin %lu { sequence=%lx }\n", uin, sequence); |
| |
637 #endif |
| |
638 |
| |
639 } |