Mercurial > pidgin
annotate src/protocols/sametime/meanwhile/srvc_ft.c @ 12068:8e9c18896431
[gaim-migrate @ 14363]
This was somehow missed in the revert of the GtkSpell stuff.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 13 Nov 2005 02:03:55 +0000 |
parents | 0110fc7c6a8a |
children |
rev | line source |
---|---|
10969 | 1 |
2 /* | |
3 Meanwhile - Unofficial Lotus Sametime Community Client Library | |
4 Copyright (C) 2004 Christopher (siege) O'Brien | |
5 | |
6 This library is free software; you can redistribute it and/or | |
7 modify it under the terms of the GNU Library General Public | |
8 License as published by the Free Software Foundation; either | |
9 version 2 of the License, or (at your option) any later version. | |
10 | |
11 This library is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 Library General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU Library General Public | |
17 License along with this library; if not, write to the Free | |
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 */ | |
20 | |
21 | |
22 #include <glib/glist.h> | |
23 | |
24 #include "mw_channel.h" | |
25 #include "mw_common.h" | |
26 #include "mw_debug.h" | |
27 #include "mw_error.h" | |
28 #include "mw_message.h" | |
29 #include "mw_service.h" | |
30 #include "mw_session.h" | |
31 #include "mw_srvc_ft.h" | |
32 #include "mw_util.h" | |
33 | |
34 | |
35 #define PROTOCOL_TYPE 0x00000000 | |
36 #define PROTOCOL_VER 0x00000001 | |
37 | |
38 | |
39 /** send-on-channel type: FT transfer data */ | |
40 #define msg_TRANSFER 0x0001 | |
41 | |
42 | |
43 /** ack received transfer data */ | |
44 #define msg_RECEIVED 0x0002 | |
45 | |
46 | |
47 struct mwServiceFileTransfer { | |
48 struct mwService service; | |
49 | |
50 struct mwFileTransferHandler *handler; | |
51 GList *transfers; | |
52 }; | |
53 | |
54 | |
55 struct mwFileTransfer { | |
56 struct mwServiceFileTransfer *service; | |
57 | |
58 struct mwChannel *channel; | |
59 struct mwIdBlock who; | |
60 | |
61 enum mwFileTransferState state; | |
62 | |
63 char *filename; | |
64 char *message; | |
65 | |
66 guint32 size; | |
67 guint32 remaining; | |
68 | |
69 struct mw_datum client_data; | |
70 }; | |
71 | |
72 | |
73 /** momentarily places a mwLoginInfo into a mwIdBlock */ | |
74 static void login_into_id(struct mwIdBlock *to, struct mwLoginInfo *from) { | |
75 to->user = from->user_id; | |
76 to->community = from->community; | |
77 } | |
78 | |
79 | |
80 static const char *ft_state_str(enum mwFileTransferState state) { | |
81 switch(state) { | |
82 case mwFileTransfer_NEW: | |
83 return "new"; | |
84 | |
85 case mwFileTransfer_PENDING: | |
86 return "pending"; | |
87 | |
88 case mwFileTransfer_OPEN: | |
89 return "open"; | |
90 | |
91 case mwFileTransfer_CANCEL_LOCAL: | |
92 return "cancelled locally"; | |
93 | |
94 case mwFileTransfer_CANCEL_REMOTE: | |
95 return "cancelled remotely"; | |
96 | |
97 case mwFileTransfer_DONE: | |
98 return "done"; | |
99 | |
100 case mwFileTransfer_ERROR: | |
101 return "error"; | |
102 | |
103 case mwFileTransfer_UNKNOWN: | |
104 default: | |
105 return "UNKNOWN"; | |
106 } | |
107 } | |
108 | |
109 | |
110 static void ft_state(struct mwFileTransfer *ft, | |
111 enum mwFileTransferState state) { | |
112 | |
113 g_return_if_fail(ft != NULL); | |
114 | |
115 if(ft->state == state) return; | |
116 | |
117 g_info("setting ft (%s, %s) state: %s", | |
118 NSTR(ft->who.user), NSTR(ft->who.community), | |
119 ft_state_str(state)); | |
120 | |
121 ft->state = state; | |
122 } | |
123 | |
124 | |
125 static void recv_channelCreate(struct mwServiceFileTransfer *srvc, | |
126 struct mwChannel *chan, | |
127 struct mwMsgChannelCreate *msg) { | |
128 | |
129 struct mwFileTransferHandler *handler; | |
130 struct mwGetBuffer *b; | |
131 | |
132 char *fnm, *txt; | |
133 guint32 size, junk; | |
134 gboolean b_err; | |
135 | |
136 g_return_if_fail(srvc->handler != NULL); | |
137 handler = srvc->handler; | |
138 | |
139 b = mwGetBuffer_wrap(&msg->addtl); | |
140 | |
141 guint32_get(b, &junk); /* unknown */ | |
142 mwString_get(b, &fnm); /* offered filename */ | |
143 mwString_get(b, &txt); /* offering message */ | |
144 guint32_get(b, &size); /* size of offered file */ | |
145 guint32_get(b, &junk); /* unknown */ | |
146 /* and we just skip an unknown guint16 at the end */ | |
147 | |
148 b_err = mwGetBuffer_error(b); | |
149 mwGetBuffer_free(b); | |
150 | |
151 if(b_err) { | |
152 g_warning("bad/malformed addtl in File Transfer service"); | |
153 mwChannel_destroy(chan, ERR_FAILURE, NULL); | |
154 | |
155 } else { | |
156 struct mwIdBlock idb; | |
157 struct mwFileTransfer *ft; | |
158 | |
159 login_into_id(&idb, mwChannel_getUser(chan)); | |
160 ft = mwFileTransfer_new(srvc, &idb, txt, fnm, size); | |
161 ft->channel = chan; | |
162 ft_state(ft, mwFileTransfer_PENDING); | |
163 | |
164 mwChannel_setServiceData(chan, ft, NULL); | |
165 | |
166 if(handler->ft_offered) | |
167 handler->ft_offered(ft); | |
168 } | |
169 | |
170 g_free(fnm); | |
171 g_free(txt); | |
172 } | |
173 | |
174 | |
175 static void recv_channelAccept(struct mwServiceFileTransfer *srvc, | |
176 struct mwChannel *chan, | |
177 struct mwMsgChannelAccept *msg) { | |
178 | |
179 struct mwFileTransferHandler *handler; | |
180 struct mwFileTransfer *ft; | |
181 | |
182 g_return_if_fail(srvc->handler != NULL); | |
183 handler = srvc->handler; | |
184 | |
185 ft = mwChannel_getServiceData(chan); | |
186 g_return_if_fail(ft != NULL); | |
187 | |
188 ft_state(ft, mwFileTransfer_OPEN); | |
189 | |
190 if(handler->ft_opened) | |
191 handler->ft_opened(ft); | |
192 } | |
193 | |
194 | |
195 static void recv_channelDestroy(struct mwServiceFileTransfer *srvc, | |
196 struct mwChannel *chan, | |
197 struct mwMsgChannelDestroy *msg) { | |
198 | |
199 struct mwFileTransferHandler *handler; | |
200 struct mwFileTransfer *ft; | |
201 guint32 code; | |
202 | |
203 code = msg->reason; | |
204 | |
205 g_return_if_fail(srvc->handler != NULL); | |
206 handler = srvc->handler; | |
207 | |
208 ft = mwChannel_getServiceData(chan); | |
209 g_return_if_fail(ft != NULL); | |
210 | |
211 ft->channel = NULL; | |
212 | |
213 if(! mwFileTransfer_isDone(ft)) | |
214 ft_state(ft, mwFileTransfer_CANCEL_REMOTE); | |
215 | |
216 mwFileTransfer_close(ft, code); | |
217 } | |
218 | |
219 | |
220 static void recv_TRANSFER(struct mwFileTransfer *ft, | |
221 struct mwOpaque *data) { | |
222 | |
223 struct mwServiceFileTransfer *srvc; | |
224 struct mwFileTransferHandler *handler; | |
225 | |
226 srvc = ft->service; | |
227 handler = srvc->handler; | |
228 | |
229 g_return_if_fail(mwFileTransfer_isOpen(ft)); | |
230 | |
231 if(data->len > ft->remaining) { | |
232 /* @todo handle error */ | |
233 | |
234 } else { | |
235 ft->remaining -= data->len; | |
236 | |
237 if(! ft->remaining) | |
238 ft_state(ft, mwFileTransfer_DONE); | |
239 | |
240 if(handler->ft_recv) | |
241 handler->ft_recv(ft, data); | |
242 } | |
243 } | |
244 | |
245 | |
246 static void recv_RECEIVED(struct mwFileTransfer *ft, | |
247 struct mwOpaque *data) { | |
248 | |
249 struct mwServiceFileTransfer *srvc; | |
250 struct mwFileTransferHandler *handler; | |
251 | |
252 srvc = ft->service; | |
253 handler = srvc->handler; | |
254 | |
255 if(! ft->remaining) | |
256 ft_state(ft, mwFileTransfer_DONE); | |
257 | |
258 if(handler->ft_ack) | |
259 handler->ft_ack(ft); | |
260 | |
261 if(! ft->remaining) | |
262 mwFileTransfer_close(ft, mwFileTransfer_SUCCESS); | |
263 } | |
264 | |
265 | |
266 static void recv(struct mwService *srvc, struct mwChannel *chan, | |
267 guint16 type, struct mwOpaque *data) { | |
268 | |
269 struct mwFileTransfer *ft; | |
270 | |
271 ft = mwChannel_getServiceData(chan); | |
272 g_return_if_fail(ft != NULL); | |
273 | |
274 switch(type) { | |
275 case msg_TRANSFER: | |
276 recv_TRANSFER(ft, data); | |
277 break; | |
278 | |
279 case msg_RECEIVED: | |
280 recv_RECEIVED(ft, data); | |
281 break; | |
282 | |
283 default: | |
11943
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
284 mw_mailme_opaque(data, "unknown message in ft service: 0x%04x", type); |
10969 | 285 } |
286 } | |
287 | |
288 | |
289 static void clear(struct mwServiceFileTransfer *srvc) { | |
290 struct mwFileTransferHandler *h; | |
291 | |
292 h = srvc->handler; | |
293 if(h && h->clear) | |
294 h->clear(srvc); | |
295 srvc->handler = NULL; | |
296 } | |
297 | |
298 | |
299 static const char *name(struct mwService *srvc) { | |
300 return "File Transfer"; | |
301 } | |
302 | |
303 | |
304 static const char *desc(struct mwService *srvc) { | |
305 return "Provides file transfer capabilities through the community server"; | |
306 } | |
307 | |
308 | |
309 static void start(struct mwService *srvc) { | |
310 mwService_started(srvc); | |
311 } | |
312 | |
313 | |
314 static void stop(struct mwServiceFileTransfer *srvc) { | |
315 while(srvc->transfers) { | |
316 mwFileTransfer_free(srvc->transfers->data); | |
317 } | |
318 | |
319 mwService_stopped(MW_SERVICE(srvc)); | |
320 } | |
321 | |
322 | |
323 struct mwServiceFileTransfer * | |
324 mwServiceFileTransfer_new(struct mwSession *session, | |
325 struct mwFileTransferHandler *handler) { | |
326 | |
327 struct mwServiceFileTransfer *srvc_ft; | |
328 struct mwService *srvc; | |
329 | |
330 g_return_val_if_fail(session != NULL, NULL); | |
331 g_return_val_if_fail(handler != NULL, NULL); | |
332 | |
333 srvc_ft = g_new0(struct mwServiceFileTransfer, 1); | |
334 srvc = MW_SERVICE(srvc_ft); | |
335 | |
336 mwService_init(srvc, session, mwService_FILE_TRANSFER); | |
337 srvc->recv_create = (mwService_funcRecvCreate) recv_channelCreate; | |
338 srvc->recv_accept = (mwService_funcRecvAccept) recv_channelAccept; | |
339 srvc->recv_destroy = (mwService_funcRecvDestroy) recv_channelDestroy; | |
340 srvc->recv = recv; | |
341 srvc->clear = (mwService_funcClear) clear; | |
342 srvc->get_name = name; | |
343 srvc->get_desc = desc; | |
344 srvc->start = start; | |
345 srvc->stop = (mwService_funcStop) stop; | |
346 | |
347 srvc_ft->handler = handler; | |
348 | |
349 return srvc_ft; | |
350 } | |
351 | |
352 | |
353 struct mwFileTransferHandler * | |
354 mwServiceFileTransfer_getHandler(struct mwServiceFileTransfer *srvc) { | |
355 g_return_val_if_fail(srvc != NULL, NULL); | |
356 return srvc->handler; | |
357 } | |
358 | |
359 | |
11943
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
360 const GList * |
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
361 mwServiceFileTransfer_getTransfers(struct mwServiceFileTransfer *srvc) { |
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
362 g_return_val_if_fail(srvc != NULL, NULL); |
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
363 return srvc->transfers; |
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
364 } |
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
365 |
0110fc7c6a8a
[gaim-migrate @ 14234]
Christopher O'Brien <siege@pidgin.im>
parents:
10977
diff
changeset
|
366 |
10969 | 367 struct mwFileTransfer * |
368 mwFileTransfer_new(struct mwServiceFileTransfer *srvc, | |
369 const struct mwIdBlock *who, const char *msg, | |
370 const char *filename, guint32 filesize) { | |
371 | |
372 struct mwFileTransfer *ft; | |
373 | |
374 g_return_val_if_fail(srvc != NULL, NULL); | |
375 g_return_val_if_fail(who != NULL, NULL); | |
376 | |
377 ft = g_new0(struct mwFileTransfer, 1); | |
378 ft->service = srvc; | |
379 mwIdBlock_clone(&ft->who, who); | |
380 ft->filename = g_strdup(filename); | |
381 ft->message = g_strdup(msg); | |
382 ft->size = ft->remaining = filesize; | |
383 | |
384 ft_state(ft, mwFileTransfer_NEW); | |
385 | |
386 /* stick a reference in the service */ | |
387 srvc->transfers = g_list_prepend(srvc->transfers, ft); | |
388 | |
389 return ft; | |
390 } | |
391 | |
392 | |
393 struct mwServiceFileTransfer * | |
394 mwFileTransfer_getService(struct mwFileTransfer *ft) { | |
395 g_return_val_if_fail(ft != NULL, NULL); | |
396 return ft->service; | |
397 } | |
398 | |
399 | |
400 enum mwFileTransferState | |
401 mwFileTransfer_getState(struct mwFileTransfer *ft) { | |
402 g_return_val_if_fail(ft != NULL, mwFileTransfer_UNKNOWN); | |
403 return ft->state; | |
404 } | |
405 | |
406 | |
407 const struct mwIdBlock * | |
408 mwFileTransfer_getUser(struct mwFileTransfer *ft) { | |
409 g_return_val_if_fail(ft != NULL, NULL); | |
410 return &ft->who; | |
411 } | |
412 | |
413 | |
414 const char * | |
415 mwFileTransfer_getMessage(struct mwFileTransfer *ft) { | |
416 g_return_val_if_fail(ft != NULL, NULL); | |
417 return ft->message; | |
418 } | |
419 | |
420 | |
421 const char * | |
422 mwFileTransfer_getFileName(struct mwFileTransfer *ft) { | |
423 g_return_val_if_fail(ft != NULL, NULL); | |
424 return ft->filename; | |
425 } | |
426 | |
427 | |
428 guint32 mwFileTransfer_getFileSize(struct mwFileTransfer *ft) { | |
429 g_return_val_if_fail(ft != NULL, 0); | |
430 return ft->size; | |
431 } | |
432 | |
433 | |
434 guint32 mwFileTransfer_getRemaining(struct mwFileTransfer *ft) { | |
435 g_return_val_if_fail(ft != NULL, 0); | |
436 return ft->remaining; | |
437 } | |
438 | |
439 | |
440 int mwFileTransfer_accept(struct mwFileTransfer *ft) { | |
441 struct mwServiceFileTransfer *srvc; | |
442 struct mwFileTransferHandler *handler; | |
443 int ret; | |
444 | |
445 g_return_val_if_fail(ft != NULL, -1); | |
446 g_return_val_if_fail(ft->channel != NULL, -1); | |
447 g_return_val_if_fail(mwFileTransfer_isPending(ft), -1); | |
448 g_return_val_if_fail(mwChannel_isIncoming(ft->channel), -1); | |
449 g_return_val_if_fail(mwChannel_isState(ft->channel, mwChannel_WAIT), -1); | |
450 | |
451 g_return_val_if_fail(ft->service != NULL, -1); | |
452 srvc = ft->service; | |
453 | |
454 g_return_val_if_fail(srvc->handler != NULL, -1); | |
455 handler = srvc->handler; | |
456 | |
457 ret = mwChannel_accept(ft->channel); | |
458 | |
459 if(ret) { | |
460 mwFileTransfer_close(ft, ERR_FAILURE); | |
461 | |
462 } else { | |
463 ft_state(ft, mwFileTransfer_OPEN); | |
464 if(handler->ft_opened) | |
465 handler->ft_opened(ft); | |
466 } | |
467 | |
468 return ret; | |
469 } | |
470 | |
471 | |
472 static void ft_create_chan(struct mwFileTransfer *ft) { | |
473 struct mwSession *s; | |
474 struct mwChannelSet *cs; | |
475 struct mwChannel *chan; | |
476 struct mwLoginInfo *login; | |
477 struct mwPutBuffer *b; | |
478 | |
479 /* we only should be calling this if there isn't a channel already | |
480 associated with the conversation */ | |
481 g_return_if_fail(ft != NULL); | |
482 g_return_if_fail(mwFileTransfer_isNew(ft)); | |
483 g_return_if_fail(ft->channel == NULL); | |
484 | |
485 s = mwService_getSession(MW_SERVICE(ft->service)); | |
486 cs = mwSession_getChannels(s); | |
487 | |
488 chan = mwChannel_newOutgoing(cs); | |
489 mwChannel_setService(chan, MW_SERVICE(ft->service)); | |
490 mwChannel_setProtoType(chan, PROTOCOL_TYPE); | |
491 mwChannel_setProtoVer(chan, PROTOCOL_VER); | |
492 | |
493 /* offer all known ciphers */ | |
494 mwChannel_populateSupportedCipherInstances(chan); | |
495 | |
496 /* set the target */ | |
497 login = mwChannel_getUser(chan); | |
498 login->user_id = g_strdup(ft->who.user); | |
499 login->community = g_strdup(ft->who.community); | |
500 | |
501 /* compose the addtl create */ | |
502 b = mwPutBuffer_new(); | |
503 guint32_put(b, 0x00); | |
504 mwString_put(b, ft->filename); | |
505 mwString_put(b, ft->message); | |
506 guint32_put(b, ft->size); | |
507 guint32_put(b, 0x00); | |
508 guint16_put(b, 0x00); | |
509 | |
510 mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b); | |
511 | |
512 ft->channel = mwChannel_create(chan)? NULL: chan; | |
513 if(ft->channel) { | |
514 mwChannel_setServiceData(ft->channel, ft, NULL); | |
515 } | |
516 } | |
517 | |
518 | |
519 int mwFileTransfer_offer(struct mwFileTransfer *ft) { | |
520 struct mwServiceFileTransfer *srvc; | |
521 struct mwFileTransferHandler *handler; | |
522 | |
523 g_return_val_if_fail(ft != NULL, -1); | |
524 g_return_val_if_fail(ft->channel == NULL, -1); | |
525 g_return_val_if_fail(mwFileTransfer_isNew(ft), -1); | |
526 | |
527 g_return_val_if_fail(ft->service != NULL, -1); | |
528 srvc = ft->service; | |
529 | |
530 g_return_val_if_fail(srvc->handler != NULL, -1); | |
531 handler = srvc->handler; | |
532 | |
533 ft_create_chan(ft); | |
534 if(ft->channel) { | |
535 ft_state(ft, mwFileTransfer_PENDING); | |
536 } else { | |
537 ft_state(ft, mwFileTransfer_ERROR); | |
538 mwFileTransfer_close(ft, ERR_FAILURE); | |
539 } | |
540 | |
541 return 0; | |
542 } | |
543 | |
544 | |
545 int mwFileTransfer_close(struct mwFileTransfer *ft, guint32 code) { | |
546 struct mwServiceFileTransfer *srvc; | |
547 struct mwFileTransferHandler *handler; | |
10977
2ce8ec01a064
[gaim-migrate @ 12803]
Christopher O'Brien <siege@pidgin.im>
parents:
10969
diff
changeset
|
548 int ret = 0; |
10969 | 549 |
550 g_return_val_if_fail(ft != NULL, -1); | |
551 | |
552 if(mwFileTransfer_isOpen(ft)) | |
553 ft_state(ft, mwFileTransfer_CANCEL_LOCAL); | |
554 | |
555 if(ft->channel) { | |
556 ret = mwChannel_destroy(ft->channel, code, NULL); | |
557 ft->channel = NULL; | |
558 } | |
559 | |
560 srvc = ft->service; | |
561 g_return_val_if_fail(srvc != NULL, ret); | |
562 | |
563 handler = srvc->handler; | |
564 g_return_val_if_fail(handler != NULL, ret); | |
565 | |
566 if(handler->ft_closed) | |
567 handler->ft_closed(ft, code); | |
568 | |
569 return ret; | |
570 } | |
571 | |
572 | |
573 void mwFileTransfer_free(struct mwFileTransfer *ft) { | |
574 struct mwServiceFileTransfer *srvc; | |
575 | |
576 if(! ft) return; | |
577 | |
578 srvc = ft->service; | |
579 if(srvc) | |
580 srvc->transfers = g_list_remove(srvc->transfers, ft); | |
581 | |
582 if(ft->channel) { | |
583 mwChannel_destroy(ft->channel, mwFileTransfer_SUCCESS, NULL); | |
584 ft->channel = NULL; | |
585 } | |
586 | |
587 mwFileTransfer_removeClientData(ft); | |
588 | |
589 mwIdBlock_clear(&ft->who); | |
590 g_free(ft->filename); | |
591 g_free(ft->message); | |
592 g_free(ft); | |
593 } | |
594 | |
595 | |
596 int mwFileTransfer_send(struct mwFileTransfer *ft, | |
597 struct mwOpaque *data) { | |
598 | |
599 struct mwChannel *chan; | |
600 int ret; | |
601 | |
602 g_return_val_if_fail(ft != NULL, -1); | |
603 g_return_val_if_fail(mwFileTransfer_isOpen(ft), -1); | |
604 g_return_val_if_fail(ft->channel != NULL, -1); | |
605 chan = ft->channel; | |
606 | |
607 g_return_val_if_fail(mwChannel_isOutgoing(chan), -1); | |
608 | |
609 if(data->len > ft->remaining) { | |
610 /* @todo handle error */ | |
611 return -1; | |
612 } | |
613 | |
614 ret = mwChannel_send(chan, msg_TRANSFER, data); | |
615 if(! ret) ft->remaining -= data->len; | |
616 | |
617 /* we're not done until we receive an ACK for the last piece of | |
618 outgoing data */ | |
619 | |
620 return ret; | |
621 } | |
622 | |
623 | |
624 int mwFileTransfer_ack(struct mwFileTransfer *ft) { | |
625 struct mwChannel *chan; | |
626 | |
627 g_return_val_if_fail(ft != NULL, -1); | |
628 | |
629 chan = ft->channel; | |
630 g_return_val_if_fail(chan != NULL, -1); | |
631 g_return_val_if_fail(mwChannel_isIncoming(chan), -1); | |
632 | |
633 return mwChannel_sendEncrypted(chan, msg_RECEIVED, NULL, FALSE); | |
634 } | |
635 | |
636 | |
637 void mwFileTransfer_setClientData(struct mwFileTransfer *ft, | |
638 gpointer data, GDestroyNotify clean) { | |
639 g_return_if_fail(ft != NULL); | |
640 mw_datum_set(&ft->client_data, data, clean); | |
641 } | |
642 | |
643 | |
644 gpointer mwFileTransfer_getClientData(struct mwFileTransfer *ft) { | |
645 g_return_val_if_fail(ft != NULL, NULL); | |
646 return mw_datum_get(&ft->client_data); | |
647 } | |
648 | |
649 | |
650 void mwFileTransfer_removeClientData(struct mwFileTransfer *ft) { | |
651 g_return_if_fail(ft != NULL); | |
652 mw_datum_clear(&ft->client_data); | |
653 } | |
654 |