[gnome-mud] network: Switch to GIO as gnet is deprecated



commit b82052212635bcca4715b8012a1134203cc3589c
Author: Steven Jackson <sj oscode net>
Date:   Tue Apr 11 12:38:05 2017 +0100

    network: Switch to GIO as gnet is deprecated
    
    As these changes required mostly rewriting the lower level network code,
    I've included some refactoring - the connection is now its own class
    with signals on connect, disconnect and data ready.
    
    The code which loads proxy settings has been moved to its own function
    to remove duplication.
    
    The reconnect button is no longer clickable when connected. GIO
    connections are done asynchronously, so doing a disconnect and connect
    (old reconnect) requires waiting for the disconnect result. It's much
    simpler to handle reconnecting over 2 (likely more) main loop passes,
    and I think the new button behaviour makes more sense.
    
    GStreamer support is broken, you must configure with
    --disable-gstreamer, it is fixed in a following patch.
    
    Bug reports:
    - https://bugzilla.gnome.org/show_bug.cgi?id=593657

 configure.ac                      |    4 +-
 gnome-mud.spec.in                 |    2 -
 src/Makefile.am                   |    2 +
 src/gnome-mud.c                   |    4 -
 src/handlers/mud-telnet-charset.c |   27 ++--
 src/handlers/mud-telnet-msp.c     |    1 -
 src/handlers/mud-telnet-naws.c    |   20 +--
 src/handlers/mud-telnet-naws.h    |    2 -
 src/handlers/mud-telnet-zmp.c     |   20 +-
 src/mud-connection-view.c         |  402 ++++++++++++-------------------------
 src/mud-connection-view.h         |    4 +-
 src/mud-connection.c              |  384 +++++++++++++++++++++++++++++++++++
 src/mud-connection.h              |   83 ++++++++
 src/mud-telnet.c                  |   34 ++--
 src/mud-telnet.h                  |    1 -
 src/mud-window.c                  |   29 +--
 16 files changed, 646 insertions(+), 373 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 125b054..9a6e006 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,13 +72,13 @@ dnl pkg-config dep checks
 GMODULE_REQUIRED=2.0.0
 GTK_REQUIRED=2.20.0
 LIBGLADE_REQUIRED=2.0.1
-LIBGNET_REQUIRED=0.22
+LIBGLIB_REQUIRED=2.36
 VTE_REQUIRED=0.11.00
 PCRE_REQUIRED=6.0.0
 GCONF_REQUIRED=0.20
 GSTREAMER_REQUIRED=1.0
 
-PKG_CHECK_MODULES(GMUD, gtk+-2.0 >= $GTK_REQUIRED vte >= $VTE_REQUIRED libglade-2.0 >= $LIBGLADE_REQUIRED 
libpcre >= $PCRE_REQUIRED gmodule-2.0 >= $GMODULE_REQUIRED gnet-2.0 >= $LIBGNET_REQUIRED gconf-2.0 >= 
$GCONF_REQUIRED)
+PKG_CHECK_MODULES(GMUD, gtk+-2.0 >= $GTK_REQUIRED vte >= $VTE_REQUIRED libglade-2.0 >= $LIBGLADE_REQUIRED 
libpcre >= $PCRE_REQUIRED gmodule-2.0 >= $GMODULE_REQUIRED glib-2.0 >= $LIBGLIB_REQUIRED gconf-2.0 >= 
$GCONF_REQUIRED)
 AC_SUBST(GMUD_CFLAGS)
 AC_SUBST(GMUD_LIBS)
 
diff --git a/gnome-mud.spec.in b/gnome-mud.spec.in
index fd965c8..c9ab38e 100644
--- a/gnome-mud.spec.in
+++ b/gnome-mud.spec.in
@@ -19,11 +19,9 @@ Requires:       gstreamer >= 1.0
 Requires:       libpcre >= 6.0.0
 Requires:       gconf-2.0 >= 2.12.0
 Requires:       gtk+-2.0 >= 2.12.0
-Requires:       gnet-2.0 >= 2.0.0
 BuildRequires:  gtk+-2.0-devel >= 2.12.0
 BuildRequires:  libpcre-devel > = 6.0.0
 BuildRequires   gstreamer-devel >= 1.0
-BuildRequires   gnet-2.0-devel >= 2.0.0
 BuildRequires: vte-devel >= 0.10.26
 BuildRequires:  scrollkeeper >= @SCROLLKEEPER_BUILD_REQUIRED@
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 12d3faf..5ecbb85 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,6 +42,8 @@ gnome_mud_SOURCES =                           \
        mud-connections.c                       \
        mud-connections.h                       \
        mud-connection-view.h                   \
+       mud-connection.c                        \
+       mud-connection.h                        \
        mud-line-buffer.c                       \
        mud-line-buffer.h                       \
        mud-log.c                               \
diff --git a/src/gnome-mud.c b/src/gnome-mud.c
index 35e2108..308f258 100644
--- a/src/gnome-mud.c
+++ b/src/gnome-mud.c
@@ -27,7 +27,6 @@
 #include <gtk/gtk.h>
 #include <stdio.h>
 #include <sys/stat.h>
-#include <gnet.h>
 
 #ifdef ENABLE_GST
 #include <gst/gst.h>
@@ -66,9 +65,6 @@ main (gint argc, char *argv[])
 
     gtk_init(&argc, &argv);
 
-    /* Initialize the Gnet library */
-    gnet_init();
-
 #ifdef ENABLE_GST
     /* Initialize GStreamer */
     gst_init(&argc, &argv);
diff --git a/src/handlers/mud-telnet-charset.c b/src/handlers/mud-telnet-charset.c
index 73b2431..8251275 100644
--- a/src/handlers/mud-telnet-charset.c
+++ b/src/handlers/mud-telnet-charset.c
@@ -24,12 +24,12 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <glib/gi18n.h>
-#include <gnet.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <glib/gprintf.h>
 
 #include "gnome-mud.h"
+#include "mud-connection.h"
 #include "mud-telnet.h"
 #include "mud-telnet-handler-interface.h"
 #include "mud-telnet-charset.h"
@@ -339,7 +339,7 @@ mud_telnet_charset_send(MudTelnetCharset *self, gchar *encoding)
 {
     guchar byte;
     guint32 i;
-    GConn *conn;
+    MudConnection *conn;
 
     g_return_if_fail(MUD_IS_TELNET_CHARSET(self));
 
@@ -352,27 +352,26 @@ mud_telnet_charset_send(MudTelnetCharset *self, gchar *encoding)
 
     /* Writes IAC SB CHARSET ACCEPTED <charset> IAC SE to server */
     byte = (guchar)TEL_IAC;
-
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
     byte = (guchar)TEL_SB;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
     byte = (guchar)TELOPT_CHARSET;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
     byte = (guchar)TEL_CHARSET_ACCEPT;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
 
-    for (i = 0; i < strlen(encoding); ++i)
+    for(i = 0; i < strlen(encoding); ++i)
     {
-       byte = (guchar)encoding[i];
-       gnet_conn_write(conn, (gchar *)&byte, 1);
+        byte = (guchar)encoding[i];
+        mud_connection_send(conn, (gchar *)&byte, 1);
 
-       if (byte == (guchar)TEL_IAC)
-           gnet_conn_write(conn, (gchar *)&byte, 1);
+        if(byte == (guchar)TEL_IAC)
+            mud_connection_send(conn, (gchar *)&byte, 1);
     }
 
     byte = (guchar)TEL_IAC;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
     byte = (guchar)TEL_SE;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
 }
 
diff --git a/src/handlers/mud-telnet-msp.c b/src/handlers/mud-telnet-msp.c
index b418854..f02d52d 100644
--- a/src/handlers/mud-telnet-msp.c
+++ b/src/handlers/mud-telnet-msp.c
@@ -24,7 +24,6 @@
 #ifdef ENABLE_GST
 
 #include <glib.h>
-#include <gnet.h>
 #include <string.h>
 #include <gst/gst.h>
 #include <ctype.h>
diff --git a/src/handlers/mud-telnet-naws.c b/src/handlers/mud-telnet-naws.c
index 4b5ccf5..61cd0f7 100644
--- a/src/handlers/mud-telnet-naws.c
+++ b/src/handlers/mud-telnet-naws.c
@@ -25,7 +25,6 @@
 #include <glib-object.h>
 #include <glib/gi18n.h>
 #include <vte/vte.h>
-#include <gnet.h>
 #include <glib/gprintf.h>
 
 #include "gnome-mud.h"
@@ -348,9 +347,7 @@ mud_telnet_naws_resized_cb(MudWindow *window,
     if(!IS_MUD_CONNECTION_VIEW(view))
         return;
 
-    if(view->connection &&
-       gnet_conn_is_connected(view->connection) &&
-       self->priv->enabled)
+    if(self->priv->enabled && mud_connection_is_connected(view->conn))
         mud_telnet_naws_send(self,
                              view->terminal->column_count,
                              view->terminal->row_count);
@@ -388,18 +385,3 @@ mud_telnet_naws_delete_event_cb(GtkWidget *widget,
 
     return FALSE;
 }
-
-void
-mud_telnet_naws_disconnect_signals(MudTelnetNaws *self)
-{
-
-    if(self->priv->resized_signal != 0)
-        g_signal_handler_disconnect(self->priv->window, self->priv->resized_signal);
-
-    if(self->priv->delete_signal != 0)
-        g_signal_handler_disconnect(self->priv->main_window, self->priv->delete_signal);
-
-    self->priv->resized_signal = 0;
-    self->priv->delete_signal = 0;
-}
-
diff --git a/src/handlers/mud-telnet-naws.h b/src/handlers/mud-telnet-naws.h
index 1dc8426..75b401c 100644
--- a/src/handlers/mud-telnet-naws.h
+++ b/src/handlers/mud-telnet-naws.h
@@ -51,8 +51,6 @@ struct _MudTelnetNaws
 
 GType mud_telnet_naws_get_type (void);
 
-void mud_telnet_naws_disconnect_signals(MudTelnetNaws *self);
-
 G_END_DECLS
 
 #endif // MUD_TELNET_NAWS_H
diff --git a/src/handlers/mud-telnet-zmp.c b/src/handlers/mud-telnet-zmp.c
index 9e544f4..e5d8c93 100644
--- a/src/handlers/mud-telnet-zmp.c
+++ b/src/handlers/mud-telnet-zmp.c
@@ -22,7 +22,6 @@
 #endif
 
 #include <glib.h>
-#include <gnet.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -412,7 +411,7 @@ mud_zmp_send_command(MudTelnetZmp *self, guint32 count, ...)
     guchar null = '\0';
     va_list va;
     gchar *arg;
-    GConn *conn;
+    MudConnection *conn;
 
     g_return_if_fail(MUD_IS_TELNET_ZMP(self));
 
@@ -423,11 +422,11 @@ mud_zmp_send_command(MudTelnetZmp *self, guint32 count, ...)
     g_log("Telnet", G_LOG_LEVEL_DEBUG, "Sending ZMP Command:");
 
     byte = (guchar)TEL_IAC;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
     byte = (guchar)TEL_SB;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
     byte = (guchar)TELOPT_ZMP;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
 
     for (i = 0; i < count; ++i)
     {
@@ -438,22 +437,21 @@ mud_zmp_send_command(MudTelnetZmp *self, guint32 count, ...)
         for(j = 0; j < strlen(arg); ++j)
         {
             byte = (guchar)arg[j];
-
-            gnet_conn_write(conn, (gchar *)&byte, 1);
+            mud_connection_send(conn, (gchar *)&byte, 1);
 
             if (byte == (guchar)TEL_IAC)
-                gnet_conn_write(conn, (gchar *)&byte, 1);
+                mud_connection_send(conn, (gchar *)&byte, 1);
         }
 
-        gnet_conn_write(conn, (gchar *)&null, 1);
+        mud_connection_send(conn, (gchar *)&null, 1);
     }
 
     va_end(va);
 
     byte = (guchar)TEL_IAC;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
     byte = (guchar)TEL_SE;
-    gnet_conn_write(conn, (gchar *)&byte, 1);
+    mud_connection_send(conn, (gchar *)&byte, 1);
 }
 
 gboolean
diff --git a/src/mud-connection-view.c b/src/mud-connection-view.c
index 0293d9b..d3f3b16 100644
--- a/src/mud-connection-view.c
+++ b/src/mud-connection-view.c
@@ -26,8 +26,6 @@
 #include <gtk/gtk.h>
 #include <glib.h>
 #include <vte/vte.h>
-#define GNET_EXPERIMENTAL
-#include <gnet.h>
 #include <string.h>
 #include <glib/gprintf.h>
 
@@ -129,9 +127,6 @@ static void mud_connection_view_popup(MudConnectionView *view,
                                       GdkEventButton *event);
 
 static void popup_menu_detach(GtkWidget *widget, GtkMenu *menu);
-static void mud_connection_view_network_event_cb(GConn *conn, 
-                                                 GConnEvent *event,
-                                                 gpointer data);
 static void mud_connection_view_close_current_cb(GtkWidget *menu_item,
                                                  MudConnectionView *view);
 static void mud_connection_view_profile_changed_cb(MudProfile *profile,
@@ -373,12 +368,9 @@ mud_connection_view_init (MudConnectionView *self)
 
     self->priv->processed = NULL;
 
-    self->connection = NULL;
-
     self->local_echo = TRUE;
     self->remote_encode = FALSE;   
     self->connect_hook = FALSE;
-    self->connected = FALSE;;
 
     self->connect_string = NULL;
     self->remote_encoding = NULL;
@@ -404,6 +396,99 @@ mud_connection_view_init (MudConnectionView *self)
                                            NULL);
 }
 
+static void
+mud_connection_connected_cb(MudConnection *conn, MudConnectionView *self)
+{
+    self->telnet = g_object_new(MUD_TYPE_TELNET,
+                                "parent-view", self,
+                                "connection", conn,
+                                NULL);
+
+    mud_tray_update_icon(self->tray, online);
+    mud_connection_view_add_text(self, _("*** Connected.\n"), System);
+}
+
+static void
+mud_connection_disconnected_cb(MudConnection *conn, MudConnectionView *self)
+{
+    g_clear_object(&self->telnet);
+
+    /* We may have been disconnected with local echo disabled, it must be
+     * enabled to display the connection closed message.
+     */
+    self->local_echo = TRUE;
+
+    mud_window_disconnected(self->window);
+    mud_connection_view_add_text(self, _("\n*** Connection closed.\n"), Error);
+}
+
+static void
+mud_connection_data_ready_cb(MudConnection *conn, MudConnectionView *self)
+{
+    const GByteArray *input;
+    gint tlen;
+
+    input = mud_connection_get_input(conn);
+
+    self->priv->processed = mud_telnet_process(self->telnet,
+                                               input->data,
+                                               input->len,
+                                               &tlen);
+
+    if(self->priv->processed)
+    {
+        mud_line_buffer_add_data(self->priv->line_buffer,
+                                 self->priv->processed->str,
+                                 self->priv->processed->len);
+        g_string_free(self->priv->processed, TRUE);
+        self->priv->processed = NULL;
+    }
+}
+
+/* TODO: Support loading the system-wide proxy. */
+static gchar *
+mud_connection_view_create_proxy_uri(const MudConnectionView *self)
+{
+    GConfClient *client;
+    gchar *uri = NULL;
+    gchar *host, *str_version;
+    guint version;
+    gchar key[2048];
+    gchar extra_path[512] = "";
+
+    if (strcmp(self->profile_name, "Default") != 0)
+    {
+        g_snprintf(extra_path, sizeof(extra_path), "profiles/%s/", self->profile_name);
+    }
+
+    client = gconf_client_get_default();
+
+    g_snprintf(key, sizeof(key), "/apps/gnome-mud/%s%s", extra_path, "functionality/use_proxy");
+    if(!gconf_client_get_bool(client, key, NULL))
+    {
+        g_object_unref(client);
+        return NULL;
+    }
+
+    g_snprintf(key, sizeof(key), "/apps/gnome-mud/%s%s", extra_path, "functionality/proxy_hostname");
+    host = gconf_client_get_string(client, key, NULL);
+
+    g_snprintf(key, sizeof(key), "/apps/gnome-mud/%s%s", extra_path, "functionality/proxy_version");
+    str_version = gconf_client_get_string(client, key, NULL);
+    if(strcmp(str_version, "4") == 0)
+        version = 4;
+    else
+        version = 5;
+
+    uri = g_strdup_printf("socks%d://%s", version, host);
+
+    g_object_unref(client);
+    g_free(host);
+    g_free(str_version);
+
+    return uri;
+}
+
 static GObject *
 mud_connection_view_constructor (GType gtype,
                                  guint n_properties,
@@ -417,16 +502,9 @@ mud_connection_view_constructor (GType gtype,
     GtkWidget *term_box;
     GtkWidget *main_window;
     MudTray *tray;
-    GConfClient *client;
-
-    gchar key[2048];
-    gchar extra_path[512] = "";
     gchar *buf;
-    gchar *proxy_host;
-    gchar *version;
-    gboolean use_proxy;
+    gchar *proxy_uri;
     MudProfile *profile;
-    
     MudConnectionView *self;
     GObject *obj;
 
@@ -546,15 +624,6 @@ mud_connection_view_constructor (GType gtype,
                  "tray", &tray,
                  NULL);
 
-    self->connection = gnet_conn_new(self->hostname, self->port,
-            mud_connection_view_network_event_cb, self);
-    gnet_conn_ref(self->connection);
-    gnet_conn_set_watch_error(self->connection, TRUE);
-
-    self->telnet = g_object_new(MUD_TYPE_TELNET,
-                                "parent-view", self,
-                                NULL);
-
     profile =
         mud_profile_manager_get_profile_by_name(self->window->profile_manager,
                                                 self->profile_name);
@@ -578,40 +647,20 @@ mud_connection_view_constructor (GType gtype,
     g_free(buf);
     buf = NULL;
 
-    if (strcmp(self->profile_name, "Default") != 0)
-    {
-        g_snprintf(extra_path, 512, "profiles/%s/", self->profile_name);
-    }
+    self->conn = g_object_new(MUD_TYPE_CONNECTION, NULL);
 
-    g_snprintf(key, 2048, "/apps/gnome-mud/%s%s", extra_path, "functionality/use_proxy");
-    client = gconf_client_get_default();
-    use_proxy = gconf_client_get_bool(client, key, NULL);
+    g_signal_connect(self->conn, "connected",
+                     G_CALLBACK(mud_connection_connected_cb), self);
 
-    g_snprintf(key, 2048, "/apps/gnome-mud/%s%s", extra_path, "functionality/proxy_hostname");
-    proxy_host = gconf_client_get_string(client, key, NULL);
+    g_signal_connect(self->conn, "disconnected",
+                     G_CALLBACK(mud_connection_disconnected_cb), self);
 
-    g_snprintf(key, 2048, "/apps/gnome-mud/%s%s", extra_path, "functionality/proxy_version");
-    version = gconf_client_get_string(client, key, NULL);
+    g_signal_connect(self->conn, "data-ready",
+                     G_CALLBACK(mud_connection_data_ready_cb), self);
 
-    if(use_proxy)
-    {
-        if(proxy_host && version)
-        {
-            gnet_socks_set_enabled(TRUE);
-            gnet_socks_set_server(gnet_inetaddr_new(proxy_host,GNET_SOCKS_PORT));
-            gnet_socks_set_version((strcmp(version, "4") == 0) ? 4 : 5);
-        }
-    }
-    else
-        gnet_socks_set_enabled(FALSE);
-
-    if(proxy_host)
-        g_free(proxy_host);
-
-    if(version)
-        g_free(version);
-
-    g_object_unref(client);
+    proxy_uri = mud_connection_view_create_proxy_uri(self);
+    mud_connection_connect(self->conn, self->hostname, self->port, proxy_uri);
+    g_free(proxy_uri);
 
     /* Show everything */
     gtk_widget_show_all(box);
@@ -635,8 +684,6 @@ mud_connection_view_constructor (GType gtype,
                      G_CALLBACK(mud_connection_view_partial_line_cb),
                      self);
 
-    gnet_conn_connect(self->connection);
-
     return obj;
 }
 
@@ -672,12 +719,8 @@ mud_connection_view_finalize (GObject *object)
         g_queue_free(connection_view->priv->download_queue);
 #endif
 
-    if(connection_view->connection && 
-            gnet_conn_is_connected(connection_view->connection))
-        gnet_conn_disconnect(connection_view->connection);
-
-    if(connection_view->connection)
-        gnet_conn_unref(connection_view->connection);
+    if(connection_view->conn)
+        g_object_unref(connection_view->conn);
 
     if(connection_view->hostname)
         g_free(connection_view->hostname);
@@ -687,13 +730,10 @@ mud_connection_view_finalize (GObject *object)
     
     if(connection_view->mud_name)
         g_free(connection_view->mud_name);
-    
+
     if(connection_view->priv->processed)
         g_string_free(connection_view->priv->processed, TRUE);
     
-    if(connection_view->telnet)
-        g_object_unref(connection_view->telnet);
-  
     g_object_unref(connection_view->log);
 
     g_object_unref(connection_view->parse);
@@ -882,7 +922,7 @@ mud_connection_view_get_property(GObject *object,
     switch(prop_id)
     {
         case PROP_CONNECTION:
-            g_value_set_pointer(value, self->connection);
+            g_value_set_pointer(value, self->conn);
             break;
 
         case PROP_LOCAL_ECHO:
@@ -898,7 +938,7 @@ mud_connection_view_get_property(GObject *object,
             break;
 
         case PROP_CONNECTED:
-            g_value_set_boolean(value, self->connected);
+            g_value_set_boolean(value, mud_connection_is_connected(self->conn));
             break;
 
         case PROP_CONNECT_STRING:
@@ -1125,101 +1165,6 @@ mud_connection_view_popup(MudConnectionView *view, GdkEventButton *event)
 }
 
 static void
-mud_connection_view_network_event_cb(GConn *conn, GConnEvent *event, gpointer pview)
-{
-    gint length;
-    MudConnectionView *view = MUD_CONNECTION_VIEW(pview);
-
-#ifdef ENABLE_GST
-    MudMSPDownloadItem *item;
-#endif
-
-    g_assert(view != NULL);
-
-    switch(event->type)
-    {
-        case GNET_CONN_ERROR:
-            mud_connection_view_add_text(view, _("*** Could not connect.\n"), Error);
-            mud_window_disconnected(view->window);
-            break;
-
-        case GNET_CONN_CONNECT:
-            mud_connection_view_add_text(view, _("*** Connected.\n"), System);
-            gnet_conn_read(view->connection);
-            break;
-
-        case GNET_CONN_CLOSE:
-#ifdef ENABLE_GST
-            if(view->priv->download_queue)
-                while((item = (MudMSPDownloadItem *)g_queue_pop_head(view->priv->download_queue)) != NULL)
-                    mud_telnet_msp_download_item_free(item);
-
-            if(view->priv->download_queue)
-                g_queue_free(view->priv->download_queue);
-
-            view->priv->download_queue = NULL;
-#endif
-
-            view->priv->processed = NULL;
-
-            gnet_conn_disconnect(view->connection);
-            gnet_conn_unref(view->connection);
-            view->connection = NULL;
-
-            if(view->telnet)
-            {
-                g_object_unref(view->telnet);
-                view->telnet = NULL;
-            }
-
-            mud_connection_view_add_text(view, _("*** Connection closed.\n"), Error);
-
-            mud_window_disconnected(view->window);
-            break;
-
-        case GNET_CONN_TIMEOUT:
-            break;
-
-        case GNET_CONN_READ:
-            if(!view->connected)
-            {
-                view->connected = TRUE;
-                mud_tray_update_icon(view->tray, online);
-            }
-
-            view->priv->processed =
-                mud_telnet_process(view->telnet, 
-                                   (guchar *)event->buffer,
-                                   event->length,
-                                   &length);
-
-            if(view->priv->processed)
-            {
-                mud_line_buffer_add_data(view->priv->line_buffer,
-                                         view->priv->processed->str,
-                                         view->priv->processed->len);
-
-                g_string_free(view->priv->processed, TRUE);
-                view->priv->processed = NULL;
-
-                mud_line_buffer_flush(view->priv->line_buffer);
-            }
-
-            gnet_conn_read(view->connection);
-            break;
-
-        case GNET_CONN_WRITE:
-            break;
-
-        case GNET_CONN_READABLE:
-            break;
-
-        case GNET_CONN_WRITABLE:
-            break;
-    }
-}
-
-static void
 mud_connection_view_line_added_cb(MudLineBuffer *buffer,
                                   MudLineBufferLine *line,
                                   guint length,
@@ -1348,6 +1293,7 @@ popup_menu_detach(GtkWidget *widget, GtkMenu *menu)
 static void
 mud_connection_view_update_geometry (MudConnectionView *window)
 {
+    /* TODO: switch to vte_terminal_set_geometry_hints_for_window */
     GtkWidget *widget = GTK_WIDGET(window->terminal);
     GtkWidget *mainwindow;
     GdkGeometry hints;
@@ -1848,138 +1794,45 @@ mud_connection_view_disconnect(MudConnectionView *view)
 
     g_return_if_fail(IS_MUD_CONNECTION_VIEW(view));
 
-    if(view->connection && gnet_conn_is_connected(view->connection))
-    {
 #ifdef ENABLE_GST
-        if(view->priv->download_queue)
-            while((item = (MudMSPDownloadItem *)g_queue_pop_head(view->priv->download_queue)) != NULL)
-                mud_telnet_msp_download_item_free(item);
+    if(view->priv->download_queue)
+        while((item = (MudMSPDownloadItem *)g_queue_pop_head(view->priv->download_queue)) != NULL)
+            mud_telnet_msp_download_item_free(item);
 
-        if(view->priv->download_queue)
-            g_queue_free(view->priv->download_queue);
+    if(view->priv->download_queue)
+        g_queue_free(view->priv->download_queue);
 
-        view->priv->download_queue = NULL;
+    view->priv->download_queue = NULL;
 #endif
 
-        mud_connection_view_stop_logging(view);
+    mud_connection_view_stop_logging(view);
 
-        view->priv->processed = NULL;
+    view->priv->processed = NULL;
 
-        gnet_conn_disconnect(view->connection);
-        gnet_conn_unref(view->connection);
-        view->connection = NULL;
-
-        if(view->telnet)
-        {
-            g_object_unref(view->telnet);
-            view->telnet = NULL;
-        }
-
-        mud_connection_view_add_text(view, _("\n*** Connection closed.\n"), System);
-    }
+    mud_connection_disconnect(view->conn);
 }
 
 void
 mud_connection_view_reconnect(MudConnectionView *view)
 {
-    gchar *buf, *profile_name, *proxy_host, *version;
-    gchar key[2048];
-    gchar extra_path[512] = "";
-    gboolean use_proxy;
-    GConfClient *client;
+    gchar *buf, *proxy_uri;
 
-#ifdef ENABLE_GST
-    MudMSPDownloadItem *item;
-#endif
     g_return_if_fail(IS_MUD_CONNECTION_VIEW(view));
 
-    if(view->connection && gnet_conn_is_connected(view->connection))
-    {
-
-#ifdef ENABLE_GST
-        while((item = (MudMSPDownloadItem *)
-                    g_queue_pop_head(view->priv->download_queue)) != NULL)
-            mud_telnet_msp_download_item_free(item);
-
-        if(view->priv->download_queue)
-            g_queue_free(view->priv->download_queue);
-
-        view->priv->download_queue = NULL;
-#endif
-
-        mud_connection_view_stop_logging(view);
-
-        view->priv->processed = NULL;
-
-        gnet_conn_disconnect(view->connection);
-        gnet_conn_unref(view->connection);
-        view->connection = NULL;
-
-        g_object_unref(view->telnet);
-        view->telnet = NULL;
-
-        mud_connection_view_add_text(view,
-                _("\n*** Connection closed.\n"), System);
-    }
-
-    view->connection = gnet_conn_new(view->hostname, view->port,
-            mud_connection_view_network_event_cb, view);
-    gnet_conn_ref(view->connection);
-    gnet_conn_set_watch_error(view->connection, TRUE);
-
-    g_object_get(view->profile, "name", &profile_name, NULL);
-
-    if (!g_str_equal(profile_name, "Default"))
-        g_snprintf(extra_path, 512, "profiles/%s/", profile_name);
-    
-    g_free(profile_name);
-
-    g_snprintf(key, 2048, "/apps/gnome-mud/%s%s", extra_path, "functionality/use_proxy");
-    client = gconf_client_get_default();
-    use_proxy = gconf_client_get_bool(client, key, NULL);
-
-    g_snprintf(key, 2048, "/apps/gnome-mud/%s%s", extra_path, "functionality/proxy_hostname");
-    proxy_host = gconf_client_get_string(client, key, NULL);
-
-    g_snprintf(key, 2048, "/apps/gnome-mud/%s%s", extra_path, "functionality/proxy_version");
-    version = gconf_client_get_string(client, key, NULL);
-
-    if(use_proxy)
-    {
-        if(proxy_host && version)
-        {
-            gnet_socks_set_enabled(TRUE);
-            gnet_socks_set_server(gnet_inetaddr_new(proxy_host,GNET_SOCKS_PORT));
-            gnet_socks_set_version((strcmp(version, "4") == 0) ? 4 : 5);
-        }
-    }
-    else
-        gnet_socks_set_enabled(FALSE);
-
-    if(proxy_host)
-        g_free(proxy_host);
-
-    if(version)
-        g_free(version);
-
 #ifdef ENABLE_GST
     view->priv->download_queue = g_queue_new();
 #endif
 
     view->local_echo = TRUE;
 
-    view->telnet = g_object_new(MUD_TYPE_TELNET,
-                                "parent-view", view,
-                                NULL);
-
     buf = g_strdup_printf(_("*** Making connection to %s, port %d.\n"),
             view->hostname, view->port);
     mud_connection_view_add_text(view, buf, System);
     g_free(buf);
 
-    g_object_unref(client);
-
-    gnet_conn_connect(view->connection);
+    proxy_uri = mud_connection_view_create_proxy_uri(view);
+    mud_connection_connect(view->conn, view->hostname, view->port, proxy_uri);
+    g_free(proxy_uri);
 }
 
 void
@@ -2000,7 +1853,7 @@ mud_connection_view_send(MudConnectionView *view, const gchar *data)
     
     g_return_if_fail(IS_MUD_CONNECTION_VIEW(view));
 
-    if(view->connection && gnet_conn_is_connected(view->connection))
+    if(mud_connection_is_connected(view->conn))
     {
         if(view->local_echo) // Prevent password from being cached.
         {
@@ -2092,10 +1945,9 @@ mud_connection_view_send(MudConnectionView *view, const gchar *data)
 
             if(!zmp_enabled)
             {
-                gchar *line = (conv_text == NULL) ? text : conv_text;
-
-                gnet_conn_write(view->connection, line, strlen(line));
-                gnet_conn_write(view->connection, "\r\n", 2);
+                const gchar *line = (conv_text == NULL) ? text : conv_text;
+                mud_connection_send(view->conn, line, -1);
+                mud_connection_send(view->conn, "\r\n", 2);
             }
             else // ZMP is enabled, use zmp.input.
             {
diff --git a/src/mud-connection-view.h b/src/mud-connection-view.h
index 2ccb733..49457aa 100644
--- a/src/mud-connection-view.h
+++ b/src/mud-connection-view.h
@@ -8,7 +8,6 @@ G_BEGIN_DECLS
 #endif
 
 #include <gtk/gtk.h>
-#include <gnet.h>
 #include <vte/vte.h>
 
 #define MUD_TYPE_CONNECTION_VIEW               (mud_connection_view_get_type ())
@@ -23,6 +22,7 @@ typedef struct _MudConnectionView           MudConnectionView;
 typedef struct _MudConnectionViewClass      MudConnectionViewClass;
 typedef struct _MudConnectionViewPrivate    MudConnectionViewPrivate;
 
+#include "mud-connection.h"
 #include "mud-telnet.h"
 #include "mud-parse-base.h"
 #include "mud-profile.h"
@@ -44,7 +44,7 @@ struct _MudConnectionView
     MudConnectionViewPrivate *priv;
 
     /*< Public >*/
-    GConn *connection;
+    MudConnection *conn;
 
     // Flags
     gboolean local_echo;
diff --git a/src/mud-connection.c b/src/mud-connection.c
new file mode 100644
index 0000000..d883130
--- /dev/null
+++ b/src/mud-connection.c
@@ -0,0 +1,384 @@
+/* Copyright (C) 2017 Steven Jackson <sj oscode net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "mud-connection.h"
+
+/* This is the initial size of the output buffer, which grows dynamically,
+ * and the total size of the input buffer, which does not.
+ */
+#define BUFFER_RESERVE 32768
+
+struct _MudConnection
+{
+    GObject parent_instance;
+
+    GCancellable *connect_cancel;
+    GSocketClient *client;
+    GByteArray *inbuf;
+    GByteArray *outbuf;
+    GSocketConnection *scon;
+    GSocket *socket;
+    GSource *write_source;
+};
+
+G_DEFINE_TYPE(MudConnection, mud_connection, G_TYPE_OBJECT)
+
+enum
+{
+    SIGNAL_CONNECTED,
+    SIGNAL_DISCONNECTED,
+    SIGNAL_DATA_READY,
+
+    /* Must be last. */
+    SIGNAL_COUNT
+};
+
+static guint mud_connection_signal[SIGNAL_COUNT];
+
+static void
+mud_connection_finalize(GObject *object)
+{
+    MudConnection *self = MUD_CONNECTION(object);
+
+    if(self->connect_cancel)
+        g_object_unref(self->connect_cancel);
+
+    if(self->client)
+        g_object_unref(self->client);
+
+    if(self->inbuf)
+        g_byte_array_free(self->inbuf, TRUE);
+
+    if(self->outbuf)
+        g_byte_array_free(self->outbuf, TRUE);
+
+    if(self->scon)
+        g_io_stream_close(G_IO_STREAM(self->scon), NULL, NULL);
+
+    G_OBJECT_CLASS(mud_connection_parent_class)->finalize(object);
+}
+
+static void
+mud_connection_class_init(MudConnectionClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+    mud_connection_signal[SIGNAL_CONNECTED] =
+        g_signal_new("connected",
+                     MUD_TYPE_CONNECTION,
+                     G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+                     0,
+                     NULL,
+                     NULL,
+                     g_cclosure_marshal_VOID__VOID,
+                     G_TYPE_NONE, 0);
+
+    mud_connection_signal[SIGNAL_DISCONNECTED] =
+        g_signal_new("disconnected",
+                     MUD_TYPE_CONNECTION,
+                     G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+                     0,
+                     NULL,
+                     NULL,
+                     g_cclosure_marshal_VOID__VOID,
+                     G_TYPE_NONE, 0);
+
+    mud_connection_signal[SIGNAL_DATA_READY] =
+        g_signal_new("data-ready",
+                     MUD_TYPE_CONNECTION,
+                     G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+                     0,
+                     NULL,
+                     NULL,
+                     g_cclosure_marshal_VOID__VOID,
+                     G_TYPE_NONE, 0);
+
+    object_class->finalize = mud_connection_finalize;
+}
+
+static void
+mud_connection_init(MudConnection *self)
+{
+    self->connect_cancel = NULL;
+    self->client = g_socket_client_new();
+    self->inbuf = g_byte_array_sized_new(BUFFER_RESERVE);
+    self->outbuf = g_byte_array_sized_new(BUFFER_RESERVE);
+    self->scon = NULL;
+    self->socket = NULL;
+    self->write_source = NULL;
+}
+
+void
+mud_connection_disconnect(MudConnection *self)
+{
+    gboolean was_connected;
+
+    g_assert(MUD_IS_CONNECTION(self));
+
+    was_connected = mud_connection_is_connected(self);
+
+    g_cancellable_cancel(self->connect_cancel);
+    self->connect_cancel = NULL;
+
+    self->socket = NULL;
+
+    if(self->scon)
+    {
+        g_io_stream_close(G_IO_STREAM(self->scon), NULL, NULL);
+        self->scon = NULL;
+    }
+
+    if(was_connected)
+        g_signal_emit_by_name(self, "disconnected");
+
+    if(self->outbuf)
+        g_byte_array_set_size(self->outbuf, 0);
+}
+
+static gboolean
+mud_connection_flush(MudConnection *self)
+{
+    GError *error = NULL;
+
+    g_assert(MUD_IS_CONNECTION(self));
+    g_assert(mud_connection_is_connected(self));
+
+    if(self->outbuf->len == 0)
+        return TRUE;
+
+    gssize ret = g_socket_send(self->socket, (const gchar *)self->outbuf->data,
+                               self->outbuf->len, NULL, &error);
+
+    if(error)
+    {
+        if(!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
+        {
+            g_warning("%s: g_socket_send failed: %s",
+                      __FUNCTION__, error->message);
+        }
+
+        g_clear_error(&error);
+    }
+
+    if(ret == 0)
+    {
+        g_debug("Disconnecting because the connection was lost during a flush");
+        mud_connection_disconnect(self);
+        return FALSE;
+    }
+
+    if(ret > 0)
+        g_byte_array_remove_range(self->outbuf, 0, ret);
+
+    return TRUE;
+}
+
+static gboolean
+socket_read_ready_cb(GSocket *socket, GIOCondition condition, gpointer user_data)
+{
+    MudConnection *self = MUD_CONNECTION(user_data);
+    gssize bytes_read;
+    GError *error = NULL;
+
+    /* We only get this condition from a connection cancellation via
+     * mud_connection_disconnect().
+     */
+    if(self->scon == NULL)
+    {
+        g_clear_object(&self->connect_cancel);
+        return FALSE;
+    }
+
+    g_byte_array_set_size(self->inbuf, BUFFER_RESERVE);
+
+    do
+    {
+        bytes_read = g_socket_receive(socket, (gchar *)self->inbuf->data,
+                                      BUFFER_RESERVE, NULL, &error);
+
+        if(error)
+        {
+            if(!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
+            {
+                g_warning("%s: g_socket_receive failed: %s",
+                          __FUNCTION__, error->message);
+            }
+
+            g_clear_error(&error);
+        }
+
+        if(bytes_read == 0)
+        {
+            g_debug("Disconnecting because the connection was lost during a read");
+            mud_connection_disconnect(self);
+            return FALSE;
+        }
+
+        if(bytes_read > 0)
+        {
+            g_byte_array_set_size(self->inbuf, bytes_read);
+            g_signal_emit_by_name(self, "data-ready");
+        }
+    }
+    while(bytes_read > 0);
+
+    return TRUE;
+}
+
+static gboolean
+socket_write_ready_cb(GSocket *socket, GIOCondition condition, gpointer user_data)
+{
+    MudConnection *self = MUD_CONNECTION(user_data);
+
+    if(!mud_connection_flush(self) || self->outbuf->len == 0)
+    {
+        self->write_source = NULL;
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+socket_client_connect_cb(GObject *source_object, GAsyncResult *res,
+                         gpointer user_data)
+{
+    MudConnection *self = MUD_CONNECTION(user_data);
+    GSource *source;
+
+    self->scon = g_socket_client_connect_to_host_finish(self->client, res, NULL);
+
+    if(self->connect_cancel == NULL)
+    {
+        /* The only way we can get here is if mud_connection_disconnect() was
+         * called on an incomplete connection, so don't emit
+         * #MudConnection::disconnected as it's already done.
+         */
+        g_debug("The connection attempt was cancelled");
+        return;
+    }
+
+    g_clear_object(&self->connect_cancel);
+
+    if(self->scon == NULL)
+    {
+        g_debug("The connection attempt failed");
+        g_signal_emit_by_name(self, "disconnected");
+        return;
+    }
+
+    self->socket = g_socket_connection_get_socket(self->scon);
+    g_socket_set_blocking(self->socket, FALSE);
+    g_socket_set_keepalive(self->socket, TRUE);
+
+    g_signal_emit_by_name(self, "connected");
+
+    source = g_socket_create_source(self->socket, G_IO_IN, NULL);
+    g_source_set_callback(source, (GSourceFunc)socket_read_ready_cb, self, NULL);
+    g_source_set_can_recurse(source, FALSE);
+    g_source_attach(source, NULL);
+    g_source_unref(source);
+}
+
+gboolean
+mud_connection_connect(MudConnection *self, const gchar *hostname, guint port,
+                       const gchar *proxy_uri)
+{
+    g_assert(MUD_IS_CONNECTION(self));
+    g_assert(!self->scon);
+    g_assert(hostname);
+    g_assert(port <= 65535);
+
+    if(mud_connection_is_connected(self))
+    {
+        g_warning("Attempting to reconnect when not disconnected");
+        return FALSE;
+    }
+
+    g_debug("Connecting to %s:%d via %s", hostname, port, proxy_uri);
+
+    if(proxy_uri)
+    {
+        /* TODO: Consider using ignore_hosts for 127.0.0.1/8 and localhost. */
+        GProxyResolver *proxy_resolver;
+
+        proxy_resolver = g_simple_proxy_resolver_new(proxy_uri, NULL);
+        g_socket_client_set_proxy_resolver(self->client, proxy_resolver);
+        g_object_unref(proxy_resolver);
+
+        g_socket_client_set_enable_proxy(self->client, TRUE);
+    }
+    else
+        g_socket_client_set_enable_proxy(self->client, FALSE);
+
+    self->connect_cancel = g_cancellable_new();
+    g_socket_client_connect_to_host_async(self->client,
+                                          hostname,
+                                          port,
+                                          self->connect_cancel,
+                                          socket_client_connect_cb,
+                                          self);
+
+    return TRUE;
+}
+
+gboolean
+mud_connection_is_connected(MudConnection *self)
+{
+    g_assert(MUD_IS_CONNECTION(self));
+
+    /* It's possible for the underlying socket to be disconnected, but
+     * until disconnect has been called, resources aren't cleaned up and should
+     * be considered connected.
+     */
+    return self->scon != NULL || self->connect_cancel != NULL;
+}
+
+void
+mud_connection_send(MudConnection *self, const gchar *buf, gssize len)
+{
+    g_assert(MUD_IS_CONNECTION(self));
+    g_assert(buf);
+
+    if(len == 0)
+        return;
+
+    if(len < 0)
+        len = strlen(buf);
+
+    g_byte_array_append(self->outbuf, (const guint8 *)buf, len);
+
+    if(!self->write_source)
+    {
+        self->write_source = g_socket_create_source(self->socket, G_IO_OUT, NULL);
+        g_source_set_callback(self->write_source, (GSourceFunc)socket_write_ready_cb, self, NULL);
+        g_source_set_can_recurse(self->write_source, FALSE);
+        g_source_attach(self->write_source, NULL);
+        g_source_unref(self->write_source);
+    }
+}
+
+const GByteArray *
+mud_connection_get_input(MudConnection *self)
+{
+    g_assert(MUD_IS_CONNECTION(self));
+    return self->inbuf;
+}
diff --git a/src/mud-connection.h b/src/mud-connection.h
new file mode 100644
index 0000000..519654d
--- /dev/null
+++ b/src/mud-connection.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2017 Steven Jackson <sj oscode net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef MUD_CONNECTION_H
+#define MUD_CONNECTION_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MUD_TYPE_CONNECTION     mud_connection_get_type()
+
+G_DECLARE_FINAL_TYPE(MudConnection, mud_connection, MUD, CONNECTION, GObject)
+
+/* mud_connection_connect:
+ * @self: a #MudConnection.
+ * @hostname: a hostname in a format understood by
+ *   g_socket_client_connect_to_host_async().
+ * @port: a port in the range of 0-65535.
+ * @proxy_uri: (nullable): a proxy URI in a format understood by
+ *   g_simple_proxy_resolver_new().
+ *
+ * Don't call this when a connection is active or a reconnect attempt is in
+ * progress, i.e. when mud_connection_is_connected() returns %TRUE.
+ *
+ * The #MudConnection::connected or #MudConnection::disconnected signal is
+ * emitted when the result of the connection is known.
+ *
+ * Returns: @TRUE when a connection attempt has begun.
+ */
+gboolean mud_connection_connect(MudConnection *self, const gchar *hostname,
+                                guint port, const gchar *proxy_uri);
+
+/* mud_connection_is_connected:
+ * @self: a #MudConnection.
+ *
+ * If self is @NULL or disconected it returns early.
+ */
+void mud_connection_disconnect(MudConnection *self);
+
+/* mud_connection_is_connected:
+ * @self: (nullable): a #MudConnection.
+ *
+ * Returns: @TRUE is the connection is connected.
+ */
+gboolean mud_connection_is_connected(MudConnection *self);
+
+/* mud_connection_get_input:
+ * @self: a #MudConnection.
+ * @buf: the data to send.
+ * @len: the length of @buf, or -1 to calculate its @NULL-terminated length.
+ *
+ * The data might not be sent immediately, it's written when the operation
+ * would not block.
+ */
+void mud_connection_send(MudConnection *self, const gchar *buf, gssize len);
+
+/* mud_connection_get_input:
+ * @self: a #MudConnection.
+ *
+ * See #MudConnection::data-ready.
+ *
+ * Returns: a #GByteArray or @NULL.
+ */
+const GByteArray *mud_connection_get_input(MudConnection *self);
+
+G_END_DECLS
+
+#endif /* MUD_CONNECTION_H */
diff --git a/src/mud-telnet.c b/src/mud-telnet.c
index 7110097..38211f8 100644
--- a/src/mud-telnet.c
+++ b/src/mud-telnet.c
@@ -25,7 +25,6 @@
 #endif
 
 #include <glib.h>
-#include <gnet.h>
 #include <stdarg.h>
 #include <string.h> // memset
 #include <glib/gprintf.h>
@@ -38,7 +37,8 @@
 
 struct _MudTelnetPrivate
 {
-    GConn *conn;
+    MudConnection *conn;
+
     gchar *mud_name;
 
     enum TelnetState tel_state;
@@ -177,7 +177,7 @@ mud_telnet_class_init (MudTelnetClass *klass)
             g_param_spec_pointer("connection",
                 "Connection",
                 "The Connection Object to the MUD",
-                G_PARAM_READABLE));
+                G_PARAM_READWRITE));
 }
 
 static void
@@ -192,6 +192,7 @@ mud_telnet_init (MudTelnet *telnet)
     telnet->ga_received = FALSE;
     telnet->eor_received = FALSE;
 
+    telnet->priv->conn = NULL;
     telnet->priv->pos = 0;
     telnet->priv->buffer = NULL;
     telnet->priv->subreq_pos = 0;
@@ -231,11 +232,6 @@ mud_telnet_constructor (GType gtype,
 
     mud_telnet_register_handlers(self);
 
-    g_object_get(self->parent_view,
-                 "connection", &self->priv->conn,
-                 "mud-name", &self->priv->mud_name,
-                 NULL);
-
     return obj;
 }
 
@@ -287,6 +283,10 @@ mud_telnet_set_property(GObject *object,
             self->eor_received = g_value_get_boolean(value);
             break;
 
+        case PROP_CONNECTION:
+            self->priv->conn = g_value_get_pointer(value);
+            break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
             break;
@@ -682,25 +682,25 @@ mud_telnet_send_sub_req(MudTelnet *telnet, guint32 count, ...)
     
     byte = (guchar)TEL_IAC;
 
-    gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+    mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
     byte = (guchar)TEL_SB;
-    gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+    mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
 
     for (i = 0; i < count; ++i)
     {
        byte = (guchar)va_arg(va, gint);
-       gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+       mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
 
        if (byte == (guchar)TEL_IAC)
-           gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+           mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
     }
 
     va_end(va);
 
     byte = (guchar)TEL_IAC;
-    gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+    mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
     byte = (guchar)TEL_SE;
-    gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+    mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
 }
 
 void
@@ -717,10 +717,10 @@ mud_telnet_send_raw(MudTelnet *telnet, guint32 count, ...)
     for (i = 0; i < count; ++i)
     {
        byte = (guchar)va_arg(va, gint);
-       gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+       mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
 
        if (byte == (guchar)TEL_IAC)
-           gnet_conn_write(telnet->priv->conn, (gchar *)&byte, 1);
+           mud_connection_send(telnet->priv->conn, (gchar *)&byte, 1);
     }
 
     va_end(va);
@@ -898,7 +898,7 @@ mud_telnet_send_iac(MudTelnet *telnet, guchar ch1, guchar ch2)
     buf[1] = ch1;
     buf[2] = ch2;
 
-    gnet_conn_write(telnet->priv->conn, (gchar *)buf, 3);
+    mud_connection_send(telnet->priv->conn, (gchar *)buf, 3);
 }
 
 static void
diff --git a/src/mud-telnet.h b/src/mud-telnet.h
index 1911026..84e7946 100644
--- a/src/mud-telnet.h
+++ b/src/mud-telnet.h
@@ -137,7 +137,6 @@ typedef struct _MudTelnet            MudTelnet;
 typedef struct _MudTelnetClass       MudTelnetClass;
 typedef struct _MudTelnetPrivate     MudTelnetPrivate;
 
-#include <gnet.h>
 #include "mud-connection-view.h"
 #include "handlers/mud-telnet-handlers.h"
 
diff --git a/src/mud-window.c b/src/mud-window.c
index b6c5d45..49b1ddc 100644
--- a/src/mud-window.c
+++ b/src/mud-window.c
@@ -517,28 +517,7 @@ mud_window_get_property(GObject *object,
 static int
 mud_window_close(GtkWidget *widget, MudWindow *self)
 {
-    GSList *entry = self->priv->mud_views_list;
-
-    while(entry != NULL)
-    {
-        MudTelnetNaws *naws;
-        gboolean enabled;
-        MudConnectionView *view =
-            MUD_CONNECTION_VIEW(entry->data);
-
-        naws = MUD_TELNET_NAWS(mud_telnet_get_handler(view->telnet,
-                    TELOPT_NAWS));
-
-        g_object_get(naws, "enabled", &enabled, NULL);
-
-        if(enabled)
-            mud_telnet_naws_disconnect_signals(naws);
-
-        entry = g_slist_next(entry);
-    }
-
     g_object_unref(self);
-
     return TRUE;
 }
 
@@ -575,7 +554,9 @@ mud_window_reconnect_cb(GtkWidget *widget, MudWindow *self)
     if (self->priv->current_view != NULL)
     {
         gtk_widget_set_sensitive(self->priv->startlog, TRUE);
+        gtk_widget_set_sensitive(self->priv->menu_reconnect, FALSE);
         gtk_widget_set_sensitive(self->priv->menu_disconnect, TRUE);
+        gtk_widget_set_sensitive(self->priv->toolbar_reconnect, FALSE);
         gtk_widget_set_sensitive(self->priv->toolbar_disconnect, TRUE);
         mud_connection_view_reconnect(self->priv->current_view);
     }
@@ -1336,10 +1317,10 @@ mud_window_add_connection_view(MudWindow *self, GObject *cview, gchar *tabLbl)
     gtk_widget_set_sensitive(self->priv->startlog, TRUE);
     gtk_widget_set_sensitive(self->priv->bufferdump, TRUE);
     gtk_widget_set_sensitive(self->priv->menu_close, TRUE);
-    gtk_widget_set_sensitive(self->priv->menu_reconnect, TRUE);
+    gtk_widget_set_sensitive(self->priv->menu_reconnect, FALSE);
     gtk_widget_set_sensitive(self->priv->menu_disconnect, TRUE);
     gtk_widget_set_sensitive(self->priv->toolbar_disconnect, TRUE);
-    gtk_widget_set_sensitive(self->priv->toolbar_reconnect, TRUE);
+    gtk_widget_set_sensitive(self->priv->toolbar_reconnect, FALSE);
 
     g_signal_connect(terminal,
                      "focus-in-event",
@@ -1360,8 +1341,10 @@ mud_window_disconnected(MudWindow *self)
     g_return_if_fail(IS_MUD_WINDOW(self));
 
     gtk_widget_set_sensitive(self->priv->startlog, FALSE);
+    gtk_widget_set_sensitive(self->priv->menu_reconnect, TRUE);
     gtk_widget_set_sensitive(self->priv->menu_disconnect, FALSE);
     gtk_widget_set_sensitive(self->priv->toolbar_disconnect, FALSE);
+    gtk_widget_set_sensitive(self->priv->toolbar_reconnect, TRUE);
 
     if(gtk_widget_get_visible(self->priv->password_entry))
     {


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