source: protocols/purple/ft.c @ 2309152

Last change on this file since 2309152 was 2309152, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-05-17T00:14:14Z

Split off the file transfer stuff into a separate file. What a mess.

  • Property mode set to 100644
File size: 6.7 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#include "bitlbee.h"
25
26#include <stdarg.h>
27
28#include <glib.h>
29#include <purple.h>
30
31struct prpl_xfer_data
32{
33        PurpleXfer *xfer;
34        file_transfer_t *ft;
35        gint ready_timer;
36        char *buf;
37        int buf_len;
38};
39
40static file_transfer_t *next_ft;
41
42struct im_connection *purple_ic_by_pa( PurpleAccount *pa );
43
44/* Glorious hack: We seem to have to remind at least some libpurple plugins
45   that we're ready because this info may get lost if we give it too early.
46   So just do it ten times a second. :-/ */
47static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond )
48{
49        struct prpl_xfer_data *px = data;
50       
51        purple_xfer_ui_ready( px->xfer );
52       
53        return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE;
54}
55
56static gboolean prpl_xfer_write_request( struct file_transfer *ft )
57{
58        struct prpl_xfer_data *px = ft->data;
59        px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px );
60        return TRUE;
61}
62
63static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len )
64{
65        struct prpl_xfer_data *px = ft->data;
66       
67        px->buf = g_memdup( buffer, len );
68        px->buf_len = len;
69
70        //purple_xfer_ui_ready( px->xfer );
71        px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px );
72       
73        return TRUE;
74}
75
76static void prpl_xfer_accept( struct file_transfer *ft )
77{
78        struct prpl_xfer_data *px = ft->data;
79        purple_xfer_request_accepted( px->xfer, NULL );
80        prpl_xfer_write_request( ft );
81}
82
83static void prpl_xfer_canceled( struct file_transfer *ft, char *reason )
84{
85        struct prpl_xfer_data *px = ft->data;
86        purple_xfer_request_denied( px->xfer );
87}
88
89static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond )
90{
91        PurpleXfer *xfer = data;
92        struct im_connection *ic = purple_ic_by_pa( xfer->account );
93        struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
94        PurpleBuddy *buddy;
95        const char *who;
96       
97        buddy = purple_find_buddy( xfer->account, xfer->who );
98        who = buddy ? purple_buddy_get_name( buddy ) : xfer->who;
99       
100        /* TODO(wilmer): After spreading some more const goodness in BitlBee,
101           remove the evil cast below. */
102        px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size );
103        px->ft->data = px;
104        px->xfer = data;
105        px->xfer->ui_data = px;
106       
107        px->ft->accept = prpl_xfer_accept;
108        px->ft->canceled = prpl_xfer_canceled;
109        px->ft->write_request = prpl_xfer_write_request;
110       
111        return FALSE;
112}
113
114static void prplcb_xfer_new( PurpleXfer *xfer )
115{
116        if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE )
117        {
118                /* This should suppress the stupid file dialog. */
119                purple_xfer_set_local_filename( xfer, "/tmp/wtf123" );
120               
121                /* Sadly the xfer struct is still empty ATM so come back after
122                   the caller is done. */
123                b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer );
124        }
125        else
126        {
127                struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
128               
129                px->ft = next_ft;
130                px->ft->data = px;
131                px->xfer = xfer;
132                px->xfer->ui_data = px;
133               
134                purple_xfer_set_filename( xfer, px->ft->file_name );
135                purple_xfer_set_size( xfer, px->ft->file_size );
136               
137                next_ft = NULL;
138        }
139}
140
141static void prplcb_xfer_progress( PurpleXfer *xfer, double percent )
142{
143        fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent );
144}
145
146static void prplcb_xfer_dbg( PurpleXfer *xfer )
147{
148        fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer );
149}
150
151static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size )
152{
153        struct prpl_xfer_data *px = xfer->ui_data;
154        gboolean st;
155       
156        fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len );
157       
158        b_event_remove( px->ready_timer );
159        px->ready_timer = 0;
160       
161        st = px->ft->write( px->ft, (char*) buffer, size );
162       
163        if( st && xfer->bytes_remaining == size )
164                imcb_file_finished( px->ft );
165       
166        return st ? size : 0;
167}
168
169gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size )
170{
171        struct prpl_xfer_data *px = xfer->ui_data;
172       
173        fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len );
174
175        if( px->buf )
176        {
177                *buffer = px->buf;
178                px->buf = NULL;
179               
180                px->ft->write_request( px->ft );
181               
182                return px->buf_len;
183        }
184       
185        return 0;
186}
187
188PurpleXferUiOps bee_xfer_uiops =
189{
190        prplcb_xfer_new,
191        prplcb_xfer_dbg,
192        prplcb_xfer_dbg,
193        prplcb_xfer_progress,
194        prplcb_xfer_dbg,
195        prplcb_xfer_dbg,
196        prplcb_xfer_write,
197        prplcb_xfer_read,
198        prplcb_xfer_dbg,
199};
200
201static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond );
202
203void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle )
204{
205        PurpleAccount *pa = ic->proto_data;
206        struct prpl_xfer_data *px;
207       
208        /* xfer_new() will pick up this variable. It's a hack but we're not
209           multi-threaded anyway. */
210        next_ft = ft;
211        serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name );
212       
213        ft->write = prpl_xfer_write;
214       
215        px = ft->data;
216        imcb_file_recv_start( ft );
217       
218        px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px );
219}
220
221static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond )
222{
223        struct prpl_xfer_data *px = data;
224       
225        if( px->ft->status & FT_STATUS_TRANSFERRING )
226        {
227                fprintf( stderr, "The ft, it is ready...\n" );
228                px->ft->write_request( px->ft );
229               
230                return FALSE;
231        }
232       
233        return TRUE;
234}
Note: See TracBrowser for help on using the repository browser.