comparison libpurple/protocols/bonjour/bonjour_ft.c @ 21522:dc703f13449a

Fix a couple bugs in the Bonjour XEP-0065 implementation, mainly related to error handling, but also send a <streamhost-used /> result. Also fix a XEP-0096 bug where the SI profile wasn't being specified. These bring ft with gajim closer to working, but we aren't there yet.
author Daniel Atallah <daniel.atallah@gmail.com>
date Thu, 15 Nov 2007 14:53:53 +0000
parents 3d70e3ec8a47
children 5b9da9db7e81
comparison
equal deleted inserted replaced
21521:287ee978db2e 21522:dc703f13449a
43 43
44 /* Look for specific xfer handle */ 44 /* Look for specific xfer handle */
45 static unsigned int next_id = 0; 45 static unsigned int next_id = 0;
46 46
47 static void 47 static void
48 xep_ft_si_reject(PurpleXfer *xfer, char *to) 48 xep_ft_si_reject(BonjourData *bd, const char *id, const char *to, const char *error_code, const char *error_type)
49 { 49 {
50 xmlnode *error_node = NULL; 50 xmlnode *error_node = NULL;
51 xmlnode *tmp_node = NULL; 51 xmlnode *tmp_node = NULL;
52 XepIq *iq = NULL; 52 XepIq *iq = NULL;
53 XepXfer *xf = NULL; 53
54 54 g_return_if_fail(error_code != NULL);
55 if(!to || !xfer) 55 g_return_if_fail(error_type != NULL);
56 return; 56
57 xf = xfer->data; 57 if(!to || !id)
58 if(!xf)
59 return; 58 return;
60 59
61 purple_debug_info("bonjour", "xep file transfer stream initialization error.\n"); 60 purple_debug_info("bonjour", "xep file transfer stream initialization error.\n");
62 iq = xep_iq_new(xf->data, XEP_IQ_ERROR, to, xf->sid); 61 iq = xep_iq_new(bd, XEP_IQ_ERROR, to, purple_account_get_username(bd->jabber_data->account), id);
63 if(iq == NULL) 62 if(iq == NULL)
64 return; 63 return;
65 64
66 error_node = xmlnode_new_child(iq->node, "error"); 65 error_node = xmlnode_new_child(iq->node, "error");
67 xmlnode_set_attrib(error_node, "code", "403"); 66 xmlnode_set_attrib(error_node, "code", error_code);
68 xmlnode_set_attrib(error_node, "type", "cancel"); 67 xmlnode_set_attrib(error_node, "type", error_type);
69 68
70 tmp_node = xmlnode_new_child(error_node, "forbidden"); 69 /* TODO: Make this better */
71 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas"); 70 if (!strcmp(error_code, "403")) {
72 71 tmp_node = xmlnode_new_child(error_node, "forbidden");
73 tmp_node = xmlnode_new_child(error_node, "text"); 72 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas");
74 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas"); 73
75 xmlnode_insert_data(tmp_node, "Offer Declined", -1); 74 tmp_node = xmlnode_new_child(error_node, "text");
75 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas");
76 xmlnode_insert_data(tmp_node, "Offer Declined", -1);
77 } else if (!strcmp(error_code, "404")) {
78 tmp_node = xmlnode_new_child(error_node, "item-not-found");
79 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas");
80 }
76 81
77 xep_iq_send_and_free(iq); 82 xep_iq_send_and_free(iq);
78 } 83 }
79 84
80 static void bonjour_xfer_cancel_send(PurpleXfer *xfer) 85 static void bonjour_xfer_cancel_send(PurpleXfer *xfer)
83 bonjour_free_xfer(xfer); 88 bonjour_free_xfer(xfer);
84 } 89 }
85 90
86 static void bonjour_xfer_request_denied(PurpleXfer *xfer) 91 static void bonjour_xfer_request_denied(PurpleXfer *xfer)
87 { 92 {
93 XepXfer *xf = NULL;
94
88 purple_debug_info("bonjour", "Bonjour-xfer-request-denied.\n"); 95 purple_debug_info("bonjour", "Bonjour-xfer-request-denied.\n");
89 xep_ft_si_reject(xfer, xfer->who); 96
97 xf = xfer->data;
98 if(xf)
99 xep_ft_si_reject(xf->data, xf->sid, xfer->who, "403", "cancel");
100
90 bonjour_free_xfer(xfer); 101 bonjour_free_xfer(xfer);
91 } 102 }
92 103
93 static void bonjour_xfer_cancel_recv(PurpleXfer *xfer) 104 static void bonjour_xfer_cancel_recv(PurpleXfer *xfer)
94 { 105 {
191 purple_debug_info("bonjour", "xep file transfer stream initialization offer-id=%d.\n", next_id); 202 purple_debug_info("bonjour", "xep file transfer stream initialization offer-id=%d.\n", next_id);
192 203
193 /* Assign stream id. */ 204 /* Assign stream id. */
194 memset(buf, 0, 32); 205 memset(buf, 0, 32);
195 g_snprintf(buf, sizeof(buf), "%u", next_id++); 206 g_snprintf(buf, sizeof(buf), "%u", next_id++);
196 iq = xep_iq_new(xf->data, XEP_IQ_SET, to, buf); 207 iq = xep_iq_new(xf->data, XEP_IQ_SET, to, purple_account_get_username(bd->jabber_data->account), buf);
197 if(iq == NULL) 208 if(iq == NULL)
198 return; 209 return;
199 210
200 g_free(xf->sid); 211 g_free(xf->sid);
201 xf->sid = g_strdup(buf); 212 xf->sid = g_strdup(buf);
202 /*Construct Stream initialization offer message.*/ 213 /*Construct Stream initialization offer message.*/
203 si_node = xmlnode_new_child(iq->node, "si"); 214 si_node = xmlnode_new_child(iq->node, "si");
204 xmlnode_set_namespace(si_node, "http://jabber.org/protocol/si"); 215 xmlnode_set_namespace(si_node, "http://jabber.org/protocol/si");
216 xmlnode_set_attrib(si_node, "profile", "http://jabber.org/protocol/si/profile/file-transfer");
205 217
206 file = xmlnode_new_child(si_node, "file"); 218 file = xmlnode_new_child(si_node, "file");
207 xmlnode_set_namespace(file, "http://jabber.org/protocol/si/profile/file-transfer"); 219 xmlnode_set_namespace(file, "http://jabber.org/protocol/si/profile/file-transfer");
208 xmlnode_set_attrib(file, "name", xfer->filename); 220 xmlnode_set_attrib(file, "name", xfer->filename);
209 memset(buf, 0, 32); 221 memset(buf, 0, 32);
234 246
235 xep_iq_send_and_free(iq); 247 xep_iq_send_and_free(iq);
236 } 248 }
237 249
238 static void 250 static void
239 xep_ft_si_reject2(BonjourData *bd, const char *to, const char *sid)
240 {
241 xmlnode *error_node = NULL;
242 xmlnode *tmp_node = NULL;
243 XepIq *iq = NULL;
244
245 g_return_if_fail(bd != NULL);
246
247 if(!to || !sid)
248 return;
249
250 purple_debug_info("bonjour", "xep file transfer stream initialization error.\n");
251 iq = xep_iq_new(bd, XEP_IQ_ERROR, to, sid);
252 if(iq == NULL)
253 return;
254
255 error_node = xmlnode_new_child(iq->node, "error");
256 xmlnode_set_attrib(error_node, "code", "403");
257 xmlnode_set_attrib(error_node, "type", "cancel");
258
259 tmp_node = xmlnode_new_child(error_node, "forbidden");
260 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas");
261
262 tmp_node = xmlnode_new_child(error_node, "text");
263 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas");
264 xmlnode_insert_data(tmp_node, "Offer Declined", -1);
265
266 xep_iq_send_and_free(iq);
267 }
268
269 static void
270 xep_ft_si_result(PurpleXfer *xfer, char *to) 251 xep_ft_si_result(PurpleXfer *xfer, char *to)
271 { 252 {
272 xmlnode *si_node = NULL; 253 xmlnode *si_node = NULL;
273 xmlnode *feature = NULL; 254 xmlnode *feature = NULL;
274 xmlnode *field = NULL; 255 xmlnode *field = NULL;
275 xmlnode *value = NULL; 256 xmlnode *value = NULL;
276 xmlnode *x = NULL; 257 xmlnode *x = NULL;
277 XepIq *iq = NULL; 258 XepIq *iq = NULL;
278 XepXfer *xf = NULL; 259 XepXfer *xf = NULL;
260 BonjourData *bd;
279 261
280 if(!to || !xfer) 262 if(!to || !xfer)
281 return; 263 return;
282 xf = xfer->data; 264 xf = xfer->data;
283 if(!xf) 265 if(!xf)
284 return; 266 return;
285 267
268 bd = xf->data;
269
286 purple_debug_info("bonjour", "xep file transfer stream initialization result.\n"); 270 purple_debug_info("bonjour", "xep file transfer stream initialization result.\n");
287 iq = xep_iq_new(xf->data, XEP_IQ_RESULT, to, xf->sid); 271 iq = xep_iq_new(bd, XEP_IQ_RESULT, to, purple_account_get_username(bd->jabber_data->account), xf->sid);
288 if(iq == NULL) 272 if(iq == NULL)
289 return; 273 return;
290 274
291 si_node = xmlnode_new_child(iq->node, "si"); 275 si_node = xmlnode_new_child(iq->node, "si");
292 xmlnode_set_namespace(si_node, "http://jabber.org/protocol/si"); 276 xmlnode_set_namespace(si_node, "http://jabber.org/protocol/si");
277 /*xmlnode_set_attrib(si_node, "profile", "http://jabber.org/protocol/si/profile/file-transfer");*/
293 278
294 feature = xmlnode_new_child(si_node, "feature"); 279 feature = xmlnode_new_child(si_node, "feature");
295 xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg"); 280 xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg");
296 281
297 x = xmlnode_new_child(feature, "x"); 282 x = xmlnode_new_child(feature, "x");
329 } 314 }
330 if (xf->proxy_connection != NULL) 315 if (xf->proxy_connection != NULL)
331 purple_proxy_connect_cancel(xf->proxy_connection); 316 purple_proxy_connect_cancel(xf->proxy_connection);
332 if (xf->listen_data != NULL) 317 if (xf->listen_data != NULL)
333 purple_network_listen_cancel(xf->listen_data); 318 purple_network_listen_cancel(xf->listen_data);
319 g_free(xf->iq_id);
334 g_free(xf->jid); 320 g_free(xf->jid);
335 g_free(xf->proxy_host); 321 g_free(xf->proxy_host);
336 g_free(xf->buddy_ip); 322 g_free(xf->buddy_ip);
337 g_free(xf->sid); 323 g_free(xf->sid);
338 g_free(xf); 324 g_free(xf);
362 xfer->data = xep_xfer = g_new0(XepXfer, 1); 348 xfer->data = xep_xfer = g_new0(XepXfer, 1);
363 xep_xfer->data = bd; 349 xep_xfer->data = bd;
364 350
365 purple_debug_info("bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data); 351 purple_debug_info("bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data);
366 352
367 xep_xfer->mode = XEP_BYTESTREAMS | XEP_IBB; 353 /* We don't support IBB yet */
354 /*xep_xfer->mode = XEP_BYTESTREAMS | XEP_IBB;*/
355 xep_xfer->mode = XEP_BYTESTREAMS;
368 xep_xfer->sid = NULL; 356 xep_xfer->sid = NULL;
369 357
370 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init); 358 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init);
371 purple_xfer_set_cancel_send_fnc(xfer, bonjour_xfer_cancel_send); 359 purple_xfer_set_cancel_send_fnc(xfer, bonjour_xfer_cancel_send);
372 purple_xfer_set_end_fnc(xfer, bonjour_xfer_end); 360 purple_xfer_set_end_fnc(xfer, bonjour_xfer_end);
377 } 365 }
378 366
379 void 367 void
380 bonjour_send_file(PurpleConnection *gc, const char *who, const char *file) 368 bonjour_send_file(PurpleConnection *gc, const char *who, const char *file)
381 { 369 {
382
383 PurpleXfer *xfer = NULL; 370 PurpleXfer *xfer = NULL;
384 if(gc == NULL || who == NULL) 371
385 return; 372 g_return_if_fail(gc != NULL);
373 g_return_if_fail(who != NULL);
374
386 purple_debug_info("bonjour", "Bonjour-send-file to=%s.\n", who); 375 purple_debug_info("bonjour", "Bonjour-send-file to=%s.\n", who);
376
387 xfer = bonjour_new_xfer(gc, who); 377 xfer = bonjour_new_xfer(gc, who);
388 if(xfer == NULL) 378
389 return;
390 if (file) 379 if (file)
391 purple_xfer_request_accepted(xfer, file); 380 purple_xfer_request_accepted(xfer, file);
392 else 381 else
393 purple_xfer_request(xfer); 382 purple_xfer_request(xfer);
394 383
399 { 388 {
400 PurpleBuddy *buddy = NULL; 389 PurpleBuddy *buddy = NULL;
401 BonjourBuddy *bd = NULL; 390 BonjourBuddy *bd = NULL;
402 XepXfer *xf = NULL; 391 XepXfer *xf = NULL;
403 392
404 if(xfer == NULL)
405 return;
406 xf = (XepXfer*)xfer->data; 393 xf = (XepXfer*)xfer->data;
407 if(xf == NULL) 394 if(xf == NULL)
408 return; 395 return;
396
409 purple_debug_info("bonjour", "Bonjour-xfer-init.\n"); 397 purple_debug_info("bonjour", "Bonjour-xfer-init.\n");
410 398
411 buddy = purple_find_buddy(xfer->account, xfer->who); 399 buddy = purple_find_buddy(xfer->account, xfer->who);
412 /* this buddy is offline. */ 400 /* this buddy is offline. */
413 if (buddy == NULL) 401 if (buddy == NULL)
417 xf->buddy_ip = g_strdup(bd->ip); 405 xf->buddy_ip = g_strdup(bd->ip);
418 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { 406 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
419 /* initiate file transfer, send SI offer. */ 407 /* initiate file transfer, send SI offer. */
420 purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_SEND.\n"); 408 purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_SEND.\n");
421 xep_ft_si_offer(xfer, xfer->who); 409 xep_ft_si_offer(xfer, xfer->who);
422
423 } else { 410 } else {
424 /* accept file transfer request, send SI result. */ 411 /* accept file transfer request, send SI result. */
425 xep_ft_si_result(xfer, xfer->who); 412 xep_ft_si_result(xfer, xfer->who);
426 purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_RECEIVE.\n"); 413 purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_RECEIVE.\n");
427 } 414 }
428 return; 415 }
429 }
430
431 416
432 void 417 void
433 xep_si_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb) 418 xep_si_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb)
434 { 419 {
435 const char *type = NULL, *from = NULL, *id = NULL; 420 const char *type, *id;
436 xmlnode *si = NULL, *file = NULL;
437 BonjourData *bd = NULL; 421 BonjourData *bd = NULL;
438 PurpleXfer *xfer = NULL; 422 PurpleXfer *xfer = NULL;
439 const char *filename = NULL, *filesize_str = NULL;
440 int filesize = 0, option = XEP_BYTESTREAMS;
441 423
442 if(pc == NULL || packet == NULL || pb == NULL) 424 if(pc == NULL || packet == NULL || pb == NULL)
443 return; 425 return;
444 bd = (BonjourData*) pc->proto_data; 426 bd = (BonjourData*) pc->proto_data;
445 if(bd == NULL) 427 if(bd == NULL)
446 return; 428 return;
447 429
448 purple_debug_info("bonjour", "xep-si-parse.\n"); 430 purple_debug_info("bonjour", "xep-si-parse.\n");
449 431
450 type = xmlnode_get_attrib(packet, "type"); 432 type = xmlnode_get_attrib(packet, "type");
451 from = pb->name;
452 id = xmlnode_get_attrib(packet, "id"); 433 id = xmlnode_get_attrib(packet, "id");
453 if(type) { 434 if(type) {
454 if(!strcmp(type, "set")){ 435 if(!strcmp(type, "set")) {
455 si = xmlnode_get_child(packet,"si"); 436 const char *profile;
437 xmlnode *si;
438 gboolean parsed_receive = FALSE;
439
440 si = xmlnode_get_child(packet, "si");
441
456 purple_debug_info("bonjour", "si offer Message type - SET.\n"); 442 purple_debug_info("bonjour", "si offer Message type - SET.\n");
457 file = xmlnode_get_child(si, "file"); 443 if (si && (profile = xmlnode_get_attrib(si, "profile"))
458 /**/ 444 && !strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) {
459 filename = xmlnode_get_attrib(file, "name"); 445 const char *filename = NULL, *filesize_str = NULL;
460 if((filesize_str = xmlnode_get_attrib(file, "size"))) 446 int filesize = 0;
461 filesize = atoi(filesize_str); 447 xmlnode *file;
462 bonjour_xfer_receive(pc, id, from, filesize, filename, option); 448
463 } else if(!strcmp(type, "result")){ 449 if ((file = xmlnode_get_child(si, "file"))) {
464 si = xmlnode_get_child(packet,"si"); 450 filename = xmlnode_get_attrib(file, "name");
451 if((filesize_str = xmlnode_get_attrib(file, "size")))
452 filesize = atoi(filesize_str);
453 }
454
455 /* TODO: Make sure that it is advertising a bytestreams transfer */
456
457 bonjour_xfer_receive(pc, id, pb->name, filesize, filename, XEP_BYTESTREAMS);
458
459 parsed_receive = TRUE;
460 }
461
462 if (!parsed_receive) {
463 purple_debug_info("bonjour", "rejecting unrecognized si SET offer.\n");
464 xep_ft_si_reject((BonjourData *)pc->proto_data, id, pb->name, "403", "cancel");
465 /*TODO: Send Cancel (501) */
466 }
467 } else if(!strcmp(type, "result")) {
465 purple_debug_info("bonjour", "si offer Message type - RESULT.\n"); 468 purple_debug_info("bonjour", "si offer Message type - RESULT.\n");
466 xfer = bonjour_si_xfer_find(bd, id, from); 469
467 if(xfer == NULL){ 470 xfer = bonjour_si_xfer_find(bd, id, pb->name);
471
472 if(xfer == NULL) {
468 purple_debug_info("bonjour", "xfer find fail.\n"); 473 purple_debug_info("bonjour", "xfer find fail.\n");
469 xep_ft_si_reject2((BonjourData *)pc->proto_data, from, id); 474 xep_ft_si_reject((BonjourData *)pc->proto_data, id, pb->name, "403", "cancel");
470 } else { 475 } else
471 bonjour_bytestreams_init(xfer); 476 bonjour_bytestreams_init(xfer);
472 } 477
473 } else if(!strcmp(type, "error")){ 478 } else if(!strcmp(type, "error")) {
474 purple_debug_info("bonjour", "si offer Message type - ERROR.\n"); 479 purple_debug_info("bonjour", "si offer Message type - ERROR.\n");
475 xfer = bonjour_si_xfer_find(bd, id, from); 480
476 if(xfer == NULL){ 481 xfer = bonjour_si_xfer_find(bd, id, pb->name);
482
483 if(xfer == NULL)
477 purple_debug_info("bonjour", "xfer find fail.\n"); 484 purple_debug_info("bonjour", "xfer find fail.\n");
478 } else { 485 else
479 purple_xfer_cancel_remote(xfer); 486 purple_xfer_cancel_remote(xfer);
480 } 487 } else
481 } else {
482 purple_debug_info("bonjour", "si offer Message type - Unknown-%d.\n", type); 488 purple_debug_info("bonjour", "si offer Message type - Unknown-%d.\n", type);
483 }
484 } 489 }
485 } 490 }
486 491
487 void 492 void
488 xep_bytestreams_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb) 493 xep_bytestreams_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb)
489 { 494 {
490 const char *type = NULL, *from = NULL, *id = NULL; 495 const char *type = NULL, *from = NULL;
491 xmlnode *query = NULL, *streamhost = NULL; 496 xmlnode *query = NULL, *streamhost = NULL;
492 BonjourData *bd = NULL; 497 BonjourData *bd = NULL;
493 PurpleXfer *xfer = NULL; 498 PurpleXfer *xfer = NULL;
494 XepXfer *xf = NULL; 499 XepXfer *xf = NULL;
495 const char *jid=NULL, *host=NULL, *port=NULL;
496 int portnum; 500 int portnum;
497 501
498 if(pc == NULL || packet == NULL || pb == NULL) 502 if(pc == NULL || packet == NULL || pb == NULL)
499 return; 503 return;
500 504
506 510
507 type = xmlnode_get_attrib(packet, "type"); 511 type = xmlnode_get_attrib(packet, "type");
508 from = pb->name; 512 from = pb->name;
509 query = xmlnode_get_child(packet,"query"); 513 query = xmlnode_get_child(packet,"query");
510 if(type) { 514 if(type) {
511 if(!strcmp(type, "set")){ 515 if(!strcmp(type, "set")) {
516 const char *iq_id, *sid;
517 gboolean found = FALSE;
518
512 purple_debug_info("bonjour", "bytestream offer Message type - SET.\n"); 519 purple_debug_info("bonjour", "bytestream offer Message type - SET.\n");
513 520
514 id = xmlnode_get_attrib(query, "sid"); 521 iq_id = xmlnode_get_attrib(packet, "id");
515 xfer = bonjour_si_xfer_find(bd, id, from); 522
516 523 sid = xmlnode_get_attrib(query, "sid");
517 if(xfer){ 524 xfer = bonjour_si_xfer_find(bd, sid, from);
525
526 if(xfer) {
527 const char *jid, *host, *port;
528
518 xf = (XepXfer*)xfer->data; 529 xf = (XepXfer*)xfer->data;
519 for(streamhost = xmlnode_get_child(query, "streamhost"); 530 for(streamhost = xmlnode_get_child(query, "streamhost");
520 streamhost; 531 streamhost;
521 streamhost = xmlnode_get_next_twin(streamhost)) { 532 streamhost = xmlnode_get_next_twin(streamhost)) {
522 533
524 (host = xmlnode_get_attrib(streamhost, "host")) && 535 (host = xmlnode_get_attrib(streamhost, "host")) &&
525 (port = xmlnode_get_attrib(streamhost, "port")) && 536 (port = xmlnode_get_attrib(streamhost, "port")) &&
526 (portnum = atoi(port))) { 537 (portnum = atoi(port))) {
527 538
528 if(!strcmp(host, xf->buddy_ip)) { 539 if(!strcmp(host, xf->buddy_ip)) {
540 g_free(xf->iq_id);
541 xf->iq_id = g_strdup(iq_id);
529 xf->jid = g_strdup(jid); 542 xf->jid = g_strdup(jid);
530 xf->proxy_host = g_strdup(host); 543 xf->proxy_host = g_strdup(host);
531 xf->proxy_port = portnum; 544 xf->proxy_port = portnum;
532 purple_debug_info("bonjour", "bytestream offer parse" 545 purple_debug_info("bonjour", "bytestream offer parse"
533 "jid=%s host=%s port=%d.\n", jid, host, portnum); 546 "jid=%s host=%s port=%d.\n", jid, host, portnum);
534 bonjour_bytestreams_connect(xfer); 547 bonjour_bytestreams_connect(xfer);
548 found = TRUE;
535 break; 549 break;
536 } 550 }
537
538 } else { 551 } else {
539 purple_debug_info("bonjour", "bytestream offer Message parse error.\n"); 552 purple_debug_info("bonjour", "bytestream offer Message parse error.\n");
540 } 553 }
541 } 554 }
542 } else { 555 } else {
543 556
544 } 557 }
545 558
559 if (!found) {
560 purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");
561
562 if (iq_id)
563 xep_ft_si_reject(bd, iq_id, xfer->who, "404", "cancel");
564 }
565
546 } else { 566 } else {
547 purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%d.\n", type); 567 purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type);
548 } 568 }
549 } 569 }
550 } 570 }
551 571
552 static void 572 static void
555 { 575 {
556 PurpleXfer *xfer = NULL; 576 PurpleXfer *xfer = NULL;
557 XepXfer *xf = NULL; 577 XepXfer *xf = NULL;
558 BonjourData *bd = NULL; 578 BonjourData *bd = NULL;
559 579
560 if(pc == NULL || id == NULL || from == NULL || filename == NULL) 580 if(pc == NULL || id == NULL || from == NULL)
561 return; 581 return;
562 582
563 bd = (BonjourData*) pc->proto_data; 583 bd = (BonjourData*) pc->proto_data;
564 if(bd == NULL) 584 if(bd == NULL)
565 return; 585 return;
591 PurpleXfer *xfer = data; 611 PurpleXfer *xfer = data;
592 XepXfer *xf = NULL; 612 XepXfer *xf = NULL;
593 int acceptfd; 613 int acceptfd;
594 int len = 0; 614 int len = 0;
595 615
596 if(xfer == NULL)
597 return;
598
599 xf = xfer->data; 616 xf = xfer->data;
600 if(xf == NULL) 617 if(xf == NULL)
601 return; 618 return;
602 619
603 purple_debug_info("bonjour", "bonjour_sock5_request_cb - req_state = 0x%x\n", xf->sock5_req_state); 620 purple_debug_info("bonjour", "bonjour_sock5_request_cb - req_state = 0x%x\n", xf->sock5_req_state);
606 case 0x00: 623 case 0x00:
607 acceptfd = accept(source, NULL, 0); 624 acceptfd = accept(source, NULL, 0);
608 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { 625 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
609 626
610 } else if(acceptfd == -1) { 627 } else if(acceptfd == -1) {
611 628 /* TODO: This should cancel the ft */
612 } else { 629 } else {
613 int flags; 630 int flags;
614 631
615 purple_debug_info("bonjour", "Accepted SOCKS5 ft connection - fd=%d\n", acceptfd); 632 purple_debug_info("bonjour", "Accepted SOCKS5 ft connection - fd=%d\n", acceptfd);
616 633
718 xmlnode *query, *streamhost; 735 xmlnode *query, *streamhost;
719 char *port; 736 char *port;
720 const char *next_ip; 737 const char *next_ip;
721 const char *local_ip = NULL; 738 const char *local_ip = NULL;
722 char token [] = ";"; 739 char token [] = ";";
740 BonjourData *bd;
723 741
724 purple_debug_info("bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock); 742 purple_debug_info("bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock);
725 if (sock < 0 || xfer == NULL) { 743 if (sock < 0 || xfer == NULL) {
726 /*purple_xfer_cancel_local(xfer);*/ 744 /*purple_xfer_cancel_local(xfer);*/
727 return; 745 return;
730 xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, 748 xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ,
731 bonjour_sock5_request_cb, xfer); 749 bonjour_sock5_request_cb, xfer);
732 xf = (XepXfer*)xfer->data; 750 xf = (XepXfer*)xfer->data;
733 xf->listen_data = NULL; 751 xf->listen_data = NULL;
734 752
735 iq = xep_iq_new(xf->data, XEP_IQ_SET, xfer->who, xf->sid); 753 bd = xf->data;
754
755 iq = xep_iq_new(bd, XEP_IQ_SET, xfer->who, purple_account_get_username(bd->jabber_data->account), xf->sid);
736 756
737 query = xmlnode_new_child(iq->node, "query"); 757 query = xmlnode_new_child(iq->node, "query");
738 xmlnode_set_namespace(query, "http://jabber.org/protocol/bytestreams"); 758 xmlnode_set_namespace(query, "http://jabber.org/protocol/bytestreams");
739 xmlnode_set_attrib(query, "sid", xf->sid); 759 xmlnode_set_attrib(query, "sid", xf->sid);
740 xmlnode_set_attrib(query, "mode", "tcp"); 760 xmlnode_set_attrib(query, "mode", "tcp");
743 763
744 local_ip = purple_network_get_my_ip_ext2(sock); 764 local_ip = purple_network_get_my_ip_ext2(sock);
745 /* cheat a little here - the intent of the "const" attribute is to make it clear that the string doesn't need to be freed */ 765 /* cheat a little here - the intent of the "const" attribute is to make it clear that the string doesn't need to be freed */
746 next_ip = strtok((char *)local_ip, token); 766 next_ip = strtok((char *)local_ip, token);
747 767
768 port = g_strdup_printf("%hu", xfer->local_port);
748 while(next_ip != NULL) { 769 while(next_ip != NULL) {
749 streamhost = xmlnode_new_child(query, "streamhost"); 770 streamhost = xmlnode_new_child(query, "streamhost");
750 xmlnode_set_attrib(streamhost, "jid", xf->sid); 771 xmlnode_set_attrib(streamhost, "jid", xf->sid);
751 xmlnode_set_attrib(streamhost, "host", next_ip); 772 xmlnode_set_attrib(streamhost, "host", next_ip);
752 port = g_strdup_printf("%hu", xfer->local_port);
753 xmlnode_set_attrib(streamhost, "port", port); 773 xmlnode_set_attrib(streamhost, "port", port);
754 g_free(port);
755 next_ip = strtok(NULL, token); 774 next_ip = strtok(NULL, token);
756 } 775 }
776 g_free(port);
757 777
758 xep_iq_send_and_free(iq); 778 xep_iq_send_and_free(iq);
759 } 779 }
760 780
761 static void 781 static void
779 static void 799 static void
780 bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) 800 bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message)
781 { 801 {
782 PurpleXfer *xfer = data; 802 PurpleXfer *xfer = data;
783 XepXfer *xf = xfer->data; 803 XepXfer *xf = xfer->data;
784 804 XepIq *iq = NULL;
785 if(data == NULL || source < 0) 805 xmlnode *q_node, *tmp_node;
786 return; 806 BonjourData *bd;
807
808 if(data == NULL || source < 0) {
809 xep_ft_si_reject(xf->data, xf->iq_id, xfer->who, "404", "cancel");
810 /* Cancel the connection */
811 purple_xfer_cancel_local(xfer);
812 return;
813 }
814
815 bd = xf->data;
787 816
788 purple_proxy_info_destroy(xf->proxy_info); 817 purple_proxy_info_destroy(xf->proxy_info);
789 xf->proxy_connection = NULL; 818 xf->proxy_connection = NULL;
790 xf->proxy_info = NULL; 819 xf->proxy_info = NULL;
791 /* Here, start the file transfer.*/ 820 /* Here, start the file transfer.*/
821
822 /* Notify Initiator of Connection */
823 iq = xep_iq_new(bd, XEP_IQ_RESULT, xfer->who, purple_account_get_username(bd->jabber_data->account), xf->iq_id);
824 q_node = xmlnode_new_child(iq->node, "query");
825 xmlnode_set_namespace(q_node, "http://jabber.org/protocol/bytestreams");
826 tmp_node = xmlnode_new_child(q_node, "streamhost-used");
827 xmlnode_set_attrib(tmp_node, "jid", xf->jid);
828 xep_iq_send_and_free(iq);
829
792 purple_xfer_start(xfer, source, NULL, -1); 830 purple_xfer_start(xfer, source, NULL, -1);
793 } 831 }
794 832
795 static void 833 static void
796 bonjour_bytestreams_connect(PurpleXfer *xfer) 834 bonjour_bytestreams_connect(PurpleXfer *xfer)
827 xf->proxy_connection = purple_proxy_connect_socks5(NULL, xf->proxy_info, 865 xf->proxy_connection = purple_proxy_connect_socks5(NULL, xf->proxy_info,
828 dstaddr, 0, 866 dstaddr, 0,
829 bonjour_bytestreams_connect_cb, xfer); 867 bonjour_bytestreams_connect_cb, xfer);
830 868
831 if(xf->proxy_connection == NULL) { 869 if(xf->proxy_connection == NULL) {
832 purple_proxy_info_destroy(xf->proxy_info); 870 xep_ft_si_reject(xf->data, xf->iq_id, xfer->who, "404", "cancel");
833 xf->proxy_info = NULL; 871 /* Cancel the connection */
834 } 872 purple_xfer_cancel_local(xfer);
835 } 873 /*purple_proxy_info_destroy(xf->proxy_info);
836 874 xf->proxy_info = NULL;*/
875 }
876 }
877