Mercurial > pidgin.yaz
changeset 10481:bcfea6c3d5c9
[gaim-migrate @ 11769]
Patch 1093958 from Felipe Contreras. It fixes stuff.
I also made some tweaks to make valgrind a bit happier.
committer: Tailor Script <tailor@pidgin.im>
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Fri, 07 Jan 2005 02:48:33 +0000 |
parents | 8e0a91d11362 |
children | 1ac8f10ce68d |
files | src/protocols/msn/cmdproc.c src/protocols/msn/cmdproc.h src/protocols/msn/error.h src/protocols/msn/httpconn.c src/protocols/msn/httpconn.h src/protocols/msn/msg.c src/protocols/msn/msn.c src/protocols/msn/msn.h src/protocols/msn/nexus.c src/protocols/msn/notification.c src/protocols/msn/notification.h src/protocols/msn/servconn.c src/protocols/msn/servconn.h src/protocols/msn/session.c src/protocols/msn/session.h src/protocols/msn/slp.h src/protocols/msn/slpcall.c src/protocols/msn/slplink.c src/protocols/msn/state.c src/protocols/msn/switchboard.c src/protocols/msn/switchboard.h src/protocols/msn/transaction.c |
diffstat | 22 files changed, 726 insertions(+), 739 deletions(-) [+] |
line wrap: on
line diff
--- a/src/protocols/msn/cmdproc.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/cmdproc.c Fri Jan 07 02:48:33 2005 +0000 @@ -43,15 +43,13 @@ { MsnTransaction *trans; - if (cmdproc->last_trans != NULL) - g_free(cmdproc->last_trans); - while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL) msn_transaction_destroy(trans); g_queue_free(cmdproc->txqueue); msn_history_destroy(cmdproc->history); + g_free(cmdproc); } void @@ -59,11 +57,8 @@ { MsnTransaction *trans; - while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL && - cmdproc->error == 0) - { + while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL) msn_cmdproc_send_trans(cmdproc, trans); - } } void @@ -109,19 +104,17 @@ size_t len; g_return_if_fail(cmdproc != NULL); - g_return_if_fail(cmdproc->ready); g_return_if_fail(trans != NULL); servconn = cmdproc->servconn; + + if (!servconn->connected) + return; + msn_history_add(cmdproc->history, trans); data = msn_transaction_to_string(trans); - if (cmdproc->last_trans != NULL) - g_free(cmdproc->last_trans); - - cmdproc->last_trans = g_strdup(data); - len = strlen(data); show_debug_cmd(cmdproc, FALSE, data); @@ -153,11 +146,13 @@ size_t len; g_return_if_fail(cmdproc != NULL); - g_return_if_fail(cmdproc->ready); g_return_if_fail(command != NULL); servconn = cmdproc->servconn; + if (!servconn->connected) + return; + if (format != NULL) { va_start(arg, format); @@ -189,9 +184,11 @@ va_list arg; g_return_if_fail(cmdproc != NULL); - g_return_if_fail(cmdproc->ready); g_return_if_fail(command != NULL); + if (!cmdproc->servconn->connected) + return; + trans = g_new0(MsnTransaction, 1); trans->command = g_strdup(command); @@ -317,19 +314,8 @@ cmd->command); } -#if 1 - /* TODO this is really ugly */ - /* Since commands have not stored payload and we need it for pendent - * commands at the time we process again the same command we will try - * to read again the payload of payload_len size but we will actually - * read sometime else, and reading from server synchronization goes to - * hell. */ - /* Now we store the payload in the command when we queue them :D */ - if (trans != NULL && trans->pendent_cmd != NULL) - if (cmdproc->ready) - msn_transaction_unqueue_cmd(trans, cmdproc); -#endif + msn_transaction_unqueue_cmd(trans, cmdproc); } void @@ -344,32 +330,3 @@ msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd); } - -void -msn_cmdproc_show_error(MsnCmdProc *cmdproc, int error) -{ - GaimConnection *gc = - gaim_account_get_connection(cmdproc->session->account); - - char *tmp; - - tmp = NULL; - - switch (error) - { - case MSN_ERROR_MISC: - tmp = _("Miscellaneous error"); break; - case MSN_ERROR_SIGNOTHER: - gc->wants_to_die = TRUE; - tmp = _("You have signed on from another location."); break; - case MSN_ERROR_SERVDOWN: - tmp = _("The MSN servers are going down temporarily."); break; - default: - break; - } - - if (tmp != NULL) - { - gaim_connection_error(gc, tmp); - } -}
--- a/src/protocols/msn/cmdproc.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/cmdproc.h Fri Jan 07 02:48:33 2005 +0000 @@ -33,11 +33,6 @@ #include "table.h" #include "history.h" -#if 0 -typedef void (*MsnPayloadCb)(MsnCmdProc *cmdproc, char *payload, - size_t len); -#endif - struct _MsnCmdProc { MsnSession *session; @@ -45,14 +40,9 @@ GQueue *txqueue; - gboolean ready; - MsnErrorType error; - MsnCommand *last_cmd; - char *last_trans; MsnTable *cbs_table; - /* MsnPayloadCb payload_cb; */ MsnHistory *history; @@ -81,6 +71,4 @@ void msn_cmdproc_disconnect(MsnCmdProc *cmdproc); -void msn_cmdproc_show_error(MsnCmdProc *cmdproc, int error); - #endif /* _MSN_CMDPROC_H_ */
--- a/src/protocols/msn/error.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/error.h Fri Jan 07 02:48:33 2005 +0000 @@ -24,18 +24,6 @@ #ifndef _MSN_ERROR_H_ #define _MSN_ERROR_H_ -typedef enum -{ - MSN_ERROR_NONE, - MSN_ERROR_MISC, - MSN_ERROR_CONNECT, - MSN_ERROR_WRITE, - MSN_ERROR_READ, - MSN_ERROR_SIGNOTHER, - MSN_ERROR_SERVDOWN - -} MsnErrorType; - #include "session.h" /**
--- a/src/protocols/msn/httpconn.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/httpconn.c Fri Jan 07 02:48:33 2005 +0000 @@ -28,7 +28,7 @@ typedef struct { MsnHttpConn *httpconn; - char *buffer; + char *data; size_t size; } MsnHttpQueueData; @@ -48,6 +48,8 @@ httpconn = g_new0(MsnHttpConn, 1); + gaim_debug_info("msn", "new httpconn (%p)\n", httpconn); + /* TODO: Remove this */ httpconn->session = servconn->session; @@ -61,87 +63,55 @@ { g_return_if_fail(httpconn != NULL); + gaim_debug_info("msn", "destroy httpconn (%p)\n", httpconn); + if (httpconn->connected) msn_httpconn_disconnect(httpconn); - if (httpconn->host != NULL) - g_free(httpconn->host); - g_free(httpconn); } -static void -show_error(MsnHttpConn *httpconn) +static ssize_t +write_raw(MsnHttpConn *httpconn, const char *header, + const char *body, size_t body_len) { - GaimConnection *gc; - char *tmp; - char *cmd; - - const char *names[] = { "Notification", "Switchboard" }; - const char *name; - - gc = gaim_account_get_connection(httpconn->servconn->session->account); - name = names[httpconn->servconn->type]; + char *buf; + size_t buf_len; - switch (httpconn->servconn->cmdproc->error) - { - case MSN_ERROR_CONNECT: - tmp = g_strdup_printf(_("Unable to connect to %s server"), - name); - break; - case MSN_ERROR_WRITE: - tmp = g_strdup_printf(_("Error writing to %s server"), name); - break; - case MSN_ERROR_READ: - cmd = httpconn->servconn->cmdproc->last_trans; - tmp = g_strdup_printf(_("Error reading from %s server"), name); - gaim_debug_info("msn", "Last command was: %s\n", cmd); - break; - default: - tmp = g_strdup_printf(_("Unknown error from %s server"), name); - break; - } - - if (httpconn->servconn->type == MSN_SERVER_NS) - { - gaim_connection_error(gc, tmp); - } - else - { - MsnSwitchBoard *swboard; - swboard = httpconn->servconn->cmdproc->data; - swboard->error = MSN_SB_ERROR_CONNECTION; - } - - g_free(tmp); -} - -static ssize_t -write_raw(MsnHttpConn *httpconn, const void *buffer, size_t len) -{ ssize_t s; ssize_t res; /* result of the write operation */ #ifdef MSN_DEBUG_HTTP - gaim_debug_misc("msn", "Writing HTTP: {%s}\n", buffer); + gaim_debug_misc("msn", "Writing HTTP (header): {%s}\n", header); #endif + buf = g_strdup_printf("%s\r\n", header); + buf_len = strlen(buf); + + if (body != NULL) + { + buf = g_realloc(buf, buf_len + body_len); + memcpy(buf + buf_len, body, body_len); + buf_len += body_len; + } + s = 0; do { - res = write(httpconn->fd, buffer, len); + res = write(httpconn->fd, buf, buf_len); if (res >= 0) { s += res; } else if (errno != EAGAIN) { - httpconn->servconn->cmdproc->error = MSN_ERROR_WRITE; - show_error(httpconn); + msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE); return -1; } - } while (s < len); + } while (s < buf_len); + + g_free(buf); return s; } @@ -149,8 +119,8 @@ void msn_httpconn_poll(MsnHttpConn *httpconn) { + char *header; int r; - char *temp; g_return_if_fail(httpconn != NULL); @@ -160,7 +130,7 @@ return; } - temp = g_strdup_printf( + header = g_strdup_printf( "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n" "Accept: */*\r\n" "Accept-Language: en-us\r\n" @@ -170,15 +140,14 @@ "Connection: Keep-Alive\r\n" "Pragma: no-cache\r\n" "Content-Type: application/x-msn-messenger\r\n" - "Content-Length: 0\r\n" - "\r\n", + "Content-Length: 0\r\n", httpconn->host, httpconn->full_session_id, httpconn->host); - r = write_raw(httpconn, temp, strlen(temp)); + r = write_raw(httpconn, header, NULL, -1); - g_free(temp); + g_free(header); if (r > 0) { @@ -224,7 +193,7 @@ else { gaim_debug_error("msn", "HTTP: Connection error\n"); - show_error(httpconn); + msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT); } } @@ -257,7 +226,9 @@ msn_httpconn_disconnect(MsnHttpConn *httpconn) { g_return_if_fail(httpconn != NULL); - g_return_if_fail(httpconn->connected); + + if (!httpconn->connected) + return; if (httpconn->timer) gaim_timeout_remove(httpconn->timer); @@ -302,7 +273,7 @@ if (len <= 0) { gaim_debug_error("msn", "HTTP: Read error\n"); - show_error(httpconn); + msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); msn_httpconn_disconnect(httpconn); return; @@ -329,7 +300,7 @@ if (error) { gaim_debug_error("msn", "HTTP: Special error\n"); - show_error(httpconn); + msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); msn_httpconn_disconnect(httpconn); return; @@ -341,6 +312,7 @@ #if 0 gaim_debug_info("msn", "HTTP: nothing to do here\n"); #endif + g_free(result_msg); g_free(httpconn->rx_buf); httpconn->rx_buf = NULL; httpconn->rx_len = 0; @@ -351,6 +323,7 @@ httpconn->rx_buf = NULL; httpconn->rx_len = 0; + g_free(servconn->rx_buf); servconn->rx_buf = result_msg; servconn->rx_len = result_len; @@ -425,10 +398,10 @@ httpconn->queue = g_list_remove(httpconn->queue, queue_data); msn_httpconn_write(queue_data->httpconn, - queue_data->buffer, + queue_data->data, queue_data->size); - g_free(queue_data->buffer); + g_free(queue_data->data); g_free(queue_data); } else @@ -438,22 +411,21 @@ } size_t -msn_httpconn_write(MsnHttpConn *httpconn, const char *buf, size_t size) +msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t size) { char *params; - char *temp; + char *header; gboolean first; const char *server_types[] = { "NS", "SB" }; const char *server_type; size_t r; /* result of the write operation */ - size_t len; char *host; MsnServConn *servconn; /* TODO: remove http data from servconn */ g_return_val_if_fail(httpconn != NULL, 0); - g_return_val_if_fail(buf != NULL, 0); + g_return_val_if_fail(data != NULL, 0); g_return_val_if_fail(size > 0, 0); servconn = httpconn->servconn; @@ -463,7 +435,7 @@ MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1); queue_data->httpconn = httpconn; - queue_data->buffer = g_memdup(buf, size); + queue_data->data = g_memdup(data, size); queue_data->size = size; httpconn->queue = g_list_append(httpconn->queue, queue_data); @@ -495,7 +467,7 @@ httpconn->full_session_id); } - temp = g_strdup_printf( + header = g_strdup_printf( "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n" "Accept: */*\r\n" "Accept-Language: en-us\r\n" @@ -505,8 +477,7 @@ "Connection: Keep-Alive\r\n" "Pragma: no-cache\r\n" "Content-Type: application/x-msn-messenger\r\n" - "Content-Length: %d\r\n" - "\r\n", + "Content-Length: %d\r\n", host, params, host, @@ -514,15 +485,9 @@ g_free(params); - len = strlen(temp); - temp = g_realloc(temp, len + size + 1); - memcpy(temp + len, buf, size); - len += size; - temp[len] = '\0'; + r = write_raw(httpconn, header, data, size); - r = write_raw(httpconn, temp, len); - - g_free(temp); + g_free(header); if (r > 0) { @@ -541,7 +506,7 @@ { GaimConnection *gc; const char *s, *c; - char *headers, *body; + char *header, *body; const char *body_start; char *tmp; size_t body_len = 0; @@ -604,12 +569,12 @@ if ((s = strstr(buf, "\r\n\r\n")) == NULL) return FALSE; - headers = g_strndup(buf, s - buf); + header = g_strndup(buf, s - buf); s += 4; /* Skip \r\n */ body_start = s; body_len = size - (body_start - buf); - if ((s = strstr(headers, "Content-Length: ")) != NULL) + if ((s = strstr(header, "Content-Length: ")) != NULL) { int tmp_len; @@ -617,7 +582,7 @@ if ((c = strchr(s, '\r')) == NULL) { - g_free(headers); + g_free(header); return FALSE; } @@ -628,7 +593,7 @@ if (body_len != tmp_len) { - g_free(headers); + g_free(header); #if 0 gaim_debug_warning("msn", @@ -640,14 +605,16 @@ } } - body = g_memdup(body_start, body_len); + body = g_malloc0(body_len + 1); + memcpy(body, body_start, body_len); #ifdef MSN_DEBUG_HTTP - gaim_debug_misc("msn", "Incoming HTTP buffer: {%s\r\n\r\n%s}\n", headers, body); + gaim_debug_misc("msn", "Incoming HTTP buffer (header): {%s\r\n}\n", + header); #endif /* Now we should be able to process the data. */ - if ((s = strstr(headers, "X-MSN-Messenger: ")) != NULL) + if ((s = strstr(header, "X-MSN-Messenger: ")) != NULL) { char *full_session_id, *gw_ip, *session_action; char *t, *session_id; @@ -659,10 +626,12 @@ if ((c = strchr(s, '\r')) == NULL) { - gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); + msn_session_set_error(httpconn->session, + MSN_ERROR_HTTP_MALFORMED, NULL); gaim_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}", buf); + g_free(body); return FALSE; } @@ -731,7 +700,7 @@ } } - g_free(headers); + g_free(header); *ret_buf = body; *ret_size = body_len;
--- a/src/protocols/msn/httpconn.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/httpconn.h Fri Jan 07 02:48:33 2005 +0000 @@ -28,101 +28,79 @@ #include "servconn.h" +/** + * An HTTP Connection. + */ struct _MsnHttpConn { - MsnSession *session; - MsnServConn *servconn; - - char *full_session_id; - char *session_id; + MsnSession *session; /**< The MSN Session. */ + MsnServConn *servconn; /**< The connection object. */ - int timer; + char *full_session_id; /**< The full session id. */ + char *session_id; /**< The trimmed session id. */ - gboolean waiting_response; - gboolean dirty; /**< The flag that states if we should poll. */ - gboolean connected; + int timer; /**< The timer for polling. */ - char *host; - GList *queue; - - int fd; - int inpa; + gboolean waiting_response; /**< The flag that states if we are waiting + a response from the server. */ + gboolean dirty; /**< The flag that states if we should poll. */ + gboolean connected; /**< The flag that states if the connection is on. */ + gboolean virgin; /**< The flag that states if this connection + should specify the host (not gateway) to + connect to. */ - char *rx_buf; - int rx_len; + char *host; /**< The HTTP gateway host. */ + GList *queue; /**< The queue of data chunks to write. */ -#if 0 - GQueue *servconn_queue; -#endif + int fd; /**< The connection's file descriptor. */ + int inpa; /**< The connection's input handler. */ - gboolean virgin; + char *rx_buf; /**< The receive buffer. */ + int rx_len; /**< The receive buffer lenght. */ }; +/** + * Creates a new HTTP connection object. + * + * @param servconn The connection object. + * + * @return The new object. + */ MsnHttpConn *msn_httpconn_new(MsnServConn *servconn); -void msn_httpconn_destroy(MsnHttpConn *httpconn); -size_t msn_httpconn_write(MsnHttpConn *httpconn, const char *buf, size_t size); - -gboolean msn_httpconn_connect(MsnHttpConn *httpconn, - const char *host, int port); -void msn_httpconn_disconnect(MsnHttpConn *httpconn); - -#if 0 -void msn_httpconn_queue_servconn(MsnHttpConn *httpconn, MsnServConn *servconn); -#endif - -#if 0 -/** - * Initializes the HTTP data for a session. - * - * @param session The session. - */ -void msn_http_session_init(MsnSession *session); /** - * Uninitializes the HTTP data for a session. + * Destroys an HTTP connection object. * - * @param session The session. + * @param httpconn The HTTP connection object. */ -void msn_http_session_uninit(MsnSession *session); +void msn_httpconn_destroy(MsnHttpConn *httpconn); /** - * Writes data to the server using the HTTP connection method. + * Writes a chunk of data to the HTTP connection. * * @param servconn The server connection. - * @param buf The data to write. + * @param data The data to write. * @param size The size of the data to write. - * @param server_type The optional server type. * * @return The number of bytes written. */ -size_t msn_http_servconn_write(MsnServConn *servconn, const char *buf, - size_t size, const char *server_type); - -/** - * Polls the server for data. - * - * @param servconn The server connection. - */ -void msn_http_servconn_poll(MsnServConn *servconn); +size_t msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t size); /** - * Processes an incoming message and returns a string the rest of MSN - * can deal with. + * Connects the HTTP connection object to a host. * - * @param servconn The server connection. - * @param buf The incoming buffer. - * @param size The incoming size. - * @param ret_buf The returned buffer. - * @param ret_len The returned length. - * @param error TRUE if there was an HTTP error. + * @param httpconn The HTTP connection object. + * @param host The host to connect to. + * @param port The port to connect to. + */ +gboolean msn_httpconn_connect(MsnHttpConn *httpconn, + const char *host, int port); + +/** + * Disconnects the HTTP connection object. * - * @return TRUE if the returned buffer is ready to be processed. - * FALSE otherwise. + * @param httpconn The HTTP connection object. */ -gboolean msn_http_servconn_parse_data(MsnServConn *servconn, - const char *buf, size_t size, - char **ret_buf, size_t *ret_size, - gboolean *error); -#endif +void msn_httpconn_disconnect(MsnHttpConn *httpconn); #endif /* _MSN_HTTPCONN_H_ */
--- a/src/protocols/msn/msg.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/msg.c Fri Jan 07 02:48:33 2005 +0000 @@ -197,7 +197,8 @@ g_return_if_fail(payload != NULL); - tmp_base = tmp = g_memdup(payload, payload_len); + tmp_base = tmp = g_malloc0(payload_len + 1); + memcpy(tmp_base, payload, payload_len); /* Parse the attributes. */ end = strstr(tmp, "\r\n\r\n");
--- a/src/protocols/msn/msn.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/msn.c Fri Jan 07 02:48:33 2005 +0000 @@ -673,22 +673,23 @@ http_method = TRUE; host = gaim_account_get_string(account, "server", MSN_SERVER); - port = gaim_account_get_int(account, "port", MSN_PORT); + port = gaim_account_get_int(account, "port", MSN_PORT); - session = msn_session_new(account, host, port, http_method); + session = msn_session_new(account); gc->proto_data = session; gc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_FORMATTING_WBFO | GAIM_CONNECTION_NO_BGCOLOR | GAIM_CONNECTION_NO_FONTSIZE | GAIM_CONNECTION_NO_URLDESC; - gaim_connection_update_progress(gc, _("Connecting"), 0, MSN_CONNECT_STEPS); + msn_session_set_login_step(session, MSN_LOGIN_STEP_START); /* Hmm, I don't like this. */ + /* XXX shx: Me neither */ username = msn_normalize(account, gaim_account_get_username(account)); if (strcmp(username, gaim_account_get_username(account))) gaim_account_set_username(account, username); - msn_session_connect(session); + msn_session_connect(session, host, port, http_method); } static void @@ -740,14 +741,7 @@ session = gc->proto_data; swboard = msn_session_get_swboard(session, who); - if (!g_queue_is_empty(swboard->im_queue) || swboard->empty) - { - msn_switchboard_queue_msg(swboard, msg); - } - else - { - msn_switchboard_send_msg(swboard, msg); - } + msn_switchboard_send_msg(swboard, msg, TRUE); } else { @@ -802,13 +796,7 @@ swboard = msn_session_find_swboard(session, who); - if (swboard == NULL) - return 0; - - if (swboard->empty) - return 0; - - if (!g_queue_is_empty(swboard->im_queue)) + if (swboard == NULL || !msn_switchboard_can_send(swboard)) return 0; msg = msn_message_new(MSN_MSG_TYPING); @@ -818,7 +806,7 @@ gaim_account_get_username(account)); msn_message_set_bin_data(msg, "\r\n", 2); - msn_switchboard_send_msg(swboard, msg); + msn_switchboard_send_msg(swboard, msg, FALSE); msn_message_destroy(msg); @@ -1150,7 +1138,7 @@ msg = msn_message_new_plain(msgtext); msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); - msn_switchboard_send_msg(swboard, msg); + msn_switchboard_send_msg(swboard, msg, FALSE); msn_message_destroy(msg); g_free(msgformat); @@ -1169,6 +1157,7 @@ MsnCmdProc *cmdproc; session = gc->proto_data; + cmdproc = session->notification->cmdproc; if (!session->http_method)
--- a/src/protocols/msn/msn.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/msn.h Fri Jan 07 02:48:33 2005 +0000 @@ -45,8 +45,13 @@ #include "ft.h" -/* XXX */ -#include "gaim.h" +/* #define MSN_DEBUG_MSG 1 */ +/* #define MSN_DEBUG_SLPMSG 1 */ +/* #define MSN_DEBUG_HTTP 1 */ + +/* #define MSN_DEBUG_SLP 1 */ +/* #define MSN_DEBUG_SLP_VERBOSE 1 */ +/* #define MSN_DEBUG_SLP_FILES 1 */ #define MSN_BUF_LEN 8192 @@ -67,8 +72,6 @@ #define MSN_FT_GUID "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" -#define MSN_CONNECT_STEPS 8 - #define MSN_CLIENTINFO \ "Client-Name: Gaim/" VERSION "\r\n" \ "Chat-Logging: Y\r\n"
--- a/src/protocols/msn/nexus.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/nexus.c Fri Jan 07 02:48:33 2005 +0000 @@ -26,6 +26,38 @@ #include "notification.h" /************************************************************************** + * Main + **************************************************************************/ + +MsnNexus * +msn_nexus_new(MsnSession *session) +{ + MsnNexus *nexus; + + nexus = g_new0(MsnNexus, 1); + nexus->session = session; + nexus->challenge_data = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + + return nexus; +} + +void +msn_nexus_destroy(MsnNexus *nexus) +{ + if (nexus->login_host != NULL) + g_free(nexus->login_host); + + if (nexus->login_path != NULL) + g_free(nexus->login_path); + + if (nexus->challenge_data != NULL) + g_hash_table_destroy(nexus->challenge_data); + + g_free(nexus); +} + +/************************************************************************** * Util **************************************************************************/ @@ -76,7 +108,7 @@ gc = gaim_account_get_connection(account); g_return_if_fail(gc != NULL); - gaim_connection_error(gc, _("Unable to connect to server")); + msn_session_set_error(session, MSN_ERROR_AUTH, _("Unable to connect")); msn_nexus_destroy(nexus); session->nexus = NULL; @@ -100,6 +132,8 @@ session = nexus->session; g_return_if_fail(session != NULL); + msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); + username = g_strdup(gaim_url_encode(gaim_account_get_username(session->account))); @@ -191,14 +225,15 @@ } else if (strstr(buffer, "HTTP/1.1 401 Unauthorized") != NULL) { - GaimConnection *gc; - const char *error, *c; - char *temp; + const char *error; if ((error = strstr(buffer, "WWW-Authenticate")) != NULL) { if ((error = strstr(error, "cbtxt=")) != NULL) { + const char *c; + char *temp; + error += strlen("cbtxt="); if ((c = strchr(error, '\n')) == NULL) @@ -210,16 +245,7 @@ } } - gc = gaim_account_get_connection(session->account); - - if (error == NULL) - { - gaim_connection_error(gc, - _("Unknown error when attempting to authorize with " - "MSN login server.")); - } - else - gaim_connection_error(gc, error); + msn_session_set_error(session, MSN_ERROR_AUTH, error); } else if (strstr(buffer, "HTTP/1.1 200 OK")) { @@ -264,6 +290,10 @@ g_free(buffer); } +/************************************************************************** + * Connect + **************************************************************************/ + static void nexus_connect_cb(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond) @@ -282,6 +312,8 @@ session = nexus->session; g_return_if_fail(session != NULL); + msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH); + request_str = g_strdup_printf("GET /rdr/pprdr.asp\r\n\r\n"); if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0) @@ -332,38 +364,6 @@ login_error_cb, nexus); } -/************************************************************************** - * Nexus - **************************************************************************/ - -MsnNexus * -msn_nexus_new(MsnSession *session) -{ - MsnNexus *nexus; - - nexus = g_new0(MsnNexus, 1); - nexus->session = session; - nexus->challenge_data = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - return nexus; -} - -void -msn_nexus_destroy(MsnNexus *nexus) -{ - if (nexus->login_host != NULL) - g_free(nexus->login_host); - - if (nexus->login_path != NULL) - g_free(nexus->login_path); - - if (nexus->challenge_data != NULL) - g_hash_table_destroy(nexus->challenge_data); - - g_free(nexus); -} - void msn_nexus_connect(MsnNexus *nexus) {
--- a/src/protocols/msn/notification.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/notification.c Fri Jan 07 02:48:33 2005 +0000 @@ -32,13 +32,12 @@ #include "sync.h" #include "slplink.h" -#define BUDDY_ALIAS_MAXLEN 388 - static MsnTable *cbs_table; /************************************************************************** * Main **************************************************************************/ + static void destroy_cb(MsnServConn *servconn) { @@ -61,7 +60,7 @@ notification = g_new0(MsnNotification, 1); notification->session = session; - notification->servconn = servconn = msn_servconn_new(session, MSN_SERVER_NS); + notification->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_NS); msn_servconn_set_destroy_cb(servconn, destroy_cb); notification->cmdproc = servconn->cmdproc; @@ -74,20 +73,19 @@ void msn_notification_destroy(MsnNotification *notification) { - if (notification->destroying) - return; + notification->cmdproc->data = NULL; - notification->destroying = TRUE; + msn_servconn_set_destroy_cb(notification->servconn, NULL); msn_servconn_destroy(notification->servconn); - notification->session->notification = NULL; g_free(notification); } /************************************************************************** * Connect **************************************************************************/ + static void connect_cb(MsnServConn *servconn) { @@ -113,17 +111,11 @@ vers = g_strjoinv(" ", a); + msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE); msn_cmdproc_send(cmdproc, "VER", "%s", vers); g_strfreev(a); g_free(vers); - - if (cmdproc->error) - return; - - if (session->user == NULL) - session->user = msn_user_new(session->userlist, - gaim_account_get_username(account), NULL); } gboolean @@ -155,6 +147,7 @@ /************************************************************************** * Util **************************************************************************/ + static void group_error_helper(MsnSession *session, const char *msg, int group_id, int error) { @@ -198,6 +191,7 @@ /************************************************************************** * Login **************************************************************************/ + void msn_got_login_params(MsnSession *session, const char *login_params) { @@ -205,6 +199,8 @@ cmdproc = session->notification->cmdproc; + msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END); + msn_cmdproc_send(cmdproc, "USR", "TWN S %s", login_params); } @@ -220,31 +216,6 @@ } static void -inf_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - GaimAccount *account; - GaimConnection *gc; - - account = cmdproc->session->account; - gc = gaim_account_get_connection(account); - - if (strcmp(cmd->params[1], "MD5")) - { - msn_cmdproc_show_error(cmdproc, MSN_ERROR_MISC); - return; - } - - msn_cmdproc_send(cmdproc, "USR", "MD5 I %s", - gaim_account_get_username(account)); - - if (cmdproc->error) - return; - - gaim_connection_update_progress(gc, _("Requesting to send password"), - 5, MSN_CONNECT_STEPS); -} - -static void usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; @@ -255,33 +226,22 @@ account = session->account; gc = gaim_account_get_connection(account); - /* - * We're either getting the passport connect info (if we're on - * MSNP8 or higher), or a challenge request (MSNP7 and lower). - * - * Let's find out. - */ if (!g_ascii_strcasecmp(cmd->params[1], "OK")) { + /* OK */ const char *friendly = gaim_url_decode(cmd->params[3]); - /* OK */ - gaim_connection_set_display_name(gc, friendly); - msn_cmdproc_send(cmdproc, "SYN", "%s", "0"); + msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN); - if (cmdproc->error) - return; - - gaim_connection_update_progress(gc, _("Retrieving buddy list"), - 7, MSN_CONNECT_STEPS); + msn_cmdproc_send(cmdproc, "SYN", "%s", "0"); } else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")) { + /* Passport authentication */ char **elems, **cur, **tokens; - /* Passport authentication */ session->nexus = msn_nexus_new(session); /* Parse the challenge data. */ @@ -298,39 +258,9 @@ g_strfreev(elems); - msn_nexus_connect(session->nexus); - - gaim_connection_update_progress(gc, _("Password sent"), - 6, MSN_CONNECT_STEPS); - } - else if (!g_ascii_strcasecmp(cmd->params[1], "MD5")) - { - /* Challenge */ - const char *challenge; - const char *password; - char buf[33]; - md5_state_t st; - md5_byte_t di[16]; - int i; + msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START); - challenge = cmd->params[3]; - password = gaim_account_get_password(account); - - md5_init(&st); - md5_append(&st, (const md5_byte_t *)challenge, strlen(challenge)); - md5_append(&st, (const md5_byte_t *)password, strlen(password)); - md5_finish(&st, di); - - for (i = 0; i < 16; i++) - g_snprintf(buf + (i*2), 3, "%02x", di[i]); - - msn_cmdproc_send(cmdproc, "USR", "MD5 S %s", buf); - - if (cmdproc->error) - return; - - gaim_connection_update_progress(gc, _("Password sent"), - 6, MSN_CONNECT_STEPS); + msn_nexus_connect(session->nexus); } } @@ -359,7 +289,8 @@ if (!protocol_supported) { - msn_cmdproc_show_error(cmdproc, MSN_ERROR_MISC); + msn_session_set_error(session, MSN_ERROR_UNSUPORTED_PROTOCOL, + NULL); return; } @@ -371,13 +302,15 @@ /************************************************************************** * Log out **************************************************************************/ + static void out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { if (!g_ascii_strcasecmp(cmd->params[0], "OTH")) - msn_cmdproc_show_error(cmdproc, MSN_ERROR_SIGNOTHER); + msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER, + NULL); else if (!g_ascii_strcasecmp(cmd->params[0], "SSD")) - msn_cmdproc_show_error(cmdproc, MSN_ERROR_SERVDOWN); + msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL); } void @@ -393,6 +326,7 @@ /************************************************************************** * Messages **************************************************************************/ + static void msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) @@ -431,6 +365,7 @@ /************************************************************************** * Challenges **************************************************************************/ + static void chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { @@ -464,6 +399,7 @@ /************************************************************************** * Buddy Lists **************************************************************************/ + static void add_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { @@ -874,22 +810,13 @@ if (cmd->param_count == 2) { - char *buf; /* * This can happen if we sent a SYN with an up-to-date * buddy list revision, but we send 0 to get a full list. * So, error out. */ - buf = g_strdup_printf( - _("Your MSN buddy list for %s is temporarily unavailable. " - "Please wait and try again."), - gaim_account_get_username(session->account)); - gaim_connection_error(gaim_account_get_connection(session->account), - buf); - - g_free(buf); - + msn_session_set_error(cmdproc->session, MSN_ERROR_BAD_BLIST, NULL); return; } @@ -916,6 +843,7 @@ /************************************************************************** * Misc commands **************************************************************************/ + static void url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { @@ -1018,6 +946,7 @@ /************************************************************************** * Switchboards **************************************************************************/ + static void rng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { @@ -1056,7 +985,8 @@ if (strcmp(cmd->params[1], "SB") && strcmp(cmd->params[1], "NS")) { - msn_cmdproc_show_error(cmdproc, MSN_ERROR_MISC); + /* Maybe we can have a generic bad command error. */ + gaim_debug_error("msn", "Bad XFR command (%s)\n", cmd->params[1]); return; } @@ -1065,19 +995,6 @@ if (!strcmp(cmd->params[1], "SB")) { gaim_debug_error("msn", "This shouldn't be handled here.\n"); -#if 0 - swboard = cmd->trans->data; - - if (swboard != NULL) - { - msn_switchboard_set_auth_key(swboard, cmd->params[4]); - - if (session->http_method) - port = 80; - - msn_switchboard_connect(swboard, host, port); - } -#endif } else if (!strcmp(cmd->params[1], "NS")) { @@ -1085,6 +1002,9 @@ session = cmdproc->session; + if (!session->logged_in) + msn_session_set_login_step(session, MSN_LOGIN_STEP_TRANSFER); + msn_notification_connect(session->notification, host, port); } @@ -1094,6 +1014,7 @@ /************************************************************************** * Message Types **************************************************************************/ + static void profile_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { @@ -1343,6 +1264,7 @@ /************************************************************************** * Init **************************************************************************/ + void msn_notification_init(void) { @@ -1360,7 +1282,6 @@ msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd); msn_table_add_cmd(cbs_table, "SYN", "SYN", syn_cmd); msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd); - msn_table_add_cmd(cbs_table, "INF", "INF", inf_cmd); msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd); msn_table_add_cmd(cbs_table, "REA", "REA", rea_cmd); /* msn_table_add_cmd(cbs_table, "PRP", "PRP", prp_cmd); */
--- a/src/protocols/msn/notification.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/notification.h Fri Jan 07 02:48:33 2005 +0000 @@ -36,9 +36,6 @@ MsnCmdProc *cmdproc; MsnServConn *servconn; - gboolean destroying; /**< A flag that states if the notification is on - the process of being destroyed. */ - gboolean in_use; };
--- a/src/protocols/msn/servconn.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/servconn.c Fri Jan 07 02:48:33 2005 +0000 @@ -27,6 +27,10 @@ static void read_cb(gpointer data, gint source, GaimInputCondition cond); +/************************************************************************** + * Main + **************************************************************************/ + MsnServConn * msn_servconn_new(MsnSession *session, MsnServConnType type) { @@ -42,8 +46,7 @@ servconn->cmdproc = msn_cmdproc_new(session); servconn->cmdproc->servconn = servconn; - if (session->http_method) - servconn->httpconn = msn_httpconn_new(servconn); + servconn->httpconn = msn_httpconn_new(servconn); servconn->num = session->servconns_count++; @@ -61,11 +64,6 @@ return; } - if (servconn->destroying) - return; - - servconn->destroying = TRUE; - if (servconn->connected) msn_servconn_disconnect(servconn); @@ -82,52 +80,83 @@ g_free(servconn); } -static void -show_error(MsnServConn *servconn) +void +msn_servconn_set_connect_cb(MsnServConn *servconn, + void (*connect_cb)(MsnServConn *)) +{ + g_return_if_fail(servconn != NULL); + servconn->connect_cb = connect_cb; +} + +void +msn_servconn_set_disconnect_cb(MsnServConn *servconn, + void (*disconnect_cb)(MsnServConn *)) { - GaimConnection *gc; + g_return_if_fail(servconn != NULL); + + servconn->disconnect_cb = disconnect_cb; +} + +void +msn_servconn_set_destroy_cb(MsnServConn *servconn, + void (*destroy_cb)(MsnServConn *)) +{ + g_return_if_fail(servconn != NULL); + + servconn->destroy_cb = destroy_cb; +} + +/************************************************************************** + * Utility + **************************************************************************/ + +void +msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error) +{ char *tmp; - char *cmd; + const char *reason; const char *names[] = { "Notification", "Switchboard" }; const char *name; - gc = gaim_account_get_connection(servconn->session->account); name = names[servconn->type]; - switch (servconn->cmdproc->error) + switch (error) { - case MSN_ERROR_CONNECT: - tmp = g_strdup_printf(_("Unable to connect to %s server"), - name); - break; - case MSN_ERROR_WRITE: - tmp = g_strdup_printf(_("Error writing to %s server"), name); - break; - case MSN_ERROR_READ: - cmd = servconn->cmdproc->last_trans; - tmp = g_strdup_printf(_("Error reading from %s server"), name); - gaim_debug_info("msn", "Last command was: %s\n", cmd); - break; + case MSN_SERVCONN_ERROR_CONNECT: + reason = _("Unable to connect"); break; + case MSN_SERVCONN_ERROR_WRITE: + reason = _("Writing error"); break; + case MSN_SERVCONN_ERROR_READ: + reason = _("Reading error"); break; default: - tmp = g_strdup_printf(_("Unknown error from %s server"), name); - break; + reason = _("Unknown error"); break; } - if (servconn->type != MSN_SERVER_SB) + tmp = g_strdup_printf(_("Connection error from %s server (%s):\n%s"), + name, servconn->host, reason); + + if (servconn->type == MSN_SERVCONN_NS) { - gaim_connection_error(gc, tmp); + msn_session_set_error(servconn->session, MSN_ERROR_SERVCONN, tmp); } - else + else if (servconn->type == MSN_SERVCONN_SB) { MsnSwitchBoard *swboard; swboard = servconn->cmdproc->data; - swboard->error = MSN_SB_ERROR_CONNECTION; + if (swboard != NULL) + swboard->error = MSN_SB_ERROR_CONNECTION; } + msn_servconn_disconnect(servconn); + g_free(tmp); } +/************************************************************************** + * Connect + **************************************************************************/ + static void connect_cb(gpointer data, gint source, GaimInputCondition cond) { @@ -146,7 +175,6 @@ if (source > 0) { servconn->connected = TRUE; - servconn->cmdproc->ready = TRUE; /* Someone wants to know we connected. */ servconn->connect_cb(servconn); @@ -155,8 +183,7 @@ } else { - servconn->cmdproc->error = MSN_ERROR_CONNECT; - show_error(servconn); + msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_CONNECT); } } @@ -188,7 +215,6 @@ msn_httpconn_connect(servconn->httpconn, host, port); servconn->connected = TRUE; - servconn->cmdproc->ready = TRUE; servconn->httpconn->virgin = TRUE; /* Someone wants to know we connected. */ @@ -216,6 +242,7 @@ if (!servconn->connected) { + /* We could not connect. */ if (servconn->disconnect_cb != NULL) servconn->disconnect_cb(servconn); @@ -224,7 +251,7 @@ if (servconn->session->http_method) { - /* Fake disconnection */ + /* Fake disconnection. */ if (servconn->disconnect_cb != NULL) servconn->disconnect_cb(servconn); @@ -244,48 +271,11 @@ servconn->payload_len = 0; servconn->connected = FALSE; - servconn->cmdproc->ready = FALSE; if (servconn->disconnect_cb != NULL) servconn->disconnect_cb(servconn); } -void -msn_servconn_set_connect_cb(MsnServConn *servconn, - void (*connect_cb)(MsnServConn *)) -{ - g_return_if_fail(servconn != NULL); - servconn->connect_cb = connect_cb; -} - -void -msn_servconn_set_disconnect_cb(MsnServConn *servconn, - void (*disconnect_cb)(MsnServConn *)) -{ - g_return_if_fail(servconn != NULL); - - servconn->disconnect_cb = disconnect_cb; -} - -void -msn_servconn_set_destroy_cb(MsnServConn *servconn, - void (*destroy_cb)(MsnServConn *)) -{ - g_return_if_fail(servconn != NULL); - - servconn->destroy_cb = destroy_cb; -} - -static void -failed_io(MsnServConn *servconn) -{ - g_return_if_fail(servconn != NULL); - - show_error(servconn); - - msn_servconn_disconnect(servconn); -} - size_t msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len) { @@ -297,14 +287,16 @@ { switch (servconn->type) { - case MSN_SERVER_NS: - case MSN_SERVER_SB: + case MSN_SERVCONN_NS: + case MSN_SERVCONN_SB: ret = write(servconn->fd, buf, len); break; - case MSN_SERVER_DC: +#if 0 + case MSN_SERVCONN_DC: ret = write(servconn->fd, &buf, sizeof(len)); ret = write(servconn->fd, buf, len); break; +#endif default: ret = write(servconn->fd, buf, len); break; @@ -317,8 +309,7 @@ if (ret == -1) { - servconn->cmdproc->error = MSN_ERROR_WRITE; - failed_io(servconn); + msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE); } return ret; @@ -340,9 +331,7 @@ if (len <= 0) { - servconn->cmdproc->error = MSN_ERROR_READ; - - failed_io(servconn); + msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ); return; }
--- a/src/protocols/msn/servconn.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/servconn.h Fri Jan 07 02:48:33 2005 +0000 @@ -32,21 +32,30 @@ #include "proxy.h" #include "httpconn.h" -/* - * Connection types +/** + * Connection error types. */ typedef enum { - MSN_SERVER_NS, - MSN_SERVER_SB, - MSN_SERVER_NX, - MSN_SERVER_DC, - MSN_SERVER_HT + MSN_SERVCONN_ERROR_NONE, + MSN_SERVCONN_ERROR_CONNECT, + MSN_SERVCONN_ERROR_WRITE, + MSN_SERVCONN_ERROR_READ, + +} MsnServConnError; + +/** + * Connection types. + */ +typedef enum +{ + MSN_SERVCONN_NS, + MSN_SERVCONN_SB } MsnServConnType; -/* - * A Connection +/** + * A Connection. */ struct _MsnServConn { @@ -58,8 +67,6 @@ gboolean processing; /**< A flag that states if something is working with this connection. */ gboolean wasted; /**< A flag that states if it should be destroyed. */ - gboolean destroying; /**< A flag that states if the connection is on - the process of being destroyed. */ char *host; /**< The host this connection is connected or should be connected to. */ @@ -148,4 +155,12 @@ size_t msn_servconn_write(MsnServConn *servconn, const char *buf, size_t size); +/** + * Function to call whenever an error related to a switchboard occurs. + * + * @param servconn The servconn. + * @param error The error that happened. + */ +void msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error); + #endif /* _MSN_SERVCONN_H_ */
--- a/src/protocols/msn/session.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/session.c Fri Jan 07 02:48:33 2005 +0000 @@ -28,8 +28,7 @@ #include "dialog.h" MsnSession * -msn_session_new(GaimAccount *account, const char *host, int port, - gboolean http_method) +msn_session_new(GaimAccount *account) { MsnSession *session; @@ -37,15 +36,14 @@ session = g_new0(MsnSession, 1); - session->account = account; - session->dispatch_host = g_strdup(host); - session->dispatch_port = port; - session->http_method = http_method; - + session->account = account; session->notification = msn_notification_new(session); session->userlist = msn_userlist_new(session); session->sync_userlist = msn_userlist_new(session); + session->user = msn_user_new(session->userlist, + gaim_account_get_username(account), NULL); + session->protocol_ver = 9; return session; @@ -61,9 +59,6 @@ if (session->connected) msn_session_disconnect(session); - if (session->dispatch_host != NULL) - g_free(session->dispatch_host); - if (session->notification != NULL) msn_notification_destroy(session->notification); @@ -102,16 +97,21 @@ if (session->nexus != NULL) msn_nexus_destroy(session->nexus); + if (session->user != NULL) + msn_user_destroy(session->user); + g_free(session); } gboolean -msn_session_connect(MsnSession *session) +msn_session_connect(MsnSession *session, const char *host, int port, + gboolean http_method) { g_return_val_if_fail(session != NULL, FALSE); g_return_val_if_fail(!session->connected, TRUE); session->connected = TRUE; + session->http_method = http_method; if (session->notification == NULL) { @@ -119,9 +119,7 @@ g_return_val_if_reached(FALSE); } - if (msn_notification_connect(session->notification, - session->dispatch_host, - session->dispatch_port)) + if (msn_notification_connect(session->notification, host, port)) { return TRUE; } @@ -135,13 +133,13 @@ g_return_if_fail(session != NULL); g_return_if_fail(session->connected); + session->connected = FALSE; + while (session->switches != NULL) msn_switchboard_close(session->switches->data); if (session->notification != NULL) msn_notification_close(session->notification); - - session->connected = FALSE; } /* TODO: This must go away when conversation is redesigned */ @@ -278,6 +276,86 @@ } void +msn_session_set_error(MsnSession *session, MsnErrorType error, + const char *info) +{ + GaimConnection *gc; + char *msg; + + gc = session->account->gc; + + switch (error) + { + case MSN_ERROR_SERVCONN: + msg = g_strdup(info); + break; + case MSN_ERROR_UNSUPORTED_PROTOCOL: + msg = g_strdup(_("Our protocol is not supported by the " + "server.")); + break; + case MSN_ERROR_HTTP_MALFORMED: + msg = g_strdup(_("Error parsing HTTP.")); + break; + case MSN_ERROR_SIGN_OTHER: + gc->wants_to_die = TRUE; + msg = g_strdup(_("You have signed on from another location.")); + break; + case MSN_ERROR_SERV_DOWN: + msg = g_strdup(_("The MSN servers are going down " + "temporarily.")); + break; + case MSN_ERROR_AUTH: + msg = g_strdup_printf(_("Unable to authenticate: %s"), + (info == NULL ) ? + _("Unknown error") : info); + break; + case MSN_ERROR_BAD_BLIST: + msg = g_strdup(_("Your MSN buddy list is temporarily " + "unavailable. Please wait and try " + "again.")); + break; + default: + msg = g_strdup(_("Unknown error.")); + break; + } + + msn_session_disconnect(session); + gaim_connection_error(gc, msg); + + g_free(msg); +} + +static const char * +get_login_step_text(MsnSession *session) +{ + const char *steps_text[] = { + _("Connecting"), + _("Handshaking"), + _("Transfering"), + _("Starting authentication"), + _("Getting cookie"), + _("Authenticating"), + _("Sending cookie"), + _("Retrieving buddy list") + }; + + return steps_text[session->login_step]; +} + +void +msn_session_set_login_step(MsnSession *session, MsnLoginStep step) +{ + GaimConnection *gc; + + gc = session->account->gc; + + session->login_step = step; + + gaim_connection_update_progress(gc, get_login_step_text(session), step, + MSN_LOGIN_STEPS); +} + +void msn_session_finish_login(MsnSession *session) { GaimAccount *account;
--- a/src/protocols/msn/session.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/session.h Fri Jan 07 02:48:33 2005 +0000 @@ -40,6 +40,40 @@ #include "userlist.h" #include "sync.h" +/** + * Types of errors. + */ +typedef enum +{ + MSN_ERROR_SERVCONN, + MSN_ERROR_UNSUPORTED_PROTOCOL, + MSN_ERROR_HTTP_MALFORMED, + MSN_ERROR_AUTH, + MSN_ERROR_BAD_BLIST, + MSN_ERROR_SIGN_OTHER, + MSN_ERROR_SERV_DOWN + +} MsnErrorType; + +/** + * Login steps. + */ +typedef enum +{ + MSN_LOGIN_STEP_START, + MSN_LOGIN_STEP_HANDSHAKE, + MSN_LOGIN_STEP_TRANSFER, + MSN_LOGIN_STEP_AUTH_START, + MSN_LOGIN_STEP_AUTH, + MSN_LOGIN_STEP_GET_COOKIE, + MSN_LOGIN_STEP_AUTH_END, + MSN_LOGIN_STEP_SYN, + MSN_LOGIN_STEP_END + +} MsnLoginStep; + +#define MSN_LOGIN_STEPS MSN_LOGIN_STEP_END + struct _MsnSession { GaimAccount *account; @@ -48,18 +82,16 @@ guint protocol_ver; - char *dispatch_host; - int dispatch_port; + MsnLoginStep login_step; /**< The current step in the login process. */ gboolean connected; gboolean logged_in; /**< A temporal flag to ignore local buddy list adds. */ gboolean destroying; /**< A flag that states if the session is being destroyed. */ + gboolean http_method; MsnNotification *notification; MsnNexus *nexus; - - gboolean http_method; - gint http_poll_timer; + MsnSync *sync; MsnUserList *userlist; MsnUserList *sync_userlist; @@ -67,8 +99,9 @@ int servconns_count; /**< The count of server connections. */ GList *switches; /**< The list of all the switchboards. */ GList *directconns; /**< The list of all the directconnections. */ + GList *slplinks; /**< The list of all the slplinks. */ - int conv_seq; + int conv_seq; /**< The current conversation sequence number. */ struct { @@ -81,27 +114,16 @@ int client_port; } passport_info; - - /* You have no idea how much I hate all that is below. */ - /* shx: What? ;) */ - - MsnSync *sync; - - GList *slplinks; }; /** * Creates an MSN session. * * @param account The account. - * @param host The dispatch server host. - * @param port The dispatch server port. * * @return The new MSN session. */ -MsnSession *msn_session_new(GaimAccount *account, - const char *host, int port, - gboolean http_method); +MsnSession *msn_session_new(GaimAccount *account); /** * Destroys an MSN session. @@ -113,11 +135,16 @@ /** * Connects to and initiates an MSN session. * - * @param session The MSN session. + * @param session The MSN session. + * @param host The dispatch server host. + * @param port The dispatch server port. + * @param http_method Whether to use or not http_method. * * @return @c TRUE on success, @c FALSE on failure. */ -gboolean msn_session_connect(MsnSession *session); +gboolean msn_session_connect(MsnSession *session, + const char *host, int port, + gboolean http_method); /** * Disconnects from an MSN session. @@ -142,6 +169,29 @@ MsnSwitchBoard *msn_session_get_swboard(MsnSession *session, const char *username); +/** + * Sets an error for the MSN session. + * + * @param session The MSN session. + * @param error The error. + * @param info Extra information. + */ +void msn_session_set_error(MsnSession *session, MsnErrorType error, + const char *info); + +/** + * Sets the current step in the login proccess. + * + * @param session The MSN session. + * @param step The current step. + */ +void msn_session_set_login_step(MsnSession *session, MsnLoginStep step); + +/** + * Finish the login proccess. + * + * @param session The MSN session. + */ void msn_session_finish_login(MsnSession *session); #endif /* _MSN_SESSION_H_ */
--- a/src/protocols/msn/slp.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/slp.h Fri Jan 07 02:48:33 2005 +0000 @@ -24,13 +24,6 @@ #ifndef _MSN_SLP_H_ #define _MSN_SLP_H_ -/* #define MSN_DEBUG_MSG 1 */ -/* #define MSN_DEBUG_SLPMSG 1 */ - -/* #define MSN_DEBUG_SLP 1 */ -/* #define MSN_DEBUG_SLP_VERBOSE 1 */ -/* #define MSN_DEBUG_SLP_FILES 1 */ - #include "slpcall.h" #include "ft.h"
--- a/src/protocols/msn/slpcall.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/slpcall.c Fri Jan 07 02:48:33 2005 +0000 @@ -96,11 +96,15 @@ g_return_if_fail(slpmsg != NULL); +#if 0 gaim_debug_info("msn", "slpcall destroy: trying slp_msg (%p)\n", slpmsg); +#endif if (slpmsg->slpcall == slpcall) + { msn_slpmsg_destroy(slpmsg); + } } if (slpcall->end_cb != NULL) @@ -188,7 +192,7 @@ { MsnSlpCall *slpcall; - gaim_debug_info("msn", "slpcall timeout\n"); + gaim_debug_info("msn", "slpcall timeout (%p)\n", slpcall); slpcall = data;
--- a/src/protocols/msn/slplink.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/slplink.c Fri Jan 07 02:48:33 2005 +0000 @@ -213,15 +213,7 @@ slplink->swboard->slplink = slplink; } - if (!g_queue_is_empty(slplink->swboard->im_queue) || - slplink->swboard->empty) - { - msn_switchboard_queue_msg(slplink->swboard, msg); - } - else - { - msn_switchboard_send_msg(slplink->swboard, msg); - } + msn_switchboard_send_msg(slplink->swboard, msg, TRUE); } }
--- a/src/protocols/msn/state.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/state.c Fri Jan 07 02:48:33 2005 +0000 @@ -46,12 +46,13 @@ MsnObject *msnobj; const char *state_text; + g_return_if_fail(session != NULL); + g_return_if_fail(session->notification != NULL); + cmdproc = session->notification->cmdproc; user = session->user; state_text = msn_state_get_text(state); - g_return_if_fail(session != NULL); - msnobj = msn_user_get_object(user); if (msnobj == NULL)
--- a/src/protocols/msn/switchboard.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/switchboard.c Fri Jan 07 02:48:33 2005 +0000 @@ -35,8 +35,9 @@ MsnMsgErrorType error); /************************************************************************** - * Main stuff + * Main **************************************************************************/ + MsnSwitchBoard * msn_switchboard_new(MsnSession *session) { @@ -48,10 +49,10 @@ swboard = g_new0(MsnSwitchBoard, 1); swboard->session = session; - swboard->servconn = servconn = msn_servconn_new(session, MSN_SERVER_SB); + swboard->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_SB); swboard->cmdproc = servconn->cmdproc; - swboard->im_queue = g_queue_new(); + swboard->msg_queue = g_queue_new(); swboard->empty = TRUE; swboard->cmdproc->data = swboard; @@ -71,17 +72,12 @@ g_return_if_fail(swboard != NULL); - if (swboard->destroying) - return; - - swboard->destroying = TRUE; - /* If it linked us is because its looking for trouble */ if (swboard->slplink != NULL) msn_slplink_destroy(swboard->slplink); /* Destroy the message queue */ - while ((msg = g_queue_pop_head(swboard->im_queue)) != NULL) + while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) { if (swboard->error != MSN_SB_ERROR_NONE) { @@ -92,7 +88,7 @@ msn_message_unref(msg); } - g_queue_free(swboard->im_queue); + g_queue_free(swboard->msg_queue); for (l = swboard->ack_list; l != NULL; l = l->next) msn_message_unref(l->data); @@ -112,8 +108,17 @@ 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); } @@ -172,8 +177,9 @@ } /************************************************************************** - * Utility functions + * Utility **************************************************************************/ + static void send_clientcaps(MsnSwitchBoard *swboard) { @@ -184,7 +190,7 @@ msn_message_set_flag(msg, 'U'); msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO)); - msn_switchboard_send_msg(swboard, msg); + msn_switchboard_send_msg(swboard, msg, TRUE); msn_message_destroy(msg); } @@ -425,8 +431,165 @@ } /************************************************************************** + * Message Stuff + **************************************************************************/ + +/** Called when a message times out. */ +static void +msg_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans) +{ + MsnMessage *msg; + + msg = trans->data; + + msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_TIMEOUT); +} + +/** Called when we receive an error of a message. */ +static void +msg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) +{ + msg_error_helper(cmdproc, trans->data, MSN_MSG_ERROR_UNKNOWN); +} + +#if 0 +/** Called when we receive an ack of a special message. */ +static void +msg_ack(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + MsnMessage *msg; + + msg = cmd->trans->data; + + if (msg->ack_cb != NULL) + msg->ack_cb(msg->ack_data); + + msn_message_unref(msg); +} + +/** Called when we receive a nak of a special message. */ +static void +msg_nak(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + MsnMessage *msg; + + msg = cmd->trans->data; + + msn_message_unref(msg); +} +#endif + +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); + + /* msn_message_show_readable(msg, "SB SEND", FALSE); */ + + 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); + + gaim_debug_info("msn", "Appending message to queue.\n"); + + g_queue_push_tail(swboard->msg_queue, msg); + + msn_message_ref(msg); +} + +static void +process_queue(MsnSwitchBoard *swboard) +{ + MsnMessage *msg; + + g_return_if_fail(swboard != NULL); + + gaim_debug_info("msn", "Processing queue\n"); + + while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) + { + gaim_debug_info("msn", "Sending message\n"); + release_msg(swboard, msg); + msn_message_unref(msg); + } +} + +gboolean +msn_switchboard_can_send(MsnSwitchBoard *swboard) +{ + g_return_val_if_fail(swboard != NULL, FALSE); + + if (swboard->empty || !g_queue_is_empty(swboard->msg_queue)) + return FALSE; + + return TRUE; +} + +void +msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg, + gboolean queue) +{ + g_return_if_fail(swboard != NULL); + g_return_if_fail(msg != NULL); + + if (msn_switchboard_can_send(swboard)) + release_msg(swboard, msg); + else if (queue) + queue_msg(swboard, msg); +} + +/************************************************************************** * Switchboard Commands **************************************************************************/ + static void ans_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { @@ -532,7 +695,7 @@ msn_switchboard_add_user(swboard, passport); - msn_switchboard_process_queue(swboard); + process_queue(swboard); if (!session->http_method) send_clientcaps(swboard); @@ -739,137 +902,6 @@ } /************************************************************************** - * Message stuff - **************************************************************************/ -/** Called when a message times out. */ -static void -msg_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans) -{ - MsnMessage *msg; - - msg = trans->data; - - msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_TIMEOUT); -} - -/** Called when we receive an error of a message. */ -static void -msg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - msg_error_helper(cmdproc, trans->data, MSN_MSG_ERROR_UNKNOWN); -} - -#if 0 -/** Called when we receive an ack of a special message. */ -static void -msg_ack(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnMessage *msg; - - msg = cmd->trans->data; - - if (msg->ack_cb != NULL) - msg->ack_cb(msg->ack_data); - - msn_message_unref(msg); -} - -/** Called when we receive a nak of a special message. */ -static void -msg_nak(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnMessage *msg; - - msg = cmd->trans->data; - - msn_message_unref(msg); -} -#endif - -void -msn_switchboard_send_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); - - /* msn_message_show_readable(msg, "SB SEND", FALSE); */ - - 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); -} - -void -msn_switchboard_queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg) -{ - g_return_if_fail(swboard != NULL); - g_return_if_fail(msg != NULL); - - gaim_debug_info("msn", "Appending message to queue.\n"); - - g_queue_push_tail(swboard->im_queue, msg); - - msn_message_ref(msg); -} - -void -msn_switchboard_process_queue(MsnSwitchBoard *swboard) -{ - MsnMessage *msg; - - g_return_if_fail(swboard != NULL); - - gaim_debug_info("msn", "Processing queue\n"); - - while ((msg = g_queue_pop_head(swboard->im_queue)) != NULL) - { - gaim_debug_info("msn", "Sending message\n"); - msn_switchboard_send_msg(swboard, msg); - msn_message_unref(msg); - } -} - -/************************************************************************** * Connect stuff **************************************************************************/ static void @@ -882,8 +914,6 @@ cmdproc = servconn->cmdproc; g_return_if_fail(cmdproc != NULL); - cmdproc->ready = TRUE; - account = cmdproc->session->account; swboard = cmdproc->data; g_return_if_fail(swboard != NULL); @@ -912,6 +942,8 @@ swboard = servconn->cmdproc->data; g_return_if_fail(swboard != NULL); + msn_servconn_set_disconnect_cb(swboard->servconn, NULL); + msn_switchboard_destroy(swboard); } @@ -1003,6 +1035,7 @@ /************************************************************************** * Create & Transfer stuff **************************************************************************/ + static void got_swboard(MsnCmdProc *cmdproc, MsnCommand *cmd) { @@ -1062,23 +1095,29 @@ { g_return_if_fail(swboard != NULL); - if (g_queue_is_empty(swboard->im_queue)) + if (swboard->error != MSN_SB_ERROR_NONE) + { + msn_switchboard_destroy(swboard); + } + else if (g_queue_is_empty(swboard->msg_queue) || + !swboard->session->connected) { MsnCmdProc *cmdproc; - cmdproc = swboard->cmdproc; - msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL); msn_switchboard_destroy(swboard); } else + { swboard->closed = TRUE; + } } /************************************************************************** * Init stuff **************************************************************************/ + void msn_switchboard_init(void) {
--- a/src/protocols/msn/switchboard.h Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/switchboard.h Fri Jan 07 02:48:33 2005 +0000 @@ -35,8 +35,8 @@ #include "slplink.h" -/* - * A switchboard error +/** + * A switchboard error. */ typedef enum { @@ -49,9 +49,10 @@ } MsnSBErrorType; -/* - * A switchboard A place where a bunch of users send messages to the rest - * of the users. +/** + * A switchboard. + * + * A place where a bunch of users send messages to the rest of the users. */ struct _MsnSwitchBoard { @@ -71,8 +72,6 @@ users in it. */ gboolean invited; /**< A flag that states if we were invited to the switchboard. */ - gboolean destroying; /**< A flag that states if the switchboard is on - the process of being destroyed. */ gboolean ready; /**< A flag that states if this switchboard is ready to be used. */ gboolean closed; /**< A flag that states if the switchboard has @@ -84,7 +83,7 @@ int chat_id; - GQueue *im_queue; /**< Queue of messages to send. */ + GQueue *msg_queue; /**< Queue of messages to send. */ GList *ack_list; /**< List of messages waiting for an ack. */ MsnSBErrorType error; /**< The error that occurred in this switchboard @@ -197,9 +196,28 @@ */ void msn_switchboard_close(MsnSwitchBoard *swboard); -void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg); -void msn_switchboard_queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg); -void msn_switchboard_process_queue(MsnSwitchBoard *swboard); +/** + * Returns whether or not we currently can send a message through this + * switchboard. + * + * @param swboard The switchboard. + * + * @return @c TRUE if a message can be sent, @c FALSE otherwise. + */ +gboolean msn_switchboard_can_send(MsnSwitchBoard *swboard); + +/** + * Sends a message through this switchboard. + * + * @param swboard The switchboard. + * @param msg The message. + * @param queue A flag that states if we want this message to be queued (in + * the case it cannot currently be sent). + * + * @return @c TRUE if a message can be sent, @c FALSE otherwise. + */ +void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg, + gboolean queue); gboolean msn_switchboard_chat_leave(MsnSwitchBoard *swboard); gboolean msn_switchboard_chat_invite(MsnSwitchBoard *swboard, const char *who); @@ -208,13 +226,27 @@ void msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user); /** - * Processes application/x-msnmsgrp2p messages. + * Processes peer to peer messages. * * @param cmdproc The command processor. * @param msg The message. */ void msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg); + +/** + * Processes emoticon messages. + * + * @param cmdproc The command processor. + * @param msg The message. + */ void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg); + +/** + * Processes INVITE messages. + * + * @param cmdproc The command processor. + * @param msg The message. + */ void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg); #endif /* _MSN_SWITCHBOARD_H_ */
--- a/src/protocols/msn/transaction.c Thu Jan 06 23:11:12 2005 +0000 +++ b/src/protocols/msn/transaction.c Fri Jan 07 02:48:33 2005 +0000 @@ -112,6 +112,9 @@ { MsnCommand *cmd; + if (!cmdproc->servconn->connected) + return; + gaim_debug_info("msn", "unqueueing command.\n"); cmd = trans->pendent_cmd;