comparison src/protocols/oscar/oscar.c @ 12909:8e3b85fe4a55

[gaim-migrate @ 15262] Make UPnP truly asynchronous. There are probably still a couple socket calls that should be made nonblocking, but I wanted to commit this before it became even bigger. This contains a number of probable leak fixes in the upnp stuff. The UPnP stuff has been updated to use gaim_url_fetch_request() instead of the specific implementation. To make this all work, I had to make gaim_network_listen() and gaim_network_listen_range() also asynchronous - seems to work just fine apart from the UPnP calls seeming to take longer than they should (I'm planning to look into this). I also triggered a STUN and UPnP discovery on startup so that we hopefully have the information when we need it. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Tue, 17 Jan 2006 05:48:51 +0000
parents ff267281e882
children a05fbd9dcc31
comparison
equal deleted inserted replaced
12908:4f2b96f23700 12909:8e3b85fe4a55
1505 static void oscar_cancel_direct_im(struct ask_do_dir_im *data) { 1505 static void oscar_cancel_direct_im(struct ask_do_dir_im *data) {
1506 g_free(data->who); 1506 g_free(data->who);
1507 g_free(data); 1507 g_free(data);
1508 } 1508 }
1509 1509
1510 struct dir_im_listen {
1511 struct oscar_direct_im *dim;
1512 const guchar *cookie;
1513 };
1514
1515 static void
1516 oscar_direct_im_listen_cb(int listenfd, gpointer data) {
1517 struct dir_im_listen *dim_l = data;
1518 const char *ip;
1519 OscarData *od;
1520 struct oscar_direct_im *dim = dim_l->dim;
1521
1522 od = (OscarData *)dim->gc->proto_data;
1523
1524 /* XXX: shouldn't this be your public IP or something? */
1525 ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1);
1526
1527 if (listenfd >= 0)
1528 dim->conn = aim_odc_initiate(od->sess, dim->name, listenfd,
1529 gaim_network_ip_atoi(ip),
1530 gaim_network_get_port_from_fd(listenfd), dim_l->cookie);
1531
1532 if (dim->conn != NULL) {
1533 char *tmp;
1534 GaimConversation *conv;
1535
1536 od->direct_ims = g_slist_append(od->direct_ims, dim);
1537 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,
1538 oscar_callback, dim->conn);
1539 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED,
1540 gaim_odc_initiate, 0);
1541
1542 conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, dim->gc->account, dim->name);
1543 tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for Direct IM."), dim->name, ip,
1544 gaim_network_get_port_from_fd(listenfd));
1545 gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
1546 g_free(tmp);
1547 } else {
1548 gaim_notify_error(dim->gc, NULL, _("Unable to open Direct IM"), NULL);
1549 oscar_direct_im_destroy(od, dim);
1550 }
1551
1552 g_free(dim_l);
1553 }
1554
1510 /* this function is used to initiate a direct im session with someone. 1555 /* this function is used to initiate a direct im session with someone.
1511 * we start listening on a port and send a request. they either connect 1556 * we start listening on a port and send a request. they either connect
1512 * or send some kind of reply. If they can't connect, they ask us to 1557 * or send some kind of reply. If they can't connect, they ask us to
1513 * connect to them, and so we do that. 1558 * connect to them, and so we do that.
1514 * 1559 *
1518 * note that cookie is an 8 byte string that isn't NULL terminated 1563 * note that cookie is an 8 byte string that isn't NULL terminated
1519 */ 1564 */
1520 static void oscar_direct_im_initiate(GaimConnection *gc, const char *who, const guchar *cookie) { 1565 static void oscar_direct_im_initiate(GaimConnection *gc, const char *who, const guchar *cookie) {
1521 OscarData *od; 1566 OscarData *od;
1522 struct oscar_direct_im *dim; 1567 struct oscar_direct_im *dim;
1523 int listenfd; 1568 struct dir_im_listen *dim_l;
1524 const char *ip;
1525 1569
1526 od = (OscarData *)gc->proto_data; 1570 od = (OscarData *)gc->proto_data;
1527 1571
1528 dim = oscar_direct_im_find(od, who); 1572 dim = oscar_direct_im_find(od, who);
1529 if (dim) { 1573 if (dim) {
1538 } 1582 }
1539 dim = g_new0(struct oscar_direct_im, 1); 1583 dim = g_new0(struct oscar_direct_im, 1);
1540 dim->gc = gc; 1584 dim->gc = gc;
1541 g_snprintf(dim->name, sizeof dim->name, "%s", who); 1585 g_snprintf(dim->name, sizeof dim->name, "%s", who);
1542 1586
1543 listenfd = gaim_network_listen_range(5190, 5199, SOCK_STREAM); 1587 dim_l = g_new0(struct dir_im_listen, 1);
1544 ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1); 1588 dim_l->dim = dim;
1545 if (listenfd >= 0) 1589 dim_l->cookie = cookie;
1546 dim->conn = aim_odc_initiate(od->sess, who, listenfd, gaim_network_ip_atoi(ip), gaim_network_get_port_from_fd(listenfd), cookie); 1590
1547 if (dim->conn != NULL) { 1591 if(!gaim_network_listen_range(5190, 5199, SOCK_STREAM, oscar_direct_im_listen_cb, dim)) {
1548 char *tmp;
1549 GaimConversation *conv;
1550
1551 od->direct_ims = g_slist_append(od->direct_ims, dim);
1552 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,
1553 oscar_callback, dim->conn);
1554 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED,
1555 gaim_odc_initiate, 0);
1556
1557 conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, dim->gc->account, who);
1558 tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for Direct IM."), who, ip,
1559 gaim_network_get_port_from_fd(listenfd));
1560 gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));
1561 g_free(tmp);
1562 } else {
1563 gaim_notify_error(gc, NULL, _("Unable to open Direct IM"), NULL); 1592 gaim_notify_error(gc, NULL, _("Unable to open Direct IM"), NULL);
1564 oscar_direct_im_destroy(od, dim); 1593 oscar_direct_im_destroy(od, dim);
1594 g_free(dim_l);
1565 } 1595 }
1566 } 1596 }
1567 1597
1568 static void oscar_direct_im(struct ask_do_dir_im *data) { 1598 static void oscar_direct_im(struct ask_do_dir_im *data) {
1569 GaimConnection *gc = data->gc; 1599 GaimConnection *gc = data->gc;
2543 _("Unable to establish listener socket or no AOL proxy connection present.")); 2573 _("Unable to establish listener socket or no AOL proxy connection present."));
2544 gaim_xfer_cancel_local(xfer); 2574 gaim_xfer_cancel_local(xfer);
2545 } 2575 }
2546 } 2576 }
2547 2577
2578 static void
2579 oscar_xfer_init_listen_cb(int listenfd, gpointer data) {
2580 GaimXfer *xfer = data;
2581 struct aim_oft_info *oft_info;
2582 GaimConnection *gc;
2583 OscarData *od;
2584
2585 /* If the ft was canceled before we get here, don't continue */
2586 if(gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) {
2587 gaim_xfer_unref(xfer);
2588 return;
2589 }
2590
2591 oft_info = xfer->data;
2592 gc = oft_info->sess->aux_data;
2593 od = gc->proto_data;
2594
2595 if (listenfd < 0) {
2596 gaim_xfer_cancel_local(xfer);
2597 return;
2598 }
2599
2600 xfer->local_port = gaim_network_get_port_from_fd(listenfd);
2601 oft_info->port = xfer->local_port;
2602 if (aim_sendfile_listen(od->sess, oft_info, listenfd) != 0) {
2603 gaim_xfer_cancel_local(xfer);
2604 return;
2605 }
2606 gaim_debug_misc("oscar",
2607 "port is %hu, ip is %s\n",
2608 xfer->local_port, oft_info->clientip);
2609
2610 if(oft_info->conn)
2611 xfer->watcher = gaim_input_add(oft_info->conn->fd, GAIM_INPUT_READ, oscar_callback,
2612 oft_info->conn);
2613 else
2614 gaim_debug_info("oscar","NULL oft_info->conn; not adding watcher\n");
2615
2616 oscar_send_file_request(xfer);
2617 }
2618
2548 2619
2549 /* 2620 /*
2550 * Opens a listener socket in preparation for sending a file 2621 * Opens a listener socket in preparation for sending a file
2551 * This is not called if we are using a rendezvous proxy server 2622 * This is not called if we are using a rendezvous proxy server
2552 */ 2623 */
2553 static void oscar_xfer_init_send(GaimXfer *xfer) 2624 static void oscar_xfer_init_send(GaimXfer *xfer)
2554 { 2625 {
2555 struct aim_oft_info *oft_info = xfer->data;
2556 GaimConnection *gc = oft_info->sess->aux_data;
2557 OscarData *od = gc->proto_data;
2558 int listenfd;
2559
2560 gaim_debug_info("oscar", "AAA - in oscar_xfer_init_send\n"); 2626 gaim_debug_info("oscar", "AAA - in oscar_xfer_init_send\n");
2561 2627
2628 gaim_xfer_ref(xfer);
2629
2562 /* Create a listening socket and an associated libfaim conn */ 2630 /* Create a listening socket and an associated libfaim conn */
2563 if ((listenfd = gaim_network_listen_range(5190, 5199, SOCK_STREAM)) < 0) { 2631 if (!gaim_network_listen_range(5190, 5199, SOCK_STREAM,
2632 oscar_xfer_init_listen_cb, xfer)) {
2633 gaim_xfer_unref(xfer);
2564 gaim_xfer_cancel_local(xfer); 2634 gaim_xfer_cancel_local(xfer);
2565 return; 2635 return;
2566 } 2636 }
2567 xfer->local_port = gaim_network_get_port_from_fd(listenfd);
2568 oft_info->port = xfer->local_port;
2569 if (aim_sendfile_listen(od->sess, oft_info, listenfd) != 0) {
2570 gaim_xfer_cancel_local(xfer);
2571 return;
2572 }
2573 gaim_debug_misc("oscar",
2574 "port is %hu, ip is %s\n",
2575 xfer->local_port, oft_info->clientip);
2576
2577 if(oft_info->conn)
2578 xfer->watcher = gaim_input_add(oft_info->conn->fd, GAIM_INPUT_READ, oscar_callback,
2579 oft_info->conn);
2580 else
2581 gaim_debug_info("oscar","NULL oft_info->conn; not adding watcher\n");
2582
2583 oscar_send_file_request(xfer);
2584 } 2637 }
2585 2638
2586 /* 2639 /*
2587 * "On second thought, you don't deserve this file." 2640 * "On second thought, you don't deserve this file."
2588 */ 2641 */