Mercurial > pidgin
changeset 14267:645598a4ec04
[gaim-migrate @ 16949]
Change gaim_network_listen() and gaim_network_listen_range()
to be cancelable. This doesn't actually help anything yet,
since the gaim_upnp_functions() are not yet cancelable. But
the framework is there, and the PRPLs shouldn't need any
additional changes.
Still to go:
gaim_upnp_everything()
gaim_url_fetch()
gaim_srv_resolve()
Let me know if there are others
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 21 Aug 2006 07:47:03 +0000 |
parents | 63ef6342db05 |
children | e6892c0050ad |
files | doc/ChangeLog.API libgaim/network.c libgaim/network.h libgaim/plugins/perl/common/Network.xs libgaim/plugins/perl/common/module.h libgaim/protocols/irc/dcc_send.c libgaim/protocols/jabber/si.c libgaim/protocols/oscar/peer.c libgaim/protocols/oscar/peer.h libgaim/protocols/simple/simple.c libgaim/protocols/simple/simple.h |
diffstat | 11 files changed, 146 insertions(+), 93 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/ChangeLog.API Mon Aug 21 07:44:31 2006 +0000 +++ b/doc/ChangeLog.API Mon Aug 21 07:47:03 2006 +0000 @@ -91,6 +91,8 @@ * gaim_network_listen() and gaim_network_listen_range(): Added socket_type parameter to allow creation of UDP listening. Modified to be asynchronous with a callback to allow for UPnP operation. + Returns a data structure that can be used to cancel the listen + attempt using gaim_network_listen_cancel() * GaimPrefCallback: val is now a gconstpointer instead of a gpointer * gtk_imhtml_get_current_format(): the arguments are now set to TRUE or FALSE. Previously they were set to TRUE or left alone. Also, you @@ -117,6 +119,9 @@ * gaim_proxy_connect(): changed to return NULL on error and a pointer to a GaimProxyConnectInfo object which can be used to cancel connection attempts using gaim_proxy_connect_cancel(). + * gaim_gethostbyname_async(): Renamed to gaim_dnsquery_a() and + changed to return a pointer to a data structure that can be + used to cancel the pending DNS query using gaim_dnsquery_destroy() * gaim_gtk_create_imhtml(): Added sw_ret() parameter * gaim_account_get_log(): Added create parameter * GAIM_CMD_P_VERYHIGH is now GAIM_CMD_P_VERY_HIGH @@ -296,6 +301,12 @@ * gaim_proxy_get_setup() * GaimNotifySearchResultsCallback: Added user_data. * gaim_notify_searchresults: Added user_data. + * gaim_network_listen_cancel(): Can be used to cancel a previous + call to gaim_network_listen() or gaim_network_listen_range() + * gaim_proxy_connect_cancel(): Can be used to cancel a pending + gaim_proxy_connect() request + * gaim_dnsquery_destroy(): Can be used to cancel a pending DNS + query. Signals - Changed: (See the Doxygen docs for details on all signals.) * Signal propagation now stops after a handler returns a non-NULL value.
--- a/libgaim/network.c Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/network.c Mon Aug 21 07:47:03 2006 +0000 @@ -42,14 +42,14 @@ #include "stun.h" #include "upnp.h" -typedef struct { +struct _GaimNetworkListenData { int listenfd; int socket_type; gboolean retry; gboolean adding; GaimNetworkListenCallback cb; gpointer cb_data; -} ListenUPnPData; +}; const unsigned char * gaim_network_ip_atoi(const char *ip) @@ -169,43 +169,49 @@ static void gaim_network_set_upnp_port_mapping_cb(gboolean success, gpointer data) { - ListenUPnPData *ldata = data; + GaimNetworkListenData *listen_data; + + listen_data = data; + /* TODO: Once we're keeping track of upnp requests... */ + /* listen_data->pnp_data = NULL; */ if (!success) { gaim_debug_info("network", "Couldn't create UPnP mapping\n"); - if (ldata->retry) { - ldata->retry = FALSE; - ldata->adding = FALSE; + if (listen_data->retry) { + listen_data->retry = FALSE; + listen_data->adding = FALSE; + /* TODO: Need to keep track of this return value! */ gaim_upnp_remove_port_mapping( - gaim_network_get_port_from_fd(ldata->listenfd), - (ldata->socket_type == SOCK_STREAM) ? "TCP" : "UDP", - gaim_network_set_upnp_port_mapping_cb, ldata); + gaim_network_get_port_from_fd(listen_data->listenfd), + (listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP", + gaim_network_set_upnp_port_mapping_cb, listen_data); return; } - } else if (!ldata->adding) { + } else if (!listen_data->adding) { /* We've tried successfully to remove the port mapping. * Try to add it again */ - ldata->adding = TRUE; + listen_data->adding = TRUE; + /* TODO: Need to keep track of this return value! */ gaim_upnp_set_port_mapping( - gaim_network_get_port_from_fd(ldata->listenfd), - (ldata->socket_type == SOCK_STREAM) ? "TCP" : "UDP", - gaim_network_set_upnp_port_mapping_cb, ldata); + gaim_network_get_port_from_fd(listen_data->listenfd), + (listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP", + gaim_network_set_upnp_port_mapping_cb, listen_data); return; } - if (ldata->cb) - ldata->cb(ldata->listenfd, ldata->cb_data); + if (listen_data->cb) + listen_data->cb(listen_data->listenfd, listen_data->cb_data); - g_free(ldata); + gaim_network_listen_cancel(listen_data); } -static gboolean +static GaimNetworkListenData * gaim_network_do_listen(unsigned short port, int socket_type, GaimNetworkListenCallback cb, gpointer cb_data) { int listenfd = -1; const int on = 1; - ListenUPnPData *ld; + GaimNetworkListenData *listen_data; #ifdef HAVE_GETADDRINFO int errnum; struct addrinfo hints, *res, *next; @@ -228,7 +234,7 @@ #else gaim_debug_warning("network", "getaddrinfo: Error Code = %d\n", errnum); #endif - return FALSE; + return NULL; } /* @@ -252,13 +258,13 @@ freeaddrinfo(res); if (next == NULL) - return FALSE; + return NULL; #else struct sockaddr_in sockin; if ((listenfd = socket(AF_INET, socket_type, 0)) < 0) { gaim_debug_warning("network", "socket: %s\n", strerror(errno)); - return FALSE; + return NULL; } if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) @@ -271,48 +277,49 @@ if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { gaim_debug_warning("network", "bind: %s\n", strerror(errno)); close(listenfd); - return FALSE; + return NULL; } #endif if (socket_type == SOCK_STREAM && listen(listenfd, 4) != 0) { gaim_debug_warning("network", "listen: %s\n", strerror(errno)); close(listenfd); - return FALSE; + return NULL; } fcntl(listenfd, F_SETFL, O_NONBLOCK); gaim_debug_info("network", "Listening on port: %hu\n", gaim_network_get_port_from_fd(listenfd)); - ld = g_new0(ListenUPnPData, 1); - ld->listenfd = listenfd; - ld->adding = TRUE; - ld->retry = TRUE; - ld->cb = cb; - ld->cb_data = cb_data; + listen_data = g_new0(GaimNetworkListenData, 1); + listen_data->listenfd = listenfd; + listen_data->adding = TRUE; + listen_data->retry = TRUE; + listen_data->cb = cb; + listen_data->cb_data = cb_data; + /* TODO: Need to keep track of this return value! */ gaim_upnp_set_port_mapping( gaim_network_get_port_from_fd(listenfd), (socket_type == SOCK_STREAM) ? "TCP" : "UDP", - gaim_network_set_upnp_port_mapping_cb, ld); + gaim_network_set_upnp_port_mapping_cb, listen_data); - return TRUE; + return listen_data; } -gboolean +GaimNetworkListenData * gaim_network_listen(unsigned short port, int socket_type, GaimNetworkListenCallback cb, gpointer cb_data) { - g_return_val_if_fail(port != 0, -1); + g_return_val_if_fail(port != 0, NULL); return gaim_network_do_listen(port, socket_type, cb, cb_data); } -gboolean +GaimNetworkListenData * gaim_network_listen_range(unsigned short start, unsigned short end, int socket_type, GaimNetworkListenCallback cb, gpointer cb_data) { - gboolean ret = FALSE; + GaimNetworkListenData *ret = NULL; if (gaim_prefs_get_bool("/core/network/ports_range_use")) { start = gaim_prefs_get_int("/core/network/ports_range_start"); @@ -324,13 +331,18 @@ for (; start <= end; start++) { ret = gaim_network_do_listen(start, socket_type, cb, cb_data); - if (ret) + if (ret != NULL) break; } return ret; } +void gaim_network_listen_cancel(GaimNetworkListenData *listen_data) +{ + g_free(listen_data); +} + unsigned short gaim_network_get_port_from_fd(int fd) {
--- a/libgaim/network.h Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/network.h Mon Aug 21 07:47:03 2006 +0000 @@ -25,11 +25,6 @@ #ifndef _GAIM_NETWORK_H_ #define _GAIM_NETWORK_H_ -/* - * TODO: This API needs a way to cancel pending calls to - * gaim_network_listen_range() and company. - */ - #ifdef __cplusplus extern "C" { #endif @@ -39,6 +34,8 @@ /**************************************************************************/ /*@{*/ +typedef struct _GaimNetworkListenData GaimNetworkListenData; + typedef void (*GaimNetworkListenCallback) (int listenfd, gpointer data); /** @@ -129,11 +126,12 @@ * this callback, or -1 if no socket could be established. * @param cb_data extra data to be returned when cb is called * - * @return TRUE if the callback will be invoked, or FALSE if unable to obtain - * a local socket to listen on. + * @return A pointer to a data structure that can be used to cancel + * the pending listener, or NULL if unable to obtain a local + * socket to listen on. */ -gboolean gaim_network_listen(unsigned short port, int socket_type, - GaimNetworkListenCallback cb, gpointer cb_data); +GaimNetworkListenData *gaim_network_listen(unsigned short port, + int socket_type, GaimNetworkListenCallback cb, gpointer cb_data); /** * Opens a listening port selected from a range of ports. The range of @@ -161,11 +159,23 @@ * this callback, or -1 if no socket could be established. * @param cb_data extra data to be returned when cb is called * - * @return TRUE if the callback will be invoked, or FALSE if unable to obtain - * a local socket to listen on. + * @return A pointer to a data structure that can be used to cancel + * the pending listener, or NULL if unable to obtain a local + * socket to listen on. */ -gboolean gaim_network_listen_range(unsigned short start, unsigned short end, - int socket_type, GaimNetworkListenCallback cb, gpointer cb_data); +GaimNetworkListenData *gaim_network_listen_range(unsigned short start, + unsigned short end, int socket_type, + GaimNetworkListenCallback cb, gpointer cb_data); + +/** + * This can be used to cancel any in-progress listener connection + * by passing in the return value from either gaim_network_listen() + * or gaim_network_listen_range(). + * + * @param listen_data This listener attempt will be canceled and + * the struct will be freed. + */ +void gaim_network_listen_cancel(GaimNetworkListenData *listen_data); /** * Gets a port number from a file descriptor.
--- a/libgaim/plugins/perl/common/Network.xs Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/plugins/perl/common/Network.xs Mon Aug 21 07:47:03 2006 +0000 @@ -25,14 +25,14 @@ gaim_network_ip_atoi(ip) const char *ip -int +Gaim::NetworkListenData * gaim_network_listen(port, socket_type, cb, cb_data) unsigned short port int socket_type Gaim::NetworkListenCallback cb gpointer cb_data -int +Gaim::NetworkListenData * gaim_network_listen_range(start, end, socket_type, cb, cb_data) unsigned short start unsigned short end
--- a/libgaim/plugins/perl/common/module.h Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/plugins/perl/common/module.h Mon Aug 21 07:47:03 2006 +0000 @@ -159,6 +159,7 @@ typedef GaimLogType Gaim__LogType; /* network.h */ +typedef GaimNetworkListenData Gaim__NetworkListenData; typedef GaimNetworkListenCallback Gaim__NetworkListenCallback; /* notify.h */
--- a/libgaim/protocols/irc/dcc_send.c Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/protocols/irc/dcc_send.c Mon Aug 21 07:47:03 2006 +0000 @@ -142,6 +142,7 @@ *******************************************************************/ struct irc_xfer_send_data { + GaimNetworkListenData *listen_data; gint inpa; int fd; guchar *rxqueue; @@ -155,6 +156,8 @@ if (xd == NULL) return; + if (xd->listen_data != NULL) + gaim_network_listen_cancel(xd->listen_data); if (xd->inpa > 0) gaim_input_remove(xd->inpa); if (xd->fd != -1) @@ -271,6 +274,9 @@ struct in_addr addr; unsigned short int port; + xd = xfer->data; + xd->listen_data = NULL; + if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL || gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_REMOTE) { gaim_xfer_unref(xfer); @@ -314,14 +320,16 @@ */ static void irc_dccsend_send_init(GaimXfer *xfer) { GaimConnection *gc = gaim_account_get_connection(gaim_xfer_get_account(xfer)); + struct irc_xfer_send_data *xd = xfer->data; xfer->filename = g_path_get_basename(xfer->local_filename); gaim_xfer_ref(xfer); /* Create a listening socket */ - if (!gaim_network_listen_range(0, 0, SOCK_STREAM, - irc_dccsend_network_listen_cb, xfer)) { + xd->listen_data = gaim_network_listen_range(0, 0, SOCK_STREAM, + irc_dccsend_network_listen_cb, xfer); + if (xd->listen_data == NULL) { gaim_xfer_unref(xfer); gaim_notify_error(gc, NULL, _("File Transfer Failed"), _("Gaim could not open a listening port."));
--- a/libgaim/protocols/jabber/si.c Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/protocols/jabber/si.c Mon Aug 21 07:47:03 2006 +0000 @@ -47,6 +47,7 @@ JabberStream *js; GaimProxyConnectData *connect_data; + GaimNetworkListenData *listen_data; gboolean accepted; @@ -539,13 +540,14 @@ xmlnode *query, *streamhost; char *jid, *port; + jsx = xfer->data; + jsx->listen_data = NULL; + if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) { gaim_xfer_unref(xfer); return; } - jsx = xfer->data; - gaim_xfer_unref(xfer); if (sock < 0) { @@ -588,10 +590,14 @@ static void jabber_si_xfer_bytestreams_send_init(GaimXfer *xfer) { + JabberSIXfer *jsx; + gaim_xfer_ref(xfer); - if(!gaim_network_listen_range(0, 0, SOCK_STREAM, - jabber_si_xfer_bytestreams_listen_cb, xfer)) { + jsx = xfer->data; + jsx->listen_data = gaim_network_listen_range(0, 0, SOCK_STREAM, + jabber_si_xfer_bytestreams_listen_cb, xfer); + if (jsx->listen_data == NULL) { gaim_xfer_unref(xfer); /* XXX: couldn't open a port, we're fscked */ gaim_xfer_cancel_local(xfer); @@ -698,6 +704,8 @@ if (jsx->connect_data != NULL) gaim_proxy_connect_cancel(jsx->connect_data); + if (jsx->listen_data != NULL) + gaim_network_listen_cancel(jsx->listen_data); g_free(jsx->stream_id); g_free(jsx->iq_id);
--- a/libgaim/protocols/oscar/peer.c Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/protocols/oscar/peer.c Mon Aug 21 07:47:03 2006 +0000 @@ -145,6 +145,12 @@ conn->connect_data = NULL; } + if (conn->listen_data != NULL) + { + gaim_network_listen_cancel(conn->listen_data); + conn->listen_data = NULL; + } + if (conn->connect_timeout_timer != 0) { gaim_timeout_remove(conn->connect_timeout_timer); @@ -561,7 +567,6 @@ static void peer_connection_establish_listener_cb(int listenerfd, gpointer data) { - NewPeerConnectionData *new_conn_data; PeerConnection *conn; OscarData *od; GaimConnection *gc; @@ -572,17 +577,8 @@ const char *listener_ip; unsigned short listener_port; - new_conn_data = data; - gc = new_conn_data->gc; - conn = new_conn_data->conn; - g_free(new_conn_data); - - if (!GAIM_CONNECTION_IS_VALID(gc)) - { - if (listenerfd != -1) - close(listenerfd); - return; - } + conn = data; + conn->listen_data = NULL; if (listenerfd == -1) { @@ -592,6 +588,7 @@ } od = conn->od; + gc = od->gc; account = gaim_connection_get_account(gc); conn->listenerfd = listenerfd; @@ -757,12 +754,6 @@ if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_INCOMING) && (!conn->use_proxy)) { - NewPeerConnectionData *new_conn_data; - - new_conn_data = g_new(NewPeerConnectionData, 1); - new_conn_data->gc = conn->od->gc; - new_conn_data->conn = conn; - conn->flags |= PEER_CONNECTION_FLAG_TRIED_INCOMING; /* @@ -771,14 +762,13 @@ */ conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING; - if (gaim_network_listen_range(5190, 5290, SOCK_STREAM, - peer_connection_establish_listener_cb, new_conn_data)) + conn->listen_data = gaim_network_listen_range(5190, 5290, SOCK_STREAM, + peer_connection_establish_listener_cb, conn); + if (conn->listen_data != NULL) { /* Opening listener socket... */ return; } - - g_free(new_conn_data); } /*
--- a/libgaim/protocols/oscar/peer.h Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/protocols/oscar/peer.h Mon Aug 21 07:47:03 2006 +0000 @@ -26,11 +26,12 @@ #define _PEER_H_ #include "ft.h" +#include "network.h" +#include "proxy.h" typedef struct _OdcFrame OdcFrame; typedef struct _OftFrame OftFrame; typedef struct _ProxyFrame ProxyFrame; -typedef struct _NewPeerConnectionData NewPeerConnectionData; typedef struct _PeerConnection PeerConnection; #define PEER_CONNECTION_FLAG_INITIATED_BY_ME 0x0001 @@ -132,12 +133,6 @@ ByteStream payload; /* 12 */ }; -struct _NewPeerConnectionData -{ - GaimConnection *gc; - PeerConnection *conn; -}; - struct _PeerConnection { OscarData *od; @@ -166,6 +161,12 @@ /** * This is only used when the peer connection is being established. */ + GaimNetworkListenData *listen_data; + + + /** + * This is only used when the peer connection is being established. + */ guint connect_timeout_timer; /**
--- a/libgaim/protocols/simple/simple.c Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/protocols/simple/simple.c Mon Aug 21 07:47:03 2006 +0000 @@ -1506,6 +1506,8 @@ static void simple_udp_host_resolved_listen_cb(int listenfd, gpointer data) { struct simple_account_data *sip = (struct simple_account_data*) data; + sip->listen_data = NULL; + if(listenfd == -1) { gaim_connection_error(sip->gc, _("Could not create listen socket")); return; @@ -1546,8 +1548,9 @@ } /* create socket for incoming connections */ - if(!gaim_network_listen_range(5060, 5160, SOCK_DGRAM, - simple_udp_host_resolved_listen_cb, sip)) { + sip->listen_data = gaim_network_listen_range(5060, 5160, SOCK_DGRAM, + simple_udp_host_resolved_listen_cb, sip); + if (sip->listen_data == NULL) { gaim_connection_error(sip->gc, _("Could not create listen socket")); return; } @@ -1558,6 +1561,8 @@ struct simple_account_data *sip = (struct simple_account_data*) data; GaimProxyConnectData *connect_data; + sip->listen_data = NULL; + sip->listenfd = listenfd; if(sip->listenfd == -1) { gaim_connection_error(sip->gc, _("Could not create listen socket")); @@ -1616,8 +1621,9 @@ /* TCP case */ if(!sip->udp) { /* create socket for incoming connections */ - if(!gaim_network_listen_range(5060, 5160, SOCK_STREAM, - simple_tcp_connect_listen_cb, sip)) { + sip->listen_data = gaim_network_listen_range(5060, 5160, SOCK_STREAM, + simple_tcp_connect_listen_cb, sip); + if (sip->listen_data == NULL) { gaim_connection_error(sip->gc, _("Could not create listen socket")); return; } @@ -1697,6 +1703,9 @@ if (sip->query_data != NULL) gaim_dnsquery_destroy(sip->query_data); + if (sip->listen_data != NULL) + gaim_network_listen_cancel(sip->listen_data); + g_free(sip->servername); g_free(sip->username); g_free(sip->password);
--- a/libgaim/protocols/simple/simple.h Mon Aug 21 07:44:31 2006 +0000 +++ b/libgaim/protocols/simple/simple.h Mon Aug 21 07:47:03 2006 +0000 @@ -1,10 +1,10 @@ /** * @file simple.h - * + * * gaim * * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de> - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -29,6 +29,8 @@ #include "cipher.h" #include "circbuffer.h" #include "dnsquery.h" +#include "network.h" +#include "proxy.h" #include "prpl.h" #include "sipmsg.h" @@ -71,6 +73,7 @@ gchar *username; gchar *password; GaimDnsQueryData *query_data; + GaimNetworkListenData *listen_data; int fd; int cseq; time_t reregister;