|
@@ -44,163 +44,221 @@
|
|
|
*/
|
|
|
|
|
|
#include "ul_callback.h"
|
|
|
-//#include "../../modules_k/pua/pua.h"
|
|
|
-//#include "../../modules_k/pua/send_publish.h"
|
|
|
+#include "../pua/pua.h"
|
|
|
+#include "../pua/send_publish.h"
|
|
|
+
|
|
|
+#include "../pua/pua_bind.h"
|
|
|
+
|
|
|
#include <libxml/parser.h>
|
|
|
|
|
|
+/*
|
|
|
+Contact: <sip:[email protected]:44733;transport=udp>;expires=600000;+g.oma.sip-im;language="en,fr";+g.3gpp.smsip;+g.oma.sip-im.large-message;audio;+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-application.ims.iari.gsma-vs";+g.3gpp.cs-voice.
|
|
|
+Call-ID: 9ad9f89f-164d-bb86-1072-52e7e9eb5025.
|
|
|
+*/
|
|
|
+
|
|
|
+/*<?xml version="1.0"?>
|
|
|
+<reginfo xmlns="urn:ietf:params:xml:ns:reginfo" version="0" state="full">
|
|
|
+.<registration aor="sip:[email protected]" id="0xb33fa860" state="active">
|
|
|
+..<contact id="0xb33fa994" state="active" event="registered" expires="3600">
|
|
|
+...<uri>sip:[email protected]:43582;transport=udp</uri>
|
|
|
+...<unknown-param name="+g.3gpp.cs-voice"></unknown-param>
|
|
|
+...<unknown-param name="+g.3gpp.icsi-ref">urn0X0.0041FB74E7B54P-1022urn-70X0P+03gpp-application.ims.iari.gsma-vs</unknown-param>
|
|
|
+...<unknown-param name="audio"></unknown-param>
|
|
|
+...<unknown-param name="+g.oma.sip-im.large-message"></unknown-param>
|
|
|
+...<unknown-param name="+g.3gpp.smsip"></unknown-param>
|
|
|
+...<unknown-param name="language">en,fr</unknown-param>
|
|
|
+...<unknown-param name="+g.oma.sip-im"></unknown-param>
|
|
|
+...<unknown-param name="expires">600000</unknown-param>
|
|
|
+..</contact>
|
|
|
+.</registration>
|
|
|
+</reginfo> */
|
|
|
+
|
|
|
+extern pua_api_t pua;
|
|
|
+extern char* pcscf_uri;
|
|
|
+extern int publish_reginfo;
|
|
|
+
|
|
|
/* methods for building reg publish */
|
|
|
-//str* build_reginfo_partial(ppublic_t *impu, struct pcontact* c, int type) {
|
|
|
-// xmlDocPtr doc = NULL;
|
|
|
-// xmlNodePtr root_node = NULL;
|
|
|
-// xmlNodePtr registration_node = NULL;
|
|
|
-// xmlNodePtr contact_node = NULL;
|
|
|
-// xmlNodePtr uri_node = NULL;
|
|
|
-// str * body = NULL;
|
|
|
-// struct pcontact * ptr;
|
|
|
-// char buf[512];
|
|
|
-// int buf_len;
|
|
|
-// int reg_active = 0;
|
|
|
-// time_t cur_time = time(0);
|
|
|
-//
|
|
|
-// /* create the XML-Body */
|
|
|
-// doc = xmlNewDoc(BAD_CAST "1.0");
|
|
|
-// if (doc == 0) {
|
|
|
-// LM_ERR("Unable to create XML-Doc\n");
|
|
|
-// return NULL;
|
|
|
-// }
|
|
|
-//
|
|
|
-// root_node = xmlNewNode(NULL, BAD_CAST "reginfo");
|
|
|
-// if (root_node == 0) {
|
|
|
-// LM_ERR("Unable to create reginfo-XML-Element\n");
|
|
|
-// return NULL;
|
|
|
-// }
|
|
|
-// /* This is our Root-Element: */
|
|
|
-// xmlDocSetRootElement(doc, root_node);
|
|
|
-//
|
|
|
-// xmlNewProp(root_node, BAD_CAST "xmlns", BAD_CAST "urn:ietf:params:xml:ns:reginfo");
|
|
|
-//
|
|
|
-// /* we set the version to 0 but it should be set to the correct value in the pua module */
|
|
|
-// xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "0");
|
|
|
-// xmlNewProp(root_node, BAD_CAST "state", BAD_CAST "partial" );
|
|
|
-//
|
|
|
-// /* Registration Node */
|
|
|
-// registration_node = xmlNewChild(root_node, NULL, BAD_CAST "registration", NULL);
|
|
|
-// if (registration_node == NULL) {
|
|
|
-// LM_ERR("while adding child\n");
|
|
|
-// goto error;
|
|
|
-// }
|
|
|
-//
|
|
|
-// /* Add the properties to this Node for AOR and ID: */
|
|
|
-// xmlNewProp(registration_node, BAD_CAST "aor", BAD_CAST impu->public_identity.s);
|
|
|
-// buf_len = snprintf(buf, sizeof(buf), "%p", impu);
|
|
|
-// xmlNewProp(registration_node, BAD_CAST "id", BAD_CAST buf);
|
|
|
-//
|
|
|
-//
|
|
|
-// //now the updated contact
|
|
|
-// contact_node =xmlNewChild(registration_node, NULL, BAD_CAST "contact", NULL);
|
|
|
-// if (contact_node == NULL) {
|
|
|
-// LM_ERR("while adding child\n");
|
|
|
-// goto error;
|
|
|
-// }
|
|
|
-// memset(buf, 0, sizeof(buf));
|
|
|
-// buf_len = snprintf(buf, sizeof(buf), "%p", c);
|
|
|
-// xmlNewProp(contact_node, BAD_CAST "id", BAD_CAST buf);
|
|
|
-//
|
|
|
-// //TODO: this needs to be dependent on state
|
|
|
-// xmlNewProp(contact_node, BAD_CAST "state", BAD_CAST "terminated");
|
|
|
-// xmlNewProp(contact_node, BAD_CAST "event", BAD_CAST "unregistered");
|
|
|
-// memset(buf, 0, sizeof(buf));
|
|
|
-// //buf_len = snprintf(buf, sizeof(buf), "%i", (int)(ptr->expires-cur_time));
|
|
|
-// //xmlNewProp(contact_node, BAD_CAST "expires", BAD_CAST buf);
|
|
|
-//
|
|
|
-// /* URI-Node */
|
|
|
-// memset(buf, 0, sizeof(buf));
|
|
|
-// buf_len = snprintf(buf, sizeof(buf), "%.*s", c->aor.len, c->aor.s);
|
|
|
-// uri_node = xmlNewChild(contact_node, NULL, BAD_CAST "uri", BAD_CAST buf);
|
|
|
-// if (uri_node == NULL) {
|
|
|
-// LM_ERR("while adding child\n");
|
|
|
-// goto error;
|
|
|
-// }
|
|
|
-//
|
|
|
-// /* create the body */
|
|
|
-// body = (str*) pkg_malloc(sizeof(str));
|
|
|
-// if (body == NULL) {
|
|
|
-// LM_ERR("while allocating memory\n");
|
|
|
-// return NULL;
|
|
|
-// }
|
|
|
-// memset(body, 0, sizeof(str));
|
|
|
-//
|
|
|
-// /* Write the XML into the body */
|
|
|
-// xmlDocDumpFormatMemory(doc, (unsigned char**) (void*) &body->s, &body->len,
|
|
|
-// 1);
|
|
|
-//
|
|
|
-// /*free the document */
|
|
|
-// xmlFreeDoc(doc);
|
|
|
-// xmlCleanupParser();
|
|
|
-//
|
|
|
-// return body;
|
|
|
-//
|
|
|
-//error:
|
|
|
-// if (body) {
|
|
|
-// if (body->s)
|
|
|
-// xmlFree(body->s);
|
|
|
-// pkg_free(body);
|
|
|
-// }
|
|
|
-// if (doc)
|
|
|
-// xmlFreeDoc(doc);
|
|
|
-// return NULL;
|
|
|
-//
|
|
|
-//}
|
|
|
-//
|
|
|
-//int send_partial_publish(ppublic_t *impu, struct pcontact *c, int type)
|
|
|
-//{
|
|
|
-// publ_info_t publ;
|
|
|
-// str content_type;
|
|
|
-// int id_buf_len;
|
|
|
-// char id_buf[512];
|
|
|
-//
|
|
|
-// content_type.s = "application/reginfo+xml";
|
|
|
-// content_type.len = 23;
|
|
|
-//
|
|
|
-// LM_DBG("Sending publish\n");
|
|
|
-// str *body = build_reginfo_partial(impu, c, type);
|
|
|
-//
|
|
|
-// if (body == NULL || body->s == NULL) {
|
|
|
-// LM_ERR("Error on creating XML-Body for publish\n");
|
|
|
-// goto error;
|
|
|
-// }
|
|
|
-// LM_DBG("XML-Body:\n%.*s\n", body->len, body->s);
|
|
|
-//
|
|
|
-// memset(&publ, 0, sizeof(publ_info_t));
|
|
|
-// publ.pres_uri = &impu->public_identity;
|
|
|
-// publ.body = body;
|
|
|
-// id_buf_len = snprintf(id_buf, sizeof(id_buf), "IMSPCSCF_PUBLISH.%.*s", c->aor.len, c->aor.s);
|
|
|
-// publ.id.s = id_buf;
|
|
|
-// publ.id.len = id_buf_len;
|
|
|
-// publ.content_type = content_type;
|
|
|
-// publ.expires = 3600;
|
|
|
-//
|
|
|
-// /* make UPDATE_TYPE, as if this "publish dialog" is not found
|
|
|
-// by pua it will fallback to INSERT_TYPE anyway */
|
|
|
-// publ.flag |= UPDATE_TYPE;
|
|
|
-// publ.source_flag |= REGINFO_PUBLISH;
|
|
|
-// publ.event |= REGINFO_EVENT;
|
|
|
-// publ.extra_headers = NULL;
|
|
|
-//
|
|
|
-// if (pua.send_publish(&publ) < 0) {
|
|
|
-// LM_ERR("Error while sending publish\n");
|
|
|
-// }
|
|
|
-//
|
|
|
-// return 1;
|
|
|
-//
|
|
|
-//error:
|
|
|
-// if (body) {
|
|
|
-// if (body->s)
|
|
|
-// xmlFree(body->s);
|
|
|
-// pkg_free(body);
|
|
|
-// }
|
|
|
-// return -1;
|
|
|
-//}
|
|
|
+str* build_reginfo_partial(ppublic_t *impu, struct pcontact* c, int type) {
|
|
|
+ xmlDocPtr doc = NULL;
|
|
|
+ xmlNodePtr root_node = NULL;
|
|
|
+ xmlNodePtr registration_node = NULL;
|
|
|
+ xmlNodePtr contact_node = NULL;
|
|
|
+ xmlNodePtr uri_node = NULL;
|
|
|
+ str * body = NULL;
|
|
|
+ char buf[512];
|
|
|
+
|
|
|
+ /* create the XML-Body */
|
|
|
+ doc = xmlNewDoc(BAD_CAST "1.0");
|
|
|
+ if (doc == 0) {
|
|
|
+ LM_ERR("Unable to create XML-Doc\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ root_node = xmlNewNode(NULL, BAD_CAST "reginfo");
|
|
|
+ if (root_node == 0) {
|
|
|
+ LM_ERR("Unable to create reginfo-XML-Element\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ /* This is our Root-Element: */
|
|
|
+ xmlDocSetRootElement(doc, root_node);
|
|
|
+
|
|
|
+ xmlNewProp(root_node, BAD_CAST "xmlns", BAD_CAST "urn:ietf:params:xml:ns:reginfo");
|
|
|
+
|
|
|
+ /* we set the version to 0 but it should be set to the correct value in the pua module */
|
|
|
+ xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "0");
|
|
|
+ xmlNewProp(root_node, BAD_CAST "state", BAD_CAST "partial" );
|
|
|
+
|
|
|
+ /* Registration Node */
|
|
|
+ registration_node = xmlNewChild(root_node, NULL, BAD_CAST "registration", NULL);
|
|
|
+ if (registration_node == NULL) {
|
|
|
+ LM_ERR("while adding child\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Add the properties to this Node for AOR and ID: */
|
|
|
+ //registration aor nodes
|
|
|
+ memset(buf, 0, sizeof(buf));
|
|
|
+ snprintf(buf, sizeof(buf), "%.*s", impu->public_identity.len, impu->public_identity.s);
|
|
|
+ xmlNewProp(registration_node, BAD_CAST "aor", BAD_CAST buf);
|
|
|
+
|
|
|
+ //registration id
|
|
|
+ memset(buf, 0, sizeof(buf));
|
|
|
+ snprintf(buf, sizeof(buf), "%p", impu);
|
|
|
+ xmlNewProp(registration_node, BAD_CAST "id", BAD_CAST buf);
|
|
|
+
|
|
|
+ //now the updated contact
|
|
|
+ contact_node =xmlNewChild(registration_node, NULL, BAD_CAST "contact", NULL);
|
|
|
+ if (contact_node == NULL) {
|
|
|
+ LM_ERR("while adding child\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ memset(buf, 0, sizeof(buf));
|
|
|
+ snprintf(buf, sizeof(buf), "%p", c);
|
|
|
+ xmlNewProp(contact_node, BAD_CAST "id", BAD_CAST buf);
|
|
|
+
|
|
|
+ //TODO: currently we only support publish of termination for event unregistered and expires 0
|
|
|
+ xmlNewProp(contact_node, BAD_CAST "state", BAD_CAST "terminated");
|
|
|
+ xmlNewProp(contact_node, BAD_CAST "event", BAD_CAST "unregistered");
|
|
|
+ memset(buf, 0, sizeof(buf));
|
|
|
+ snprintf(buf, sizeof(buf), "%i", 0);
|
|
|
+ xmlNewProp(contact_node, BAD_CAST "expires", BAD_CAST buf);
|
|
|
+
|
|
|
+ /* URI-Node */
|
|
|
+ memset(buf, 0, sizeof(buf));
|
|
|
+ snprintf(buf, sizeof(buf), "%.*s", c->aor.len, c->aor.s);
|
|
|
+ uri_node = xmlNewChild(contact_node, NULL, BAD_CAST "uri", BAD_CAST buf);
|
|
|
+ if (uri_node == NULL) {
|
|
|
+ LM_ERR("while adding child\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* create the body */
|
|
|
+ body = (str*) pkg_malloc(sizeof(str));
|
|
|
+ if (body == NULL) {
|
|
|
+ LM_ERR("while allocating memory\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ memset(body, 0, sizeof(str));
|
|
|
+
|
|
|
+ /* Write the XML into the body */
|
|
|
+ xmlDocDumpFormatMemory(doc, (unsigned char**) (void*) &body->s, &body->len,
|
|
|
+ 1);
|
|
|
+
|
|
|
+ /*free the document */
|
|
|
+ xmlFreeDoc(doc);
|
|
|
+ xmlCleanupParser();
|
|
|
+
|
|
|
+ return body;
|
|
|
+
|
|
|
+error:
|
|
|
+ if (body) {
|
|
|
+ if (body->s)
|
|
|
+ xmlFree(body->s);
|
|
|
+ pkg_free(body);
|
|
|
+ }
|
|
|
+ if (doc)
|
|
|
+ xmlFreeDoc(doc);
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+#define P_ASSERTED_IDENTITY_HDR_PREFIX "P-Asserted-Identity: <"
|
|
|
+int send_partial_publish(ppublic_t *impu, struct pcontact *c, int type)
|
|
|
+{
|
|
|
+ publ_info_t publ;
|
|
|
+ str content_type;
|
|
|
+ int id_buf_len;
|
|
|
+ char id_buf[512];
|
|
|
+ str server_address = {pcscf_uri, strlen(pcscf_uri)};
|
|
|
+ str p_asserted_identity_header;
|
|
|
+
|
|
|
+ content_type.s = "application/reginfo+xml";
|
|
|
+ content_type.len = 23;
|
|
|
+
|
|
|
+ int len = strlen(P_ASSERTED_IDENTITY_HDR_PREFIX) + server_address.len + 1 + CRLF_LEN;
|
|
|
+ p_asserted_identity_header.s = (char *)pkg_malloc( len );
|
|
|
+ if ( p_asserted_identity_header.s == NULL ) {
|
|
|
+ LM_ERR( "insert_asserted_identity: pkg_malloc %d bytes failed", len );
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(p_asserted_identity_header.s, P_ASSERTED_IDENTITY_HDR_PREFIX, strlen(P_ASSERTED_IDENTITY_HDR_PREFIX));
|
|
|
+ p_asserted_identity_header.len = strlen(P_ASSERTED_IDENTITY_HDR_PREFIX);
|
|
|
+ memcpy(p_asserted_identity_header.s + p_asserted_identity_header.len, server_address.s, server_address.len);
|
|
|
+ p_asserted_identity_header.len += server_address.len;
|
|
|
+ *(p_asserted_identity_header.s + p_asserted_identity_header.len) = '>';
|
|
|
+ p_asserted_identity_header.len ++;
|
|
|
+ memcpy( p_asserted_identity_header.s + p_asserted_identity_header.len, CRLF, CRLF_LEN );
|
|
|
+ p_asserted_identity_header.len += CRLF_LEN;
|
|
|
+
|
|
|
+ LM_DBG("p_asserted_identity_header: [%.*s]", p_asserted_identity_header.len, p_asserted_identity_header.s);
|
|
|
+
|
|
|
+ LM_DBG("Sending publish\n");
|
|
|
+ str *body = build_reginfo_partial(impu, c, type);
|
|
|
+
|
|
|
+ if (body == NULL || body->s == NULL) {
|
|
|
+ LM_ERR("Error on creating XML-Body for publish\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ LM_DBG("XML-Body:\n%.*s\n", body->len, body->s);
|
|
|
+
|
|
|
+ memset(&publ, 0, sizeof(publ_info_t));
|
|
|
+ publ.pres_uri = &impu->public_identity;
|
|
|
+ publ.body = body;
|
|
|
+ id_buf_len = snprintf(id_buf, sizeof(id_buf), "IMSPCSCF_PUBLISH.%.*s", c->aor.len, c->aor.s);
|
|
|
+ publ.id.s = id_buf;
|
|
|
+ publ.id.len = id_buf_len;
|
|
|
+ publ.content_type = content_type;
|
|
|
+ publ.expires = 3600;
|
|
|
+
|
|
|
+ /* make UPDATE_TYPE, as if this "publish dialog" is not found
|
|
|
+ by pua it will fallback to INSERT_TYPE anyway */
|
|
|
+ publ.flag |= UPDATE_TYPE;
|
|
|
+ publ.source_flag |= REGINFO_PUBLISH;
|
|
|
+ publ.event |= REGINFO_EVENT;
|
|
|
+ publ.extra_headers = &p_asserted_identity_header;
|
|
|
+
|
|
|
+ if (pua.send_publish(&publ) < 0) {
|
|
|
+ LM_ERR("Error while sending publish\n");
|
|
|
+ }
|
|
|
+ if (p_asserted_identity_header.s) {
|
|
|
+ pkg_free(p_asserted_identity_header.s);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+
|
|
|
+error:
|
|
|
+
|
|
|
+ if (p_asserted_identity_header.s) {
|
|
|
+ pkg_free(p_asserted_identity_header.s);
|
|
|
+ }
|
|
|
+ if (body) {
|
|
|
+ if (body->s)
|
|
|
+ xmlFree(body->s);
|
|
|
+ pkg_free(body);
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+}
|
|
|
|
|
|
void callback_pcscf_contact_cb(struct pcontact *c, int type, void *param) {
|
|
|
ppublic_t *ptr;
|
|
@@ -209,16 +267,21 @@ void callback_pcscf_contact_cb(struct pcontact *c, int type, void *param) {
|
|
|
LM_DBG("PCSCF Contact Callback in regsitrar!\n");
|
|
|
LM_DBG("Contact AOR: [%.*s]\n", c->aor.len, c->aor.s);
|
|
|
LM_DBG("Callback type [%d]\n", type);
|
|
|
+ LM_DBG("Reg state [%d]\n", c->reg_state);
|
|
|
|
|
|
- if (type == (PCSCF_CONTACT_DELETE | PCSCF_CONTACT_UPDATE)) {
|
|
|
+ if ((type&PCSCF_CONTACT_UPDATE)) {
|
|
|
//send publish for each associated IMPU
|
|
|
ptr = c->head;
|
|
|
while (ptr) {
|
|
|
- if (c->reg_state == PCONTACT_DEREG_PENDING_PUBLISH) {
|
|
|
+ if (c->reg_state == PCONTACT_DEREG_PENDING_PUBLISH && publish_reginfo) {
|
|
|
LM_DBG("delete/update on contact <%.*s> associated with IMPU <%.*s> (sending publish)\n",
|
|
|
c->aor.len, c->aor.s,
|
|
|
ptr->public_identity.len, ptr->public_identity.s);
|
|
|
- //send_partial_publish(ptr, c, type);
|
|
|
+ if (ptr->public_identity.len > 4 && strncasecmp(ptr->public_identity.s,"tel:",4)==0) {
|
|
|
+ LM_DBG("This is a tel URI - it is not routable so we don't publish for it");
|
|
|
+ }else{
|
|
|
+ send_partial_publish(ptr, c, type);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
ptr = ptr->next;
|