📄 switchboard.c
字号:
/** * @file switchboard.c MSN switchboard functions * * 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 "prefs.h"#include "switchboard.h"#include "notification.h"#include "msn-utils.h"#include "error.h"static MsnTable *cbs_table;static void msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error);/************************************************************************** * Main **************************************************************************/MsnSwitchBoard *msn_switchboard_new(MsnSession *session){ MsnSwitchBoard *swboard; MsnServConn *servconn; g_return_val_if_fail(session != NULL, NULL); swboard = g_new0(MsnSwitchBoard, 1); swboard->session = session; swboard->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_SB); swboard->cmdproc = servconn->cmdproc; swboard->msg_queue = g_queue_new(); swboard->empty = TRUE; swboard->cmdproc->data = swboard; swboard->cmdproc->cbs_table = cbs_table; session->switches = g_list_append(session->switches, swboard); return swboard;}voidmsn_switchboard_destroy(MsnSwitchBoard *swboard){ MsnSession *session; MsnMessage *msg; GList *l;#ifdef MSN_DEBUG_SB purple_debug_info("msn", "switchboard_destroy: swboard(%p)\n", swboard);#endif g_return_if_fail(swboard != NULL); if (swboard->destroying) return; swboard->destroying = TRUE; /* If it linked us is because its looking for trouble */ while (swboard->slplinks != NULL) msn_slplink_destroy(swboard->slplinks->data); /* Destroy the message queue */ while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) { if (swboard->error != MSN_SB_ERROR_NONE) { /* The messages could not be sent due to a switchboard error */ msg_error_helper(swboard->cmdproc, msg, MSN_MSG_ERROR_SB); } msn_message_unref(msg); } g_queue_free(swboard->msg_queue); /* msg_error_helper will both remove the msg from ack_list and unref it, so we don't need to do either here */ while ((l = swboard->ack_list) != NULL) msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB); g_free(swboard->im_user); g_free(swboard->auth_key); g_free(swboard->session_id); for (l = swboard->users; l != NULL; l = l->next) g_free(l->data); session = swboard->session; session->switches = g_list_remove(session->switches, swboard);#if 0 /* This should never happen or we are in trouble. */ if (swboard->servconn != NULL) msn_servconn_destroy(swboard->servconn);#endif swboard->cmdproc->data = NULL; msn_servconn_set_disconnect_cb(swboard->servconn, NULL); msn_servconn_destroy(swboard->servconn); g_free(swboard);}voidmsn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key){ g_return_if_fail(swboard != NULL); g_return_if_fail(key != NULL); swboard->auth_key = g_strdup(key);}const char *msn_switchboard_get_auth_key(MsnSwitchBoard *swboard){ g_return_val_if_fail(swboard != NULL, NULL); return swboard->auth_key;}voidmsn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id){ g_return_if_fail(swboard != NULL); g_return_if_fail(id != NULL); if (swboard->session_id != NULL) g_free(swboard->session_id); swboard->session_id = g_strdup(id);}const char *msn_switchboard_get_session_id(MsnSwitchBoard *swboard){ g_return_val_if_fail(swboard != NULL, NULL); return swboard->session_id;}voidmsn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited){ g_return_if_fail(swboard != NULL); swboard->invited = invited;}gbooleanmsn_switchboard_is_invited(MsnSwitchBoard *swboard){ g_return_val_if_fail(swboard != NULL, FALSE); return swboard->invited;}/************************************************************************** * Utility **************************************************************************/static voidsend_clientcaps(MsnSwitchBoard *swboard){ MsnMessage *msg; msg = msn_message_new(MSN_MSG_CAPS); msn_message_set_content_type(msg, "text/x-clientcaps"); msn_message_set_flag(msg, 'U'); msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO)); msn_switchboard_send_msg(swboard, msg, TRUE); msn_message_destroy(msg);}static voidmsn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user){ MsnCmdProc *cmdproc; PurpleAccount *account; g_return_if_fail(swboard != NULL); cmdproc = swboard->cmdproc; account = cmdproc->session->account; swboard->users = g_list_prepend(swboard->users, g_strdup(user)); swboard->current_users++; swboard->empty = FALSE;#ifdef MSN_DEBUG_CHAT purple_debug_info("msn", "user=[%s], total=%d\n", user, swboard->current_users);#endif if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL)) { /* This is a helper switchboard. */ purple_debug_error("msn", "switchboard_add_user: conv != NULL\n"); return; } if ((swboard->conv != NULL) && (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) { purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL, PURPLE_CBFLAGS_NONE, TRUE); } else if (swboard->current_users > 1 || swboard->total_users > 1) { if (swboard->conv == NULL || purple_conversation_get_type(swboard->conv) != PURPLE_CONV_TYPE_CHAT) { GList *l;#ifdef MSN_DEBUG_CHAT purple_debug_info("msn", "[chat] Switching to chat.\n");#endif#if 0 /* this is bad - it causes msn_switchboard_close to be called on the * switchboard we're in the middle of using :( */ if (swboard->conv != NULL) purple_conversation_destroy(swboard->conv);#endif swboard->chat_id = cmdproc->session->conv_seq++; swboard->flag |= MSN_SB_FLAG_IM; swboard->conv = serv_got_joined_chat(account->gc, swboard->chat_id, "MSN Chat"); for (l = swboard->users; l != NULL; l = l->next) { const char *tmp_user; tmp_user = l->data;#ifdef MSN_DEBUG_CHAT purple_debug_info("msn", "[chat] Adding [%s].\n", tmp_user);#endif purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), tmp_user, NULL, PURPLE_CBFLAGS_NONE, TRUE); }#ifdef MSN_DEBUG_CHAT purple_debug_info("msn", "[chat] We add ourselves.\n");#endif purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), purple_account_get_username(account), NULL, PURPLE_CBFLAGS_NONE, TRUE); g_free(swboard->im_user); swboard->im_user = NULL; } } else if (swboard->conv == NULL) { swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, user, account); } else { purple_debug_warning("msn", "switchboard_add_user: This should not happen!\n"); }}static PurpleConversation *msn_switchboard_get_conv(MsnSwitchBoard *swboard){ PurpleAccount *account; g_return_val_if_fail(swboard != NULL, NULL); if (swboard->conv != NULL) return swboard->conv; purple_debug_error("msn", "Switchboard with unassigned conversation\n"); account = swboard->session->account; return (swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, swboard->im_user));}static voidmsn_switchboard_report_user(MsnSwitchBoard *swboard, PurpleMessageFlags flags, const char *msg){ PurpleConversation *conv; g_return_if_fail(swboard != NULL); g_return_if_fail(msg != NULL); if ((conv = msn_switchboard_get_conv(swboard)) != NULL) { purple_conversation_write(conv, NULL, msg, flags, time(NULL)); }}static voidswboard_error_helper(MsnSwitchBoard *swboard, int reason, const char *passport){ g_return_if_fail(swboard != NULL); purple_debug_warning("msg", "Error: Unable to call the user %s for reason %i\n", passport ? passport : "(null)", reason); /* TODO: if current_users > 0, this is probably a chat and an invite failed, * we should report that in the chat or something */ if (swboard->current_users == 0) { swboard->error = reason; msn_switchboard_close(swboard); }}static voidcal_error_helper(MsnTransaction *trans, int reason){ MsnSwitchBoard *swboard; const char *passport; char **params; params = g_strsplit(trans->params, " ", 0); passport = params[0]; swboard = trans->data; purple_debug_warning("msn", "cal_error_helper: command %s failed for reason %i\n",trans->command,reason); swboard_error_helper(swboard, reason, passport); g_strfreev(params);}static voidmsg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error){ MsnSwitchBoard *swboard; g_return_if_fail(cmdproc != NULL); g_return_if_fail(msg != NULL); if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL)) msg->nak_cb(msg, msg->ack_data); swboard = cmdproc->data; /* This is not good, and should be fixed somewhere else. */ g_return_if_fail(swboard != NULL); if (msg->type == MSN_MSG_TEXT) { const char *format, *str_reason; char *body_str, *body_enc, *pre, *post;#if 0 if (swboard->conv == NULL) { if (msg->ack_ref) msn_message_unref(msg); return; }#endif if (error == MSN_MSG_ERROR_TIMEOUT) { str_reason = _("Message may have not been sent " "because a timeout occurred:"); } else if (error == MSN_MSG_ERROR_SB) { switch (swboard->error) { case MSN_SB_ERROR_OFFLINE: str_reason = _("Message could not be sent, " "not allowed while invisible:"); break; case MSN_SB_ERROR_USER_OFFLINE: str_reason = _("Message could not be sent " "because the user is offline:"); break; case MSN_SB_ERROR_CONNECTION: str_reason = _("Message could not be sent " "because a connection error occurred:"); break; case MSN_SB_ERROR_TOO_FAST: str_reason = _("Message could not be sent " "because we are sending too quickly:"); break; case MSN_SB_ERROR_AUTHFAILED: str_reason = _("Message could not be sent " "because we wer unable to establish a " "session with the server. This is " "likely a server problem, try again in " "a few minutes:"); break; default: str_reason = _("Message could not be sent " "because an error with " "the switchboard occurred:"); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -