/** * Process the user left message, we close the current channel, * and remove the session from the session list. */ static void process_left_cb(fetion_account *ac, const gchar *sipmsg) { extern GSList *channel_list; GSList *pos; g_return_if_fail(ac != NULL); g_return_if_fail(sipmsg != NULL); hybrid_debug_info("fetion", "buddy left, recv:\n%s", sipmsg); for (pos = channel_list; pos; pos = pos->next) { if (pos->data == ac) { channel_list = g_slist_remove(channel_list, ac); goto channel_removed; } } hybrid_debug_error("fetion", "FATAL, can't find channel"); return; channel_removed: /* remove the read event source. */ g_source_remove(ac->source); /* close the channel. */ close(ac->sk); /* destroy the account. */ fetion_account_destroy(ac); }
/** * Callback function to handle the pushed message. */ gboolean hybrid_push_cb(gint sk, gpointer user_data) { gchar sipmsg[BUF_LENGTH]; gchar *pos; gchar *h; gchar *msg; fetion_account *ac = (fetion_account*)user_data; gint n; guint len, data_len; if ((n = recv(sk, sipmsg, sizeof(sipmsg), 0)) == -1) { hybrid_account_error_reason(ac->account, _("connection terminated")); return FALSE; } else if (0 == n) { hybrid_debug_info("fetion", "hybrid_push_cb in fetion received 0 bytes," "connection closed."); channel_list = g_slist_remove(channel_list, ac); fetion_account_destroy(ac); close(sk); return FALSE; } sipmsg[n] = '\0'; data_len = ac->buffer ? strlen(ac->buffer) : 0; ac->buffer = (gchar*)realloc(ac->buffer, data_len + n + 1); memcpy(ac->buffer + data_len, sipmsg, n + 1); recheck: data_len = ac->buffer ? strlen(ac->buffer) : 0; if ((pos = strstr(ac->buffer, "\r\n\r\n"))) { pos += 4; h = (gchar*)g_malloc0(data_len - strlen(pos) + 1); memcpy(h, ac->buffer, data_len - strlen(pos)); h[data_len - strlen(pos)] = '\0'; if (strstr(h, "L: ")) { len = fetion_sip_get_length(ac->buffer); if (len <= strlen(pos)) { msg = (gchar*)g_malloc0(strlen(h) + len + 1); memcpy(msg, ac->buffer, strlen(h) + len); msg[strlen(h) + len] = '\0'; /* A message is complete, process it. */ process_pushed(ac, msg); memmove(ac->buffer, ac->buffer + strlen(msg), data_len - strlen(msg)); ac->buffer = (gchar*)realloc(ac->buffer, data_len - strlen(msg) + 1); ac->buffer[data_len - strlen(msg)] = '\0'; g_free(msg); g_free(h); msg = NULL; h = NULL; goto recheck; } } else { /* A message is complete, process it. */ process_pushed(ac, h); memmove(ac->buffer, ac->buffer + strlen(h), data_len - strlen(h)); ac->buffer = (gchar*)realloc(ac->buffer, data_len - strlen(h) + 1); ac->buffer[data_len - strlen(h)] = '\0'; g_free(h); h = NULL; goto recheck; } g_free(h); } return TRUE; }