static void release_msg(MsnSwitchBoard *swboard, MsnMessage *msg) { MsnCmdProc *cmdproc; MsnTransaction *trans; char *payload; gsize payload_len; char flag; g_return_if_fail(swboard != NULL); g_return_if_fail(msg != NULL); cmdproc = swboard->cmdproc; payload = msn_message_gen_payload(msg, &payload_len); if (purple_debug_is_verbose()) { purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}\n", payload_len); msn_message_show_readable(msg, "SB SEND", FALSE); } flag = msn_message_get_flag(msg); trans = msn_transaction_new(cmdproc, "MSG", "%c %" G_GSIZE_FORMAT, flag, payload_len); /* Data for callbacks */ msn_transaction_set_data(trans, msg); if (flag != 'U') { if (msg->type == MSN_MSG_TEXT) { msg->ack_ref = TRUE; msn_message_ref(msg); swboard->ack_list = g_list_append(swboard->ack_list, msg); msn_transaction_set_timeout_cb(trans, msg_timeout); } else if (msg->type == MSN_MSG_SLP) { msg->ack_ref = TRUE; msn_message_ref(msg); swboard->ack_list = g_list_append(swboard->ack_list, msg); msn_transaction_set_timeout_cb(trans, msg_timeout); #if 0 if (msg->ack_cb != NULL) { msn_transaction_add_cb(trans, "ACK", msg_ack); msn_transaction_add_cb(trans, "NAK", msg_nak); } #endif } } trans->payload = payload; trans->payload_len = payload_len; msg->trans = trans; msn_cmdproc_send_trans(cmdproc, trans); }
static void release_msg(MsnSwitchBoard *swboard, MsnMessage *msg) { MsnCmdProc *cmdproc; MsnTransaction *trans; char *payload; gsize payload_len; g_return_if_fail(swboard != NULL); g_return_if_fail(msg != NULL); cmdproc = swboard->cmdproc; payload = msn_message_gen_payload(msg, &payload_len); #ifdef MSN_DEBUG_SB msn_message_show_readable(msg, "SB SEND", FALSE); #endif trans = msn_transaction_new(cmdproc, "MSG", "%c %d", msn_message_get_flag(msg), payload_len); /* Data for callbacks */ msn_transaction_set_data(trans, msg); if (msg->type == MSN_MSG_TEXT) { msg->ack_ref = TRUE; msn_message_ref(msg); swboard->ack_list = g_list_append(swboard->ack_list, msg); msn_transaction_set_timeout_cb(trans, msg_timeout); } else if (msg->type == MSN_MSG_SLP) { msg->ack_ref = TRUE; msn_message_ref(msg); swboard->ack_list = g_list_append(swboard->ack_list, msg); msn_transaction_set_timeout_cb(trans, msg_timeout); #if 0 if (msg->ack_cb != NULL) { msn_transaction_add_cb(trans, "ACK", msg_ack); msn_transaction_add_cb(trans, "NAK", msg_nak); } #endif } trans->payload = payload; trans->payload_len = payload_len; msg->trans = trans; msn_cmdproc_send_trans(cmdproc, trans); }
static void queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg) { g_return_if_fail(swboard != NULL); g_return_if_fail(msg != NULL); purple_debug_info("msn", "Appending message to queue.\n"); g_queue_push_tail(swboard->msg_queue, msg); msn_message_ref(msg); }
void msn_slp_session_send_msg(MsnSlpSession *slpsession, MsnMessage *msg) { g_return_if_fail(slpsession != NULL); g_return_if_fail(msg != NULL); g_return_if_fail(msg->msnslp_message); g_return_if_fail(slpsession->outgoing_msg == NULL); msg->msnslp_header.session_id = slpsession->session_id; slpsession->outgoing_msg = msn_message_ref(msg); if (slpsession->base_id == 0) { slpsession->base_id = rand() % 0x0FFFFFF0 + 4; slpsession->prev_msg_id = slpsession->base_id; } else if (slpsession->offset == 0) slpsession->prev_msg_id = ++slpsession->base_id; msg->msnslp_header.id = slpsession->prev_msg_id; // msg->msnslp_header.ack_session_id = rand() % 0xFFFFFF00; msg->msnslp_header.ack_session_id = 0x1407C7DE; msn_message_set_charset(msg, NULL); if (msg->msnslp_header.session_id != 0) msg->msnslp_footer.app_id = 1; if (msg->bin_content) { const void *temp; temp = msn_message_get_bin_data(msg, &slpsession->orig_len); slpsession->orig_body = g_memdup(temp, slpsession->orig_len); } else { slpsession->orig_body = g_strdup(msn_message_get_body(msg)); slpsession->orig_len = strlen(slpsession->orig_body); } msg->msnslp_header.total_size_1 = slpsession->orig_len; send_msg_part(slpsession, msg); }
MsnMessage * msn_message_new(MsnMsgType type) { MsnMessage *msg; msg = g_new0(MsnMessage, 1); msg->type = type; if (purple_debug_is_verbose()) purple_debug_info("msn", "message new (%p)(%d)\n", msg, type); msg->header_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); msn_message_ref(msg); return msg; }
MsnMessage * msn_message_new(MsnMsgType type) { MsnMessage *msg; msg = g_new0(MsnMessage, 1); msg->type = type; #ifdef MSN_DEBUG_MSG purple_debug_info("msn", "message new (%p)(%d)\n", msg, type); #endif msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); msn_message_ref(msg); return msg; }
MsnMessage * msn_message_new(MsnMsgType type) { MsnMessage *msg; msg = g_new0(MsnMessage, 1); msg->type = type; #ifdef PECAN_DEBUG_MSG pn_log ("msg=%p,type=%d", msg, type); #endif msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); msn_message_ref(msg); return msg; }
/* We have received the message ack */ static void msg_ack(MsnMessage *msg, void *data) { MsnSlpMessage *slpmsg; long long real_size; slpmsg = data; real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; slpmsg->offset += msg->msnslp_header.length; slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); if (slpmsg->offset < real_size) { if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) { slpmsg->slpcall->xfer_msg = slpmsg; msn_message_ref(msg); purple_xfer_prpl_ready(slpmsg->slpcall->xfer); } else msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); } else { /* The whole message has been sent */ if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) { if (slpmsg->slpcall != NULL) { if (slpmsg->slpcall->cb) slpmsg->slpcall->cb(slpmsg->slpcall, NULL, 0); } } } msn_message_unref(msg); }
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_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { MsnMsgTypeCb cb; const char *messageId = NULL; /* Multi-part messages */ if ((messageId = msn_message_get_attr(msg, "Message-ID")) != NULL) { const char *chunk_text = msn_message_get_attr(msg, "Chunks"); guint chunk; if (chunk_text != NULL) { chunk = strtol(chunk_text, NULL, 10); /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent some random client causing pidgin to hog a ton of memory. Probably should figure out the maximum that the official client actually supports, though. */ if (chunk > 0 && chunk < 1024) { msg->total_chunks = chunk; msg->received_chunks = 1; g_hash_table_insert(cmdproc->multiparts, (gpointer)messageId, msn_message_ref(msg)); purple_debug_info("msn", "Received chunked message, messageId: '%s', total chunks: %d\n", messageId, chunk); } else { purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", messageId, chunk); } return; } else { chunk_text = msn_message_get_attr(msg, "Chunk"); if (chunk_text != NULL) { MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, messageId); chunk = strtol(chunk_text, NULL, 10); if (first == NULL) { purple_debug_error("msn", "Unable to find first chunk of messageId '%s' to correspond with chunk %d.\n", messageId, chunk+1); } else if (first->received_chunks == chunk) { /* Chunk is from 1 to total-1 (doesn't count first one) */ purple_debug_info("msn", "Received chunk %d of %d, messageId: '%s'\n", chunk+1, first->total_chunks, messageId); first->body = g_realloc(first->body, first->body_len + msg->body_len); memcpy(first->body + first->body_len, msg->body, msg->body_len); first->body_len += msg->body_len; first->received_chunks++; if (first->received_chunks != first->total_chunks) return; else /* We're done! Send it along... The caller takes care of freeing the old one. */ msg = first; } else { /* TODO: Can you legitimately receive chunks out of order? */ g_hash_table_remove(cmdproc->multiparts, messageId); return; } } else { purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", messageId); } } } if (msn_message_get_content_type(msg) == NULL) { purple_debug_misc("msn", "failed to find message content\n"); return; } cb = g_hash_table_lookup(cmdproc->cbs_table->msgs, msn_message_get_content_type(msg)); if (cb != NULL) cb(cmdproc, msg); else purple_debug_warning("msn", "Unhandled content-type '%s'\n", msn_message_get_content_type(msg)); if (messageId != NULL) g_hash_table_remove(cmdproc->multiparts, messageId); }