--- a/libpurple/protocols/ircv3/purpleircv3connection.c Mon Oct 31 22:52:24 2022 -0500
+++ b/libpurple/protocols/ircv3/purpleircv3connection.c Mon Oct 31 23:00:12 2022 -0500
@@ -25,7 +25,6 @@
@@ -33,10 +32,7 @@
static GParamSpec *properties[N_PROPERTIES] = {NULL, };
struct _PurpleIRCv3Connection {
- GError *validate_error;
- PurpleAccount *account;
+ PurpleConnection parent; GSocketConnection *connection;
GCancellable *cancellable;
@@ -52,42 +48,32 @@
G_DEFINE_DYNAMIC_TYPE(PurpleIRCv3Connection, purple_ircv3_connection,
+ PURPLE_TYPE_CONNECTION) /******************************************************************************
*****************************************************************************/
-purple_ircv3_connection_set_account(PurpleIRCv3Connection *connection,
- PurpleAccount *account)
- g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
- if(g_set_object(&connection->account, account)) {
- g_object_notify_by_pspec(G_OBJECT(connection),
- properties[PROP_ACCOUNT]);
purple_ircv3_connection_send_user_command(PurpleIRCv3Connection *connection) {
- PurpleConnection *purple_connection = NULL;
+ PurpleAccount *account = NULL; const char *identname = NULL;
const char *nickname = NULL;
const char *realname = NULL;
- purple_connection = purple_account_get_connection(connection->account);
- nickname = purple_connection_get_display_name(purple_connection);
+ purple_connection_get_display_name(PURPLE_CONNECTION(connection)); + account = purple_connection_get_account(PURPLE_CONNECTION(connection)); /* The stored value could be an empty string, so pass a default of empty
* string and then if it was empty, set our correct fallback.
- identname = purple_account_get_string(connection->account, "ident", "");
+ identname = purple_account_get_string(account, "ident", ""); if(identname == NULL || *identname == '\0') {
- realname = purple_account_get_string(connection->account, "real-name", "");
+ realname = purple_account_get_string(account, "real-name", ""); if(realname == NULL || *realname == '\0') {
@@ -98,12 +84,10 @@
purple_ircv3_connection_send_nick_command(PurpleIRCv3Connection *connection) {
- PurpleConnection *purple_connection = NULL;
const char *nickname = NULL;
- purple_connection = purple_account_get_connection(connection->account);
- nickname = purple_connection_get_display_name(purple_connection);
+ purple_connection_get_display_name(PURPLE_CONNECTION(connection)); purple_ircv3_connection_writef(connection, "NICK %s", nickname);
@@ -115,8 +99,7 @@
purple_ircv3_connection_read_cb(GObject *source, GAsyncResult *result,
- PurpleIRCv3Connection *connection = NULL;
- PurpleConnection *purple_connection = data;
+ PurpleIRCv3Connection *connection = data; GDataInputStream *istream = G_DATA_INPUT_STREAM(source);
@@ -125,24 +108,24 @@
line = g_data_input_stream_read_line_finish(istream, result, &length,
if(line == NULL || error != NULL) {
- g_set_error_literal(&error, PURPLE_CONNECTION_ERROR,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Server closed the connection"));
- g_prefix_error(&error, "%s", _("Lost connection with server: "));
+ if(PURPLE_IS_CONNECTION(connection)) { + g_set_error_literal(&error, PURPLE_CONNECTION_ERROR, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Server closed the connection")); + g_prefix_error(&error, "%s", _("Lost connection with server: ")); + purple_connection_take_error(PURPLE_CONNECTION(connection), error); - purple_connection_take_error(purple_connection, error);
/* In the off chance that line was returned, make sure we free it. */
- connection = g_object_get_data(G_OBJECT(purple_connection),
- PURPLE_IRCV3_CONNECTION_KEY);
purple_ircv3_parser_parse(connection->parser, line, &error, connection);
@@ -152,7 +135,7 @@
purple_ircv3_connection_read_cb,
@@ -168,14 +151,11 @@
- PurpleConnection *purple_connection = NULL;
- purple_connection = purple_account_get_connection(connection->account);
purple_queued_output_stream_clear_queue(stream);
g_prefix_error(&error, "%s", _("Lost connection with server: "));
- purple_connection_take_error(purple_connection, error);
+ purple_connection_take_error(PURPLE_CONNECTION(connection), error); @@ -185,8 +165,7 @@
purple_ircv3_connection_connected_cb(GObject *source, GAsyncResult *result,
- PurpleIRCv3Connection *connection = NULL;
- PurpleConnection *purple_connection = data;
+ PurpleIRCv3Connection *connection = data; GInputStream *istream = NULL;
GOutputStream *ostream = NULL;
@@ -198,15 +177,12 @@
if(conn == NULL || error != NULL) {
g_prefix_error(&error, "%s", _("Unable to connect: "));
- purple_connection_take_error(purple_connection, error);
+ purple_connection_take_error(PURPLE_CONNECTION(connection), error); - connection = g_object_get_data(G_OBJECT(purple_connection),
- PURPLE_IRCV3_CONNECTION_KEY);
- purple_connection_set_state(purple_connection,
+ purple_connection_set_state(PURPLE_CONNECTION(connection), PURPLE_CONNECTION_STATE_CONNECTED);
g_message("Successfully connected to %s", connection->server_name);
@@ -231,7 +207,7 @@
purple_ircv3_connection_read_cb,
/* Send our registration commands. */
purple_ircv3_connection_writef(connection, "CAP LS %s",
@@ -241,6 +217,89 @@
/******************************************************************************
+ * PurpleConnection Implementation + *****************************************************************************/ +purple_ircv3_connection_connect(PurpleConnection *purple_connection, + PurpleIRCv3Connection *connection = NULL; + PurpleAccount *account = NULL; + GSocketClient *client = NULL; + gint default_port = PURPLE_IRCV3_DEFAULT_TLS_PORT; + gboolean use_tls = TRUE; + g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(purple_connection), FALSE); + connection = PURPLE_IRCV3_CONNECTION(purple_connection); + account = purple_connection_get_account(purple_connection); + client = purple_gio_socket_client_new(account, error); + if(!G_IS_SOCKET_CLIENT(client)) { + if(error != NULL && *error != NULL) { + purple_connection_take_error(purple_connection, *error); + /* Turn on TLS if requested. */ + use_tls = purple_account_get_bool(account, "use-tls", TRUE); + g_socket_client_set_tls(client, use_tls); + /* If TLS is not being used, set the default port to the plain port. */ + default_port = PURPLE_IRCV3_DEFAULT_PLAIN_PORT; + port = purple_account_get_int(account, "port", default_port); + /* Finally start the async connection. */ + g_socket_client_connect_to_host_async(client, connection->server_name, + port, connection->cancellable, + purple_ircv3_connection_connected_cb, + g_clear_object(&client); +purple_ircv3_connection_disconnect(PurpleConnection *purple_connection, + PurpleIRCv3Connection *connection = NULL; + g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(purple_connection), FALSE); + connection = PURPLE_IRCV3_CONNECTION(purple_connection); + /* TODO: send QUIT command. */ + /* Cancel the cancellable to tell everyone we're shutting down. */ + if(G_IS_CANCELLABLE(connection->cancellable)) { + g_cancellable_cancel(connection->cancellable); + g_clear_object(&connection->cancellable); + if(G_IS_SOCKET_CONNECTION(connection->connection)) { + GInputStream *istream = G_INPUT_STREAM(connection->input); + GOutputStream *ostream = G_OUTPUT_STREAM(connection->output); + purple_gio_graceful_close(G_IO_STREAM(connection->connection), + g_clear_object(&connection->input); + g_clear_object(&connection->output); + g_clear_object(&connection->connection); +/****************************************************************************** *****************************************************************************/
@@ -250,10 +309,6 @@
PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
- g_value_set_object(value,
- purple_ircv3_connection_get_account(connection));
g_value_set_object(value,
purple_ircv3_connection_get_cancellable(connection));
@@ -272,13 +327,9 @@
purple_ircv3_connection_set_property(GObject *obj, guint param_id,
const GValue *value, GParamSpec *pspec)
- PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
+ // PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
- purple_ircv3_connection_set_account(connection,
- g_value_get_object(value));
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -289,7 +340,6 @@
purple_ircv3_connection_dispose(GObject *obj) {
PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
- g_clear_object(&connection->account);
g_clear_object(&connection->cancellable);
g_clear_object(&connection->input);
@@ -305,7 +355,6 @@
purple_ircv3_connection_finalize(GObject *obj) {
PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
- g_clear_error(&connection->validate_error);
g_clear_pointer(&connection->server_name, g_free);
g_clear_pointer(&connection->capabilities, g_free);
@@ -316,30 +365,19 @@
purple_ircv3_connection_constructed(GObject *obj) {
PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj);
- PurpleConnection *purple_connection = NULL;
+ PurpleAccount *account = NULL; gchar **userparts = NULL;
const gchar *username = NULL;
G_OBJECT_CLASS(purple_ircv3_connection_parent_class)->constructed(obj);
- purple_connection = purple_account_get_connection(connection->account);
- /* Make sure the username (which includes the servername via usersplits),
- * does not contain any whitespace.
- username = purple_account_get_username(connection->account);
- if(strpbrk(username, " \t\v\r\n") != NULL) {
- g_set_error(&connection->validate_error,
- PURPLE_CONNECTION_ERROR,
- PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
- _("IRC nick and server may not contain whitespace"));
+ account = purple_connection_get_account(PURPLE_CONNECTION(connection)); /* Split the username into nick and server and store the values. */
+ username = purple_account_get_username(account); userparts = g_strsplit(username, "@", 2);
- purple_connection_set_display_name(purple_connection, userparts[0]);
+ purple_connection_set_display_name(PURPLE_CONNECTION(connection), connection->server_name = g_strdup(userparts[1]);
@@ -358,6 +396,7 @@
purple_ircv3_connection_class_init(PurpleIRCv3ConnectionClass *klass) {
GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+ PurpleConnectionClass *connection_class = PURPLE_CONNECTION_CLASS(klass); obj_class->get_property = purple_ircv3_connection_get_property;
obj_class->set_property = purple_ircv3_connection_set_property;
@@ -365,18 +404,8 @@
obj_class->dispose = purple_ircv3_connection_dispose;
obj_class->finalize = purple_ircv3_connection_finalize;
- * PurpleIRCv3Connection:account:
- * The [class@Purple.Account] that this connection is for.
- properties[PROP_ACCOUNT] = g_param_spec_object(
- "The account for this connection",
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ connection_class->connect = purple_ircv3_connection_connect; + connection_class->disconnect = purple_ircv3_connection_disconnect; * PurpleIRCv3Connection:cancellable:
@@ -418,21 +447,6 @@
purple_ircv3_connection_register_type(G_TYPE_MODULE(plugin));
-purple_ircv3_connection_new(PurpleAccount *account) {
- PURPLE_IRCV3_TYPE_CONNECTION,
-purple_ircv3_connection_get_account(PurpleIRCv3Connection *connection) {
- g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), NULL);
- return connection->account;
purple_ircv3_connection_get_cancellable(PurpleIRCv3Connection *connection) {
g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), NULL);
@@ -440,87 +454,6 @@
return connection->cancellable;
-purple_ircv3_connection_valid(PurpleIRCv3Connection *connection,
- g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), FALSE);
- if(connection->validate_error != NULL) {
- g_propagate_error(error, connection->validate_error);
- connection->validate_error = NULL;
-purple_ircv3_connection_connect(PurpleIRCv3Connection *connection) {
- PurpleConnection *purple_connection = NULL;
- GSocketClient *client = NULL;
- gint default_port = PURPLE_IRCV3_DEFAULT_TLS_PORT;
- gboolean use_tls = TRUE;
- g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
- g_return_if_fail(connection->connection == NULL);
- purple_connection = purple_account_get_connection(connection->account);
- client = purple_gio_socket_client_new(connection->account, &error);
- if(!G_IS_SOCKET_CLIENT(client)) {
- purple_connection_take_error(purple_connection, error);
- /* Turn on TLS if requested. */
- use_tls = purple_account_get_bool(connection->account, "use-tls", TRUE);
- g_socket_client_set_tls(client, use_tls);
- /* If TLS is not being used, set the default port to the plain port. */
- default_port = PURPLE_IRCV3_DEFAULT_PLAIN_PORT;
- port = purple_account_get_int(connection->account, "port", default_port);
- /* Finally start the async connection. */
- g_socket_client_connect_to_host_async(client, connection->server_name,
- port, connection->cancellable,
- purple_ircv3_connection_connected_cb,
- g_clear_object(&client);
-purple_ircv3_connection_close(PurpleIRCv3Connection *connection) {
- g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
- /* TODO: send QUIT command. */
- /* Cancel the cancellable to tell everyone we're shutting down. */
- if(G_IS_CANCELLABLE(connection->cancellable)) {
- g_cancellable_cancel(connection->cancellable);
- g_clear_object(&connection->cancellable);
- if(G_IS_SOCKET_CONNECTION(connection->connection)) {
- GInputStream *istream = G_INPUT_STREAM(connection->input);
- GOutputStream *ostream = G_OUTPUT_STREAM(connection->output);
- purple_gio_graceful_close(G_IO_STREAM(connection->connection),
- g_clear_object(&connection->input);
- g_clear_object(&connection->output);
- g_clear_object(&connection->connection);
purple_ircv3_connection_writef(PurpleIRCv3Connection *connection,
--- a/libpurple/protocols/ircv3/purpleircv3protocol.c Mon Oct 31 22:52:24 2022 -0500
+++ b/libpurple/protocols/ircv3/purpleircv3protocol.c Mon Oct 31 23:00:12 2022 -0500
@@ -23,10 +23,6 @@
#include "purpleircv3connection.h"
#include "purpleircv3core.h"
-} PurpleIRCv3ProtocolPrivate;
/******************************************************************************
* PurpleProtocol Implementation
*****************************************************************************/
@@ -84,44 +80,36 @@
-purple_ircv3_protocol_login(G_GNUC_UNUSED PurpleProtocol *protocol,
- PurpleAccount *account)
+static PurpleConnection * +purple_ircv3_protocol_create_connection(PurpleProtocol *protocol, + PurpleAccount *account, - PurpleIRCv3Connection *connection = NULL;
- PurpleConnection *purple_connection = NULL;
+ const char *username = NULL; + g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); + g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); - purple_connection = purple_account_get_connection(account);
+ /* Make sure the username (which includes the servername via usersplits), + * does not contain any whitespace. + username = purple_account_get_username(account); + if(strpbrk(username, " \t\v\r\n") != NULL) { + PURPLE_CONNECTION_ERROR, + PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, + _("IRC nick and server may not contain whitespace")); - connection = purple_ircv3_connection_new(account);
- if(!purple_ircv3_connection_valid(connection, &error)) {
- purple_connection_take_error(purple_connection, error);
- g_object_set_data_full(G_OBJECT(purple_connection),
- PURPLE_IRCV3_CONNECTION_KEY,
- connection, g_object_unref);
- purple_ircv3_connection_connect(connection);
-purple_ircv3_protocol_close(G_GNUC_UNUSED PurpleProtocol *protocol,
- PurpleConnection *purple_connection)
- PurpleIRCv3Connection *connection = NULL;
- connection = g_object_get_data(G_OBJECT(purple_connection),
- PURPLE_IRCV3_CONNECTION_KEY);
- purple_ircv3_connection_close(connection);
- /* Set our connection data to NULL which will remove the last reference. */
- g_object_set_data(G_OBJECT(purple_connection), PURPLE_IRCV3_CONNECTION_KEY,
+ PURPLE_IRCV3_TYPE_CONNECTION, @@ -149,9 +137,8 @@
/******************************************************************************
*****************************************************************************/
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
- PurpleIRCv3Protocol, purple_ircv3_protocol, PURPLE_TYPE_PROTOCOL, 0,
- G_ADD_PRIVATE_DYNAMIC(PurpleIRCv3Protocol))
+G_DEFINE_DYNAMIC_TYPE(PurpleIRCv3Protocol, purple_ircv3_protocol, purple_ircv3_protocol_init(PurpleIRCv3Protocol *protocol) {
@@ -168,8 +155,8 @@
protocol_class->get_user_splits = purple_ircv3_protocol_get_user_splits;
protocol_class->get_account_options =
purple_ircv3_protocol_get_account_options;
- protocol_class->login = purple_ircv3_protocol_login;
- protocol_class->close = purple_ircv3_protocol_close;
+ protocol_class->create_connection = + purple_ircv3_protocol_create_connection; protocol_class->status_types = purple_ircv3_protocol_status_types;