ikspak * iks_packet (iks *x) { ikspak *pak; ikstack *s; char *tmp; s = iks_stack (x); pak = iks_stack_alloc (s, sizeof (ikspak)); if (!pak) return NULL; memset (pak, 0, sizeof (ikspak)); pak->x = x; tmp = iks_find_attrib (x, "from"); if (tmp) pak->from = iks_id_new (s, tmp); pak->id = iks_find_attrib (x, "id"); tmp = iks_find_attrib (x, "type"); if (strcmp (iks_name (x), "message") == 0) { pak->type = IKS_PAK_MESSAGE; if (tmp) { if (strcmp (tmp, "chat") == 0) pak->subtype = IKS_TYPE_CHAT; else if (strcmp (tmp, "groupchat") == 0) pak->subtype = IKS_TYPE_GROUPCHAT; else if (strcmp (tmp, "headline") == 0) pak->subtype = IKS_TYPE_HEADLINE; else if (strcmp (tmp, "error") == 0) pak->subtype = IKS_TYPE_ERROR; } } else if (strcmp (iks_name (x), "presence") == 0) { pak->type = IKS_PAK_S10N; if (tmp) { if (strcmp (tmp, "unavailable") == 0) { pak->type = IKS_PAK_PRESENCE; pak->subtype = IKS_TYPE_UNAVAILABLE; pak->show = IKS_SHOW_UNAVAILABLE; } else if (strcmp (tmp, "probe") == 0) { pak->type = IKS_PAK_PRESENCE; pak->subtype = IKS_TYPE_PROBE; } else if(strcmp(tmp, "subscribe") == 0) pak->subtype = IKS_TYPE_SUBSCRIBE; else if(strcmp(tmp, "subscribed") == 0) pak->subtype = IKS_TYPE_SUBSCRIBED; else if(strcmp(tmp, "unsubscribe") == 0) pak->subtype = IKS_TYPE_UNSUBSCRIBE; else if(strcmp(tmp, "unsubscribed") == 0) pak->subtype = IKS_TYPE_UNSUBSCRIBED; else if(strcmp(tmp, "error") == 0) pak->subtype = IKS_TYPE_ERROR; } else { pak->type = IKS_PAK_PRESENCE; pak->subtype = IKS_TYPE_AVAILABLE; tmp = iks_find_cdata (x, "show"); pak->show = IKS_SHOW_AVAILABLE; if (tmp) { if (strcmp (tmp, "chat") == 0) pak->show = IKS_SHOW_CHAT; else if (strcmp (tmp, "away") == 0) pak->show = IKS_SHOW_AWAY; else if (strcmp (tmp, "xa") == 0) pak->show = IKS_SHOW_XA; else if (strcmp (tmp, "dnd") == 0) pak->show = IKS_SHOW_DND; } } } else if (strcmp (iks_name (x), "iq") == 0) { iks *q; pak->type = IKS_PAK_IQ; if (tmp) { if (strcmp (tmp, "get") == 0) pak->subtype = IKS_TYPE_GET; else if (strcmp (tmp, "set") == 0) pak->subtype = IKS_TYPE_SET; else if (strcmp (tmp, "result") == 0) pak->subtype = IKS_TYPE_RESULT; else if (strcmp (tmp, "error") == 0) pak->subtype = IKS_TYPE_ERROR; } for (q = iks_child (x); q; q = iks_next (q)) { if (IKS_TAG == iks_type (q)) { char *ns; ns = iks_find_attrib (q, "xmlns"); if (ns) { pak->query = q; pak->ns = ns; break; } } } } return pak; }
// 客户端解析服务器响应的协商包,从协商包中解析出临时密钥,并使用自己的私钥进行解密 // 服务器端解析客户端发来的协商包,并填充服务器包解析器 int pkg_talk_parse(packet_parser_t *pkg, const char* xml) { iks *x, *e, *c; int result=0; int dest_len; if(NULL==xml) return NULL_ERROR; x = iks_tree (xml, 0, &result); if(!x) return NULL_ERROR; if(result != IKS_OK) { iks_delete(x); return IKS_BADXML; } if(0 == iks_strcmp("connection",iks_name(x))) { char* tmp = NULL; char *tempkey; char *output; tmp = iks_find_attrib(x, "type"); if(NULL != tmp){ if(strcmp(tmp, "create")==0) set_talk_type(1, pkg); //说明为服务端 else set_talk_type(0, pkg); //说明为客户端 } if(1 == pkg->talk_type) { //说明本端为服务端 tmp = iks_find_cdata(x, "client-id"); set_client_id(tmp, pkg); tmp = iks_find_cdata(x, "public-key"); if(SUCCESS != set_talk_crt_public_key(tmp, pkg)) return SET_TALK_CRT_KEY_ERROR; tmp = iks_find_attrib(iks_find(x,"public-key"), "type"); if(SUCCESS != set_talk_crt_type(tmp, pkg)) return SET_TALK_CRT_TYPE_ERROR; e = iks_find(x,"encryption"); while( e ){ tmp = iks_find_cdata(e, "allow"); if(SUCCESS == set_transfer_crt_type(tmp, pkg)) break; e = iks_next(e); } // 服务器端设置传输数据使用的临时密钥 set_transfer_crt_key(TRANSFERKEY, pkg); c = iks_find(x,"compression"); while( c ){ tmp = iks_find_cdata(c, "allow"); if(SUCCESS == set_cps_type(tmp, pkg)) break; c = iks_next(c); } } else if(0 == pkg->talk_type) { // 说明本端为客户端 tempkey = iks_find_cdata(x,"encryption"); output = (char *)calloc(strlen(tempkey)/2+1, 1); hex2byte(tempkey, strlen(tempkey), (unsigned char *)output); if (pkg->asym_encrypt_hook == NULL) { tempkey = (char *)rsa_encrypt((unsigned char *)output, strlen(tempkey)/2, &dest_len, pkg->curr_ert.ert_keys[1], CRYPT_TYPE_DECRYPT); } else { tempkey = (char *)pkg->asym_encrypt_hook((unsigned char *)output, strlen(tempkey)/2, &dest_len, pkg->curr_ert.ert_keys[1], CRYPT_TYPE_DECRYPT); } free(output); // 比较服务器端响应的压缩加密方式与客户端请求的是否相同 if( SUCCESS != set_transfer_crt_key(tempkey, pkg)) return SET_TRANSFER_ERT_KEY_ERROR; free(tempkey); if( SUCCESS != cmp_transfer_crt_type(iks_find_attrib(iks_find(x, "encryption"), "type"), pkg) ) return CMP_TRANSFER_CRT_TYPE_ERROR; if( SUCCESS != cmp_cps_type(iks_find_cdata(x, "compression"), pkg) ) return CMP_CPS_TYPE_ERROR; set_heatbeat("client", iks_find_attrib(iks_find(x, "heartbeat"), "seconds"), pkg); } } //iks_parser_delete (p); iks_delete(x); return SUCCESS; }