static void process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info) { MsnSlpCall *slpcall; slpcall = msn_slp_process_msg(slplink, slpmsg); if (slpcall == NULL) { msn_slpmsg_destroy(slpmsg); return; } purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n"); if (msn_p2p_info_require_ack(slpmsg->p2p_info)) { /* Release all the messages and send the ACK */ if (slpcall->wait_for_socket) { /* * Save ack for later because we have to send * a 200 OK message to the previous direct connect * invitation before ACK but the listening socket isn't * created yet. */ purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n"); slpcall->slplink->dc->prev_ack = msn_slpmsg_ack_new(slplink, info); } else if (!slpcall->wasted) { purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n"); msn_slplink_send_ack(slplink, info); msn_slplink_send_queued_slpmsgs(slplink); } } msn_slpmsg_destroy(slpmsg); if (!slpcall->wait_for_socket && slpcall->wasted) msn_slpcall_destroy(slpcall); }
void msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpHeader *header, const char *data, gsize len) { MsnSlpMessage *slpmsg; guint64 offset; PurpleXfer *xfer = NULL; if (header->total_size < header->length) { purple_debug_error("msn", "This can't be good\n"); g_return_if_reached(); } offset = header->offset; if (offset == 0) { slpmsg = msn_slpmsg_new(slplink); slpmsg->id = header->id; slpmsg->session_id = header->session_id; slpmsg->size = header->total_size; slpmsg->flags = header->flags; if (slpmsg->session_id) { if (slpmsg->slpcall == NULL) slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); if (slpmsg->slpcall != NULL) { if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) { xfer = slpmsg->slpcall->xfer; if (xfer != NULL) { slpmsg->ft = TRUE; slpmsg->slpcall->xfer_msg = slpmsg; purple_xfer_ref(xfer); purple_xfer_start(xfer, -1, NULL, 0); if (xfer->data == NULL) { purple_xfer_unref(xfer); msn_slpmsg_destroy(slpmsg); g_return_if_reached(); } else { purple_xfer_unref(xfer); } } } } } if (!slpmsg->ft && slpmsg->size) { slpmsg->buffer = g_try_malloc(slpmsg->size); if (slpmsg->buffer == NULL) { purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n"); msn_slpmsg_destroy(slpmsg); return; } } } else { slpmsg = msn_slplink_message_find(slplink, header->session_id, header->id); if (slpmsg == NULL) { /* Probably the transfer was canceled */ purple_debug_error("msn", "Couldn't find slpmsg\n"); return; } } if (slpmsg->ft) { xfer = slpmsg->slpcall->xfer; slpmsg->slpcall->u.incoming_data = g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len); purple_xfer_prpl_ready(xfer); } else if (slpmsg->size && slpmsg->buffer) { if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size || slpmsg->offset != offset) { purple_debug_error("msn", "Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n", slpmsg->size, offset, len); g_return_if_reached(); } else { memcpy(slpmsg->buffer + offset, data, len); slpmsg->offset += len; } } if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) && (slpmsg->slpcall != NULL)) { slpmsg->slpcall->progress = TRUE; if (slpmsg->slpcall->progress_cb != NULL) { slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size, len, offset); } } #if 0 if (slpmsg->buffer == NULL) return; #endif if (header->offset + header->length >= header->total_size) { /* All the pieces of the slpmsg have been received */ MsnSlpCall *slpcall; slpcall = msn_slp_process_msg(slplink, slpmsg); if (slpcall == NULL) { msn_slpmsg_destroy(slpmsg); return; } purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n"); if (/* !slpcall->wasted && */ slpmsg->flags == 0x100) { #if 0 MsnDirectConn *directconn; directconn = slplink->directconn; if (!directconn->acked) msn_directconn_send_handshake(directconn); #endif } else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 || slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) { /* Release all the messages and send the ACK */ if (slpcall->wait_for_socket) { /* * Save ack for later because we have to send * a 200 OK message to the previous direct connect * invitation before ACK but the listening socket isn't * created yet. */ purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n"); slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, header); } else if (!slpcall->wasted) { purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n"); msn_slplink_send_ack(slplink, header); msn_slplink_send_queued_slpmsgs(slplink); } } msn_slpmsg_destroy(slpmsg); if (!slpcall->wait_for_socket && slpcall->wasted) msn_slpcall_destroy(slpcall); } }
void msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg) { MsnSlpMessage *slpmsg; const char *data; gsize offset; gsize len; #ifdef MSN_DEBUG_SLP msn_slpmsg_show(msg); #endif #ifdef MSN_DEBUG_SLP_FILES debug_msg_to_file(msg, FALSE); #endif if (msg->msnslp_header.total_size < msg->msnslp_header.length) { purple_debug_error("msn", "This can't be good\n"); g_return_if_reached(); } slpmsg = NULL; data = msn_message_get_bin_data(msg, &len); /* OVERHEAD! if (msg->msnslp_header.length < msg->msnslp_header.total_size) */ offset = msg->msnslp_header.offset; if (offset == 0) { slpmsg = msn_slpmsg_new(slplink); slpmsg->id = msg->msnslp_header.id; slpmsg->session_id = msg->msnslp_header.session_id; slpmsg->size = msg->msnslp_header.total_size; slpmsg->flags = msg->msnslp_header.flags; if (slpmsg->session_id) { if (slpmsg->slpcall == NULL) slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); if (slpmsg->slpcall != NULL) { if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { PurpleXfer *xfer; xfer = slpmsg->slpcall->xfer; if (xfer != NULL) { purple_xfer_ref(xfer); purple_xfer_start(xfer, 0, NULL, 0); if (xfer->data == NULL) { purple_xfer_unref(xfer); return; } else { purple_xfer_unref(xfer); slpmsg->fp = xfer->dest_fp; xfer->dest_fp = NULL; /* Disable double fclose() */ } } } } } if (!slpmsg->fp && slpmsg->size) { slpmsg->buffer = g_try_malloc(slpmsg->size); if (slpmsg->buffer == NULL) { purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n"); return; } } } else { slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id); } if (slpmsg == NULL) { /* Probably the transfer was canceled */ purple_debug_error("msn", "Couldn't find slpmsg\n"); return; } if (slpmsg->fp) { /* fseek(slpmsg->fp, offset, SEEK_SET); */ len = fwrite(data, 1, len, slpmsg->fp); } else if (slpmsg->size) { if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size) { purple_debug_error("msn", "Oversized slpmsg\n"); g_return_if_reached(); } else memcpy(slpmsg->buffer + offset, data, len); } if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) && (slpmsg->slpcall != NULL)) { slpmsg->slpcall->progress = TRUE; if (slpmsg->slpcall->progress_cb != NULL) { slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size, len, offset); } } #if 0 if (slpmsg->buffer == NULL) return; #endif if (msg->msnslp_header.offset + msg->msnslp_header.length >= msg->msnslp_header.total_size) { /* All the pieces of the slpmsg have been received */ MsnSlpCall *slpcall; slpcall = msn_slp_process_msg(slplink, slpmsg); if (slpmsg->flags == 0x100) { MsnDirectConn *directconn; directconn = slplink->directconn; if (!directconn->acked) msn_directconn_send_handshake(directconn); } else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { /* Release all the messages and send the ACK */ msn_slplink_send_ack(slplink, msg); msn_slplink_unleash(slplink); } msn_slpmsg_destroy(slpmsg); if (slpcall != NULL && slpcall->wasted) msn_slp_call_destroy(slpcall); } }