Mercurial > pidgin
comparison plugins/icq/tcp.c @ 1152:201ec77f3a60
[gaim-migrate @ 1162]
icq. whoop de doo
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Tue, 28 Nov 2000 02:22:42 +0000 |
parents | |
children | 0a766047b4fd |
comparison
equal
deleted
inserted
replaced
1151:428372cc1e39 | 1152:201ec77f3a60 |
---|---|
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 } |