pidgin: e6eebfe6: ft: Add infrastructure to allow a prpl t...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Wed Aug 12 00:37:18 EDT 2009
-----------------------------------------------------------------
Revision: e6eebfe6a1965a7729803ad45b5d9bf3f4ea4330
Ancestor: 9953e3b86db32def937899bca8dc07d159f11eae
Author: darkrain42 at pidgin.im
Date: 2009-08-12T04:31:17
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/e6eebfe6a1965a7729803ad45b5d9bf3f4ea4330
Modified files:
ChangeLog.API libpurple/ft.c libpurple/ft.h
ChangeLog:
ft: Add infrastructure to allow a prpl to moderate when to send packets.
The file transfer subsystem should now allow a prpl to serialize packets
(the way XMPP IBB does, where we wait for an ACK before sending the next
packet.) I think this will also be usable for msn and any other prpls
that currently try to open the local file manually.
-------------- next part --------------
============================================================
--- ChangeLog.API 078354f9aa830779e94166079a89db9e537815dc
+++ ChangeLog.API cf717ca4347c54f8e7960a8b203dc13e09373db3
@@ -68,6 +68,7 @@ version 2.6.0 (??/??/2009):
* purple_strequal
* purple_utf8_strip_unprintables
* purple_util_fetch_url_request_len_with_account
+ * purple_xfer_prpl_ready
* purple_xfer_ui_ready
* xmlnode_from_file
* xmlnode_get_parent
============================================================
--- libpurple/ft.c 48a79ff9dc60eff2e893ab7c1a21d0999afa5369
+++ libpurple/ft.c 3f729c170caca25e0b9284b474742fe30bf5c35b
@@ -40,8 +40,35 @@ static GList *xfers;
static PurpleXferUiOps *xfer_ui_ops = NULL;
static GList *xfers;
+/*
+ * A hack to store more data since we can't extend the size of PurpleXfer
+ * easily.
+ */
+static GHashTable *xfers_data = NULL;
+
+typedef struct _PurpleXferPrivData {
+ /*
+ * Used to moderate the file transfer when either the read/write ui_ops are
+ * set or fd is not set. In those cases, the UI/prpl call the respective
+ * function, which is somewhat akin to a fd watch being triggered.
+ */
+ enum {
+ PURPLE_XFER_READY_NONE = 0x0,
+ PURPLE_XFER_READY_UI = 0x1,
+ PURPLE_XFER_READY_PRPL = 0x2,
+ } ready;
+} PurpleXferPrivData;
+
static int purple_xfer_choose_file(PurpleXfer *xfer);
+static void
+purple_xfer_priv_data_destroy(gpointer data)
+{
+ PurpleXferPrivData *priv = data;
+
+ g_free(priv);
+}
+
GList *
purple_xfers_get_all()
{
@@ -53,6 +80,7 @@ purple_xfer_new(PurpleAccount *account,
{
PurpleXfer *xfer;
PurpleXferUiOps *ui_ops;
+ PurpleXferPrivData *priv;
g_return_val_if_fail(type != PURPLE_XFER_UNKNOWN, NULL);
g_return_val_if_fail(account != NULL, NULL);
@@ -70,6 +98,11 @@ purple_xfer_new(PurpleAccount *account,
xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE;
xfer->fd = -1;
+ priv = g_new0(PurpleXferPrivData, 1);
+ priv->ready = PURPLE_XFER_READY_NONE;
+
+ g_hash_table_insert(xfers_data, xfer, priv);
+
ui_ops = purple_xfer_get_ui_ops(xfer);
if (ui_ops != NULL && ui_ops->new_xfer != NULL)
@@ -102,9 +135,11 @@ purple_xfer_destroy(PurpleXfer *xfer)
g_free(xfer->remote_ip);
g_free(xfer->local_filename);
+ g_hash_table_remove(xfers_data, xfer);
+
PURPLE_DBUS_UNREGISTER_POINTER(xfer);
+ xfers = g_list_remove(xfers, xfer);
g_free(xfer);
- xfers = g_list_remove(xfers, xfer);
}
void
@@ -946,16 +981,15 @@ static void
}
static void
-transfer_cb(gpointer data, gint source, PurpleInputCondition condition)
+do_transfer(PurpleXfer *xfer)
{
PurpleXferUiOps *ui_ops;
- PurpleXfer *xfer = (PurpleXfer *)data;
guchar *buffer = NULL;
gssize r = 0;
ui_ops = purple_xfer_get_ui_ops(xfer);
-
- if (condition & PURPLE_INPUT_READ) {
+
+ if (xfer->type == PURPLE_XFER_RECEIVE) {
r = purple_xfer_read(xfer, &buffer);
if (r > 0) {
size_t wc;
@@ -975,7 +1009,7 @@ transfer_cb(gpointer data, gint source,
g_free(buffer);
return;
}
- } else if (condition & PURPLE_INPUT_WRITE) {
+ } else if (xfer->type == PURPLE_XFER_SEND) {
size_t result;
size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
@@ -1067,6 +1101,26 @@ static void
}
static void
+transfer_cb(gpointer data, gint source, PurpleInputCondition condition)
+{
+ PurpleXfer *xfer = data;
+
+ if (xfer->dest_fp == NULL) {
+ /* The UI is moderating its side manually */
+ PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
+ if (0 == (priv->ready & PURPLE_XFER_READY_UI)) {
+ priv->ready |= PURPLE_XFER_READY_PRPL;
+
+ purple_input_remove(xfer->watcher);
+ xfer->watcher = 0;
+ return;
+ }
+ }
+
+ do_transfer(xfer);
+}
+
+static void
begin_transfer(PurpleXfer *xfer, PurpleInputCondition cond)
{
PurpleXferType type = purple_xfer_get_type(xfer);
@@ -1114,9 +1168,16 @@ purple_xfer_ui_ready(PurpleXfer *xfer)
{
PurpleInputCondition cond;
PurpleXferType type;
+ PurpleXferPrivData *priv;
g_return_if_fail(xfer != NULL);
+ priv = g_hash_table_lookup(xfers_data, xfer);
+ priv->ready |= PURPLE_XFER_READY_UI;
+
+ if (0 == (priv->ready & PURPLE_XFER_READY_PRPL))
+ return;
+
type = purple_xfer_get_type(xfer);
if (type == PURPLE_XFER_SEND)
cond = PURPLE_INPUT_WRITE;
@@ -1126,10 +1187,31 @@ purple_xfer_ui_ready(PurpleXfer *xfer)
if (xfer->watcher == 0 && xfer->fd != -1)
xfer->watcher = purple_input_add(xfer->fd, cond, transfer_cb, xfer);
- transfer_cb(xfer, 0, cond);
+ priv->ready = PURPLE_XFER_READY_NONE;
+
+ do_transfer(xfer);
}
void
+purple_xfer_prpl_ready(PurpleXfer *xfer)
+{
+ PurpleXferPrivData *priv;
+
+ g_return_if_fail(xfer != NULL);
+
+ priv = g_hash_table_lookup(xfers_data, xfer);
+ priv->ready |= PURPLE_XFER_READY_PRPL;
+
+ /* I don't think fwrite/fread are ever *not* ready */
+ if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI))
+ return;
+
+ priv->ready = PURPLE_XFER_READY_NONE;
+
+ do_transfer(xfer);
+}
+
+void
purple_xfer_start(PurpleXfer *xfer, int fd, const char *ip,
unsigned int port)
{
@@ -1394,6 +1476,9 @@ purple_xfers_init(void) {
purple_xfers_init(void) {
void *handle = purple_xfers_get_handle();
+ xfers_data = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, purple_xfer_priv_data_destroy);
+
/* register signals */
purple_signal_register(handle, "file-recv-accept",
purple_marshal_VOID__POINTER, NULL, 1,
@@ -1440,6 +1525,9 @@ purple_xfers_uninit(void)
purple_signals_disconnect_by_handle(handle);
purple_signals_unregister_by_instance(handle);
+
+ g_hash_table_destroy(xfers_data);
+ xfers_data = NULL;
}
void
============================================================
--- libpurple/ft.h 6324b78c116985dc27147503d6d733e8423c53de
+++ libpurple/ft.h 8d4d3387e1bbbcde694d536ff749cf155fb94c64
@@ -664,14 +664,26 @@ void purple_xfer_conversation_write(Purp
/**
* Allows the UI to signal it's ready to send/receive data (depending on
- * the direction of the file transfer.
+ * the direction of the file transfer. Used when the UI is providing
+ * read/write/data_not_sent UI ops.
*
- * @param xfer The file transfer for which data is ready.
+ * @param xfer The file transfer which is ready.
*
* @since 2.6.0
*/
void purple_xfer_ui_ready(PurpleXfer *xfer);
+/**
+ * Allows the prpl to signal it's readh to send/receive data (depending on
+ * the direction of the file transfer. Used when the prpl provides read/write
+ * ops and cannot/does not provide a raw fd to the core.
+ *
+ * @param xfer The file transfer which is ready.
+ *
+ * @since 2.6.0
+ */
+void purple_xfer_prpl_ready(PurpleXfer *xfer);
+
/*@}*/
/**************************************************************************/
More information about the Commits
mailing list