source: protocols/purple/ft-direct.c @ 4c73ba62

Last change on this file since 4c73ba62 was 553767c, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-05-17T20:30:45Z

Move direct ft stuff to an unused file: This gets too hairy and too fragile.
I don't have time to work out all the details, I doubt if this is supposed
to work reliably yet at all. Let's go for the simple via-disk approach for
now.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  libpurple module - File transfer stuff                                   *
5*                                                                           *
6*  Copyright 2009-2010 Wilmer van der Gaast <wilmer@gaast.net>              *
7*                                                                           *
8*  This program is free software; you can redistribute it and/or modify     *
9*  it under the terms of the GNU General Public License as published by     *
10*  the Free Software Foundation; either version 2 of the License, or        *
11*  (at your option) any later version.                                      *
12*                                                                           *
13*  This program is distributed in the hope that it will be useful,          *
14*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
15*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
16*  GNU General Public License for more details.                             *
17*                                                                           *
18*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24/* This code tries to do direct file transfers, i.e. without caching the file
25   locally on disk first. Since libpurple can only do this since version 2.6.0
26   and even then very unreliably (and not with all IM modules), I'm canning
27   this code for now. */
28
29#include "bitlbee.h"
30
31#include <stdarg.h>
32
33#include <glib.h>
34#include <purple.h>
35
36struct prpl_xfer_data
37{
38        PurpleXfer *xfer;
39        file_transfer_t *ft;
40        gint ready_timer;
41        char *buf;
42        int buf_len;
43};
44
45static file_transfer_t *next_ft;
46
47struct im_connection *purple_ic_by_pa( PurpleAccount *pa );
48
49/* Glorious hack: We seem to have to remind at least some libpurple plugins
50   that we're ready because this info may get lost if we give it too early.
51   So just do it ten times a second. :-/ */
52static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond )
53{
54        struct prpl_xfer_data *px = data;
55       
56        purple_xfer_ui_ready( px->xfer );
57       
58        return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE;
59}
60
61static gboolean prpl_xfer_write_request( struct file_transfer *ft )
62{
63        struct prpl_xfer_data *px = ft->data;
64        px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px );
65        return TRUE;
66}
67
68static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len )
69{
70        struct prpl_xfer_data *px = ft->data;
71       
72        px->buf = g_memdup( buffer, len );
73        px->buf_len = len;
74
75        //purple_xfer_ui_ready( px->xfer );
76        px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px );
77       
78        return TRUE;
79}
80
81static void prpl_xfer_accept( struct file_transfer *ft )
82{
83        struct prpl_xfer_data *px = ft->data;
84        purple_xfer_request_accepted( px->xfer, NULL );
85        prpl_xfer_write_request( ft );
86}
87
88static void prpl_xfer_canceled( struct file_transfer *ft, char *reason )
89{
90        struct prpl_xfer_data *px = ft->data;
91        purple_xfer_request_denied( px->xfer );
92}
93
94static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond )
95{
96        PurpleXfer *xfer = data;
97        struct im_connection *ic = purple_ic_by_pa( xfer->account );
98        struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
99        PurpleBuddy *buddy;
100        const char *who;
101       
102        buddy = purple_find_buddy( xfer->account, xfer->who );
103        who = buddy ? purple_buddy_get_name( buddy ) : xfer->who;
104       
105        /* TODO(wilmer): After spreading some more const goodness in BitlBee,
106           remove the evil cast below. */
107        px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size );
108        px->ft->data = px;
109        px->xfer = data;
110        px->xfer->ui_data = px;
111       
112        px->ft->accept = prpl_xfer_accept;
113        px->ft->canceled = prpl_xfer_canceled;
114        px->ft->write_request = prpl_xfer_write_request;
115       
116        return FALSE;
117}
118
119static void prplcb_xfer_new( PurpleXfer *xfer )
120{
121        if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE )
122        {
123                /* This should suppress the stupid file dialog. */
124                purple_xfer_set_local_filename( xfer, "/tmp/wtf123" );
125               
126                /* Sadly the xfer struct is still empty ATM so come back after
127                   the caller is done. */
128                b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer );
129        }
130        else
131        {
132                struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
133               
134                px->ft = next_ft;
135                px->ft->data = px;
136                px->xfer = xfer;
137                px->xfer->ui_data = px;
138               
139                purple_xfer_set_filename( xfer, px->ft->file_name );
140                purple_xfer_set_size( xfer, px->ft->file_size );
141               
142                next_ft = NULL;
143        }
144}
145
146static void prplcb_xfer_progress( PurpleXfer *xfer, double percent )
147{
148        fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent );
149}
150
151static void prplcb_xfer_dbg( PurpleXfer *xfer )
152{
153        fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer );
154}
155
156static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size )
157{
158        struct prpl_xfer_data *px = xfer->ui_data;
159        gboolean st;
160       
161        fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len );
162       
163        b_event_remove( px->ready_timer );
164        px->ready_timer = 0;
165       
166        st = px->ft->write( px->ft, (char*) buffer, size );
167       
168        if( st && xfer->bytes_remaining == size )
169                imcb_file_finished( px->ft );
170       
171        return st ? size : 0;
172}
173
174gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size )
175{
176        struct prpl_xfer_data *px = xfer->ui_data;
177       
178        fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len );
179
180        if( px->buf )
181        {
182                *buffer = px->buf;
183                px->buf = NULL;
184               
185                px->ft->write_request( px->ft );
186               
187                return px->buf_len;
188        }
189       
190        return 0;
191}
192
193PurpleXferUiOps bee_xfer_uiops =
194{
195        prplcb_xfer_new,
196        prplcb_xfer_dbg,
197        prplcb_xfer_dbg,
198        prplcb_xfer_progress,
199        prplcb_xfer_dbg,
200        prplcb_xfer_dbg,
201        prplcb_xfer_write,
202        prplcb_xfer_read,
203        prplcb_xfer_dbg,
204};
205
206static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond );
207
208void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle )
209{
210        PurpleAccount *pa = ic->proto_data;
211        struct prpl_xfer_data *px;
212       
213        /* xfer_new() will pick up this variable. It's a hack but we're not
214           multi-threaded anyway. */
215        next_ft = ft;
216        serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name );
217       
218        ft->write = prpl_xfer_write;
219       
220        px = ft->data;
221        imcb_file_recv_start( ft );
222       
223        px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px );
224}
225
226static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond )
227{
228        struct prpl_xfer_data *px = data;
229       
230        if( px->ft->status & FT_STATUS_TRANSFERRING )
231        {
232                fprintf( stderr, "The ft, it is ready...\n" );
233                px->ft->write_request( px->ft );
234               
235                return FALSE;
236        }
237       
238        return TRUE;
239}
Note: See TracBrowser for help on using the repository browser.