qulogic/pidgin

start of the new xmpp's connection

4 months ago, Gary Kramlich
a8a644e3e561
Parents 26ae6ffab6d0
Children 7a4558293dca
start of the new xmpp's connection

Right now this just establishes a TCP connection via SRV record and nothing
more.

Testing Done:
Connected to pidginchat.com successfully and verified the traffic via charles proxy.

Reviewed at https://reviews.imfreedom.org/r/2866/
--- a/protocols/xmpp/meson.build Tue Dec 05 17:53:57 2023 -0600
+++ b/protocols/xmpp/meson.build Tue Dec 12 01:21:38 2023 -0600
@@ -1,9 +1,12 @@
XMPP_SOURCES = [
+ 'purplexmppconnection.c',
'purplexmppcore.c',
'purplexmppprotocol.c',
]
XMPP_HEADERS = [
+ 'purplexmppconnection.h',
+ 'purplexmppconstants.h',
'purplexmppcore.h',
'purplexmppprotocol.h',
]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/protocols/xmpp/purplexmppconnection.c Tue Dec 12 01:21:38 2023 -0600
@@ -0,0 +1,213 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include <xeme.h>
+
+#include "purplexmppconnection.h"
+
+#include "purplexmppconstants.h"
+#include "purplexmppcore.h"
+
+struct _PurpleXmppConnection {
+ PurpleConnection parent;
+
+ XemeConnection *xeme_connection;
+ XemeOutputStream *output;
+};
+
+G_DEFINE_DYNAMIC_TYPE(PurpleXmppConnection, purple_xmpp_connection,
+ PURPLE_TYPE_CONNECTION)
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static void
+purple_xmpp_connection_connect_cb(GObject *source, GAsyncResult *result,
+ gpointer data)
+{
+ PurpleXmppConnection *connection = data;
+ XemeOutputStream *output = NULL;
+ GError *error = NULL;
+
+ output = xeme_connection_connect_finish(XEME_CONNECTION(source), result,
+ &error);
+ if(error != NULL) {
+ purple_connection_take_error(PURPLE_CONNECTION(connection), error);
+
+ return;
+ }
+
+ connection->output = output;
+
+ purple_connection_set_state(PURPLE_CONNECTION(connection),
+ PURPLE_CONNECTION_STATE_CONNECTED);
+}
+
+/******************************************************************************
+ * PurpleConnection Implementation
+ *****************************************************************************/
+static gboolean
+purple_xmpp_connection_connect(PurpleConnection *purple_connection,
+ GError **error)
+{
+ PurpleXmppConnection *connection = NULL;
+ PurpleAccount *account = NULL;
+ XemeInputStream *input = NULL;
+ XemeTlsMode xeme_tls_mode = XEME_TLS_MODE_DIRECT_TLS;
+ GCancellable *cancellable = NULL;
+ GError *local_error = NULL;
+ GProxyResolver *resolver = NULL;
+ const char *resource = NULL;
+ const char *server = NULL;
+ const char *tls_mode = NULL;
+ const char *username = NULL;
+ guint16 port = PURPLE_XMPP_DEFAULT_PORT_TLS;
+
+ g_return_val_if_fail(PURPLE_XMPP_IS_CONNECTION(purple_connection), FALSE);
+
+ purple_connection_set_state(purple_connection,
+ PURPLE_CONNECTION_STATE_CONNECTING);
+
+ connection = PURPLE_XMPP_CONNECTION(purple_connection);
+ cancellable = purple_connection_get_cancellable(purple_connection);
+ account = purple_connection_get_account(purple_connection);
+
+ /* Figure out what proxy resolver to use. */
+ resolver = purple_proxy_get_proxy_resolver(account, &local_error);
+ if(!G_IS_PROXY_RESOLVER(resolver) || local_error != NULL) {
+ if(local_error == NULL) {
+ local_error = g_error_new(PURPLE_XMPP_DOMAIN, 0, "unknown error");
+ }
+
+ g_propagate_error(error, local_error);
+
+ g_clear_object(&resolver);
+
+ return FALSE;
+ }
+
+ /* Grab some more information that we need. */
+ username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(account));
+ connection->xeme_connection = xeme_connection_new(username);
+
+ /* If we have a resource, tell the xeme connection about it. */
+ resource = purple_account_get_string(account, PURPLE_XMPP_OPTION_RESOURCE,
+ NULL);
+ if(!purple_strempty(resource)) {
+ xeme_connection_set_resource(connection->xeme_connection, resource);
+ }
+
+ /* If we have a server, tell the xeme connection about it. */
+ server = purple_account_get_string(account, PURPLE_XMPP_OPTION_SERVER,
+ NULL);
+ if(!purple_strempty(server)) {
+ xeme_connection_set_server(connection->xeme_connection, server);
+ }
+
+ /* Set whatever port we have on our xeme connection. */
+ port = purple_account_get_int(account, PURPLE_XMPP_OPTION_PORT,
+ PURPLE_XMPP_DEFAULT_PORT_TLS);
+ xeme_connection_set_port(connection->xeme_connection, port);
+
+ /* Figure out what if any TLS we're doing. This is initialized to direct
+ * tls above, so if we don't know which to use, that's what we'll end up
+ * using. Doing so should avoid possible accidental leaks.
+ */
+ tls_mode = purple_account_get_string(account, PURPLE_XMPP_OPTION_TLS_MODE,
+ PURPLE_XMPP_TLS_DIRECT);
+ if(purple_strequal(tls_mode, PURPLE_XMPP_TLS_DIRECT)) {
+ xeme_tls_mode = XEME_TLS_MODE_DIRECT_TLS;
+ } else if(purple_strequal(tls_mode, PURPLE_XMPP_TLS_STARTTLS)) {
+ xeme_tls_mode = XEME_TLS_MODE_START_TLS;
+ } else if(purple_strequal(tls_mode, PURPLE_XMPP_TLS_NONE)) {
+ xeme_tls_mode = XEME_TLS_MODE_NONE;
+ }
+
+ xeme_connection_set_tls_mode(connection->xeme_connection, xeme_tls_mode);
+
+ input = xeme_input_stream_new();
+
+ /* Finally start connecting!! */
+ xeme_connection_connect_async(connection->xeme_connection, input, resolver,
+ cancellable, purple_xmpp_connection_connect_cb,
+ connection);
+
+ g_clear_object(&input);
+
+ return TRUE;
+}
+
+static gboolean
+purple_xmpp_connection_disconnect(PurpleConnection *purple_connection,
+ GError **error)
+{
+ PurpleXmppConnection *connection = NULL;
+ PurpleConnectionClass *parent_class = NULL;
+
+ g_return_val_if_fail(PURPLE_XMPP_IS_CONNECTION(purple_connection), FALSE);
+
+ connection = PURPLE_XMPP_CONNECTION(purple_connection);
+
+ /* Chain up to our parent's disconnect method. */
+ parent_class = PURPLE_CONNECTION_CLASS(purple_xmpp_connection_parent_class);
+ parent_class->disconnect(purple_connection, error);
+
+ return xeme_connection_close(connection->xeme_connection, error);
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+purple_xmpp_connection_dispose(GObject *obj) {
+ PurpleXmppConnection *connection = PURPLE_XMPP_CONNECTION(obj);
+
+ g_clear_object(&connection->xeme_connection);
+ g_clear_object(&connection->output);
+
+ G_OBJECT_CLASS(purple_xmpp_connection_parent_class)->dispose(obj);
+}
+
+static void
+purple_xmpp_connection_init(G_GNUC_UNUSED PurpleXmppConnection *connection) {
+}
+
+static void
+purple_xmpp_connection_class_init(PurpleXmppConnectionClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+ PurpleConnectionClass *connection_class = PURPLE_CONNECTION_CLASS(klass);
+
+ obj_class->dispose = purple_xmpp_connection_dispose;
+
+ connection_class->connect = purple_xmpp_connection_connect;
+ connection_class->disconnect = purple_xmpp_connection_disconnect;
+}
+
+static void
+purple_xmpp_connection_class_finalize(G_GNUC_UNUSED PurpleXmppConnectionClass *klass) {
+}
+
+/******************************************************************************
+ * Internal API
+ *****************************************************************************/
+void
+purple_xmpp_connection_register(GPluginNativePlugin *plugin) {
+ purple_xmpp_connection_register_type(G_TYPE_MODULE(plugin));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/protocols/xmpp/purplexmppconnection.h Tue Dec 12 01:21:38 2023 -0600
@@ -0,0 +1,48 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef PURPLE_XMPP_CONNECTION_H
+#define PURPLE_XMPP_CONNECTION_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+#define PURPLE_XMPP_TYPE_CONNECTION (purple_xmpp_connection_get_type())
+
+G_DECLARE_FINAL_TYPE(PurpleXmppConnection, purple_xmpp_connection, PURPLE_XMPP,
+ CONNECTION, PurpleConnection)
+
+/**
+ * purple_xmpp_connection_register: (skip)
+ * @plugin: The GTypeModule
+ *
+ * Registers the dynamic type using @plugin.
+ *
+ * Since: 3.0.0
+ */
+G_GNUC_INTERNAL void purple_xmpp_connection_register(GPluginNativePlugin *plugin);
+
+G_END_DECLS
+
+#endif /* PURPLE_XMPP_CONNECTION_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/protocols/xmpp/purplexmppconstants.h Tue Dec 12 01:21:38 2023 -0600
@@ -0,0 +1,36 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef PURPLE_XMPP_CONSTANTS_H
+#define PURPLE_XMPP_CONSTANTS_H
+
+#define PURPLE_XMPP_DEFAULT_PORT_CLEAR (5222)
+#define PURPLE_XMPP_DEFAULT_PORT_TLS (5223)
+
+#define PURPLE_XMPP_OPTION_RESOURCE ("resource")
+#define PURPLE_XMPP_OPTION_SERVER ("server")
+#define PURPLE_XMPP_OPTION_PORT ("port")
+#define PURPLE_XMPP_OPTION_TLS_MODE ("tls-mode")
+#define PURPLE_XMPP_OPTION_SASL_LOGIN_NAME ("sasl-login-name")
+#define PURPLE_XMPP_OPTION_SASL_MECHANISMS ("sasl-mechanisms")
+#define PURPLE_XMPP_OPTION_PLAIN_SASL_IN_CLEAR ("plain-sasl-in-clear")
+
+#define PURPLE_XMPP_TLS_DIRECT ("direct")
+#define PURPLE_XMPP_TLS_STARTTLS ("starttls")
+#define PURPLE_XMPP_TLS_NONE ("none")
+
+#endif /* PURPLE_XMPP_CONSTANTS_H */
--- a/protocols/xmpp/purplexmppcore.c Tue Dec 05 17:53:57 2023 -0600
+++ b/protocols/xmpp/purplexmppcore.c Tue Dec 12 01:21:38 2023 -0600
@@ -26,6 +26,7 @@
#include "purplexmppcore.h"
+#include "purplexmppconnection.h"
#include "purplexmppprotocol.h"
/******************************************************************************
@@ -71,6 +72,7 @@
}
purple_xmpp_protocol_register(GPLUGIN_NATIVE_PLUGIN(plugin));
+ purple_xmpp_connection_register(GPLUGIN_NATIVE_PLUGIN(plugin));
xmpp_protocol = purple_xmpp_protocol_new();
--- a/protocols/xmpp/purplexmppprotocol.c Tue Dec 05 17:53:57 2023 -0600
+++ b/protocols/xmpp/purplexmppprotocol.c Tue Dec 12 01:21:38 2023 -0600
@@ -20,6 +20,9 @@
#include "purplexmppprotocol.h"
+#include "purplexmppconnection.h"
+#include "purplexmppconstants.h"
+
struct _PurpleXmppProtocol {
PurpleProtocol parent;
};
@@ -39,6 +42,59 @@
}
static GList *
+purple_xmpp_protocol_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol)
+{
+ PurpleAccountOption *option = NULL;
+ PurpleKeyValuePair *pair = NULL;
+ GList *options = NULL;
+ GList *items = NULL;
+
+ option = purple_account_option_string_new(_("Resource"),
+ PURPLE_XMPP_OPTION_RESOURCE,
+ NULL);
+ options = g_list_append(options, option);
+
+ option = purple_account_option_string_new(_("Server"),
+ PURPLE_XMPP_OPTION_SERVER, NULL);
+ options = g_list_append(options, option);
+
+ option = purple_account_option_int_new(_("Port"), PURPLE_XMPP_OPTION_PORT,
+ PURPLE_XMPP_DEFAULT_PORT_TLS);
+ options = g_list_append(options, option);
+
+ pair = purple_key_value_pair_new(_("Direct TLS"), PURPLE_XMPP_TLS_DIRECT);
+ items = g_list_append(items, pair);
+ pair = purple_key_value_pair_new(_("STARTTLS"), PURPLE_XMPP_TLS_STARTTLS);
+ items = g_list_append(items, pair);
+ pair = purple_key_value_pair_new(_("None"), PURPLE_XMPP_TLS_NONE);
+ items = g_list_append(items, pair);
+
+ option = purple_account_option_list_new(_("TLS Mode"),
+ PURPLE_XMPP_OPTION_TLS_MODE,
+ items);
+ options = g_list_append(options, option);
+
+ option = purple_account_option_string_new(_("SASL login name"),
+ PURPLE_XMPP_OPTION_SASL_LOGIN_NAME,
+ NULL);
+ options = g_list_append(options, option);
+
+ option = purple_account_option_string_new(_("SASL mechanisms"),
+ PURPLE_XMPP_OPTION_SASL_MECHANISMS,
+ NULL);
+ options = g_list_append(options, option);
+
+ option = purple_account_option_bool_new(_("Allow plaintext SASL auth over "
+ "unencrypted connection"),
+ PURPLE_XMPP_OPTION_PLAIN_SASL_IN_CLEAR,
+ FALSE);
+ options = g_list_append(options, option);
+
+ return options;
+}
+
+
+static GList *
purple_xmpp_protocol_status_types(G_GNUC_UNUSED PurpleProtocol *protocol,
G_GNUC_UNUSED PurpleAccount *account)
{
@@ -54,6 +110,20 @@
return types;
}
+static PurpleConnection *
+purple_xmpp_protocol_create_connection(PurpleProtocol *protocol,
+ PurpleAccount *account,
+ const char *password,
+ G_GNUC_UNUSED GError **error)
+{
+ return g_object_new(
+ PURPLE_XMPP_TYPE_CONNECTION,
+ "protocol", protocol,
+ "account", account,
+ "password", password,
+ NULL);
+}
+
/******************************************************************************
* GObject Implementation
*****************************************************************************/
@@ -77,7 +147,10 @@
PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
protocol_class->get_user_splits = purple_xmpp_protocol_get_user_splits;
+ protocol_class->get_account_options = purple_xmpp_protocol_get_account_options;
protocol_class->status_types = purple_xmpp_protocol_status_types;
+
+ protocol_class->create_connection = purple_xmpp_protocol_create_connection;
}
/******************************************************************************
--- a/subprojects/xeme.wrap Tue Dec 05 17:53:57 2023 -0600
+++ b/subprojects/xeme.wrap Tue Dec 12 01:21:38 2023 -0600
@@ -1,4 +1,4 @@
[wrap-hg]
directory = xeme
url = https://keep.imfreedom.org/xeme/xeme/
-revision = 6f495ad383bb
+revision = 7f086dfa22c7