Mercurial > pidgin
comparison libpurple/protocols/bonjour/jabber.c @ 18761:316be7e715c6
Update the Bonjour prpl to use libxml explicitly instead of the xml_node stuff. This allows us to deal with partial reads. I also fixed issues related to starting conversations with iChat and a couple other things. Fixes #2022,#1652
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Tue, 31 Jul 2007 23:23:25 +0000 |
parents | b981d3c39d0b |
children | 6e3cd5e80420 |
comparison
equal
deleted
inserted
replaced
18760:bf47d0401a96 | 18761:316be7e715c6 |
---|---|
40 #include "debug.h" | 40 #include "debug.h" |
41 #include "notify.h" | 41 #include "notify.h" |
42 #include "util.h" | 42 #include "util.h" |
43 | 43 |
44 #include "jabber.h" | 44 #include "jabber.h" |
45 #include "parser.h" | |
45 #include "bonjour.h" | 46 #include "bonjour.h" |
46 #include "buddy.h" | 47 #include "buddy.h" |
47 | 48 |
48 #define STREAM_END "</stream:stream>" | 49 #define STREAM_END "</stream:stream>" |
49 /* TODO: specify version='1.0' and send stream features */ | 50 /* TODO: specify version='1.0' and send stream features */ |
107 | 108 |
108 return "1"; | 109 return "1"; |
109 } | 110 } |
110 | 111 |
111 static void | 112 static void |
112 _jabber_parse_and_write_message_to_ui(xmlnode *message_node, PurpleConnection *connection, PurpleBuddy *pb) | 113 _jabber_parse_and_write_message_to_ui(xmlnode *message_node, PurpleBuddy *pb) |
113 { | 114 { |
114 xmlnode *body_node, *html_node, *events_node; | 115 xmlnode *body_node, *html_node, *events_node; |
116 PurpleConnection *gc = pb->account->gc; | |
115 char *body, *html_body = NULL; | 117 char *body, *html_body = NULL; |
116 const char *ichat_balloon_color = NULL; | 118 const char *ichat_balloon_color = NULL; |
117 const char *ichat_text_color = NULL; | 119 const char *ichat_text_color = NULL; |
118 const char *font_face = NULL; | 120 const char *font_face = NULL; |
119 const char *font_size = NULL; | 121 const char *font_size = NULL; |
184 } | 186 } |
185 | 187 |
186 /* TODO: Should we do something with "composing_event" here? */ | 188 /* TODO: Should we do something with "composing_event" here? */ |
187 | 189 |
188 /* Send the message to the UI */ | 190 /* Send the message to the UI */ |
189 serv_got_im(connection, pb->name, body, 0, time(NULL)); | 191 serv_got_im(gc, pb->name, body, 0, time(NULL)); |
190 | 192 |
191 g_free(body); | 193 g_free(body); |
192 g_free(html_body); | 194 g_free(html_body); |
193 } | 195 } |
194 | 196 |
216 if ((bb != NULL) && (g_ascii_strcasecmp(bb->ip, cbba->address) == 0)) | 218 if ((bb != NULL) && (g_ascii_strcasecmp(bb->ip, cbba->address) == 0)) |
217 *(cbba->pb) = pb; | 219 *(cbba->pb) = pb; |
218 } | 220 } |
219 } | 221 } |
220 | 222 |
221 static gint | |
222 _read_data(gint socket, char **message) | |
223 { | |
224 GString *data = g_string_new(""); | |
225 char partial_data[512]; | |
226 gint total_message_length = 0; | |
227 gint partial_message_length = 0; | |
228 | |
229 /* Read chunks of 512 bytes till the end of the data */ | |
230 while ((partial_message_length = recv(socket, partial_data, 512, 0)) > 0) | |
231 { | |
232 g_string_append_len(data, partial_data, partial_message_length); | |
233 total_message_length += partial_message_length; | |
234 } | |
235 | |
236 if (partial_message_length == -1) | |
237 { | |
238 if (errno != EAGAIN) | |
239 purple_debug_warning("bonjour", "receive error: %s\n", strerror(errno)); | |
240 if (total_message_length == 0) { | |
241 return -1; | |
242 } | |
243 } | |
244 | |
245 *message = g_string_free(data, FALSE); | |
246 if (total_message_length != 0) | |
247 purple_debug_info("bonjour", "Receive: -%s- %d bytes\n", *message, total_message_length); | |
248 | |
249 return total_message_length; | |
250 } | |
251 | |
252 static void | 223 static void |
253 _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) | 224 _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) |
254 { | 225 { |
255 PurpleBuddy *pb = data; | 226 PurpleBuddy *pb = data; |
256 BonjourBuddy *bb = pb->proto_data; | 227 BonjourBuddy *bb = pb->proto_data; |
301 BonjourJabberConversation *bconv = bb->conversation; | 272 BonjourJabberConversation *bconv = bb->conversation; |
302 | 273 |
303 /* If we're not ready to actually send, append it to the buffer */ | 274 /* If we're not ready to actually send, append it to the buffer */ |
304 if (bconv->tx_handler != -1 | 275 if (bconv->tx_handler != -1 |
305 || bconv->connect_data != NULL | 276 || bconv->connect_data != NULL |
306 || !bconv->stream_started | 277 || !bconv->sent_stream_start |
278 || !bconv->recv_stream_start | |
307 || purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { | 279 || purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { |
308 ret = -1; | 280 ret = -1; |
309 errno = EAGAIN; | 281 errno = EAGAIN; |
310 } else { | 282 } else { |
311 ret = send(bconv->socket, message, len, 0); | 283 ret = send(bconv->socket, message, len, 0); |
339 } | 311 } |
340 | 312 |
341 return ret; | 313 return ret; |
342 } | 314 } |
343 | 315 |
316 void bonjour_jabber_process_packet(PurpleBuddy *pb, xmlnode *packet) { | |
317 if (!strcmp(packet->name, "message")) | |
318 _jabber_parse_and_write_message_to_ui(packet, pb); | |
319 else | |
320 purple_debug_warning("bonjour", "Unknown packet: %s\n", | |
321 packet->name); | |
322 } | |
323 | |
324 | |
344 static void | 325 static void |
345 _client_socket_handler(gpointer data, gint socket, PurpleInputCondition condition) | 326 _client_socket_handler(gpointer data, gint socket, PurpleInputCondition condition) |
346 { | 327 { |
347 char *message = NULL; | |
348 gint message_length; | |
349 PurpleBuddy *pb = data; | 328 PurpleBuddy *pb = data; |
350 PurpleAccount *account = pb->account; | 329 gint len, message_length; |
351 BonjourBuddy *bb = pb->proto_data; | 330 static char message[4096]; |
352 gboolean closed_conversation = FALSE; | 331 |
332 /*TODO: use a static buffer */ | |
353 | 333 |
354 /* Read the data from the socket */ | 334 /* Read the data from the socket */ |
355 if ((message_length = _read_data(socket, &message)) == -1) { | 335 if ((len = recv(socket, message, sizeof(message) - 1, 0)) == -1) { |
356 /* There have been an error reading from the socket */ | 336 /* There have been an error reading from the socket */ |
357 if (errno != EAGAIN) { | 337 if (errno != EAGAIN) { |
338 BonjourBuddy *bb = pb->proto_data; | |
339 | |
340 purple_debug_warning("bonjour", "receive error: %s\n", strerror(errno)); | |
341 | |
358 bonjour_jabber_close_conversation(bb->conversation); | 342 bonjour_jabber_close_conversation(bb->conversation); |
359 bb->conversation = NULL; | 343 bb->conversation = NULL; |
360 | 344 |
361 /* I guess we really don't need to notify the user. | 345 /* I guess we really don't need to notify the user. |
362 * If they try to send another message it'll reconnect */ | 346 * If they try to send another message it'll reconnect */ |
363 } | 347 } |
364 return; | 348 return; |
365 } else if (message_length == 0) { /* The other end has closed the socket */ | 349 } else if (len == 0) { /* The other end has closed the socket */ |
366 closed_conversation = TRUE; | 350 purple_debug_warning("bonjour", "Connection closed (without stream end) by %s.\n", pb->name); |
351 bonjour_jabber_stream_ended(pb); | |
352 return; | |
367 } else { | 353 } else { |
354 message_length = len; | |
368 message[message_length] = '\0'; | 355 message[message_length] = '\0'; |
369 | 356 |
370 while (g_ascii_iscntrl(message[message_length - 1])) { | 357 while (message_length > 0 && g_ascii_iscntrl(message[message_length - 1])) { |
371 message[message_length - 1] = '\0'; | 358 message[message_length - 1] = '\0'; |
372 message_length--; | 359 message_length--; |
373 } | 360 } |
374 } | 361 } |
375 | 362 |
376 /* | 363 purple_debug_info("bonjour", "Receive: -%s- %d bytes\n", message, len); |
377 * Check that this is not the end of the conversation. This is | 364 |
378 * using a magic string, but xmlnode won't play nice when just | 365 bonjour_parser_process(pb, message, message_length); |
379 * parsing an end tag | 366 } |
380 */ | 367 |
381 if (closed_conversation || purple_str_has_prefix(message, STREAM_END)) { | 368 void bonjour_jabber_stream_ended(PurpleBuddy *pb) { |
382 PurpleConversation *conv; | 369 BonjourBuddy *bb = pb->proto_data; |
383 | 370 PurpleConversation *conv; |
384 /* Close the socket, clear the watcher and free memory */ | 371 |
385 bonjour_jabber_close_conversation(bb->conversation); | 372 purple_debug_info("bonjour", "Recieved conversation close notification from %s.\n", pb->name); |
386 bb->conversation = NULL; | 373 |
387 | 374 /* Close the socket, clear the watcher and free memory */ |
388 /* Inform the user that the conversation has been closed */ | 375 bonjour_jabber_close_conversation(bb->conversation); |
389 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, account); | 376 bb->conversation = NULL; |
390 if (conv != NULL) { | 377 |
391 char *tmp = g_strdup_printf(_("%s has closed the conversation."), pb->name); | 378 /* Inform the user that the conversation has been closed */ |
392 purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); | 379 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, pb->account); |
393 g_free(tmp); | 380 if (conv != NULL) { |
394 } | 381 char *tmp = g_strdup_printf(_("%s has closed the conversation."), pb->name); |
395 } else { | 382 purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); |
396 xmlnode *message_node; | 383 g_free(tmp); |
397 | 384 } |
398 /* Parse the message into an XMLnode for analysis */ | 385 } |
399 message_node = xmlnode_from_str(message, strlen(message)); | 386 |
400 | 387 void bonjour_jabber_stream_started(PurpleBuddy *pb) { |
401 if (message_node != NULL) { | 388 BonjourBuddy *bb = pb->proto_data; |
402 /* Parse the message to get the data and send to the ui */ | 389 BonjourJabberConversation *bconv = bb->conversation; |
403 _jabber_parse_and_write_message_to_ui(message_node, account->gc, pb); | 390 |
404 xmlnode_free(message_node); | 391 /* If the stream has been completely started, we can start doing stuff */ |
405 } else { | 392 if (bconv->sent_stream_start && bconv->recv_stream_start && purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { |
406 /* TODO: Deal with receiving only a partial message */ | 393 /* Watch for when we can write the buffered messages */ |
407 } | 394 bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, |
408 } | 395 _send_data_write_cb, pb); |
409 | 396 /* We can probably write the data right now. */ |
410 g_free(message); | 397 _send_data_write_cb(pb, bconv->socket, PURPLE_INPUT_WRITE); |
398 } | |
399 | |
411 } | 400 } |
412 | 401 |
413 struct _stream_start_data { | 402 struct _stream_start_data { |
414 char *msg; | 403 char *msg; |
415 PurpleInputFunction tx_handler_cb; | |
416 }; | 404 }; |
405 | |
417 | 406 |
418 static void | 407 static void |
419 _start_stream(gpointer data, gint source, PurpleInputCondition condition) | 408 _start_stream(gpointer data, gint source, PurpleInputCondition condition) |
420 { | 409 { |
421 PurpleBuddy *pb = data; | 410 PurpleBuddy *pb = data; |
422 BonjourBuddy *bb = pb->proto_data; | 411 BonjourBuddy *bb = pb->proto_data; |
423 struct _stream_start_data *ss = bb->conversation->stream_data; | 412 BonjourJabberConversation *bconv = bb->conversation; |
413 struct _stream_start_data *ss = bconv->stream_data; | |
424 int len, ret; | 414 int len, ret; |
425 | 415 |
426 len = strlen(ss->msg); | 416 len = strlen(ss->msg); |
427 | 417 |
428 /* Start Stream */ | 418 /* Start Stream */ |
441 if (conv != NULL) | 431 if (conv != NULL) |
442 purple_conversation_write(conv, NULL, | 432 purple_conversation_write(conv, NULL, |
443 _("Unable to send the message, the conversation couldn't be started."), | 433 _("Unable to send the message, the conversation couldn't be started."), |
444 PURPLE_MESSAGE_SYSTEM, time(NULL)); | 434 PURPLE_MESSAGE_SYSTEM, time(NULL)); |
445 | 435 |
446 bonjour_jabber_close_conversation(bb->conversation); | 436 bonjour_jabber_close_conversation(bconv); |
447 bb->conversation = NULL; | 437 bb->conversation = NULL; |
448 | 438 |
449 return; | 439 return; |
450 } | 440 } |
451 | 441 |
455 g_free(ss->msg); | 445 g_free(ss->msg); |
456 ss->msg = tmp; | 446 ss->msg = tmp; |
457 return; | 447 return; |
458 } | 448 } |
459 | 449 |
460 /* Stream started; process the send buffer if there is one*/ | |
461 purple_input_remove(bb->conversation->tx_handler); | |
462 bb->conversation->tx_handler= -1; | |
463 | |
464 bb->conversation->stream_started = TRUE; | |
465 | |
466 g_free(ss->msg); | 450 g_free(ss->msg); |
467 g_free(ss); | 451 g_free(ss); |
468 bb->conversation->stream_data = NULL; | 452 bconv->stream_data = NULL; |
469 | 453 |
470 if (ss->tx_handler_cb) { | 454 /* Stream started; process the send buffer if there is one */ |
471 bb->conversation->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, | 455 purple_input_remove(bconv->tx_handler); |
472 ss->tx_handler_cb, pb); | 456 bconv->tx_handler= -1; |
473 /* We can probably write the data now. */ | 457 bconv->sent_stream_start = TRUE; |
474 (ss->tx_handler_cb)(pb, source, PURPLE_INPUT_WRITE); | 458 |
475 } | 459 bonjour_jabber_stream_started(pb); |
460 | |
461 } | |
462 | |
463 static gboolean bonjour_jabber_stream_init(PurpleBuddy *pb, int client_socket) | |
464 { | |
465 int ret, len; | |
466 char *stream_start; | |
467 BonjourBuddy *bb = pb->proto_data; | |
468 | |
469 stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), | |
470 purple_buddy_get_name(pb)); | |
471 len = strlen(stream_start); | |
472 | |
473 /* Start the stream */ | |
474 ret = send(client_socket, stream_start, len, 0); | |
475 | |
476 if (ret == -1 && errno == EAGAIN) | |
477 ret = 0; | |
478 else if (ret <= 0) { | |
479 const char *err = strerror(errno); | |
480 | |
481 purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n", | |
482 purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)"); | |
483 | |
484 close(client_socket); | |
485 g_free(stream_start); | |
486 | |
487 return FALSE; | |
488 } | |
489 | |
490 /* This is unlikely to happen */ | |
491 if (ret < len) { | |
492 struct _stream_start_data *ss = g_new(struct _stream_start_data, 1); | |
493 ss->msg = g_strdup(stream_start + ret); | |
494 bb->conversation->stream_data = ss; | |
495 /* Finish sending the stream start */ | |
496 bb->conversation->tx_handler = purple_input_add(client_socket, | |
497 PURPLE_INPUT_WRITE, _start_stream, pb); | |
498 } else | |
499 bb->conversation->sent_stream_start = TRUE; | |
500 | |
501 g_free(stream_start); | |
502 | |
503 /* setup the parser fresh for each stream */ | |
504 bonjour_parser_setup(bb->conversation); | |
505 | |
506 bb->conversation->socket = client_socket; | |
507 bb->conversation->rx_handler = purple_input_add(client_socket, | |
508 PURPLE_INPUT_READ, _client_socket_handler, pb); | |
509 | |
510 return TRUE; | |
476 } | 511 } |
477 | 512 |
478 static void | 513 static void |
479 _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition condition) | 514 _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition condition) |
480 { | 515 { |
496 | 531 |
497 fcntl(client_socket, F_SETFL, O_NONBLOCK); | 532 fcntl(client_socket, F_SETFL, O_NONBLOCK); |
498 | 533 |
499 /* Look for the buddy that has opened the conversation and fill information */ | 534 /* Look for the buddy that has opened the conversation and fill information */ |
500 address_text = inet_ntoa(their_addr.sin_addr); | 535 address_text = inet_ntoa(their_addr.sin_addr); |
536 purple_debug_info("bonjour", "Received incoming connection from %s\n.", address_text); | |
501 cbba = g_new0(struct _check_buddy_by_address_t, 1); | 537 cbba = g_new0(struct _check_buddy_by_address_t, 1); |
502 cbba->address = address_text; | 538 cbba->address = address_text; |
503 cbba->pb = &pb; | 539 cbba->pb = &pb; |
504 cbba->bj = data; | 540 cbba->bj = data; |
505 g_hash_table_foreach(bl->buddies, _check_buddy_by_address, cbba); | 541 g_hash_table_foreach(bl->buddies, _check_buddy_by_address, cbba); |
513 bb = pb->proto_data; | 549 bb = pb->proto_data; |
514 | 550 |
515 /* Check if the conversation has been previously started */ | 551 /* Check if the conversation has been previously started */ |
516 if (bb->conversation == NULL) | 552 if (bb->conversation == NULL) |
517 { | 553 { |
518 int ret, len; | 554 bb->conversation = bonjour_jabber_conv_new(); |
519 char *stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), | 555 |
520 purple_buddy_get_name(pb)); | 556 if (!bonjour_jabber_stream_init(pb, client_socket)) { |
521 | |
522 len = strlen(stream_start); | |
523 | |
524 /* Start the stream */ | |
525 ret = send(client_socket, stream_start, len, 0); | |
526 | |
527 if (ret == -1 && errno == EAGAIN) | |
528 ret = 0; | |
529 else if (ret <= 0) { | |
530 const char *err = strerror(errno); | |
531 | |
532 purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n", | |
533 purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)"); | |
534 | |
535 close(client_socket); | 557 close(client_socket); |
536 g_free(stream_start); | |
537 | |
538 return; | 558 return; |
539 } | 559 } |
540 | 560 |
541 bb->conversation = bonjour_jabber_conv_new(); | |
542 bb->conversation->socket = client_socket; | |
543 bb->conversation->rx_handler = purple_input_add(client_socket, | |
544 PURPLE_INPUT_READ, _client_socket_handler, pb); | |
545 | |
546 /* This is unlikely to happen */ | |
547 if (ret < len) { | |
548 struct _stream_start_data *ss = g_new(struct _stream_start_data, 1); | |
549 ss->msg = g_strdup(stream_start + ret); | |
550 ss->tx_handler_cb = NULL; /* We have nothing to write yet */ | |
551 bb->conversation->stream_data = ss; | |
552 /* Finish sending the stream start */ | |
553 bb->conversation->tx_handler = purple_input_add(client_socket, | |
554 PURPLE_INPUT_WRITE, _start_stream, pb); | |
555 } else { | |
556 bb->conversation->stream_started = TRUE; | |
557 } | |
558 | |
559 g_free(stream_start); | |
560 } else { | 561 } else { |
562 purple_debug_warning("bonjour", "Ignoring incoming connection because an existing connection exists.\n"); | |
561 close(client_socket); | 563 close(client_socket); |
562 } | 564 } |
563 } | 565 } |
564 | 566 |
565 gint | 567 gint |
637 static void | 639 static void |
638 _connected_to_buddy(gpointer data, gint source, const gchar *error) | 640 _connected_to_buddy(gpointer data, gint source, const gchar *error) |
639 { | 641 { |
640 PurpleBuddy *pb = data; | 642 PurpleBuddy *pb = data; |
641 BonjourBuddy *bb = pb->proto_data; | 643 BonjourBuddy *bb = pb->proto_data; |
642 int len, ret; | |
643 char *stream_start; | |
644 | 644 |
645 bb->conversation->connect_data = NULL; | 645 bb->conversation->connect_data = NULL; |
646 | 646 |
647 if (source < 0) { | 647 if (source < 0) { |
648 PurpleConversation *conv; | 648 PurpleConversation *conv; |
659 bonjour_jabber_close_conversation(bb->conversation); | 659 bonjour_jabber_close_conversation(bb->conversation); |
660 bb->conversation = NULL; | 660 bb->conversation = NULL; |
661 return; | 661 return; |
662 } | 662 } |
663 | 663 |
664 stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), purple_buddy_get_name(pb)); | 664 if (!bonjour_jabber_stream_init(pb, source)) { |
665 len = strlen(stream_start); | |
666 | |
667 /* Start the stream and send queued messages */ | |
668 ret = send(source, stream_start, len, 0); | |
669 | |
670 if (ret == -1 && errno == EAGAIN) | |
671 ret = 0; | |
672 else if (ret <= 0) { | |
673 const char *err = strerror(errno); | 665 const char *err = strerror(errno); |
674 PurpleConversation *conv; | 666 PurpleConversation *conv; |
675 | 667 |
676 purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n", | 668 purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n", |
677 purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)"); | 669 purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)"); |
683 PURPLE_MESSAGE_SYSTEM, time(NULL)); | 675 PURPLE_MESSAGE_SYSTEM, time(NULL)); |
684 | 676 |
685 close(source); | 677 close(source); |
686 bonjour_jabber_close_conversation(bb->conversation); | 678 bonjour_jabber_close_conversation(bb->conversation); |
687 bb->conversation = NULL; | 679 bb->conversation = NULL; |
688 | 680 return; |
689 g_free(stream_start); | 681 } |
690 | |
691 return; | |
692 } | |
693 | |
694 bb->conversation->socket = source; | |
695 bb->conversation->rx_handler = purple_input_add(source, | |
696 PURPLE_INPUT_READ, _client_socket_handler, pb); | |
697 | |
698 /* This is unlikely to happen */ | |
699 if (ret < len) { | |
700 struct _stream_start_data *ss = g_new(struct _stream_start_data, 1); | |
701 ss->msg = g_strdup(stream_start + ret); | |
702 ss->tx_handler_cb = _send_data_write_cb; | |
703 bb->conversation->stream_data = ss; | |
704 /* Finish sending the stream start */ | |
705 bb->conversation->tx_handler = purple_input_add(source, | |
706 PURPLE_INPUT_WRITE, _start_stream, pb); | |
707 } | |
708 /* Process the send buffer */ | |
709 else { | |
710 bb->conversation->stream_started = TRUE; | |
711 /* Watch for when we can write the buffered messages */ | |
712 bb->conversation->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, | |
713 _send_data_write_cb, pb); | |
714 /* We can probably write the data now. */ | |
715 _send_data_write_cb(pb, source, PURPLE_INPUT_WRITE); | |
716 } | |
717 | |
718 g_free(stream_start); | |
719 } | 682 } |
720 | 683 |
721 int | 684 int |
722 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) | 685 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) |
723 { | 686 { |
807 if (bconv != NULL) | 770 if (bconv != NULL) |
808 { | 771 { |
809 /* Close the socket and remove the watcher */ | 772 /* Close the socket and remove the watcher */ |
810 if (bconv->socket >= 0) { | 773 if (bconv->socket >= 0) { |
811 /* Send the end of the stream to the other end of the conversation */ | 774 /* Send the end of the stream to the other end of the conversation */ |
812 if (bconv->stream_started) | 775 if (bconv->sent_stream_start) |
813 send(bconv->socket, STREAM_END, strlen(STREAM_END), 0); | 776 send(bconv->socket, STREAM_END, strlen(STREAM_END), 0); |
814 /* TODO: We're really supposed to wait for "</stream:stream>" before closing the socket */ | 777 /* TODO: We're really supposed to wait for "</stream:stream>" before closing the socket */ |
815 close(bconv->socket); | 778 close(bconv->socket); |
816 } | 779 } |
817 if (bconv->rx_handler != -1) | 780 if (bconv->rx_handler != -1) |
826 if (bconv->stream_data != NULL) { | 789 if (bconv->stream_data != NULL) { |
827 struct _stream_start_data *ss = bconv->stream_data; | 790 struct _stream_start_data *ss = bconv->stream_data; |
828 g_free(ss->msg); | 791 g_free(ss->msg); |
829 g_free(ss); | 792 g_free(ss); |
830 } | 793 } |
794 | |
795 if (bconv->context != NULL) | |
796 bonjour_parser_setup(bconv); | |
797 | |
831 g_free(bconv); | 798 g_free(bconv); |
832 } | 799 } |
833 } | 800 } |
834 | 801 |
835 void | 802 void |