diff options
Diffstat (limited to 'patches/06-revert-purple-socket.patch')
-rw-r--r-- | patches/06-revert-purple-socket.patch | 637 |
1 files changed, 637 insertions, 0 deletions
diff --git a/patches/06-revert-purple-socket.patch b/patches/06-revert-purple-socket.patch new file mode 100644 index 0000000..230ccd0 --- /dev/null +++ b/patches/06-revert-purple-socket.patch @@ -0,0 +1,637 @@ +diff --git a/libpurple/purple-socket.c b/libpurple/purple-socket.c +new file mode 100644 +--- /dev/null ++++ b/libpurple/purple-socket.c +@@ -0,0 +1,410 @@ ++/* purple ++ * ++ * Purple is the legal property of its developers, whose names are too numerous ++ * to list here. Please refer to the COPYRIGHT file distributed with this ++ * source distribution. ++ * ++ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA ++ */ ++ ++#include "purple-socket.h" ++ ++#include "internal.h" ++ ++#include "debug.h" ++#include "proxy.h" ++#include "sslconn.h" ++ ++typedef enum { ++ PURPLE_SOCKET_STATE_DISCONNECTED = 0, ++ PURPLE_SOCKET_STATE_CONNECTING, ++ PURPLE_SOCKET_STATE_CONNECTED, ++ PURPLE_SOCKET_STATE_ERROR ++} PurpleSocketState; ++ ++struct _PurpleSocket ++{ ++ PurpleConnection *gc; ++ gchar *host; ++ int port; ++ gboolean is_tls; ++ GHashTable *data; ++ ++ PurpleSocketState state; ++ ++ PurpleSslConnection *tls_connection; ++ PurpleProxyConnectData *raw_connection; ++ int fd; ++ guint inpa; ++ ++ PurpleSocketConnectCb cb; ++ gpointer cb_data; ++}; ++ ++static GHashTable *handles = NULL; ++ ++static void ++handle_add(PurpleSocket *ps) ++{ ++ PurpleConnection *gc = ps->gc; ++ GSList *l; ++ ++ l = g_hash_table_lookup(handles, gc); ++ l = g_slist_prepend(l, ps); ++ g_hash_table_insert(handles, gc, l); ++} ++ ++static void ++handle_remove(PurpleSocket *ps) ++{ ++ PurpleConnection *gc = ps->gc; ++ GSList *l; ++ ++ l = g_hash_table_lookup(handles, gc); ++ l = g_slist_remove(l, ps); ++ g_hash_table_insert(handles, gc, l); ++} ++ ++void ++_purple_socket_init(void) ++{ ++ handles = g_hash_table_new(g_direct_hash, g_direct_equal); ++} ++ ++void ++_purple_socket_uninit(void) ++{ ++ g_hash_table_destroy(handles); ++ handles = NULL; ++} ++ ++PurpleSocket * ++purple_socket_new(PurpleConnection *gc) ++{ ++ PurpleSocket *ps = g_new0(PurpleSocket, 1); ++ ++ ps->gc = gc; ++ ps->fd = -1; ++ ps->port = -1; ++ ps->data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); ++ ++ handle_add(ps); ++ ++ return ps; ++} ++ ++PurpleConnection * ++purple_socket_get_connection(PurpleSocket *ps) ++{ ++ g_return_val_if_fail(ps != NULL, NULL); ++ ++ return ps->gc; ++} ++ ++static gboolean ++purple_socket_check_state(PurpleSocket *ps, PurpleSocketState wanted_state) ++{ ++ g_return_val_if_fail(ps != NULL, FALSE); ++ ++ if (ps->state == wanted_state) ++ return TRUE; ++ ++ purple_debug_error("socket", "invalid state: %d (should be: %d)", ++ ps->state, wanted_state); ++ ps->state = PURPLE_SOCKET_STATE_ERROR; ++ return FALSE; ++} ++ ++void ++purple_socket_set_tls(PurpleSocket *ps, gboolean is_tls) ++{ ++ g_return_if_fail(ps != NULL); ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED)) ++ return; ++ ++ ps->is_tls = is_tls; ++} ++ ++void ++purple_socket_set_host(PurpleSocket *ps, const gchar *host) ++{ ++ g_return_if_fail(ps != NULL); ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED)) ++ return; ++ ++ g_free(ps->host); ++ ps->host = g_strdup(host); ++} ++ ++void ++purple_socket_set_port(PurpleSocket *ps, int port) ++{ ++ g_return_if_fail(ps != NULL); ++ g_return_if_fail(port >= 0); ++ g_return_if_fail(port <= 65535); ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED)) ++ return; ++ ++ ps->port = port; ++} ++ ++static void ++_purple_socket_connected_raw(gpointer _ps, gint fd, const gchar *error_message) ++{ ++ PurpleSocket *ps = _ps; ++ ++ ps->raw_connection = NULL; ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTING)) { ++ if (fd > 0) ++ close(fd); ++ ps->cb(ps, _("Invalid socket state"), ps->cb_data); ++ return; ++ } ++ ++ if (fd <= 0 || error_message != NULL) { ++ if (error_message == NULL) ++ error_message = _("Unknown error"); ++ ps->fd = -1; ++ ps->state = PURPLE_SOCKET_STATE_ERROR; ++ ps->cb(ps, error_message, ps->cb_data); ++ return; ++ } ++ ++ ps->state = PURPLE_SOCKET_STATE_CONNECTED; ++ ps->fd = fd; ++ ps->cb(ps, NULL, ps->cb_data); ++} ++ ++static void ++_purple_socket_connected_tls(gpointer _ps, PurpleSslConnection *tls_connection, ++ PurpleInputCondition cond) ++{ ++ PurpleSocket *ps = _ps; ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTING)) { ++ purple_ssl_close(tls_connection); ++ ps->tls_connection = NULL; ++ ps->cb(ps, _("Invalid socket state"), ps->cb_data); ++ return; ++ } ++ ++ if (ps->tls_connection->fd <= 0) { ++ ps->state = PURPLE_SOCKET_STATE_ERROR; ++ purple_ssl_close(tls_connection); ++ ps->tls_connection = NULL; ++ ps->cb(ps, _("Invalid file descriptor"), ps->cb_data); ++ return; ++ } ++ ++ ps->state = PURPLE_SOCKET_STATE_CONNECTED; ++ ps->fd = ps->tls_connection->fd; ++ ps->cb(ps, NULL, ps->cb_data); ++} ++ ++static void ++_purple_socket_connected_tls_error(PurpleSslConnection *ssl_connection, ++ PurpleSslErrorType error, gpointer _ps) ++{ ++ PurpleSocket *ps = _ps; ++ ++ ps->state = PURPLE_SOCKET_STATE_ERROR; ++ ps->tls_connection = NULL; ++ ps->cb(ps, purple_ssl_strerror(error), ps->cb_data); ++} ++ ++gboolean ++purple_socket_connect(PurpleSocket *ps, PurpleSocketConnectCb cb, ++ gpointer user_data) ++{ ++ PurpleAccount *account = NULL; ++ ++ g_return_val_if_fail(ps != NULL, FALSE); ++ ++ if (ps->gc && purple_connection_is_disconnecting(ps->gc)) { ++ purple_debug_error("socket", "connection is being destroyed"); ++ ps->state = PURPLE_SOCKET_STATE_ERROR; ++ return FALSE; ++ } ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED)) ++ return FALSE; ++ ps->state = PURPLE_SOCKET_STATE_CONNECTING; ++ ++ if (ps->host == NULL || ps->port < 0) { ++ purple_debug_error("socket", "Host or port is not specified"); ++ ps->state = PURPLE_SOCKET_STATE_ERROR; ++ return FALSE; ++ } ++ ++ if (ps->gc != NULL) ++ account = purple_connection_get_account(ps->gc); ++ ++ ps->cb = cb; ++ ps->cb_data = user_data; ++ ++ if (ps->is_tls) { ++ ps->tls_connection = purple_ssl_connect(account, ps->host, ++ ps->port, _purple_socket_connected_tls, ++ _purple_socket_connected_tls_error, ps); ++ } else { ++ ps->raw_connection = purple_proxy_connect(ps->gc, account, ++ ps->host, ps->port, _purple_socket_connected_raw, ps); ++ } ++ ++ if (ps->tls_connection == NULL && ++ ps->raw_connection == NULL) ++ { ++ ps->state = PURPLE_SOCKET_STATE_ERROR; ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++gssize ++purple_socket_read(PurpleSocket *ps, guchar *buf, size_t len) ++{ ++ g_return_val_if_fail(ps != NULL, -1); ++ g_return_val_if_fail(buf != NULL, -1); ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED)) ++ return -1; ++ ++ if (ps->is_tls) ++ return purple_ssl_read(ps->tls_connection, buf, len); ++ else ++ return read(ps->fd, buf, len); ++} ++ ++gssize ++purple_socket_write(PurpleSocket *ps, const guchar *buf, size_t len) ++{ ++ g_return_val_if_fail(ps != NULL, -1); ++ g_return_val_if_fail(buf != NULL, -1); ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED)) ++ return -1; ++ ++ if (ps->is_tls) ++ return purple_ssl_write(ps->tls_connection, buf, len); ++ else ++ return write(ps->fd, buf, len); ++} ++ ++void ++purple_socket_watch(PurpleSocket *ps, PurpleInputCondition cond, ++ PurpleInputFunction func, gpointer user_data) ++{ ++ g_return_if_fail(ps != NULL); ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED)) ++ return; ++ ++ if (ps->inpa > 0) ++ purple_input_remove(ps->inpa); ++ ps->inpa = 0; ++ ++ g_return_if_fail(ps->fd > 0); ++ ++ if (func != NULL) ++ ps->inpa = purple_input_add(ps->fd, cond, func, user_data); ++} ++ ++int ++purple_socket_get_fd(PurpleSocket *ps) ++{ ++ g_return_val_if_fail(ps != NULL, -1); ++ ++ if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED)) ++ return -1; ++ ++ g_return_val_if_fail(ps->fd > 0, -1); ++ ++ return ps->fd; ++} ++ ++void ++purple_socket_set_data(PurpleSocket *ps, const gchar *key, gpointer data) ++{ ++ g_return_if_fail(ps != NULL); ++ g_return_if_fail(key != NULL); ++ ++ if (data == NULL) ++ g_hash_table_remove(ps->data, key); ++ else ++ g_hash_table_insert(ps->data, g_strdup(key), data); ++} ++ ++gpointer ++purple_socket_get_data(PurpleSocket *ps, const gchar *key) ++{ ++ g_return_val_if_fail(ps != NULL, NULL); ++ g_return_val_if_fail(key != NULL, NULL); ++ ++ return g_hash_table_lookup(ps->data, key); ++} ++ ++static void ++purple_socket_cancel(PurpleSocket *ps) ++{ ++ if (ps->inpa > 0) ++ purple_input_remove(ps->inpa); ++ ps->inpa = 0; ++ ++ if (ps->tls_connection != NULL) { ++ purple_ssl_close(ps->tls_connection); ++ ps->fd = -1; ++ } ++ ps->tls_connection = NULL; ++ ++ if (ps->raw_connection != NULL) ++ purple_proxy_connect_cancel(ps->raw_connection); ++ ps->raw_connection = NULL; ++ ++ if (ps->fd > 0) ++ close(ps->fd); ++ ps->fd = 0; ++} ++ ++void ++purple_socket_destroy(PurpleSocket *ps) ++{ ++ if (ps == NULL) ++ return; ++ ++ handle_remove(ps); ++ ++ purple_socket_cancel(ps); ++ ++ g_free(ps->host); ++ g_hash_table_destroy(ps->data); ++ g_free(ps); ++} ++ ++void ++_purple_socket_cancel_with_connection(PurpleConnection *gc) ++{ ++ GSList *it; ++ ++ it = g_hash_table_lookup(handles, gc); ++ for (; it; it = g_slist_next(it)) { ++ PurpleSocket *ps = it->data; ++ purple_socket_cancel(ps); ++ } ++} +diff --git a/libpurple/purple-socket.h b/libpurple/purple-socket.h +new file mode 100644 +--- /dev/null ++++ b/libpurple/purple-socket.h +@@ -0,0 +1,217 @@ ++/* purple ++ * ++ * Purple is the legal property of its developers, whose names are too numerous ++ * to list here. Please refer to the COPYRIGHT file distributed with this ++ * source distribution. ++ * ++ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA ++ */ ++ ++#ifndef _PURPLE_SOCKET_H_ ++#define _PURPLE_SOCKET_H_ ++/** ++ * SECTION:purple-socket ++ * @section_id: libpurple-purple-socket ++ * @short_description: <filename>purple-socket.h</filename> ++ * @title: Generic Sockets ++ */ ++ ++#include "connection.h" ++ ++/** ++ * PurpleSocket: ++ * ++ * A structure holding all resources needed for the TCP connection. ++ */ ++typedef struct _PurpleSocket PurpleSocket; ++ ++/** ++ * PurpleSocketConnectCb: ++ * @ps: The socket. ++ * @error: Error message, or NULL if connection was successful. ++ * @user_data: The user data passed with callback function. ++ * ++ * A callback fired after (successfully or not) establishing a connection. ++ */ ++typedef void (*PurpleSocketConnectCb)(PurpleSocket *ps, const gchar *error, ++ gpointer user_data); ++ ++/** ++ * purple_socket_new: ++ * @gc: The connection for which the socket is needed, or NULL. ++ * ++ * Creates new, disconnected socket. ++ * ++ * Passing a PurpleConnection allows for proper proxy handling. ++ * ++ * Returns: The new socket struct. ++ */ ++PurpleSocket * ++purple_socket_new(PurpleConnection *gc); ++ ++/** ++ * purple_socket_get_connection: ++ * @ps: The socket. ++ * ++ * Gets PurpleConnection tied with specified socket. ++ * ++ * Returns: The PurpleConnection object. ++ */ ++PurpleConnection * ++purple_socket_get_connection(PurpleSocket *ps); ++ ++/** ++ * purple_socket_set_tls: ++ * @ps: The socket. ++ * @is_tls: TRUE, if TLS should be handled transparently, FALSE otherwise. ++ * ++ * Determines, if socket should handle TLS. ++ */ ++void ++purple_socket_set_tls(PurpleSocket *ps, gboolean is_tls); ++ ++/** ++ * purple_socket_set_host: ++ * @ps: The socket. ++ * @host: The connection host. ++ * ++ * Sets connection host. ++ */ ++void ++purple_socket_set_host(PurpleSocket *ps, const gchar *host); ++ ++/** ++ * purple_socket_set_port: ++ * @ps: The socket. ++ * @port: The connection port. ++ * ++ * Sets connection port. ++ */ ++void ++purple_socket_set_port(PurpleSocket *ps, int port); ++ ++/** ++ * purple_socket_connect: ++ * @ps: The socket. ++ * @cb: The function to call after establishing a connection, or on ++ * error. ++ * @user_data: The user data to be passed to callback function. ++ * ++ * Establishes a connection. ++ * ++ * Returns: TRUE on success (this doesn't mean it's connected yet), FALSE ++ * otherwise. ++ */ ++gboolean ++purple_socket_connect(PurpleSocket *ps, PurpleSocketConnectCb cb, ++ gpointer user_data); ++ ++/** ++ * purple_socket_read: ++ * @ps: The socket. ++ * @buf: The buffer to write data to. ++ * @len: The buffer size. ++ * ++ * Reads incoming data from socket. ++ * ++ * This function deals with TLS, if the socket is configured to do it. ++ * ++ * Returns: Amount of data written, or -1 on error (errno will be also be set). ++ */ ++gssize ++purple_socket_read(PurpleSocket *ps, guchar *buf, size_t len); ++ ++/** ++ * purple_socket_write: ++ * @ps: The socket. ++ * @buf: The buffer to read data from. ++ * @len: The amount of data to read and send. ++ * ++ * Sends data through socket. ++ * ++ * This function deals with TLS, if the socket is configured to do it. ++ * ++ * Returns: Amount of data sent, or -1 on error (errno will albo be set). ++ */ ++gssize ++purple_socket_write(PurpleSocket *ps, const guchar *buf, size_t len); ++ ++/** ++ * purple_socket_watch: ++ * @ps: The socket. ++ * @cond: The condition type. ++ * @func: The callback function for data, or NULL to remove any ++ * existing callbacks. ++ * @user_data: The user data to be passed to callback function. ++ * ++ * Adds an input handler for the socket. ++ * ++ * If the specified socket had input handler already registered, it will be ++ * removed. To remove any input handlers, pass an NULL handler function. ++ */ ++void ++purple_socket_watch(PurpleSocket *ps, PurpleInputCondition cond, ++ PurpleInputFunction func, gpointer user_data); ++ ++/** ++ * purple_socket_get_fd: ++ * @ps: The socket ++ * ++ * Gets underlying file descriptor for socket. ++ * ++ * It's not meant to read/write data (use purple_socket_read/ ++ * purple_socket_write), rather for watching for changes with select(). ++ * ++ * Returns: The file descriptor, or -1 on error. ++ */ ++int ++purple_socket_get_fd(PurpleSocket *ps); ++ ++/** ++ * purple_socket_set_data: ++ * @ps: The socket. ++ * @key: The unique key. ++ * @data: The data to assign, or NULL to remove. ++ * ++ * Sets extra data for a socket. ++ */ ++void ++purple_socket_set_data(PurpleSocket *ps, const gchar *key, gpointer data); ++ ++/** ++ * purple_socket_get_data: ++ * @ps: The socket. ++ * @key: The unqiue key. ++ * ++ * Returns extra data in a socket. ++ * ++ * Returns: The data associated with the key. ++ */ ++gpointer ++purple_socket_get_data(PurpleSocket *ps, const gchar *key); ++ ++/** ++ * purple_socket_destroy: ++ * @ps: The socket. ++ * ++ * Destroys the socket, closes connection and frees all resources. ++ * ++ * If file descriptor for the socket was extracted with purple_socket_get_fd and ++ * added to event loop, it have to be removed prior this. ++ */ ++void ++purple_socket_destroy(PurpleSocket *ps); ++ ++#endif /* _PURPLE_SOCKET_H_ */ |