diff src/protocols/irc/dcc_send.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 d5b8f4dc1622
children 33bef17125c2
line wrap: on
line diff
--- a/src/protocols/irc/dcc_send.c	Tue Jan 17 05:20:38 2006 +0000
+++ b/src/protocols/irc/dcc_send.c	Tue Jan 17 05:48:51 2006 +0000
@@ -250,23 +250,29 @@
 	gaim_xfer_start(xfer, conn, NULL, 0);
 }
 
-/*
- * This function is called after the user has selected a file to send.
- */
-static void irc_dccsend_send_init(GaimXfer *xfer) {
-	struct irc_xfer_send_data *xd = xfer->data;
-	GaimConnection *gc = gaim_account_get_connection(gaim_xfer_get_account(xfer));
-	struct irc_conn *irc = gc->proto_data;
-	int sock;
+static void
+irc_dccsend_network_listen_cb(int sock, gpointer data)
+{
+	GaimXfer *xfer = data;
+	struct irc_xfer_send_data *xd;
+	GaimConnection *gc;
+	struct irc_conn *irc;
 	const char *arg[2];
 	char *tmp;
 	struct in_addr addr;
 	unsigned short int port;
 
-	xfer->filename = g_path_get_basename(xfer->local_filename);
+	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);
+		return;
+	}
 
-	/* Create a listening socket */
-	sock = gaim_network_listen_range(0, 0, SOCK_STREAM);
+	xd = xfer->data;
+	gc = gaim_account_get_connection(gaim_xfer_get_account(xfer));
+	irc = gc->proto_data;
+
+	gaim_xfer_unref(xfer);
 
 	if (sock < 0) {
 		gaim_notify_error(gc, NULL, _("File Transfer Failed"),
@@ -294,6 +300,27 @@
 	g_free(tmp);
 }
 
+/*
+ * This function is called after the user has selected a file to send.
+ */
+static void irc_dccsend_send_init(GaimXfer *xfer) {
+	GaimConnection *gc = gaim_account_get_connection(gaim_xfer_get_account(xfer));
+
+	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)) {
+		gaim_xfer_unref(xfer);
+		gaim_notify_error(gc, NULL, _("File Transfer Failed"),
+		                  _("Gaim could not open a listening port."));
+		gaim_xfer_cancel_local(xfer);
+	}
+
+}
+
 GaimXfer *irc_dccsend_new_xfer(GaimConnection *gc, const char *who) {
 	GaimXfer *xfer;
 	struct irc_xfer_send_data *xd;