6 * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>
7 * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>
8 * Copyright (C) 2010 Tomáš Hrabčík <tomas.hrabcik@tieto.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 #include "win32/libc_interface.h"
42 #include "sipe-common.h"
43 #include "sipe-backend.h"
44 #include "sipe-core.h"
47 #include "purple-private.h"
49 #define PURPLE_XFER ((PurpleXfer *) ft->backend_private)
50 #define PURPLE_XFER_TO_SIPE_FILE_TRANSFER ((struct sipe_file_transfer *) xfer->data)
51 #define PURPLE_XFER_TO_SIPE_CORE_PUBLIC ((struct sipe_core_public *) xfer->account->gc->proto_data)
53 void sipe_backend_ft_error(struct sipe_file_transfer
*ft
,
56 PurpleXfer
*xfer
= PURPLE_XFER
;
57 purple_xfer_error(purple_xfer_get_type(xfer
),
58 xfer
->account
, xfer
->who
,
62 const gchar
*sipe_backend_ft_get_error(SIPE_UNUSED_PARAMETER
struct sipe_file_transfer
*ft
)
64 return strerror(errno
);
67 void sipe_backend_ft_deallocate(struct sipe_file_transfer
*ft
)
69 PurpleXfer
*xfer
= PURPLE_XFER
;
70 PurpleXferStatusType status
= purple_xfer_get_status(xfer
);
72 // If file transfer is not finished, cancel it
73 if ( status
!= PURPLE_XFER_STATUS_DONE
74 && status
!= PURPLE_XFER_STATUS_CANCEL_LOCAL
75 && status
!= PURPLE_XFER_STATUS_CANCEL_REMOTE
) {
76 purple_xfer_set_cancel_recv_fnc(xfer
, NULL
);
77 purple_xfer_set_cancel_send_fnc(xfer
, NULL
);
78 purple_xfer_cancel_remote(xfer
);
82 gssize
sipe_backend_ft_read(struct sipe_file_transfer
*ft
,
86 gssize bytes_read
= read(PURPLE_XFER
->fd
, data
, size
);
87 if (bytes_read
== 0) {
88 /* Sender canceled transfer before it was finished */
90 } else if (bytes_read
== -1) {
99 gssize
sipe_backend_ft_write(struct sipe_file_transfer
*ft
,
103 gssize bytes_written
= write(PURPLE_XFER
->fd
, data
, size
);
104 if (bytes_written
== -1) {
110 return bytes_written
;
113 void sipe_backend_ft_cancel_local(struct sipe_file_transfer
*ft
)
115 purple_xfer_cancel_local(PURPLE_XFER
);
118 void sipe_backend_ft_cancel_remote(struct sipe_file_transfer
*ft
)
120 purple_xfer_cancel_remote(PURPLE_XFER
);
124 ft_free_xfer_struct(PurpleXfer
*xfer
)
126 struct sipe_file_transfer
*ft
= PURPLE_XFER_TO_SIPE_FILE_TRANSFER
;
130 purple_input_remove(xfer
->watcher
);
133 sipe_core_ft_deallocate(ft
);
139 ft_request_denied(PurpleXfer
*xfer
)
141 if (xfer
->type
== PURPLE_XFER_RECEIVE
)
142 sipe_core_ft_cancel(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
);
143 ft_free_xfer_struct(xfer
);
147 ft_incoming_init(PurpleXfer
*xfer
)
149 sipe_core_ft_incoming_init(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
);
153 tftp_incoming_start(PurpleXfer
*xfer
)
155 sipe_core_tftp_incoming_start(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
,
160 tftp_incoming_stop(PurpleXfer
*xfer
)
162 if (sipe_core_tftp_incoming_stop(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
)) {
163 /* We're done with this transfer */
164 ft_free_xfer_struct(xfer
);
166 unlink(xfer
->local_filename
);
171 tftp_read(guchar
**buffer
, PurpleXfer
*xfer
)
173 return sipe_core_tftp_read(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
,
175 purple_xfer_get_bytes_remaining(xfer
),
176 xfer
->current_buffer_size
);
180 ft_outgoing_init(PurpleXfer
*xfer
)
182 sipe_core_ft_outgoing_init(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
,
183 purple_xfer_get_filename(xfer
),
184 purple_xfer_get_size(xfer
),
189 tftp_outgoing_start(PurpleXfer
*xfer
)
191 /* Set socket to non-blocking mode */
192 int flags
= fcntl(xfer
->fd
, F_GETFL
, 0);
195 fcntl(xfer
->fd
, F_SETFL
, flags
| O_NONBLOCK
);
197 sipe_core_tftp_outgoing_start(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
,
202 tftp_outgoing_stop(PurpleXfer
*xfer
)
204 if (sipe_core_tftp_outgoing_stop(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
)) {
205 /* We're done with this transfer */
206 ft_free_xfer_struct(xfer
);
211 tftp_write(const guchar
*buffer
, size_t size
, PurpleXfer
*xfer
)
213 gssize bytes_written
= sipe_core_tftp_write(PURPLE_XFER_TO_SIPE_FILE_TRANSFER
,
216 if ((xfer
->bytes_remaining
- bytes_written
) == 0)
217 purple_xfer_set_completed(xfer
, TRUE
);
219 return bytes_written
;
222 //******************************************************************************
224 void sipe_backend_ft_incoming(struct sipe_core_public
*sipe_public
,
225 struct sipe_file_transfer
*ft
,
227 const gchar
*file_name
,
230 struct sipe_backend_private
*purple_private
= sipe_public
->backend_private
;
233 xfer
= purple_xfer_new(purple_private
->account
,
238 ft
->backend_private
= (struct sipe_backend_file_transfer
*)xfer
;
241 purple_xfer_set_filename(xfer
, file_name
);
242 purple_xfer_set_size(xfer
, file_size
);
244 purple_xfer_set_init_fnc(xfer
, ft_incoming_init
);
245 purple_xfer_set_request_denied_fnc(xfer
, ft_request_denied
);
246 purple_xfer_set_cancel_send_fnc(xfer
, ft_free_xfer_struct
);
247 purple_xfer_set_cancel_recv_fnc(xfer
, ft_free_xfer_struct
);
248 purple_xfer_set_start_fnc(xfer
, tftp_incoming_start
);
249 purple_xfer_set_end_fnc(xfer
, tftp_incoming_stop
);
250 purple_xfer_set_read_fnc(xfer
, tftp_read
);
252 purple_xfer_request(xfer
);
257 connect_cb(gpointer data
, gint fd
, SIPE_UNUSED_PARAMETER
const gchar
*error_message
)
259 struct sipe_file_transfer
*ft
= data
;
262 purple_xfer_cancel_local(PURPLE_XFER
);
266 purple_xfer_start(PURPLE_XFER
, fd
, NULL
, 0);
270 sipe_backend_ft_start(struct sipe_file_transfer
*ft
, int fd
,
271 const char* ip
, unsigned port
)
273 if (ip
&& port
&& !sipe_backend_ft_is_incoming(ft
)) {
274 /* Purple accepts ip & port only for incoming file transfers.
275 * If we want to send file with Sender-Connect = TRUE negotiated,
276 * we have to open the connection ourselves and pass the file
277 * descriptor to purple_xfer_start. */
278 purple_proxy_connect(NULL
, PURPLE_XFER
->account
, ip
, port
,
283 purple_xfer_start(PURPLE_XFER
, fd
, ip
, port
);
286 void sipe_purple_ft_send_file(PurpleConnection
*gc
,
290 PurpleXfer
*xfer
= sipe_purple_ft_new_xfer(gc
, who
);
294 purple_xfer_request_accepted(xfer
, file
);
296 purple_xfer_request(xfer
);
300 PurpleXfer
*sipe_purple_ft_new_xfer(PurpleConnection
*gc
, const char *who
)
302 PurpleXfer
*xfer
= NULL
;
304 if (PURPLE_CONNECTION_IS_VALID(gc
)) {
305 xfer
= purple_xfer_new(purple_connection_get_account(gc
),
306 PURPLE_XFER_SEND
, who
);
309 struct sipe_file_transfer
*ft
= sipe_core_ft_allocate(PURPLE_GC_TO_SIPE_CORE_PUBLIC
);
311 ft
->backend_private
= (struct sipe_backend_file_transfer
*)xfer
;
314 purple_xfer_set_init_fnc(xfer
, ft_outgoing_init
);
315 purple_xfer_set_request_denied_fnc(xfer
, ft_request_denied
);
316 purple_xfer_set_cancel_send_fnc(xfer
, ft_free_xfer_struct
);
317 purple_xfer_set_cancel_recv_fnc(xfer
, ft_free_xfer_struct
);
318 purple_xfer_set_start_fnc(xfer
, tftp_outgoing_start
);
319 purple_xfer_set_end_fnc(xfer
, tftp_outgoing_stop
);
320 purple_xfer_set_write_fnc(xfer
, tftp_write
);
328 sipe_backend_ft_is_incoming(struct sipe_file_transfer
*ft
)
330 return purple_xfer_get_type(PURPLE_XFER
) == PURPLE_XFER_RECEIVE
;