/** * Process the message sip message. */ static void process_message_cb(fetion_account *ac, const gchar *sipmsg) { gchar *event; gchar *sysmsg_text; gchar *sysmsg_url; HybridNotify *notify; if ((event = sip_header_get_attr(sipmsg, "N")) && g_strcmp0(event, "system-message") == 0) { if (fetion_message_parse_sysmsg(sipmsg, &sysmsg_text, &sysmsg_url) != HYBRID_OK) { return; } notify = hybrid_notify_create(ac->account, _("System Message")); hybrid_notify_set_text(notify, sysmsg_text); g_free(sysmsg_text); g_free(sysmsg_url); } hybrid_debug_info("fetion", "received message:\n%s", sipmsg); fetion_process_message(ac, sipmsg); g_free(event); }
static gint parse_sipc_verification(fetion_account *ac, const gchar *resp) { gchar *w; gchar *start; gchar *end; ac->verification = fetion_verification_create(); w = sip_header_get_attr(resp, "W"); for (start = w; *start != '\0' && *start != '\"'; start ++); if (!*start) { g_free(w); return HYBRID_ERROR; } start ++; for (end = start; *end != '\0' && *end != '\"'; end ++); if (!*end) { g_free(w); return HYBRID_ERROR; } ac->verification->algorithm = g_strndup(start, end - start); for (start = end + 1; *start != '\0' && *start != '\"'; start ++); if (!*start) { g_free(w); return HYBRID_ERROR; } start ++; for (end = start; *end != '\0' && *end != '\"'; end ++); if (!*end) { g_free(w); return HYBRID_ERROR; } ac->verification->type = g_strndup(start, end - start); return HYBRID_OK; }
/** * Callback function to handle the sipc reg response. */ static gboolean sipc_reg_cb(gint sk, gpointer user_data) { gchar buf[BUF_LENGTH]; gchar *digest; gchar *nonce, *key, *aeskey; gchar *response; gint n; fetion_account *ac = (fetion_account*)user_data; if ((n = recv(sk, buf, sizeof(buf), 0)) == -1) { hybrid_account_error_reason(ac->account, _("sipc reg error.")); return FALSE; } buf[n] = '\0'; hybrid_debug_info("fetion", "recv:\n%s", buf); /* parse response, we need the key and nouce */ digest = sip_header_get_attr(buf, "W"); if (parse_sipc_reg_response(digest, &nonce, &key) != HYBRID_OK) { g_free(digest); return FALSE; } aeskey = generate_aes_key(); response = generate_response(nonce, ac->userid, ac->password, key, aeskey); /* fill verify_data for pic confirm */ strncpy(verify_data.response, response, sizeof(verify_data.response)); /* now we start to handle the pushed messages */ ac->source = hybrid_event_add(sk, HYBRID_EVENT_READ, hybrid_push_cb, ac); /* start sipc authencation action. */ sipc_aut_action(sk, ac, response); g_free(digest); g_free(nonce); g_free(key); g_free(aeskey); g_free(response); return FALSE; }
/** * Callback function to handle the new_chat response message, if success * we would get the following message: * * SIP-C/4.0 200 OK * I: 4 * Q: 2 S * A: CS address="221.176.31.128:8080;221.176.31.128:443",credential="439333922.916967705" * * Now we should start a new socket connect to 221.176.31.128:8080 with port 443 as * a back port if 8080 failed to connect. */ gint new_chat_cb(fetion_account *account, const gchar *sipmsg, fetion_transaction *trans) { gchar *auth; gchar *ip; gint port; gchar *credential; invite_data *data; fetion_transaction *new_trans; fetion_account *new_account; printf("%s\n", sipmsg); if (!(auth = sip_header_get_attr(sipmsg, "A"))) { hybrid_debug_error("fetion", "invalid invitation response."); return HYBRID_ERROR; } if (sip_header_get_auth(auth, &ip, &port, &credential) != HYBRID_OK) { hybrid_debug_error("fetion", "invalid invitation response."); return HYBRID_ERROR; } g_free(auth); new_trans = transaction_clone(trans); new_account = fetion_account_clone(account); fetion_account_set_who(new_account, trans->userid); transaction_set_data(new_trans, new_account); data = g_new0(invite_data, 1); data->trans = new_trans; data->credential = credential; hybrid_proxy_connect(ip, port, invite_connect_cb, data); g_free(ip); return HYBRID_OK; }
gint fetion_sip_get_length(const gchar *sipmsg) { gint length; gchar *temp; g_return_val_if_fail(sipmsg != NULL, 0); if(!(temp = sip_header_get_attr(sipmsg, "L"))) { return 0; } length = atoi(temp); g_free(temp); return length; }
/** * Process the sip response message. */ static void process_sipc_cb(fetion_account *ac, const gchar *sipmsg) { gchar *callid; gint callid0; fetion_transaction *trans; GSList *trans_cur; if (!(callid = sip_header_get_attr(sipmsg, "I"))) { hybrid_debug_error("fetion", "invalid sipc message received\n%s", sipmsg); g_free(callid); return; } callid0 = atoi(callid); trans_cur = ac->trans_list; while(trans_cur) { trans = (fetion_transaction*)(trans_cur->data); if (trans->callid == callid0) { if (trans->callback) { (trans->callback)(ac, sipmsg, trans); } transaction_remove(ac, trans); break; } trans_cur = g_slist_next(trans_cur); } }
gint fetion_process_invite(fetion_account *account, const gchar *sipmsg) { gchar *from; gchar *auth; gchar *ip; gchar *credential; gchar *sid; gint port; gchar *sip_text; fetion_account *new_account; fetion_buddy *buddy; invite_conn_data *data; g_return_val_if_fail(account != NULL, HYBRID_ERROR); g_return_val_if_fail(sipmsg != NULL, HYBRID_ERROR); from = sip_header_get_attr(sipmsg, "F"); auth = sip_header_get_attr(sipmsg, "A"); sip_header_get_auth(auth, &ip, &port, &credential); g_free(auth); sip_text = g_strdup_printf("SIP-C/4.0 200 OK\r\n" "F: %s\r\n" "I: 61\r\n" "Q: 200002 I\r\n\r\n", from); hybrid_debug_info("fetion", "invite, send back:\n%s", sip_text); if (send(account->sk, sip_text, strlen(sip_text), 0) == -1) { hybrid_debug_error("fetion", "process an invitation error."); g_free(from); g_free(ip); g_free(credential); g_free(sip_text); return HYBRID_ERROR; } g_free(sip_text); sid = get_sid_from_sipuri(from); if (!(buddy = fetion_buddy_find_by_sid(account, sid))) { hybrid_debug_error("fetion", "can't find buddy %s", from); g_free(from); g_free(ip); g_free(credential); g_free(sid); return HYBRID_ERROR; } g_free(sid); new_account = fetion_account_clone(account); fetion_account_set_who(new_account, buddy->userid); data = g_new0(invite_conn_data, 1); data->account = new_account; data->credential = credential; hybrid_proxy_connect(ip, port, process_invite_conn_cb, data); g_free(from); g_free(ip); return HYBRID_OK; }
gint fetion_process_message(fetion_account *account, const gchar *sipmsg) { gchar *from; gchar *sid; gchar *callid; gchar *sequence; gchar *sendtime; gchar *text; gchar *sip_text; fetion_buddy *buddy; g_return_val_if_fail(account != NULL, HYBRID_ERROR); g_return_val_if_fail(sipmsg != NULL, HYBRID_ERROR); if (!(text = strstr(sipmsg, "\r\n\r\n"))) { hybrid_debug_error("fetion", "invalid message received\n"); return HYBRID_ERROR; } text += 4; from = sip_header_get_attr(sipmsg, "F"); callid = sip_header_get_attr(sipmsg, "I"); sendtime = sip_header_get_attr(sipmsg, "D"); sequence = sip_header_get_attr(sipmsg, "Q"); sip_text = g_strdup_printf( "SIP-C/4.0 200 OK\r\n" "I: %s\r\n" "Q: %s\r\n" "F: %s\r\n\r\n", callid, sequence, from); g_free(callid); g_free(sendtime); g_free(sequence); hybrid_debug_info("fetion", "message response, send:\n%s", sip_text); if (send(account->sk, sip_text, strlen(sip_text), 0) == -1) { g_free(sip_text); g_free(from); return HYBRID_ERROR; } g_free(sip_text); sid = get_sid_from_sipuri(from); g_free(from); if (!(buddy = fetion_buddy_find_by_sid(account, sid))) { hybrid_debug_error("fetion", "invalid message received\n"); g_free(sid); return HYBRID_ERROR; } hybrid_conv_got_message(account->account, buddy->userid, text, time(NULL)); g_free(sid); return HYBRID_OK; }
void sip_parse_notify(const gchar *sipmsg, gint *notify_type, gint *event_type) { gchar *attr; gchar *pos; gchar *event; xmlnode *root = NULL; xmlnode *node; g_return_if_fail(sipmsg != NULL); if (!(attr = sip_header_get_attr(sipmsg, "N"))) { *notify_type = NOTIFICATION_TYPE_UNKNOWN; *event_type = NOTIFICATION_EVENT_UNKNOWN; return; } if (g_strcmp0(attr, "PresenceV4") == 0) { *notify_type = NOTIFICATION_TYPE_PRESENCE; } else if (g_strcmp0(attr, "Conversation") == 0) { *notify_type = NOTIFICATION_TYPE_CONVERSATION; } else if (g_strcmp0(attr, "contact") == 0) { *notify_type = NOTIFICATION_TYPE_CONTACT; } else if (g_strcmp0(attr, "registration") == 0) { *notify_type = NOTIFICATION_TYPE_REGISTRATION; } else if (g_strcmp0(attr, "SyncUserInfoV4") == 0) { *notify_type = NOTIFICATION_TYPE_SYNCUSERINFO; } else if (g_strcmp0(attr, "PGGroup") == 0) { *notify_type = NOTIFICATION_TYPE_PGGROUP; } else { *notify_type = NOTIFICATION_TYPE_UNKNOWN; } g_free(attr); if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { goto notify_err; } pos += 4; if (!(root = xmlnode_root(pos, strlen(pos)))) { goto notify_err; } if (!(node = xmlnode_find(root, "event"))) { goto notify_err; } if (!(event = xmlnode_prop(node, "type"))) { goto notify_err; } if (g_strcmp0(event, "Support") == 0) { if (!(node = xmlnode_next(node))) { goto notify_err; } if (g_strcmp0(node->name, "event") != 0) { goto notify_err; } if (!(event = xmlnode_prop(node, "type"))) { goto notify_err; } } if (g_strcmp0(event, "PresenceChanged") == 0) { *event_type = NOTIFICATION_EVENT_PRESENCECHANGED; } else if (g_strcmp0(event, "UserEntered") == 0) { *event_type = NOTIFICATION_EVENT_USERENTER; } else if (g_strcmp0(event, "UserLeft") == 0) { *event_type = NOTIFICATION_EVENT_USERLEFT; } else if (g_strcmp0(event, "deregistered") == 0) { *event_type = NOTIFICATION_EVENT_DEREGISTRATION; } else if (g_strcmp0(event, "SyncUserInfo") == 0) { *event_type = NOTIFICATION_EVENT_SYNCUSERINFO; } else if (g_strcmp0(event, "AddBuddyApplication") == 0) { *event_type = NOTIFICATION_EVENT_ADDBUDDYAPPLICATION; } else if (g_strcmp0(event, "PGGetGroupInfo") == 0) { *event_type = NOTIFICATION_EVENT_PGGETGROUPINFO; } else { *event_type = NOTIFICATION_EVENT_UNKNOWN; } xmlnode_free(root); return; notify_err: xmlnode_free(root); *event_type = NOTIFICATION_EVENT_UNKNOWN; return; }