📄 slplink.c
字号:
/** * @file slplink.c MSNSLP Link support * * purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "msn.h"#include "slplink.h"#include "switchboard.h"#include "slp.h"void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);#ifdef MSN_DEBUG_SLP_FILESstatic int m_sc = 0;static int m_rc = 0;static voiddebug_msg_to_file(MsnMessage *msg, gboolean send){ char *tmp; char *dir; char *pload; FILE *tf; int c; gsize pload_size; dir = send ? "send" : "recv"; c = send ? m_sc++ : m_rc++; tmp = g_strdup_printf("%s/msntest/%s/%03d", g_get_home_dir(), dir, c); tf = g_fopen(tmp, "wb"); if (tf == NULL) { purple_debug_error("msn", "could not open debug file"); return; } pload = msn_message_gen_payload(msg, &pload_size); fwrite(pload, 1, pload_size, tf); fclose(tf); g_free(tmp);}#endif/************************************************************************** * Main **************************************************************************/MsnSlpLink *msn_slplink_new(MsnSession *session, const char *username){ MsnSlpLink *slplink; g_return_val_if_fail(session != NULL, NULL); slplink = g_new0(MsnSlpLink, 1);#ifdef MSN_DEBUG_SLPLINK purple_debug_info("msn", "slplink_new: slplink(%p)\n", slplink);#endif slplink->session = session; slplink->slp_seq_id = rand() % 0xFFFFFF00 + 4; slplink->local_user = g_strdup(msn_user_get_passport(session->user)); slplink->remote_user = g_strdup(username); slplink->slp_msg_queue = g_queue_new(); session->slplinks = g_list_append(session->slplinks, slplink); return slplink;}voidmsn_slplink_destroy(MsnSlpLink *slplink){ MsnSession *session;#ifdef MSN_DEBUG_SLPLINK purple_debug_info("msn", "slplink_destroy: slplink(%p)\n", slplink);#endif g_return_if_fail(slplink != NULL); if (slplink->swboard != NULL) slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); session = slplink->session; if (slplink->local_user != NULL) g_free(slplink->local_user); if (slplink->remote_user != NULL) g_free(slplink->remote_user); if (slplink->directconn != NULL) msn_directconn_destroy(slplink->directconn); while (slplink->slp_calls != NULL) msn_slp_call_destroy(slplink->slp_calls->data); session->slplinks = g_list_remove(session->slplinks, slplink); g_free(slplink);}MsnSlpLink *msn_session_find_slplink(MsnSession *session, const char *who){ GList *l; for (l = session->slplinks; l != NULL; l = l->next) { MsnSlpLink *slplink; slplink = l->data; if (!strcmp(slplink->remote_user, who)) return slplink; } return NULL;}MsnSlpLink *msn_session_get_slplink(MsnSession *session, const char *username){ MsnSlpLink *slplink; g_return_val_if_fail(session != NULL, NULL); g_return_val_if_fail(username != NULL, NULL); slplink = msn_session_find_slplink(session, username); if (slplink == NULL) slplink = msn_slplink_new(session, username); return slplink;}MsnSlpSession *msn_slplink_find_slp_session(MsnSlpLink *slplink, long session_id){ GList *l; MsnSlpSession *slpsession; for (l = slplink->slp_sessions; l != NULL; l = l->next) { slpsession = l->data; if (slpsession->id == session_id) return slpsession; } return NULL;}voidmsn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall){ if (slplink->swboard != NULL) slplink->swboard->flag |= MSN_SB_FLAG_FT; slplink->slp_calls = g_list_append(slplink->slp_calls, slpcall);}voidmsn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall){ slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall); /* The slplink has no slpcalls in it. If no one is using it, we might * destroy the switchboard, but we should be careful not to use the slplink * again. */ if (slplink->slp_calls == NULL) { if (slplink->swboard != NULL) { if (msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT)) /* I'm not sure this is the best thing to do, but it's better * than nothing. */ slpcall->slplink = NULL; } }}MsnSlpCall *msn_slplink_find_slp_call(MsnSlpLink *slplink, const char *id){ GList *l; MsnSlpCall *slpcall; if (!id) return NULL; for (l = slplink->slp_calls; l != NULL; l = l->next) { slpcall = l->data; if (slpcall->id && !strcmp(slpcall->id, id)) return slpcall; } return NULL;}MsnSlpCall *msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id){ GList *l; MsnSlpCall *slpcall; for (l = slplink->slp_calls; l != NULL; l = l->next) { slpcall = l->data; if (slpcall->session_id == id) return slpcall; } return NULL;}voidmsn_slplink_send_msg(MsnSlpLink *slplink, MsnMessage *msg){ if (slplink->directconn != NULL) { msn_directconn_send_msg(slplink->directconn, msg); } else { if (slplink->swboard == NULL) { slplink->swboard = msn_session_get_swboard(slplink->session, slplink->remote_user, MSN_SB_FLAG_FT); if (slplink->swboard == NULL) return; /* If swboard is destroyed we will be too */ slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); } msn_switchboard_send_msg(slplink->swboard, msg, TRUE); }}/* We have received the message ack */static voidmsg_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; if (slpmsg->offset < real_size) { msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); } else { /* The whole message has been sent */ if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { if (slpmsg->slpcall != NULL) { if (slpmsg->slpcall->cb) slpmsg->slpcall->cb(slpmsg->slpcall, NULL, 0); } } } slpmsg->msgs = g_list_remove(slpmsg->msgs, msg);}/* We have received the message nak. */static voidmsg_nak(MsnMessage *msg, void *data){ MsnSlpMessage *slpmsg; slpmsg = data; msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); slpmsg->msgs = g_list_remove(slpmsg->msgs, msg);}voidmsn_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; */}voidmsn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg){ MsnMessage *msg; slpmsg->msg = msg = msn_message_new_msnslp(); if (slpmsg->flags == 0x0) { msg->msnslp_header.session_id = slpmsg->session_id; msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; } else if (slpmsg->flags == 0x2) { msg->msnslp_header.session_id = slpmsg->session_id; msg->msnslp_header.ack_id = slpmsg->ack_id; msg->msnslp_header.ack_size = slpmsg->ack_size; msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id; } else if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { MsnSlpSession *slpsession; slpsession = slpmsg->slpsession; g_return_if_fail(slpsession != NULL); msg->msnslp_header.session_id = slpsession->id; msg->msnslp_footer.value = slpsession->app_id; msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -