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); } }
void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) { MsnMessage *msg; long long real_size; size_t len = 0; /* Maybe we will want to create a new msg for this slpmsg instead of * reusing the same one all the time. */ msg = slpmsg->msg; real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; if (slpmsg->offset < real_size) { if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) { len = MIN(1202, slpmsg->slpcall->u.outgoing.len); msn_message_set_bin_data(msg, slpmsg->slpcall->u.outgoing.data, len); } else { len = slpmsg->size - slpmsg->offset; if (len > 1202) len = 1202; msn_message_set_bin_data(msg, slpmsg->buffer + slpmsg->offset, len); } msg->msnslp_header.offset = slpmsg->offset; msg->msnslp_header.length = len; } if (purple_debug_is_verbose()) msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body); #ifdef MSN_DEBUG_SLP_FILES debug_msg_to_file(msg, TRUE); #endif slpmsg->msgs = g_list_append(slpmsg->msgs, msn_message_ref(msg)); msn_slplink_send_msg(slplink, msg); 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, slpmsg->offset); } } /* slpmsg->offset += len; */ }
void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) { MsnMessage *msg; long long real_size; size_t len = 0; /* Maybe we will want to create a new msg for this slpmsg instead of * reusing the same one all the time. */ msg = slpmsg->msg; real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; if (slpmsg->offset < real_size) { if (slpmsg->fp) { char data[1202]; len = fread(data, 1, sizeof(data), slpmsg->fp); msn_message_set_bin_data(msg, data, len); } else { len = slpmsg->size - slpmsg->offset; if (len > 1202) len = 1202; msn_message_set_bin_data(msg, slpmsg->buffer + slpmsg->offset, len); } msg->msnslp_header.offset = slpmsg->offset; msg->msnslp_header.length = len; } #ifdef MSN_DEBUG_SLP msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body); #endif #ifdef MSN_DEBUG_SLP_FILES debug_msg_to_file(msg, TRUE); #endif slpmsg->msgs = g_list_append(slpmsg->msgs, msg); msn_slplink_send_msg(slplink, msg); 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, slpmsg->offset); } } /* slpmsg->offset += len; */ }