[gvfs] ftp: Use TCP_NODELAY



commit 4667adac97ff1617373c3d3d7f56ba9f94bda877
Author: Ross Lagerwall <rosslagerwall gmail com>
Date:   Thu Feb 26 22:48:13 2015 +0000

    ftp: Use TCP_NODELAY
    
    When ftp is layered on top of TLS, it does a write-write-read which
    causes a large amount of latency due to the combination of Nagle's
    algorithm and delayed ACKs. Use TCP_NODELAY to disable Nagle's algorithm
    and prevent this.
    
    The flag is used for both secure and normal connections.  This should
    not cause any issues.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=526582

 daemon/gvfsftpconnection.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)
---
diff --git a/daemon/gvfsftpconnection.c b/daemon/gvfsftpconnection.c
index 217d798..2db6f51 100644
--- a/daemon/gvfsftpconnection.c
+++ b/daemon/gvfsftpconnection.c
@@ -26,6 +26,7 @@
 
 #include <string.h>
 #include <glib/gi18n.h>
+#include <gio/gnetworking.h>
 
 #include "gvfsbackendftp.h"
 
@@ -63,6 +64,21 @@ enable_keepalive (GSocketConnection *conn)
   g_socket_set_keepalive (g_socket_connection_get_socket (conn), TRUE);
 }
 
+/* Set TCP_NODELAY on the connection to avoid a bad interaction between Nagle's
+ * algorithm and delayed acks when doing a write-write-read. */
+static void
+enable_nodelay (GSocketConnection *conn)
+{
+  GError *error = NULL;
+  GSocket *socket = g_socket_connection_get_socket (conn);
+
+  if (!g_socket_set_option (socket, IPPROTO_TCP, TCP_NODELAY, TRUE, &error))
+    {
+      g_warning ("Could not set TCP_NODELAY: %s\n", error->message);
+      g_error_free (error);
+    }
+}
+
 static void
 create_input_stream (GVfsFtpConnection *conn)
 {
@@ -100,6 +116,7 @@ g_vfs_ftp_connection_new (GSocketConnectable *addr,
     }
 
   conn->connection = G_SOCKET_CONNECTION (conn->commands);
+  enable_nodelay (conn->connection);
   enable_keepalive (conn->connection);
   create_input_stream (conn);
   /* The first thing that needs to happen is receiving the welcome message */
@@ -334,6 +351,8 @@ g_vfs_ftp_connection_open_data_connection (GVfsFtpConnection *conn,
                                                      G_SOCKET_CONNECTABLE (addr),
                                                      cancellable,
                                                      error));
+  if (conn->data)
+    enable_nodelay (G_SOCKET_CONNECTION (conn->data));
 
   return conn->data != NULL;
 }
@@ -474,6 +493,7 @@ g_vfs_ftp_connection_accept_data_connection (GVfsFtpConnection *conn,
 
   conn->data = G_IO_STREAM (g_socket_connection_factory_create_connection (accepted));
   g_object_unref (accepted);
+  enable_nodelay (G_SOCKET_CONNECTION (conn->data));
   return TRUE;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]