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