Mercurial > pidgin.yaz
diff src/protocols/msn/servconn.c @ 8646:1e211dde3cae
[gaim-migrate @ 9398]
Added a patch by shx to clean up the message-handling code and split the
command stuff from it, among a few other things. Also, I fixed a crash in
message parsing, which I think may close a couple bug reports.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Tue, 13 Apr 2004 04:08:22 +0000 |
parents | fc27237783ee |
children | c47a90a0a3b1 |
line wrap: on
line diff
--- a/src/protocols/msn/servconn.c Tue Apr 13 03:53:37 2004 +0000 +++ b/src/protocols/msn/servconn.c Tue Apr 13 04:08:22 2004 +0000 @@ -32,15 +32,16 @@ } MsnQueueEntry; -static gboolean -process_message(MsnServConn *servconn, MsnMessage *msg) +gboolean +msn_servconn_process_message(MsnServConn *servconn, MsnMessage *msg) { MsnServConnMsgCb cb; cb = g_hash_table_lookup(servconn->msg_types, msn_message_get_content_type(msg)); - if (cb == NULL) { + if (cb == NULL) + { gaim_debug(GAIM_DEBUG_WARNING, "msn", "Unhandled content-type '%s': %s\n", msn_message_get_content_type(msg), @@ -54,144 +55,6 @@ return TRUE; } -static gboolean -process_single_line(MsnServConn *servconn, char *str) -{ - MsnSession *session = servconn->session; - MsnServConnCommandCb cb; - GSList *l, *l_next = NULL; - gboolean result; - size_t param_count = 0; - char *command, *param_start; - char **params = NULL; - - command = str; - - /** - * See how many spaces we have in this. - */ - param_start = strchr(command, ' '); - - if (param_start != NULL) { - params = g_strsplit(param_start + 1, " ", 0); - - for (param_count = 0; params[param_count] != NULL; param_count++) - ; - - *param_start = '\0'; - } - - cb = g_hash_table_lookup(servconn->commands, command); - - if (cb == NULL) { - cb = g_hash_table_lookup(servconn->commands, "_unknown_"); - - if (cb == NULL) { - if (isdigit(*str)) - msn_error_handle(session, atoi(str)); - else - gaim_debug(GAIM_DEBUG_WARNING, "msn", - "Unhandled command '%s'\n", str); - - if (params != NULL) - g_strfreev(params); - - return TRUE; - } - } - - result = cb(servconn, command, (const char **)params, param_count); - - if (params != NULL) - g_strfreev(params); - - if (g_list_find(session->servconns, servconn) == NULL) - return result; - - /* Process all queued messages that are waiting on this command. */ - for (l = servconn->msg_queue; l != NULL; l = l_next) { - MsnQueueEntry *entry = l->data; - MsnMessage *msg; - - l_next = l->next; - - if (entry->command == NULL || - !g_ascii_strcasecmp(entry->command, command)) { - - MsnUser *sender; - - msg = entry->msg; - - msn_message_ref(msg); - - sender = msn_message_get_sender(msg); - - servconn->msg_passport = g_strdup(msn_user_get_passport(sender)); - servconn->msg_friendly = g_strdup(msn_user_get_name(sender)); - - process_message(servconn, msg); - - g_free(servconn->msg_passport); - g_free(servconn->msg_friendly); - - msn_servconn_unqueue_message(servconn, entry->msg); - - msn_message_destroy(msg); - entry->msg = NULL; - } - } - - return result; -} - -static gboolean -process_multi_line(MsnServConn *servconn, char *buffer) -{ - char msg_str[MSN_BUF_LEN]; - gboolean result = TRUE; - - if (servconn->multiline_type == MSN_MULTILINE_MSG) { - MsnMessage *msg; - size_t header_len; - - g_snprintf(msg_str, sizeof(msg_str), - "MSG %s %s %d\r\n", - servconn->msg_passport, servconn->msg_friendly, - servconn->multiline_len); - - header_len = strlen(msg_str); - - memcpy(msg_str + header_len, buffer, servconn->multiline_len); - - gaim_debug(GAIM_DEBUG_MISC, "msn", - "Message: {%s}\n", buffer); - - msg = msn_message_new_from_str(servconn->session, msg_str); - - result = process_message(servconn, msg); - - msn_message_destroy(msg); - } - else if (servconn->multiline_type == MSN_MULTILINE_IPG) { - g_snprintf(msg_str, sizeof(msg_str), - "IPG %d\r\n%s", - servconn->multiline_len, buffer); - - gaim_debug(GAIM_DEBUG_MISC, "msn", - "Incoming Page: {%s}\n", buffer); - } - else if (servconn->multiline_type == MSN_MULTILINE_NOT) { - g_snprintf(msg_str, sizeof(msg_str), - "NOT %d\r\n%s", - servconn->multiline_len, buffer); - - gaim_debug(GAIM_DEBUG_MISC, "msn", - "Notification: {%s}\n", buffer); - } - - return result; -} - static void connect_cb(gpointer data, gint source, GaimInputCondition cond) { @@ -284,13 +147,14 @@ session = servconn->session; - if (servconn->inpa) + if (servconn->inpa > 0) + { gaim_input_remove(servconn->inpa); + servconn->inpa = 0; + } close(servconn->fd); - servconn->connected = FALSE; - if (servconn->http_data != NULL) { if (servconn->http_data->session_id != NULL) @@ -308,8 +172,8 @@ g_free(servconn->http_data); } - if (servconn->rxqueue != NULL) - g_free(servconn->rxqueue); + servconn->rx_len = 0; + servconn->payload_len = 0; while (servconn->txqueue != NULL) { g_free(servconn->txqueue->data); @@ -324,8 +188,10 @@ msn_servconn_unqueue_message(servconn, entry->msg); } - if (servconn->disconnect_cb) + if (servconn->disconnect_cb != NULL) servconn->disconnect_cb(servconn); + + servconn->connected = FALSE; } void @@ -526,15 +392,103 @@ } static void +process_payload(MsnServConn *servconn, char *payload, int payload_len) +{ + g_return_if_fail(servconn != NULL); + g_return_if_fail(servconn->payload_cb != NULL); + + servconn->payload_cb(servconn, payload, payload_len); +} + +static int +process_cmd_text(MsnServConn *servconn, const char *command) +{ + MsnSession *session = servconn->session; + MsnServConnCommandCb cb; + GSList *l, *l_next = NULL; + gboolean result; + size_t param_count = 0; + char *param_start; + char **params = NULL; + +#if 0 + if (servconn->last_cmd != NULL) + gfree(servconn->last_cmd); + + servconn->last_cmd = gstrdup(command); +#endif + + /** + * See how many spaces we have in this. + */ + param_start = strchr(command, ' '); + + if (param_start != NULL) { + params = g_strsplit(param_start + 1, " ", 0); + + for (param_count = 0; params[param_count] != NULL; param_count++) + ; + + *param_start = '\0'; + } + + cb = g_hash_table_lookup(servconn->commands, command); + + if (cb == NULL) { + cb = g_hash_table_lookup(servconn->commands, "_unknown_"); + + if (cb == NULL) { + gaim_debug(GAIM_DEBUG_WARNING, "msn", + "Unhandled command '%s'\n", command); + + if (params != NULL) + g_strfreev(params); + + return TRUE; + } + } + + result = cb(servconn, command, (const char **)params, param_count); + + if (params != NULL) + g_strfreev(params); + + if (g_list_find(session->servconns, servconn) == NULL) + return result; + + /* Process all queued messages that are waiting on this command. */ + for (l = servconn->msg_queue; l != NULL; l = l_next) { + MsnQueueEntry *entry = l->data; + MsnMessage *msg; + + l_next = l->next; + + if (entry->command == NULL || + !g_ascii_strcasecmp(entry->command, command)) { + + msg = entry->msg; + + msn_servconn_process_message(servconn, msg); + + msn_servconn_unqueue_message(servconn, msg); + + entry->msg = NULL; + } + } + + return result; +} + +static void read_cb(gpointer data, gint source, GaimInputCondition cond) { MsnServConn *servconn = (MsnServConn *)data; MsnSession *session = servconn->session; char buf[MSN_BUF_LEN]; - gboolean cont = TRUE; - int len; + char *cur, *end, *old_rx_buf; + int len, cur_len; - len = read(servconn->fd, buf, sizeof(buf)); + len = read(servconn->fd, buf, sizeof(buf) - 1); if (len <= 0) { @@ -543,9 +497,9 @@ return; } - servconn->rxqueue = g_realloc(servconn->rxqueue, len + servconn->rxlen); - memcpy(servconn->rxqueue + servconn->rxlen, buf, len); - servconn->rxlen += len; + servconn->rx_buf = g_realloc(servconn->rx_buf, len + servconn->rx_len); + memcpy(servconn->rx_buf + servconn->rx_len, buf, len); + servconn->rx_len += len; if (session->http_method) { @@ -554,10 +508,10 @@ gboolean error; char *tmp; - tmp = g_strndup(servconn->rxqueue, servconn->rxlen); + tmp = g_strndup(servconn->rx_buf, servconn->rx_len); if (!msn_http_servconn_parse_data(servconn, tmp, - servconn->rxlen, &result_msg, + servconn->rx_len, &result_msg, &result_len, &error)) { g_free(tmp); @@ -607,90 +561,63 @@ } #endif - g_free(servconn->rxqueue); - servconn->rxqueue = result_msg; - servconn->rxlen = result_len; + g_free(servconn->rx_buf); + servconn->rx_buf = result_msg; + servconn->rx_len = result_len; } - while (cont) + end = old_rx_buf = servconn->rx_buf; + + do { - if (servconn->parsing_multiline) + cur = end; + + if (servconn->payload_len) { - char *msg; - - if (servconn->rxlen == 0) + if (servconn->payload_len > servconn->rx_len) + /* The payload is still not complete. */ break; - if (servconn->multiline_len > servconn->rxlen) + cur_len = servconn->payload_len; + end += cur_len; + } + else + { + end = strstr(cur, "\r\n"); + + if (!end) + /* The command is still not complete. */ break; - msg = servconn->rxqueue; - servconn->rxlen -= servconn->multiline_len; - - if (servconn->rxlen) { - servconn->rxqueue = g_memdup(msg + servconn->multiline_len, - servconn->rxlen); - } - else { - servconn->rxqueue = NULL; - msg = g_realloc(msg, servconn->multiline_len + 1); - } - - msg[servconn->multiline_len] = '\0'; - servconn->parsing_multiline = FALSE; + *end = '\0'; + cur_len = end - cur + 2; + end += 2; + } - process_multi_line(servconn, msg); - - if (g_list_find(session->servconns, servconn) != NULL) { - servconn->multiline_len = 0; - - if (servconn->msg_passport != NULL) - g_free(servconn->msg_passport); + servconn->rx_len -= cur_len; - if (servconn->msg_friendly != NULL) - g_free(servconn->msg_friendly); - } - else - cont = 0; - - g_free(msg); + if (servconn->payload_len) + { + process_payload(servconn, cur, cur_len); + servconn->payload_len = 0; } - else { - char *end = servconn->rxqueue; - char *cmd; - int cmdlen, i; - - if (!servconn->rxlen) - return; - - for (i = 0; i < servconn->rxlen - 1; end++, i++) { - if (*end == '\r' && end[1] == '\n') - break; - } - - if (i == servconn->rxlen - 1) - return; - - cmdlen = end - servconn->rxqueue + 2; - cmd = servconn->rxqueue; - servconn->rxlen -= cmdlen; + else + { + gaim_debug(GAIM_DEBUG_MISC, "msn", "S: %s\n", cur); + process_cmd_text(servconn, cur); + } + } while (servconn->connected && servconn->rx_len); - if (servconn->rxlen) - servconn->rxqueue = g_memdup(cmd + cmdlen, servconn->rxlen); - else { - servconn->rxqueue = NULL; - cmd = g_realloc(cmd, cmdlen + 1); - } - - cmd[cmdlen] = '\0'; + if (servconn->connected) + { + if (servconn->rx_len) + servconn->rx_buf = g_memdup(cur, servconn->rx_len); + else + servconn->rx_buf = NULL; + } - gaim_debug(GAIM_DEBUG_MISC, "msn", "S: %s", cmd); - - g_strchomp(cmd); + if (servconn->wasted) + msn_servconn_destroy(servconn); - cont = process_single_line(servconn, cmd); - - g_free(cmd); - } - } + g_free(old_rx_buf); }