Mercurial > pidgin.yaz
annotate plugins/icq/tcplink.c @ 1474:4e891576c226
[gaim-migrate @ 1484]
bah
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Tue, 06 Feb 2001 13:49:32 +0000 |
parents | 4c510ca3563f |
children | 0ef6603d986e |
rev | line source |
---|---|
1152 | 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 /* | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
3 $Id: tcplink.c 1442 2001-01-28 01:52:27Z warmenhoven $ |
1152 | 4 $Log$ |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
5 Revision 1.3 2001/01/28 01:52:27 warmenhoven |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
6 icqlib 1.1.5 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
7 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
8 Revision 1.43 2001/01/27 22:48:01 bills |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
9 fix bugs related to TCP and new socket manager: implemented accepting TCP |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
10 sockets, fixed crashes when sending TCP messages. |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
11 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
12 Revision 1.42 2001/01/17 01:29:17 bills |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
13 Rework chat and file session interfaces; implement socket notifications. |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
14 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
15 Revision 1.41 2001/01/15 06:19:12 denis |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
16 Applied patch from Ilya Melamed <ilya@ort.org.il> which fixes random |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
17 icq_TCPLinkAccept() fails. |
1309
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
18 |
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
19 Revision 1.40 2000/12/19 06:00:07 bills |
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
20 moved members from ICQLINK to ICQLINK_private struct |
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
21 |
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
22 Revision 1.39 2000/12/03 21:57:15 bills |
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
23 fixed bug #105068 |
1152 | 24 |
25 Revision 1.38 2000/07/09 22:19:35 bills | |
26 added new *Close functions, use *Close functions instead of *Delete | |
27 where correct, and misc cleanup | |
28 | |
29 Revision 1.37 2000/06/15 01:53:17 bills | |
30 added icq_TCPLinkSendSeq function | |
31 | |
32 Revision 1.36 2000/05/04 15:57:20 bills | |
33 Reworked file transfer notification, small bugfixes, and cleanups. | |
34 | |
35 Revision 1.35 2000/05/03 18:29:15 denis | |
36 Callbacks have been moved to the ICQLINK structure. | |
37 | |
38 Revision 1.34 2000/04/10 18:11:45 denis | |
39 ANSI cleanups. | |
40 | |
41 Revision 1.33 2000/04/10 16:36:04 denis | |
42 Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> | |
43 | |
44 Revision 1.32 2000/04/05 14:37:02 denis | |
45 Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 | |
46 compatibility. | |
47 | |
48 Revision 1.31 2000/02/15 04:00:16 bills | |
49 new icq_ChatRusConv_n function | |
50 | |
51 Revision 1.30 2000/02/07 02:46:29 bills | |
52 implemented non-blocking TCP connects over SOCKS, cyrillic translation for chat | |
53 | |
54 Revision 1.29 2000/01/20 19:59:35 bills | |
55 fixed bug in icq_TCPLinkConnect that caused file/chat connection attempts | |
56 to go to the wrong port | |
57 | |
58 Revision 1.28 2000/01/16 03:59:10 bills | |
59 reworked list code so list_nodes don't need to be inside item structures, | |
60 removed strlist code and replaced with generic list calls | |
61 | |
62 Revision 1.27 1999/12/27 16:13:29 bills | |
63 fixed bug in icq_TCPOnDataReceived, removed flags variable ;) | |
64 | |
65 Revision 1.26 1999/12/27 10:56:10 denis | |
66 Unused "flags" variable commented out. | |
67 | |
68 Revision 1.25 1999/12/21 00:30:53 bills | |
69 added icq_TCPLinkProcessReceived to support processing receive queue | |
70 before delete (packets used to get dropped in this instance, oops), | |
71 reworked icq_TCPLinkOnDataReceived to handle quick, large streams of data, | |
72 changed icq_TCPLinkOnConnect and *Accept to make all sockets non-blocking. | |
73 | |
74 Revision 1.24 1999/12/14 03:33:34 bills | |
75 icq_TCPLinkConnect now uses real_ip when our IP is same as remote IP to make | |
76 connection, added code to implement connect timeout | |
77 | |
78 Revision 1.23 1999/11/30 09:57:44 bills | |
79 buffer overflow check added, tcplinks will now close if buffer overflows. | |
80 increased icq_TCPLinkBufferSize to 4096 to support file transfer packets | |
81 | |
82 Revision 1.22 1999/11/29 17:15:51 denis | |
83 Absence of socklen_t type fixed. | |
84 | |
85 Revision 1.21 1999/10/01 00:49:21 lord | |
86 some compilation problems are fixed. | |
87 | |
88 Revision 1.20 1999/09/29 20:26:41 bills | |
89 ack forgot the args :) | |
90 | |
91 Revision 1.19 1999/09/29 20:21:45 bills | |
92 renamed denis' new function | |
93 | |
94 Revision 1.18 1999/09/29 20:11:29 bills | |
95 renamed tcp_link* to icq_TCPLink*. many cleanups, added icq_TCPLinkOnConnect | |
96 | |
97 Revision 1.17 1999/09/29 17:10:05 denis | |
98 TCP code SOCKS-ification. Not finished. | |
99 | |
100 Revision 1.16 1999/07/18 20:21:34 bills | |
101 fixed fail notification bug introduced during ICQLINK changes, changed to | |
102 use new byte-order functions & contact list functions, added better log | |
103 messages | |
104 | |
105 Revision 1.15 1999/07/16 15:45:57 denis | |
106 Cleaned up. | |
107 | |
108 Revision 1.14 1999/07/16 12:02:58 denis | |
109 tcp_packet* functions renamed to icq_Packet* | |
110 Cleaned up. | |
111 | |
112 Revision 1.13 1999/07/12 15:13:36 cproch | |
113 - added definition of ICQLINK to hold session-specific global variabled | |
114 applications which have more than one connection are now possible | |
115 - changed nearly every function defintion to support ICQLINK parameter | |
116 | |
117 Revision 1.12 1999/07/03 06:33:51 lord | |
118 . byte order conversion macros added | |
119 . some compilation warnings removed | |
120 | |
121 Revision 1.11 1999/06/30 13:52:23 bills | |
122 implemented non-blocking connects | |
123 | |
124 Revision 1.10 1999/05/03 21:39:41 bills | |
125 removed exit calls | |
126 | |
127 Revision 1.9 1999/04/29 09:35:54 denis | |
128 Cleanups, warning removed | |
129 | |
130 Revision 1.8 1999/04/17 19:34:49 bills | |
131 fixed bug in icq_TCPLinkOnDataReceived, multiple packets that come in on | |
132 one recv call are now handled correctly. added icq_TCPLinkAccept and | |
133 icq_TCPLinkListen. started using mode and type structure entries. added | |
134 icq_TCPLinks list and icq_FindTCPLink function. changed received_queue and | |
135 send_queue to lists. | |
136 | |
137 Revision 1.7 1999/04/14 15:02:45 denis | |
138 Cleanups for "strict" compiling (-ansi -pedantic) | |
139 | |
140 Revision 1.6 1999/04/05 18:47:17 bills | |
141 initial chat support implemented | |
142 | |
143 Revision 1.5 1999/03/31 01:50:54 bills | |
144 wrapped up many tcp details- tcp code now handles incoming and outgoing | |
145 tcp messages and urls! | |
146 | |
147 Revision 1.4 1999/03/28 03:27:49 bills | |
148 fixed icq_TCPLinkConnect so it really connects to remote ip instead of | |
149 always my local test computer O:) | |
150 | |
151 Revision 1.3 1999/03/26 20:02:41 bills | |
152 fixed C++ comments, cleaned up | |
153 | |
154 Revision 1.2 1999/03/25 22:21:59 bills | |
155 added necessary includes | |
156 | |
157 Revision 1.1 1999/03/25 21:09:07 bills | |
158 tcp link functions | |
159 */ | |
160 | |
161 #include <stdlib.h> | |
162 | |
163 #ifndef _WIN32 | |
164 #include <unistd.h> | |
165 #endif | |
166 | |
167 #include <fcntl.h> | |
168 #include <stdarg.h> | |
169 #include <errno.h> | |
170 #include <sys/types.h> | |
171 | |
172 #ifdef _WIN32 | |
173 #include <winsock.h> | |
174 #define EINPROGRESS WSAEINPROGRESS | |
175 #define ENETUNREACH WSAENETUNREACH | |
176 #define ECONNREFUSED WSAECONNREFUSED | |
177 #define ETIMEDOUT WSAETIMEDOUT | |
178 #define EOPNOTSUPP WSAEOPNOTSUPP | |
179 #define EAFNOSUPPORT WSAEAFNOSUPPORT | |
180 #define EWOULDBLOCK WSAEWOULDBLOCK | |
181 #else | |
182 #include <sys/socket.h> | |
183 #include <netdb.h> | |
184 #endif | |
185 | |
186 #include "icqtypes.h" | |
187 #include "icq.h" | |
188 #include "icqlib.h" | |
189 #include "tcplink.h" | |
190 #include "stdpackets.h" | |
191 #include "util.h" | |
192 #include "tcp.h" | |
193 #include "errno.h" | |
194 #include "chatsession.h" | |
195 #include "filesession.h" | |
196 | |
197 icq_TCPLink *icq_TCPLinkNew(ICQLINK *link) | |
198 { | |
199 icq_TCPLink *p=(icq_TCPLink *)malloc(sizeof(icq_TCPLink)); | |
200 | |
201 p->socket=-1; | |
202 p->icqlink=link; | |
203 p->mode=0; | |
204 p->session=0L; | |
205 p->type=TCP_LINK_MESSAGE; | |
206 p->buffer_count=0; | |
207 p->send_queue=list_new(); | |
208 p->received_queue=list_new(); | |
209 p->id=0; | |
210 p->remote_uin=0; | |
211 p->remote_version=0; | |
212 p->flags=0; | |
213 p->proxy_status = 0; | |
214 | |
215 if(p) | |
1309
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
216 list_enqueue(link->d->icq_TCPLinks, p); |
1152 | 217 |
218 return p; | |
219 } | |
220 | |
221 int _icq_TCPLinkDelete(void *pv, va_list data) | |
222 { | |
223 icq_Packet *p=(icq_Packet *)pv; | |
224 ICQLINK *icqlink=va_arg(data, ICQLINK *); | |
225 | |
226 /* notify the app the packet didn't make it */ | |
227 if(p->id) | |
228 (*icqlink->icq_RequestNotify)(icqlink, p->id, ICQ_NOTIFY_FAILED, 0, 0); | |
229 | |
230 return 0; | |
231 } | |
232 | |
233 void icq_TCPLinkDelete(void *pv) | |
234 { | |
235 icq_TCPLink *p=(icq_TCPLink *)pv; | |
236 | |
237 /* process anything left in the received queue */ | |
238 icq_TCPLinkProcessReceived(p); | |
239 | |
240 /* make sure we notify app that packets in send queue didn't make it */ | |
241 (void)list_traverse(p->send_queue, _icq_TCPLinkDelete, p->icqlink); | |
242 | |
243 /* destruct all packets still waiting on queues */ | |
244 list_delete(p->send_queue, icq_PacketDelete); | |
245 list_delete(p->received_queue, icq_PacketDelete); | |
246 | |
247 /* if this is a chat or file link, delete the associated session as | |
248 * well, but make sure we unassociate ourself first so the session | |
249 * doesn't try to close us */ | |
250 if(p->session) | |
251 { | |
252 if(p->type==TCP_LINK_CHAT) | |
253 { | |
254 icq_ChatSession *psession=p->session; | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
255 psession->tcplink=NULL; |
1152 | 256 icq_ChatSessionClose(psession); |
257 } | |
258 | |
259 if(p->type==TCP_LINK_FILE) { | |
260 icq_FileSession *psession=p->session; | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
261 psession->tcplink=NULL; |
1152 | 262 icq_FileSessionClose(psession); |
263 } | |
264 } | |
265 | |
266 /* close the socket after we notify app so app can read errno if necessary */ | |
267 if (p->socket > -1) | |
268 { | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
269 icq_SocketDelete(p->socket); |
1152 | 270 } |
271 | |
272 free(p); | |
273 } | |
274 | |
275 void icq_TCPLinkClose(icq_TCPLink *plink) | |
276 { | |
1309
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
277 list_remove(plink->icqlink->d->icq_TCPLinks, plink); |
1152 | 278 icq_TCPLinkDelete(plink); |
279 } | |
280 | |
281 int icq_TCPLinkProxyConnect(icq_TCPLink *plink, DWORD uin, int port) | |
282 { | |
283 struct sockaddr_in prsin; | |
284 struct hostent *host_struct; | |
285 int conct; | |
286 | |
287 (void)uin; (void)port; | |
288 | |
289 prsin.sin_addr.s_addr = htonl(plink->icqlink->icq_ProxyIP); | |
290 if(prsin.sin_addr.s_addr == (unsigned long)-1) | |
291 { | |
292 prsin.sin_addr.s_addr = inet_addr(plink->icqlink->icq_ProxyHost); | |
293 if(prsin.sin_addr.s_addr == (unsigned long)-1) /* name isn't n.n.n.n so must be DNS */ | |
294 { | |
295 host_struct = gethostbyname(plink->icqlink->icq_ProxyHost); | |
296 if(host_struct == 0L) | |
297 { | |
298 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Can't find hostname: %s\n", | |
299 plink->icqlink->icq_ProxyHost); | |
300 return -1; | |
301 } | |
302 prsin.sin_addr = *((struct in_addr *)host_struct->h_addr); | |
303 } | |
304 } | |
305 prsin.sin_family = AF_INET; /* we're using the inet not appletalk*/ | |
306 prsin.sin_port = htons(plink->icqlink->icq_ProxyPort); /* port */ | |
307 /* flags = fcntl(plink->socket, F_GETFL, 0); */ | |
308 /* fcntl(plink->socket, F_SETFL, flags & (~O_NONBLOCK)); */ | |
309 plink->mode |= TCP_LINK_SOCKS_CONNECTING; | |
310 conct = connect(plink->socket, (struct sockaddr *) &prsin, sizeof(prsin)); | |
311 if(conct == -1) /* did we connect ?*/ | |
312 { | |
313 if(errno != EINPROGRESS) | |
314 { | |
315 conct = errno; | |
316 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n"); | |
317 return conct; | |
318 } | |
319 return 1; | |
320 } | |
321 return 0; | |
322 } | |
323 | |
324 int icq_TCPLinkProxyRequestAuthorization(icq_TCPLink *plink) | |
325 { | |
326 char buf[1024]; | |
327 | |
328 plink->mode = (plink->mode & (~TCP_LINK_SOCKS_CONNECTING)); | |
329 buf[0] = 5; /* protocol version */ | |
330 buf[1] = 1; /* number of methods */ | |
331 if(!strlen(plink->icqlink->icq_ProxyName) || !strlen(plink->icqlink->icq_ProxyPass) || | |
332 !plink->icqlink->icq_ProxyAuth) | |
333 { | |
334 buf[2] = 0; /* no authorization required */ | |
335 plink->mode |= TCP_LINK_SOCKS_NOAUTHSTATUS; | |
336 } | |
337 else | |
338 { | |
339 buf[2] = 2; /* method username/password */ | |
340 plink->mode |= TCP_LINK_SOCKS_AUTHORIZATION; | |
341 } | |
342 #ifdef _WIN32 | |
343 if(send(plink->socket, buf, 3, 0) != 3) | |
344 return errno; | |
345 #else | |
346 if(write(plink->socket, buf, 3) != 3) | |
347 return errno; | |
348 #endif | |
349 return 0; | |
350 } | |
351 | |
352 int icq_TCPLinkProxyAuthorization(icq_TCPLink *plink) | |
353 { | |
354 int res; | |
355 char buf[1024]; | |
356 | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
357 plink->mode &= ~TCP_LINK_SOCKS_AUTHORIZATION; |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
358 plink->mode |= TCP_LINK_SOCKS_AUTHSTATUS; |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
359 |
1152 | 360 #ifdef _WIN32 |
361 res = recv(plink->socket, buf, 2, 0); | |
362 #else | |
363 res = read(plink->socket, buf, 2); | |
364 #endif | |
365 if(res != 2 || buf[0] != 5 || buf[1] != 2) /* username/password authentication*/ | |
366 { | |
367 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
368 icq_SocketDelete(plink->socket); |
1152 | 369 return -1; |
370 } | |
371 buf[0] = 1; /* version of subnegotiation */ | |
372 buf[1] = strlen(plink->icqlink->icq_ProxyName); | |
373 memcpy(&buf[2], plink->icqlink->icq_ProxyName, buf[1]); | |
374 buf[2+buf[1]] = strlen(plink->icqlink->icq_ProxyPass); | |
375 memcpy(&buf[3+buf[1]], plink->icqlink->icq_ProxyPass, buf[2+buf[1]]); | |
376 #ifdef _WIN32 | |
377 if(send(plink->socket, buf, buf[1]+buf[2+buf[1]]+3, 0) != buf[1] + buf[2+buf[1]]+3) | |
378 return errno; | |
379 #else | |
380 if(write(plink->socket, buf, buf[1]+buf[2+buf[1]]+3) != buf[1] + buf[2+buf[1]]+3) | |
381 return errno; | |
382 #endif | |
383 return 0; | |
384 } | |
385 | |
386 int icq_TCPLinkProxyAuthStatus(icq_TCPLink *plink) | |
387 { | |
388 int res; | |
389 char buf[20]; | |
390 | |
391 plink->mode = (plink->mode & (~TCP_LINK_SOCKS_AUTHSTATUS)) | TCP_LINK_SOCKS_CROSSCONNECT; | |
392 #ifdef _WIN32 | |
393 res = recv(plink->socket, buf, 2, 0); | |
394 #else | |
395 res = read(plink->socket, buf, 2); | |
396 #endif | |
397 if(res != 2 || buf[0] != 1 || buf[1] != 0) | |
398 { | |
399 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authorization failure\n"); | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
400 icq_SocketDelete(plink->socket); |
1152 | 401 return -1; |
402 } | |
403 return 0; | |
404 } | |
405 | |
406 int icq_TCPLinkProxyNoAuthStatus(icq_TCPLink *plink) | |
407 { | |
408 int res; | |
409 char buf[20]; | |
410 | |
411 plink->mode = (plink->mode & (~TCP_LINK_SOCKS_NOAUTHSTATUS)) | TCP_LINK_SOCKS_CROSSCONNECT; | |
412 #ifdef _WIN32 | |
413 res = recv(plink->socket, buf, 2, 0); | |
414 #else | |
415 res = read(plink->socket, buf, 2); | |
416 #endif | |
417 if(res != 2 || buf[0] != 5 || buf[1] != 0) /* no authentication required */ | |
418 { | |
419 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
420 icq_SocketDelete(plink->socket); |
1152 | 421 return -1; |
422 } | |
423 return 0; | |
424 } | |
425 | |
426 int icq_TCPLinkProxyCrossConnect(icq_TCPLink *plink) | |
427 { | |
428 char buf[20]; | |
429 | |
430 plink->mode = (plink->mode & ~(TCP_LINK_SOCKS_CROSSCONNECT)) | TCP_LINK_SOCKS_CONNSTATUS; | |
431 buf[0] = 5; /* protocol version */ | |
432 buf[1] = 1; /* command connect */ | |
433 buf[2] = 0; /* reserved */ | |
434 buf[3] = 1; /* address type IP v4 */ | |
435 memcpy(&buf[4], &plink->remote_address.sin_addr.s_addr, 4); | |
436 memcpy(&buf[8], &plink->remote_address.sin_port, 2); | |
437 #ifdef _WIN32 | |
438 if(send(plink->socket, buf, 10, 0) != 10) | |
439 return errno; | |
440 #else | |
441 if(write(plink->socket, buf, 10) != 10) | |
442 return errno; | |
443 #endif | |
444 return 0; | |
445 } | |
446 | |
447 int icq_TCPLinkProxyConnectStatus(icq_TCPLink *plink) | |
448 { | |
449 int res; | |
450 char buf[1024]; | |
451 | |
452 plink->mode = (plink->mode & (~TCP_LINK_SOCKS_CONNSTATUS)); | |
453 #ifdef _WIN32 | |
454 res = recv(plink->socket, buf, 10, 0); | |
455 #else | |
456 res = read(plink->socket, buf, 10); | |
457 #endif | |
458 if(res != 10 || buf[0] != 5 || buf[1] != 0) | |
459 { | |
460 switch(buf[1]) | |
461 { | |
462 case 1: | |
463 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] General SOCKS server failure\n"); | |
464 res = EFAULT; | |
465 break; | |
466 case 2: | |
467 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection not allowed by ruleset\n"); | |
468 res = EACCES; | |
469 break; | |
470 case 3: | |
471 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Network unreachable\n"); | |
472 res = ENETUNREACH; | |
473 break; | |
474 case 4: | |
475 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Host unreachable\n"); | |
476 res = ENETUNREACH; | |
477 break; | |
478 case 5: | |
479 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n"); | |
480 res = ECONNREFUSED; | |
481 break; | |
482 case 6: | |
483 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] TTL expired\n"); | |
484 res = ETIMEDOUT; | |
485 break; | |
486 case 7: | |
487 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Command not supported\n"); | |
488 res = EOPNOTSUPP; | |
489 break; | |
490 case 8: | |
491 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Address type not supported\n"); | |
492 res = EAFNOSUPPORT; | |
493 break; | |
494 default: | |
495 icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Unknown SOCKS server failure\n"); | |
496 res = EFAULT; | |
497 break; | |
498 } | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
499 icq_SocketDelete(plink->socket); |
1152 | 500 return res; |
501 } | |
502 return 0; | |
503 } | |
504 | |
505 int icq_TCPLinkConnect(icq_TCPLink *plink, DWORD uin, int port) | |
506 { | |
507 icq_ContactItem *pcontact=icq_ContactFind(plink->icqlink, uin); | |
508 icq_Packet *p; | |
509 int result; | |
510 | |
511 #ifndef _WIN32 | |
512 int flags; | |
513 #else | |
514 u_long iosflag; | |
515 #endif | |
516 | |
517 /* these return values never and nowhere checked */ | |
518 /* denis. */ | |
519 if(!pcontact) | |
520 return -2; | |
521 | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
522 if((plink->socket=icq_SocketNew(AF_INET, SOCK_STREAM, 0)) < 0) |
1152 | 523 return -3; |
524 | |
525 /* bzero(&(plink->remote_address), sizeof(plink->remote_address)); Win32 incompatible... */ | |
526 memset(&(plink->remote_address), 0, sizeof(plink->remote_address)); | |
527 plink->remote_address.sin_family = AF_INET; | |
528 | |
529 /* if our IP is the same as the remote user's ip, connect to real_ip | |
530 instead since we're both probably behind a firewall */ | |
531 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, | |
532 "local IP is %08X:%d, remote real IP is %08X:%d, remote IP is %08X:%d, port is %d\n", | |
533 plink->icqlink->icq_OurIP, | |
534 plink->icqlink->icq_OurPort, | |
535 pcontact->remote_real_ip, | |
536 pcontact->remote_port, | |
537 pcontact->remote_ip, | |
538 pcontact->remote_port, | |
539 port | |
540 ); | |
541 if (plink->icqlink->icq_OurIP == pcontact->remote_ip) | |
542 plink->remote_address.sin_addr.s_addr = htonl(pcontact->remote_real_ip); | |
543 else | |
544 plink->remote_address.sin_addr.s_addr = htonl(pcontact->remote_ip); | |
545 | |
546 if(plink->type==TCP_LINK_MESSAGE) | |
547 { | |
548 plink->remote_address.sin_port = htons(pcontact->remote_port); | |
549 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, | |
550 "initiating message connect to %d (%s:%d)\n", uin, | |
551 inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), | |
552 pcontact->remote_port); | |
553 } | |
554 else | |
555 { | |
556 plink->remote_address.sin_port = htons(port); | |
557 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, | |
558 "initiating file/chat connect to %d (%s:%d)\n", uin, | |
559 inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), | |
560 port); | |
561 } | |
562 | |
563 /* set the socket to non-blocking */ | |
564 #ifdef _WIN32 | |
565 iosflag = TRUE; | |
566 ioctlsocket(plink->socket, FIONBIO, &iosflag); | |
567 #else | |
568 flags=fcntl(plink->socket, F_GETFL, 0); | |
569 fcntl(plink->socket, F_SETFL, flags | O_NONBLOCK); | |
570 #endif | |
571 | |
572 if(!plink->icqlink->icq_UseProxy) | |
573 result=connect(plink->socket, (struct sockaddr *)&(plink->remote_address), | |
574 sizeof(plink->remote_address)); | |
575 else /* SOCKS proxy support */ | |
576 result=icq_TCPLinkProxyConnect(plink, uin, port); | |
577 /* FIXME: Here we should check for errors on connection */ | |
578 /* because of proxy support - it can't be checked */ | |
579 /* by getsockopt() later in _handle_ready_sockets() */ | |
580 /* denis. */ | |
581 | |
582 plink->mode|=TCP_LINK_MODE_CONNECTING; | |
583 | |
584 plink->remote_uin=uin; | |
585 | |
586 plink->connect_time=time(0L); | |
587 | |
588 /* Send the hello packet */ | |
589 p=icq_TCPCreateInitPacket(plink); | |
590 icq_TCPLinkSend(plink, p); | |
591 | |
592 #ifdef TCP_PACKET_TRACE | |
593 printf("hello packet queued for %lu\n", uin); | |
594 #endif /* TCP_PACKET_TRACE */ | |
595 | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
596 icq_SocketSetHandler(plink->socket, ICQ_SOCKET_WRITE, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
597 icq_TCPLinkOnConnect, plink); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
598 |
1152 | 599 return 1; |
600 } | |
601 | |
602 icq_TCPLink *icq_TCPLinkAccept(icq_TCPLink *plink) | |
603 { | |
604 #ifdef _WIN32 | |
605 u_long iosflag; | |
606 #else | |
607 int flags; | |
608 #endif | |
609 int socket; | |
610 size_t remote_length; | |
611 icq_TCPLink *pnewlink=icq_TCPLinkNew( plink->icqlink ); | |
612 | |
613 if(pnewlink) | |
614 { | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
615 remote_length = sizeof(struct sockaddr_in); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
616 socket=icq_SocketAccept(plink->socket, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
617 (struct sockaddr *)&(plink->remote_address), &remote_length); |
1152 | 618 |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
619 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
620 "accepting tcp connection from %s:%d\n", |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
621 inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
622 ntohs(plink->remote_address.sin_port)); |
1152 | 623 |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
624 /* FIXME: make sure accept succeeded */ |
1152 | 625 |
626 pnewlink->type=plink->type; | |
627 pnewlink->socket=socket; | |
628 | |
629 /* first packet sent on an icq tcp link is always the hello packet */ | |
630 pnewlink->mode|=TCP_LINK_MODE_HELLOWAIT; | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
631 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
632 /* install socket handler for new socket */ |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
633 icq_SocketSetHandler(socket, ICQ_SOCKET_READ, icq_TCPLinkOnDataReceived, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
634 pnewlink); |
1152 | 635 } |
636 | |
637 /* set the socket to non-blocking */ | |
638 #ifdef _WIN32 | |
639 iosflag = TRUE; | |
640 ioctlsocket(plink->socket, FIONBIO, &iosflag); | |
641 #else | |
642 flags=fcntl(pnewlink->socket, F_GETFL, 0); | |
643 fcntl(pnewlink->socket, F_SETFL, flags | O_NONBLOCK); | |
644 #endif | |
645 | |
646 return pnewlink; | |
647 } | |
648 | |
649 int icq_TCPLinkListen(icq_TCPLink *plink) | |
650 { | |
651 unsigned int t; | |
652 | |
653 /* listening links have 0 uin */ | |
654 plink->remote_uin=0; | |
655 | |
656 /* create tcp listen socket */ | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
657 if((plink->socket=icq_SocketNew(AF_INET, SOCK_STREAM, 0)) < 0) |
1152 | 658 return -1; |
659 | |
660 /* must use memset, no bzero for Win32! */ | |
661 memset(&plink->socket_address, 0, sizeof(struct sockaddr_in)); | |
662 plink->socket_address.sin_family=AF_INET; | |
663 plink->socket_address.sin_addr.s_addr=htonl(INADDR_ANY); | |
664 plink->socket_address.sin_port=0; | |
665 | |
666 if(bind(plink->socket, (struct sockaddr *)&plink->socket_address, sizeof(struct sockaddr_in)) < 0) | |
667 return -2; | |
668 | |
669 if(listen(plink->socket, 5) < 0) | |
670 return -3; | |
671 | |
672 t=sizeof(struct sockaddr_in); | |
673 if(getsockname(plink->socket, (struct sockaddr *)&plink->socket_address, &t) < 0) | |
674 return -4; | |
675 | |
676 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, | |
677 "created tcp listening socket %d, local address=%s:%d\n", | |
678 plink->socket, | |
679 inet_ntoa(*((struct in_addr *)(&plink->socket_address.sin_addr))), | |
680 ntohs(plink->socket_address.sin_port)); | |
681 | |
682 plink->mode|=TCP_LINK_MODE_LISTEN; | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
683 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
684 icq_SocketSetHandler(plink->socket, ICQ_SOCKET_READ, icq_TCPLinkAccept, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
685 plink); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
686 |
1152 | 687 return 0; |
688 } | |
689 | |
690 /* Doing Cyrillic translations for Chat dialog sessions */ | |
691 void icq_ChatRusConv_n(const char to[4], char *t_in, int t_len) | |
692 { | |
693 int i, j; | |
694 | |
695 for(i = j = 0; i < t_len; ++i) | |
696 { | |
697 if((((unsigned char)t_in[i]) < ' ') && (t_in[i] != '\r')) | |
698 { | |
699 if(i - 1 > j) | |
700 icq_RusConv_n(to, &t_in[j], i - j - 1); | |
701 switch(t_in[i]) | |
702 { | |
703 case '\x07': /* Bell */ | |
704 case '\x08': /* BackSpace */ | |
705 case '\x03': /* Chat is active */ | |
706 case '\x04': /* Chat is not active */ | |
707 break; | |
708 case '\x00': /* Foregroung color (RR GG BB ?? ) */ | |
709 case '\x01': /* Background color (RR GG BB ?? ) */ | |
710 case '\x11': /* Font style change (Bold - 1, Italic - 2, Underline - 4) */ | |
711 case '\x12': /* Font size change */ | |
712 i += 4; | |
713 break; | |
714 case '\x10': /* Font family and encoding change */ | |
715 i += t_in[i+1] + 2 + 2; | |
716 icq_RusConv_n(to, &t_in[i+3], t_in[i+1]); | |
717 break; | |
718 } | |
719 j = i + 1; | |
720 } | |
721 } | |
722 if(i > t_len) | |
723 i = t_len; | |
724 if(j > t_len) | |
725 j = t_len; | |
726 if(i > j) | |
727 icq_RusConv_n(to, &t_in[j], i - j); | |
728 } | |
729 | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
730 void icq_TCPLinkOnDataReceived(icq_TCPLink *plink) |
1152 | 731 { |
732 int process_count=0, recv_result=0; | |
733 char *buffer=plink->buffer; | |
734 | |
735 do { /* while recv_result > 0 */ | |
736 | |
737 int done=0; | |
738 | |
739 /* append received data onto end of buffer */ | |
740 if((recv_result=recv(plink->socket, buffer+plink->buffer_count, | |
741 icq_TCPLinkBufferSize-plink->buffer_count, 0)) < 1) | |
742 { | |
743 /* either there was an error or the remote side has closed | |
744 * the connection - fall out of the loop */ | |
745 continue; | |
746 }; | |
747 | |
748 plink->buffer_count+=recv_result; | |
749 | |
750 #ifdef TCP_BUFFER_TRACE | |
751 printf("received %d bytes from link %x, new buffer count %d\n", | |
752 recv_result, plink, plink->buffer_count); | |
753 | |
754 hex_dump(plink->buffer, plink->buffer_count); | |
755 #endif /*TCP_BUFFER_TRACE*/ | |
756 | |
757 process_count+=recv_result; | |
758 | |
759 /* don't do any packet processing if we're in raw mode */ | |
760 if(plink->mode & TCP_LINK_MODE_RAW) { | |
761 /* notify the app with the new data */ | |
762 if(plink->type == TCP_LINK_CHAT) | |
763 icq_ChatRusConv_n("wk", plink->buffer, plink->buffer_count); | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
764 invoke_callback(plink->icqlink, icq_ChatNotify)(plink->session, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
765 CHAT_NOTIFY_DATA, plink->buffer_count, plink->buffer); |
1152 | 766 plink->buffer_count=0; |
767 continue; | |
768 } | |
769 | |
770 /* remove packets from the buffer until the buffer is empty | |
771 * or the remaining bytes do not equal a full packet */ | |
772 while((unsigned)plink->buffer_count>sizeof(WORD) && !done) | |
773 { | |
774 WORD packet_size=(*((WORD *)buffer)); | |
775 | |
776 /* warn if the buffer is too small to hold the whole packet */ | |
777 if(packet_size>icq_TCPLinkBufferSize-sizeof(WORD)) | |
778 { | |
779 icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "tcplink buffer " | |
780 "overflow, packet size = %d, buffer size = %d, closing link\n", | |
781 packet_size, icq_TCPLinkBufferSize); | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
782 return; |
1152 | 783 } |
784 | |
785 if(packet_size+sizeof(WORD) <= (unsigned)plink->buffer_count) | |
786 { | |
787 /* copy the packet into memory */ | |
788 icq_Packet *p=icq_PacketNew(); | |
789 icq_PacketAppend(p, buffer+sizeof(WORD), packet_size); | |
790 | |
791 /* remove it from the buffer */ | |
792 memcpy(buffer, buffer+packet_size+sizeof(WORD), | |
793 plink->buffer_count-packet_size-sizeof(WORD)); | |
794 | |
795 plink->buffer_count-=(packet_size+sizeof(WORD)); | |
796 | |
797 icq_TCPLinkOnPacketReceived(plink, p); | |
798 } | |
799 else | |
800 { | |
801 /* not enough bytes in buffer to form the complete packet. | |
802 * we're done for now */ | |
803 done=1; | |
804 } | |
805 } /* while packets remain in buffer */ | |
806 | |
807 } while (recv_result > 0); | |
808 | |
809 if (recv_result < 0 && errno!=EWOULDBLOCK) { | |
810 | |
811 /* receive error - log it */ | |
812 icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "recv failed from %d (%d-%s)," | |
813 " closing link\n", plink->remote_uin, errno, strerror(errno)); | |
814 | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
815 icq_TCPLinkClose(plink); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
816 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
817 } else { |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
818 |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
819 icq_TCPLinkProcessReceived(plink); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
820 |
1152 | 821 } |
822 | |
823 } | |
824 | |
825 void icq_TCPLinkOnPacketReceived(icq_TCPLink *plink, icq_Packet *p) | |
826 { | |
827 | |
828 #ifdef TCP_RAW_TRACE | |
829 printf("packet received! { length=%d }\n", p->length); | |
830 icq_PacketDump(p); | |
831 #endif | |
832 | |
833 /* Stick packet on ready packet linked list */ | |
834 list_enqueue(plink->received_queue, p); | |
835 } | |
836 | |
837 void icq_TCPLinkOnConnect(icq_TCPLink *plink) | |
838 { | |
839 #ifdef _WIN32 | |
840 int len; | |
841 #else | |
842 size_t len; | |
843 #endif | |
844 int error; | |
845 | |
846 /* check getsockopt */ | |
847 len=sizeof(error); | |
848 | |
849 #ifdef _WIN32 | |
850 getsockopt(plink->socket, SOL_SOCKET, SO_ERROR, (char *)&error, &len); | |
851 #else | |
852 getsockopt(plink->socket, SOL_SOCKET, SO_ERROR, &error, &len); | |
853 #endif | |
854 if(!error && (plink->mode & (TCP_LINK_SOCKS_CONNECTING | TCP_LINK_SOCKS_AUTHORIZATION | | |
855 TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_NOAUTHSTATUS | | |
856 TCP_LINK_SOCKS_CROSSCONNECT | TCP_LINK_SOCKS_CONNSTATUS))) | |
857 { | |
858 if(plink->mode & TCP_LINK_SOCKS_CONNECTING) | |
859 error = icq_TCPLinkProxyRequestAuthorization(plink); | |
860 else if(plink->mode & TCP_LINK_SOCKS_AUTHORIZATION) | |
861 error = icq_TCPLinkProxyAuthorization(plink); | |
862 else if(plink->mode & TCP_LINK_SOCKS_AUTHSTATUS) | |
863 error = icq_TCPLinkProxyAuthStatus(plink); | |
864 else if(plink->mode & TCP_LINK_SOCKS_NOAUTHSTATUS) | |
865 error = icq_TCPLinkProxyNoAuthStatus(plink); | |
866 else if(plink->mode & TCP_LINK_SOCKS_CROSSCONNECT) | |
867 error = icq_TCPLinkProxyCrossConnect(plink); | |
868 else if(plink->mode & TCP_LINK_SOCKS_CONNSTATUS) | |
869 error = icq_TCPLinkProxyConnectStatus(plink); | |
870 else | |
871 error = EINVAL; | |
872 } | |
873 | |
874 if(error) | |
875 { | |
876 /* connection failed- close the link, which takes care | |
877 * of notifying the app about packets that didn't make it */ | |
878 icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "connect failed to %d (%d-%s)," | |
879 " closing link\n", plink->remote_uin, error, strerror(error)); | |
880 | |
881 icq_TCPLinkClose(plink); | |
882 return; | |
883 } | |
884 | |
885 if(plink->mode & (TCP_LINK_SOCKS_CONNECTING | TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_CROSSCONNECT | TCP_LINK_SOCKS_CONNSTATUS)) | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
886 { |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
887 icq_SocketSetHandler(plink->socket, ICQ_SOCKET_WRITE, NULL, NULL); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
888 icq_SocketSetHandler(plink->socket, ICQ_SOCKET_READ, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
889 icq_TCPLinkOnConnect, plink); |
1152 | 890 return; |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
891 } |
1152 | 892 |
893 len=sizeof(plink->socket_address); | |
894 getsockname(plink->socket, (struct sockaddr *)&plink->socket_address, &len); | |
895 | |
896 icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, | |
897 "connected to uin %d, socket=%d local address=%s:%d remote address=%s:%d\n", | |
898 plink->remote_uin, plink->socket, | |
899 inet_ntoa(*((struct in_addr *)(&plink->socket_address.sin_addr))), | |
900 ntohs(plink->socket_address.sin_port), | |
901 inet_ntoa(*((struct in_addr *)(&plink->remote_address.sin_addr))), | |
902 ntohs(plink->remote_address.sin_port)); | |
903 | |
904 plink->mode&= ~TCP_LINK_MODE_CONNECTING; | |
905 | |
1432
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
906 icq_SocketSetHandler(plink->socket, ICQ_SOCKET_READ, |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
907 icq_TCPLinkOnDataReceived, plink); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
908 icq_SocketSetHandler(plink->socket, ICQ_SOCKET_WRITE, NULL, NULL); |
4c510ca3563f
[gaim-migrate @ 1442]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1309
diff
changeset
|
909 |
1152 | 910 /* socket is now connected, notify each request that connection |
911 * has been established and send pending data */ | |
912 while(plink->send_queue->count>0) | |
913 { | |
914 icq_Packet *p=list_dequeue(plink->send_queue); | |
915 if(p->id) | |
916 if(plink->icqlink->icq_RequestNotify) | |
917 (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTED, 0, 0); | |
918 icq_TCPLinkSend(plink, p); | |
919 } | |
920 | |
921 /* yeah this probably shouldn't be here. oh well :) */ | |
922 if(plink->type==TCP_LINK_CHAT) | |
923 { | |
924 icq_ChatSessionSetStatus((icq_ChatSession *)plink->session, | |
925 CHAT_STATUS_CONNECTED); | |
926 icq_ChatSessionSetStatus((icq_ChatSession *)plink->session, | |
927 CHAT_STATUS_WAIT_ALLINFO); | |
928 } | |
929 | |
930 if(plink->type==TCP_LINK_FILE) | |
931 { | |
932 icq_FileSessionSetStatus((icq_FileSession *)plink->session, | |
933 FILE_STATUS_CONNECTED); | |
934 } | |
935 | |
936 } | |
937 | |
938 unsigned long icq_TCPLinkSendSeq(icq_TCPLink *plink, icq_Packet *p, | |
939 unsigned long sequence) | |
940 { | |
941 /* append the next sequence number on the packet */ | |
942 if (!sequence) | |
1309
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
943 sequence=plink->icqlink->d->icq_TCPSequence--; |
1152 | 944 p->id=sequence; |
945 icq_PacketEnd(p); | |
946 icq_PacketAppend32(p, sequence); | |
947 | |
948 /* if the link is currently connecting, queue the packets for | |
949 * later, else send immediately */ | |
950 if(plink->mode & TCP_LINK_MODE_CONNECTING) { | |
951 list_insert(plink->send_queue, 0, p); | |
952 if(plink->icqlink->icq_RequestNotify) | |
953 (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTING, 0, 0); | |
954 } else { | |
955 icq_PacketSend(p, plink->socket); | |
956 if(p->id) | |
957 if(plink->icqlink->icq_RequestNotify) | |
958 (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SENT, 0, 0); | |
959 icq_PacketDelete(p); | |
960 } | |
961 return sequence; | |
962 } | |
963 | |
964 void icq_TCPLinkSend(icq_TCPLink *plink, icq_Packet *p) | |
965 { | |
966 /* if the link is currently connecting, queue the packets for | |
967 * later, else send immediately */ | |
968 if(plink->mode & TCP_LINK_MODE_CONNECTING) { | |
969 list_insert(plink->send_queue, 0, p); | |
970 if(plink->icqlink->icq_RequestNotify) | |
971 (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTING, 0, 0); | |
972 } else { | |
973 icq_PacketSend(p, plink->socket); | |
974 if(p->id) | |
975 if(plink->icqlink->icq_RequestNotify) | |
976 (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SENT, 0, 0); | |
977 icq_PacketDelete(p); | |
978 } | |
979 } | |
980 | |
981 void icq_TCPLinkProcessReceived(icq_TCPLink *plink) | |
982 { | |
983 list *plist=plink->received_queue; | |
984 while(plist->count>0) | |
985 | |
986 { | |
987 icq_Packet *p=list_dequeue(plist); | |
988 | |
989 if(plink->mode & TCP_LINK_MODE_HELLOWAIT) | |
990 { | |
991 icq_TCPProcessHello(p, plink); | |
992 } | |
993 else | |
994 { | |
995 | |
996 switch (plink->type) { | |
997 | |
998 case TCP_LINK_MESSAGE: | |
999 icq_TCPProcessPacket(p, plink); | |
1000 break; | |
1001 | |
1002 case TCP_LINK_CHAT: | |
1003 icq_TCPProcessChatPacket(p, plink); | |
1004 break; | |
1005 | |
1006 case TCP_LINK_FILE: | |
1007 icq_TCPProcessFilePacket(p, plink); | |
1008 break; | |
1009 | |
1010 } | |
1011 } | |
1012 | |
1013 icq_PacketDelete(p); | |
1014 } | |
1015 | |
1016 } | |
1017 | |
1018 int _icq_FindTCPLink(void *p, va_list data) | |
1019 { | |
1020 icq_TCPLink *plink=(icq_TCPLink *)p; | |
1021 unsigned long uin=va_arg(data, unsigned long); | |
1022 int type=va_arg(data, int); | |
1023 | |
1024 return ( (plink->remote_uin == uin ) && (plink->type == type) ); | |
1025 } | |
1026 | |
1027 icq_TCPLink *icq_FindTCPLink(ICQLINK *link, unsigned long uin, int type) | |
1028 { | |
1309
0a766047b4fd
[gaim-migrate @ 1319]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1152
diff
changeset
|
1029 return list_traverse(link->d->icq_TCPLinks, _icq_FindTCPLink, uin, type); |
1152 | 1030 } |