| 1 /** |
|
| 2 * @file switchboard.c MSN switchboard functions |
|
| 3 * |
|
| 4 * gaim |
|
| 5 * |
|
| 6 * Gaim is the legal property of its developers, whose names are too numerous |
|
| 7 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 8 * source distribution. |
|
| 9 * |
|
| 10 * This program is free software; you can redistribute it and/or modify |
|
| 11 * it under the terms of the GNU General Public License as published by |
|
| 12 * the Free Software Foundation; either version 2 of the License, or |
|
| 13 * (at your option) any later version. |
|
| 14 * |
|
| 15 * This program is distributed in the hope that it will be useful, |
|
| 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 18 * GNU General Public License for more details. |
|
| 19 * |
|
| 20 * You should have received a copy of the GNU General Public License |
|
| 21 * along with this program; if not, write to the Free Software |
|
| 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
| 23 */ |
|
| 24 #include "msn.h" |
|
| 25 #include "prefs.h" |
|
| 26 #include "switchboard.h" |
|
| 27 #include "notification.h" |
|
| 28 #include "msn-utils.h" |
|
| 29 |
|
| 30 #include "error.h" |
|
| 31 |
|
| 32 static MsnTable *cbs_table; |
|
| 33 |
|
| 34 static void msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, |
|
| 35 MsnMsgErrorType error); |
|
| 36 |
|
| 37 /************************************************************************** |
|
| 38 * Main |
|
| 39 **************************************************************************/ |
|
| 40 |
|
| 41 MsnSwitchBoard * |
|
| 42 msn_switchboard_new(MsnSession *session) |
|
| 43 { |
|
| 44 MsnSwitchBoard *swboard; |
|
| 45 MsnServConn *servconn; |
|
| 46 |
|
| 47 g_return_val_if_fail(session != NULL, NULL); |
|
| 48 |
|
| 49 swboard = g_new0(MsnSwitchBoard, 1); |
|
| 50 |
|
| 51 swboard->session = session; |
|
| 52 swboard->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_SB); |
|
| 53 swboard->cmdproc = servconn->cmdproc; |
|
| 54 |
|
| 55 swboard->msg_queue = g_queue_new(); |
|
| 56 swboard->empty = TRUE; |
|
| 57 |
|
| 58 swboard->cmdproc->data = swboard; |
|
| 59 swboard->cmdproc->cbs_table = cbs_table; |
|
| 60 |
|
| 61 session->switches = g_list_append(session->switches, swboard); |
|
| 62 |
|
| 63 return swboard; |
|
| 64 } |
|
| 65 |
|
| 66 void |
|
| 67 msn_switchboard_destroy(MsnSwitchBoard *swboard) |
|
| 68 { |
|
| 69 MsnSession *session; |
|
| 70 MsnMessage *msg; |
|
| 71 GList *l; |
|
| 72 |
|
| 73 #ifdef MSN_DEBUG_SB |
|
| 74 gaim_debug_info("msn", "switchboard_destroy: swboard(%p)\n", swboard); |
|
| 75 #endif |
|
| 76 |
|
| 77 g_return_if_fail(swboard != NULL); |
|
| 78 |
|
| 79 if (swboard->destroying) |
|
| 80 return; |
|
| 81 |
|
| 82 swboard->destroying = TRUE; |
|
| 83 |
|
| 84 /* If it linked us is because its looking for trouble */ |
|
| 85 while (swboard->slplinks != NULL) |
|
| 86 msn_slplink_destroy(swboard->slplinks->data); |
|
| 87 |
|
| 88 /* Destroy the message queue */ |
|
| 89 while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) |
|
| 90 { |
|
| 91 if (swboard->error != MSN_SB_ERROR_NONE) |
|
| 92 { |
|
| 93 /* The messages could not be sent due to a switchboard error */ |
|
| 94 msg_error_helper(swboard->cmdproc, msg, |
|
| 95 MSN_MSG_ERROR_SB); |
|
| 96 } |
|
| 97 msn_message_unref(msg); |
|
| 98 } |
|
| 99 |
|
| 100 g_queue_free(swboard->msg_queue); |
|
| 101 |
|
| 102 /* msg_error_helper will both remove the msg from ack_list and |
|
| 103 unref it, so we don't need to do either here */ |
|
| 104 while ((l = swboard->ack_list) != NULL) |
|
| 105 msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB); |
|
| 106 |
|
| 107 g_free(swboard->im_user); |
|
| 108 g_free(swboard->auth_key); |
|
| 109 g_free(swboard->session_id); |
|
| 110 |
|
| 111 for (l = swboard->users; l != NULL; l = l->next) |
|
| 112 g_free(l->data); |
|
| 113 |
|
| 114 session = swboard->session; |
|
| 115 session->switches = g_list_remove(session->switches, swboard); |
|
| 116 |
|
| 117 #if 0 |
|
| 118 /* This should never happen or we are in trouble. */ |
|
| 119 if (swboard->servconn != NULL) |
|
| 120 msn_servconn_destroy(swboard->servconn); |
|
| 121 #endif |
|
| 122 |
|
| 123 swboard->cmdproc->data = NULL; |
|
| 124 |
|
| 125 msn_servconn_set_disconnect_cb(swboard->servconn, NULL); |
|
| 126 |
|
| 127 msn_servconn_destroy(swboard->servconn); |
|
| 128 |
|
| 129 g_free(swboard); |
|
| 130 } |
|
| 131 |
|
| 132 void |
|
| 133 msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key) |
|
| 134 { |
|
| 135 g_return_if_fail(swboard != NULL); |
|
| 136 g_return_if_fail(key != NULL); |
|
| 137 |
|
| 138 swboard->auth_key = g_strdup(key); |
|
| 139 } |
|
| 140 |
|
| 141 const char * |
|
| 142 msn_switchboard_get_auth_key(MsnSwitchBoard *swboard) |
|
| 143 { |
|
| 144 g_return_val_if_fail(swboard != NULL, NULL); |
|
| 145 |
|
| 146 return swboard->auth_key; |
|
| 147 } |
|
| 148 |
|
| 149 void |
|
| 150 msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id) |
|
| 151 { |
|
| 152 g_return_if_fail(swboard != NULL); |
|
| 153 g_return_if_fail(id != NULL); |
|
| 154 |
|
| 155 if (swboard->session_id != NULL) |
|
| 156 g_free(swboard->session_id); |
|
| 157 |
|
| 158 swboard->session_id = g_strdup(id); |
|
| 159 } |
|
| 160 |
|
| 161 const char * |
|
| 162 msn_switchboard_get_session_id(MsnSwitchBoard *swboard) |
|
| 163 { |
|
| 164 g_return_val_if_fail(swboard != NULL, NULL); |
|
| 165 |
|
| 166 return swboard->session_id; |
|
| 167 } |
|
| 168 |
|
| 169 void |
|
| 170 msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited) |
|
| 171 { |
|
| 172 g_return_if_fail(swboard != NULL); |
|
| 173 |
|
| 174 swboard->invited = invited; |
|
| 175 } |
|
| 176 |
|
| 177 gboolean |
|
| 178 msn_switchboard_is_invited(MsnSwitchBoard *swboard) |
|
| 179 { |
|
| 180 g_return_val_if_fail(swboard != NULL, FALSE); |
|
| 181 |
|
| 182 return swboard->invited; |
|
| 183 } |
|
| 184 |
|
| 185 /************************************************************************** |
|
| 186 * Utility |
|
| 187 **************************************************************************/ |
|
| 188 |
|
| 189 static void |
|
| 190 send_clientcaps(MsnSwitchBoard *swboard) |
|
| 191 { |
|
| 192 MsnMessage *msg; |
|
| 193 |
|
| 194 msg = msn_message_new(MSN_MSG_CAPS); |
|
| 195 msn_message_set_content_type(msg, "text/x-clientcaps"); |
|
| 196 msn_message_set_flag(msg, 'U'); |
|
| 197 msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO)); |
|
| 198 |
|
| 199 msn_switchboard_send_msg(swboard, msg, TRUE); |
|
| 200 |
|
| 201 msn_message_destroy(msg); |
|
| 202 } |
|
| 203 |
|
| 204 static void |
|
| 205 msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user) |
|
| 206 { |
|
| 207 MsnCmdProc *cmdproc; |
|
| 208 GaimAccount *account; |
|
| 209 |
|
| 210 g_return_if_fail(swboard != NULL); |
|
| 211 |
|
| 212 cmdproc = swboard->cmdproc; |
|
| 213 account = cmdproc->session->account; |
|
| 214 |
|
| 215 swboard->users = g_list_prepend(swboard->users, g_strdup(user)); |
|
| 216 swboard->current_users++; |
|
| 217 swboard->empty = FALSE; |
|
| 218 |
|
| 219 #ifdef MSN_DEBUG_CHAT |
|
| 220 gaim_debug_info("msn", "user=[%s], total=%d\n", user, |
|
| 221 swboard->current_users); |
|
| 222 #endif |
|
| 223 |
|
| 224 if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL)) |
|
| 225 { |
|
| 226 /* This is a helper switchboard. */ |
|
| 227 gaim_debug_error("msn", "switchboard_add_user: conv != NULL\n"); |
|
| 228 return; |
|
| 229 } |
|
| 230 |
|
| 231 if ((swboard->conv != NULL) && |
|
| 232 (gaim_conversation_get_type(swboard->conv) == GAIM_CONV_TYPE_CHAT)) |
|
| 233 { |
|
| 234 gaim_conv_chat_add_user(GAIM_CONV_CHAT(swboard->conv), user, NULL, |
|
| 235 GAIM_CBFLAGS_NONE, TRUE); |
|
| 236 } |
|
| 237 else if (swboard->current_users > 1 || swboard->total_users > 1) |
|
| 238 { |
|
| 239 if (swboard->conv == NULL || |
|
| 240 gaim_conversation_get_type(swboard->conv) != GAIM_CONV_TYPE_CHAT) |
|
| 241 { |
|
| 242 GList *l; |
|
| 243 |
|
| 244 #ifdef MSN_DEBUG_CHAT |
|
| 245 gaim_debug_info("msn", "[chat] Switching to chat.\n"); |
|
| 246 #endif |
|
| 247 |
|
| 248 #if 0 |
|
| 249 /* this is bad - it causes msn_switchboard_close to be called on the |
|
| 250 * switchboard we're in the middle of using :( */ |
|
| 251 if (swboard->conv != NULL) |
|
| 252 gaim_conversation_destroy(swboard->conv); |
|
| 253 #endif |
|
| 254 |
|
| 255 cmdproc->session->conv_seq++; |
|
| 256 swboard->chat_id = cmdproc->session->conv_seq; |
|
| 257 swboard->flag |= MSN_SB_FLAG_IM; |
|
| 258 swboard->conv = serv_got_joined_chat(account->gc, |
|
| 259 swboard->chat_id, |
|
| 260 "MSN Chat"); |
|
| 261 |
|
| 262 for (l = swboard->users; l != NULL; l = l->next) |
|
| 263 { |
|
| 264 const char *tmp_user; |
|
| 265 |
|
| 266 tmp_user = l->data; |
|
| 267 |
|
| 268 #ifdef MSN_DEBUG_CHAT |
|
| 269 gaim_debug_info("msn", "[chat] Adding [%s].\n", tmp_user); |
|
| 270 #endif |
|
| 271 |
|
| 272 gaim_conv_chat_add_user(GAIM_CONV_CHAT(swboard->conv), |
|
| 273 tmp_user, NULL, GAIM_CBFLAGS_NONE, TRUE); |
|
| 274 } |
|
| 275 |
|
| 276 #ifdef MSN_DEBUG_CHAT |
|
| 277 gaim_debug_info("msn", "[chat] We add ourselves.\n"); |
|
| 278 #endif |
|
| 279 |
|
| 280 gaim_conv_chat_add_user(GAIM_CONV_CHAT(swboard->conv), |
|
| 281 gaim_account_get_username(account), |
|
| 282 NULL, GAIM_CBFLAGS_NONE, TRUE); |
|
| 283 |
|
| 284 g_free(swboard->im_user); |
|
| 285 swboard->im_user = NULL; |
|
| 286 } |
|
| 287 } |
|
| 288 else if (swboard->conv == NULL) |
|
| 289 { |
|
| 290 swboard->conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, |
|
| 291 user, account); |
|
| 292 } |
|
| 293 else |
|
| 294 { |
|
| 295 gaim_debug_warning("msn", "switchboard_add_user: This should not happen!\n"); |
|
| 296 } |
|
| 297 } |
|
| 298 |
|
| 299 static GaimConversation * |
|
| 300 msn_switchboard_get_conv(MsnSwitchBoard *swboard) |
|
| 301 { |
|
| 302 GaimAccount *account; |
|
| 303 |
|
| 304 g_return_val_if_fail(swboard != NULL, NULL); |
|
| 305 |
|
| 306 if (swboard->conv != NULL) |
|
| 307 return swboard->conv; |
|
| 308 |
|
| 309 gaim_debug_error("msn", "Switchboard with unassigned conversation\n"); |
|
| 310 |
|
| 311 account = swboard->session->account; |
|
| 312 |
|
| 313 return (swboard->conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, |
|
| 314 account, swboard->im_user)); |
|
| 315 } |
|
| 316 |
|
| 317 static void |
|
| 318 msn_switchboard_report_user(MsnSwitchBoard *swboard, GaimMessageFlags flags, const char *msg) |
|
| 319 { |
|
| 320 GaimConversation *conv; |
|
| 321 |
|
| 322 g_return_if_fail(swboard != NULL); |
|
| 323 g_return_if_fail(msg != NULL); |
|
| 324 |
|
| 325 if ((conv = msn_switchboard_get_conv(swboard)) != NULL) |
|
| 326 { |
|
| 327 gaim_conversation_write(conv, NULL, msg, flags, time(NULL)); |
|
| 328 } |
|
| 329 } |
|
| 330 |
|
| 331 static void |
|
| 332 swboard_error_helper(MsnSwitchBoard *swboard, int reason, const char *passport) |
|
| 333 { |
|
| 334 g_return_if_fail(swboard != NULL); |
|
| 335 |
|
| 336 gaim_debug_warning("msg", "Error: Unable to call the user %s for reason %i\n", |
|
| 337 passport ? passport : "(null)", reason); |
|
| 338 |
|
| 339 /* TODO: if current_users > 0, this is probably a chat and an invite failed, |
|
| 340 * we should report that in the chat or something */ |
|
| 341 if (swboard->current_users == 0) |
|
| 342 { |
|
| 343 swboard->error = reason; |
|
| 344 msn_switchboard_close(swboard); |
|
| 345 } |
|
| 346 } |
|
| 347 |
|
| 348 static void |
|
| 349 cal_error_helper(MsnTransaction *trans, int reason) |
|
| 350 { |
|
| 351 MsnSwitchBoard *swboard; |
|
| 352 const char *passport; |
|
| 353 char **params; |
|
| 354 |
|
| 355 params = g_strsplit(trans->params, " ", 0); |
|
| 356 |
|
| 357 passport = params[0]; |
|
| 358 |
|
| 359 swboard = trans->data; |
|
| 360 |
|
| 361 gaim_debug_warning("msn", "cal_error_helper: command %s failed for reason %i\n",trans->command,reason); |
|
| 362 |
|
| 363 swboard_error_helper(swboard, reason, passport); |
|
| 364 |
|
| 365 g_strfreev(params); |
|
| 366 } |
|
| 367 |
|
| 368 static void |
|
| 369 msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error) |
|
| 370 { |
|
| 371 MsnSwitchBoard *swboard; |
|
| 372 |
|
| 373 g_return_if_fail(cmdproc != NULL); |
|
| 374 g_return_if_fail(msg != NULL); |
|
| 375 |
|
| 376 if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL)) |
|
| 377 msg->nak_cb(msg, msg->ack_data); |
|
| 378 |
|
| 379 swboard = cmdproc->data; |
|
| 380 |
|
| 381 /* This is not good, and should be fixed somewhere else. */ |
|
| 382 g_return_if_fail(swboard != NULL); |
|
| 383 |
|
| 384 if (msg->type == MSN_MSG_TEXT) |
|
| 385 { |
|
| 386 const char *format, *str_reason; |
|
| 387 char *body_str, *body_enc, *pre, *post; |
|
| 388 |
|
| 389 #if 0 |
|
| 390 if (swboard->conv == NULL) |
|
| 391 { |
|
| 392 if (msg->ack_ref) |
|
| 393 msn_message_unref(msg); |
|
| 394 |
|
| 395 return; |
|
| 396 } |
|
| 397 #endif |
|
| 398 |
|
| 399 if (error == MSN_MSG_ERROR_TIMEOUT) |
|
| 400 { |
|
| 401 str_reason = _("Message may have not been sent " |
|
| 402 "because a timeout occurred:"); |
|
| 403 } |
|
| 404 else if (error == MSN_MSG_ERROR_SB) |
|
| 405 { |
|
| 406 switch (swboard->error) |
|
| 407 { |
|
| 408 case MSN_SB_ERROR_OFFLINE: |
|
| 409 str_reason = _("Message could not be sent, " |
|
| 410 "not allowed while invisible:"); |
|
| 411 break; |
|
| 412 case MSN_SB_ERROR_USER_OFFLINE: |
|
| 413 str_reason = _("Message could not be sent " |
|
| 414 "because the user is offline:"); |
|
| 415 break; |
|
| 416 case MSN_SB_ERROR_CONNECTION: |
|
| 417 str_reason = _("Message could not be sent " |
|
| 418 "because a connection error occurred:"); |
|
| 419 break; |
|
| 420 case MSN_SB_ERROR_TOO_FAST: |
|
| 421 str_reason = _("Message could not be sent " |
|
| 422 "because we are sending too quickly:"); |
|
| 423 break; |
|
| 424 default: |
|
| 425 str_reason = _("Message could not be sent " |
|
| 426 "because an error with " |
|
| 427 "the switchboard occurred:"); |
|
| 428 break; |
|
| 429 } |
|
| 430 } |
|
| 431 else |
|
| 432 { |
|
| 433 str_reason = _("Message may have not been sent " |
|
| 434 "because an unknown error occurred:"); |
|
| 435 } |
|
| 436 |
|
| 437 body_str = msn_message_to_string(msg); |
|
| 438 body_enc = g_markup_escape_text(body_str, -1); |
|
| 439 g_free(body_str); |
|
| 440 |
|
| 441 format = msn_message_get_attr(msg, "X-MMS-IM-Format"); |
|
| 442 msn_parse_format(format, &pre, &post); |
|
| 443 body_str = g_strdup_printf("%s%s%s", pre ? pre : "", |
|
| 444 body_enc ? body_enc : "", post ? post : ""); |
|
| 445 g_free(body_enc); |
|
| 446 g_free(pre); |
|
| 447 g_free(post); |
|
| 448 |
|
| 449 msn_switchboard_report_user(swboard, GAIM_MESSAGE_ERROR, |
|
| 450 str_reason); |
|
| 451 msn_switchboard_report_user(swboard, GAIM_MESSAGE_RAW, |
|
| 452 body_str); |
|
| 453 |
|
| 454 g_free(body_str); |
|
| 455 } |
|
| 456 |
|
| 457 /* If a timeout occures we will want the msg around just in case we |
|
| 458 * receive the ACK after the timeout. */ |
|
| 459 if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT) |
|
| 460 { |
|
| 461 swboard->ack_list = g_list_remove(swboard->ack_list, msg); |
|
| 462 msn_message_unref(msg); |
|
| 463 } |
|
| 464 } |
|
| 465 |
|
| 466 /************************************************************************** |
|
| 467 * Message Stuff |
|
| 468 **************************************************************************/ |
|
| 469 |
|
| 470 /** Called when a message times out. */ |
|
| 471 static void |
|
| 472 msg_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans) |
|
| 473 { |
|
| 474 MsnMessage *msg; |
|
| 475 |
|
| 476 msg = trans->data; |
|
| 477 |
|
| 478 msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_TIMEOUT); |
|
| 479 } |
|
| 480 |
|
| 481 /** Called when we receive an error of a message. */ |
|
| 482 static void |
|
| 483 msg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) |
|
| 484 { |
|
| 485 msg_error_helper(cmdproc, trans->data, MSN_MSG_ERROR_UNKNOWN); |
|
| 486 } |
|
| 487 |
|
| 488 #if 0 |
|
| 489 /** Called when we receive an ack of a special message. */ |
|
| 490 static void |
|
| 491 msg_ack(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 492 { |
|
| 493 MsnMessage *msg; |
|
| 494 |
|
| 495 msg = cmd->trans->data; |
|
| 496 |
|
| 497 if (msg->ack_cb != NULL) |
|
| 498 msg->ack_cb(msg->ack_data); |
|
| 499 |
|
| 500 msn_message_unref(msg); |
|
| 501 } |
|
| 502 |
|
| 503 /** Called when we receive a nak of a special message. */ |
|
| 504 static void |
|
| 505 msg_nak(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 506 { |
|
| 507 MsnMessage *msg; |
|
| 508 |
|
| 509 msg = cmd->trans->data; |
|
| 510 |
|
| 511 msn_message_unref(msg); |
|
| 512 } |
|
| 513 #endif |
|
| 514 |
|
| 515 static void |
|
| 516 release_msg(MsnSwitchBoard *swboard, MsnMessage *msg) |
|
| 517 { |
|
| 518 MsnCmdProc *cmdproc; |
|
| 519 MsnTransaction *trans; |
|
| 520 char *payload; |
|
| 521 gsize payload_len; |
|
| 522 |
|
| 523 g_return_if_fail(swboard != NULL); |
|
| 524 g_return_if_fail(msg != NULL); |
|
| 525 |
|
| 526 cmdproc = swboard->cmdproc; |
|
| 527 |
|
| 528 payload = msn_message_gen_payload(msg, &payload_len); |
|
| 529 |
|
| 530 #ifdef MSN_DEBUG_SB |
|
| 531 msn_message_show_readable(msg, "SB SEND", FALSE); |
|
| 532 #endif |
|
| 533 |
|
| 534 trans = msn_transaction_new(cmdproc, "MSG", "%c %d", |
|
| 535 msn_message_get_flag(msg), payload_len); |
|
| 536 |
|
| 537 /* Data for callbacks */ |
|
| 538 msn_transaction_set_data(trans, msg); |
|
| 539 |
|
| 540 if (msg->type == MSN_MSG_TEXT) |
|
| 541 { |
|
| 542 msg->ack_ref = TRUE; |
|
| 543 msn_message_ref(msg); |
|
| 544 swboard->ack_list = g_list_append(swboard->ack_list, msg); |
|
| 545 msn_transaction_set_timeout_cb(trans, msg_timeout); |
|
| 546 } |
|
| 547 else if (msg->type == MSN_MSG_SLP) |
|
| 548 { |
|
| 549 msg->ack_ref = TRUE; |
|
| 550 msn_message_ref(msg); |
|
| 551 swboard->ack_list = g_list_append(swboard->ack_list, msg); |
|
| 552 msn_transaction_set_timeout_cb(trans, msg_timeout); |
|
| 553 #if 0 |
|
| 554 if (msg->ack_cb != NULL) |
|
| 555 { |
|
| 556 msn_transaction_add_cb(trans, "ACK", msg_ack); |
|
| 557 msn_transaction_add_cb(trans, "NAK", msg_nak); |
|
| 558 } |
|
| 559 #endif |
|
| 560 } |
|
| 561 |
|
| 562 trans->payload = payload; |
|
| 563 trans->payload_len = payload_len; |
|
| 564 |
|
| 565 msg->trans = trans; |
|
| 566 |
|
| 567 msn_cmdproc_send_trans(cmdproc, trans); |
|
| 568 } |
|
| 569 |
|
| 570 static void |
|
| 571 queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg) |
|
| 572 { |
|
| 573 g_return_if_fail(swboard != NULL); |
|
| 574 g_return_if_fail(msg != NULL); |
|
| 575 |
|
| 576 gaim_debug_info("msn", "Appending message to queue.\n"); |
|
| 577 |
|
| 578 g_queue_push_tail(swboard->msg_queue, msg); |
|
| 579 |
|
| 580 msn_message_ref(msg); |
|
| 581 } |
|
| 582 |
|
| 583 static void |
|
| 584 process_queue(MsnSwitchBoard *swboard) |
|
| 585 { |
|
| 586 MsnMessage *msg; |
|
| 587 |
|
| 588 g_return_if_fail(swboard != NULL); |
|
| 589 |
|
| 590 gaim_debug_info("msn", "Processing queue\n"); |
|
| 591 |
|
| 592 while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) |
|
| 593 { |
|
| 594 gaim_debug_info("msn", "Sending message\n"); |
|
| 595 release_msg(swboard, msg); |
|
| 596 msn_message_unref(msg); |
|
| 597 } |
|
| 598 } |
|
| 599 |
|
| 600 gboolean |
|
| 601 msn_switchboard_can_send(MsnSwitchBoard *swboard) |
|
| 602 { |
|
| 603 g_return_val_if_fail(swboard != NULL, FALSE); |
|
| 604 |
|
| 605 if (swboard->empty || !g_queue_is_empty(swboard->msg_queue)) |
|
| 606 return FALSE; |
|
| 607 |
|
| 608 return TRUE; |
|
| 609 } |
|
| 610 |
|
| 611 void |
|
| 612 msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg, |
|
| 613 gboolean queue) |
|
| 614 { |
|
| 615 g_return_if_fail(swboard != NULL); |
|
| 616 g_return_if_fail(msg != NULL); |
|
| 617 |
|
| 618 if (msn_switchboard_can_send(swboard)) |
|
| 619 release_msg(swboard, msg); |
|
| 620 else if (queue) |
|
| 621 queue_msg(swboard, msg); |
|
| 622 } |
|
| 623 |
|
| 624 /************************************************************************** |
|
| 625 * Switchboard Commands |
|
| 626 **************************************************************************/ |
|
| 627 |
|
| 628 static void |
|
| 629 ans_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 630 { |
|
| 631 MsnSwitchBoard *swboard; |
|
| 632 |
|
| 633 swboard = cmdproc->data; |
|
| 634 swboard->ready = TRUE; |
|
| 635 } |
|
| 636 |
|
| 637 static void |
|
| 638 bye_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 639 { |
|
| 640 MsnSwitchBoard *swboard; |
|
| 641 const char *user; |
|
| 642 |
|
| 643 swboard = cmdproc->data; |
|
| 644 user = cmd->params[0]; |
|
| 645 |
|
| 646 if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL)) |
|
| 647 gaim_debug_error("msn_switchboard", "bye_cmd: helper bug\n"); |
|
| 648 |
|
| 649 if (swboard->conv == NULL) |
|
| 650 { |
|
| 651 /* This is a helper switchboard */ |
|
| 652 msn_switchboard_destroy(swboard); |
|
| 653 } |
|
| 654 else if ((swboard->current_users > 1) || |
|
| 655 (gaim_conversation_get_type(swboard->conv) == GAIM_CONV_TYPE_CHAT)) |
|
| 656 { |
|
| 657 /* This is a switchboard used for a chat */ |
|
| 658 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(swboard->conv), user, NULL); |
|
| 659 swboard->current_users--; |
|
| 660 if (swboard->current_users == 0) |
|
| 661 msn_switchboard_destroy(swboard); |
|
| 662 } |
|
| 663 else |
|
| 664 { |
|
| 665 /* This is a switchboard used for a im session */ |
|
| 666 msn_switchboard_destroy(swboard); |
|
| 667 } |
|
| 668 } |
|
| 669 |
|
| 670 static void |
|
| 671 iro_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 672 { |
|
| 673 GaimAccount *account; |
|
| 674 GaimConnection *gc; |
|
| 675 MsnSwitchBoard *swboard; |
|
| 676 |
|
| 677 account = cmdproc->session->account; |
|
| 678 gc = account->gc; |
|
| 679 swboard = cmdproc->data; |
|
| 680 |
|
| 681 swboard->total_users = atoi(cmd->params[2]); |
|
| 682 |
|
| 683 msn_switchboard_add_user(swboard, cmd->params[3]); |
|
| 684 } |
|
| 685 |
|
| 686 static void |
|
| 687 joi_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 688 { |
|
| 689 MsnSession *session; |
|
| 690 GaimAccount *account; |
|
| 691 GaimConnection *gc; |
|
| 692 MsnSwitchBoard *swboard; |
|
| 693 const char *passport; |
|
| 694 |
|
| 695 passport = cmd->params[0]; |
|
| 696 |
|
| 697 session = cmdproc->session; |
|
| 698 account = session->account; |
|
| 699 gc = account->gc; |
|
| 700 swboard = cmdproc->data; |
|
| 701 |
|
| 702 msn_switchboard_add_user(swboard, passport); |
|
| 703 |
|
| 704 process_queue(swboard); |
|
| 705 |
|
| 706 if (!session->http_method) |
|
| 707 send_clientcaps(swboard); |
|
| 708 |
|
| 709 if (swboard->closed) |
|
| 710 msn_switchboard_close(swboard); |
|
| 711 } |
|
| 712 |
|
| 713 static void |
|
| 714 msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) |
|
| 715 { |
|
| 716 MsnMessage *msg; |
|
| 717 |
|
| 718 msg = msn_message_new_from_cmd(cmdproc->session, cmd); |
|
| 719 |
|
| 720 msn_message_parse_payload(msg, payload, len); |
|
| 721 #ifdef MSN_DEBUG_SB |
|
| 722 msn_message_show_readable(msg, "SB RECV", FALSE); |
|
| 723 #endif |
|
| 724 |
|
| 725 if (msg->remote_user != NULL) |
|
| 726 g_free (msg->remote_user); |
|
| 727 |
|
| 728 msg->remote_user = g_strdup(cmd->params[0]); |
|
| 729 msn_cmdproc_process_msg(cmdproc, msg); |
|
| 730 |
|
| 731 msn_message_destroy(msg); |
|
| 732 } |
|
| 733 |
|
| 734 static void |
|
| 735 msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 736 { |
|
| 737 cmdproc->servconn->payload_len = atoi(cmd->params[2]); |
|
| 738 cmdproc->last_cmd->payload_cb = msg_cmd_post; |
|
| 739 } |
|
| 740 |
|
| 741 static void |
|
| 742 nak_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 743 { |
|
| 744 MsnMessage *msg; |
|
| 745 |
|
| 746 msg = cmd->trans->data; |
|
| 747 g_return_if_fail(msg != NULL); |
|
| 748 |
|
| 749 msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_NAK); |
|
| 750 } |
|
| 751 |
|
| 752 static void |
|
| 753 ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 754 { |
|
| 755 MsnSwitchBoard *swboard; |
|
| 756 MsnMessage *msg; |
|
| 757 |
|
| 758 msg = cmd->trans->data; |
|
| 759 |
|
| 760 if (msg->ack_cb != NULL) |
|
| 761 msg->ack_cb(msg, msg->ack_data); |
|
| 762 |
|
| 763 swboard = cmdproc->data; |
|
| 764 swboard->ack_list = g_list_remove(swboard->ack_list, msg); |
|
| 765 msn_message_unref(msg); |
|
| 766 } |
|
| 767 |
|
| 768 static void |
|
| 769 out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 770 { |
|
| 771 GaimConnection *gc; |
|
| 772 MsnSwitchBoard *swboard; |
|
| 773 |
|
| 774 gc = cmdproc->session->account->gc; |
|
| 775 swboard = cmdproc->data; |
|
| 776 |
|
| 777 if (swboard->current_users > 1) |
|
| 778 serv_got_chat_left(gc, swboard->chat_id); |
|
| 779 |
|
| 780 msn_switchboard_disconnect(swboard); |
|
| 781 } |
|
| 782 |
|
| 783 static void |
|
| 784 usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 785 { |
|
| 786 MsnSwitchBoard *swboard; |
|
| 787 |
|
| 788 swboard = cmdproc->data; |
|
| 789 |
|
| 790 #if 0 |
|
| 791 GList *l; |
|
| 792 |
|
| 793 for (l = swboard->users; l != NULL; l = l->next) |
|
| 794 { |
|
| 795 const char *user; |
|
| 796 user = l->data; |
|
| 797 |
|
| 798 msn_cmdproc_send(cmdproc, "CAL", "%s", user); |
|
| 799 } |
|
| 800 #endif |
|
| 801 |
|
| 802 swboard->ready = TRUE; |
|
| 803 msn_cmdproc_process_queue(cmdproc); |
|
| 804 } |
|
| 805 |
|
| 806 /************************************************************************** |
|
| 807 * Message Handlers |
|
| 808 **************************************************************************/ |
|
| 809 static void |
|
| 810 plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) |
|
| 811 { |
|
| 812 GaimConnection *gc; |
|
| 813 MsnSwitchBoard *swboard; |
|
| 814 const char *body; |
|
| 815 char *body_str; |
|
| 816 char *body_enc; |
|
| 817 char *body_final; |
|
| 818 size_t body_len; |
|
| 819 const char *passport; |
|
| 820 const char *value; |
|
| 821 |
|
| 822 gc = cmdproc->session->account->gc; |
|
| 823 swboard = cmdproc->data; |
|
| 824 |
|
| 825 body = msn_message_get_bin_data(msg, &body_len); |
|
| 826 body_str = g_strndup(body, body_len); |
|
| 827 body_enc = g_markup_escape_text(body_str, -1); |
|
| 828 g_free(body_str); |
|
| 829 |
|
| 830 passport = msg->remote_user; |
|
| 831 |
|
| 832 if (!strcmp(passport, "messenger@microsoft.com") && |
|
| 833 strstr(body, "immediate security update")) |
|
| 834 { |
|
| 835 return; |
|
| 836 } |
|
| 837 |
|
| 838 #if 0 |
|
| 839 if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL) |
|
| 840 { |
|
| 841 gaim_debug_misc("msn", "User-Agent = '%s'\n", value); |
|
| 842 } |
|
| 843 #endif |
|
| 844 |
|
| 845 if ((value = msn_message_get_attr(msg, "X-MMS-IM-Format")) != NULL) |
|
| 846 { |
|
| 847 char *pre, *post; |
|
| 848 |
|
| 849 msn_parse_format(value, &pre, &post); |
|
| 850 |
|
| 851 body_final = g_strdup_printf("%s%s%s", pre ? pre : "", |
|
| 852 body_enc ? body_enc : "", post ? post : ""); |
|
| 853 |
|
| 854 g_free(pre); |
|
| 855 g_free(post); |
|
| 856 g_free(body_enc); |
|
| 857 } |
|
| 858 else |
|
| 859 { |
|
| 860 body_final = body_enc; |
|
| 861 } |
|
| 862 |
|
| 863 swboard->flag |= MSN_SB_FLAG_IM; |
|
| 864 |
|
| 865 if (swboard->current_users > 1 || |
|
| 866 ((swboard->conv != NULL) && |
|
| 867 gaim_conversation_get_type(swboard->conv) == GAIM_CONV_TYPE_CHAT)) |
|
| 868 { |
|
| 869 /* If current_users is always ok as it should then there is no need to |
|
| 870 * check if this is a chat. */ |
|
| 871 if (swboard->current_users <= 1) |
|
| 872 gaim_debug_misc("msn", "plain_msg: current_users(%d)\n", |
|
| 873 swboard->current_users); |
|
| 874 |
|
| 875 serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final, |
|
| 876 time(NULL)); |
|
| 877 if (swboard->conv == NULL) |
|
| 878 { |
|
| 879 swboard->conv = gaim_find_chat(gc, swboard->chat_id); |
|
| 880 swboard->flag |= MSN_SB_FLAG_IM; |
|
| 881 } |
|
| 882 } |
|
| 883 else |
|
| 884 { |
|
| 885 serv_got_im(gc, passport, body_final, 0, time(NULL)); |
|
| 886 if (swboard->conv == NULL) |
|
| 887 { |
|
| 888 swboard->conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, |
|
| 889 passport, gaim_connection_get_account(gc)); |
|
| 890 swboard->flag |= MSN_SB_FLAG_IM; |
|
| 891 } |
|
| 892 } |
|
| 893 |
|
| 894 g_free(body_final); |
|
| 895 } |
|
| 896 |
|
| 897 static void |
|
| 898 control_msg(MsnCmdProc *cmdproc, MsnMessage *msg) |
|
| 899 { |
|
| 900 GaimConnection *gc; |
|
| 901 MsnSwitchBoard *swboard; |
|
| 902 char *passport; |
|
| 903 |
|
| 904 gc = cmdproc->session->account->gc; |
|
| 905 swboard = cmdproc->data; |
|
| 906 passport = msg->remote_user; |
|
| 907 |
|
| 908 if (swboard->current_users == 1 && |
|
| 909 msn_message_get_attr(msg, "TypingUser") != NULL) |
|
| 910 { |
|
| 911 serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, |
|
| 912 GAIM_TYPING); |
|
| 913 } |
|
| 914 } |
|
| 915 |
|
| 916 static void |
|
| 917 clientcaps_msg(MsnCmdProc *cmdproc, MsnMessage *msg) |
|
| 918 { |
|
| 919 #if 0 |
|
| 920 MsnSession *session; |
|
| 921 MsnSwitchBoard *swboard; |
|
| 922 MsnUser *user; |
|
| 923 GHashTable *clientcaps; |
|
| 924 const char *value; |
|
| 925 |
|
| 926 char *passport = msg->sender; |
|
| 927 |
|
| 928 session = cmdproc->session; |
|
| 929 swboard = cmdproc->servconn->swboard; |
|
| 930 |
|
| 931 clientcaps = msn_message_get_hashtable_from_body(msg); |
|
| 932 #endif |
|
| 933 } |
|
| 934 |
|
| 935 static void |
|
| 936 nudge_msg(MsnCmdProc *cmdproc, MsnMessage *msg) |
|
| 937 { |
|
| 938 MsnSwitchBoard *swboard; |
|
| 939 char *username, *str; |
|
| 940 GaimAccount *account; |
|
| 941 GaimBuddy *buddy; |
|
| 942 const char *user; |
|
| 943 |
|
| 944 swboard = cmdproc->data; |
|
| 945 account = cmdproc->session->account; |
|
| 946 user = msg->remote_user; |
|
| 947 |
|
| 948 if ((buddy = gaim_find_buddy(account, user)) != NULL) |
|
| 949 username = g_markup_escape_text(gaim_buddy_get_alias(buddy), -1); |
|
| 950 else |
|
| 951 username = g_markup_escape_text(user, -1); |
|
| 952 |
|
| 953 str = g_strdup_printf(_("%s just sent you a Nudge!"), username); |
|
| 954 g_free(username); |
|
| 955 msn_switchboard_report_user(swboard, GAIM_MESSAGE_SYSTEM, str); |
|
| 956 g_free(str); |
|
| 957 } |
|
| 958 |
|
| 959 /************************************************************************** |
|
| 960 * Connect stuff |
|
| 961 **************************************************************************/ |
|
| 962 static void |
|
| 963 connect_cb(MsnServConn *servconn) |
|
| 964 { |
|
| 965 MsnSwitchBoard *swboard; |
|
| 966 MsnCmdProc *cmdproc; |
|
| 967 GaimAccount *account; |
|
| 968 |
|
| 969 cmdproc = servconn->cmdproc; |
|
| 970 g_return_if_fail(cmdproc != NULL); |
|
| 971 |
|
| 972 account = cmdproc->session->account; |
|
| 973 swboard = cmdproc->data; |
|
| 974 g_return_if_fail(swboard != NULL); |
|
| 975 |
|
| 976 if (msn_switchboard_is_invited(swboard)) |
|
| 977 { |
|
| 978 swboard->empty = FALSE; |
|
| 979 |
|
| 980 msn_cmdproc_send(cmdproc, "ANS", "%s %s %s", |
|
| 981 gaim_account_get_username(account), |
|
| 982 swboard->auth_key, swboard->session_id); |
|
| 983 } |
|
| 984 else |
|
| 985 { |
|
| 986 msn_cmdproc_send(cmdproc, "USR", "%s %s", |
|
| 987 gaim_account_get_username(account), |
|
| 988 swboard->auth_key); |
|
| 989 } |
|
| 990 } |
|
| 991 |
|
| 992 static void |
|
| 993 disconnect_cb(MsnServConn *servconn) |
|
| 994 { |
|
| 995 MsnSwitchBoard *swboard; |
|
| 996 |
|
| 997 swboard = servconn->cmdproc->data; |
|
| 998 g_return_if_fail(swboard != NULL); |
|
| 999 |
|
| 1000 msn_servconn_set_disconnect_cb(swboard->servconn, NULL); |
|
| 1001 |
|
| 1002 msn_switchboard_destroy(swboard); |
|
| 1003 } |
|
| 1004 |
|
| 1005 gboolean |
|
| 1006 msn_switchboard_connect(MsnSwitchBoard *swboard, const char *host, int port) |
|
| 1007 { |
|
| 1008 g_return_val_if_fail(swboard != NULL, FALSE); |
|
| 1009 |
|
| 1010 msn_servconn_set_connect_cb(swboard->servconn, connect_cb); |
|
| 1011 msn_servconn_set_disconnect_cb(swboard->servconn, disconnect_cb); |
|
| 1012 |
|
| 1013 return msn_servconn_connect(swboard->servconn, host, port); |
|
| 1014 } |
|
| 1015 |
|
| 1016 void |
|
| 1017 msn_switchboard_disconnect(MsnSwitchBoard *swboard) |
|
| 1018 { |
|
| 1019 g_return_if_fail(swboard != NULL); |
|
| 1020 |
|
| 1021 msn_servconn_disconnect(swboard->servconn); |
|
| 1022 } |
|
| 1023 |
|
| 1024 /************************************************************************** |
|
| 1025 * Call stuff |
|
| 1026 **************************************************************************/ |
|
| 1027 static void |
|
| 1028 got_cal(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 1029 { |
|
| 1030 #if 0 |
|
| 1031 MsnSwitchBoard *swboard; |
|
| 1032 const char *user; |
|
| 1033 |
|
| 1034 swboard = cmdproc->data; |
|
| 1035 |
|
| 1036 user = cmd->params[0]; |
|
| 1037 |
|
| 1038 msn_switchboard_add_user(swboard, user); |
|
| 1039 #endif |
|
| 1040 } |
|
| 1041 |
|
| 1042 static void |
|
| 1043 cal_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans) |
|
| 1044 { |
|
| 1045 gaim_debug_warning("msn", "cal_timeout: command %s timed out\n", trans->command); |
|
| 1046 |
|
| 1047 cal_error_helper(trans, MSN_SB_ERROR_UNKNOWN); |
|
| 1048 } |
|
| 1049 |
|
| 1050 static void |
|
| 1051 cal_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) |
|
| 1052 { |
|
| 1053 int reason = MSN_SB_ERROR_UNKNOWN; |
|
| 1054 |
|
| 1055 if (error == 215) |
|
| 1056 { |
|
| 1057 gaim_debug_info("msn", "Invited user already in switchboard\n"); |
|
| 1058 return; |
|
| 1059 } |
|
| 1060 else if (error == 217) |
|
| 1061 { |
|
| 1062 reason = MSN_SB_ERROR_USER_OFFLINE; |
|
| 1063 } |
|
| 1064 |
|
| 1065 gaim_debug_warning("msn", "cal_error: command %s gave error %i\n", trans->command, error); |
|
| 1066 |
|
| 1067 cal_error_helper(trans, reason); |
|
| 1068 } |
|
| 1069 |
|
| 1070 void |
|
| 1071 msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user) |
|
| 1072 { |
|
| 1073 MsnTransaction *trans; |
|
| 1074 MsnCmdProc *cmdproc; |
|
| 1075 |
|
| 1076 g_return_if_fail(swboard != NULL); |
|
| 1077 |
|
| 1078 cmdproc = swboard->cmdproc; |
|
| 1079 |
|
| 1080 trans = msn_transaction_new(cmdproc, "CAL", "%s", user); |
|
| 1081 /* this doesn't do anything, but users seem to think that |
|
| 1082 * 'Unhandled command' is some kind of error, so we don't report it */ |
|
| 1083 msn_transaction_add_cb(trans, "CAL", got_cal); |
|
| 1084 |
|
| 1085 msn_transaction_set_data(trans, swboard); |
|
| 1086 msn_transaction_set_timeout_cb(trans, cal_timeout); |
|
| 1087 |
|
| 1088 if (swboard->ready) |
|
| 1089 msn_cmdproc_send_trans(cmdproc, trans); |
|
| 1090 else |
|
| 1091 msn_cmdproc_queue_trans(cmdproc, trans); |
|
| 1092 } |
|
| 1093 |
|
| 1094 /************************************************************************** |
|
| 1095 * Create & Transfer stuff |
|
| 1096 **************************************************************************/ |
|
| 1097 |
|
| 1098 static void |
|
| 1099 got_swboard(MsnCmdProc *cmdproc, MsnCommand *cmd) |
|
| 1100 { |
|
| 1101 MsnSwitchBoard *swboard; |
|
| 1102 char *host; |
|
| 1103 int port; |
|
| 1104 swboard = cmd->trans->data; |
|
| 1105 |
|
| 1106 if (g_list_find(cmdproc->session->switches, swboard) == NULL) |
|
| 1107 /* The conversation window was closed. */ |
|
| 1108 return; |
|
| 1109 |
|
| 1110 msn_switchboard_set_auth_key(swboard, cmd->params[4]); |
|
| 1111 |
|
| 1112 msn_parse_socket(cmd->params[2], &host, &port); |
|
| 1113 |
|
| 1114 if (!msn_switchboard_connect(swboard, host, port)) |
|
| 1115 msn_switchboard_destroy(swboard); |
|
| 1116 |
|
| 1117 g_free(host); |
|
| 1118 } |
|
| 1119 |
|
| 1120 static void |
|
| 1121 xfr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) |
|
| 1122 { |
|
| 1123 MsnSwitchBoard *swboard; |
|
| 1124 int reason = MSN_SB_ERROR_UNKNOWN; |
|
| 1125 |
|
| 1126 if (error == 913) |
|
| 1127 reason = MSN_SB_ERROR_OFFLINE; |
|
| 1128 else if (error == 800) |
|
| 1129 reason = MSN_SB_ERROR_TOO_FAST; |
|
| 1130 |
|
| 1131 swboard = trans->data; |
|
| 1132 |
|
| 1133 gaim_debug_info("msn", "xfr_error %i for %s: trans %x, command %s, reason %i\n", |
|
| 1134 error, (swboard->im_user ? swboard->im_user : "(null)"), trans, |
|
| 1135 (trans->command ? trans->command : "(null)"), reason); |
|
| 1136 |
|
| 1137 swboard_error_helper(swboard, reason, swboard->im_user); |
|
| 1138 } |
|
| 1139 |
|
| 1140 void |
|
| 1141 msn_switchboard_request(MsnSwitchBoard *swboard) |
|
| 1142 { |
|
| 1143 MsnCmdProc *cmdproc; |
|
| 1144 MsnTransaction *trans; |
|
| 1145 |
|
| 1146 g_return_if_fail(swboard != NULL); |
|
| 1147 |
|
| 1148 cmdproc = swboard->session->notification->cmdproc; |
|
| 1149 |
|
| 1150 trans = msn_transaction_new(cmdproc, "XFR", "%s", "SB"); |
|
| 1151 msn_transaction_add_cb(trans, "XFR", got_swboard); |
|
| 1152 |
|
| 1153 msn_transaction_set_data(trans, swboard); |
|
| 1154 msn_transaction_set_error_cb(trans, xfr_error); |
|
| 1155 |
|
| 1156 msn_cmdproc_send_trans(cmdproc, trans); |
|
| 1157 } |
|
| 1158 |
|
| 1159 void |
|
| 1160 msn_switchboard_close(MsnSwitchBoard *swboard) |
|
| 1161 { |
|
| 1162 g_return_if_fail(swboard != NULL); |
|
| 1163 |
|
| 1164 if (swboard->error != MSN_SB_ERROR_NONE) |
|
| 1165 { |
|
| 1166 msn_switchboard_destroy(swboard); |
|
| 1167 } |
|
| 1168 else if (g_queue_is_empty(swboard->msg_queue) || |
|
| 1169 !swboard->session->connected) |
|
| 1170 { |
|
| 1171 MsnCmdProc *cmdproc; |
|
| 1172 cmdproc = swboard->cmdproc; |
|
| 1173 msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL); |
|
| 1174 |
|
| 1175 msn_switchboard_destroy(swboard); |
|
| 1176 } |
|
| 1177 else |
|
| 1178 { |
|
| 1179 swboard->closed = TRUE; |
|
| 1180 } |
|
| 1181 } |
|
| 1182 |
|
| 1183 gboolean |
|
| 1184 msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag) |
|
| 1185 { |
|
| 1186 g_return_val_if_fail(swboard != NULL, FALSE); |
|
| 1187 |
|
| 1188 swboard->flag &= ~flag; |
|
| 1189 |
|
| 1190 if (flag == MSN_SB_FLAG_IM) |
|
| 1191 /* Forget any conversation that used to be associated with this |
|
| 1192 * swboard. */ |
|
| 1193 swboard->conv = NULL; |
|
| 1194 |
|
| 1195 if (swboard->flag == 0) |
|
| 1196 { |
|
| 1197 msn_switchboard_close(swboard); |
|
| 1198 return TRUE; |
|
| 1199 } |
|
| 1200 |
|
| 1201 return FALSE; |
|
| 1202 } |
|
| 1203 |
|
| 1204 /************************************************************************** |
|
| 1205 * Init stuff |
|
| 1206 **************************************************************************/ |
|
| 1207 |
|
| 1208 void |
|
| 1209 msn_switchboard_init(void) |
|
| 1210 { |
|
| 1211 cbs_table = msn_table_new(); |
|
| 1212 |
|
| 1213 msn_table_add_cmd(cbs_table, "ANS", "ANS", ans_cmd); |
|
| 1214 msn_table_add_cmd(cbs_table, "ANS", "IRO", iro_cmd); |
|
| 1215 |
|
| 1216 msn_table_add_cmd(cbs_table, "MSG", "ACK", ack_cmd); |
|
| 1217 msn_table_add_cmd(cbs_table, "MSG", "NAK", nak_cmd); |
|
| 1218 |
|
| 1219 msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd); |
|
| 1220 |
|
| 1221 msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd); |
|
| 1222 msn_table_add_cmd(cbs_table, NULL, "JOI", joi_cmd); |
|
| 1223 msn_table_add_cmd(cbs_table, NULL, "BYE", bye_cmd); |
|
| 1224 msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd); |
|
| 1225 |
|
| 1226 #if 0 |
|
| 1227 /* They might skip the history */ |
|
| 1228 msn_table_add_cmd(cbs_table, NULL, "ACK", NULL); |
|
| 1229 #endif |
|
| 1230 |
|
| 1231 msn_table_add_error(cbs_table, "MSG", msg_error); |
|
| 1232 msn_table_add_error(cbs_table, "CAL", cal_error); |
|
| 1233 |
|
| 1234 /* Register the message type callbacks. */ |
|
| 1235 msn_table_add_msg_type(cbs_table, "text/plain", |
|
| 1236 plain_msg); |
|
| 1237 msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol", |
|
| 1238 control_msg); |
|
| 1239 msn_table_add_msg_type(cbs_table, "text/x-clientcaps", |
|
| 1240 clientcaps_msg); |
|
| 1241 msn_table_add_msg_type(cbs_table, "text/x-clientinfo", |
|
| 1242 clientcaps_msg); |
|
| 1243 msn_table_add_msg_type(cbs_table, "application/x-msnmsgrp2p", |
|
| 1244 msn_p2p_msg); |
|
| 1245 msn_table_add_msg_type(cbs_table, "text/x-mms-emoticon", |
|
| 1246 msn_emoticon_msg); |
|
| 1247 msn_table_add_msg_type(cbs_table, "text/x-mms-animemoticon", |
|
| 1248 msn_emoticon_msg); |
|
| 1249 msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast", |
|
| 1250 nudge_msg); |
|
| 1251 #if 0 |
|
| 1252 msn_table_add_msg_type(cbs_table, "text/x-msmmsginvite", |
|
| 1253 msn_invite_msg); |
|
| 1254 #endif |
|
| 1255 } |
|
| 1256 |
|
| 1257 void |
|
| 1258 msn_switchboard_end(void) |
|
| 1259 { |
|
| 1260 msn_table_destroy(cbs_table); |
|
| 1261 } |
|