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