Mercurial > pidgin.yaz
comparison libpurple/network.c @ 15441:56a2a0bb290a
Fix a crash when a network_listen_range process is canceled before its UPnP port mapping completes, which occurs regularly on certain routers when file transfers are initiated and then quickly finished. Much thanks to Elliott Harris and Eric Richie for their hard work with me hunting this down and fixing it.
author | Evan Schoenberg <evan.s@dreskin.net> |
---|---|
date | Sun, 28 Jan 2007 15:05:23 +0000 |
parents | 5fe8042783c1 |
children | 552be3958d6a |
comparison
equal
deleted
inserted
replaced
15439:a415922e2882 | 15441:56a2a0bb290a |
---|---|
72 int socket_type; | 72 int socket_type; |
73 gboolean retry; | 73 gboolean retry; |
74 gboolean adding; | 74 gboolean adding; |
75 GaimNetworkListenCallback cb; | 75 GaimNetworkListenCallback cb; |
76 gpointer cb_data; | 76 gpointer cb_data; |
77 UPnPMappingAddRemove *mapping_data; | |
77 }; | 78 }; |
78 | 79 |
79 #ifdef HAVE_LIBNM | 80 #ifdef HAVE_LIBNM |
80 void nm_callback_func(libnm_glib_ctx* ctx, gpointer user_data); | 81 void nm_callback_func(libnm_glib_ctx* ctx, gpointer user_data); |
81 #endif | 82 #endif |
208 if (!success) { | 209 if (!success) { |
209 gaim_debug_info("network", "Couldn't create UPnP mapping\n"); | 210 gaim_debug_info("network", "Couldn't create UPnP mapping\n"); |
210 if (listen_data->retry) { | 211 if (listen_data->retry) { |
211 listen_data->retry = FALSE; | 212 listen_data->retry = FALSE; |
212 listen_data->adding = FALSE; | 213 listen_data->adding = FALSE; |
213 /* TODO: Need to keep track of this return value! */ | 214 listen_data->mapping_data = gaim_upnp_remove_port_mapping( |
214 gaim_upnp_remove_port_mapping( | 215 gaim_network_get_port_from_fd(listen_data->listenfd), |
215 gaim_network_get_port_from_fd(listen_data->listenfd), | 216 (listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP", |
216 (listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP", | 217 gaim_network_set_upnp_port_mapping_cb, listen_data); |
217 gaim_network_set_upnp_port_mapping_cb, listen_data); | |
218 return; | 218 return; |
219 } | 219 } |
220 } else if (!listen_data->adding) { | 220 } else if (!listen_data->adding) { |
221 /* We've tried successfully to remove the port mapping. | 221 /* We've tried successfully to remove the port mapping. |
222 * Try to add it again */ | 222 * Try to add it again */ |
223 listen_data->adding = TRUE; | 223 listen_data->adding = TRUE; |
224 /* TODO: Need to keep track of this return value! */ | 224 listen_data->mapping_data = gaim_upnp_set_port_mapping( |
225 gaim_upnp_set_port_mapping( | 225 gaim_network_get_port_from_fd(listen_data->listenfd), |
226 gaim_network_get_port_from_fd(listen_data->listenfd), | 226 (listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP", |
227 (listen_data->socket_type == SOCK_STREAM) ? "TCP" : "UDP", | 227 gaim_network_set_upnp_port_mapping_cb, listen_data); |
228 gaim_network_set_upnp_port_mapping_cb, listen_data); | |
229 return; | 228 return; |
230 } | 229 } |
231 | 230 |
232 if (listen_data->cb) | 231 if (listen_data->cb) |
233 listen_data->cb(listen_data->listenfd, listen_data->cb_data); | 232 listen_data->cb(listen_data->listenfd, listen_data->cb_data); |
234 | 233 |
234 /* Clear the UPnP mapping data, since it's complete and gaim_netweork_listen_cancel() will try to cancel | |
235 * it otherwise. */ | |
236 listen_data->mapping_data = NULL; | |
235 gaim_network_listen_cancel(listen_data); | 237 gaim_network_listen_cancel(listen_data); |
236 } | 238 } |
237 | 239 |
238 | 240 |
239 static GaimNetworkListenData * | 241 static GaimNetworkListenData * |
325 listen_data->adding = TRUE; | 327 listen_data->adding = TRUE; |
326 listen_data->retry = TRUE; | 328 listen_data->retry = TRUE; |
327 listen_data->cb = cb; | 329 listen_data->cb = cb; |
328 listen_data->cb_data = cb_data; | 330 listen_data->cb_data = cb_data; |
329 | 331 |
330 /* TODO: Need to keep track of this return value! */ | 332 listen_data->mapping_data = gaim_upnp_set_port_mapping( |
331 gaim_upnp_set_port_mapping( | 333 gaim_network_get_port_from_fd(listenfd), |
332 gaim_network_get_port_from_fd(listenfd), | 334 (socket_type == SOCK_STREAM) ? "TCP" : "UDP", |
333 (socket_type == SOCK_STREAM) ? "TCP" : "UDP", | 335 gaim_network_set_upnp_port_mapping_cb, listen_data); |
334 gaim_network_set_upnp_port_mapping_cb, listen_data); | |
335 | 336 |
336 return listen_data; | 337 return listen_data; |
337 } | 338 } |
338 | 339 |
339 GaimNetworkListenData * | 340 GaimNetworkListenData * |
368 return ret; | 369 return ret; |
369 } | 370 } |
370 | 371 |
371 void gaim_network_listen_cancel(GaimNetworkListenData *listen_data) | 372 void gaim_network_listen_cancel(GaimNetworkListenData *listen_data) |
372 { | 373 { |
374 if (listen_data->mapping_data != NULL) | |
375 gaim_upnp_cancel_port_mapping(listen_data->mapping_data); | |
376 | |
373 g_free(listen_data); | 377 g_free(listen_data); |
374 } | 378 } |
375 | 379 |
376 unsigned short | 380 unsigned short |
377 gaim_network_get_port_from_fd(int fd) | 381 gaim_network_get_port_from_fd(int fd) |