static void _start_stream(gpointer data, gint source, PurpleInputCondition condition) { BonjourJabberConversation *bconv = data; struct _stream_start_data *ss = bconv->stream_data; int len, ret; len = strlen(ss->msg); /* Start Stream */ ret = send(source, ss->msg, len, 0); if (ret == -1 && errno == EAGAIN) return; else if (ret <= 0) { const char *err = g_strerror(errno); PurpleConversation *conv; const char *bname = bconv->buddy_name; BonjourBuddy *bb = NULL; if(bconv->pb) { bb = purple_buddy_get_protocol_data(bconv->pb); bname = purple_buddy_get_name(bconv->pb); } purple_debug_error("bonjour", "Error starting stream with buddy %s at %s error: %s\n", bname ? bname : "(unknown)", bconv->ip, err ? err : "(null)"); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bname, bconv->account); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send the message, the conversation couldn't be started."), PURPLE_MESSAGE_SYSTEM, time(NULL)); bonjour_jabber_close_conversation(bconv); if(bb != NULL) bb->conversation = NULL; return; } /* This is EXTREMELY unlikely to happen */ if (ret < len) { char *tmp = g_strdup(ss->msg + ret); g_free(ss->msg); ss->msg = tmp; return; } g_free(ss->msg); g_free(ss); bconv->stream_data = NULL; /* Stream started; process the send buffer if there is one */ purple_input_remove(bconv->tx_handler); bconv->tx_handler = 0; bconv->sent_stream_start = FULLY_SENT; bonjour_jabber_stream_started(bconv); }
static void bonjour_jabber_stream_ended(BonjourJabberConversation *bconv) { /* Inform the user that the conversation has been closed */ BonjourBuddy *bb = NULL; const gchar *name = bconv->pb ? purple_buddy_get_name(bconv->pb) : "(unknown)"; purple_debug_info("bonjour", "Received conversation close notification from %s.\n", name); if(bconv->pb != NULL) bb = purple_buddy_get_protocol_data(bconv->pb); #if 0 if(bconv->pb != NULL) { PurpleConversation *conv; conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bconv->pb->name, bconv->pb->account); if (conv != NULL) { char *tmp = g_strdup_printf(_("%s has closed the conversation."), bconv->pb->name); purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } } #endif /* Close the socket, clear the watcher and free memory */ bonjour_jabber_close_conversation(bconv); if(bb) bb->conversation = NULL; }
/** * Deletes a buddy from memory. */ void bonjour_buddy_delete(BonjourBuddy *buddy) { g_free(buddy->name); g_free(buddy->ip); g_free(buddy->first); g_free(buddy->phsh); g_free(buddy->status); g_free(buddy->email); g_free(buddy->last); g_free(buddy->jid); g_free(buddy->AIM); g_free(buddy->vc); g_free(buddy->msg); g_free(buddy->ext); g_free(buddy->nick); g_free(buddy->node); g_free(buddy->ver); bonjour_jabber_close_conversation(buddy->conversation); buddy->conversation = NULL; /* Clean up any mdns implementation data */ _mdns_delete_buddy(buddy); g_free(buddy); }
static gint _send_data(PurpleBuddy *pb, char *message) { gint ret; int len = strlen(message); BonjourBuddy *bb = purple_buddy_get_protocol_data(pb); BonjourJabberConversation *bconv = bb->conversation; /* If we're not ready to actually send, append it to the buffer */ if (bconv->tx_handler != 0 || bconv->connect_data != NULL || bconv->sent_stream_start != FULLY_SENT || !bconv->recv_stream_start || purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { ret = -1; errno = EAGAIN; } else { ret = send(bconv->socket, message, len, 0); } if (ret == -1 && errno == EAGAIN) ret = 0; else if (ret <= 0) { PurpleConversation *conv; PurpleAccount *account; const char *error = g_strerror(errno); purple_debug_error("bonjour", "Error sending message to buddy %s error: %s\n", purple_buddy_get_name(pb), error ? error : "(null)"); account = purple_buddy_get_account(pb); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send message."), PURPLE_MESSAGE_SYSTEM, time(NULL)); bonjour_jabber_close_conversation(bb->conversation); bb->conversation = NULL; return -1; } if (ret < len) { /* Don't interfere with the stream starting */ if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start && bconv->tx_handler == 0) bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, pb); purple_circ_buffer_append(bconv->tx_buf, message + ret, len - ret); } return ret; }
static void _client_socket_handler(gpointer data, gint socket, PurpleInputCondition condition) { BonjourJabberConversation *bconv = data; gint len, message_length; static char message[4096]; /* Read the data from the socket */ if ((len = recv(socket, message, sizeof(message) - 1, 0)) == -1) { /* There have been an error reading from the socket */ if (errno != EAGAIN) { const char *err = g_strerror(errno); purple_debug_warning("bonjour", "receive error: %s\n", err ? err : "(null)"); bonjour_jabber_close_conversation(bconv); if (bconv->pb != NULL) { BonjourBuddy *bb = purple_buddy_get_protocol_data(bconv->pb); if(bb != NULL) bb->conversation = NULL; } /* I guess we really don't need to notify the user. * If they try to send another message it'll reconnect */ } return; } else if (len == 0) { /* The other end has closed the socket */ const gchar *name = purple_buddy_get_name(bconv->pb); purple_debug_warning("bonjour", "Connection closed (without stream end) by %s.\n", (name) ? name : "(unknown)"); bonjour_jabber_stream_ended(bconv); return; } else { message_length = len; message[message_length] = '\0'; while (message_length > 0 && g_ascii_iscntrl(message[message_length - 1])) { message[message_length - 1] = '\0'; message_length--; } } purple_debug_info("bonjour", "Receive: -%s- %d bytes\n", message, len); bonjour_parser_process(bconv, message, message_length); }
static void _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleBuddy *pb = data; BonjourBuddy *bb = purple_buddy_get_protocol_data(pb); BonjourJabberConversation *bconv = bb->conversation; int ret, writelen; writelen = purple_circ_buffer_get_max_read(bconv->tx_buf); if (writelen == 0) { purple_input_remove(bconv->tx_handler); bconv->tx_handler = 0; return; } ret = send(bconv->socket, bconv->tx_buf->outptr, writelen, 0); if (ret < 0 && errno == EAGAIN) return; else if (ret <= 0) { PurpleConversation *conv = NULL; PurpleAccount *account = NULL; const char *error = g_strerror(errno); purple_debug_error("bonjour", "Error sending message to buddy %s error: %s\n", purple_buddy_get_name(pb), error ? error : "(null)"); account = purple_buddy_get_account(pb); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send message."), PURPLE_MESSAGE_SYSTEM, time(NULL)); bonjour_jabber_close_conversation(bb->conversation); bb->conversation = NULL; return; } purple_circ_buffer_mark_read(bconv->tx_buf, ret); }