/cpw/tomkiewicz/http: 013c5aebb665: Let's connect
Tomasz Wasilczyk
tomkiewicz at cpw.pidgin.im
Fri Oct 12 22:14:01 EDT 2012
Changeset: 013c5aebb665e0c3c159b9f6c4b59142907e310e
Author: Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date: 2012-10-13 04:13 +0200
Branch: default
URL: http://hg.pidgin.im/cpw/tomkiewicz/http/rev/013c5aebb665
Description:
Let's connect
diffstat:
libpurple/http.c | 228 ++++++++++++++++++++++++++++++++++++++++---
libpurple/http.h | 14 +-
libpurple/protocols/gg/gg.c | 6 +-
3 files changed, 227 insertions(+), 21 deletions(-)
diffs (truncated from 381 to 300 lines):
diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -31,6 +31,18 @@
typedef struct _PurpleHttpURL PurpleHttpURL;
+typedef struct _PurpleHttpSocket PurpleHttpSocket;
+
+struct _PurpleHttpSocket
+{
+ gboolean is_connected;
+ gboolean is_ssl;
+ PurpleSslConnection *ssl_connection;
+ PurpleProxyConnectData *raw_connection;
+ int fd;
+ guint inpa;
+};
+
struct _PurpleHttpRequest
{
int ref_count;
@@ -47,11 +59,14 @@ struct _PurpleHttpConnection
PurpleHttpURL *url;
PurpleHttpRequest *request;
PurpleHttpResponse *response;
+
+ PurpleHttpSocket socket;
};
struct _PurpleHttpResponse
{
int code;
+ gchar *error;
gchar *data;
gsize data_len;
@@ -79,6 +94,178 @@ static void purple_http_url_free(PurpleH
static const gchar * purple_http_url_debug(PurpleHttpURL *parsed_url);
+/*** HTTP protocol backend ****************************************************/
+
+static void purple_http_dummy_success(PurpleHttpConnection *hc)
+{
+ PurpleHttpResponse *response = hc->response;
+
+ response->code = 200;
+ response->data = g_strdup(purple_http_url_debug(hc->url));
+ response->data_len = strlen(response->data);
+
+ purple_http_conn_cancel(hc);
+}
+
+static void _purple_http_disconnect(PurpleHttpConnection *hc);
+
+static void _purple_http_send(gpointer _hc, gint fd, PurpleInputCondition cond);
+
+static void _purple_http_connected_raw(gpointer _hc, gint source,
+ const gchar *error_message);
+static void _purple_http_connected_ssl(gpointer _hc,
+ PurpleSslConnection *ssl_connection, PurpleInputCondition cond);
+static void _purple_http_connected_ssl_error(
+ PurpleSslConnection *ssl_connection, PurpleSslErrorType error,
+ gpointer _hc);
+
+/* closes current connection (if exists), estabilishes one and proceeds with
+ * request */
+static gboolean _purple_http_reconnect(PurpleHttpConnection *hc);
+
+static void _purple_http_error(PurpleHttpConnection *hc, const char *format,
+ ...) G_GNUC_PRINTF(2, 3);
+
+static void _purple_http_error(PurpleHttpConnection *hc, const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ hc->response->error = g_strdup_vprintf(format, args);
+ va_end(args);
+
+ purple_http_conn_cancel(hc);
+}
+
+static void _purple_http_send(gpointer _hc, gint fd, PurpleInputCondition cond)
+{ // url_fetch_send_cb
+ PurpleHttpConnection *hc = _hc;
+
+ purple_debug_misc("http", "[tmp] sending...\n");
+
+ purple_http_dummy_success(hc);
+}
+
+static void _purple_http_connected_raw(gpointer _hc, gint fd,
+ const gchar *error_message)
+{
+ PurpleHttpConnection *hc = _hc;
+ PurpleHttpSocket *hs = &hc->socket;
+
+ hs->raw_connection = NULL;
+
+ if (fd == -1) {
+ _purple_http_error(hc, _("Unable to connect to %s: %s"),
+ hc->url->host, error_message);
+ return;
+ }
+
+ hs->fd = fd;
+ hs->inpa = purple_input_add(fd, PURPLE_INPUT_WRITE,
+ _purple_http_send, hc);
+ _purple_http_send(hc, fd, PURPLE_INPUT_WRITE);
+}
+
+static void _purple_http_connected_ssl(gpointer _hc,
+ PurpleSslConnection *ssl_connection, PurpleInputCondition cond)
+{
+ PurpleHttpConnection *hc = _hc;
+ PurpleHttpSocket *hs = &hc->socket;
+
+ hs->fd = hs->ssl_connection->fd;
+ hs->inpa = purple_input_add(hs->fd, PURPLE_INPUT_WRITE,
+ _purple_http_send, hc);
+ _purple_http_send(hc, hs->fd, PURPLE_INPUT_WRITE);
+}
+
+static void _purple_http_connected_ssl_error(
+ PurpleSslConnection *ssl_connection, PurpleSslErrorType error,
+ gpointer _hc)
+{
+ PurpleHttpConnection *hc = _hc;
+ PurpleHttpSocket *hs = &hc->socket;
+
+ hs->ssl_connection = NULL;
+ _purple_http_error(hc, _("Unable to connect to %s: %s"),
+ hc->url->host, purple_ssl_strerror(error));
+}
+
+static void _purple_http_disconnect(PurpleHttpConnection *hc)
+{
+ PurpleHttpSocket *hs;
+
+ g_return_if_fail(hc != NULL);
+
+ hs = &hc->socket;
+
+ if (!hs->is_connected)
+ return;
+
+ if (hs->inpa != 0)
+ purple_input_remove(hs->inpa);
+
+ if (hs->is_ssl) {
+ if (hs->ssl_connection != NULL)
+ purple_ssl_close(hs->ssl_connection);
+ } else {
+ if (hs->raw_connection != NULL)
+ purple_proxy_connect_cancel(hs->raw_connection);
+ if (hs->fd > 0)
+ close(hs->fd);
+ }
+
+ memset(hs, 0, sizeof(PurpleHttpSocket));
+}
+
+static gboolean _purple_http_reconnect(PurpleHttpConnection *hc)
+{
+ PurpleHttpURL *url;
+ gboolean is_ssl = FALSE;
+ PurpleAccount *account = NULL;
+
+ g_return_val_if_fail(hc != NULL, FALSE);
+ g_return_val_if_fail(hc->url != NULL, FALSE);
+
+ _purple_http_disconnect(hc);
+
+ if (hc->gc)
+ account = purple_connection_get_account(hc->gc);
+
+ url = hc->url;
+ if (url->protocol[0] == '\0' ||
+ g_ascii_strcasecmp(url->protocol, "http") == 0) {
+ /* do nothing */
+ } else if (g_ascii_strcasecmp(url->protocol, "https") == 0) {
+ is_ssl = TRUE;
+ } else {
+ _purple_http_error(hc, _("Unsupported protocol: %s"),
+ url->protocol);
+ return FALSE;
+ }
+
+ hc->socket.is_ssl = is_ssl;
+ if (is_ssl) {
+ hc->socket.ssl_connection = purple_ssl_connect(account,
+ url->host, url->port,
+ _purple_http_connected_ssl,
+ _purple_http_connected_ssl_error, hc);
+ } else {
+ hc->socket.raw_connection = purple_proxy_connect(hc->gc, account,
+ url->host, url->port,
+ _purple_http_connected_raw, hc);
+ }
+
+ if (hc->socket.ssl_connection == NULL &&
+ hc->socket.raw_connection == NULL) {
+ _purple_http_error(hc, _("Unable to connect to %s"), url->host);
+ return FALSE;
+ }
+ hc->socket.is_connected = TRUE;
+
+ return TRUE;
+}
+
/*** Performing HTTP requests *************************************************/
PurpleHttpConnection * purple_http_get(PurpleConnection *gc, const gchar *url,
@@ -96,20 +283,6 @@ PurpleHttpConnection * purple_http_get(P
return hc;
}
-static gboolean purple_http_request_dummy_timeout(gpointer user_data)
-{
- PurpleHttpConnection *hc = user_data;
- PurpleHttpResponse *response = hc->response;
-
- response->code = 200;
- response->data = g_strdup(purple_http_url_debug(hc->url));
- response->data_len = strlen(response->data);
-
- purple_http_connection_terminate(hc);
-
- return FALSE;
-}
-
PurpleHttpConnection * purple_http_request(PurpleConnection *gc,
PurpleHttpRequest *request, PurpleHttpCallback callback,
gpointer user_data)
@@ -130,13 +303,15 @@ PurpleHttpConnection * purple_http_reque
purple_debug_misc("http", "Performing new request %p.\n", hc);
hc->url = purple_http_url_parse(request->url);
- if (!hc->url) {
+ if (!hc->url || hc->url->host[0] == '\0') {
purple_debug_error("http", "Invalid URL requested.\n");
purple_http_connection_terminate(hc);
return NULL;
}
- purple_timeout_add_seconds(1, purple_http_request_dummy_timeout, hc);
+ _purple_http_reconnect(hc);
+
+ /* TODO: timeout */
return hc;
}
@@ -161,6 +336,10 @@ static void purple_http_connection_free(
purple_http_url_free(hc->url);
purple_http_request_unref(hc->request);
purple_http_response_free(hc->response);
+
+ if (hc->socket.is_connected)
+ purple_debug_error("http", "Socket is still connected!");
+
g_free(hc);
}
@@ -179,6 +358,13 @@ static void purple_http_connection_termi
purple_http_connection_free(hc);
}
+void purple_http_conn_cancel(PurpleHttpConnection *http_conn)
+{
+ http_conn->response->code = 0;
+ _purple_http_disconnect(http_conn);
+ purple_http_connection_terminate(http_conn);
+}
+
void purple_http_conn_cancel_all(PurpleConnection *gc)
{
purple_debug_warning("http", "purple_http_conn_cancel_all: To be implemented\n");
@@ -241,6 +427,7 @@ static PurpleHttpResponse * purple_http_
static void purple_http_response_free(PurpleHttpResponse *response)
{
+ g_free(response->error);
g_free(response);
}
@@ -258,6 +445,13 @@ int purple_http_response_get_code(Purple
return response->code;
}
+const gchar * purple_http_response_get_error(PurpleHttpResponse *response)
+{
+ g_return_val_if_fail(response != NULL, NULL);
+
+ return response->error;
+}
+
gsize purple_http_response_get_data_len(PurpleHttpResponse *response)
More information about the Commits
mailing list