ft: re-add some of the removed #include lines
[siplcs.git] / src / purple / purple-ft.c
blob3aa30d4a366297dc3bed54be1154a2f1bc92bcb6
1 /**
2 * @file purple-ft.c
4 * pidgin-sipe
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
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 #include <string.h>
30 #include <fcntl.h>
31 #include <errno.h>
33 #include <glib.h>
35 #include "ft.h"
36 #include "request.h"
38 #ifdef _WIN32
39 #include "win32/libc_interface.h"
40 #endif
42 #include "sipe-common.h"
43 #include "sipe-backend.h"
44 #include "sipe-core.h"
45 #include "sipe-nls.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,
54 const char *errmsg)
56 PurpleXfer *xfer = PURPLE_XFER;
57 purple_xfer_error(purple_xfer_get_type(xfer),
58 xfer->account, xfer->who,
59 errmsg);
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,
83 guchar *data,
84 gsize size)
86 gssize bytes_read = read(PURPLE_XFER->fd, data, size);
87 if (bytes_read == 0) {
88 /* Sender canceled transfer before it was finished */
89 return -2;
90 } else if (bytes_read == -1) {
91 if (errno == EAGAIN)
92 return 0;
93 else
94 return -1;
96 return bytes_read;
99 gssize sipe_backend_ft_write(struct sipe_file_transfer *ft,
100 const guchar *data,
101 gsize size)
103 gssize bytes_written = write(PURPLE_XFER->fd, data, size);
104 if (bytes_written == -1) {
105 if (errno == EAGAIN)
106 return 0;
107 else
108 return -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);
123 static void
124 ft_free_xfer_struct(PurpleXfer *xfer)
126 struct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;
128 if (ft) {
129 if (xfer->watcher) {
130 purple_input_remove(xfer->watcher);
131 xfer->watcher = 0;
133 sipe_core_ft_deallocate(ft);
134 xfer->data = NULL;
138 static void
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);
146 static void
147 ft_incoming_init(PurpleXfer *xfer)
149 sipe_core_ft_incoming_init(PURPLE_XFER_TO_SIPE_FILE_TRANSFER);
152 static void
153 tftp_incoming_start(PurpleXfer *xfer)
155 sipe_core_tftp_incoming_start(PURPLE_XFER_TO_SIPE_FILE_TRANSFER,
156 xfer->size);
159 static void
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);
165 } else {
166 unlink(xfer->local_filename);
170 static gssize
171 tftp_read(guchar **buffer, PurpleXfer *xfer)
173 return sipe_core_tftp_read(PURPLE_XFER_TO_SIPE_FILE_TRANSFER,
174 buffer,
175 purple_xfer_get_bytes_remaining(xfer),
176 xfer->current_buffer_size);
179 static void
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),
185 xfer->who);
188 static void
189 tftp_outgoing_start(PurpleXfer *xfer)
191 /* Set socket to non-blocking mode */
192 int flags = fcntl(xfer->fd, F_GETFL, 0);
193 if (flags == -1)
194 flags = 0;
195 fcntl(xfer->fd, F_SETFL, flags | O_NONBLOCK);
197 sipe_core_tftp_outgoing_start(PURPLE_XFER_TO_SIPE_FILE_TRANSFER,
198 xfer->size);
201 static void
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);
210 static gssize
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,
214 buffer, size);
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,
226 const gchar *who,
227 const gchar *file_name,
228 gsize file_size)
230 struct sipe_backend_private *purple_private = sipe_public->backend_private;
231 PurpleXfer *xfer;
233 xfer = purple_xfer_new(purple_private->account,
234 PURPLE_XFER_RECEIVE,
235 who);
237 if (xfer) {
238 ft->backend_private = (struct sipe_backend_file_transfer *)xfer;
239 xfer->data = ft;
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);
256 static void
257 connect_cb(gpointer data, gint fd, SIPE_UNUSED_PARAMETER const gchar *error_message)
259 struct sipe_file_transfer *ft = data;
261 if (fd < 0) {
262 purple_xfer_cancel_local(PURPLE_XFER);
263 return;
266 purple_xfer_start(PURPLE_XFER, fd, NULL, 0);
269 void
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,
279 connect_cb, ft);
280 return;
283 purple_xfer_start(PURPLE_XFER, fd, ip, port);
286 void sipe_purple_ft_send_file(PurpleConnection *gc,
287 const char *who,
288 const char *file)
290 PurpleXfer *xfer = sipe_purple_ft_new_xfer(gc, who);
292 if (xfer) {
293 if (file != NULL)
294 purple_xfer_request_accepted(xfer, file);
295 else
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);
308 if (xfer) {
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;
312 xfer->data = ft;
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);
324 return xfer;
327 gboolean
328 sipe_backend_ft_is_incoming(struct sipe_file_transfer *ft)
330 return purple_xfer_get_type(PURPLE_XFER) == PURPLE_XFER_RECEIVE;
334 Local Variables:
335 mode: c
336 c-file-style: "bsd"
337 indent-tabs-mode: t
338 tab-width: 8
339 End: