+static HCConn *
+server_conn_new (char *server, char *port, int ssl)
+{
+ int fd;
+ HCConn *conn;
+ HCConn *ssl_conn;
+ int r;
+ fd = hc_tcp_connect (server, port);
+ if (fd < 0)
+ {
+ g_warning ("Could not connect to server at %s:%s.", server, port);
+ return NULL;
+ }
+ conn = hc_conn_new (NULL, NULL);
+ r = hc_conn_set_driver_channel (conn, fd);
+ if (r != 0)
+ {
+ hc_conn_close (conn);
+ close (fd);
+ return NULL;
+ }
+ if (!ssl)
+ return conn;
+ ssl_conn = hc_conn_new (NULL, NULL);
+ r = hc_conn_set_driver_ssl_client (ssl_conn, conn);
+ if (r != 0)
+ {
+ hc_conn_close (ssl_conn);
+ hc_conn_close (conn);
+ return NULL;
+ }
+ return ssl_conn;
+}
+
+static HCConn *
+client_conn_new (int fd)
+{
+ HCConn *conn;
+ HCConn *ssl_conn;
+ HCConn *pop_conn;
+ int r;
+ conn = hc_conn_new (NULL, NULL);
+ r = hc_conn_set_driver_channel (conn, fd);
+ if (r != 0)
+ {
+ hc_conn_close (conn);
+ close (fd);
+ return NULL;
+ }
+ ssl_conn = hc_conn_new (NULL, NULL);
+ hc_conn_set_driver_ssl_server (ssl_conn, conn);
+ if (r != 0)
+ {
+ hc_conn_close (ssl_conn);
+ hc_conn_close (conn);
+ return NULL;
+ }
+ pop_conn = hc_conn_new (NULL, NULL);
+ r = hc_conn_set_driver_pop (pop_conn, ssl_conn);
+ if (r != 0)
+ {
+ hc_conn_close (pop_conn);
+ hc_conn_close (ssl_conn);
+ return NULL;
+ }
+ return pop_conn;
+}
+
+static void
+push_other (HCConn *conn, HCEvent event, gpointer data)
+{
+ char buffer[4096];
+ int r;
+ switch (event)
+ {
+ case HC_EVENT_READ:
+ while ((r = hc_conn_read (conn, buffer, sizeof (buffer))) > 0)
+ hc_conn_write (data, buffer, r);
+ break;
+ case HC_EVENT_CLOSE:
+ hc_conn_close (conn);
+ hc_conn_close (data);
+ break;
+ }
+}
+
+static void
+ssl_connected (HCConn *client_conn, HCEvent event, gpointer data)
+{
+ struct pop_address *address = data;
+ HCConn *server_conn;
+ if (event != HC_EVENT_CONNECT)
+ {
+ g_debug ("Did not get connect event when trying to handshake:"
+ " got %d", event);
+ hc_conn_close (client_conn);
+ return;
+ }
+ server_conn = server_conn_new (address->server, address->port,
+ address->ssl);
+ if (server_conn == NULL)
+ {
+ g_debug ("Failure to create connection to server.");
+ hc_conn_close (client_conn);
+ return;
+ }
+ hc_conn_set_callback (client_conn, push_other, server_conn);
+ hc_conn_set_callback (server_conn, push_other, client_conn);
+}
+