Mercurial > pidgin.yaz
comparison libgaim/proxy.c @ 14262:baff095b146c
[gaim-migrate @ 16944]
Rename GaimProxyConnectInfo to GaimProxyConnectData, and change the
variables from connect_info to connect_data. Sorry, but I wanted
to get this right before it becomes permanent.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 21 Aug 2006 05:25:44 +0000 |
parents | f189327b9968 |
children | 4ae3c2913c3e |
comparison
equal
deleted
inserted
replaced
14261:bb060cdc23d1 | 14262:baff095b146c |
---|---|
37 #include "ntlm.h" | 37 #include "ntlm.h" |
38 #include "prefs.h" | 38 #include "prefs.h" |
39 #include "proxy.h" | 39 #include "proxy.h" |
40 #include "util.h" | 40 #include "util.h" |
41 | 41 |
42 struct _GaimProxyConnectInfo { | 42 struct _GaimProxyConnectData { |
43 GaimProxyConnectFunction connect_cb; | 43 GaimProxyConnectFunction connect_cb; |
44 gpointer data; | 44 gpointer data; |
45 char *host; | 45 char *host; |
46 int port; | 46 int port; |
47 int fd; | 47 int fd; |
85 /* | 85 /* |
86 * TODO: Once all callers of gaim_proxy_connect() are keeping track | 86 * TODO: Once all callers of gaim_proxy_connect() are keeping track |
87 * of the return value from that function this linked list | 87 * of the return value from that function this linked list |
88 * will no longer be needed. | 88 * will no longer be needed. |
89 */ | 89 */ |
90 static GSList *connect_infos = NULL; | 90 static GSList *connect_datas = NULL; |
91 | 91 |
92 static void try_connect(GaimProxyConnectInfo *connect_info); | 92 static void try_connect(GaimProxyConnectData *connect_data); |
93 | 93 |
94 /************************************************************************** | 94 /************************************************************************** |
95 * Proxy structure API | 95 * Proxy structure API |
96 **************************************************************************/ | 96 **************************************************************************/ |
97 GaimProxyInfo * | 97 GaimProxyInfo * |
279 * address fails. We close the socket, remove the watcher and get | 279 * address fails. We close the socket, remove the watcher and get |
280 * rid of input and output buffers. Normally try_connect() will | 280 * rid of input and output buffers. Normally try_connect() will |
281 * be called immediately after this. | 281 * be called immediately after this. |
282 */ | 282 */ |
283 static void | 283 static void |
284 gaim_proxy_connect_info_disconnect(GaimProxyConnectInfo *connect_info) | 284 gaim_proxy_connect_data_disconnect(GaimProxyConnectData *connect_data) |
285 { | 285 { |
286 if (connect_info->inpa > 0) | 286 if (connect_data->inpa > 0) |
287 { | 287 { |
288 gaim_input_remove(connect_info->inpa); | 288 gaim_input_remove(connect_data->inpa); |
289 connect_info->inpa = 0; | 289 connect_data->inpa = 0; |
290 } | 290 } |
291 | 291 |
292 if (connect_info->fd >= 0) | 292 if (connect_data->fd >= 0) |
293 { | 293 { |
294 close(connect_info->fd); | 294 close(connect_data->fd); |
295 connect_info->fd = -1; | 295 connect_data->fd = -1; |
296 } | 296 } |
297 | 297 |
298 g_free(connect_info->write_buffer); | 298 g_free(connect_data->write_buffer); |
299 connect_info->write_buffer = NULL; | 299 connect_data->write_buffer = NULL; |
300 | 300 |
301 g_free(connect_info->read_buffer); | 301 g_free(connect_data->read_buffer); |
302 connect_info->read_buffer = NULL; | 302 connect_data->read_buffer = NULL; |
303 } | 303 } |
304 | 304 |
305 static void | 305 static void |
306 gaim_proxy_connect_info_destroy(GaimProxyConnectInfo *connect_info) | 306 gaim_proxy_connect_data_destroy(GaimProxyConnectData *connect_data) |
307 { | 307 { |
308 gaim_proxy_connect_info_disconnect(connect_info); | 308 gaim_proxy_connect_data_disconnect(connect_data); |
309 | 309 |
310 connect_infos = g_slist_remove(connect_infos, connect_info); | 310 connect_datas = g_slist_remove(connect_datas, connect_data); |
311 | 311 |
312 if (connect_info->query_data != NULL) | 312 if (connect_data->query_data != NULL) |
313 gaim_dnsquery_destroy(connect_info->query_data); | 313 gaim_dnsquery_destroy(connect_data->query_data); |
314 | 314 |
315 while (connect_info->hosts != NULL) | 315 while (connect_data->hosts != NULL) |
316 { | 316 { |
317 /* Discard the length... */ | 317 /* Discard the length... */ |
318 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); | 318 connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data); |
319 /* Free the address... */ | 319 /* Free the address... */ |
320 g_free(connect_info->hosts->data); | 320 g_free(connect_data->hosts->data); |
321 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); | 321 connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data); |
322 } | 322 } |
323 | 323 |
324 g_free(connect_info->host); | 324 g_free(connect_data->host); |
325 g_free(connect_info); | 325 g_free(connect_data); |
326 } | 326 } |
327 | 327 |
328 static void | 328 static void |
329 gaim_proxy_connect_info_connected(GaimProxyConnectInfo *connect_info) | 329 gaim_proxy_connect_data_connected(GaimProxyConnectData *connect_data) |
330 { | 330 { |
331 connect_info->connect_cb(connect_info->data, connect_info->fd, NULL); | 331 connect_data->connect_cb(connect_data->data, connect_data->fd, NULL); |
332 | 332 |
333 /* | 333 /* |
334 * We've passed the file descriptor to the protocol, so it's no longer | 334 * We've passed the file descriptor to the protocol, so it's no longer |
335 * our responsibility, and we should be careful not to free it when | 335 * our responsibility, and we should be careful not to free it when |
336 * we destroy the connect_info. | 336 * we destroy the connect_data. |
337 */ | 337 */ |
338 connect_info->fd = -1; | 338 connect_data->fd = -1; |
339 | 339 |
340 gaim_proxy_connect_info_destroy(connect_info); | 340 gaim_proxy_connect_data_destroy(connect_data); |
341 } | 341 } |
342 | 342 |
343 /** | 343 /** |
344 * @param error An error message explaining why the connection | 344 * @param error An error message explaining why the connection |
345 * failed. This will be passed to the callback function | 345 * failed. This will be passed to the callback function |
348 /* | 348 /* |
349 * TODO: Make sure all callers of this function pass a really really | 349 * TODO: Make sure all callers of this function pass a really really |
350 * good error_message. | 350 * good error_message. |
351 */ | 351 */ |
352 static void | 352 static void |
353 gaim_proxy_connect_info_error(GaimProxyConnectInfo *connect_info, const gchar *error_message) | 353 gaim_proxy_connect_data_error(GaimProxyConnectData *connect_data, const gchar *error_message) |
354 { | 354 { |
355 connect_info->connect_cb(connect_info->data, -1, error_message); | 355 connect_data->connect_cb(connect_data->data, -1, error_message); |
356 gaim_proxy_connect_info_destroy(connect_info); | 356 gaim_proxy_connect_data_destroy(connect_data); |
357 } | 357 } |
358 | 358 |
359 static void | 359 static void |
360 no_one_calls(gpointer data, gint source, GaimInputCondition cond) | 360 no_one_calls(gpointer data, gint source, GaimInputCondition cond) |
361 { | 361 { |
362 GaimProxyConnectInfo *connect_info = data; | 362 GaimProxyConnectData *connect_data = data; |
363 socklen_t len; | 363 socklen_t len; |
364 int error=0, ret; | 364 int error=0, ret; |
365 | 365 |
366 gaim_debug_info("proxy", "Connected.\n"); | 366 gaim_debug_info("proxy", "Connected.\n"); |
367 | 367 |
376 * | 376 * |
377 * (error == EINPROGRESS can happen after a select because the kernel can | 377 * (error == EINPROGRESS can happen after a select because the kernel can |
378 * be overly optimistic sometimes. select is just a hint that you might be | 378 * be overly optimistic sometimes. select is just a hint that you might be |
379 * able to do something.) | 379 * able to do something.) |
380 */ | 380 */ |
381 ret = getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len); | 381 ret = getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len); |
382 if (ret == 0 && error == EINPROGRESS) | 382 if (ret == 0 && error == EINPROGRESS) |
383 return; /* we'll be called again later */ | 383 return; /* we'll be called again later */ |
384 if (ret < 0 || error != 0) { | 384 if (ret < 0 || error != 0) { |
385 if (ret!=0) | 385 if (ret!=0) |
386 error = errno; | 386 error = errno; |
387 | 387 |
388 gaim_debug_error("proxy", | 388 gaim_debug_error("proxy", |
389 "getsockopt SO_ERROR check: %s\n", strerror(error)); | 389 "getsockopt SO_ERROR check: %s\n", strerror(error)); |
390 | 390 |
391 gaim_proxy_connect_info_disconnect(connect_info); | 391 gaim_proxy_connect_data_disconnect(connect_data); |
392 try_connect(connect_info); | 392 try_connect(connect_data); |
393 return; | 393 return; |
394 } | 394 } |
395 | 395 |
396 gaim_input_remove(connect_info->inpa); | 396 gaim_input_remove(connect_data->inpa); |
397 connect_info->inpa = 0; | 397 connect_data->inpa = 0; |
398 | 398 |
399 gaim_proxy_connect_info_connected(connect_info); | 399 gaim_proxy_connect_data_connected(connect_data); |
400 } | 400 } |
401 | 401 |
402 static gboolean | 402 static gboolean |
403 clean_connect(gpointer data) | 403 clean_connect(gpointer data) |
404 { | 404 { |
405 GaimProxyConnectInfo *connect_info; | 405 GaimProxyConnectData *connect_data; |
406 | 406 |
407 connect_info = data; | 407 connect_data = data; |
408 gaim_proxy_connect_info_connected(connect_info); | 408 gaim_proxy_connect_data_connected(connect_data); |
409 | 409 |
410 return FALSE; | 410 return FALSE; |
411 } | 411 } |
412 | 412 |
413 static int | 413 static int |
414 proxy_connect_none(GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) | 414 proxy_connect_none(GaimProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) |
415 { | 415 { |
416 gaim_debug_info("proxy", "Connecting to %s:%d with no proxy\n", | 416 gaim_debug_info("proxy", "Connecting to %s:%d with no proxy\n", |
417 connect_info->host, connect_info->port); | 417 connect_data->host, connect_data->port); |
418 | 418 |
419 connect_info->fd = socket(addr->sa_family, SOCK_STREAM, 0); | 419 connect_data->fd = socket(addr->sa_family, SOCK_STREAM, 0); |
420 if (connect_info->fd < 0) | 420 if (connect_data->fd < 0) |
421 { | 421 { |
422 gaim_debug_error("proxy", | 422 gaim_debug_error("proxy", |
423 "Unable to create socket: %s\n", strerror(errno)); | 423 "Unable to create socket: %s\n", strerror(errno)); |
424 return -1; | 424 return -1; |
425 } | 425 } |
426 fcntl(connect_info->fd, F_SETFL, O_NONBLOCK); | 426 fcntl(connect_data->fd, F_SETFL, O_NONBLOCK); |
427 #ifndef _WIN32 | 427 #ifndef _WIN32 |
428 fcntl(connect_info->fd, F_SETFD, FD_CLOEXEC); | 428 fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC); |
429 #endif | 429 #endif |
430 | 430 |
431 if (connect(connect_info->fd, (struct sockaddr *)addr, addrlen) != 0) | 431 if (connect(connect_data->fd, (struct sockaddr *)addr, addrlen) != 0) |
432 { | 432 { |
433 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 433 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
434 gaim_debug_info("proxy", "Connection in progress\n"); | 434 gaim_debug_info("proxy", "Connection in progress\n"); |
435 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, no_one_calls, connect_info); | 435 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, no_one_calls, connect_data); |
436 } | 436 } |
437 else { | 437 else { |
438 gaim_debug_error("proxy", | 438 gaim_debug_error("proxy", |
439 "Connect failed: %s\n", strerror(errno)); | 439 "Connect failed: %s\n", strerror(errno)); |
440 close(connect_info->fd); | 440 close(connect_data->fd); |
441 connect_info->fd = -1; | 441 connect_data->fd = -1; |
442 return -1; | 442 return -1; |
443 } | 443 } |
444 } | 444 } |
445 else | 445 else |
446 { | 446 { |
449 */ | 449 */ |
450 socklen_t len; | 450 socklen_t len; |
451 int error = ETIMEDOUT; | 451 int error = ETIMEDOUT; |
452 gaim_debug_info("proxy", "Connected immediately.\n"); | 452 gaim_debug_info("proxy", "Connected immediately.\n"); |
453 len = sizeof(error); | 453 len = sizeof(error); |
454 if (getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) | 454 if (getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
455 { | 455 { |
456 gaim_debug_error("proxy", "getsockopt failed.\n"); | 456 gaim_debug_error("proxy", "getsockopt failed.\n"); |
457 close(connect_info->fd); | 457 close(connect_data->fd); |
458 connect_info->fd = -1; | 458 connect_data->fd = -1; |
459 return -1; | 459 return -1; |
460 } | 460 } |
461 | 461 |
462 /* | 462 /* |
463 * We want to call the "connected" callback eventually, but we | 463 * We want to call the "connected" callback eventually, but we |
464 * don't want to call it before we return, just in case. | 464 * don't want to call it before we return, just in case. |
465 */ | 465 */ |
466 gaim_timeout_add(10, clean_connect, connect_info); | 466 gaim_timeout_add(10, clean_connect, connect_data); |
467 } | 467 } |
468 | 468 |
469 return connect_info->fd; | 469 return connect_data->fd; |
470 } | 470 } |
471 | 471 |
472 static void | 472 static void |
473 proxy_do_write(gpointer data, gint source, GaimInputCondition cond) | 473 proxy_do_write(gpointer data, gint source, GaimInputCondition cond) |
474 { | 474 { |
475 GaimProxyConnectInfo *connect_info = data; | 475 GaimProxyConnectData *connect_data = data; |
476 const guchar *request = connect_info->write_buffer + connect_info->written_len; | 476 const guchar *request = connect_data->write_buffer + connect_data->written_len; |
477 gsize request_len = connect_info->write_buf_len - connect_info->written_len; | 477 gsize request_len = connect_data->write_buf_len - connect_data->written_len; |
478 | 478 |
479 int ret = write(connect_info->fd, request, request_len); | 479 int ret = write(connect_data->fd, request, request_len); |
480 | 480 |
481 if(ret < 0 && errno == EAGAIN) | 481 if(ret < 0 && errno == EAGAIN) |
482 return; | 482 return; |
483 else if(ret < 0) { | 483 else if(ret < 0) { |
484 gaim_proxy_connect_info_disconnect(connect_info); | 484 gaim_proxy_connect_data_disconnect(connect_data); |
485 try_connect(connect_info); | 485 try_connect(connect_data); |
486 return; | 486 return; |
487 } else if (ret < request_len) { | 487 } else if (ret < request_len) { |
488 connect_info->written_len += ret; | 488 connect_data->written_len += ret; |
489 return; | 489 return; |
490 } | 490 } |
491 | 491 |
492 gaim_input_remove(connect_info->inpa); | 492 gaim_input_remove(connect_data->inpa); |
493 g_free(connect_info->write_buffer); | 493 g_free(connect_data->write_buffer); |
494 connect_info->write_buffer = NULL; | 494 connect_data->write_buffer = NULL; |
495 | 495 |
496 /* register the response handler for the response */ | 496 /* register the response handler for the response */ |
497 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_READ, connect_info->read_cb, connect_info); | 497 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_READ, connect_data->read_cb, connect_data); |
498 } | 498 } |
499 | 499 |
500 #define HTTP_GOODSTRING "HTTP/1.0 200" | 500 #define HTTP_GOODSTRING "HTTP/1.0 200" |
501 #define HTTP_GOODSTRING2 "HTTP/1.1 200" | 501 #define HTTP_GOODSTRING2 "HTTP/1.1 200" |
502 | 502 |
504 static void | 504 static void |
505 http_canread(gpointer data, gint source, GaimInputCondition cond) | 505 http_canread(gpointer data, gint source, GaimInputCondition cond) |
506 { | 506 { |
507 int len, headers_len, status = 0; | 507 int len, headers_len, status = 0; |
508 gboolean error; | 508 gboolean error; |
509 GaimProxyConnectInfo *connect_info = data; | 509 GaimProxyConnectData *connect_data = data; |
510 guchar *p; | 510 guchar *p; |
511 gsize max_read; | 511 gsize max_read; |
512 gchar *msg; | 512 gchar *msg; |
513 | 513 |
514 if(connect_info->read_buffer == NULL) { | 514 if(connect_data->read_buffer == NULL) { |
515 connect_info->read_buf_len = 8192; | 515 connect_data->read_buf_len = 8192; |
516 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); | 516 connect_data->read_buffer = g_malloc(connect_data->read_buf_len); |
517 connect_info->read_len = 0; | 517 connect_data->read_len = 0; |
518 } | 518 } |
519 | 519 |
520 p = connect_info->read_buffer + connect_info->read_len; | 520 p = connect_data->read_buffer + connect_data->read_len; |
521 max_read = connect_info->read_buf_len - connect_info->read_len - 1; | 521 max_read = connect_data->read_buf_len - connect_data->read_len - 1; |
522 | 522 |
523 len = read(connect_info->fd, p, max_read); | 523 len = read(connect_data->fd, p, max_read); |
524 if(len < 0 && errno == EAGAIN) | 524 if(len < 0 && errno == EAGAIN) |
525 return; | 525 return; |
526 else if(len <= 0) { | 526 else if(len <= 0) { |
527 gaim_proxy_connect_info_error(connect_info, _("Lost connection with server for an unknown reason.")); | 527 gaim_proxy_connect_data_error(connect_data, _("Lost connection with server for an unknown reason.")); |
528 return; | 528 return; |
529 } else { | 529 } else { |
530 connect_info->read_len += len; | 530 connect_data->read_len += len; |
531 } | 531 } |
532 p[len] = '\0'; | 532 p[len] = '\0'; |
533 | 533 |
534 if((p = (guchar *)g_strstr_len((const gchar *)connect_info->read_buffer, connect_info->read_len, "\r\n\r\n"))) { | 534 if((p = (guchar *)g_strstr_len((const gchar *)connect_data->read_buffer, connect_data->read_len, "\r\n\r\n"))) { |
535 *p = '\0'; | 535 *p = '\0'; |
536 headers_len = (p - connect_info->read_buffer) + 4; | 536 headers_len = (p - connect_data->read_buffer) + 4; |
537 } else if(len == max_read) | 537 } else if(len == max_read) |
538 headers_len = len; | 538 headers_len = len; |
539 else | 539 else |
540 return; | 540 return; |
541 | 541 |
542 error = strncmp((const char *)connect_info->read_buffer, "HTTP/", 5) != 0; | 542 error = strncmp((const char *)connect_data->read_buffer, "HTTP/", 5) != 0; |
543 if (!error) | 543 if (!error) |
544 { | 544 { |
545 int major; | 545 int major; |
546 p = connect_info->read_buffer + 5; | 546 p = connect_data->read_buffer + 5; |
547 major = strtol((const char *)p, (char **)&p, 10); | 547 major = strtol((const char *)p, (char **)&p, 10); |
548 error = (major == 0) || (*p != '.'); | 548 error = (major == 0) || (*p != '.'); |
549 if(!error) { | 549 if(!error) { |
550 int minor; | 550 int minor; |
551 p++; | 551 p++; |
558 } | 558 } |
559 } | 559 } |
560 } | 560 } |
561 | 561 |
562 /* Read the contents */ | 562 /* Read the contents */ |
563 p = (guchar *)g_strrstr((const gchar *)connect_info->read_buffer, "Content-Length: "); | 563 p = (guchar *)g_strrstr((const gchar *)connect_data->read_buffer, "Content-Length: "); |
564 if (p != NULL) | 564 if (p != NULL) |
565 { | 565 { |
566 gchar *tmp; | 566 gchar *tmp; |
567 int len = 0; | 567 int len = 0; |
568 char tmpc; | 568 char tmpc; |
573 len = atoi((const char *)p); | 573 len = atoi((const char *)p); |
574 if(tmp) | 574 if(tmp) |
575 *tmp = '\r'; | 575 *tmp = '\r'; |
576 | 576 |
577 /* Compensate for what has already been read */ | 577 /* Compensate for what has already been read */ |
578 len -= connect_info->read_len - headers_len; | 578 len -= connect_data->read_len - headers_len; |
579 /* I'm assuming that we're doing this to prevent the server from | 579 /* I'm assuming that we're doing this to prevent the server from |
580 complaining / breaking since we don't read the whole page */ | 580 complaining / breaking since we don't read the whole page */ |
581 while(len--) { | 581 while(len--) { |
582 /* TODO: deal with EAGAIN (and other errors) better */ | 582 /* TODO: deal with EAGAIN (and other errors) better */ |
583 if (read(connect_info->fd, &tmpc, 1) < 0 && errno != EAGAIN) | 583 if (read(connect_data->fd, &tmpc, 1) < 0 && errno != EAGAIN) |
584 break; | 584 break; |
585 } | 585 } |
586 } | 586 } |
587 | 587 |
588 if (error) | 588 if (error) |
589 { | 589 { |
590 msg = g_strdup_printf("Unable to parse response from HTTP proxy: %s\n", | 590 msg = g_strdup_printf("Unable to parse response from HTTP proxy: %s\n", |
591 connect_info->read_buffer); | 591 connect_data->read_buffer); |
592 gaim_proxy_connect_info_error(connect_info, msg); | 592 gaim_proxy_connect_data_error(connect_data, msg); |
593 g_free(msg); | 593 g_free(msg); |
594 return; | 594 return; |
595 } | 595 } |
596 else if (status != 200) | 596 else if (status != 200) |
597 { | 597 { |
598 gaim_debug_error("proxy", | 598 gaim_debug_error("proxy", |
599 "Proxy server replied with:\n%s\n", | 599 "Proxy server replied with:\n%s\n", |
600 connect_info->read_buffer); | 600 connect_data->read_buffer); |
601 | 601 |
602 | 602 |
603 if(status == 407 /* Proxy Auth */) { | 603 if(status == 407 /* Proxy Auth */) { |
604 gchar *ntlm; | 604 gchar *ntlm; |
605 if((ntlm = g_strrstr((const gchar *)connect_info->read_buffer, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */ | 605 if((ntlm = g_strrstr((const gchar *)connect_data->read_buffer, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */ |
606 gchar *tmp = ntlm; | 606 gchar *tmp = ntlm; |
607 guint8 *nonce; | 607 guint8 *nonce; |
608 gchar *domain = (gchar*)gaim_proxy_info_get_username(connect_info->gpi); | 608 gchar *domain = (gchar*)gaim_proxy_info_get_username(connect_data->gpi); |
609 gchar *username; | 609 gchar *username; |
610 gchar *request; | 610 gchar *request; |
611 gchar *response; | 611 gchar *response; |
612 username = strchr(domain, '\\'); | 612 username = strchr(domain, '\\'); |
613 if (username == NULL) | 613 if (username == NULL) |
614 { | 614 { |
615 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 615 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
616 gaim_proxy_connect_info_error(connect_info, msg); | 616 gaim_proxy_connect_data_error(connect_data, msg); |
617 g_free(msg); | 617 g_free(msg); |
618 return; | 618 return; |
619 } | 619 } |
620 *username = '\0'; | 620 *username = '\0'; |
621 username++; | 621 username++; |
622 ntlm += strlen("Proxy-Authenticate: NTLM "); | 622 ntlm += strlen("Proxy-Authenticate: NTLM "); |
623 while(*tmp != '\r' && *tmp != '\0') tmp++; | 623 while(*tmp != '\r' && *tmp != '\0') tmp++; |
624 *tmp = '\0'; | 624 *tmp = '\0'; |
625 nonce = gaim_ntlm_parse_type2(ntlm, NULL); | 625 nonce = gaim_ntlm_parse_type2(ntlm, NULL); |
626 response = gaim_ntlm_gen_type3(username, | 626 response = gaim_ntlm_gen_type3(username, |
627 (gchar*) gaim_proxy_info_get_password(connect_info->gpi), | 627 (gchar*) gaim_proxy_info_get_password(connect_data->gpi), |
628 (gchar*) gaim_proxy_info_get_host(connect_info->gpi), | 628 (gchar*) gaim_proxy_info_get_host(connect_data->gpi), |
629 domain, nonce, NULL); | 629 domain, nonce, NULL); |
630 username--; | 630 username--; |
631 *username = '\\'; | 631 *username = '\\'; |
632 request = g_strdup_printf( | 632 request = g_strdup_printf( |
633 "CONNECT %s:%d HTTP/1.1\r\n" | 633 "CONNECT %s:%d HTTP/1.1\r\n" |
634 "Host: %s:%d\r\n" | 634 "Host: %s:%d\r\n" |
635 "Proxy-Authorization: NTLM %s\r\n" | 635 "Proxy-Authorization: NTLM %s\r\n" |
636 "Proxy-Connection: Keep-Alive\r\n\r\n", | 636 "Proxy-Connection: Keep-Alive\r\n\r\n", |
637 connect_info->host, connect_info->port, connect_info->host, | 637 connect_data->host, connect_data->port, connect_data->host, |
638 connect_info->port, response); | 638 connect_data->port, response); |
639 g_free(response); | 639 g_free(response); |
640 | 640 |
641 gaim_input_remove(connect_info->inpa); | 641 gaim_input_remove(connect_data->inpa); |
642 g_free(connect_info->read_buffer); | 642 g_free(connect_data->read_buffer); |
643 connect_info->read_buffer = NULL; | 643 connect_data->read_buffer = NULL; |
644 | 644 |
645 connect_info->write_buffer = (guchar *)request; | 645 connect_data->write_buffer = (guchar *)request; |
646 connect_info->write_buf_len = strlen(request); | 646 connect_data->write_buf_len = strlen(request); |
647 connect_info->written_len = 0; | 647 connect_data->written_len = 0; |
648 | 648 |
649 connect_info->read_cb = http_canread; | 649 connect_data->read_cb = http_canread; |
650 | 650 |
651 connect_info->inpa = gaim_input_add(connect_info->fd, | 651 connect_data->inpa = gaim_input_add(connect_data->fd, |
652 GAIM_INPUT_WRITE, proxy_do_write, connect_info); | 652 GAIM_INPUT_WRITE, proxy_do_write, connect_data); |
653 | 653 |
654 proxy_do_write(connect_info, connect_info->fd, cond); | 654 proxy_do_write(connect_data, connect_data->fd, cond); |
655 return; | 655 return; |
656 } else if((ntlm = g_strrstr((const char *)connect_info->read_buffer, "Proxy-Authenticate: NTLM"))) { /* Empty message */ | 656 } else if((ntlm = g_strrstr((const char *)connect_data->read_buffer, "Proxy-Authenticate: NTLM"))) { /* Empty message */ |
657 gchar request[2048]; | 657 gchar request[2048]; |
658 gchar *domain = (gchar*) gaim_proxy_info_get_username(connect_info->gpi); | 658 gchar *domain = (gchar*) gaim_proxy_info_get_username(connect_data->gpi); |
659 gchar *username; | 659 gchar *username; |
660 int request_len; | 660 int request_len; |
661 username = strchr(domain, '\\'); | 661 username = strchr(domain, '\\'); |
662 if (username == NULL) | 662 if (username == NULL) |
663 { | 663 { |
664 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 664 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
665 gaim_proxy_connect_info_error(connect_info, msg); | 665 gaim_proxy_connect_data_error(connect_data, msg); |
666 g_free(msg); | 666 g_free(msg); |
667 return; | 667 return; |
668 } | 668 } |
669 *username = '\0'; | 669 *username = '\0'; |
670 | 670 |
671 request_len = g_snprintf(request, sizeof(request), | 671 request_len = g_snprintf(request, sizeof(request), |
672 "CONNECT %s:%d HTTP/1.1\r\n" | 672 "CONNECT %s:%d HTTP/1.1\r\n" |
673 "Host: %s:%d\r\n", | 673 "Host: %s:%d\r\n", |
674 connect_info->host, connect_info->port, | 674 connect_data->host, connect_data->port, |
675 connect_info->host, connect_info->port); | 675 connect_data->host, connect_data->port); |
676 | 676 |
677 g_return_if_fail(request_len < sizeof(request)); | 677 g_return_if_fail(request_len < sizeof(request)); |
678 request_len += g_snprintf(request + request_len, | 678 request_len += g_snprintf(request + request_len, |
679 sizeof(request) - request_len, | 679 sizeof(request) - request_len, |
680 "Proxy-Authorization: NTLM %s\r\n" | 680 "Proxy-Authorization: NTLM %s\r\n" |
681 "Proxy-Connection: Keep-Alive\r\n\r\n", | 681 "Proxy-Connection: Keep-Alive\r\n\r\n", |
682 gaim_ntlm_gen_type1( | 682 gaim_ntlm_gen_type1( |
683 (gchar*) gaim_proxy_info_get_host(connect_info->gpi), | 683 (gchar*) gaim_proxy_info_get_host(connect_data->gpi), |
684 domain)); | 684 domain)); |
685 *username = '\\'; | 685 *username = '\\'; |
686 | 686 |
687 gaim_input_remove(connect_info->inpa); | 687 gaim_input_remove(connect_data->inpa); |
688 g_free(connect_info->read_buffer); | 688 g_free(connect_data->read_buffer); |
689 connect_info->read_buffer = NULL; | 689 connect_data->read_buffer = NULL; |
690 | 690 |
691 connect_info->write_buffer = g_memdup(request, request_len); | 691 connect_data->write_buffer = g_memdup(request, request_len); |
692 connect_info->write_buf_len = request_len; | 692 connect_data->write_buf_len = request_len; |
693 connect_info->written_len = 0; | 693 connect_data->written_len = 0; |
694 | 694 |
695 connect_info->read_cb = http_canread; | 695 connect_data->read_cb = http_canread; |
696 | 696 |
697 connect_info->inpa = gaim_input_add(connect_info->fd, | 697 connect_data->inpa = gaim_input_add(connect_data->fd, |
698 GAIM_INPUT_WRITE, proxy_do_write, connect_info); | 698 GAIM_INPUT_WRITE, proxy_do_write, connect_data); |
699 | 699 |
700 proxy_do_write(connect_info, connect_info->fd, cond); | 700 proxy_do_write(connect_data, connect_data->fd, cond); |
701 return; | 701 return; |
702 } else { | 702 } else { |
703 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 703 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
704 gaim_proxy_connect_info_error(connect_info, msg); | 704 gaim_proxy_connect_data_error(connect_data, msg); |
705 g_free(msg); | 705 g_free(msg); |
706 return; | 706 return; |
707 } | 707 } |
708 } | 708 } |
709 if(status == 403 /* Forbidden */ ) { | 709 if(status == 403 /* Forbidden */ ) { |
710 msg = g_strdup_printf(_("Access denied: HTTP proxy server forbids port %d tunnelling."), connect_info->port); | 710 msg = g_strdup_printf(_("Access denied: HTTP proxy server forbids port %d tunnelling."), connect_data->port); |
711 gaim_proxy_connect_info_error(connect_info, msg); | 711 gaim_proxy_connect_data_error(connect_data, msg); |
712 g_free(msg); | 712 g_free(msg); |
713 } else { | 713 } else { |
714 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 714 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
715 gaim_proxy_connect_info_error(connect_info, msg); | 715 gaim_proxy_connect_data_error(connect_data, msg); |
716 g_free(msg); | 716 g_free(msg); |
717 } | 717 } |
718 } else { | 718 } else { |
719 gaim_input_remove(connect_info->inpa); | 719 gaim_input_remove(connect_data->inpa); |
720 connect_info->inpa = 0; | 720 connect_data->inpa = 0; |
721 g_free(connect_info->read_buffer); | 721 g_free(connect_data->read_buffer); |
722 connect_info->read_buffer = NULL; | 722 connect_data->read_buffer = NULL; |
723 gaim_debug_info("proxy", "HTTP proxy connection established\n"); | 723 gaim_debug_info("proxy", "HTTP proxy connection established\n"); |
724 gaim_proxy_connect_info_connected(connect_info); | 724 gaim_proxy_connect_data_connected(connect_data); |
725 return; | 725 return; |
726 } | 726 } |
727 } | 727 } |
728 | 728 |
729 | 729 |
731 static void | 731 static void |
732 http_canwrite(gpointer data, gint source, GaimInputCondition cond) | 732 http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
733 { | 733 { |
734 char request[8192]; | 734 char request[8192]; |
735 int request_len = 0; | 735 int request_len = 0; |
736 GaimProxyConnectInfo *connect_info = data; | 736 GaimProxyConnectData *connect_data = data; |
737 socklen_t len; | 737 socklen_t len; |
738 int error = ETIMEDOUT; | 738 int error = ETIMEDOUT; |
739 | 739 |
740 gaim_debug_info("http proxy", "Connected.\n"); | 740 gaim_debug_info("http proxy", "Connected.\n"); |
741 | 741 |
742 if (connect_info->inpa > 0) | 742 if (connect_data->inpa > 0) |
743 { | 743 { |
744 gaim_input_remove(connect_info->inpa); | 744 gaim_input_remove(connect_data->inpa); |
745 connect_info->inpa = 0; | 745 connect_data->inpa = 0; |
746 } | 746 } |
747 | 747 |
748 len = sizeof(error); | 748 len = sizeof(error); |
749 | 749 |
750 if (getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 750 if (getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
751 gaim_proxy_connect_info_disconnect(connect_info); | 751 gaim_proxy_connect_data_disconnect(connect_data); |
752 try_connect(connect_info); | 752 try_connect(connect_data); |
753 return; | 753 return; |
754 } | 754 } |
755 | 755 |
756 gaim_debug_info("proxy", "using CONNECT tunnelling for %s:%d\n", | 756 gaim_debug_info("proxy", "using CONNECT tunnelling for %s:%d\n", |
757 connect_info->host, connect_info->port); | 757 connect_data->host, connect_data->port); |
758 request_len = g_snprintf(request, sizeof(request), | 758 request_len = g_snprintf(request, sizeof(request), |
759 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", | 759 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", |
760 connect_info->host, connect_info->port, connect_info->host, connect_info->port); | 760 connect_data->host, connect_data->port, connect_data->host, connect_data->port); |
761 | 761 |
762 if (gaim_proxy_info_get_username(connect_info->gpi) != NULL) { | 762 if (gaim_proxy_info_get_username(connect_data->gpi) != NULL) { |
763 char *t1, *t2; | 763 char *t1, *t2; |
764 t1 = g_strdup_printf("%s:%s", | 764 t1 = g_strdup_printf("%s:%s", |
765 gaim_proxy_info_get_username(connect_info->gpi), | 765 gaim_proxy_info_get_username(connect_data->gpi), |
766 gaim_proxy_info_get_password(connect_info->gpi) ? | 766 gaim_proxy_info_get_password(connect_data->gpi) ? |
767 gaim_proxy_info_get_password(connect_info->gpi) : ""); | 767 gaim_proxy_info_get_password(connect_data->gpi) : ""); |
768 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1)); | 768 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1)); |
769 g_free(t1); | 769 g_free(t1); |
770 g_return_if_fail(request_len < sizeof(request)); | 770 g_return_if_fail(request_len < sizeof(request)); |
771 | 771 |
772 request_len += g_snprintf(request + request_len, | 772 request_len += g_snprintf(request + request_len, |
773 sizeof(request) - request_len, | 773 sizeof(request) - request_len, |
774 "Proxy-Authorization: Basic %s\r\n" | 774 "Proxy-Authorization: Basic %s\r\n" |
775 "Proxy-Authorization: NTLM %s\r\n" | 775 "Proxy-Authorization: NTLM %s\r\n" |
776 "Proxy-Connection: Keep-Alive\r\n", t2, | 776 "Proxy-Connection: Keep-Alive\r\n", t2, |
777 gaim_ntlm_gen_type1( | 777 gaim_ntlm_gen_type1( |
778 (gchar*)gaim_proxy_info_get_host(connect_info->gpi),"")); | 778 (gchar*)gaim_proxy_info_get_host(connect_data->gpi),"")); |
779 g_free(t2); | 779 g_free(t2); |
780 } | 780 } |
781 | 781 |
782 g_return_if_fail(request_len < sizeof(request)); | 782 g_return_if_fail(request_len < sizeof(request)); |
783 strcpy(request + request_len, "\r\n"); | 783 strcpy(request + request_len, "\r\n"); |
784 request_len += 2; | 784 request_len += 2; |
785 connect_info->write_buffer = g_memdup(request, request_len); | 785 connect_data->write_buffer = g_memdup(request, request_len); |
786 connect_info->write_buf_len = request_len; | 786 connect_data->write_buf_len = request_len; |
787 connect_info->written_len = 0; | 787 connect_data->written_len = 0; |
788 | 788 |
789 connect_info->read_cb = http_canread; | 789 connect_data->read_cb = http_canread; |
790 | 790 |
791 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, proxy_do_write, | 791 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, proxy_do_write, |
792 connect_info); | 792 connect_data); |
793 | 793 |
794 proxy_do_write(connect_info, connect_info->fd, cond); | 794 proxy_do_write(connect_data, connect_data->fd, cond); |
795 } | 795 } |
796 | 796 |
797 static int | 797 static int |
798 proxy_connect_http(GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) | 798 proxy_connect_http(GaimProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) |
799 { | 799 { |
800 gaim_debug_info("http proxy", | 800 gaim_debug_info("http proxy", |
801 "Connecting to %s:%d via %s:%d using HTTP\n", | 801 "Connecting to %s:%d via %s:%d using HTTP\n", |
802 (connect_info->host ? connect_info->host : "(null)"), connect_info->port, | 802 (connect_data->host ? connect_data->host : "(null)"), connect_data->port, |
803 (gaim_proxy_info_get_host(connect_info->gpi) ? gaim_proxy_info_get_host(connect_info->gpi) : "(null)"), | 803 (gaim_proxy_info_get_host(connect_data->gpi) ? gaim_proxy_info_get_host(connect_data->gpi) : "(null)"), |
804 gaim_proxy_info_get_port(connect_info->gpi)); | 804 gaim_proxy_info_get_port(connect_data->gpi)); |
805 | 805 |
806 connect_info->fd = socket(addr->sa_family, SOCK_STREAM, 0); | 806 connect_data->fd = socket(addr->sa_family, SOCK_STREAM, 0); |
807 if (connect_info->fd < 0) | 807 if (connect_data->fd < 0) |
808 return -1; | 808 return -1; |
809 | 809 |
810 fcntl(connect_info->fd, F_SETFL, O_NONBLOCK); | 810 fcntl(connect_data->fd, F_SETFL, O_NONBLOCK); |
811 #ifndef _WIN32 | 811 #ifndef _WIN32 |
812 fcntl(connect_info->fd, F_SETFD, FD_CLOEXEC); | 812 fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC); |
813 #endif | 813 #endif |
814 | 814 |
815 if (connect(connect_info->fd, addr, addrlen) != 0) | 815 if (connect(connect_data->fd, addr, addrlen) != 0) |
816 { | 816 { |
817 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 817 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
818 gaim_debug_info("http proxy", "Connection in progress\n"); | 818 gaim_debug_info("http proxy", "Connection in progress\n"); |
819 | 819 |
820 if (connect_info->port != 80) { | 820 if (connect_data->port != 80) { |
821 /* we need to do CONNECT first */ | 821 /* we need to do CONNECT first */ |
822 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, | 822 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, |
823 http_canwrite, connect_info); | 823 http_canwrite, connect_data); |
824 } else { | 824 } else { |
825 gaim_debug_info("proxy", "HTTP proxy connection established\n"); | 825 gaim_debug_info("proxy", "HTTP proxy connection established\n"); |
826 gaim_proxy_connect_info_connected(connect_info); | 826 gaim_proxy_connect_data_connected(connect_data); |
827 } | 827 } |
828 } else { | 828 } else { |
829 close(connect_info->fd); | 829 close(connect_data->fd); |
830 connect_info->fd = -1; | 830 connect_data->fd = -1; |
831 return -1; | 831 return -1; |
832 } | 832 } |
833 } | 833 } |
834 else { | 834 else { |
835 socklen_t len; | 835 socklen_t len; |
836 int error = ETIMEDOUT; | 836 int error = ETIMEDOUT; |
837 | 837 |
838 gaim_debug_info("http proxy", "Connected immediately.\n"); | 838 gaim_debug_info("http proxy", "Connected immediately.\n"); |
839 | 839 |
840 len = sizeof(error); | 840 len = sizeof(error); |
841 if (getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) | 841 if (getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
842 { | 842 { |
843 close(connect_info->fd); | 843 close(connect_data->fd); |
844 connect_info->fd = -1; | 844 connect_data->fd = -1; |
845 return -1; | 845 return -1; |
846 } | 846 } |
847 http_canwrite(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 847 http_canwrite(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
848 } | 848 } |
849 | 849 |
850 return connect_info->fd; | 850 return connect_data->fd; |
851 } | 851 } |
852 | 852 |
853 | 853 |
854 static void | 854 static void |
855 s4_canread(gpointer data, gint source, GaimInputCondition cond) | 855 s4_canread(gpointer data, gint source, GaimInputCondition cond) |
856 { | 856 { |
857 GaimProxyConnectInfo *connect_info = data; | 857 GaimProxyConnectData *connect_data = data; |
858 guchar *buf; | 858 guchar *buf; |
859 int len, max_read; | 859 int len, max_read; |
860 | 860 |
861 /* This is really not going to block under normal circumstances, but to | 861 /* This is really not going to block under normal circumstances, but to |
862 * be correct, we deal with the unlikely scenario */ | 862 * be correct, we deal with the unlikely scenario */ |
863 | 863 |
864 if (connect_info->read_buffer == NULL) { | 864 if (connect_data->read_buffer == NULL) { |
865 connect_info->read_buf_len = 12; | 865 connect_data->read_buf_len = 12; |
866 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); | 866 connect_data->read_buffer = g_malloc(connect_data->read_buf_len); |
867 connect_info->read_len = 0; | 867 connect_data->read_len = 0; |
868 } | 868 } |
869 | 869 |
870 buf = connect_info->read_buffer + connect_info->read_len; | 870 buf = connect_data->read_buffer + connect_data->read_len; |
871 max_read = connect_info->read_buf_len - connect_info->read_len; | 871 max_read = connect_data->read_buf_len - connect_data->read_len; |
872 | 872 |
873 len = read(connect_info->fd, buf, max_read); | 873 len = read(connect_data->fd, buf, max_read); |
874 | 874 |
875 if ((len < 0 && errno == EAGAIN) || (len > 0 && len + connect_info->read_len < 4)) | 875 if ((len < 0 && errno == EAGAIN) || (len > 0 && len + connect_data->read_len < 4)) |
876 return; | 876 return; |
877 else if (len + connect_info->read_len >= 4) { | 877 else if (len + connect_data->read_len >= 4) { |
878 if (connect_info->read_buffer[1] == 90) { | 878 if (connect_data->read_buffer[1] == 90) { |
879 gaim_proxy_connect_info_connected(connect_info); | 879 gaim_proxy_connect_data_connected(connect_data); |
880 return; | 880 return; |
881 } | 881 } |
882 } | 882 } |
883 | 883 |
884 gaim_proxy_connect_info_disconnect(connect_info); | 884 gaim_proxy_connect_data_disconnect(connect_data); |
885 try_connect(connect_info); | 885 try_connect(connect_data); |
886 } | 886 } |
887 | 887 |
888 static void | 888 static void |
889 s4_canwrite(gpointer data, gint source, GaimInputCondition cond) | 889 s4_canwrite(gpointer data, gint source, GaimInputCondition cond) |
890 { | 890 { |
891 unsigned char packet[9]; | 891 unsigned char packet[9]; |
892 struct hostent *hp; | 892 struct hostent *hp; |
893 GaimProxyConnectInfo *connect_info = data; | 893 GaimProxyConnectData *connect_data = data; |
894 socklen_t len; | 894 socklen_t len; |
895 int error = ETIMEDOUT; | 895 int error = ETIMEDOUT; |
896 | 896 |
897 gaim_debug_info("socks4 proxy", "Connected.\n"); | 897 gaim_debug_info("socks4 proxy", "Connected.\n"); |
898 | 898 |
899 if (connect_info->inpa > 0) | 899 if (connect_data->inpa > 0) |
900 { | 900 { |
901 gaim_input_remove(connect_info->inpa); | 901 gaim_input_remove(connect_data->inpa); |
902 connect_info->inpa = 0; | 902 connect_data->inpa = 0; |
903 } | 903 } |
904 | 904 |
905 len = sizeof(error); | 905 len = sizeof(error); |
906 | 906 |
907 if (getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 907 if (getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
908 gaim_proxy_connect_info_disconnect(connect_info); | 908 gaim_proxy_connect_data_disconnect(connect_data); |
909 try_connect(connect_info); | 909 try_connect(connect_data); |
910 return; | 910 return; |
911 } | 911 } |
912 | 912 |
913 /* | 913 /* |
914 * The socks4 spec doesn't include support for doing host name | 914 * The socks4 spec doesn't include support for doing host name |
917 * server supports this, it would need to be implemented | 917 * server supports this, it would need to be implemented |
918 * with an option, or some detection mechanism - in the | 918 * with an option, or some detection mechanism - in the |
919 * meantime, stick with plain old SOCKS4. | 919 * meantime, stick with plain old SOCKS4. |
920 */ | 920 */ |
921 /* TODO: This needs to be non-blocking! */ | 921 /* TODO: This needs to be non-blocking! */ |
922 hp = gethostbyname(connect_info->host); | 922 hp = gethostbyname(connect_data->host); |
923 if (hp == NULL) { | 923 if (hp == NULL) { |
924 gaim_proxy_connect_info_disconnect(connect_info); | 924 gaim_proxy_connect_data_disconnect(connect_data); |
925 try_connect(connect_info); | 925 try_connect(connect_data); |
926 return; | 926 return; |
927 } | 927 } |
928 | 928 |
929 packet[0] = 4; | 929 packet[0] = 4; |
930 packet[1] = 1; | 930 packet[1] = 1; |
931 packet[2] = connect_info->port >> 8; | 931 packet[2] = connect_data->port >> 8; |
932 packet[3] = connect_info->port & 0xff; | 932 packet[3] = connect_data->port & 0xff; |
933 packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; | 933 packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; |
934 packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; | 934 packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; |
935 packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; | 935 packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; |
936 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; | 936 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; |
937 packet[8] = 0; | 937 packet[8] = 0; |
938 | 938 |
939 connect_info->write_buffer = g_memdup(packet, sizeof(packet)); | 939 connect_data->write_buffer = g_memdup(packet, sizeof(packet)); |
940 connect_info->write_buf_len = sizeof(packet); | 940 connect_data->write_buf_len = sizeof(packet); |
941 connect_info->written_len = 0; | 941 connect_data->written_len = 0; |
942 connect_info->read_cb = s4_canread; | 942 connect_data->read_cb = s4_canread; |
943 | 943 |
944 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, proxy_do_write, connect_info); | 944 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, proxy_do_write, connect_data); |
945 | 945 |
946 proxy_do_write(connect_info, connect_info->fd, cond); | 946 proxy_do_write(connect_data, connect_data->fd, cond); |
947 } | 947 } |
948 | 948 |
949 static int | 949 static int |
950 proxy_connect_socks4(GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) | 950 proxy_connect_socks4(GaimProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) |
951 { | 951 { |
952 gaim_debug_info("socks4 proxy", | 952 gaim_debug_info("socks4 proxy", |
953 "Connecting to %s:%d via %s:%d using SOCKS4\n", | 953 "Connecting to %s:%d via %s:%d using SOCKS4\n", |
954 connect_info->host, connect_info->port, | 954 connect_data->host, connect_data->port, |
955 gaim_proxy_info_get_host(connect_info->gpi), | 955 gaim_proxy_info_get_host(connect_data->gpi), |
956 gaim_proxy_info_get_port(connect_info->gpi)); | 956 gaim_proxy_info_get_port(connect_data->gpi)); |
957 | 957 |
958 connect_info->fd = socket(addr->sa_family, SOCK_STREAM, 0); | 958 connect_data->fd = socket(addr->sa_family, SOCK_STREAM, 0); |
959 if (connect_info->fd < 0) | 959 if (connect_data->fd < 0) |
960 return -1; | 960 return -1; |
961 | 961 |
962 fcntl(connect_info->fd, F_SETFL, O_NONBLOCK); | 962 fcntl(connect_data->fd, F_SETFL, O_NONBLOCK); |
963 #ifndef _WIN32 | 963 #ifndef _WIN32 |
964 fcntl(connect_info->fd, F_SETFD, FD_CLOEXEC); | 964 fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC); |
965 #endif | 965 #endif |
966 | 966 |
967 if (connect(connect_info->fd, addr, addrlen) != 0) | 967 if (connect(connect_data->fd, addr, addrlen) != 0) |
968 { | 968 { |
969 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 969 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
970 gaim_debug_info("socks4 proxy", "Connection in progress.\n"); | 970 gaim_debug_info("socks4 proxy", "Connection in progress.\n"); |
971 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, s4_canwrite, connect_info); | 971 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, s4_canwrite, connect_data); |
972 } | 972 } |
973 else { | 973 else { |
974 close(connect_info->fd); | 974 close(connect_data->fd); |
975 connect_info->fd = -1; | 975 connect_data->fd = -1; |
976 return -1; | 976 return -1; |
977 } | 977 } |
978 } else { | 978 } else { |
979 socklen_t len; | 979 socklen_t len; |
980 int error = ETIMEDOUT; | 980 int error = ETIMEDOUT; |
981 | 981 |
982 gaim_debug_info("socks4 proxy", "Connected immediately.\n"); | 982 gaim_debug_info("socks4 proxy", "Connected immediately.\n"); |
983 | 983 |
984 len = sizeof(error); | 984 len = sizeof(error); |
985 | 985 |
986 if (getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) | 986 if (getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
987 { | 987 { |
988 close(connect_info->fd); | 988 close(connect_data->fd); |
989 connect_info->fd = -1; | 989 connect_data->fd = -1; |
990 return -1; | 990 return -1; |
991 } | 991 } |
992 | 992 |
993 s4_canwrite(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 993 s4_canwrite(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
994 } | 994 } |
995 | 995 |
996 return connect_info->fd; | 996 return connect_data->fd; |
997 } | 997 } |
998 | 998 |
999 static void | 999 static void |
1000 s5_canread_again(gpointer data, gint source, GaimInputCondition cond) | 1000 s5_canread_again(gpointer data, gint source, GaimInputCondition cond) |
1001 { | 1001 { |
1002 guchar *dest, *buf; | 1002 guchar *dest, *buf; |
1003 GaimProxyConnectInfo *connect_info = data; | 1003 GaimProxyConnectData *connect_data = data; |
1004 int len; | 1004 int len; |
1005 | 1005 |
1006 if (connect_info->read_buffer == NULL) { | 1006 if (connect_data->read_buffer == NULL) { |
1007 connect_info->read_buf_len = 512; | 1007 connect_data->read_buf_len = 512; |
1008 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); | 1008 connect_data->read_buffer = g_malloc(connect_data->read_buf_len); |
1009 connect_info->read_len = 0; | 1009 connect_data->read_len = 0; |
1010 } | 1010 } |
1011 | 1011 |
1012 dest = connect_info->read_buffer + connect_info->read_len; | 1012 dest = connect_data->read_buffer + connect_data->read_len; |
1013 buf = connect_info->read_buffer; | 1013 buf = connect_data->read_buffer; |
1014 | 1014 |
1015 gaim_debug_info("socks5 proxy", "Able to read again.\n"); | 1015 gaim_debug_info("socks5 proxy", "Able to read again.\n"); |
1016 | 1016 |
1017 len = read(connect_info->fd, dest, (connect_info->read_buf_len - connect_info->read_len)); | 1017 len = read(connect_data->fd, dest, (connect_data->read_buf_len - connect_data->read_len)); |
1018 if(len < 0 && errno == EAGAIN) | 1018 if(len < 0 && errno == EAGAIN) |
1019 return; | 1019 return; |
1020 else if(len <= 0) { | 1020 else if(len <= 0) { |
1021 gaim_debug_warning("socks5 proxy", "or not...\n"); | 1021 gaim_debug_warning("socks5 proxy", "or not...\n"); |
1022 gaim_proxy_connect_info_disconnect(connect_info); | 1022 gaim_proxy_connect_data_disconnect(connect_data); |
1023 try_connect(connect_info); | 1023 try_connect(connect_data); |
1024 return; | 1024 return; |
1025 } | 1025 } |
1026 connect_info->read_len += len; | 1026 connect_data->read_len += len; |
1027 | 1027 |
1028 if(connect_info->read_len < 4) | 1028 if(connect_data->read_len < 4) |
1029 return; | 1029 return; |
1030 | 1030 |
1031 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { | 1031 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { |
1032 if ((buf[0] == 0x05) && (buf[1] < 0x09)) | 1032 if ((buf[0] == 0x05) && (buf[1] < 0x09)) |
1033 gaim_debug_error("socks5 proxy", socks5errors[buf[1]]); | 1033 gaim_debug_error("socks5 proxy", socks5errors[buf[1]]); |
1034 else | 1034 else |
1035 gaim_debug_error("socks5 proxy", "Bad data.\n"); | 1035 gaim_debug_error("socks5 proxy", "Bad data.\n"); |
1036 gaim_proxy_connect_info_disconnect(connect_info); | 1036 gaim_proxy_connect_data_disconnect(connect_data); |
1037 try_connect(connect_info); | 1037 try_connect(connect_data); |
1038 return; | 1038 return; |
1039 } | 1039 } |
1040 | 1040 |
1041 /* Skip past BND.ADDR */ | 1041 /* Skip past BND.ADDR */ |
1042 switch(buf[3]) { | 1042 switch(buf[3]) { |
1043 case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */ | 1043 case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */ |
1044 if(connect_info->read_len < 4 + 4) | 1044 if(connect_data->read_len < 4 + 4) |
1045 return; | 1045 return; |
1046 buf += 4 + 4; | 1046 buf += 4 + 4; |
1047 break; | 1047 break; |
1048 case 0x03: /* the address field contains a fully-qualified domain name. The first | 1048 case 0x03: /* the address field contains a fully-qualified domain name. The first |
1049 octet of the address field contains the number of octets of name that | 1049 octet of the address field contains the number of octets of name that |
1050 follow, there is no terminating NUL octet. */ | 1050 follow, there is no terminating NUL octet. */ |
1051 if(connect_info->read_len < 4 + 1) | 1051 if(connect_data->read_len < 4 + 1) |
1052 return; | 1052 return; |
1053 buf += 4 + 1; | 1053 buf += 4 + 1; |
1054 if(connect_info->read_len < 4 + 1 + buf[0]) | 1054 if(connect_data->read_len < 4 + 1 + buf[0]) |
1055 return; | 1055 return; |
1056 buf += buf[0]; | 1056 buf += buf[0]; |
1057 break; | 1057 break; |
1058 case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */ | 1058 case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */ |
1059 if(connect_info->read_len < 4 + 16) | 1059 if(connect_data->read_len < 4 + 16) |
1060 return; | 1060 return; |
1061 buf += 4 + 16; | 1061 buf += 4 + 16; |
1062 break; | 1062 break; |
1063 } | 1063 } |
1064 | 1064 |
1065 if(connect_info->read_len < (buf - connect_info->read_buffer) + 2) | 1065 if(connect_data->read_len < (buf - connect_data->read_buffer) + 2) |
1066 return; | 1066 return; |
1067 | 1067 |
1068 /* Skip past BND.PORT */ | 1068 /* Skip past BND.PORT */ |
1069 buf += 2; | 1069 buf += 2; |
1070 | 1070 |
1071 gaim_proxy_connect_info_connected(connect_info); | 1071 gaim_proxy_connect_data_connected(connect_data); |
1072 } | 1072 } |
1073 | 1073 |
1074 static void | 1074 static void |
1075 s5_sendconnect(gpointer data, int source) | 1075 s5_sendconnect(gpointer data, int source) |
1076 { | 1076 { |
1077 GaimProxyConnectInfo *connect_info = data; | 1077 GaimProxyConnectData *connect_data = data; |
1078 int hlen = strlen(connect_info->host); | 1078 int hlen = strlen(connect_data->host); |
1079 connect_info->write_buf_len = 5 + hlen + 2; | 1079 connect_data->write_buf_len = 5 + hlen + 2; |
1080 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); | 1080 connect_data->write_buffer = g_malloc(connect_data->write_buf_len); |
1081 connect_info->written_len = 0; | 1081 connect_data->written_len = 0; |
1082 | 1082 |
1083 connect_info->write_buffer[0] = 0x05; | 1083 connect_data->write_buffer[0] = 0x05; |
1084 connect_info->write_buffer[1] = 0x01; /* CONNECT */ | 1084 connect_data->write_buffer[1] = 0x01; /* CONNECT */ |
1085 connect_info->write_buffer[2] = 0x00; /* reserved */ | 1085 connect_data->write_buffer[2] = 0x00; /* reserved */ |
1086 connect_info->write_buffer[3] = 0x03; /* address type -- host name */ | 1086 connect_data->write_buffer[3] = 0x03; /* address type -- host name */ |
1087 connect_info->write_buffer[4] = hlen; | 1087 connect_data->write_buffer[4] = hlen; |
1088 memcpy(connect_info->write_buffer + 5, connect_info->host, hlen); | 1088 memcpy(connect_data->write_buffer + 5, connect_data->host, hlen); |
1089 connect_info->write_buffer[5 + hlen] = connect_info->port >> 8; | 1089 connect_data->write_buffer[5 + hlen] = connect_data->port >> 8; |
1090 connect_info->write_buffer[5 + hlen + 1] = connect_info->port & 0xff; | 1090 connect_data->write_buffer[5 + hlen + 1] = connect_data->port & 0xff; |
1091 | 1091 |
1092 connect_info->read_cb = s5_canread_again; | 1092 connect_data->read_cb = s5_canread_again; |
1093 | 1093 |
1094 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, proxy_do_write, connect_info); | 1094 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, proxy_do_write, connect_data); |
1095 proxy_do_write(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 1095 proxy_do_write(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
1096 } | 1096 } |
1097 | 1097 |
1098 static void | 1098 static void |
1099 s5_readauth(gpointer data, gint source, GaimInputCondition cond) | 1099 s5_readauth(gpointer data, gint source, GaimInputCondition cond) |
1100 { | 1100 { |
1101 GaimProxyConnectInfo *connect_info = data; | 1101 GaimProxyConnectData *connect_data = data; |
1102 int len; | 1102 int len; |
1103 | 1103 |
1104 if (connect_info->read_buffer == NULL) { | 1104 if (connect_data->read_buffer == NULL) { |
1105 connect_info->read_buf_len = 2; | 1105 connect_data->read_buf_len = 2; |
1106 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); | 1106 connect_data->read_buffer = g_malloc(connect_data->read_buf_len); |
1107 connect_info->read_len = 0; | 1107 connect_data->read_len = 0; |
1108 } | 1108 } |
1109 | 1109 |
1110 gaim_debug_info("socks5 proxy", "Got auth response.\n"); | 1110 gaim_debug_info("socks5 proxy", "Got auth response.\n"); |
1111 | 1111 |
1112 len = read(connect_info->fd, connect_info->read_buffer + connect_info->read_len, | 1112 len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len, |
1113 connect_info->read_buf_len - connect_info->read_len); | 1113 connect_data->read_buf_len - connect_data->read_len); |
1114 if(len < 0 && errno == EAGAIN) | 1114 if(len < 0 && errno == EAGAIN) |
1115 return; | 1115 return; |
1116 else if(len <= 0) { | 1116 else if(len <= 0) { |
1117 gaim_proxy_connect_info_disconnect(connect_info); | 1117 gaim_proxy_connect_data_disconnect(connect_data); |
1118 try_connect(connect_info); | 1118 try_connect(connect_data); |
1119 return; | 1119 return; |
1120 } | 1120 } |
1121 connect_info->read_len += len; | 1121 connect_data->read_len += len; |
1122 | 1122 |
1123 if (connect_info->read_len < 2) | 1123 if (connect_data->read_len < 2) |
1124 return; | 1124 return; |
1125 | 1125 |
1126 gaim_input_remove(connect_info->inpa); | 1126 gaim_input_remove(connect_data->inpa); |
1127 connect_info->inpa = 0; | 1127 connect_data->inpa = 0; |
1128 | 1128 |
1129 if ((connect_info->read_buffer[0] != 0x01) || (connect_info->read_buffer[1] != 0x00)) { | 1129 if ((connect_data->read_buffer[0] != 0x01) || (connect_data->read_buffer[1] != 0x00)) { |
1130 gaim_proxy_connect_info_disconnect(connect_info); | 1130 gaim_proxy_connect_data_disconnect(connect_data); |
1131 try_connect(connect_info); | 1131 try_connect(connect_data); |
1132 return; | 1132 return; |
1133 } | 1133 } |
1134 | 1134 |
1135 g_free(connect_info->read_buffer); | 1135 g_free(connect_data->read_buffer); |
1136 connect_info->read_buffer = NULL; | 1136 connect_data->read_buffer = NULL; |
1137 | 1137 |
1138 s5_sendconnect(connect_info, connect_info->fd); | 1138 s5_sendconnect(connect_data, connect_data->fd); |
1139 } | 1139 } |
1140 | 1140 |
1141 static void | 1141 static void |
1142 hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response) | 1142 hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response) |
1143 { | 1143 { |
1184 | 1184 |
1185 static void | 1185 static void |
1186 s5_readchap(gpointer data, gint source, GaimInputCondition cond) | 1186 s5_readchap(gpointer data, gint source, GaimInputCondition cond) |
1187 { | 1187 { |
1188 guchar *cmdbuf, *buf; | 1188 guchar *cmdbuf, *buf; |
1189 GaimProxyConnectInfo *connect_info = data; | 1189 GaimProxyConnectData *connect_data = data; |
1190 int len, navas, currentav; | 1190 int len, navas, currentav; |
1191 | 1191 |
1192 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got CHAP response.\n"); | 1192 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got CHAP response.\n"); |
1193 | 1193 |
1194 if (connect_info->read_buffer == NULL) { | 1194 if (connect_data->read_buffer == NULL) { |
1195 connect_info->read_buf_len = 20; | 1195 connect_data->read_buf_len = 20; |
1196 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); | 1196 connect_data->read_buffer = g_malloc(connect_data->read_buf_len); |
1197 connect_info->read_len = 0; | 1197 connect_data->read_len = 0; |
1198 } | 1198 } |
1199 | 1199 |
1200 len = read(connect_info->fd, connect_info->read_buffer + connect_info->read_len, | 1200 len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len, |
1201 connect_info->read_buf_len - connect_info->read_len); | 1201 connect_data->read_buf_len - connect_data->read_len); |
1202 | 1202 |
1203 if(len < 0 && errno == EAGAIN) | 1203 if(len < 0 && errno == EAGAIN) |
1204 return; | 1204 return; |
1205 else if(len <= 0) { | 1205 else if(len <= 0) { |
1206 gaim_proxy_connect_info_disconnect(connect_info); | 1206 gaim_proxy_connect_data_disconnect(connect_data); |
1207 try_connect(connect_info); | 1207 try_connect(connect_data); |
1208 return; | 1208 return; |
1209 } | 1209 } |
1210 connect_info->read_len += len; | 1210 connect_data->read_len += len; |
1211 | 1211 |
1212 if (connect_info->read_len < 2) | 1212 if (connect_data->read_len < 2) |
1213 return; | 1213 return; |
1214 | 1214 |
1215 cmdbuf = connect_info->read_buffer; | 1215 cmdbuf = connect_data->read_buffer; |
1216 | 1216 |
1217 if (*cmdbuf != 0x01) { | 1217 if (*cmdbuf != 0x01) { |
1218 gaim_proxy_connect_info_disconnect(connect_info); | 1218 gaim_proxy_connect_data_disconnect(connect_data); |
1219 try_connect(connect_info); | 1219 try_connect(connect_data); |
1220 return; | 1220 return; |
1221 } | 1221 } |
1222 cmdbuf++; | 1222 cmdbuf++; |
1223 | 1223 |
1224 navas = *cmdbuf; | 1224 navas = *cmdbuf; |
1225 cmdbuf++; | 1225 cmdbuf++; |
1226 | 1226 |
1227 for (currentav = 0; currentav < navas; currentav++) { | 1227 for (currentav = 0; currentav < navas; currentav++) { |
1228 if (connect_info->read_len - (cmdbuf - connect_info->read_buffer) < 2) | 1228 if (connect_data->read_len - (cmdbuf - connect_data->read_buffer) < 2) |
1229 return; | 1229 return; |
1230 if (connect_info->read_len - (cmdbuf - connect_info->read_buffer) < cmdbuf[1]) | 1230 if (connect_data->read_len - (cmdbuf - connect_data->read_buffer) < cmdbuf[1]) |
1231 return; | 1231 return; |
1232 buf = cmdbuf + 2; | 1232 buf = cmdbuf + 2; |
1233 switch (cmdbuf[0]) { | 1233 switch (cmdbuf[0]) { |
1234 case 0x00: | 1234 case 0x00: |
1235 /* Did auth work? */ | 1235 /* Did auth work? */ |
1236 if (buf[0] == 0x00) { | 1236 if (buf[0] == 0x00) { |
1237 gaim_input_remove(connect_info->inpa); | 1237 gaim_input_remove(connect_data->inpa); |
1238 connect_info->inpa = 0; | 1238 connect_data->inpa = 0; |
1239 g_free(connect_info->read_buffer); | 1239 g_free(connect_data->read_buffer); |
1240 connect_info->read_buffer = NULL; | 1240 connect_data->read_buffer = NULL; |
1241 /* Success */ | 1241 /* Success */ |
1242 s5_sendconnect(connect_info, connect_info->fd); | 1242 s5_sendconnect(connect_data, connect_data->fd); |
1243 return; | 1243 return; |
1244 } else { | 1244 } else { |
1245 /* Failure */ | 1245 /* Failure */ |
1246 gaim_debug_warning("proxy", | 1246 gaim_debug_warning("proxy", |
1247 "socks5 CHAP authentication " | 1247 "socks5 CHAP authentication " |
1248 "failed. Disconnecting..."); | 1248 "failed. Disconnecting..."); |
1249 gaim_proxy_connect_info_disconnect(connect_info); | 1249 gaim_proxy_connect_data_disconnect(connect_data); |
1250 try_connect(connect_info); | 1250 try_connect(connect_data); |
1251 return; | 1251 return; |
1252 } | 1252 } |
1253 break; | 1253 break; |
1254 case 0x03: | 1254 case 0x03: |
1255 /* Server wants our credentials */ | 1255 /* Server wants our credentials */ |
1256 | 1256 |
1257 connect_info->write_buf_len = 16 + 4; | 1257 connect_data->write_buf_len = 16 + 4; |
1258 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); | 1258 connect_data->write_buffer = g_malloc(connect_data->write_buf_len); |
1259 connect_info->written_len = 0; | 1259 connect_data->written_len = 0; |
1260 | 1260 |
1261 hmacmd5_chap(buf, cmdbuf[1], | 1261 hmacmd5_chap(buf, cmdbuf[1], |
1262 gaim_proxy_info_get_password(connect_info->gpi), | 1262 gaim_proxy_info_get_password(connect_data->gpi), |
1263 connect_info->write_buffer + 4); | 1263 connect_data->write_buffer + 4); |
1264 connect_info->write_buffer[0] = 0x01; | 1264 connect_data->write_buffer[0] = 0x01; |
1265 connect_info->write_buffer[1] = 0x01; | 1265 connect_data->write_buffer[1] = 0x01; |
1266 connect_info->write_buffer[2] = 0x04; | 1266 connect_data->write_buffer[2] = 0x04; |
1267 connect_info->write_buffer[3] = 0x10; | 1267 connect_data->write_buffer[3] = 0x10; |
1268 | 1268 |
1269 gaim_input_remove(connect_info->inpa); | 1269 gaim_input_remove(connect_data->inpa); |
1270 g_free(connect_info->read_buffer); | 1270 g_free(connect_data->read_buffer); |
1271 connect_info->read_buffer = NULL; | 1271 connect_data->read_buffer = NULL; |
1272 | 1272 |
1273 connect_info->read_cb = s5_readchap; | 1273 connect_data->read_cb = s5_readchap; |
1274 | 1274 |
1275 connect_info->inpa = gaim_input_add(connect_info->fd, | 1275 connect_data->inpa = gaim_input_add(connect_data->fd, |
1276 GAIM_INPUT_WRITE, proxy_do_write, connect_info); | 1276 GAIM_INPUT_WRITE, proxy_do_write, connect_data); |
1277 | 1277 |
1278 proxy_do_write(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 1278 proxy_do_write(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
1279 break; | 1279 break; |
1280 case 0x11: | 1280 case 0x11: |
1281 /* Server wants to select an algorithm */ | 1281 /* Server wants to select an algorithm */ |
1282 if (buf[0] != 0x85) { | 1282 if (buf[0] != 0x85) { |
1283 /* Only currently support HMAC-MD5 */ | 1283 /* Only currently support HMAC-MD5 */ |
1285 "Server tried to select an " | 1285 "Server tried to select an " |
1286 "algorithm that we did not advertise " | 1286 "algorithm that we did not advertise " |
1287 "as supporting. This is a violation " | 1287 "as supporting. This is a violation " |
1288 "of the socks5 CHAP specification. " | 1288 "of the socks5 CHAP specification. " |
1289 "Disconnecting..."); | 1289 "Disconnecting..."); |
1290 gaim_proxy_connect_info_disconnect(connect_info); | 1290 gaim_proxy_connect_data_disconnect(connect_data); |
1291 try_connect(connect_info); | 1291 try_connect(connect_data); |
1292 return; | 1292 return; |
1293 } | 1293 } |
1294 break; | 1294 break; |
1295 } | 1295 } |
1296 cmdbuf = buf + cmdbuf[1]; | 1296 cmdbuf = buf + cmdbuf[1]; |
1301 } | 1301 } |
1302 | 1302 |
1303 static void | 1303 static void |
1304 s5_canread(gpointer data, gint source, GaimInputCondition cond) | 1304 s5_canread(gpointer data, gint source, GaimInputCondition cond) |
1305 { | 1305 { |
1306 GaimProxyConnectInfo *connect_info = data; | 1306 GaimProxyConnectData *connect_data = data; |
1307 int len; | 1307 int len; |
1308 | 1308 |
1309 if (connect_info->read_buffer == NULL) { | 1309 if (connect_data->read_buffer == NULL) { |
1310 connect_info->read_buf_len = 2; | 1310 connect_data->read_buf_len = 2; |
1311 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); | 1311 connect_data->read_buffer = g_malloc(connect_data->read_buf_len); |
1312 connect_info->read_len = 0; | 1312 connect_data->read_len = 0; |
1313 } | 1313 } |
1314 | 1314 |
1315 gaim_debug_info("socks5 proxy", "Able to read.\n"); | 1315 gaim_debug_info("socks5 proxy", "Able to read.\n"); |
1316 | 1316 |
1317 len = read(connect_info->fd, connect_info->read_buffer + connect_info->read_len, | 1317 len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len, |
1318 connect_info->read_buf_len - connect_info->read_len); | 1318 connect_data->read_buf_len - connect_data->read_len); |
1319 if(len < 0 && errno == EAGAIN) | 1319 if(len < 0 && errno == EAGAIN) |
1320 return; | 1320 return; |
1321 else if(len <= 0) { | 1321 else if(len <= 0) { |
1322 gaim_proxy_connect_info_disconnect(connect_info); | 1322 gaim_proxy_connect_data_disconnect(connect_data); |
1323 try_connect(connect_info); | 1323 try_connect(connect_data); |
1324 return; | 1324 return; |
1325 } | 1325 } |
1326 connect_info->read_len += len; | 1326 connect_data->read_len += len; |
1327 | 1327 |
1328 if (connect_info->read_len < 2) | 1328 if (connect_data->read_len < 2) |
1329 return; | 1329 return; |
1330 | 1330 |
1331 gaim_input_remove(connect_info->inpa); | 1331 gaim_input_remove(connect_data->inpa); |
1332 connect_info->inpa = 0; | 1332 connect_data->inpa = 0; |
1333 | 1333 |
1334 if ((connect_info->read_buffer[0] != 0x05) || (connect_info->read_buffer[1] == 0xff)) { | 1334 if ((connect_data->read_buffer[0] != 0x05) || (connect_data->read_buffer[1] == 0xff)) { |
1335 gaim_proxy_connect_info_disconnect(connect_info); | 1335 gaim_proxy_connect_data_disconnect(connect_data); |
1336 try_connect(connect_info); | 1336 try_connect(connect_data); |
1337 return; | 1337 return; |
1338 } | 1338 } |
1339 | 1339 |
1340 if (connect_info->read_buffer[1] == 0x02) { | 1340 if (connect_data->read_buffer[1] == 0x02) { |
1341 gsize i, j; | 1341 gsize i, j; |
1342 const char *u, *p; | 1342 const char *u, *p; |
1343 | 1343 |
1344 u = gaim_proxy_info_get_username(connect_info->gpi); | 1344 u = gaim_proxy_info_get_username(connect_data->gpi); |
1345 p = gaim_proxy_info_get_password(connect_info->gpi); | 1345 p = gaim_proxy_info_get_password(connect_data->gpi); |
1346 | 1346 |
1347 i = (u == NULL) ? 0 : strlen(u); | 1347 i = (u == NULL) ? 0 : strlen(u); |
1348 j = (p == NULL) ? 0 : strlen(p); | 1348 j = (p == NULL) ? 0 : strlen(p); |
1349 | 1349 |
1350 connect_info->write_buf_len = 1 + 1 + i + 1 + j; | 1350 connect_data->write_buf_len = 1 + 1 + i + 1 + j; |
1351 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); | 1351 connect_data->write_buffer = g_malloc(connect_data->write_buf_len); |
1352 connect_info->written_len = 0; | 1352 connect_data->written_len = 0; |
1353 | 1353 |
1354 connect_info->write_buffer[0] = 0x01; /* version 1 */ | 1354 connect_data->write_buffer[0] = 0x01; /* version 1 */ |
1355 connect_info->write_buffer[1] = i; | 1355 connect_data->write_buffer[1] = i; |
1356 if (u != NULL) | 1356 if (u != NULL) |
1357 memcpy(connect_info->write_buffer + 2, u, i); | 1357 memcpy(connect_data->write_buffer + 2, u, i); |
1358 connect_info->write_buffer[2 + i] = j; | 1358 connect_data->write_buffer[2 + i] = j; |
1359 if (p != NULL) | 1359 if (p != NULL) |
1360 memcpy(connect_info->write_buffer + 2 + i + 1, p, j); | 1360 memcpy(connect_data->write_buffer + 2 + i + 1, p, j); |
1361 | 1361 |
1362 g_free(connect_info->read_buffer); | 1362 g_free(connect_data->read_buffer); |
1363 connect_info->read_buffer = NULL; | 1363 connect_data->read_buffer = NULL; |
1364 | 1364 |
1365 connect_info->read_cb = s5_readauth; | 1365 connect_data->read_cb = s5_readauth; |
1366 | 1366 |
1367 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, | 1367 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, |
1368 proxy_do_write, connect_info); | 1368 proxy_do_write, connect_data); |
1369 | 1369 |
1370 proxy_do_write(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 1370 proxy_do_write(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
1371 | 1371 |
1372 return; | 1372 return; |
1373 } else if (connect_info->read_buffer[1] == 0x03) { | 1373 } else if (connect_data->read_buffer[1] == 0x03) { |
1374 gsize userlen; | 1374 gsize userlen; |
1375 userlen = strlen(gaim_proxy_info_get_username(connect_info->gpi)); | 1375 userlen = strlen(gaim_proxy_info_get_username(connect_data->gpi)); |
1376 | 1376 |
1377 connect_info->write_buf_len = 7 + userlen; | 1377 connect_data->write_buf_len = 7 + userlen; |
1378 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); | 1378 connect_data->write_buffer = g_malloc(connect_data->write_buf_len); |
1379 connect_info->written_len = 0; | 1379 connect_data->written_len = 0; |
1380 | 1380 |
1381 connect_info->write_buffer[0] = 0x01; | 1381 connect_data->write_buffer[0] = 0x01; |
1382 connect_info->write_buffer[1] = 0x02; | 1382 connect_data->write_buffer[1] = 0x02; |
1383 connect_info->write_buffer[2] = 0x11; | 1383 connect_data->write_buffer[2] = 0x11; |
1384 connect_info->write_buffer[3] = 0x01; | 1384 connect_data->write_buffer[3] = 0x01; |
1385 connect_info->write_buffer[4] = 0x85; | 1385 connect_data->write_buffer[4] = 0x85; |
1386 connect_info->write_buffer[5] = 0x02; | 1386 connect_data->write_buffer[5] = 0x02; |
1387 connect_info->write_buffer[6] = userlen; | 1387 connect_data->write_buffer[6] = userlen; |
1388 memcpy(connect_info->write_buffer + 7, | 1388 memcpy(connect_data->write_buffer + 7, |
1389 gaim_proxy_info_get_username(connect_info->gpi), userlen); | 1389 gaim_proxy_info_get_username(connect_data->gpi), userlen); |
1390 | 1390 |
1391 g_free(connect_info->read_buffer); | 1391 g_free(connect_data->read_buffer); |
1392 connect_info->read_buffer = NULL; | 1392 connect_data->read_buffer = NULL; |
1393 | 1393 |
1394 connect_info->read_cb = s5_readchap; | 1394 connect_data->read_cb = s5_readchap; |
1395 | 1395 |
1396 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, | 1396 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, |
1397 proxy_do_write, connect_info); | 1397 proxy_do_write, connect_data); |
1398 | 1398 |
1399 proxy_do_write(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 1399 proxy_do_write(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
1400 | 1400 |
1401 return; | 1401 return; |
1402 } else { | 1402 } else { |
1403 g_free(connect_info->read_buffer); | 1403 g_free(connect_data->read_buffer); |
1404 connect_info->read_buffer = NULL; | 1404 connect_data->read_buffer = NULL; |
1405 | 1405 |
1406 s5_sendconnect(connect_info, connect_info->fd); | 1406 s5_sendconnect(connect_data, connect_data->fd); |
1407 } | 1407 } |
1408 } | 1408 } |
1409 | 1409 |
1410 static void | 1410 static void |
1411 s5_canwrite(gpointer data, gint source, GaimInputCondition cond) | 1411 s5_canwrite(gpointer data, gint source, GaimInputCondition cond) |
1412 { | 1412 { |
1413 unsigned char buf[5]; | 1413 unsigned char buf[5]; |
1414 int i; | 1414 int i; |
1415 GaimProxyConnectInfo *connect_info = data; | 1415 GaimProxyConnectData *connect_data = data; |
1416 socklen_t len; | 1416 socklen_t len; |
1417 int error = ETIMEDOUT; | 1417 int error = ETIMEDOUT; |
1418 | 1418 |
1419 gaim_debug_info("socks5 proxy", "Connected.\n"); | 1419 gaim_debug_info("socks5 proxy", "Connected.\n"); |
1420 | 1420 |
1421 if (connect_info->inpa > 0) | 1421 if (connect_data->inpa > 0) |
1422 { | 1422 { |
1423 gaim_input_remove(connect_info->inpa); | 1423 gaim_input_remove(connect_data->inpa); |
1424 connect_info->inpa = 0; | 1424 connect_data->inpa = 0; |
1425 } | 1425 } |
1426 | 1426 |
1427 len = sizeof(error); | 1427 len = sizeof(error); |
1428 if (getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1428 if (getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1429 gaim_proxy_connect_info_disconnect(connect_info); | 1429 gaim_proxy_connect_data_disconnect(connect_data); |
1430 try_connect(connect_info); | 1430 try_connect(connect_data); |
1431 return; | 1431 return; |
1432 } | 1432 } |
1433 | 1433 |
1434 i = 0; | 1434 i = 0; |
1435 buf[0] = 0x05; /* SOCKS version 5 */ | 1435 buf[0] = 0x05; /* SOCKS version 5 */ |
1436 | 1436 |
1437 if (gaim_proxy_info_get_username(connect_info->gpi) != NULL) { | 1437 if (gaim_proxy_info_get_username(connect_data->gpi) != NULL) { |
1438 buf[1] = 0x03; /* three methods */ | 1438 buf[1] = 0x03; /* three methods */ |
1439 buf[2] = 0x00; /* no authentication */ | 1439 buf[2] = 0x00; /* no authentication */ |
1440 buf[3] = 0x03; /* CHAP authentication */ | 1440 buf[3] = 0x03; /* CHAP authentication */ |
1441 buf[4] = 0x02; /* username/password authentication */ | 1441 buf[4] = 0x02; /* username/password authentication */ |
1442 i = 5; | 1442 i = 5; |
1445 buf[1] = 0x01; | 1445 buf[1] = 0x01; |
1446 buf[2] = 0x00; | 1446 buf[2] = 0x00; |
1447 i = 3; | 1447 i = 3; |
1448 } | 1448 } |
1449 | 1449 |
1450 connect_info->write_buf_len = i; | 1450 connect_data->write_buf_len = i; |
1451 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); | 1451 connect_data->write_buffer = g_malloc(connect_data->write_buf_len); |
1452 memcpy(connect_info->write_buffer, buf, i); | 1452 memcpy(connect_data->write_buffer, buf, i); |
1453 | 1453 |
1454 connect_info->read_cb = s5_canread; | 1454 connect_data->read_cb = s5_canread; |
1455 | 1455 |
1456 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, proxy_do_write, connect_info); | 1456 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, proxy_do_write, connect_data); |
1457 proxy_do_write(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 1457 proxy_do_write(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
1458 } | 1458 } |
1459 | 1459 |
1460 static int | 1460 static int |
1461 proxy_connect_socks5(GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) | 1461 proxy_connect_socks5(GaimProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) |
1462 { | 1462 { |
1463 gaim_debug_info("socks5 proxy", | 1463 gaim_debug_info("socks5 proxy", |
1464 "Connecting to %s:%d via %s:%d using SOCKS5\n", | 1464 "Connecting to %s:%d via %s:%d using SOCKS5\n", |
1465 connect_info->host, connect_info->port, | 1465 connect_data->host, connect_data->port, |
1466 gaim_proxy_info_get_host(connect_info->gpi), | 1466 gaim_proxy_info_get_host(connect_data->gpi), |
1467 gaim_proxy_info_get_port(connect_info->gpi)); | 1467 gaim_proxy_info_get_port(connect_data->gpi)); |
1468 | 1468 |
1469 connect_info->fd = socket(addr->sa_family, SOCK_STREAM, 0); | 1469 connect_data->fd = socket(addr->sa_family, SOCK_STREAM, 0); |
1470 if (connect_info->fd < 0) | 1470 if (connect_data->fd < 0) |
1471 return -1; | 1471 return -1; |
1472 | 1472 |
1473 fcntl(connect_info->fd, F_SETFL, O_NONBLOCK); | 1473 fcntl(connect_data->fd, F_SETFL, O_NONBLOCK); |
1474 #ifndef _WIN32 | 1474 #ifndef _WIN32 |
1475 fcntl(connect_info->fd, F_SETFD, FD_CLOEXEC); | 1475 fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC); |
1476 #endif | 1476 #endif |
1477 | 1477 |
1478 if (connect(connect_info->fd, addr, addrlen) != 0) | 1478 if (connect(connect_data->fd, addr, addrlen) != 0) |
1479 { | 1479 { |
1480 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 1480 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
1481 gaim_debug_info("socks5 proxy", "Connection in progress\n"); | 1481 gaim_debug_info("socks5 proxy", "Connection in progress\n"); |
1482 connect_info->inpa = gaim_input_add(connect_info->fd, GAIM_INPUT_WRITE, s5_canwrite, connect_info); | 1482 connect_data->inpa = gaim_input_add(connect_data->fd, GAIM_INPUT_WRITE, s5_canwrite, connect_data); |
1483 } | 1483 } |
1484 else { | 1484 else { |
1485 close(connect_info->fd); | 1485 close(connect_data->fd); |
1486 connect_info->fd = -1; | 1486 connect_data->fd = -1; |
1487 return -1; | 1487 return -1; |
1488 } | 1488 } |
1489 } | 1489 } |
1490 else { | 1490 else { |
1491 socklen_t len; | 1491 socklen_t len; |
1493 | 1493 |
1494 gaim_debug_info("socks5 proxy", "Connected immediately.\n"); | 1494 gaim_debug_info("socks5 proxy", "Connected immediately.\n"); |
1495 | 1495 |
1496 len = sizeof(error); | 1496 len = sizeof(error); |
1497 | 1497 |
1498 if (getsockopt(connect_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) | 1498 if (getsockopt(connect_data->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
1499 { | 1499 { |
1500 close(connect_info->fd); | 1500 close(connect_data->fd); |
1501 connect_info->fd = -1; | 1501 connect_data->fd = -1; |
1502 return -1; | 1502 return -1; |
1503 } | 1503 } |
1504 | 1504 |
1505 s5_canwrite(connect_info, connect_info->fd, GAIM_INPUT_WRITE); | 1505 s5_canwrite(connect_data, connect_data->fd, GAIM_INPUT_WRITE); |
1506 } | 1506 } |
1507 | 1507 |
1508 return connect_info->fd; | 1508 return connect_data->fd; |
1509 } | 1509 } |
1510 | 1510 |
1511 /** | 1511 /** |
1512 * This function iterates through a list of IP addresses and attempts | 1512 * This function iterates through a list of IP addresses and attempts |
1513 * to connect to each one. This is called after the hostname is | 1513 * to connect to each one. This is called after the hostname is |
1514 * resolved, and if a connection attempt fails. | 1514 * resolved, and if a connection attempt fails. |
1515 */ | 1515 */ |
1516 static void try_connect(GaimProxyConnectInfo *connect_info) | 1516 static void try_connect(GaimProxyConnectData *connect_data) |
1517 { | 1517 { |
1518 size_t addrlen; | 1518 size_t addrlen; |
1519 struct sockaddr *addr; | 1519 struct sockaddr *addr; |
1520 int ret = -1; | 1520 int ret = -1; |
1521 | 1521 |
1522 if (connect_info->hosts == NULL) | 1522 if (connect_data->hosts == NULL) |
1523 { | 1523 { |
1524 gaim_proxy_connect_info_error(connect_info, _("Could not resolve host name")); | 1524 gaim_proxy_connect_data_error(connect_data, _("Could not resolve host name")); |
1525 return; | 1525 return; |
1526 } | 1526 } |
1527 | 1527 |
1528 while (connect_info->hosts) | 1528 while (connect_data->hosts) |
1529 { | 1529 { |
1530 addrlen = GPOINTER_TO_INT(connect_info->hosts->data); | 1530 addrlen = GPOINTER_TO_INT(connect_data->hosts->data); |
1531 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); | 1531 connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data); |
1532 addr = connect_info->hosts->data; | 1532 addr = connect_data->hosts->data; |
1533 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); | 1533 connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data); |
1534 | 1534 |
1535 switch (gaim_proxy_info_get_type(connect_info->gpi)) { | 1535 switch (gaim_proxy_info_get_type(connect_data->gpi)) { |
1536 case GAIM_PROXY_NONE: | 1536 case GAIM_PROXY_NONE: |
1537 ret = proxy_connect_none(connect_info, addr, addrlen); | 1537 ret = proxy_connect_none(connect_data, addr, addrlen); |
1538 break; | 1538 break; |
1539 | 1539 |
1540 case GAIM_PROXY_HTTP: | 1540 case GAIM_PROXY_HTTP: |
1541 ret = proxy_connect_http(connect_info, addr, addrlen); | 1541 ret = proxy_connect_http(connect_data, addr, addrlen); |
1542 break; | 1542 break; |
1543 | 1543 |
1544 case GAIM_PROXY_SOCKS4: | 1544 case GAIM_PROXY_SOCKS4: |
1545 ret = proxy_connect_socks4(connect_info, addr, addrlen); | 1545 ret = proxy_connect_socks4(connect_data, addr, addrlen); |
1546 break; | 1546 break; |
1547 | 1547 |
1548 case GAIM_PROXY_SOCKS5: | 1548 case GAIM_PROXY_SOCKS5: |
1549 ret = proxy_connect_socks5(connect_info, addr, addrlen); | 1549 ret = proxy_connect_socks5(connect_data, addr, addrlen); |
1550 break; | 1550 break; |
1551 | 1551 |
1552 case GAIM_PROXY_USE_ENVVAR: | 1552 case GAIM_PROXY_USE_ENVVAR: |
1553 ret = proxy_connect_http(connect_info, addr, addrlen); | 1553 ret = proxy_connect_http(connect_data, addr, addrlen); |
1554 break; | 1554 break; |
1555 | 1555 |
1556 default: | 1556 default: |
1557 break; | 1557 break; |
1558 } | 1558 } |
1562 if (ret >= 0) | 1562 if (ret >= 0) |
1563 break; | 1563 break; |
1564 } | 1564 } |
1565 | 1565 |
1566 if (ret < 0) { | 1566 if (ret < 0) { |
1567 gaim_proxy_connect_info_error(connect_info, _("Unable to establish a connection")); | 1567 gaim_proxy_connect_data_error(connect_data, _("Unable to establish a connection")); |
1568 } | 1568 } |
1569 } | 1569 } |
1570 | 1570 |
1571 static void | 1571 static void |
1572 connection_host_resolved(GSList *hosts, gpointer data, | 1572 connection_host_resolved(GSList *hosts, gpointer data, |
1573 const char *error_message) | 1573 const char *error_message) |
1574 { | 1574 { |
1575 GaimProxyConnectInfo *connect_info; | 1575 GaimProxyConnectData *connect_data; |
1576 | 1576 |
1577 connect_info = data; | 1577 connect_data = data; |
1578 connect_info->query_data = NULL; | 1578 connect_data->query_data = NULL; |
1579 | 1579 |
1580 if (error_message != NULL) | 1580 if (error_message != NULL) |
1581 { | 1581 { |
1582 gchar *tmp; | 1582 gchar *tmp; |
1583 tmp = g_strdup_printf("Error while resolving hostname: %s\n", error_message); | 1583 tmp = g_strdup_printf("Error while resolving hostname: %s\n", error_message); |
1584 gaim_proxy_connect_info_error(connect_info, tmp); | 1584 gaim_proxy_connect_data_error(connect_data, tmp); |
1585 g_free(tmp); | 1585 g_free(tmp); |
1586 return; | 1586 return; |
1587 } | 1587 } |
1588 | 1588 |
1589 connect_info->hosts = hosts; | 1589 connect_data->hosts = hosts; |
1590 | 1590 |
1591 try_connect(connect_info); | 1591 try_connect(connect_data); |
1592 } | 1592 } |
1593 | 1593 |
1594 GaimProxyInfo * | 1594 GaimProxyInfo * |
1595 gaim_proxy_get_setup(GaimAccount *account) | 1595 gaim_proxy_get_setup(GaimAccount *account) |
1596 { | 1596 { |
1655 } | 1655 } |
1656 | 1656 |
1657 return gpi; | 1657 return gpi; |
1658 } | 1658 } |
1659 | 1659 |
1660 GaimProxyConnectInfo * | 1660 GaimProxyConnectData * |
1661 gaim_proxy_connect(GaimAccount *account, const char *host, int port, | 1661 gaim_proxy_connect(GaimAccount *account, const char *host, int port, |
1662 GaimProxyConnectFunction connect_cb, gpointer data) | 1662 GaimProxyConnectFunction connect_cb, gpointer data) |
1663 { | 1663 { |
1664 const char *connecthost = host; | 1664 const char *connecthost = host; |
1665 int connectport = port; | 1665 int connectport = port; |
1666 GaimProxyConnectInfo *connect_info; | 1666 GaimProxyConnectData *connect_data; |
1667 | 1667 |
1668 g_return_val_if_fail(host != NULL, NULL); | 1668 g_return_val_if_fail(host != NULL, NULL); |
1669 g_return_val_if_fail(port > 0, NULL); | 1669 g_return_val_if_fail(port > 0, NULL); |
1670 g_return_val_if_fail(connect_cb != NULL, NULL); | 1670 g_return_val_if_fail(connect_cb != NULL, NULL); |
1671 | 1671 |
1672 connect_info = g_new0(GaimProxyConnectInfo, 1); | 1672 connect_data = g_new0(GaimProxyConnectData, 1); |
1673 connect_info->fd = -1; | 1673 connect_data->fd = -1; |
1674 connect_info->connect_cb = connect_cb; | 1674 connect_data->connect_cb = connect_cb; |
1675 connect_info->data = data; | 1675 connect_data->data = data; |
1676 connect_info->host = g_strdup(host); | 1676 connect_data->host = g_strdup(host); |
1677 connect_info->port = port; | 1677 connect_data->port = port; |
1678 connect_info->gpi = gaim_proxy_get_setup(account); | 1678 connect_data->gpi = gaim_proxy_get_setup(account); |
1679 | 1679 |
1680 if ((gaim_proxy_info_get_type(connect_info->gpi) != GAIM_PROXY_NONE) && | 1680 if ((gaim_proxy_info_get_type(connect_data->gpi) != GAIM_PROXY_NONE) && |
1681 (gaim_proxy_info_get_host(connect_info->gpi) == NULL || | 1681 (gaim_proxy_info_get_host(connect_data->gpi) == NULL || |
1682 gaim_proxy_info_get_port(connect_info->gpi) <= 0)) { | 1682 gaim_proxy_info_get_port(connect_data->gpi) <= 0)) { |
1683 | 1683 |
1684 gaim_notify_error(NULL, NULL, _("Invalid proxy settings"), _("Either the host name or port number specified for your given proxy type is invalid.")); | 1684 gaim_notify_error(NULL, NULL, _("Invalid proxy settings"), _("Either the host name or port number specified for your given proxy type is invalid.")); |
1685 gaim_proxy_connect_info_destroy(connect_info); | 1685 gaim_proxy_connect_data_destroy(connect_data); |
1686 return NULL; | 1686 return NULL; |
1687 } | 1687 } |
1688 | 1688 |
1689 switch (gaim_proxy_info_get_type(connect_info->gpi)) | 1689 switch (gaim_proxy_info_get_type(connect_data->gpi)) |
1690 { | 1690 { |
1691 case GAIM_PROXY_NONE: | 1691 case GAIM_PROXY_NONE: |
1692 break; | 1692 break; |
1693 | 1693 |
1694 case GAIM_PROXY_HTTP: | 1694 case GAIM_PROXY_HTTP: |
1695 case GAIM_PROXY_SOCKS4: | 1695 case GAIM_PROXY_SOCKS4: |
1696 case GAIM_PROXY_SOCKS5: | 1696 case GAIM_PROXY_SOCKS5: |
1697 case GAIM_PROXY_USE_ENVVAR: | 1697 case GAIM_PROXY_USE_ENVVAR: |
1698 connecthost = gaim_proxy_info_get_host(connect_info->gpi); | 1698 connecthost = gaim_proxy_info_get_host(connect_data->gpi); |
1699 connectport = gaim_proxy_info_get_port(connect_info->gpi); | 1699 connectport = gaim_proxy_info_get_port(connect_data->gpi); |
1700 break; | 1700 break; |
1701 | 1701 |
1702 default: | 1702 default: |
1703 gaim_proxy_connect_info_destroy(connect_info); | 1703 gaim_proxy_connect_data_destroy(connect_data); |
1704 return NULL; | 1704 return NULL; |
1705 } | 1705 } |
1706 | 1706 |
1707 connect_info->query_data = gaim_dnsquery_a(connecthost, | 1707 connect_data->query_data = gaim_dnsquery_a(connecthost, |
1708 connectport, connection_host_resolved, connect_info); | 1708 connectport, connection_host_resolved, connect_data); |
1709 if (connect_info->query_data == NULL) | 1709 if (connect_data->query_data == NULL) |
1710 { | 1710 { |
1711 gaim_proxy_connect_info_destroy(connect_info); | 1711 gaim_proxy_connect_data_destroy(connect_data); |
1712 return NULL; | 1712 return NULL; |
1713 } | 1713 } |
1714 | 1714 |
1715 connect_infos = g_slist_prepend(connect_infos, connect_info); | 1715 connect_datas = g_slist_prepend(connect_datas, connect_data); |
1716 | 1716 |
1717 return connect_info; | 1717 return connect_data; |
1718 } | 1718 } |
1719 | 1719 |
1720 /* | 1720 /* |
1721 * Combine some of this code with gaim_proxy_connect() | 1721 * Combine some of this code with gaim_proxy_connect() |
1722 */ | 1722 */ |
1723 GaimProxyConnectInfo * | 1723 GaimProxyConnectData * |
1724 gaim_proxy_connect_socks5(GaimProxyInfo *gpi, const char *host, int port, | 1724 gaim_proxy_connect_socks5(GaimProxyInfo *gpi, const char *host, int port, |
1725 GaimProxyConnectFunction connect_cb, gpointer data) | 1725 GaimProxyConnectFunction connect_cb, gpointer data) |
1726 { | 1726 { |
1727 GaimProxyConnectInfo *connect_info; | 1727 GaimProxyConnectData *connect_data; |
1728 | 1728 |
1729 g_return_val_if_fail(host != NULL, NULL); | 1729 g_return_val_if_fail(host != NULL, NULL); |
1730 g_return_val_if_fail(port > 0, NULL); | 1730 g_return_val_if_fail(port > 0, NULL); |
1731 g_return_val_if_fail(connect_cb != NULL, NULL); | 1731 g_return_val_if_fail(connect_cb != NULL, NULL); |
1732 | 1732 |
1733 connect_info = g_new0(GaimProxyConnectInfo, 1); | 1733 connect_data = g_new0(GaimProxyConnectData, 1); |
1734 connect_info->fd = -1; | 1734 connect_data->fd = -1; |
1735 connect_info->connect_cb = connect_cb; | 1735 connect_data->connect_cb = connect_cb; |
1736 connect_info->data = data; | 1736 connect_data->data = data; |
1737 connect_info->host = g_strdup(host); | 1737 connect_data->host = g_strdup(host); |
1738 connect_info->port = port; | 1738 connect_data->port = port; |
1739 connect_info->gpi = gpi; | 1739 connect_data->gpi = gpi; |
1740 | 1740 |
1741 connect_info->query_data = | 1741 connect_data->query_data = |
1742 gaim_dnsquery_a(gaim_proxy_info_get_host(gpi), | 1742 gaim_dnsquery_a(gaim_proxy_info_get_host(gpi), |
1743 gaim_proxy_info_get_port(gpi), | 1743 gaim_proxy_info_get_port(gpi), |
1744 connection_host_resolved, connect_info); | 1744 connection_host_resolved, connect_data); |
1745 if (connect_info->query_data == NULL) | 1745 if (connect_data->query_data == NULL) |
1746 { | 1746 { |
1747 gaim_proxy_connect_info_destroy(connect_info); | 1747 gaim_proxy_connect_data_destroy(connect_data); |
1748 return NULL; | 1748 return NULL; |
1749 } | 1749 } |
1750 | 1750 |
1751 connect_infos = g_slist_prepend(connect_infos, connect_info); | 1751 connect_datas = g_slist_prepend(connect_datas, connect_data); |
1752 | 1752 |
1753 return connect_info; | 1753 return connect_data; |
1754 } | 1754 } |
1755 | 1755 |
1756 void | 1756 void |
1757 gaim_proxy_connect_cancel(GaimProxyConnectInfo *connect_info) | 1757 gaim_proxy_connect_cancel(GaimProxyConnectData *connect_data) |
1758 { | 1758 { |
1759 gaim_proxy_connect_info_destroy(connect_info); | 1759 gaim_proxy_connect_data_destroy(connect_data); |
1760 } | 1760 } |
1761 | 1761 |
1762 static void | 1762 static void |
1763 proxy_pref_cb(const char *name, GaimPrefType type, | 1763 proxy_pref_cb(const char *name, GaimPrefType type, |
1764 gconstpointer value, gpointer data) | 1764 gconstpointer value, gpointer data) |
1832 } | 1832 } |
1833 | 1833 |
1834 void | 1834 void |
1835 gaim_proxy_uninit(void) | 1835 gaim_proxy_uninit(void) |
1836 { | 1836 { |
1837 while (connect_infos != NULL) | 1837 while (connect_datas != NULL) |
1838 gaim_proxy_connect_info_destroy(connect_infos->data); | 1838 gaim_proxy_connect_data_destroy(connect_datas->data); |
1839 } | 1839 } |