/pidgin/main: 8df870b218ca: HTTP: chop off another HTTP implemen...
Tomasz Wasilczyk
tomkiewicz at cpw.pidgin.im
Mon Aug 5 09:47:45 EDT 2013
Changeset: 8df870b218ca1128c099f15494ba56d57ef473a1
Author: Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date: 2013-08-05 15:47 +0200
Branch: default
URL: https://hg.pidgin.im/pidgin/main/rev/8df870b218ca
Description:
HTTP: chop off another HTTP implementation (for xmpp oob file transfers)
diffstat:
libpurple/ft.c | 47 ++++++-
libpurple/ft.h | 12 ++
libpurple/http.c | 9 +-
libpurple/http.h | 4 +-
libpurple/protocols/jabber/oob.c | 215 +++++++++++++++-----------------------
5 files changed, 148 insertions(+), 139 deletions(-)
diffs (truncated from 417 to 300 lines):
diff --git a/libpurple/ft.c b/libpurple/ft.c
--- a/libpurple/ft.c
+++ b/libpurple/ft.c
@@ -1144,6 +1144,43 @@ purple_xfer_write(PurpleXfer *xfer, cons
return r;
}
+gboolean
+purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size)
+{
+ PurpleXferUiOps *ui_ops;
+ gsize wc;
+ gboolean fs_known;
+
+ g_return_val_if_fail(xfer != NULL, FALSE);
+ g_return_val_if_fail(buffer != NULL, FALSE);
+
+ ui_ops = purple_xfer_get_ui_ops(xfer);
+ fs_known = (purple_xfer_get_size(xfer) > 0);
+
+ if (fs_known && size > purple_xfer_get_bytes_remaining(xfer)) {
+ purple_debug_warning("filetransfer",
+ "Got too much data (truncating).\n");
+ size = purple_xfer_get_bytes_remaining(xfer);
+ }
+
+ if (ui_ops && ui_ops->ui_write)
+ wc = ui_ops->ui_write(xfer, buffer, size);
+ else
+ wc = fwrite(buffer, 1, size, xfer->dest_fp);
+
+ if (wc != size) {
+ purple_debug_error("filetransfer",
+ "Unable to write whole buffer.\n");
+ purple_xfer_cancel_local(xfer);
+ return FALSE;
+ }
+
+ purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) +
+ size);
+
+ return TRUE;
+}
+
static void
do_transfer(PurpleXfer *xfer)
{
@@ -1156,15 +1193,7 @@ do_transfer(PurpleXfer *xfer)
if (xfer->type == PURPLE_XFER_RECEIVE) {
r = purple_xfer_read(xfer, &buffer);
if (r > 0) {
- size_t wc;
- if (ui_ops && ui_ops->ui_write)
- wc = ui_ops->ui_write(xfer, buffer, r);
- else
- wc = fwrite(buffer, 1, r, xfer->dest_fp);
-
- if (wc != r) {
- purple_debug_error("filetransfer", "Unable to write whole buffer.\n");
- purple_xfer_cancel_local(xfer);
+ if (!purple_xfer_write_file(xfer, buffer, r)) {
g_free(buffer);
return;
}
diff --git a/libpurple/ft.h b/libpurple/ft.h
--- a/libpurple/ft.h
+++ b/libpurple/ft.h
@@ -629,6 +629,18 @@ gssize purple_xfer_read(PurpleXfer *xfer
gssize purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size);
/**
+ * Writes chunk of received file.
+ *
+ * @param xfer The file transfer.
+ * @param buffer The buffer to read the data from.
+ * @param size The number of bytes to write.
+ *
+ * @return TRUE on success, FALSE otherwise.
+ */
+gboolean
+purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size);
+
+/**
* Starts a file transfer.
*
* Either @a fd must be specified <i>or</i> @a ip and @a port on a
diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -40,6 +40,8 @@
#define PURPLE_HTTP_REQUEST_DEFAULT_TIMEOUT 30
#define PURPLE_HTTP_REQUEST_DEFAULT_MAX_LENGTH 1048576
+#define PURPLE_HTTP_PROGRESS_WATCHER_DEFAULT_INTERVAL 250000
+
typedef struct _PurpleHttpSocket PurpleHttpSocket;
typedef struct _PurpleHttpHeaders PurpleHttpHeaders;
@@ -1722,10 +1724,15 @@ PurpleConnection * purple_http_conn_get_
void purple_http_conn_set_progress_watcher(PurpleHttpConnection *http_conn,
PurpleHttpProgressWatcher watcher, gpointer user_data,
- guint interval_threshold)
+ gint interval_threshold)
{
g_return_if_fail(http_conn != NULL);
+ if (interval_threshold < 0) {
+ interval_threshold =
+ PURPLE_HTTP_PROGRESS_WATCHER_DEFAULT_INTERVAL;
+ }
+
http_conn->watcher = watcher;
http_conn->watcher_user_data = user_data;
http_conn->watcher_interval_threshold = interval_threshold;
diff --git a/libpurple/http.h b/libpurple/http.h
--- a/libpurple/http.h
+++ b/libpurple/http.h
@@ -235,11 +235,11 @@ PurpleConnection * purple_http_conn_get_
* @param watcher The watcher.
* @param user_data The user data to pass to the callback function.
* @param interval_threshold Minimum interval (in microseconds) of calls to
- * watcher.
+ * watcher, or -1 for default.
*/
void purple_http_conn_set_progress_watcher(PurpleHttpConnection *http_conn,
PurpleHttpProgressWatcher watcher, gpointer user_data,
- guint interval_threshold);
+ gint interval_threshold);
/*@}*/
diff --git a/libpurple/protocols/jabber/oob.c b/libpurple/protocols/jabber/oob.c
--- a/libpurple/protocols/jabber/oob.c
+++ b/libpurple/protocols/jabber/oob.c
@@ -31,44 +31,28 @@
#include "oob.h"
typedef struct _JabberOOBXfer {
- char *address;
- int port;
- char *page;
-
- GString *headers;
-
- char *iq_id;
-
JabberStream *js;
-
- gchar *write_buffer;
- gsize written_len;
- guint writeh;
-
+ gchar *iq_id;
+ gchar *url;
+ PurpleHttpConnection *hc;
} JabberOOBXfer;
static void jabber_oob_xfer_init(PurpleXfer *xfer)
{
- JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
- purple_xfer_start(xfer, -1, jox->address, jox->port);
+ purple_xfer_start(xfer, -1, NULL, 0);
}
static void jabber_oob_xfer_free(PurpleXfer *xfer)
{
JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
+
+ purple_xfer_set_protocol_data(xfer, NULL);
jox->js->oob_file_transfers = g_list_remove(jox->js->oob_file_transfers,
xfer);
- g_string_free(jox->headers, TRUE);
- g_free(jox->address);
- g_free(jox->page);
g_free(jox->iq_id);
- g_free(jox->write_buffer);
- if(jox->writeh)
- purple_input_remove(jox->writeh);
+ g_free(jox->url);
g_free(jox);
-
- purple_xfer_set_protocol_data(xfer, NULL);
}
static void jabber_oob_xfer_end(PurpleXfer *xfer)
@@ -85,82 +69,67 @@ static void jabber_oob_xfer_end(PurpleXf
jabber_oob_xfer_free(xfer);
}
-static void jabber_oob_xfer_request_send(gpointer data, gint source, PurpleInputCondition cond) {
- PurpleXfer *xfer = data;
- JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
- int len, total_len = strlen(jox->write_buffer);
+static void
+jabber_oob_xfer_got(PurpleHttpConnection *hc, PurpleHttpResponse *response,
+ gpointer _xfer)
+{
+ PurpleXfer *xfer = _xfer;
+ JabberOOBXfer *jox;
- len = purple_xfer_write(xfer, (guchar*) jox->write_buffer + jox->written_len,
- total_len - jox->written_len);
+ if (purple_xfer_is_cancelled(xfer))
+ return;
- if(len < 0 && errno == EAGAIN)
+ jox = purple_xfer_get_protocol_data(xfer);
+ jox->hc = NULL;
+
+ if (!purple_http_response_is_successfull(response) ||
+ purple_xfer_get_bytes_remaining(xfer) > 0)
+ {
+ purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
+ purple_xfer_end(xfer);
+ } else {
+ purple_xfer_set_completed(xfer, TRUE);
+ purple_xfer_end(xfer);
+ }
+}
+
+static void
+jabber_oob_xfer_progress_watcher(PurpleHttpConnection *hc,
+ gboolean reading_state, int processed, int total, gpointer _xfer)
+{
+ PurpleXfer *xfer = _xfer;
+
+ if (!reading_state)
return;
- else if(len < 0) {
- purple_debug_error("jabber", "Write error on oob xfer!\n");
- purple_input_remove(jox->writeh);
- purple_xfer_cancel_local(xfer);
- }
- jox->written_len += len;
- if(jox->written_len == total_len) {
- purple_input_remove(jox->writeh);
- g_free(jox->write_buffer);
- jox->write_buffer = NULL;
- }
+ purple_xfer_set_size(xfer, total);
+ purple_xfer_update_progress(xfer);
+}
+
+static gboolean
+jabber_oob_xfer_writer(PurpleHttpConnection *http_conn,
+ PurpleHttpResponse *response, const gchar *buffer, size_t offset,
+ size_t length, gpointer _xfer)
+{
+ PurpleXfer *xfer = _xfer;
+
+ return purple_xfer_write_file(xfer, (const guchar*)buffer, length);
}
static void jabber_oob_xfer_start(PurpleXfer *xfer)
{
+ PurpleHttpRequest *req;
JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
- if(jox->write_buffer == NULL) {
- jox->write_buffer = g_strdup_printf(
- "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n",
- jox->page, jox->address);
- jox->written_len = 0;
- }
+ req = purple_http_request_new(jox->url);
+ purple_http_request_set_max_len(req, -1);
+ purple_http_request_set_response_writer(req, jabber_oob_xfer_writer,
+ xfer);
+ jox->hc = purple_http_request(jox->js->gc, req, jabber_oob_xfer_got,
+ xfer);
- jox->writeh = purple_input_add(purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE,
- jabber_oob_xfer_request_send, xfer);
-
- jabber_oob_xfer_request_send(xfer, purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE);
-}
-
-static gssize jabber_oob_xfer_read(guchar **buffer, PurpleXfer *xfer) {
- JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
- char test[2048];
- char *tmp, *lenstr;
- int len;
-
- if((len = read(purple_xfer_get_fd(xfer), test, sizeof(test))) > 0) {
- jox->headers = g_string_append_len(jox->headers, test, len);
- if((tmp = strstr(jox->headers->str, "\r\n\r\n"))) {
- *tmp = '\0';
- lenstr = strstr(jox->headers->str, "Content-Length: ");
- if(lenstr) {
- goffset size;
- if (sscanf(lenstr, "Content-Length: %" G_GOFFSET_FORMAT, &size) == 1)
- purple_xfer_set_size(xfer, size);
- else {
- purple_debug_error("jabber", "Unable to parse Content-Length!\n");
- purple_xfer_cancel_local(xfer);
- return 0;
- }
More information about the Commits
mailing list