Mercurial > pidgin
comparison src/proxy.c @ 3630:9682c0e022c6
[gaim-migrate @ 3753]
Yeah this will probably break a lot of shit knowing my luck. But hey, I really don't care what people thnk.
committer: Tailor Script <tailor@pidgin.im>
author | Rob Flynn <gaim@robflynn.com> |
---|---|
date | Fri, 11 Oct 2002 03:14:01 +0000 |
parents | 8d0fa912ecaf |
children | 988485669631 |
comparison
equal
deleted
inserted
replaced
3629:afc5bb164c5a | 3630:9682c0e022c6 |
---|---|
28 #endif | 28 #endif |
29 #include <stdio.h> | 29 #include <stdio.h> |
30 #include <stdlib.h> | 30 #include <stdlib.h> |
31 #include <string.h> | 31 #include <string.h> |
32 #include <sys/types.h> | 32 #include <sys/types.h> |
33 | |
34 #ifndef _WIN32 | |
33 #include <sys/socket.h> | 35 #include <sys/socket.h> |
34 #include <netdb.h> | 36 #include <netdb.h> |
35 #include <netinet/in.h> | 37 #include <netinet/in.h> |
36 #include <arpa/inet.h> | 38 #include <arpa/inet.h> |
37 #include <unistd.h> | 39 #include <unistd.h> |
40 #else | |
41 #include <winsock.h> | |
42 #endif | |
43 | |
38 #include <fcntl.h> | 44 #include <fcntl.h> |
39 #include <errno.h> | 45 #include <errno.h> |
40 #include "gaim.h" | 46 #include "gaim.h" |
41 #include "proxy.h" | 47 #include "proxy.h" |
48 | |
49 #ifdef _WIN32 | |
50 #include "win32dep.h" | |
51 #endif | |
42 | 52 |
43 #define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) | 53 #define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) |
44 #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) | 54 #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) |
45 | 55 |
46 char proxyhost[128] = { 0 }; | 56 char proxyhost[128] = { 0 }; |
121 | 131 |
122 static struct sockaddr_in *gaim_gethostbyname(char *host, int port) | 132 static struct sockaddr_in *gaim_gethostbyname(char *host, int port) |
123 { | 133 { |
124 static struct sockaddr_in sin; | 134 static struct sockaddr_in sin; |
125 | 135 |
136 #ifndef _WIN32 | |
126 if (!inet_aton(host, &sin.sin_addr)) { | 137 if (!inet_aton(host, &sin.sin_addr)) { |
138 #else | |
139 if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) { | |
140 #endif | |
127 struct hostent *hp; | 141 struct hostent *hp; |
128 if (!(hp = gethostbyname(host))) { | 142 if(!(hp = gethostbyname(host))) { |
143 #ifndef _WIN32 | |
129 debug_printf("gaim_gethostbyname(\"%s\", %d) failed: %s", | 144 debug_printf("gaim_gethostbyname(\"%s\", %d) failed: %s", |
130 host, port, hstrerror(h_errno)); | 145 host, port, hstrerror(h_errno)); |
146 #else | |
147 debug_printf("gaim_gethostbyname(\"%s\", %d) failed: Error %d", | |
148 host, port, WSAGetLastError()); | |
149 #endif | |
131 return NULL; | 150 return NULL; |
132 } | 151 } |
133 memset(&sin, 0, sizeof(struct sockaddr_in)); | 152 memset(&sin, 0, sizeof(struct sockaddr_in)); |
134 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); | 153 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); |
135 sin.sin_family = hp->h_addrtype; | 154 sin.sin_family = hp->h_addrtype; |
142 | 161 |
143 static void no_one_calls(gpointer data, gint source, GaimInputCondition cond) | 162 static void no_one_calls(gpointer data, gint source, GaimInputCondition cond) |
144 { | 163 { |
145 struct PHB *phb = data; | 164 struct PHB *phb = data; |
146 unsigned int len; | 165 unsigned int len; |
166 #ifdef _WIN32 | |
167 int werror = WSAETIMEDOUT; | |
168 u_long imode; | |
169 #else | |
147 int error = ETIMEDOUT; | 170 int error = ETIMEDOUT; |
171 #endif | |
148 debug_printf("Connected\n"); | 172 debug_printf("Connected\n"); |
173 #ifdef _WIN32 | |
174 len = sizeof(werror); | |
175 if (getsockopt(source, SOL_SOCKET, SO_ERROR, (char*)&werror, &len) < 0) { | |
176 closesocket(source); | |
177 gaim_input_remove(phb->inpa); | |
178 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
179 g_free(phb); | |
180 return; | |
181 } else | |
182 WSASetLastError(werror); | |
183 imode=0; | |
184 ioctlsocket(source, FIONBIO, &imode); | |
185 #else | |
149 len = sizeof(error); | 186 len = sizeof(error); |
150 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 187 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
151 close(source); | 188 close(source); |
152 gaim_input_remove(phb->inpa); | 189 gaim_input_remove(phb->inpa); |
153 phb->func(phb->data, -1, GAIM_INPUT_READ); | 190 phb->func(phb->data, -1, GAIM_INPUT_READ); |
154 g_free(phb); | 191 g_free(phb); |
155 return; | 192 return; |
156 } | 193 } |
157 fcntl(source, F_SETFL, 0); | 194 fcntl(source, F_SETFL, 0); |
195 #endif | |
158 gaim_input_remove(phb->inpa); | 196 gaim_input_remove(phb->inpa); |
159 phb->func(phb->data, source, GAIM_INPUT_READ); | 197 phb->func(phb->data, source, GAIM_INPUT_READ); |
160 g_free(phb); | 198 g_free(phb); |
161 } | 199 } |
162 | 200 |
173 | 211 |
174 static int proxy_connect_none(char *host, unsigned short port, struct PHB *phb) | 212 static int proxy_connect_none(char *host, unsigned short port, struct PHB *phb) |
175 { | 213 { |
176 struct sockaddr_in *sin; | 214 struct sockaddr_in *sin; |
177 int fd = -1; | 215 int fd = -1; |
178 | 216 #ifdef _WIN32 |
217 u_long imode; | |
218 int w_errno; | |
219 #endif | |
179 debug_printf("connecting to %s:%d with no proxy\n", host, port); | 220 debug_printf("connecting to %s:%d with no proxy\n", host, port); |
180 | 221 |
181 if (!(sin = gaim_gethostbyname(host, port))) { | 222 if (!(sin = gaim_gethostbyname(host, port))) { |
182 debug_printf("gethostbyname failed\n"); | 223 debug_printf("gethostbyname failed\n"); |
183 g_free(phb); | 224 g_free(phb); |
187 if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { | 228 if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { |
188 debug_printf("unable to create socket\n"); | 229 debug_printf("unable to create socket\n"); |
189 g_free(phb); | 230 g_free(phb); |
190 return -1; | 231 return -1; |
191 } | 232 } |
192 | 233 #ifdef _WIN32 |
234 imode=1; | |
235 ioctlsocket(fd, FIONBIO, &imode); | |
236 #else | |
193 fcntl(fd, F_SETFL, O_NONBLOCK); | 237 fcntl(fd, F_SETFL, O_NONBLOCK); |
238 #endif | |
194 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { | 239 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { |
240 #ifdef _WIN32 | |
241 w_errno = WSAGetLastError(); | |
242 if ((w_errno == WSAEINPROGRESS) || (w_errno == WSAEINTR) || (w_errno == WSAEWOULDBLOCK)) { | |
243 #else | |
195 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 244 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
245 #endif | |
196 debug_printf("Connect would have blocked\n"); | 246 debug_printf("Connect would have blocked\n"); |
197 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, phb); | 247 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, phb); |
198 } else { | 248 } else { |
249 #ifdef _WIN32 | |
250 debug_printf("connect failed (errno %d)\n", w_errno); | |
251 closesocket(fd); | |
252 #else | |
199 debug_printf("connect failed (errno %d)\n", errno); | 253 debug_printf("connect failed (errno %d)\n", errno); |
200 close(fd); | 254 close(fd); |
255 #endif | |
201 g_free(phb); | 256 g_free(phb); |
202 return -1; | 257 return -1; |
203 } | 258 } |
204 } else { | 259 } else { |
260 #ifdef _WIN32 | |
261 int werror = WSAETIMEDOUT; | |
262 unsigned int len; | |
263 u_long imode; | |
264 | |
265 debug_printf("Connect didn't block\n"); | |
266 len = sizeof(werror); | |
267 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&werror, &len) < 0) { | |
268 debug_printf("getsockopt failed\n"); | |
269 closesocket(fd); | |
270 g_free(phb); | |
271 return -1; | |
272 } else | |
273 WSASetLastError(werror); | |
274 imode=0; | |
275 ioctlsocket(fd, FIONBIO, &imode); | |
276 #else | |
205 unsigned int len; | 277 unsigned int len; |
206 int error = ETIMEDOUT; | 278 int error = ETIMEDOUT; |
207 debug_printf("Connect didn't block\n"); | 279 debug_printf("Connect didn't block\n"); |
208 len = sizeof(error); | 280 len = sizeof(error); |
209 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 281 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
211 close(fd); | 283 close(fd); |
212 g_free(phb); | 284 g_free(phb); |
213 return -1; | 285 return -1; |
214 } | 286 } |
215 fcntl(fd, F_SETFL, 0); | 287 fcntl(fd, F_SETFL, 0); |
288 #endif | |
216 phb->port = fd; /* bleh */ | 289 phb->port = fd; /* bleh */ |
217 g_timeout_add(50, clean_connect, phb); /* we do this because we never | 290 g_timeout_add(50, clean_connect, phb); /* we do this because we never |
218 want to call our callback | 291 want to call our callback |
219 before we return. */ | 292 before we return. */ |
220 } | 293 } |
232 struct PHB *phb = data; | 305 struct PHB *phb = data; |
233 char inputline[8192]; | 306 char inputline[8192]; |
234 | 307 |
235 gaim_input_remove(phb->inpa); | 308 gaim_input_remove(phb->inpa); |
236 | 309 |
310 #ifdef _WIN32 | |
311 while ((nlc != 2) && (recv(source, &inputline[pos++], 1, 0) == 1)) { | |
312 #else | |
237 while ((nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { | 313 while ((nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { |
314 #endif | |
238 if (inputline[pos - 1] == '\n') | 315 if (inputline[pos - 1] == '\n') |
239 nlc++; | 316 nlc++; |
240 else if (inputline[pos - 1] != '\r') | 317 else if (inputline[pos - 1] != '\r') |
241 nlc = 0; | 318 nlc = 0; |
242 } | 319 } |
250 g_free(phb->host); | 327 g_free(phb->host); |
251 g_free(phb); | 328 g_free(phb); |
252 return; | 329 return; |
253 } | 330 } |
254 | 331 |
332 #ifdef _WIN32 | |
333 closesocket(source); | |
334 #else | |
255 close(source); | 335 close(source); |
336 #endif | |
256 phb->func(phb->data, -1, GAIM_INPUT_READ); | 337 phb->func(phb->data, -1, GAIM_INPUT_READ); |
257 g_free(phb->host); | 338 g_free(phb->host); |
258 g_free(phb); | 339 g_free(phb); |
259 return; | 340 return; |
260 } | 341 } |
262 static void http_canwrite(gpointer data, gint source, GaimInputCondition cond) | 343 static void http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
263 { | 344 { |
264 char cmd[384]; | 345 char cmd[384]; |
265 struct PHB *phb = data; | 346 struct PHB *phb = data; |
266 unsigned int len; | 347 unsigned int len; |
348 #ifdef _WIN32 | |
349 int w_error = WSAETIMEDOUT; | |
350 u_long imode = 0; | |
351 #else | |
267 int error = ETIMEDOUT; | 352 int error = ETIMEDOUT; |
353 #endif | |
268 debug_printf("Connected\n"); | 354 debug_printf("Connected\n"); |
269 if (phb->inpa > 0) | 355 if (phb->inpa > 0) |
270 gaim_input_remove(phb->inpa); | 356 gaim_input_remove(phb->inpa); |
357 #ifdef _WIN32 | |
358 len = sizeof(w_error); | |
359 if (getsockopt(source, SOL_SOCKET, SO_ERROR, (char*)&w_error, &len) < 0) { | |
360 closesocket(source); | |
361 #else | |
271 len = sizeof(error); | 362 len = sizeof(error); |
272 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 363 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
273 close(source); | 364 close(source); |
274 phb->func(phb->data, -1, GAIM_INPUT_READ); | 365 #endif |
275 g_free(phb->host); | 366 phb->func(phb->data, -1, GAIM_INPUT_READ); |
276 g_free(phb); | 367 g_free(phb->host); |
277 return; | 368 g_free(phb); |
369 return; | |
370 #ifdef _WIN32 | |
371 } else | |
372 WSASetLastError( w_error ); | |
373 ioctlsocket(source, FIONBIO, &imode); | |
374 #else | |
278 } | 375 } |
279 fcntl(source, F_SETFL, 0); | 376 fcntl(source, F_SETFL, 0); |
280 | 377 #endif |
281 g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port, | 378 g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port, |
282 phb->host, phb->port); | 379 phb->host, phb->port); |
283 if (send(source, cmd, strlen(cmd), 0) < 0) { | 380 if (send(source, cmd, strlen(cmd), 0) < 0) { |
284 close(source); | 381 #ifdef _WIN32 |
382 closesocket(source); | |
383 #else | |
384 close(source); | |
385 #endif | |
285 phb->func(phb->data, -1, GAIM_INPUT_READ); | 386 phb->func(phb->data, -1, GAIM_INPUT_READ); |
286 g_free(phb->host); | 387 g_free(phb->host); |
287 g_free(phb); | 388 g_free(phb); |
288 return; | 389 return; |
289 } | 390 } |
294 t2 = tobase64(t1); | 395 t2 = tobase64(t1); |
295 g_free(t1); | 396 g_free(t1); |
296 g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2); | 397 g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2); |
297 g_free(t2); | 398 g_free(t2); |
298 if (send(source, cmd, strlen(cmd), 0) < 0) { | 399 if (send(source, cmd, strlen(cmd), 0) < 0) { |
400 #ifdef _WIN32 | |
401 closesocket(source); | |
402 #else | |
299 close(source); | 403 close(source); |
404 #endif | |
300 phb->func(phb->data, -1, GAIM_INPUT_READ); | 405 phb->func(phb->data, -1, GAIM_INPUT_READ); |
301 g_free(phb->host); | 406 g_free(phb->host); |
302 g_free(phb); | 407 g_free(phb); |
303 return; | 408 return; |
304 } | 409 } |
305 } | 410 } |
306 | 411 |
307 g_snprintf(cmd, sizeof(cmd), "\r\n"); | 412 g_snprintf(cmd, sizeof(cmd), "\r\n"); |
308 if (send(source, cmd, strlen(cmd), 0) < 0) { | 413 if (send(source, cmd, strlen(cmd), 0) < 0) { |
309 close(source); | 414 #ifdef _WIN32 |
415 closesocket(source); | |
416 #else | |
417 close(source); | |
418 #endif | |
310 phb->func(phb->data, -1, GAIM_INPUT_READ); | 419 phb->func(phb->data, -1, GAIM_INPUT_READ); |
311 g_free(phb->host); | 420 g_free(phb->host); |
312 g_free(phb); | 421 g_free(phb); |
313 return; | 422 return; |
314 } | 423 } |
318 | 427 |
319 static int proxy_connect_http(char *host, unsigned short port, struct PHB *phb) | 428 static int proxy_connect_http(char *host, unsigned short port, struct PHB *phb) |
320 { | 429 { |
321 struct sockaddr_in *sin; | 430 struct sockaddr_in *sin; |
322 int fd = -1; | 431 int fd = -1; |
432 #ifdef _WIN32 | |
433 u_long imode; | |
434 #endif | |
323 | 435 |
324 debug_printf("connecting to %s:%d via %s:%d using HTTP\n", host, port, proxyhost, proxyport); | 436 debug_printf("connecting to %s:%d via %s:%d using HTTP\n", host, port, proxyhost, proxyport); |
325 | 437 |
326 if (!(sin = gaim_gethostbyname(proxyhost, proxyport))) { | 438 if (!(sin = gaim_gethostbyname(proxyhost, proxyport))) { |
327 g_free(phb); | 439 g_free(phb); |
334 } | 446 } |
335 | 447 |
336 phb->host = g_strdup(host); | 448 phb->host = g_strdup(host); |
337 phb->port = port; | 449 phb->port = port; |
338 | 450 |
451 #ifdef _WIN32 | |
452 imode = 1; | |
453 ioctlsocket(fd, FIONBIO, &imode); | |
454 #else | |
339 fcntl(fd, F_SETFL, O_NONBLOCK); | 455 fcntl(fd, F_SETFL, O_NONBLOCK); |
456 #endif | |
340 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { | 457 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { |
458 #ifdef _WIN32 | |
459 int w_errno = WSAGetLastError(); | |
460 if ((w_errno == WSAEINPROGRESS) || (w_errno == WSAEINTR)) { | |
461 #else | |
341 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 462 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
463 #endif | |
342 debug_printf("Connect would have blocked\n"); | 464 debug_printf("Connect would have blocked\n"); |
343 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, http_canwrite, phb); | 465 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, http_canwrite, phb); |
344 } else { | 466 } else { |
467 #ifdef _WIN32 | |
468 closesocket(fd); | |
469 #else | |
345 close(fd); | 470 close(fd); |
471 #endif | |
346 g_free(phb->host); | 472 g_free(phb->host); |
347 g_free(phb); | 473 g_free(phb); |
348 return -1; | 474 return -1; |
349 } | 475 } |
350 } else { | 476 } else { |
351 unsigned int len; | 477 unsigned int len; |
478 #ifdef _WIN32 | |
479 int werror = WSAETIMEDOUT; | |
480 u_long imode; | |
481 #else | |
352 int error = ETIMEDOUT; | 482 int error = ETIMEDOUT; |
483 #endif | |
353 debug_printf("Connect didn't block\n"); | 484 debug_printf("Connect didn't block\n"); |
485 #ifdef _WIN32 | |
486 len = sizeof(werror); | |
487 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&werror, &len) < 0) { | |
488 closesocket(fd); | |
489 #else | |
354 len = sizeof(error); | 490 len = sizeof(error); |
355 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 491 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
356 close(fd); | 492 close(fd); |
493 #endif | |
357 g_free(phb->host); | 494 g_free(phb->host); |
358 g_free(phb); | 495 g_free(phb); |
359 return -1; | 496 return -1; |
497 #ifdef _WIN32 | |
498 } else | |
499 WSASetLastError(werror); | |
500 imode=0; | |
501 ioctlsocket(fd, FIONBIO, &imode); | |
502 #else | |
360 } | 503 } |
361 fcntl(fd, F_SETFL, 0); | 504 fcntl(fd, F_SETFL, 0); |
505 #endif | |
362 http_canwrite(phb, fd, GAIM_INPUT_WRITE); | 506 http_canwrite(phb, fd, GAIM_INPUT_WRITE); |
363 } | 507 } |
364 | 508 |
365 return fd; | 509 return fd; |
366 } | 510 } |
371 struct PHB *phb = data; | 515 struct PHB *phb = data; |
372 | 516 |
373 gaim_input_remove(phb->inpa); | 517 gaim_input_remove(phb->inpa); |
374 | 518 |
375 memset(packet, 0, sizeof(packet)); | 519 memset(packet, 0, sizeof(packet)); |
520 #ifdef _WIN32 | |
521 if (recv(source, packet, 9, 0) >= 4 && packet[1] == 90) { | |
522 #else | |
376 if (read(source, packet, 9) >= 4 && packet[1] == 90) { | 523 if (read(source, packet, 9) >= 4 && packet[1] == 90) { |
524 #endif | |
377 phb->func(phb->data, source, GAIM_INPUT_READ); | 525 phb->func(phb->data, source, GAIM_INPUT_READ); |
378 g_free(phb->host); | 526 g_free(phb->host); |
379 g_free(phb); | 527 g_free(phb); |
380 return; | 528 return; |
381 } | 529 } |
382 | 530 |
531 #ifdef _WIN32 | |
532 closesocket(source); | |
533 #else | |
383 close(source); | 534 close(source); |
535 #endif | |
384 phb->func(phb->data, -1, GAIM_INPUT_READ); | 536 phb->func(phb->data, -1, GAIM_INPUT_READ); |
385 g_free(phb->host); | 537 g_free(phb->host); |
386 g_free(phb); | 538 g_free(phb); |
387 } | 539 } |
388 | 540 |
390 { | 542 { |
391 unsigned char packet[12]; | 543 unsigned char packet[12]; |
392 struct hostent *hp; | 544 struct hostent *hp; |
393 struct PHB *phb = data; | 545 struct PHB *phb = data; |
394 unsigned int len; | 546 unsigned int len; |
547 #ifdef _WIN32 | |
548 int werror = WSAETIMEDOUT; | |
549 u_long imode; | |
550 #else | |
395 int error = ETIMEDOUT; | 551 int error = ETIMEDOUT; |
552 #endif | |
396 debug_printf("Connected\n"); | 553 debug_printf("Connected\n"); |
397 if (phb->inpa > 0) | 554 if (phb->inpa > 0) |
398 gaim_input_remove(phb->inpa); | 555 gaim_input_remove(phb->inpa); |
556 #ifdef _WIN32 | |
557 len = sizeof(werror); | |
558 if (getsockopt(source, SOL_SOCKET, SO_ERROR, (char*)&werror, &len) < 0) { | |
559 closesocket(source); | |
560 #else | |
399 len = sizeof(error); | 561 len = sizeof(error); |
400 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 562 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
401 close(source); | 563 close(source); |
402 phb->func(phb->data, -1, GAIM_INPUT_READ); | 564 #endif |
403 g_free(phb->host); | 565 phb->func(phb->data, -1, GAIM_INPUT_READ); |
404 g_free(phb); | 566 g_free(phb->host); |
405 return; | 567 g_free(phb); |
568 return; | |
569 #ifdef _WIN32 | |
570 } else | |
571 WSASetLastError(werror); | |
572 imode=0; | |
573 ioctlsocket(source, FIONBIO, &imode); | |
574 #else | |
406 } | 575 } |
407 fcntl(source, F_SETFL, 0); | 576 fcntl(source, F_SETFL, 0); |
408 | 577 #endif |
409 /* XXX does socks4 not support host name lookups by the proxy? */ | 578 /* XXX does socks4 not support host name lookups by the proxy? */ |
410 if (!(hp = gethostbyname(phb->host))) { | 579 if (!(hp = gethostbyname(phb->host))) { |
411 close(source); | 580 #ifdef _WIN32 |
581 closesocket(source); | |
582 #else | |
583 close(source); | |
584 #endif | |
412 phb->func(phb->data, -1, GAIM_INPUT_READ); | 585 phb->func(phb->data, -1, GAIM_INPUT_READ); |
413 g_free(phb->host); | 586 g_free(phb->host); |
414 g_free(phb); | 587 g_free(phb); |
415 return; | 588 return; |
416 } | 589 } |
422 packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; | 595 packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; |
423 packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; | 596 packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; |
424 packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; | 597 packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; |
425 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; | 598 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; |
426 packet[8] = 0; | 599 packet[8] = 0; |
600 #ifdef _WIN32 | |
601 if (send(source, packet, 9, 0) != 9) { | |
602 closesocket(source); | |
603 #else | |
427 if (write(source, packet, 9) != 9) { | 604 if (write(source, packet, 9) != 9) { |
428 close(source); | 605 close(source); |
606 #endif | |
429 phb->func(phb->data, -1, GAIM_INPUT_READ); | 607 phb->func(phb->data, -1, GAIM_INPUT_READ); |
430 g_free(phb->host); | 608 g_free(phb->host); |
431 g_free(phb); | 609 g_free(phb); |
432 return; | 610 return; |
433 } | 611 } |
437 | 615 |
438 static int proxy_connect_socks4(char *host, unsigned short port, struct PHB *phb) | 616 static int proxy_connect_socks4(char *host, unsigned short port, struct PHB *phb) |
439 { | 617 { |
440 struct sockaddr_in *sin; | 618 struct sockaddr_in *sin; |
441 int fd = -1; | 619 int fd = -1; |
620 #ifdef _WIN32 | |
621 int werrno; | |
622 u_long imode; | |
623 #endif | |
442 | 624 |
443 debug_printf("connecting to %s:%d via %s:%d using SOCKS4\n", host, port, proxyhost, proxyport); | 625 debug_printf("connecting to %s:%d via %s:%d using SOCKS4\n", host, port, proxyhost, proxyport); |
444 | 626 |
445 if (!(sin = gaim_gethostbyname(proxyhost, proxyport))) { | 627 if (!(sin = gaim_gethostbyname(proxyhost, proxyport))) { |
446 g_free(phb); | 628 g_free(phb); |
453 } | 635 } |
454 | 636 |
455 phb->host = g_strdup(host); | 637 phb->host = g_strdup(host); |
456 phb->port = port; | 638 phb->port = port; |
457 | 639 |
640 #ifdef _WIN32 | |
641 imode=1; | |
642 ioctlsocket(fd, FIONBIO, &imode); | |
643 #else | |
458 fcntl(fd, F_SETFL, O_NONBLOCK); | 644 fcntl(fd, F_SETFL, O_NONBLOCK); |
645 #endif | |
459 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { | 646 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { |
647 #ifdef _WIN32 | |
648 werrno = WSAGetLastError(); | |
649 if ((werrno == WSAEINPROGRESS) || (werrno == WSAEINTR)) { | |
650 #else | |
460 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 651 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
652 #endif | |
461 debug_printf("Connect would have blocked\n"); | 653 debug_printf("Connect would have blocked\n"); |
462 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb); | 654 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb); |
463 } else { | 655 } else { |
656 #ifdef _WIN32 | |
657 closesocket(fd); | |
658 #else | |
464 close(fd); | 659 close(fd); |
660 #endif | |
465 g_free(phb->host); | 661 g_free(phb->host); |
466 g_free(phb); | 662 g_free(phb); |
467 return -1; | 663 return -1; |
468 } | 664 } |
469 } else { | 665 } else { |
470 unsigned int len; | 666 unsigned int len; |
667 #ifdef _WIN32 | |
668 int werror = WSAETIMEDOUT; | |
669 u_long imode; | |
670 #else | |
471 int error = ETIMEDOUT; | 671 int error = ETIMEDOUT; |
672 #endif | |
472 debug_printf("Connect didn't block\n"); | 673 debug_printf("Connect didn't block\n"); |
674 #ifdef _WIN32 | |
675 len = sizeof(werror); | |
676 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&werror, &len) < 0) { | |
677 closesocket(fd); | |
678 #else | |
473 len = sizeof(error); | 679 len = sizeof(error); |
474 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 680 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
475 close(fd); | 681 close(fd); |
682 #endif | |
476 g_free(phb->host); | 683 g_free(phb->host); |
477 g_free(phb); | 684 g_free(phb); |
478 return -1; | 685 return -1; |
686 #ifdef _WIN32 | |
687 } else | |
688 WSASetLastError(werror); | |
689 imode=0; | |
690 ioctlsocket(fd, FIONBIO, &imode); | |
691 #else | |
479 } | 692 } |
480 fcntl(fd, F_SETFL, 0); | 693 fcntl(fd, F_SETFL, 0); |
694 #endif | |
481 s4_canwrite(phb, fd, GAIM_INPUT_WRITE); | 695 s4_canwrite(phb, fd, GAIM_INPUT_WRITE); |
482 } | 696 } |
483 | 697 |
484 return fd; | 698 return fd; |
485 } | 699 } |
490 struct PHB *phb = data; | 704 struct PHB *phb = data; |
491 | 705 |
492 gaim_input_remove(phb->inpa); | 706 gaim_input_remove(phb->inpa); |
493 debug_printf("able to read again\n"); | 707 debug_printf("able to read again\n"); |
494 | 708 |
709 #ifdef _WIN32 | |
710 if (recv(source, buf, 10, 0) < 10) { | |
711 #else | |
495 if (read(source, buf, 10) < 10) { | 712 if (read(source, buf, 10) < 10) { |
713 #endif | |
496 debug_printf("or not...\n"); | 714 debug_printf("or not...\n"); |
497 close(source); | 715 #ifdef _WIN32 |
716 closesocket(source); | |
717 #else | |
718 close(source); | |
719 #endif | |
498 phb->func(phb->data, -1, GAIM_INPUT_READ); | 720 phb->func(phb->data, -1, GAIM_INPUT_READ); |
499 g_free(phb->host); | 721 g_free(phb->host); |
500 g_free(phb); | 722 g_free(phb); |
501 return; | 723 return; |
502 } | 724 } |
503 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { | 725 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { |
504 debug_printf("bad data\n"); | 726 debug_printf("bad data\n"); |
505 close(source); | 727 #ifdef _WIN32 |
728 closesocket(source); | |
729 #else | |
730 close(source); | |
731 #endif | |
506 phb->func(phb->data, -1, GAIM_INPUT_READ); | 732 phb->func(phb->data, -1, GAIM_INPUT_READ); |
507 g_free(phb->host); | 733 g_free(phb->host); |
508 g_free(phb); | 734 g_free(phb); |
509 return; | 735 return; |
510 } | 736 } |
528 buf[4] = hlen; | 754 buf[4] = hlen; |
529 memcpy(buf + 5, phb->host, hlen); | 755 memcpy(buf + 5, phb->host, hlen); |
530 buf[5 + strlen(phb->host)] = phb->port >> 8; | 756 buf[5 + strlen(phb->host)] = phb->port >> 8; |
531 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; | 757 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; |
532 | 758 |
759 #ifdef _WIN32 | |
760 if (send(source, buf, (5 + strlen(phb->host) + 2), 0) < (5 + strlen(phb->host) + 2)) { | |
761 closesocket(source); | |
762 #else | |
533 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { | 763 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { |
534 close(source); | 764 close(source); |
765 #endif | |
535 phb->func(phb->data, -1, GAIM_INPUT_READ); | 766 phb->func(phb->data, -1, GAIM_INPUT_READ); |
536 g_free(phb->host); | 767 g_free(phb->host); |
537 g_free(phb); | 768 g_free(phb); |
538 return; | 769 return; |
539 } | 770 } |
547 struct PHB *phb = data; | 778 struct PHB *phb = data; |
548 | 779 |
549 gaim_input_remove(phb->inpa); | 780 gaim_input_remove(phb->inpa); |
550 debug_printf("got auth response\n"); | 781 debug_printf("got auth response\n"); |
551 | 782 |
783 #ifdef _WIN32 | |
784 if (recv(source, buf, 2, 0) < 2) { | |
785 closesocket(source); | |
786 #else | |
552 if (read(source, buf, 2) < 2) { | 787 if (read(source, buf, 2) < 2) { |
553 close(source); | 788 close(source); |
789 #endif | |
554 phb->func(phb->data, -1, GAIM_INPUT_READ); | 790 phb->func(phb->data, -1, GAIM_INPUT_READ); |
555 g_free(phb->host); | 791 g_free(phb->host); |
556 g_free(phb); | 792 g_free(phb); |
557 return; | 793 return; |
558 } | 794 } |
559 | 795 |
560 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { | 796 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { |
561 close(source); | 797 #ifdef _WIN32 |
798 closesocket(source); | |
799 #else | |
800 close(source); | |
801 #endif | |
562 phb->func(phb->data, -1, GAIM_INPUT_READ); | 802 phb->func(phb->data, -1, GAIM_INPUT_READ); |
563 g_free(phb->host); | 803 g_free(phb->host); |
564 g_free(phb); | 804 g_free(phb); |
565 return; | 805 return; |
566 } | 806 } |
574 struct PHB *phb = data; | 814 struct PHB *phb = data; |
575 | 815 |
576 gaim_input_remove(phb->inpa); | 816 gaim_input_remove(phb->inpa); |
577 debug_printf("able to read\n"); | 817 debug_printf("able to read\n"); |
578 | 818 |
819 #ifdef _WIN32 | |
820 if (recv(source, buf, 2, 0) < 2) { | |
821 closesocket(source); | |
822 #else | |
579 if (read(source, buf, 2) < 2) { | 823 if (read(source, buf, 2) < 2) { |
580 close(source); | 824 close(source); |
825 #endif | |
581 phb->func(phb->data, -1, GAIM_INPUT_READ); | 826 phb->func(phb->data, -1, GAIM_INPUT_READ); |
582 g_free(phb->host); | 827 g_free(phb->host); |
583 g_free(phb); | 828 g_free(phb); |
584 return; | 829 return; |
585 } | 830 } |
586 | 831 |
587 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { | 832 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { |
588 close(source); | 833 #ifdef _WIN32 |
834 closesocket(source); | |
835 #else | |
836 close(source); | |
837 #endif | |
589 phb->func(phb->data, -1, GAIM_INPUT_READ); | 838 phb->func(phb->data, -1, GAIM_INPUT_READ); |
590 g_free(phb->host); | 839 g_free(phb->host); |
591 g_free(phb); | 840 g_free(phb); |
592 return; | 841 return; |
593 } | 842 } |
597 buf[0] = 0x01; /* version 1 */ | 846 buf[0] = 0x01; /* version 1 */ |
598 buf[1] = i; | 847 buf[1] = i; |
599 memcpy(buf + 2, proxyuser, i); | 848 memcpy(buf + 2, proxyuser, i); |
600 buf[2 + i] = j; | 849 buf[2 + i] = j; |
601 memcpy(buf + 2 + i + 1, proxypass, j); | 850 memcpy(buf + 2 + i + 1, proxypass, j); |
851 #ifdef _WIN32 | |
852 if (send(source, buf, 3 + i + j, 0) < 3 + i + j) { | |
853 closesocket(source); | |
854 #else | |
602 if (write(source, buf, 3 + i + j) < 3 + i + j) { | 855 if (write(source, buf, 3 + i + j) < 3 + i + j) { |
603 close(source); | 856 close(source); |
857 #endif | |
604 phb->func(phb->data, -1, GAIM_INPUT_READ); | 858 phb->func(phb->data, -1, GAIM_INPUT_READ); |
605 g_free(phb->host); | 859 g_free(phb->host); |
606 g_free(phb); | 860 g_free(phb); |
607 return; | 861 return; |
608 } | 862 } |
617 { | 871 { |
618 unsigned char buf[512]; | 872 unsigned char buf[512]; |
619 int i; | 873 int i; |
620 struct PHB *phb = data; | 874 struct PHB *phb = data; |
621 unsigned int len; | 875 unsigned int len; |
876 #ifdef _WIN32 | |
877 int werror = WSAETIMEDOUT; | |
878 u_long imode; | |
879 #else | |
622 int error = ETIMEDOUT; | 880 int error = ETIMEDOUT; |
881 #endif | |
623 debug_printf("Connected\n"); | 882 debug_printf("Connected\n"); |
624 if (phb->inpa > 0) | 883 if (phb->inpa > 0) |
625 gaim_input_remove(phb->inpa); | 884 gaim_input_remove(phb->inpa); |
885 #ifdef _WIN32 | |
886 len = sizeof(werror); | |
887 if (getsockopt(source, SOL_SOCKET, SO_ERROR, (char*)&werror, &len) < 0) { | |
888 closesocket(source); | |
889 #else | |
626 len = sizeof(error); | 890 len = sizeof(error); |
627 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 891 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
628 close(source); | 892 close(source); |
629 phb->func(phb->data, -1, GAIM_INPUT_READ); | 893 #endif |
630 g_free(phb->host); | 894 phb->func(phb->data, -1, GAIM_INPUT_READ); |
631 g_free(phb); | 895 g_free(phb->host); |
632 return; | 896 g_free(phb); |
897 return; | |
898 #ifdef _WIN32 | |
899 } else | |
900 WSASetLastError(werror); | |
901 imode=0; | |
902 ioctlsocket(source, FIONBIO, &imode); | |
903 #else | |
633 } | 904 } |
634 fcntl(source, F_SETFL, 0); | 905 fcntl(source, F_SETFL, 0); |
906 #endif | |
635 | 907 |
636 i = 0; | 908 i = 0; |
637 buf[0] = 0x05; /* SOCKS version 5 */ | 909 buf[0] = 0x05; /* SOCKS version 5 */ |
638 if (proxyuser[0]) { | 910 if (proxyuser[0]) { |
639 buf[1] = 0x02; /* two methods */ | 911 buf[1] = 0x02; /* two methods */ |
643 } else { | 915 } else { |
644 buf[1] = 0x01; | 916 buf[1] = 0x01; |
645 buf[2] = 0x00; | 917 buf[2] = 0x00; |
646 i = 3; | 918 i = 3; |
647 } | 919 } |
648 | 920 #ifdef _WIN32 |
921 if (send(source, buf, i, 0) < i) { | |
922 #else | |
649 if (write(source, buf, i) < i) { | 923 if (write(source, buf, i) < i) { |
924 #endif | |
650 debug_printf("unable to write\n"); | 925 debug_printf("unable to write\n"); |
651 close(source); | 926 #ifdef _WIN32 |
927 closesocket(source); | |
928 #else | |
929 close(source); | |
930 #endif | |
652 phb->func(phb->data, -1, GAIM_INPUT_READ); | 931 phb->func(phb->data, -1, GAIM_INPUT_READ); |
653 g_free(phb->host); | 932 g_free(phb->host); |
654 g_free(phb); | 933 g_free(phb); |
655 return; | 934 return; |
656 } | 935 } |
660 | 939 |
661 static int proxy_connect_socks5(char *host, unsigned short port, struct PHB *phb) | 940 static int proxy_connect_socks5(char *host, unsigned short port, struct PHB *phb) |
662 { | 941 { |
663 struct sockaddr_in *sin; | 942 struct sockaddr_in *sin; |
664 int fd = -1; | 943 int fd = -1; |
944 #ifdef _WIN32 | |
945 u_long imode; | |
946 int werrno; | |
947 #endif | |
665 | 948 |
666 debug_printf("connecting to %s:%d via %s:%d using SOCKS5\n", host, port, proxyhost, proxyport); | 949 debug_printf("connecting to %s:%d via %s:%d using SOCKS5\n", host, port, proxyhost, proxyport); |
667 | 950 |
668 if (!(sin = gaim_gethostbyname(proxyhost, proxyport))) { | 951 if (!(sin = gaim_gethostbyname(proxyhost, proxyport))) { |
669 g_free(phb); | 952 g_free(phb); |
676 } | 959 } |
677 | 960 |
678 phb->host = g_strdup(host); | 961 phb->host = g_strdup(host); |
679 phb->port = port; | 962 phb->port = port; |
680 | 963 |
964 #ifdef _WIN32 | |
965 imode=1; | |
966 ioctlsocket(fd, FIONBIO, &imode); | |
967 #else | |
681 fcntl(fd, F_SETFL, O_NONBLOCK); | 968 fcntl(fd, F_SETFL, O_NONBLOCK); |
969 #endif | |
682 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { | 970 if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { |
971 #ifdef _WIN32 | |
972 werrno = WSAGetLastError(); | |
973 if ((werrno == WSAEINPROGRESS) || (werrno == WSAEINTR)) { | |
974 #else | |
683 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 975 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
976 #endif | |
684 debug_printf("Connect would have blocked\n"); | 977 debug_printf("Connect would have blocked\n"); |
685 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb); | 978 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb); |
686 } else { | 979 } else { |
980 #ifdef _WIN32 | |
981 closesocket(fd); | |
982 #else | |
687 close(fd); | 983 close(fd); |
984 #endif | |
688 g_free(phb->host); | 985 g_free(phb->host); |
689 g_free(phb); | 986 g_free(phb); |
690 return -1; | 987 return -1; |
691 } | 988 } |
692 } else { | 989 } else { |
693 unsigned int len; | 990 unsigned int len; |
991 #ifdef _WIN32 | |
992 int werror = WSAETIMEDOUT; | |
993 #else | |
694 int error = ETIMEDOUT; | 994 int error = ETIMEDOUT; |
995 #endif | |
695 debug_printf("Connect didn't block\n"); | 996 debug_printf("Connect didn't block\n"); |
997 #ifdef _WIN32 | |
998 len = sizeof(werror); | |
999 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&werror, &len) < 0) { | |
1000 closesocket(fd); | |
1001 #else | |
696 len = sizeof(error); | 1002 len = sizeof(error); |
697 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1003 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
698 close(fd); | 1004 close(fd); |
1005 #endif | |
699 g_free(phb->host); | 1006 g_free(phb->host); |
700 g_free(phb); | 1007 g_free(phb); |
701 return -1; | 1008 return -1; |
1009 #ifdef _WIN32 | |
1010 } else | |
1011 WSASetLastError(werror); | |
1012 imode=0; | |
1013 ioctlsocket(fd, FIONBIO, &imode); | |
1014 #else | |
702 } | 1015 } |
703 fcntl(fd, F_SETFL, 0); | 1016 fcntl(fd, F_SETFL, 0); |
1017 #endif | |
704 s5_canwrite(phb, fd, GAIM_INPUT_WRITE); | 1018 s5_canwrite(phb, fd, GAIM_INPUT_WRITE); |
705 } | 1019 } |
706 | 1020 |
707 return fd; | 1021 return fd; |
708 } | 1022 } |
715 | 1029 |
716 if (!host || !port || (port == -1) || !func) { | 1030 if (!host || !port || (port == -1) || !func) { |
717 g_free(phb); | 1031 g_free(phb); |
718 return -1; | 1032 return -1; |
719 } | 1033 } |
720 | 1034 #ifndef _WIN32 |
721 sethostent(1); | 1035 sethostent(1); |
722 | 1036 #endif |
723 if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1)) | 1037 if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1)) |
724 return proxy_connect_none(host, port, phb); | 1038 return proxy_connect_none(host, port, phb); |
725 else if (proxytype == PROXY_HTTP) | 1039 else if (proxytype == PROXY_HTTP) |
726 return proxy_connect_http(host, port, phb); | 1040 return proxy_connect_http(host, port, phb); |
727 else if (proxytype == PROXY_SOCKS4) | 1041 else if (proxytype == PROXY_SOCKS4) |
730 return proxy_connect_socks5(host, port, phb); | 1044 return proxy_connect_socks5(host, port, phb); |
731 | 1045 |
732 g_free(phb); | 1046 g_free(phb); |
733 return -1; | 1047 return -1; |
734 } | 1048 } |
1049 |