Browse code

Merge pull request #1424 from kamailio/eschmidbauer/pua_json

pua_json: new module to update presence using JSON data objects

Emmanuel Schmidbauer authored on 08/02/2018 14:27:42 • GitHub committed on 08/02/2018 14:27:42
Showing 15 changed files
... ...
@@ -43,7 +43,7 @@ typedef int (*pres_handle_publish_t)(struct sip_msg* msg, char *str1, char* str2
43 43
 typedef int (*pres_handle_subscribe0_t)(struct sip_msg* msg);
44 44
 typedef int (*pres_handle_subscribe_t)(struct sip_msg* msg, str watcher_user, str watcher_domain);
45 45
 typedef int (*pres_update_presentity_t)(str *event, str *realm, str *user, str *etag,
46
-		str *sender, str *body, int expires, int new_t);
46
+		str *sender, str *body, int expires, int new_t, int replace);
47 47
 typedef int (*pres_refresh_watchers_t)(str *pres, str *event, int type);
48 48
 
49 49
 typedef struct presence_api {
... ...
@@ -302,7 +302,7 @@ int pres_dmq_handle_msg(
302 302
 	switch(action) {
303 303
 		case PRES_DMQ_UPDATE_PRESENTITY:
304 304
 			if(update_presentity(NULL, presentity, &p_body, t_new, &sent_reply,
305
-					   sphere, &cur_etag, &ruid)
305
+					   sphere, &cur_etag, &ruid, 0)
306 306
 					< 0) {
307 307
 				goto error;
308 308
 			}
... ...
@@ -281,7 +281,7 @@ int check_if_dialog(str body, int *is_dialog, char **dialog_id)
281 281
 	doc = xmlParseMemory(body.s, body.len);
282 282
 	if(doc== NULL)
283 283
 	{
284
-		LM_ERR("failed to parse xml document\n");
284
+		LM_INFO("failed to parse xml document\n");
285 285
 		return -1;
286 286
 	}
287 287
 
... ...
@@ -556,7 +556,7 @@ int is_dialog_terminated(presentity_t* presentity)
556 556
 }
557 557
 
558 558
 int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
559
-		int new_t, int* sent_reply, char* sphere, str* etag_override, str* ruid)
559
+		int new_t, int* sent_reply, char* sphere, str* etag_override, str* ruid, int replace)
560 560
 {
561 561
 	db_key_t query_cols[14], rquery_cols[2], update_keys[9], result_cols[7];
562 562
 	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,
658 658
 		}
659 659
 
660 660
 		LM_DBG("new htable record added\n");
661
+		if (presentity->expires == -1) {
662
+			replace = 1;
663
+		}
661 664
 
662 665
 		/* insert new record into database */
663 666
 		query_cols[n_query_cols] = &str_sender_col;
... ...
@@ -697,7 +700,7 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
697 700
 		query_vals[n_query_cols].val.str_val = p_ruid;
698 701
 		n_query_cols++;
699 702
 
700
-		if (presentity->expires != -1)
703
+		if (!replace)
701 704
 		{
702 705
 			/* A real PUBLISH */
703 706
 			query_cols[n_query_cols] = &str_expires_col;
... ...
@@ -748,6 +751,10 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
748 751
 			query_vals[n_query_cols].type = DB1_INT;
749 752
 			query_vals[n_query_cols].nul = 0;
750 753
 			query_vals[n_query_cols].val.int_val = -1;
754
+			if(presentity->expires != -1) {
755
+				query_vals[n_query_cols].val.int_val =
756
+						presentity->expires + (int)time(NULL);
757
+			}
751 758
 			n_query_cols++;
752 759
 
753 760
 			if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
... ...
@@ -1918,7 +1925,7 @@ error:
1918 1925
 
1919 1926
 // used for API updates to the presentity table
1920 1927
 int _api_update_presentity(str *event, str *realm, str *user, str *etag,
1921
-		str *sender, str *body, int expires, int new_t)
1928
+		str *sender, str *body, int expires, int new_t, int replace)
1922 1929
 {
1923 1930
 	int ret;
1924 1931
 	presentity_t *pres = NULL;
... ...
@@ -1936,7 +1943,7 @@ int _api_update_presentity(str *event, str *realm, str *user, str *etag,
1936 1943
 	if(sphere_enable) {
1937 1944
 		sphere = extract_sphere(*body);
1938 1945
 	}
1939
-	ret = update_presentity(NULL, pres, body, new_t, NULL, sphere, NULL, NULL);
1946
+	ret = update_presentity(NULL, pres, body, new_t, NULL, sphere, NULL, NULL, replace);
1940 1947
 
1941 1948
 	if(pres)
1942 1949
 		pkg_free(pres);
... ...
@@ -55,11 +55,11 @@ presentity_t* new_presentity( str* domain,str* user,int expires,
55 55
 
56 56
 /* update presentity in database */
57 57
 int update_presentity(struct sip_msg* msg,presentity_t* p,str* body,int t_new,
58
-		int* sent_reply, char* sphere, str* etag_override, str* ruid);
58
+		int* sent_reply, char* sphere, str* etag_override, str* ruid, int replace);
59 59
 
60 60
 /* update presentity in database using API */
61 61
 int _api_update_presentity(str *event, str *realm, str *user, str *etag,
62
-		str *sender, str *body, int expires, int reset);
62
+		str *sender, str *body, int expires, int new_t, int replace);
63 63
 
64 64
 /* free memory */
65 65
 void free_presentity(presentity_t *p);
... ...
@@ -494,7 +494,7 @@ int ki_handle_publish_uri(struct sip_msg* msg, str* sender_uri)
494 494
 	}
495 495
 
496 496
 	/* querry the database and update or insert */
497
-	if(update_presentity(msg, presentity, &body, etag_gen, &sent_reply, sphere, NULL, NULL) <0)
497
+	if(update_presentity(msg, presentity, &body, etag_gen, &sent_reply, sphere, NULL, NULL, 0) <0)
498 498
 	{
499 499
 		LM_ERR("when updating presentity\n");
500 500
 		goto error;
... ...
@@ -635,7 +635,7 @@ int update_hard_presentity(str *pres_uri, pres_ev_t *event, str *file_uri, str *
635 635
 		goto done;
636 636
 	}
637 637
 
638
-	if (update_presentity(NULL, pres, pidf_doc, new_t, NULL, sphere, NULL, NULL) < 0)
638
+	if (update_presentity(NULL, pres, pidf_doc, new_t, NULL, sphere, NULL, NULL, 0) < 0)
639 639
 	{
640 640
 		LM_ERR("updating presentity\n");
641 641
 		goto done;
642 642
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+#
2
+# PUA_JSON module
3
+#
4
+#
5
+# WARNING: do not run this directly, it should be run by the master Makefile
6
+
7
+include ../../Makefile.defs
8
+
9
+auto_gen=
10
+NAME=pua_json.so
11
+
12
+LIBS=-ljson-c
13
+DEFS+=-I$(LOCALBASE)/include -I/usr/local/include $(shell pkg-config --cflags json-c)
14
+
15
+DEFS+=-DKAMAILIO_MOD_INTERFACE
16
+
17
+include ../../Makefile.modules
0 18
new file mode 100644
1 19
new file mode 100644
... ...
@@ -0,0 +1,134 @@
1
+/*
2
+ * PUA_JSON module
3
+ *
4
+ * Copyright (C) 2010-2014 2600Hz
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ * Contributor(s):
23
+ * 2600Hz Team
24
+ * Emmanuel Schmidbauer <eschmidbauer@gmail.com>
25
+ *
26
+ */
27
+
28
+#ifndef _PUA_JSON_DEFS_H_
29
+#define _PUA_JSON_DEFS_H_
30
+
31
+#define BLF_MAX_DIALOGS 8
32
+#define BLF_JSON_PRES		"Presentity"
33
+#define BLF_JSON_PRES_USER	"Presentity-User"
34
+#define BLF_JSON_PRES_REALM	"Presentity-Realm"
35
+#define BLF_JSON_FROM      	"From"
36
+#define BLF_JSON_FROM_USER 	"From-User"
37
+#define BLF_JSON_FROM_REALM	"From-Realm"
38
+#define BLF_JSON_FROM_URI	"From-URI"
39
+#define BLF_JSON_TO        	"To"
40
+#define BLF_JSON_TO_USER 	"To-User"
41
+#define BLF_JSON_TO_REALM	"To-Realm"
42
+#define BLF_JSON_TO_URI		"To-URI"
43
+#define BLF_JSON_CALLID    	"Call-ID"
44
+#define BLF_JSON_TOTAG     	"To-Tag"
45
+#define BLF_JSON_FROMTAG   	"From-Tag"
46
+#define BLF_JSON_STATE     	"State"
47
+#define BLF_JSON_USER      	"User"
48
+#define BLF_JSON_QUEUE     	"Queue"
49
+#define BLF_JSON_EXPIRES	"Expires"
50
+#define BLF_JSON_APP_NAME       "App-Name"
51
+#define BLF_JSON_APP_VERSION    "App-Version"
52
+#define BLF_JSON_NODE           "Node"
53
+#define BLF_JSON_SERVERID       "Server-ID"
54
+#define BLF_JSON_EVENT_CATEGORY "Event-Category"
55
+#define BLF_JSON_EVENT_NAME     "Event-Name"
56
+#define BLF_JSON_TYPE           "Type"
57
+#define BLF_JSON_MSG_ID         "Msg-ID"
58
+#define BLF_JSON_DIRECTION      "Direction"
59
+
60
+#define BLF_JSON_CONTACT   	"Contact"
61
+#define BLF_JSON_EVENT_PKG      "Event-Package"
62
+#define MWI_JSON_WAITING        "Messages-Waiting"
63
+#define MWI_JSON_VOICE_MESSAGE  "MWI-Voice-Message"
64
+#define MWI_JSON_NEW            "Messages-New"
65
+#define MWI_JSON_SAVED          "Messages-Saved"
66
+#define MWI_JSON_URGENT         "Messages-Urgent"
67
+#define MWI_JSON_URGENT_SAVED   "Messages-Urgent-Saved"
68
+#define MWI_JSON_ACCOUNT        "Message-Account"
69
+#define MWI_JSON_FROM      	"From"
70
+#define MWI_JSON_TO        	"To"
71
+
72
+#define TO_TAG_BUFFER_SIZE 128
73
+#define FROM_TAG_BUFFER_SIZE 128
74
+#define SENDER_BUFFER_SIZE 1024
75
+#define DIALOGINFO_BODY_BUFFER_SIZE 8192
76
+#define MWI_BODY_BUFFER_SIZE 2048
77
+#define PRESENCE_BODY_BUFFER_SIZE 4096
78
+
79
+#define MWI_BODY_VOICE_MESSAGE "Messages-Waiting: %.*s\r\nMessage-Account: %.*s\r\nVoice-Message: %.*s\r\n"
80
+#define MWI_BODY_NO_VOICE_MESSAGE "Messages-Waiting: %.*s\r\nMessage-Account: %.*s\r\n"
81
+#define MWI_BODY             "Messages-Waiting: %.*s\r\nMessage-Account: %.*s\r\nVoice-Message: %.*s/%.*s (%.*s/%.*s)\r\n"
82
+#define PRESENCE_BODY        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
83
+<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\"> \
84
+<tuple xmlns=\"urn:ietf:params:xml:ns:pidf\" id=\"%s\">\
85
+<status>\
86
+<basic>%s</basic>\
87
+</status>\
88
+</tuple>\
89
+<note xmlns=\"urn:ietf:params:xml:ns:pidf\">%s</note>\
90
+<dm:person xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" id=\"1\">\
91
+<rpid:activities>%s</rpid:activities>\
92
+<dm:note>%s</dm:note>\
93
+</dm:person>\
94
+</presence>"
95
+
96
+#define DIALOGINFO_EMPTY_BODY "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
97
+<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"1\" state=\"full\" entity=\"%.*s\"> \
98
+<dialog call-id=\"76001e23e09704ea9e1257ebea85e1f3\" direction=\"initiator\">\
99
+<state>terminated</state>\
100
+</dialog>\
101
+</dialog-info>"
102
+
103
+#define LOCAL_TAG "local-tag=\"%.*s\""
104
+#define REMOTE_TAG "remote-tag=\"%.*s\""
105
+
106
+#define DIALOGINFO_BODY "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
107
+<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"1\" state=\"full\" entity=\"%.*s\">\
108
+<dialog id=\"%.*s\" call-id=\"%.*s\" %.*s %.*s direction=\"%.*s\">\
109
+<state>%.*s</state>\
110
+<local>\
111
+<identity display=\"%.*s\">%.*s</identity>\
112
+<target uri=\"%.*s\"/>\
113
+</local>\
114
+<remote>\
115
+<identity display=\"%.*s\">%.*s</identity>\
116
+<target uri=\"%.*s\"/>\
117
+</remote>\
118
+</dialog>\
119
+</dialog-info>"
120
+
121
+#define DIALOGINFO_BODY_2 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
122
+<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"1\" state=\"full\" entity=\"%.*s\">\
123
+<dialog id=\"%.*s\" call-id=\"%.*s\" %.*s %.*s direction=\"%.*s\">\
124
+<state>%.*s</state>\
125
+<local>\
126
+<identity display=\"%.*s\">%.*s</identity>\
127
+</local>\
128
+<remote>\
129
+<identity display=\"%.*s\">%.*s</identity>\
130
+</remote>\
131
+</dialog>\
132
+</dialog-info>"
133
+
134
+#endif /* _PUA_JSON_DEFS_H_ */
0 135
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+docs = json_pua.xml
2
+
3
+docbook_dir = ../../../../doc/docbook
4
+include $(docbook_dir)/Makefile.module
0 5
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+
11
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
12
+    <bookinfo>
13
+	<title>PUA_JSON Module</title>
14
+	<productname class="trade">&kamailioname;</productname>
15
+	<authorgroup>
16
+	    <author>
17
+		<firstname>Emmanuel Schmidbauer</firstname>
18
+		<email>eschmidbauer@gmail.com</email>
19
+	    </author>
20
+	    <editor>
21
+		<firstname>Emmanuel</firstname>
22
+		<surname>Schmidbauer</surname>
23
+		<email>eschmidbauer@gmail.com</email>
24
+	    </editor>
25
+	</authorgroup>
26
+	<copyright>
27
+	    <year>2018</year>
28
+	    <holder>VoIPxSWITCH</holder>
29
+	</copyright>
30
+    </bookinfo>
31
+    <toc></toc>
32
+    
33
+    <xi:include href="pua_json_admin.xml"/>
34
+    <!-- <xi:include href="db_text_devel.xml"/> -->
35
+    
36
+
37
+</book>
0 38
new file mode 100644
... ...
@@ -0,0 +1,105 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+<!-- Module User's Guide -->
11
+
12
+<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
13
+	<title>&adminguide;</title>
14
+
15
+
16
+	<section>
17
+		<title>Overview</title>
18
+		<para>The PUA_JSON module adds support to publish updates to the presence module through the pua_json_publish() function.
19
+		</para>
20
+		<para>
21
+			From a high-level perspective, the module may be used for:
22
+			<itemizedlist>
23
+				<listitem>
24
+					<para>
25
+						Providing a real-time presence updates.
26
+					</para>
27
+				</listitem>
28
+			</itemizedlist>
29
+		</para>
30
+
31
+	</section>
32
+	<section>
33
+		<title>How it works</title>
34
+		<para>
35
+			The module parses json data objects and inserts them into the presentity table for real-time presence updates.
36
+		</para>
37
+	</section>
38
+
39
+	<section>
40
+		<title>Dependencies</title>
41
+		<section>
42
+			<title>&kamailio; Modules</title>
43
+			<para>
44
+				The following modules must be loaded before this module:
45
+				<itemizedlist>
46
+					<listitem>
47
+						<para>
48
+							<emphasis>none</emphasis>.
49
+						</para>
50
+					</listitem>
51
+				</itemizedlist>
52
+			</para>
53
+		</section>
54
+		<section>
55
+			<title>External Libraries or Applications</title>
56
+			<para>
57
+				The following libraries or applications must be installed
58
+				<itemizedlist>
59
+					<listitem>
60
+						<para>
61
+							<emphasis>libjson</emphasis>.
62
+						</para>
63
+					</listitem>
64
+				</itemizedlist>
65
+			</para>
66
+		</section>
67
+	</section>
68
+
69
+	<section>
70
+		<title>Functions</title>
71
+		<section>
72
+			<title>
73
+				<function moreinfo="none">pua_json_publish(json_payload)</function>
74
+			</title>
75
+			<para>
76
+				The function build presentity state from json_payload and updates presentity table.
77
+			</para>
78
+			<para>
79
+				Usage: presence related.
80
+			</para>
81
+			<para>
82
+				This function can be used from ANY ROUTE.
83
+			</para>
84
+
85
+			<example>
86
+				<title><function>pua_json_publish</function> usage</title>
87
+<programlisting format="linespecific">
88
+...
89
+event_route[xhttp:request] {
90
+	$var(call-id) = $(rb{json.parse,Call-ID});
91
+	if ($(rb{json.parse,Event-Package}) == "dialog") {
92
+		xlog("L_INFO", "$var(call-id)|log|received $(rb{json.parse,Event-Package}) update for $(rb{json.parse,From})");
93
+		pua_json_publish($rb);
94
+	}
95
+}
96
+...
97
+</programlisting>
98
+			</example>
99
+		</section>
100
+
101
+	</section>
102
+
103
+
104
+</chapter>
105
+
0 106
new file mode 100644
... ...
@@ -0,0 +1,68 @@
1
+/*
2
+ * PUA_JSON module interface
3
+ *
4
+ * Copyright (C) 2018 VoIPxSWITCH
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ *
23
+ */
24
+
25
+#include <stdio.h>
26
+#include <string.h>
27
+
28
+#include "../json/api.h"
29
+#include "../presence/bind_presence.h"
30
+#include "pua_json_mod.h"
31
+
32
+MODULE_VERSION
33
+
34
+static param_export_t params[] = {
35
+		{"pua_include_entity", INT_PARAM, &pua_include_entity},
36
+		{0, 0, 0}};
37
+
38
+static cmd_export_t cmds[] = {
39
+		{"pua_json_publish", (cmd_function)pua_json_publish, 1, 0, 0,
40
+				ANY_ROUTE},
41
+		{0, 0, 0, 0, 0, 0}};
42
+
43
+struct module_exports exports = {
44
+		"pua_json", DEFAULT_DLFLAGS, /* dlopen flags */
45
+		cmds,						 /* Exported functions */
46
+		params,						 /* Exported parameters */
47
+		0,							 /* exported statistics */
48
+		0,							 /* exported MI functions */
49
+		0, 0,						 /* extra processes */
50
+		mod_init,					 /* module initialization function */
51
+		0,							 /* response function*/
52
+		0,							 /* destroy function */
53
+		0							 /* per-child init function */
54
+};
55
+
56
+static int mod_init(void)
57
+{
58
+	if(json_load_api(&json_api) < 0) {
59
+		LM_ERR("cannot bind to JSON API\n");
60
+		return -1;
61
+	}
62
+	if(presence_load_api(&presence_api) < 0) {
63
+		LM_ERR("cannot bind to PRESENCE API\n");
64
+		return -1;
65
+	}
66
+
67
+	return 0;
68
+}
0 69
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+/*
2
+ * PUA_JSON module interface
3
+ *
4
+ * Copyright (C) 2018 VoIPxSWITCH
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ *
23
+ */
24
+
25
+#ifndef __PUA_JSON_MOD_H_
26
+#define __PUA_JSON_MOD_H_
27
+
28
+#include "../../core/mod_fix.h"
29
+#include "pua_json_publish.h"
30
+
31
+json_api_t json_api;
32
+presence_api_t presence_api;
33
+int pua_include_entity = 1;
34
+
35
+static int mod_init(void);
36
+
37
+#endif
0 38
new file mode 100644
... ...
@@ -0,0 +1,389 @@
1
+/*
2
+ * PUA_JSON module interface
3
+ *
4
+ * Copyright (C) 2010-2014 2600Hz
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ * Contributor(s):
23
+ * 2600Hz Team
24
+ * Emmanuel Schmidbauer <eschmidbauer@gmail.com>
25
+ *
26
+ */
27
+
28
+#include <json.h>
29
+#include "../json/api.h"
30
+#include "../presence/bind_presence.h"
31
+
32
+#include "defs.h"
33
+#include "pua_json_publish.h"
34
+
35
+extern json_api_t json_api;
36
+extern presence_api_t presence_api;
37
+extern int pua_include_entity;
38
+
39
+str str_event_message_summary = str_init("message-summary");
40
+str str_event_dialog = str_init("dialog");
41
+str str_event_presence = str_init("presence");
42
+
43
+str str_username_col = str_init("username");
44
+str str_domain_col = str_init("domain");
45
+str str_body_col = str_init("body");
46
+str str_expires_col = str_init("expires");
47
+str str_received_time_col = str_init("received_time");
48
+str str_presentity_uri_col = str_init("presentity_uri");
49
+str str_priority_col = str_init("priority");
50
+
51
+str str_event_col = str_init("event");
52
+str str_contact_col = str_init("contact");
53
+str str_callid_col = str_init("callid");
54
+str str_from_tag_col = str_init("from_tag");
55
+str str_to_tag_col = str_init("to_tag");
56
+str str_etag_col = str_init("etag");
57
+str str_sender_col = str_init("sender");
58
+
59
+str str_presence_note_busy = str_init("Busy");
60
+str str_presence_note_otp = str_init("On the Phone");
61
+str str_presence_note_idle = str_init("Idle");
62
+str str_presence_note_offline = str_init("Offline");
63
+str str_presence_act_busy = str_init("<rpid:busy/>");
64
+str str_presence_act_otp = str_init("<rpid:on-the-phone/>");
65
+str str_presence_status_offline = str_init("closed");
66
+str str_presence_status_online = str_init("open");
67
+
68
+str str_null_string = str_init("NULL");
69
+
70
+int pua_json_update_presentity(str *event, str *realm, str *user, str *etag, str *sender, str *body, int expires, int new_t, int replace) {
71
+	int ret;
72
+	if(!event->len)
73
+	{
74
+		LM_ERR("presence event must be set\n");
75
+		return -1;
76
+	}
77
+	if (!realm->len) {	
78
+		LM_ERR("presence realm must be set\n");
79
+		return -1;
80
+	}
81
+	if (!user->len) {
82
+		LM_ERR("presence user must be set\n");
83
+		return -1;
84
+	}
85
+	if (!etag->len) {
86
+		LM_ERR("presence etag must be set\n");
87
+		return -1;
88
+	}
89
+	if (!sender->len) {
90
+		LM_ERR("presence sender must be set\n");
91
+		return -1;
92
+	}
93
+	if (!body->len) {
94
+		LM_ERR("presence body must be set\n");
95
+		return -1;
96
+	}
97
+	ret = presence_api.update_presentity(
98
+			event, realm, user, etag, sender, body, expires, new_t, replace);
99
+	return ret;
100
+}
101
+
102
+int pua_json_publish_presence_to_presentity(struct json_object *json_obj) {
103
+	int ret = 1;
104
+	int len;
105
+	str from = {0, 0};
106
+	str from_user = {0, 0}, to_user = {0, 0};
107
+	str from_realm = {0, 0};
108
+	str callid = {0, 0};
109
+	str state = {0, 0};
110
+	str event = str_init("presence");
111
+	str presence_body = {0, 0};
112
+	str activity = str_init("");
113
+	str note = str_init("Available");
114
+	str status = str_presence_status_online;
115
+	int expires = 0;
116
+
117
+	char *body = (char *)pkg_malloc(PRESENCE_BODY_BUFFER_SIZE);
118
+	if (body == NULL) {
119
+		LM_ERR("Error allocating buffer for publish\n");
120
+		ret = -1;
121
+		goto error;
122
+	}
123
+
124
+	json_api.extract_field(json_obj, BLF_JSON_FROM, &from);
125
+	json_api.extract_field(json_obj, BLF_JSON_FROM_USER, &from_user);
126
+	json_api.extract_field(json_obj, BLF_JSON_FROM_REALM, &from_realm);
127
+	json_api.extract_field(json_obj, BLF_JSON_TO_USER, &to_user);
128
+	json_api.extract_field(json_obj, BLF_JSON_CALLID, &callid);
129
+	json_api.extract_field(json_obj, BLF_JSON_STATE, &state);
130
+
131
+	struct json_object *ExpiresObj =  json_api.get_object(json_obj, BLF_JSON_EXPIRES);
132
+	if (ExpiresObj != NULL) {
133
+		expires = json_object_get_int(ExpiresObj);
134
+	}
135
+
136
+	if (!from_user.len || !to_user.len || !state.len) {
137
+		LM_ERR("missing one of From / To / State\n");
138
+		goto error;
139
+	}
140
+
141
+	if (!strcmp(state.s, "early")) {
142
+		note = str_presence_note_busy;
143
+		activity = str_presence_act_busy;
144
+
145
+	} else if (!strcmp(state.s, "confirmed")) {
146
+		note = str_presence_note_otp;
147
+		activity = str_presence_act_otp;
148
+
149
+	} else if (!strcmp(state.s, "offline")) {
150
+		note = str_presence_note_offline;
151
+		status = str_presence_status_offline;
152
+
153
+	}; // else {
154
+	//	note = str_presence_note_idle;
155
+	//}
156
+
157
+	len = snprintf(body, PRESENCE_BODY_BUFFER_SIZE, PRESENCE_BODY, from_user.s,
158
+			callid.s, status.s, note.s, activity.s, note.s);
159
+
160
+	presence_body.s = body;
161
+	presence_body.len = len;
162
+
163
+	pua_json_update_presentity(&event, &from_realm, &from_user, &callid, &from, &presence_body, expires, 1, 1);
164
+
165
+ error:
166
+
167
+	if(body)
168
+		pkg_free(body);
169
+
170
+	return ret;
171
+}
172
+
173
+int pua_json_publish_mwi_to_presentity(struct json_object *json_obj) {
174
+	int ret = 1;
175
+	int len;
176
+	str event = str_init("message-summary");
177
+	str from = {0, 0};
178
+	str from_user = {0, 0};
179
+	str from_realm = {0, 0};
180
+	str callid = {0, 0};
181
+	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};
182
+	int expires = 0;
183
+
184
+	char *body = (char *)pkg_malloc(MWI_BODY_BUFFER_SIZE);
185
+	if(body == NULL) {
186
+		LM_ERR("Error allocating buffer for publish\n");
187
+		ret = -1;
188
+		goto error;
189
+	}
190
+
191
+	json_api.extract_field(json_obj, BLF_JSON_FROM, &from);
192
+	json_api.extract_field(json_obj, BLF_JSON_FROM_USER, &from_user);
193
+	json_api.extract_field(json_obj, BLF_JSON_FROM_REALM, &from_realm);
194
+	json_api.extract_field(json_obj, BLF_JSON_CALLID, &callid);
195
+
196
+	json_api.extract_field(json_obj, MWI_JSON_WAITING, &mwi_waiting);
197
+	json_api.extract_field(
198
+			json_obj, MWI_JSON_VOICE_MESSAGE, &mwi_voice_message);
199
+	json_api.extract_field(json_obj, MWI_JSON_NEW, &mwi_new);
200
+	json_api.extract_field(json_obj, MWI_JSON_SAVED, &mwi_saved);
201
+	json_api.extract_field(json_obj, MWI_JSON_URGENT, &mwi_urgent);
202
+	json_api.extract_field(json_obj, MWI_JSON_URGENT_SAVED, &mwi_urgent_saved);
203
+	json_api.extract_field(json_obj, MWI_JSON_ACCOUNT, &mwi_account);
204
+
205
+	struct json_object *ExpiresObj =
206
+			json_api.get_object(json_obj, BLF_JSON_EXPIRES);
207
+	if (ExpiresObj != NULL) {
208
+		expires = json_object_get_int(ExpiresObj);
209
+	}
210
+
211
+	if (mwi_new.len > 0) {
212
+		len = snprintf(body, MWI_BODY_BUFFER_SIZE, MWI_BODY, mwi_waiting.len,
213
+				mwi_waiting.s, mwi_account.len, mwi_account.s, mwi_new.len,
214
+				mwi_new.s, mwi_saved.len, mwi_saved.s, mwi_urgent.len,
215
+				mwi_urgent.s, mwi_urgent_saved.len, mwi_urgent_saved.s);
216
+	} else if (mwi_voice_message.len > 0) {
217
+		len = snprintf(body, MWI_BODY_BUFFER_SIZE, MWI_BODY_VOICE_MESSAGE,
218
+				mwi_waiting.len, mwi_waiting.s, mwi_account.len, mwi_account.s,
219
+				mwi_voice_message.len, mwi_voice_message.s);
220
+	} else {
221
+		len = snprintf(body, MWI_BODY_BUFFER_SIZE, MWI_BODY_NO_VOICE_MESSAGE,
222
+				mwi_waiting.len, mwi_waiting.s, mwi_account.len, mwi_account.s);
223
+	}
224
+
225
+	mwi_body.s = body;
226
+	mwi_body.len = len;
227
+
228
+	pua_json_update_presentity(&event, &from_realm, &from_user, &callid, &from, &mwi_body, expires, 1, 1);
229
+
230
+ error:
231
+
232
+	if(body)
233
+		pkg_free(body);
234
+
235
+	return ret;
236
+}
237
+
238
+
239
+int pua_json_publish_dialoginfo_to_presentity(struct json_object *json_obj) {
240
+	int ret = 1;
241
+	int len;
242
+	str from = {0, 0}, to = {0, 0}, pres = {0, 0};
243
+	str from_user = {0, 0}, to_user = {0, 0}, pres_user = {0, 0};
244
+	str from_realm = {0, 0}, pres_realm = {0, 0};
245
+	str from_uri = {0, 0}, to_uri = {0, 0};
246
+	str callid = {0, 0}, fromtag = {0, 0}, totag = {0, 0};
247
+	str state = {0, 0};
248
+	str direction = {0, 0};
249
+	char sender_buf[SENDER_BUFFER_SIZE + 1];
250
+	str sender = {0, 0};
251
+	str dialoginfo_body = {0, 0};
252
+	int expires = 0;
253
+	str event = str_init("dialog");
254
+	char to_tag_buffer[TO_TAG_BUFFER_SIZE + 1];
255
+	char from_tag_buffer[FROM_TAG_BUFFER_SIZE + 1];
256
+
257
+	char *body = (char *)pkg_malloc(DIALOGINFO_BODY_BUFFER_SIZE);
258
+	if(body == NULL) {
259
+		LM_ERR("Error allocating buffer for publish\n");
260
+		ret = -1;
261
+		goto error;
262
+	}
263
+
264
+	json_api.extract_field(json_obj, BLF_JSON_PRES, &pres);
265
+	json_api.extract_field(json_obj, BLF_JSON_PRES_USER, &pres_user);
266
+	json_api.extract_field(json_obj, BLF_JSON_PRES_REALM, &pres_realm);
267
+	json_api.extract_field(json_obj, BLF_JSON_FROM, &from);
268
+	json_api.extract_field(json_obj, BLF_JSON_FROM_USER, &from_user);
269
+	json_api.extract_field(json_obj, BLF_JSON_FROM_REALM, &from_realm);
270
+	json_api.extract_field(json_obj, BLF_JSON_FROM_URI, &from_uri);
271
+	json_api.extract_field(json_obj, BLF_JSON_TO, &to);
272
+	json_api.extract_field(json_obj, BLF_JSON_TO_USER, &to_user);
273
+	json_api.extract_field(json_obj, BLF_JSON_TO_URI, &to_uri);
274
+	json_api.extract_field(json_obj, BLF_JSON_CALLID, &callid);
275
+	json_api.extract_field(json_obj, BLF_JSON_FROMTAG, &fromtag);
276
+	json_api.extract_field(json_obj, BLF_JSON_TOTAG, &totag);
277
+	json_api.extract_field(json_obj, BLF_JSON_DIRECTION, &direction);
278
+	json_api.extract_field(json_obj, BLF_JSON_STATE, &state);
279
+
280
+	struct json_object *ExpiresObj =
281
+			json_api.get_object(json_obj, BLF_JSON_EXPIRES);
282
+	if (ExpiresObj != NULL) {
283
+		expires = json_object_get_int(ExpiresObj);
284
+	}
285
+
286
+	if (!from.len || !to.len || !state.len) {
287
+		LM_ERR("missing one of From / To / State\n");
288
+		goto error;
289
+	}
290
+
291
+	if (!pres.len || !pres_user.len || !pres_realm.len) {
292
+		pres = from;
293
+		pres_user = from_user;
294
+		pres_realm = from_realm;
295
+	}
296
+
297
+	if (!from_uri.len)
298
+		from_uri = from;
299
+
300
+	if (!to_uri.len)
301
+		to_uri = to;
302
+
303
+	if (fromtag.len > 0) {
304
+		fromtag.len = snprintf(from_tag_buffer, TO_TAG_BUFFER_SIZE, LOCAL_TAG,
305
+				fromtag.len, fromtag.s);
306
+		fromtag.s = from_tag_buffer;
307
+	}
308
+
309
+	if (totag.len > 0) {
310
+		totag.len = snprintf(to_tag_buffer, FROM_TAG_BUFFER_SIZE, REMOTE_TAG,
311
+				totag.len, totag.s);
312
+		totag.s = to_tag_buffer;
313
+	}
314
+
315
+	if (callid.len) {
316
+		if (pua_include_entity) {
317
+			len = snprintf(body, DIALOGINFO_BODY_BUFFER_SIZE, DIALOGINFO_BODY,
318
+					pres.len, pres.s, callid.len, callid.s, callid.len,
319
+					callid.s, fromtag.len, fromtag.s, totag.len, totag.s,
320
+					direction.len, direction.s, state.len, state.s,
321
+					from_user.len, from_user.s, from.len, from.s, from_uri.len,
322
+					from_uri.s, to_user.len, to_user.s, to.len, to.s,
323
+					to_uri.len, to_uri.s);
324
+		} else {
325
+			len = snprintf(body, DIALOGINFO_BODY_BUFFER_SIZE, DIALOGINFO_BODY_2,
326
+					pres.len, pres.s, callid.len, callid.s, callid.len,
327
+					callid.s, fromtag.len, fromtag.s, totag.len, totag.s,
328
+					direction.len, direction.s, state.len, state.s,
329
+					from_user.len, from_user.s, from.len, from.s, to_user.len,
330
+					to_user.s, to.len, to.s);
331
+		}
332
+	} else {
333
+		len = snprintf(body, DIALOGINFO_BODY_BUFFER_SIZE, DIALOGINFO_EMPTY_BODY,
334
+				pres.len, pres.s);
335
+	}
336
+
337
+	sender.len = snprintf(sender_buf, SENDER_BUFFER_SIZE, "sip:%s", callid.s);
338
+	sender.s = sender_buf;
339
+
340
+	dialoginfo_body.s = body;
341
+	dialoginfo_body.len = len;
342
+
343
+	pua_json_update_presentity(&event, &pres_realm, &pres_user, &callid, &sender, &dialoginfo_body, expires, 1, 1);
344
+
345
+ error:
346
+
347
+	if(body)
348
+		pkg_free(body);
349
+
350
+	return ret;
351
+}
352
+
353
+
354
+int pua_json_publish(struct sip_msg* msg, char *json) {
355
+	str event_name = {0, 0}, event_package = {0, 0};
356
+	struct json_object *json_obj = NULL;
357
+	int ret = 1;
358
+
359
+	/* extract info from json and construct xml */
360
+	json_obj = json_api.json_parse(json);
361
+	if (json_obj == NULL) {
362
+		ret = -1;
363
+		goto error;
364
+	}
365
+
366
+	json_api.extract_field(json_obj, BLF_JSON_EVENT_NAME, &event_name);
367
+	if (event_name.len == 6 && strncmp(event_name.s, "update", 6) == 0) {
368
+		json_api.extract_field(json_obj, BLF_JSON_EVENT_PKG, &event_package);
369
+		if (event_package.len == str_event_dialog.len
370
+				&& strncmp(event_package.s, str_event_dialog.s, event_package.len) == 0) {
371
+			ret = pua_json_publish_dialoginfo_to_presentity(
372
+					json_obj);
373
+		} else if (event_package.len == str_event_message_summary.len
374
+				&& strncmp(event_package.s, str_event_message_summary.s, event_package.len) == 0) {
375
+			ret = pua_json_publish_mwi_to_presentity(json_obj);
376
+		} else if (event_package.len == str_event_presence.len
377
+				&& strncmp(event_package.s, str_event_presence.s, event_package.len) == 0) {
378
+			ret = pua_json_publish_presence_to_presentity(
379
+					json_obj);
380
+		}
381
+	}
382
+
383
+error:
384
+
385
+	if (json_obj)
386
+		json_object_put(json_obj);
387
+
388
+	return ret;
389
+}
0 390
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+/*
2
+ * PUA_JSON module interface
3
+ *
4
+ * Copyright (C) 2010-2014 2600Hz
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ * Contributor(s):
23
+ * 2600Hz Team
24
+ * Emmanuel Schmidbauer <eschmidbauer@gmail.com>
25
+ *
26
+ */
27
+
28
+#ifndef __PUA_JSON_PUBLISH_H_
29
+#define __PUA_JSON_PUBLISH_H_
30
+
31
+int pua_json_publish(struct sip_msg* msg, char *json);
32
+
33
+#endif