/pidgin/main: 4523af5dc59c: irc: Port to use Gio directly for th...

Mike Ruprecht <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 4523af5dc59ccbb8c622e0ddaf2bd5cf79a3e9fa
Author:	 Mike Ruprecht <[email protected]>
Date:	 2016-04-29 02:31 -0500
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/4523af5dc59c

Description:

irc: Port to use Gio directly for the main connection

This patch ports the IRC plugin to directly use Gio for the main
connection. It uses a GSocketConnection for the main connection,
GDataInputStream for receiving data, and a PurpleQueuedOutputStream
for sending data. All of these are using their asynchronous functions.

diffstat:

 libpurple/protocols/irc/dcc_send.c |   11 +-
 libpurple/protocols/irc/irc.c      |  355 +++++++++++++-----------------------
 libpurple/protocols/irc/irc.h      |   14 +-
 3 files changed, 142 insertions(+), 238 deletions(-)

diffs (truncated from 569 to 300 lines):

diff --git a/libpurple/protocols/irc/dcc_send.c b/libpurple/protocols/irc/dcc_send.c
--- a/libpurple/protocols/irc/dcc_send.c
+++ b/libpurple/protocols/irc/dcc_send.c
@@ -279,6 +279,8 @@ irc_dccsend_network_listen_cb(int sock, 
 	struct irc_xfer_send_data *xd;
 	PurpleConnection *gc;
 	struct irc_conn *irc;
+	GSocket *gsock;
+	int fd = -1;
 	const char *arg[2];
 	char *tmp;
 	struct in_addr addr;
@@ -317,7 +319,14 @@ irc_dccsend_network_listen_cb(int sock, 
 
 	/* Send the intended recipient the DCC request */
 	arg[0] = purple_xfer_get_remote_user(xfer);
-	inet_aton(purple_network_get_my_ip(irc->fd), &addr);
+
+	/* Fetching this fd here assumes it won't be modified */
+	gsock = g_socket_connection_get_socket(irc->conn);
+	if (gsock != NULL) {
+		fd = g_socket_get_fd(gsock);
+	}
+
+	inet_aton(purple_network_get_my_ip(fd), &addr);
 	arg[1] = tmp = g_strdup_printf("\001DCC SEND \"%s\" %u %hu %" G_GOFFSET_FORMAT "\001",
 	                               purple_xfer_get_filename(xfer), ntohl(addr.s_addr),
 	                               port, purple_xfer_get_size(xfer));
diff --git a/libpurple/protocols/irc/irc.c b/libpurple/protocols/irc/irc.c
--- a/libpurple/protocols/irc/irc.c
+++ b/libpurple/protocols/irc/irc.c
@@ -32,6 +32,7 @@
 #include "notify.h"
 #include "protocol.h"
 #include "plugins.h"
+#include "tls-certificate.h"
 #include "util.h"
 #include "version.h"
 
@@ -46,15 +47,12 @@ static GList *irc_status_types(PurpleAcc
 static GList *irc_get_actions(PurpleConnection *gc);
 /* static GList *irc_chat_info(PurpleConnection *gc); */
 static void irc_login(PurpleAccount *account);
-static void irc_login_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond);
-static void irc_login_cb(gpointer data, gint source, const gchar *error_message);
-static void irc_ssl_connect_failure(PurpleSslConnection *gsc, PurpleSslErrorType error, gpointer data);
+static void irc_login_cb(GObject *source, GAsyncResult *res, gpointer user_data);
 static void irc_close(PurpleConnection *gc);
 static int irc_im_send(PurpleConnection *gc, PurpleMessage *msg);
 static int irc_chat_send(PurpleConnection *gc, int id, PurpleMessage *msg);
 static void irc_chat_join (PurpleConnection *gc, GHashTable *data);
-static void irc_input_cb(gpointer data, gint source, PurpleInputCondition cond);
-static void irc_input_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond);
+static void irc_read_input(struct irc_conn *irc);
 
 static guint irc_nick_hash(const char *nick);
 static gboolean irc_nick_equal(const char *nick1, const char *nick2);
@@ -87,19 +85,6 @@ static void irc_view_motd(PurpleProtocol
 	g_free(body);
 }
 
-static int do_send(struct irc_conn *irc, const char *buf, gsize len)
-{
-	int ret;
-
-	if (irc->gsc) {
-		ret = purple_ssl_write(irc->gsc, buf, len);
-	} else {
-		ret = write(irc->fd, buf, len);
-	}
-
-	return ret;
-}
-
 static int irc_send_raw(PurpleConnection *gc, const char *buf, int len)
 {
 	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
@@ -111,44 +96,21 @@ static int irc_send_raw(PurpleConnection
 }
 
 static void
-irc_send_cb(gpointer data, gint source, PurpleInputCondition cond)
+irc_flush_cb(GObject *source, GAsyncResult *res, gpointer data)
 {
-	struct irc_conn *irc = data;
-	int ret, writelen;
-	const gchar *buffer = NULL;
+	PurpleConnection *gc = data;
+	gboolean result;
+	GError *error = NULL;
 
-	writelen = purple_circular_buffer_get_max_read(irc->outbuf);
+	result = g_output_stream_flush_finish(G_OUTPUT_STREAM(source),
+			res, &error);
 
-	if (writelen == 0) {
-		purple_input_remove(irc->writeh);
-		irc->writeh = 0;
+	if (!result) {
+		purple_connection_g_error(gc, error,
+				_("Lost connection with server: %s"));
+		g_clear_error(&error);
 		return;
 	}
-
-	buffer = purple_circular_buffer_get_output(irc->outbuf);
-
-	ret = do_send(irc, buffer, writelen);
-
-	if (ret < 0 && errno == EAGAIN)
-		return;
-	else if (ret <= 0) {
-		PurpleConnection *gc = purple_account_get_connection(irc->account);
-		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
-			g_strerror(errno));
-		purple_connection_error (gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
-		return;
-	}
-
-	purple_circular_buffer_mark_read(irc->outbuf, ret);
-
-#if 0
-	/* We *could* try to write more if we wrote it all */
-	if (ret == write_len) {
-		irc_send_cb(data, source, cond);
-	}
-#endif
 }
 
 int irc_send(struct irc_conn *irc, const char *buf)
@@ -158,43 +120,27 @@ int irc_send(struct irc_conn *irc, const
 
 int irc_send_len(struct irc_conn *irc, const char *buf, int buflen)
 {
-	int ret;
  	char *tosend= g_strdup(buf);
+	GBytes *data;
 
 	purple_signal_emit(_irc_protocol, "irc-sending-text", purple_account_get_connection(irc->account), &tosend);
 	
 	if (tosend == NULL)
 		return 0;
 
-	/* If we're not buffering writes, try to send immediately */
-	if (!irc->writeh)
-		ret = do_send(irc, tosend, buflen);
-	else {
-		ret = -1;
-		errno = EAGAIN;
+	data = g_bytes_new_take(tosend, strlen(tosend));
+	purple_queued_output_stream_push_bytes(irc->output, data);
+	g_bytes_unref(data);
+
+	if (!g_output_stream_has_pending(G_OUTPUT_STREAM(irc->output))) {
+		/* Connection idle. Flush data. */
+		g_output_stream_flush_async(G_OUTPUT_STREAM(irc->output),
+				G_PRIORITY_DEFAULT, irc->cancellable,
+				irc_flush_cb,
+				purple_account_get_connection(irc->account));
 	}
 
-	/* purple_debug(PURPLE_DEBUG_MISC, "irc", "sent%s: %s",
-		irc->gsc ? " (ssl)" : "", tosend); */
-	if (ret <= 0 && errno != EAGAIN) {
-		PurpleConnection *gc = purple_account_get_connection(irc->account);
-		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
-			g_strerror(errno));
-		purple_connection_error (gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
-	} else if (ret < buflen) {
-		if (ret < 0)
-			ret = 0;
-		if (!irc->writeh)
-			irc->writeh = purple_input_add(
-				irc->gsc ? irc->gsc->fd : irc->fd,
-				PURPLE_INPUT_WRITE, irc_send_cb, irc);
-		purple_circular_buffer_append(irc->outbuf, tosend + ret,
-			buflen - ret);
-	}
-	g_free(tosend);
-	return ret;
+	return strlen(tosend);
 }
 
 /* XXX I don't like messing directly with these buddies */
@@ -337,6 +283,8 @@ static void irc_login(PurpleAccount *acc
 	struct irc_conn *irc;
 	char **userparts;
 	const char *username = purple_account_get_username(account);
+	GSocketClient *client;
+	GProxyResolver *resolver;
 
 	gc = purple_account_get_connection(account);
 	purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_NEWLINES |
@@ -351,9 +299,8 @@ static void irc_login(PurpleAccount *acc
 
 	irc = g_new0(struct irc_conn, 1);
 	purple_connection_set_protocol_data(gc, irc);
-	irc->fd = -1;
 	irc->account = account;
-	irc->outbuf = purple_circular_buffer_new(512);
+	irc->cancellable = g_cancellable_new();
 
 	userparts = g_strsplit(username, "@", 2);
 	purple_connection_set_display_name(gc, userparts[0]);
@@ -369,24 +316,31 @@ static void irc_login(PurpleAccount *acc
 
 	purple_connection_update_progress(gc, _("Connecting"), 1, 2);
 
-	if (purple_account_get_bool(account, "ssl", FALSE)) {
-		irc->gsc = purple_ssl_connect(account, irc->server,
-				purple_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT),
-				irc_login_cb_ssl, irc_ssl_connect_failure, gc);
+	if ((resolver = purple_proxy_get_proxy_resolver(account)) == NULL) {
+		/* Invalid proxy settings */
+		purple_connection_error (gc,
+			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			_("Unable to connect"));
+		return;
 	}
 
-	if (!irc->gsc) {
+	client = g_socket_client_new();
+	g_socket_client_set_proxy_resolver(client, resolver);
+	g_object_unref(resolver);
 
-		if (purple_proxy_connect(gc, account, irc->server,
-				 purple_account_get_int(account, "port", IRC_DEFAULT_PORT),
-				 irc_login_cb, gc) == NULL)
-		{
-			purple_connection_error (gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Unable to connect"));
-			return;
-		}
+	/* Optionally use TLS if it's set in the account settings */
+	if (purple_account_get_bool(account, "ssl", FALSE)) {
+		g_socket_client_set_tls(client, TRUE);
+		purple_tls_certificate_attach_to_socket_client(client);
 	}
+
+	g_socket_client_connect_to_host_async(client, irc->server,
+			purple_account_get_int(account, "port",
+					g_socket_client_get_tls(client) ?
+							IRC_DEFAULT_SSL_PORT :
+							IRC_DEFAULT_PORT),
+			irc->cancellable, irc_login_cb, gc);
+	g_object_unref(client);
 }
 
 static gboolean do_login(PurpleConnection *gc) {
@@ -458,49 +412,37 @@ static gboolean do_login(PurpleConnectio
 	return TRUE;
 }
 
-static void irc_login_cb_ssl(gpointer data, PurpleSslConnection *gsc,
-	PurpleInputCondition cond)
+static void
+irc_login_cb(GObject *source, GAsyncResult *res, gpointer user_data)
 {
-	PurpleConnection *gc = data;
+	PurpleConnection *gc = user_data;
+	GSocketConnection *conn;
+	GError *error = NULL;
+	struct irc_conn *irc;
 
-	if (do_login(gc)) {
-		purple_ssl_input_add(gsc, irc_input_cb_ssl, gc);
-	}
-}
+	conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
+			res, &error);
 
-static void irc_login_cb(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleConnection *gc = data;
-	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
-
-	if (source < 0) {
-		gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
-			error_message);
-		purple_connection_error (gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
+	if (conn == NULL) {
+		purple_connection_g_error(gc, error,
+				_("Unable to connect: %s"));
+		g_clear_error(&error);
 		return;
 	}
 
-	irc->fd = source;
+	irc = purple_connection_get_protocol_data(gc);
+	irc->conn = conn;
+	irc->output = purple_queued_output_stream_new(
+			g_io_stream_get_output_stream(G_IO_STREAM(irc->conn)));
 

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.