im.pidgin.pidgin: 7a98d978e56502762335bda8f19011a139ac460a
datallah at pidgin.im
datallah at pidgin.im
Tue Nov 13 01:35:45 EST 2007
-----------------------------------------------------------------
Revision: 7a98d978e56502762335bda8f19011a139ac460a
Ancestor: a3430424ec320991ba0e73fcd49b3c87526dd307
Author: datallah at pidgin.im
Date: 2007-11-13T06:27:27
Branch: im.pidgin.pidgin
Modified files:
libpurple/protocols/bonjour/bonjour_ft.c
ChangeLog:
My changes to disable external port mapping exposed a flaw where the server socket was being closed immediately, before the client had read all the data - this caused the client to receive a RST and consequently error. The solution is to wait for the client to close the connection before closing the server connection. I'm surprised this hasn't been a problem elsewhere - it seems like it would be.
-------------- next part --------------
============================================================
--- libpurple/protocols/bonjour/bonjour_ft.c 41e0adc50742131e79c29cf0df5f46a29e695459
+++ libpurple/protocols/bonjour/bonjour_ft.c e1df8a54a25ee1a6219c4e7ffc6343f7ba9db0ea
@@ -96,10 +96,42 @@ static void bonjour_xfer_cancel_recv(Pur
bonjour_free_xfer(xfer);
}
+struct socket_cleanup {
+ int fd;
+ guint handle;
+};
+static void
+_wait_for_socket_close(gpointer data, gint source, PurpleInputCondition cond)
+{
+ struct socket_cleanup *sc = data;
+ char buf[1];
+ int ret;
+
+ ret = recv(source, buf, 1, 0);
+
+ if (ret == 0 || (ret == -1 && !(errno == EAGAIN || errno == EWOULDBLOCK))) {
+ purple_debug_info("bonjour", "Client completed recieving; closing server socket.\n");
+ purple_input_remove(sc->handle);
+ close(sc->fd);
+ g_free(sc);
+ }
+}
+
static void bonjour_xfer_end(PurpleXfer *xfer)
{
purple_debug_info("bonjour", "Bonjour-xfer-end.\n");
+
+ /* We can't allow the server side to close the connection until the client is complete,
+ * otherwise there is a RST resulting in an error on the client side */
+ if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && purple_xfer_is_completed(xfer)) {
+ struct socket_cleanup *sc = g_new0(struct socket_cleanup, 1);
+ sc->fd = xfer->fd;
+ xfer->fd = -1;
+ sc->handle = purple_input_add(sc->fd, PURPLE_INPUT_READ,
+ _wait_for_socket_close, sc);
+ }
+
bonjour_free_xfer(xfer);
}
@@ -568,6 +600,8 @@ bonjour_sock5_request_cb(gpointer data,
if(xf == NULL)
return;
+ purple_debug_info("bonjour", "bonjour_sock5_request_cb - req_state = 0x%x\n", xf->sock5_req_state);
+
switch(xf->sock5_req_state){
case 0x00:
acceptfd = accept(source, NULL, 0);
@@ -576,7 +610,13 @@ bonjour_sock5_request_cb(gpointer data,
} else if(acceptfd == -1) {
} else {
- purple_debug_info("bonjour", "Conjour-sock5-request-cb. state= %d, accept=%d\n", xf->sock5_req_state, acceptfd);
+ int flags;
+
+ purple_debug_info("bonjour", "Accepted SOCKS5 ft connection - fd=%d\n", acceptfd);
+
+ flags = fcntl(acceptfd, F_GETFL);
+ fcntl(acceptfd, F_SETFL, flags | O_NONBLOCK);
+
purple_input_remove(xfer->watcher);
close(source);
xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ,
More information about the Commits
mailing list