static void msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond) { MsnDirectConn *dc = data; MsnDirectConnPacket *p; int bytes_to_send; int bytes_sent; g_return_if_fail(dc != NULL); g_return_if_fail(fd != -1); if (g_queue_is_empty(dc->out_queue)) { if (dc->send_handle != 0) { purple_input_remove(dc->send_handle); dc->send_handle = 0; } return; } p = g_queue_peek_head(dc->out_queue); if (dc->msg_pos < 0) { /* First we send the length of the packet */ guint32 len = GUINT32_TO_LE(p->length); bytes_sent = send(fd, &len, 4, 0); if (bytes_sent < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) return; purple_debug_warning("msn", "msn_dc_send_cb: send error\n"); msn_dc_destroy(dc); return; } dc->msg_pos = 0; } bytes_to_send = p->length - dc->msg_pos; bytes_sent = send(fd, p->data + dc->msg_pos, bytes_to_send, 0); if (bytes_sent < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) return; purple_debug_warning("msn", "msn_dc_send_cb: send error\n"); msn_dc_destroy(dc); return; } dc->progress = TRUE; dc->msg_pos += bytes_sent; if (dc->msg_pos == p->length) { if (p->sent_cb != NULL) p->sent_cb(p); g_queue_pop_head(dc->out_queue); msn_dc_destroy_packet(p); dc->msg_pos = -1; } }
void msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall) { /* if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED) msn_dc_unref(slplink->dc); */ slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall); /* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT. * If nothing else is using it then this might cause swboard to be * destroyed. */ if (slplink->slp_calls == NULL && slplink->swboard != NULL) { slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT); slplink->swboard = NULL; } /* The slplink has no slpcalls in it, release it from the DC. */ if (slplink->slp_calls == NULL && slplink->dc != NULL) { slplink->dc->slplink = NULL; msn_dc_destroy(slplink->dc); slplink->dc = NULL; } }
void msn_dc_fallback_to_sb(MsnDirectConn *dc) { MsnSlpLink *slplink; MsnSlpCall *slpcall; GQueue *queue = NULL; purple_debug_info("msn", "msn_dc_fallback_to_sb %p\n", dc); g_return_if_fail(dc != NULL); slpcall = dc->slpcall; slplink = msn_slplink_ref(dc->slplink); if (slpcall && !g_queue_is_empty(dc->out_queue)) { queue = dc->out_queue; dc->out_queue = NULL; } msn_dc_destroy(dc); if (slpcall) { msn_slpcall_session_init(slpcall); if (queue) { while (!g_queue_is_empty(queue)) { MsnDirectConnPacket *p = g_queue_pop_head(queue); msn_slplink_send_msgpart(slplink, (MsnSlpMessage*)p->part->ack_data); msn_dc_destroy_packet(p); } g_queue_free(queue); } } msn_slplink_unref(slplink); }
void msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall) { /* if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED) msn_dc_unref(slplink->dc); */ slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall); /* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT. * If nothing else is using it then this might cause swboard to be * destroyed. */ if (slplink->slp_calls == NULL && slplink->swboard != NULL) { slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT); slplink->swboard = NULL; } if (slplink->dc != NULL) { if ((slplink->dc->state != DC_STATE_ESTABLISHED && slplink->dc->slpcall == slpcall) || (slplink->slp_calls == NULL)) { /* The DC is not established and its corresponding slpcall is dead, * or the slplink has no slpcalls in it and no longer needs the DC. */ slplink->dc->slplink = NULL; msn_dc_destroy(slplink->dc); slplink->dc = NULL; } } }
static void msn_slplink_destroy(MsnSlpLink *slplink) { MsnSession *session; if (purple_debug_is_verbose()) purple_debug_info("msn", "slplink_destroy: slplink(%p)\n", slplink); if (slplink->swboard != NULL) { slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); slplink->swboard = NULL; } session = slplink->session; if (slplink->dc != NULL) { slplink->dc->slplink = NULL; msn_dc_destroy(slplink->dc); slplink->dc = NULL; } while (slplink->slp_calls != NULL) msn_slpcall_destroy(slplink->slp_calls->data); g_queue_free(slplink->slp_msg_queue); session->slplinks = g_list_remove(session->slplinks, slplink); g_free(slplink->remote_user); g_free(slplink); }
static gboolean msn_dc_timeout(gpointer data) { MsnDirectConn *dc = data; g_return_val_if_fail(dc != NULL, FALSE); if (dc->progress) { dc->progress = FALSE; return TRUE; } else { dc->timeout_handle = 0; msn_dc_destroy(dc); return FALSE; } }
static void msn_dc_recv_cb(gpointer data, gint fd, PurpleInputCondition cond) { MsnDirectConn *dc; int free_buf_space; int bytes_received; guint32 packet_length; g_return_if_fail(data != NULL); g_return_if_fail(fd != -1); dc = data; free_buf_space = dc->in_size - dc->in_pos; bytes_received = recv(fd, dc->in_buffer + dc->in_pos, free_buf_space, 0); if (bytes_received < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) return; purple_debug_warning("msn", "msn_dc_recv_cb: recv error\n"); if(dc->state != DC_STATE_ESTABLISHED) msn_dc_fallback_to_sb(dc); else msn_dc_destroy(dc); return; } else if (bytes_received == 0) { /* EOF. Remote side closed connection. */ purple_debug_info("msn", "msn_dc_recv_cb: recv EOF\n"); if(dc->state != DC_STATE_ESTABLISHED) msn_dc_fallback_to_sb(dc); else msn_dc_destroy(dc); return; } dc->progress = TRUE; dc->in_pos += bytes_received; /* Wait for packet length */ while (dc->in_pos >= 4) { packet_length = GUINT32_FROM_LE(*((guint32*)dc->in_buffer)); if (packet_length > DC_MAX_PACKET_SIZE) { /* Oversized packet */ purple_debug_warning("msn", "msn_dc_recv_cb: oversized packet received\n"); return; } /* Wait for the whole packet to arrive */ if (dc->in_pos < 4 + packet_length) return; switch (msn_dc_process_packet(dc, packet_length)) { case DC_PROCESS_CLOSE: return; case DC_PROCESS_FALLBACK: purple_debug_warning("msn", "msn_dc_recv_cb: packet processing error, fall back to SB\n"); msn_dc_fallback_to_sb(dc); return; } if (dc->in_pos > packet_length + 4) { g_memmove(dc->in_buffer, dc->in_buffer + 4 + packet_length, dc->in_pos - packet_length - 4); } dc->in_pos -= packet_length + 4; } }