Преглед на файлове

Merge pull request #1424 from kamailio/eschmidbauer/pua_json

pua_json: new module to update presence using JSON data objects
Emmanuel Schmidbauer преди 7 години
родител
ревизия
02cb90c978

+ 1 - 1
src/modules/presence/bind_presence.h

@@ -43,7 +43,7 @@ typedef int (*pres_handle_publish_t)(struct sip_msg* msg, char *str1, char* str2
 typedef int (*pres_handle_subscribe0_t)(struct sip_msg* msg);
 typedef int (*pres_handle_subscribe_t)(struct sip_msg* msg, str watcher_user, str watcher_domain);
 typedef int (*pres_update_presentity_t)(str *event, str *realm, str *user, str *etag,
-		str *sender, str *body, int expires, int new_t);
+		str *sender, str *body, int expires, int new_t, int replace);
 typedef int (*pres_refresh_watchers_t)(str *pres, str *event, int type);
 
 typedef struct presence_api {

+ 1 - 1
src/modules/presence/presence_dmq.c

@@ -302,7 +302,7 @@ int pres_dmq_handle_msg(
 	switch(action) {
 		case PRES_DMQ_UPDATE_PRESENTITY:
 			if(update_presentity(NULL, presentity, &p_body, t_new, &sent_reply,
-					   sphere, &cur_etag, &ruid)
+					   sphere, &cur_etag, &ruid, 0)
 					< 0) {
 				goto error;
 			}

+ 12 - 5
src/modules/presence/presentity.c

@@ -281,7 +281,7 @@ int check_if_dialog(str body, int *is_dialog, char **dialog_id)
 	doc = xmlParseMemory(body.s, body.len);
 	if(doc== NULL)
 	{
-		LM_ERR("failed to parse xml document\n");
+		LM_INFO("failed to parse xml document\n");
 		return -1;
 	}
 
@@ -556,7 +556,7 @@ int is_dialog_terminated(presentity_t* presentity)
 }
 
 int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
-		int new_t, int* sent_reply, char* sphere, str* etag_override, str* ruid)
+		int new_t, int* sent_reply, char* sphere, str* etag_override, str* ruid, int replace)
 {
 	db_key_t query_cols[14], rquery_cols[2], update_keys[9], result_cols[7];
 	db_op_t  query_ops[14], rquery_ops[2];
@@ -658,6 +658,9 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
 		}
 
 		LM_DBG("new htable record added\n");
+		if (presentity->expires == -1) {
+			replace = 1;
+		}
 
 		/* insert new record into database */
 		query_cols[n_query_cols] = &str_sender_col;
@@ -697,7 +700,7 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
 		query_vals[n_query_cols].val.str_val = p_ruid;
 		n_query_cols++;
 
-		if (presentity->expires != -1)
+		if (!replace)
 		{
 			/* A real PUBLISH */
 			query_cols[n_query_cols] = &str_expires_col;
@@ -748,6 +751,10 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
 			query_vals[n_query_cols].type = DB1_INT;
 			query_vals[n_query_cols].nul = 0;
 			query_vals[n_query_cols].val.int_val = -1;
+			if(presentity->expires != -1) {
+				query_vals[n_query_cols].val.int_val =
+						presentity->expires + (int)time(NULL);
+			}
 			n_query_cols++;
 
 			if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
@@ -1918,7 +1925,7 @@ error:
 
 // used for API updates to the presentity table
 int _api_update_presentity(str *event, str *realm, str *user, str *etag,
-		str *sender, str *body, int expires, int new_t)
+		str *sender, str *body, int expires, int new_t, int replace)
 {
 	int ret;
 	presentity_t *pres = NULL;
@@ -1936,7 +1943,7 @@ int _api_update_presentity(str *event, str *realm, str *user, str *etag,
 	if(sphere_enable) {
 		sphere = extract_sphere(*body);
 	}
-	ret = update_presentity(NULL, pres, body, new_t, NULL, sphere, NULL, NULL);
+	ret = update_presentity(NULL, pres, body, new_t, NULL, sphere, NULL, NULL, replace);
 
 	if(pres)
 		pkg_free(pres);

+ 2 - 2
src/modules/presence/presentity.h

@@ -55,11 +55,11 @@ presentity_t* new_presentity( str* domain,str* user,int expires,
 
 /* update presentity in database */
 int update_presentity(struct sip_msg* msg,presentity_t* p,str* body,int t_new,
-		int* sent_reply, char* sphere, str* etag_override, str* ruid);
+		int* sent_reply, char* sphere, str* etag_override, str* ruid, int replace);
 
 /* update presentity in database using API */
 int _api_update_presentity(str *event, str *realm, str *user, str *etag,
-		str *sender, str *body, int expires, int reset);
+		str *sender, str *body, int expires, int new_t, int replace);
 
 /* free memory */
 void free_presentity(presentity_t *p);

+ 2 - 2
src/modules/presence/publish.c

@@ -494,7 +494,7 @@ int ki_handle_publish_uri(struct sip_msg* msg, str* sender_uri)
 	}
 
 	/* querry the database and update or insert */
-	if(update_presentity(msg, presentity, &body, etag_gen, &sent_reply, sphere, NULL, NULL) <0)
+	if(update_presentity(msg, presentity, &body, etag_gen, &sent_reply, sphere, NULL, NULL, 0) <0)
 	{
 		LM_ERR("when updating presentity\n");
 		goto error;
@@ -635,7 +635,7 @@ int update_hard_presentity(str *pres_uri, pres_ev_t *event, str *file_uri, str *
 		goto done;
 	}
 
-	if (update_presentity(NULL, pres, pidf_doc, new_t, NULL, sphere, NULL, NULL) < 0)
+	if (update_presentity(NULL, pres, pidf_doc, new_t, NULL, sphere, NULL, NULL, 0) < 0)
 	{
 		LM_ERR("updating presentity\n");
 		goto done;

+ 17 - 0
src/modules/pua_json/Makefile

@@ -0,0 +1,17 @@
+#
+# PUA_JSON module
+#
+#
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+
+auto_gen=
+NAME=pua_json.so
+
+LIBS=-ljson-c
+DEFS+=-I$(LOCALBASE)/include -I/usr/local/include $(shell pkg-config --cflags json-c)
+
+DEFS+=-DKAMAILIO_MOD_INTERFACE
+
+include ../../Makefile.modules

+ 0 - 0
src/modules/pua_json/README


+ 134 - 0
src/modules/pua_json/defs.h

@@ -0,0 +1,134 @@
+/*
+ * PUA_JSON module
+ *
+ * Copyright (C) 2010-2014 2600Hz
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Contributor(s):
+ * 2600Hz Team
+ * Emmanuel Schmidbauer <[email protected]>
+ *
+ */
+
+#ifndef _PUA_JSON_DEFS_H_
+#define _PUA_JSON_DEFS_H_
+
+#define BLF_MAX_DIALOGS 8
+#define BLF_JSON_PRES		"Presentity"
+#define BLF_JSON_PRES_USER	"Presentity-User"
+#define BLF_JSON_PRES_REALM	"Presentity-Realm"
+#define BLF_JSON_FROM      	"From"
+#define BLF_JSON_FROM_USER 	"From-User"
+#define BLF_JSON_FROM_REALM	"From-Realm"
+#define BLF_JSON_FROM_URI	"From-URI"
+#define BLF_JSON_TO        	"To"
+#define BLF_JSON_TO_USER 	"To-User"
+#define BLF_JSON_TO_REALM	"To-Realm"
+#define BLF_JSON_TO_URI		"To-URI"
+#define BLF_JSON_CALLID    	"Call-ID"
+#define BLF_JSON_TOTAG     	"To-Tag"
+#define BLF_JSON_FROMTAG   	"From-Tag"
+#define BLF_JSON_STATE     	"State"
+#define BLF_JSON_USER      	"User"
+#define BLF_JSON_QUEUE     	"Queue"
+#define BLF_JSON_EXPIRES	"Expires"
+#define BLF_JSON_APP_NAME       "App-Name"
+#define BLF_JSON_APP_VERSION    "App-Version"
+#define BLF_JSON_NODE           "Node"
+#define BLF_JSON_SERVERID       "Server-ID"
+#define BLF_JSON_EVENT_CATEGORY "Event-Category"
+#define BLF_JSON_EVENT_NAME     "Event-Name"
+#define BLF_JSON_TYPE           "Type"
+#define BLF_JSON_MSG_ID         "Msg-ID"
+#define BLF_JSON_DIRECTION      "Direction"
+
+#define BLF_JSON_CONTACT   	"Contact"
+#define BLF_JSON_EVENT_PKG      "Event-Package"
+#define MWI_JSON_WAITING        "Messages-Waiting"
+#define MWI_JSON_VOICE_MESSAGE  "MWI-Voice-Message"
+#define MWI_JSON_NEW            "Messages-New"
+#define MWI_JSON_SAVED          "Messages-Saved"
+#define MWI_JSON_URGENT         "Messages-Urgent"
+#define MWI_JSON_URGENT_SAVED   "Messages-Urgent-Saved"
+#define MWI_JSON_ACCOUNT        "Message-Account"
+#define MWI_JSON_FROM      	"From"
+#define MWI_JSON_TO        	"To"
+
+#define TO_TAG_BUFFER_SIZE 128
+#define FROM_TAG_BUFFER_SIZE 128
+#define SENDER_BUFFER_SIZE 1024
+#define DIALOGINFO_BODY_BUFFER_SIZE 8192
+#define MWI_BODY_BUFFER_SIZE 2048
+#define PRESENCE_BODY_BUFFER_SIZE 4096
+
+#define MWI_BODY_VOICE_MESSAGE "Messages-Waiting: %.*s\r\nMessage-Account: %.*s\r\nVoice-Message: %.*s\r\n"
+#define MWI_BODY_NO_VOICE_MESSAGE "Messages-Waiting: %.*s\r\nMessage-Account: %.*s\r\n"
+#define MWI_BODY             "Messages-Waiting: %.*s\r\nMessage-Account: %.*s\r\nVoice-Message: %.*s/%.*s (%.*s/%.*s)\r\n"
+#define PRESENCE_BODY        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" xmlns:c=\"urn:ietf:params:xml:ns:pidf:cipid\" entity=\"%s\"> \
+<tuple xmlns=\"urn:ietf:params:xml:ns:pidf\" id=\"%s\">\
+<status>\
+<basic>%s</basic>\
+</status>\
+</tuple>\
+<note xmlns=\"urn:ietf:params:xml:ns:pidf\">%s</note>\
+<dm:person xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" id=\"1\">\
+<rpid:activities>%s</rpid:activities>\
+<dm:note>%s</dm:note>\
+</dm:person>\
+</presence>"
+
+#define DIALOGINFO_EMPTY_BODY "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"1\" state=\"full\" entity=\"%.*s\"> \
+<dialog call-id=\"76001e23e09704ea9e1257ebea85e1f3\" direction=\"initiator\">\
+<state>terminated</state>\
+</dialog>\
+</dialog-info>"
+
+#define LOCAL_TAG "local-tag=\"%.*s\""
+#define REMOTE_TAG "remote-tag=\"%.*s\""
+
+#define DIALOGINFO_BODY "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"1\" state=\"full\" entity=\"%.*s\">\
+<dialog id=\"%.*s\" call-id=\"%.*s\" %.*s %.*s direction=\"%.*s\">\
+<state>%.*s</state>\
+<local>\
+<identity display=\"%.*s\">%.*s</identity>\
+<target uri=\"%.*s\"/>\
+</local>\
+<remote>\
+<identity display=\"%.*s\">%.*s</identity>\
+<target uri=\"%.*s\"/>\
+</remote>\
+</dialog>\
+</dialog-info>"
+
+#define DIALOGINFO_BODY_2 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"1\" state=\"full\" entity=\"%.*s\">\
+<dialog id=\"%.*s\" call-id=\"%.*s\" %.*s %.*s direction=\"%.*s\">\
+<state>%.*s</state>\
+<local>\
+<identity display=\"%.*s\">%.*s</identity>\
+</local>\
+<remote>\
+<identity display=\"%.*s\">%.*s</identity>\
+</remote>\
+</dialog>\
+</dialog-info>"
+
+#endif /* _PUA_JSON_DEFS_H_ */

+ 4 - 0
src/modules/pua_json/doc/Makefile

@@ -0,0 +1,4 @@
+docs = json_pua.xml
+
+docbook_dir = ../../../../doc/docbook
+include $(docbook_dir)/Makefile.module

+ 37 - 0
src/modules/pua_json/doc/pua_json.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+	<title>PUA_JSON Module</title>
+	<productname class="trade">&kamailioname;</productname>
+	<authorgroup>
+	    <author>
+		<firstname>Emmanuel Schmidbauer</firstname>
+		<email>[email protected]</email>
+	    </author>
+	    <editor>
+		<firstname>Emmanuel</firstname>
+		<surname>Schmidbauer</surname>
+		<email>[email protected]</email>
+	    </editor>
+	</authorgroup>
+	<copyright>
+	    <year>2018</year>
+	    <holder>VoIPxSWITCH</holder>
+	</copyright>
+    </bookinfo>
+    <toc></toc>
+    
+    <xi:include href="pua_json_admin.xml"/>
+    <!-- <xi:include href="db_text_devel.xml"/> -->
+    
+
+</book>

+ 105 - 0
src/modules/pua_json/doc/pua_json_admin.xml

@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
+	<title>&adminguide;</title>
+
+
+	<section>
+		<title>Overview</title>
+		<para>The PUA_JSON module adds support to publish updates to the presence module through the pua_json_publish() function.
+		</para>
+		<para>
+			From a high-level perspective, the module may be used for:
+			<itemizedlist>
+				<listitem>
+					<para>
+						Providing a real-time presence updates.
+					</para>
+				</listitem>
+			</itemizedlist>
+		</para>
+
+	</section>
+	<section>
+		<title>How it works</title>
+		<para>
+			The module parses json data objects and inserts them into the presentity table for real-time presence updates.
+		</para>
+	</section>
+
+	<section>
+		<title>Dependencies</title>
+		<section>
+			<title>&kamailio; Modules</title>
+			<para>
+				The following modules must be loaded before this module:
+				<itemizedlist>
+					<listitem>
+						<para>
+							<emphasis>none</emphasis>.
+						</para>
+					</listitem>
+				</itemizedlist>
+			</para>
+		</section>
+		<section>
+			<title>External Libraries or Applications</title>
+			<para>
+				The following libraries or applications must be installed
+				<itemizedlist>
+					<listitem>
+						<para>
+							<emphasis>libjson</emphasis>.
+						</para>
+					</listitem>
+				</itemizedlist>
+			</para>
+		</section>
+	</section>
+
+	<section>
+		<title>Functions</title>
+		<section>
+			<title>
+				<function moreinfo="none">pua_json_publish(json_payload)</function>
+			</title>
+			<para>
+				The function build presentity state from json_payload and updates presentity table.
+			</para>
+			<para>
+				Usage: presence related.
+			</para>
+			<para>
+				This function can be used from ANY ROUTE.
+			</para>
+
+			<example>
+				<title><function>pua_json_publish</function> usage</title>
+<programlisting format="linespecific">
+...
+event_route[xhttp:request] {
+	$var(call-id) = $(rb{json.parse,Call-ID});
+	if ($(rb{json.parse,Event-Package}) == "dialog") {
+		xlog("L_INFO", "$var(call-id)|log|received $(rb{json.parse,Event-Package}) update for $(rb{json.parse,From})");
+		pua_json_publish($rb);
+	}
+}
+...
+</programlisting>
+			</example>
+		</section>
+
+	</section>
+
+
+</chapter>
+

+ 68 - 0
src/modules/pua_json/pua_json_mod.c

@@ -0,0 +1,68 @@
+/*
+ * PUA_JSON module interface
+ *
+ * Copyright (C) 2018 VoIPxSWITCH
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../json/api.h"
+#include "../presence/bind_presence.h"
+#include "pua_json_mod.h"
+
+MODULE_VERSION
+
+static param_export_t params[] = {
+		{"pua_include_entity", INT_PARAM, &pua_include_entity},
+		{0, 0, 0}};
+
+static cmd_export_t cmds[] = {
+		{"pua_json_publish", (cmd_function)pua_json_publish, 1, 0, 0,
+				ANY_ROUTE},
+		{0, 0, 0, 0, 0, 0}};
+
+struct module_exports exports = {
+		"pua_json", DEFAULT_DLFLAGS, /* dlopen flags */
+		cmds,						 /* Exported functions */
+		params,						 /* Exported parameters */
+		0,							 /* exported statistics */
+		0,							 /* exported MI functions */
+		0, 0,						 /* extra processes */
+		mod_init,					 /* module initialization function */
+		0,							 /* response function*/
+		0,							 /* destroy function */
+		0							 /* per-child init function */
+};
+
+static int mod_init(void)
+{
+	if(json_load_api(&json_api) < 0) {
+		LM_ERR("cannot bind to JSON API\n");
+		return -1;
+	}
+	if(presence_load_api(&presence_api) < 0) {
+		LM_ERR("cannot bind to PRESENCE API\n");
+		return -1;
+	}
+
+	return 0;
+}

+ 37 - 0
src/modules/pua_json/pua_json_mod.h

@@ -0,0 +1,37 @@
+/*
+ * PUA_JSON module interface
+ *
+ * Copyright (C) 2018 VoIPxSWITCH
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ */
+
+#ifndef __PUA_JSON_MOD_H_
+#define __PUA_JSON_MOD_H_
+
+#include "../../core/mod_fix.h"
+#include "pua_json_publish.h"
+
+json_api_t json_api;
+presence_api_t presence_api;
+int pua_include_entity = 1;
+
+static int mod_init(void);
+
+#endif

+ 389 - 0
src/modules/pua_json/pua_json_publish.c

@@ -0,0 +1,389 @@
+/*
+ * PUA_JSON module interface
+ *
+ * Copyright (C) 2010-2014 2600Hz
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Contributor(s):
+ * 2600Hz Team
+ * Emmanuel Schmidbauer <[email protected]>
+ *
+ */
+
+#include <json.h>
+#include "../json/api.h"
+#include "../presence/bind_presence.h"
+
+#include "defs.h"
+#include "pua_json_publish.h"
+
+extern json_api_t json_api;
+extern presence_api_t presence_api;
+extern int pua_include_entity;
+
+str str_event_message_summary = str_init("message-summary");
+str str_event_dialog = str_init("dialog");
+str str_event_presence = str_init("presence");
+
+str str_username_col = str_init("username");
+str str_domain_col = str_init("domain");
+str str_body_col = str_init("body");
+str str_expires_col = str_init("expires");
+str str_received_time_col = str_init("received_time");
+str str_presentity_uri_col = str_init("presentity_uri");
+str str_priority_col = str_init("priority");
+
+str str_event_col = str_init("event");
+str str_contact_col = str_init("contact");
+str str_callid_col = str_init("callid");
+str str_from_tag_col = str_init("from_tag");
+str str_to_tag_col = str_init("to_tag");
+str str_etag_col = str_init("etag");
+str str_sender_col = str_init("sender");
+
+str str_presence_note_busy = str_init("Busy");
+str str_presence_note_otp = str_init("On the Phone");
+str str_presence_note_idle = str_init("Idle");
+str str_presence_note_offline = str_init("Offline");
+str str_presence_act_busy = str_init("<rpid:busy/>");
+str str_presence_act_otp = str_init("<rpid:on-the-phone/>");
+str str_presence_status_offline = str_init("closed");
+str str_presence_status_online = str_init("open");
+
+str str_null_string = str_init("NULL");
+
+int pua_json_update_presentity(str *event, str *realm, str *user, str *etag, str *sender, str *body, int expires, int new_t, int replace) {
+	int ret;
+	if(!event->len)
+	{
+		LM_ERR("presence event must be set\n");
+		return -1;
+	}
+	if (!realm->len) {	
+		LM_ERR("presence realm must be set\n");
+		return -1;
+	}
+	if (!user->len) {
+		LM_ERR("presence user must be set\n");
+		return -1;
+	}
+	if (!etag->len) {
+		LM_ERR("presence etag must be set\n");
+		return -1;
+	}
+	if (!sender->len) {
+		LM_ERR("presence sender must be set\n");
+		return -1;
+	}
+	if (!body->len) {
+		LM_ERR("presence body must be set\n");
+		return -1;
+	}
+	ret = presence_api.update_presentity(
+			event, realm, user, etag, sender, body, expires, new_t, replace);
+	return ret;
+}
+
+int pua_json_publish_presence_to_presentity(struct json_object *json_obj) {
+	int ret = 1;
+	int len;
+	str from = {0, 0};
+	str from_user = {0, 0}, to_user = {0, 0};
+	str from_realm = {0, 0};
+	str callid = {0, 0};
+	str state = {0, 0};
+	str event = str_init("presence");
+	str presence_body = {0, 0};
+	str activity = str_init("");
+	str note = str_init("Available");
+	str status = str_presence_status_online;
+	int expires = 0;
+
+	char *body = (char *)pkg_malloc(PRESENCE_BODY_BUFFER_SIZE);
+	if (body == NULL) {
+		LM_ERR("Error allocating buffer for publish\n");
+		ret = -1;
+		goto error;
+	}
+
+	json_api.extract_field(json_obj, BLF_JSON_FROM, &from);
+	json_api.extract_field(json_obj, BLF_JSON_FROM_USER, &from_user);
+	json_api.extract_field(json_obj, BLF_JSON_FROM_REALM, &from_realm);
+	json_api.extract_field(json_obj, BLF_JSON_TO_USER, &to_user);
+	json_api.extract_field(json_obj, BLF_JSON_CALLID, &callid);
+	json_api.extract_field(json_obj, BLF_JSON_STATE, &state);
+
+	struct json_object *ExpiresObj =  json_api.get_object(json_obj, BLF_JSON_EXPIRES);
+	if (ExpiresObj != NULL) {
+		expires = json_object_get_int(ExpiresObj);
+	}
+
+	if (!from_user.len || !to_user.len || !state.len) {
+		LM_ERR("missing one of From / To / State\n");
+		goto error;
+	}
+
+	if (!strcmp(state.s, "early")) {
+		note = str_presence_note_busy;
+		activity = str_presence_act_busy;
+
+	} else if (!strcmp(state.s, "confirmed")) {
+		note = str_presence_note_otp;
+		activity = str_presence_act_otp;
+
+	} else if (!strcmp(state.s, "offline")) {
+		note = str_presence_note_offline;
+		status = str_presence_status_offline;
+
+	}; // else {
+	//	note = str_presence_note_idle;
+	//}
+
+	len = snprintf(body, PRESENCE_BODY_BUFFER_SIZE, PRESENCE_BODY, from_user.s,
+			callid.s, status.s, note.s, activity.s, note.s);
+
+	presence_body.s = body;
+	presence_body.len = len;
+
+	pua_json_update_presentity(&event, &from_realm, &from_user, &callid, &from, &presence_body, expires, 1, 1);
+
+ error:
+
+	if(body)
+		pkg_free(body);
+
+	return ret;
+}
+
+int pua_json_publish_mwi_to_presentity(struct json_object *json_obj) {
+	int ret = 1;
+	int len;
+	str event = str_init("message-summary");
+	str from = {0, 0};
+	str from_user = {0, 0};
+	str from_realm = {0, 0};
+	str callid = {0, 0};
+	str mwi_waiting = {0, 0}, mwi_voice_message = {0, 0}, mwi_new = {0, 0}, mwi_saved = {0, 0}, mwi_urgent = {0, 0}, mwi_urgent_saved = {0, 0}, mwi_account = {0, 0}, mwi_body = {0, 0};
+	int expires = 0;
+
+	char *body = (char *)pkg_malloc(MWI_BODY_BUFFER_SIZE);
+	if(body == NULL) {
+		LM_ERR("Error allocating buffer for publish\n");
+		ret = -1;
+		goto error;
+	}
+
+	json_api.extract_field(json_obj, BLF_JSON_FROM, &from);
+	json_api.extract_field(json_obj, BLF_JSON_FROM_USER, &from_user);
+	json_api.extract_field(json_obj, BLF_JSON_FROM_REALM, &from_realm);
+	json_api.extract_field(json_obj, BLF_JSON_CALLID, &callid);
+
+	json_api.extract_field(json_obj, MWI_JSON_WAITING, &mwi_waiting);
+	json_api.extract_field(
+			json_obj, MWI_JSON_VOICE_MESSAGE, &mwi_voice_message);
+	json_api.extract_field(json_obj, MWI_JSON_NEW, &mwi_new);
+	json_api.extract_field(json_obj, MWI_JSON_SAVED, &mwi_saved);
+	json_api.extract_field(json_obj, MWI_JSON_URGENT, &mwi_urgent);
+	json_api.extract_field(json_obj, MWI_JSON_URGENT_SAVED, &mwi_urgent_saved);
+	json_api.extract_field(json_obj, MWI_JSON_ACCOUNT, &mwi_account);
+
+	struct json_object *ExpiresObj =
+			json_api.get_object(json_obj, BLF_JSON_EXPIRES);
+	if (ExpiresObj != NULL) {
+		expires = json_object_get_int(ExpiresObj);
+	}
+
+	if (mwi_new.len > 0) {
+		len = snprintf(body, MWI_BODY_BUFFER_SIZE, MWI_BODY, mwi_waiting.len,
+				mwi_waiting.s, mwi_account.len, mwi_account.s, mwi_new.len,
+				mwi_new.s, mwi_saved.len, mwi_saved.s, mwi_urgent.len,
+				mwi_urgent.s, mwi_urgent_saved.len, mwi_urgent_saved.s);
+	} else if (mwi_voice_message.len > 0) {
+		len = snprintf(body, MWI_BODY_BUFFER_SIZE, MWI_BODY_VOICE_MESSAGE,
+				mwi_waiting.len, mwi_waiting.s, mwi_account.len, mwi_account.s,
+				mwi_voice_message.len, mwi_voice_message.s);
+	} else {
+		len = snprintf(body, MWI_BODY_BUFFER_SIZE, MWI_BODY_NO_VOICE_MESSAGE,
+				mwi_waiting.len, mwi_waiting.s, mwi_account.len, mwi_account.s);
+	}
+
+	mwi_body.s = body;
+	mwi_body.len = len;
+
+	pua_json_update_presentity(&event, &from_realm, &from_user, &callid, &from, &mwi_body, expires, 1, 1);
+
+ error:
+
+	if(body)
+		pkg_free(body);
+
+	return ret;
+}
+
+
+int pua_json_publish_dialoginfo_to_presentity(struct json_object *json_obj) {
+	int ret = 1;
+	int len;
+	str from = {0, 0}, to = {0, 0}, pres = {0, 0};
+	str from_user = {0, 0}, to_user = {0, 0}, pres_user = {0, 0};
+	str from_realm = {0, 0}, pres_realm = {0, 0};
+	str from_uri = {0, 0}, to_uri = {0, 0};
+	str callid = {0, 0}, fromtag = {0, 0}, totag = {0, 0};
+	str state = {0, 0};
+	str direction = {0, 0};
+	char sender_buf[SENDER_BUFFER_SIZE + 1];
+	str sender = {0, 0};
+	str dialoginfo_body = {0, 0};
+	int expires = 0;
+	str event = str_init("dialog");
+	char to_tag_buffer[TO_TAG_BUFFER_SIZE + 1];
+	char from_tag_buffer[FROM_TAG_BUFFER_SIZE + 1];
+
+	char *body = (char *)pkg_malloc(DIALOGINFO_BODY_BUFFER_SIZE);
+	if(body == NULL) {
+		LM_ERR("Error allocating buffer for publish\n");
+		ret = -1;
+		goto error;
+	}
+
+	json_api.extract_field(json_obj, BLF_JSON_PRES, &pres);
+	json_api.extract_field(json_obj, BLF_JSON_PRES_USER, &pres_user);
+	json_api.extract_field(json_obj, BLF_JSON_PRES_REALM, &pres_realm);
+	json_api.extract_field(json_obj, BLF_JSON_FROM, &from);
+	json_api.extract_field(json_obj, BLF_JSON_FROM_USER, &from_user);
+	json_api.extract_field(json_obj, BLF_JSON_FROM_REALM, &from_realm);
+	json_api.extract_field(json_obj, BLF_JSON_FROM_URI, &from_uri);
+	json_api.extract_field(json_obj, BLF_JSON_TO, &to);
+	json_api.extract_field(json_obj, BLF_JSON_TO_USER, &to_user);
+	json_api.extract_field(json_obj, BLF_JSON_TO_URI, &to_uri);
+	json_api.extract_field(json_obj, BLF_JSON_CALLID, &callid);
+	json_api.extract_field(json_obj, BLF_JSON_FROMTAG, &fromtag);
+	json_api.extract_field(json_obj, BLF_JSON_TOTAG, &totag);
+	json_api.extract_field(json_obj, BLF_JSON_DIRECTION, &direction);
+	json_api.extract_field(json_obj, BLF_JSON_STATE, &state);
+
+	struct json_object *ExpiresObj =
+			json_api.get_object(json_obj, BLF_JSON_EXPIRES);
+	if (ExpiresObj != NULL) {
+		expires = json_object_get_int(ExpiresObj);
+	}
+
+	if (!from.len || !to.len || !state.len) {
+		LM_ERR("missing one of From / To / State\n");
+		goto error;
+	}
+
+	if (!pres.len || !pres_user.len || !pres_realm.len) {
+		pres = from;
+		pres_user = from_user;
+		pres_realm = from_realm;
+	}
+
+	if (!from_uri.len)
+		from_uri = from;
+
+	if (!to_uri.len)
+		to_uri = to;
+
+	if (fromtag.len > 0) {
+		fromtag.len = snprintf(from_tag_buffer, TO_TAG_BUFFER_SIZE, LOCAL_TAG,
+				fromtag.len, fromtag.s);
+		fromtag.s = from_tag_buffer;
+	}
+
+	if (totag.len > 0) {
+		totag.len = snprintf(to_tag_buffer, FROM_TAG_BUFFER_SIZE, REMOTE_TAG,
+				totag.len, totag.s);
+		totag.s = to_tag_buffer;
+	}
+
+	if (callid.len) {
+		if (pua_include_entity) {
+			len = snprintf(body, DIALOGINFO_BODY_BUFFER_SIZE, DIALOGINFO_BODY,
+					pres.len, pres.s, callid.len, callid.s, callid.len,
+					callid.s, fromtag.len, fromtag.s, totag.len, totag.s,
+					direction.len, direction.s, state.len, state.s,
+					from_user.len, from_user.s, from.len, from.s, from_uri.len,
+					from_uri.s, to_user.len, to_user.s, to.len, to.s,
+					to_uri.len, to_uri.s);
+		} else {
+			len = snprintf(body, DIALOGINFO_BODY_BUFFER_SIZE, DIALOGINFO_BODY_2,
+					pres.len, pres.s, callid.len, callid.s, callid.len,
+					callid.s, fromtag.len, fromtag.s, totag.len, totag.s,
+					direction.len, direction.s, state.len, state.s,
+					from_user.len, from_user.s, from.len, from.s, to_user.len,
+					to_user.s, to.len, to.s);
+		}
+	} else {
+		len = snprintf(body, DIALOGINFO_BODY_BUFFER_SIZE, DIALOGINFO_EMPTY_BODY,
+				pres.len, pres.s);
+	}
+
+	sender.len = snprintf(sender_buf, SENDER_BUFFER_SIZE, "sip:%s", callid.s);
+	sender.s = sender_buf;
+
+	dialoginfo_body.s = body;
+	dialoginfo_body.len = len;
+
+	pua_json_update_presentity(&event, &pres_realm, &pres_user, &callid, &sender, &dialoginfo_body, expires, 1, 1);
+
+ error:
+
+	if(body)
+		pkg_free(body);
+
+	return ret;
+}
+
+
+int pua_json_publish(struct sip_msg* msg, char *json) {
+	str event_name = {0, 0}, event_package = {0, 0};
+	struct json_object *json_obj = NULL;
+	int ret = 1;
+
+	/* extract info from json and construct xml */
+	json_obj = json_api.json_parse(json);
+	if (json_obj == NULL) {
+		ret = -1;
+		goto error;
+	}
+
+	json_api.extract_field(json_obj, BLF_JSON_EVENT_NAME, &event_name);
+	if (event_name.len == 6 && strncmp(event_name.s, "update", 6) == 0) {
+		json_api.extract_field(json_obj, BLF_JSON_EVENT_PKG, &event_package);
+		if (event_package.len == str_event_dialog.len
+				&& strncmp(event_package.s, str_event_dialog.s, event_package.len) == 0) {
+			ret = pua_json_publish_dialoginfo_to_presentity(
+					json_obj);
+		} else if (event_package.len == str_event_message_summary.len
+				&& strncmp(event_package.s, str_event_message_summary.s, event_package.len) == 0) {
+			ret = pua_json_publish_mwi_to_presentity(json_obj);
+		} else if (event_package.len == str_event_presence.len
+				&& strncmp(event_package.s, str_event_presence.s, event_package.len) == 0) {
+			ret = pua_json_publish_presence_to_presentity(
+					json_obj);
+		}
+	}
+
+error:
+
+	if (json_obj)
+		json_object_put(json_obj);
+
+	return ret;
+}

+ 33 - 0
src/modules/pua_json/pua_json_publish.h

@@ -0,0 +1,33 @@
+/*
+ * PUA_JSON module interface
+ *
+ * Copyright (C) 2010-2014 2600Hz
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Contributor(s):
+ * 2600Hz Team
+ * Emmanuel Schmidbauer <[email protected]>
+ *
+ */
+
+#ifndef __PUA_JSON_PUBLISH_H_
+#define __PUA_JSON_PUBLISH_H_
+
+int pua_json_publish(struct sip_msg* msg, char *json);
+
+#endif