diff options
author | dequis <dx@dxzone.com.ar> | 2015-10-25 01:06:22 -0300 |
---|---|---|
committer | dequis <dx@dxzone.com.ar> | 2015-10-26 00:42:15 -0300 |
commit | 4e365cec5275e3dec782af3ec0bc9a651cc2b831 (patch) | |
tree | 08382036a53279ac3681ea848e423ebc1881beb7 /lib/proxy.c | |
parent | f710673a3d6f7d602c8261789ae78a4f273fb1a9 (diff) |
Add proxy_disconnect() to interrupt possibly pending connections
Fixes trac ticket 1198, https://bugs.bitlbee.org/bitlbee/ticket/1198
This function can be used as a safe drop-in replacement to closesocket()
If a proxy connection is pending (connected callback still not called),
it looks up the PHB in a hash table indexed by fd. If it is there, it
closes, frees the phb and avoids further calls to the callback.
If it is not in there, it just does closesocket()
Diffstat (limited to 'lib/proxy.c')
-rw-r--r-- | lib/proxy.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/lib/proxy.c b/lib/proxy.c index 88649d4e..af30cf4f 100644 --- a/lib/proxy.c +++ b/lib/proxy.c @@ -50,6 +50,8 @@ char proxypass[128] = ""; #define AI_ADDRCONFIG 0 #endif +static GHashTable *phb_hash = NULL; + struct PHB { b_event_handler func, proxy_func; gpointer data, proxy_data; @@ -66,6 +68,8 @@ static int proxy_connect_none(const char *host, unsigned short port_, struct PHB static gboolean phb_free(struct PHB *phb, gboolean success) { + g_hash_table_remove(phb_hash, &phb->fd); + if (!success) { if (phb->fd > 0) { closesocket(phb->fd); @@ -99,6 +103,7 @@ static gboolean proxy_connected(gpointer data, gint source, b_input_condition co closesocket(source); dup2(new_fd, source); closesocket(new_fd); + phb->fd = source; phb->inpa = b_input_add(source, B_EV_IO_WRITE, proxy_connected, phb); return FALSE; } @@ -522,6 +527,11 @@ int proxy_connect(const char *host, int port, b_event_handler func, gpointer dat { struct PHB *phb; proxy_connect_func fun; + int fd; + + if (!phb_hash) { + phb_hash = g_hash_table_new(g_int_hash, g_int_equal); + } if (!host || port <= 0 || !func || strlen(host) > 128) { return -1; @@ -537,5 +547,33 @@ int proxy_connect(const char *host, int port, b_event_handler func, gpointer dat fun = proxy_connect_none; } - return fun(host, port, phb); + fd = fun(host, port, phb); + + if (fd != -1) { + g_hash_table_insert(phb_hash, &phb->fd, phb); + } + + return fd; +} + +void proxy_disconnect(int fd) +{ + struct PHB *phb = g_hash_table_lookup(phb_hash, &fd); + + if (!phb) { + /* not in the early part of the connection - just close the fd */ + closesocket(fd); + return; + } + + if (phb->inpa) { + b_event_remove(phb->inpa); + phb->inpa = 0; + } + + /* avoid calling the callback, which might result in double-free */ + phb->func = NULL; + + /* close and free */ + phb_free(phb, FALSE); } |