diff --git a/src/modules/json/json_funcs.c b/src/modules/json/json_funcs.c index ae036ac1f1d..4b57a22d123 100644 --- a/src/modules/json/json_funcs.c +++ b/src/modules/json/json_funcs.c @@ -270,39 +270,6 @@ int tr_json_get_field(struct sip_msg *msg, char *json, char *field, char *dst) return 1; } -struct json_object *json_parse(const char *str) -{ - struct json_tokener *tok; - struct json_object *obj; - - tok = json_tokener_new(); - if(!tok) { - LM_ERR("Error parsing json: could not allocate tokener\n"); - return NULL; - } - - obj = json_tokener_parse_ex(tok, str, -1); - if(tok->err != json_tokener_success) { - LM_ERR("Error parsing json: %s\n", json_tokener_error_desc(tok->err)); - LM_ERR("%s\n", str); - if(obj != NULL) { - json_object_put(obj); - } - obj = NULL; - } - - json_tokener_free(tok); - return obj; -} - -struct json_object *json_get_object( - struct json_object *jso, const char *key) -{ - struct json_object *result = NULL; - json_object_object_get_ex(jso, key, &result); - return result; -} - int tr_json_get_keys(struct sip_msg *msg, char *json, char *field, char *dst) { str json_s; diff --git a/src/modules/json/json_funcs.h b/src/modules/json/json_funcs.h index 331d1e3df8b..18298b1530e 100644 --- a/src/modules/json/json_funcs.h +++ b/src/modules/json/json_funcs.h @@ -51,8 +51,37 @@ extern str json_event_sub_key; int tr_json_get_field(struct sip_msg *msg, char *json, char *field, char *dst); int tr_json_get_keys(struct sip_msg *msg, char *json, char *field, char *dst); -struct json_object *json_parse(const char *str); -struct json_object *json_get_object( - struct json_object *jso, const char *key); +static inline struct json_object *json_parse(const char *str) +{ + struct json_tokener *tok; + struct json_object *obj; + + tok = json_tokener_new(); + if(!tok) { + LM_ERR("Error parsing json: could not allocate tokener\n"); + return NULL; + } + + obj = json_tokener_parse_ex(tok, str, -1); + if(tok->err != json_tokener_success) { + LM_ERR("Error parsing json: %s\n", json_tokener_error_desc(tok->err)); + LM_ERR("%s\n", str); + if(obj != NULL) { + json_object_put(obj); + } + obj = NULL; + } + + json_tokener_free(tok); + return obj; +} + +static inline struct json_object *json_get_object( + struct json_object *jso, const char *key) +{ + struct json_object *result = NULL; + json_object_object_get_ex(jso, key, &result); + return result; +} #endif diff --git a/src/modules/json_pua/Makefile b/src/modules/json_pua/Makefile new file mode 100644 index 00000000000..6ed989927e6 --- /dev/null +++ b/src/modules/json_pua/Makefile @@ -0,0 +1,20 @@ +# +# JSON_PUA module +# +# +# WARNING: do not run this directly, it should be run by the master Makefile + +include ../../Makefile.defs + +auto_gen= +NAME=json_pua.so + +LIBS=-ljson-c +DEFS+=-I$(LOCALBASE)/include -I/usr/local/include $(shell pkg-config --cflags json-c) + +DEFS+=-DKAMAILIO_MOD_INTERFACE + +SERLIBPATH=../../lib +SER_LIBS=$(SERLIBPATH)/srdb1/srdb1 + +include ../../Makefile.modules diff --git a/src/modules/json_pua/README b/src/modules/json_pua/README new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/modules/json_pua/defs.h b/src/modules/json_pua/defs.h new file mode 100644 index 00000000000..f9a4088a3bb --- /dev/null +++ b/src/modules/json_pua/defs.h @@ -0,0 +1,130 @@ +/* + * JSON_PUA 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): + * Emmanuel Schmidbauer + * + */ + +#ifndef _JSON_PUA_DEFS_H_ +#define _JSON_PUA_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 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 "\ + \ +\ +\ +%s\ +\ +\ +%s\ +\ +%s\ +%s\ +\ +" + +#define DIALOGINFO_EMPTY_BODY "\ + \ +\ +terminated\ +\ +" + +#define LOCAL_TAG "local-tag=\"%.*s\"" +#define REMOTE_TAG "remote-tag=\"%.*s\"" + +#define DIALOGINFO_BODY "\ +\ +\ +%.*s\ +\ +%.*s\ +\ +\ +\ +%.*s\ +\ +\ +\ +" + +#define DIALOGINFO_BODY_2 "\ +\ +\ +%.*s\ +\ +%.*s\ +\ +\ +%.*s\ +\ +\ +" + +#endif /* _JSON_PUA_DEFS_H_ */ diff --git a/src/modules/json_pua/doc/Makefile b/src/modules/json_pua/doc/Makefile new file mode 100644 index 00000000000..253a1aa1f47 --- /dev/null +++ b/src/modules/json_pua/doc/Makefile @@ -0,0 +1,4 @@ +docs = json_pua.xml + +docbook_dir = ../../../../doc/docbook +include $(docbook_dir)/Makefile.module diff --git a/src/modules/json_pua/doc/json_pua.xml b/src/modules/json_pua/doc/json_pua.xml new file mode 100644 index 00000000000..dc7ad3e2073 --- /dev/null +++ b/src/modules/json_pua/doc/json_pua.xml @@ -0,0 +1,37 @@ + + + +%docentities; + +]> + + + + JSON_PUA Module + &kamailioname; + + + Weave Communications + comm@getweave.com + + + Emmanuel + Schmidbauer + emmanuel@getweave.com + + + + 2018 + Weave Communications + + + + + + + + + diff --git a/src/modules/json_pua/doc/json_pua_admin.xml b/src/modules/json_pua/doc/json_pua_admin.xml new file mode 100644 index 00000000000..ea3d5ef0339 --- /dev/null +++ b/src/modules/json_pua/doc/json_pua_admin.xml @@ -0,0 +1,170 @@ + + + +%docentities; + +]> + + + + &adminguide; + + +
+ Overview + The JSON_PUA module adds support to publish updates to the presence module through the json_pua_publish() function. + + + From a high-level perspective, the module may be used for: + + + + Providing a real-time presence updates. + + + + + +
+
+ How it works + + The module parses json data objects and inserts them into the presentity table for real-time presence updates. + +
+ +
+ Dependencies +
+ &kamailio; Modules + + The following modules must be loaded before this module: + + + + none. + + + + +
+
+ External Libraries or Applications + + The following libraries or applications must be installed + + + + libjson. + + + + +
+
+ +
+ Parameters +
+ <varname>db_url</varname>(str) + + The database for the presentity table. + + + If set, the json_pua_publish function will update the presentity status in the database. + + + Usage: presence related. + + + Default value is NULL. + + + Set <varname>db_url</varname> parameter + +... +modparam("json_pua", "db_url", "&defaultdb;") +... + + +
+ +
+ <varname>presentity_table</varname>(str) + + The name of the presentity table in the database. + + + Default value is presentity. + + + Set <varname>presentity_table</varname> parameter + +... +modparam("json_pua", "presentity_table", "my_presentity_table") +... + + +
+ +
+ <varname>db_table_lock_type</varname>(int) + + Enable (=1) or disable (=0) the locks for table during a + transaction. + + + Default value is 1. + + + Set <varname>db_table_lock_type</varname> parameter + +... +modparam("json_pua", "db_table_lock_type", 0) +... + + +
+ +
+
+ Functions +
+ + <function moreinfo="none">json_pua_publish(json_payload)</function> + + + The function build presentity state from json_payload and updates presentity table. + + + Usage: presence related. + + + This function can be used from ANY ROUTE. + + + + <function>json_pua_publish</function> usage + +... +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})"); + json_pua_publish($rb); + pres_refresh_watchers("$(tb{json.parse,From})", "$(rb{json.parse,Event-Package})", 1); + } +} +... + + +
+ +
+ + +
+ diff --git a/src/modules/json_pua/json_pua_mod.c b/src/modules/json_pua/json_pua_mod.c new file mode 100644 index 00000000000..86784207b6e --- /dev/null +++ b/src/modules/json_pua/json_pua_mod.c @@ -0,0 +1,125 @@ +/* + * JSON_PUA module interface + * + * Copyright (C) 2016 Weave Communications + * + * 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 + * + * This module was based on the Kazoo module created by 2600hz. + * Thank you to 2600hz and their brilliant VoIP developers. + * + */ + +#include +#include + +#include "../../core/mod_fix.h" +#include "../../core/sr_module.h" + +#include "json_pua_mod.h" + +MODULE_VERSION + +static cmd_export_t cmds[] = { + {"json_pua_publish", (cmd_function) json_pua_publish, 1, 0, 0, ANY_ROUTE}, + {0, 0, 0, 0, 0, 0} +}; + +static param_export_t params[] = { + {"pua_include_entity", INT_PARAM, &dbn_include_entity}, + {"presentity_table", PARAM_STR, &json_presentity_table}, + {"db_url", PARAM_STR, &json_db_url}, + {"pua_mode", INT_PARAM, &dbn_pua_mode}, + {"db_table_lock_type", INT_PARAM, &db_table_lock_type}, + {0, 0, 0} +}; + +struct module_exports exports = { + "json_pua", + 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 */ + mod_child_init /* per-child init function */ +}; + +static int mod_init(void) +{ + if (dbn_pua_mode == 1) { + json_db_url.len = json_db_url.s ? strlen(json_db_url.s) : 0; + LM_DBG("db_url=%s/%d/%p\n", ZSW(json_db_url.s), json_db_url.len,json_db_url.s); + json_presentity_table.len = strlen(json_presentity_table.s); + + if (json_db_url.len > 0) { + + /* binding to database module */ + if (db_bind_mod(&json_db_url, &json_pa_dbf)) { + LM_ERR("database module not found\n"); + return -1; + } + + if (!DB_CAPABILITY(json_pa_dbf, DB_CAP_ALL)) { + LM_ERR("database module does not implement all functions" + " needed by JSON_PUA module\n"); + return -1; + } + + json_pa_db = json_pa_dbf.init(&json_db_url); + if (!json_pa_db) { + LM_ERR("connection to database failed\n"); + return -1; + } + + if (db_table_lock_type != 1) { + db_table_lock = DB_LOCKING_NONE; + } + + json_pa_dbf.close(json_pa_db); + json_pa_db = NULL; + } + } + + return 0; +} + +static int mod_child_init(int rank) +{ + if(dbn_pua_mode == 1) { + if(json_pa_dbf.init == 0) { + LM_CRIT("child_init: database not bound\n"); + return -1; + } + json_pa_db = json_pa_dbf.init(&json_db_url); + if(!json_pa_db) { + LM_ERR("child %d: unsuccessful connecting to database\n", rank); + return -1; + } + + if(json_pa_dbf.use_table(json_pa_db, &json_presentity_table) < 0) { + LM_ERR("child %d:unsuccessful use_table presentity_table\n", rank); + return -1; + } + LM_DBG("child %d: Database connection opened successfully\n", rank); + } + + return 0; +} \ No newline at end of file diff --git a/src/modules/json_pua/json_pua_mod.h b/src/modules/json_pua/json_pua_mod.h new file mode 100644 index 00000000000..cb13da43bdb --- /dev/null +++ b/src/modules/json_pua/json_pua_mod.h @@ -0,0 +1,50 @@ +/* + * JSON_PUA module interface + * + * Copyright (C) 2016 Weave Communications + * + * 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 + * + * This module was based on the Kazoo module created by 2600hz. + * Thank you to 2600hz and their brilliant VoIP developers. + * + */ + +#ifndef __JSON_PUA_MOD_H_ +#define __JSON_PUA_MOD_H_ + +#include +#include "../../lib/srdb1/db.h" +#include "json_pua_publish.h" + +#define PRESENTITY_TABLE "presentity" + +int dbn_pua_mode = 1; +int dbn_include_entity = 1; + +/* database connection */ +db1_con_t *json_pa_db = NULL; +db_func_t json_pa_dbf; +str json_presentity_table = str_init(PRESENTITY_TABLE); +str json_db_url = {NULL, 0}; +int db_table_lock_type = 1; +db_locking_t db_table_lock = DB_LOCKING_WRITE; + +static int mod_init(void); +static int mod_child_init(int); + +#endif diff --git a/src/modules/json_pua/json_pua_publish.c b/src/modules/json_pua/json_pua_publish.c new file mode 100644 index 00000000000..6a5502498a3 --- /dev/null +++ b/src/modules/json_pua/json_pua_publish.c @@ -0,0 +1,538 @@ +/* + * JSON_PUA 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): + * Emmanuel Schmidbauer + * + */ + +#include "../presence/bind_presence.h" +#include "../json/json_funcs.h" +#include "defs.h" +#include "json_pua_publish.h" +#include + +extern db1_con_t *json_pa_db; +extern db_func_t json_pa_dbf; +extern db_locking_t db_table_lock; +extern str json_presentity_table; +extern str json_db_url; + +extern int dbn_include_entity; +extern int dbn_pua_mode; + +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(""); +str str_presence_act_otp = str_init(""); +str str_presence_status_offline = str_init("closed"); +str str_presence_status_online = str_init("open"); + +str str_null_string = str_init("NULL"); + +int json_pua_update_presentity(str* event, str* realm, str* user, str* etag, str* sender, str* body, int expires, int reset) +{ + db_key_t query_cols[13]; + db_op_t query_ops[13]; + db_val_t query_vals[13]; + int n_query_cols = 0; + int ret = -1; + int use_replace = 1; + + query_cols[n_query_cols] = &str_event_col; + query_ops[n_query_cols] = OP_EQ; + query_vals[n_query_cols].type = DB1_STR; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.str_val = *event; + n_query_cols++; + + query_cols[n_query_cols] = &str_domain_col; + query_ops[n_query_cols] = OP_EQ; + query_vals[n_query_cols].type = DB1_STR; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.str_val = *realm; + n_query_cols++; + + query_cols[n_query_cols] = &str_username_col; + query_ops[n_query_cols] = OP_EQ; + query_vals[n_query_cols].type = DB1_STR; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.str_val = *user; + n_query_cols++; + + query_cols[n_query_cols] = &str_etag_col; + query_ops[n_query_cols] = OP_EQ; + query_vals[n_query_cols].type = DB1_STR; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.str_val = *etag; + n_query_cols++; + + query_cols[n_query_cols] = &str_sender_col; + query_vals[n_query_cols].type = DB1_STR; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.str_val = *sender; + n_query_cols++; + + query_cols[n_query_cols] = &str_body_col; + query_vals[n_query_cols].type = DB1_BLOB; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.str_val = *body; + n_query_cols++; + + query_cols[n_query_cols] = &str_received_time_col; + query_vals[n_query_cols].type = DB1_INT; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.int_val = (int)time(NULL); + n_query_cols++; + + query_cols[n_query_cols] = &str_expires_col; + query_vals[n_query_cols].type = DB1_INT; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.int_val = expires; + n_query_cols++; + + query_cols[n_query_cols] = &str_priority_col; + query_vals[n_query_cols].type = DB1_INT; + query_vals[n_query_cols].nul = 0; + query_vals[n_query_cols].val.int_val = 0; + n_query_cols++; + + if (json_pa_dbf.use_table(json_pa_db, &json_presentity_table) < 0) { + LM_ERR("unsuccessful use_table [%.*s]\n", json_presentity_table.len, json_presentity_table.s); + goto error; + } + + if (json_pa_dbf.replace == NULL || reset > 0) { + use_replace = 0; + LM_DBG("using delete/insert instead of replace\n"); + } + + if (json_pa_dbf.start_transaction) { + if (json_pa_dbf.start_transaction(json_pa_db, db_table_lock) < 0) { + LM_ERR("in start_transaction\n"); + goto error; + } + } + + if (use_replace) { + if (json_pa_dbf.replace(json_pa_db, query_cols, query_vals, n_query_cols, 4, 0) < 0) { + LM_ERR("replacing record in database\n"); + if (json_pa_dbf.abort_transaction) { + if (json_pa_dbf.abort_transaction(json_pa_db) < 0) { + LM_ERR("in abort_transaction\n"); + } + } + goto error; + } + } else { + if (json_pa_dbf.delete(json_pa_db, query_cols, query_ops, query_vals, 4-reset) < 0) { + LM_ERR("deleting record in database\n"); + if (json_pa_dbf.abort_transaction) { + if (json_pa_dbf.abort_transaction(json_pa_db) < 0) + LM_ERR("in abort_transaction\n"); + } + goto error; + } + if (json_pa_dbf.insert(json_pa_db, query_cols, query_vals, n_query_cols) < 0) { + LM_ERR("replacing record in database\n"); + if (json_pa_dbf.abort_transaction) { + if (json_pa_dbf.abort_transaction(json_pa_db) < 0) { + LM_ERR("in abort_transaction\n"); + } + } + goto error; + } + } + + if (json_pa_dbf.end_transaction) { + if (json_pa_dbf.end_transaction(json_pa_db) < 0) { + LM_ERR("in end_transaction\n"); + goto error; + } + } + +error: + + return ret; +} + +int json_pua_publish_presence_to_presentity(struct json_object *json_obj) { + int ret = 1; + str from = { 0, 0 }, to = { 0, 0 }; + str from_user = { 0, 0 }, to_user = { 0, 0 }; + str from_realm = { 0, 0 }, to_realm = { 0, 0 }; + str callid = { 0, 0 }, fromtag = { 0, 0 }, totag = { 0, 0 }; + str state = { 0, 0 }; + str direction = { 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_extract_field(BLF_JSON_FROM, from); + json_extract_field(BLF_JSON_FROM_USER, from_user); + json_extract_field(BLF_JSON_FROM_REALM, from_realm); + json_extract_field(BLF_JSON_TO, to); + json_extract_field(BLF_JSON_TO_USER, to_user); + json_extract_field(BLF_JSON_TO_REALM, to_realm); + json_extract_field(BLF_JSON_CALLID, callid); + json_extract_field(BLF_JSON_FROMTAG, fromtag); + json_extract_field(BLF_JSON_TOTAG, totag); + json_extract_field(BLF_JSON_DIRECTION, direction); + json_extract_field(BLF_JSON_STATE, state); + + struct json_object *ExpiresObj = json_get_object(json_obj, BLF_JSON_EXPIRES); + if (ExpiresObj != NULL) { + expires = json_object_get_int(ExpiresObj); + if (expires > 0) + expires += (int)time(NULL); + } + + 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; + //} + + + sprintf(body, PRESENCE_BODY, from_user.s, callid.s, status.s, note.s, activity.s, note.s); + + presence_body.s = body; + presence_body.len = strlen(body); + + if (dbn_pua_mode == 1) { + json_pua_update_presentity(&event, &from_realm, &from_user, &callid, &from, &presence_body, expires, 1); + } + + error: + + if (body) + pkg_free(body); + + return ret; + +} + +int json_pua_publish_mwi_to_presentity(struct json_object *json_obj) { + int ret = 1; + str event = str_init("message-summary"); + str from = { 0, 0 }, to = { 0, 0 }; + str from_user = { 0, 0 }, to_user = { 0, 0 }; + str from_realm = { 0, 0 }, to_realm = { 0, 0 }; + str callid = { 0, 0 }, fromtag = { 0, 0 }, totag = { 0, 0 }; + str mwi_user = { 0, 0 }, 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_extract_field(BLF_JSON_FROM, from); + json_extract_field(BLF_JSON_FROM_USER, from_user); + json_extract_field(BLF_JSON_FROM_REALM, from_realm); + json_extract_field(BLF_JSON_TO, to); + json_extract_field(BLF_JSON_TO_USER, to_user); + json_extract_field(BLF_JSON_TO_REALM, to_realm); + json_extract_field(BLF_JSON_CALLID, callid); + json_extract_field(BLF_JSON_FROMTAG, fromtag); + json_extract_field(BLF_JSON_TOTAG, totag); + + json_extract_field(MWI_JSON_TO, mwi_user); + json_extract_field(MWI_JSON_WAITING, mwi_waiting); + json_extract_field(MWI_JSON_VOICE_MESSAGE, mwi_voice_message); + json_extract_field(MWI_JSON_NEW, mwi_new); + json_extract_field(MWI_JSON_SAVED, mwi_saved); + json_extract_field(MWI_JSON_URGENT, mwi_urgent); + json_extract_field(MWI_JSON_URGENT_SAVED, mwi_urgent_saved); + json_extract_field(MWI_JSON_ACCOUNT, mwi_account); + + struct json_object *ExpiresObj = json_get_object(json_obj, BLF_JSON_EXPIRES); + if (ExpiresObj != NULL) { + expires = json_object_get_int(ExpiresObj); + if (expires > 0) + expires += (int)time(NULL); + } + + if (mwi_new.len > 0) { + sprintf(body, 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) { + sprintf(body, 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 { + sprintf(body, MWI_BODY_NO_VOICE_MESSAGE, mwi_waiting.len, mwi_waiting.s, + mwi_account.len, mwi_account.s); + } + + mwi_body.s = body; + mwi_body.len = strlen(body); + + if (dbn_pua_mode == 1) { + json_pua_update_presentity(&event, &from_realm, &from_user, &callid, &from, &mwi_body, expires, 1); + } + + error: + + if (body) + pkg_free(body); + + + return ret; +} + + +int json_pua_publish_dialoginfo_to_presentity(struct json_object *json_obj) { + int ret = 1; + 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 }, to_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[1024]; + str sender = {0, 0}; + str dialoginfo_body = {0 , 0}; + int expires = 0; + str event = str_init("dialog"); + int reset = 0; + char to_tag_buffer[100]; + char from_tag_buffer[100]; + + 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_extract_field(BLF_JSON_PRES, pres); + json_extract_field(BLF_JSON_PRES_USER, pres_user); + json_extract_field(BLF_JSON_PRES_REALM, pres_realm); + json_extract_field(BLF_JSON_FROM, from); + json_extract_field(BLF_JSON_FROM_USER, from_user); + json_extract_field(BLF_JSON_FROM_REALM, from_realm); + json_extract_field(BLF_JSON_FROM_URI, from_uri); + json_extract_field(BLF_JSON_TO, to); + json_extract_field(BLF_JSON_TO_USER, to_user); + json_extract_field(BLF_JSON_TO_REALM, to_realm); + json_extract_field(BLF_JSON_TO_URI, to_uri); + json_extract_field(BLF_JSON_CALLID, callid); + json_extract_field(BLF_JSON_FROMTAG, fromtag); + json_extract_field(BLF_JSON_TOTAG, totag); + json_extract_field(BLF_JSON_DIRECTION, direction); + json_extract_field(BLF_JSON_STATE, state); + + struct json_object *ExpiresObj = json_get_object(json_obj, BLF_JSON_EXPIRES); + if (ExpiresObj != NULL) { + expires = json_object_get_int(ExpiresObj); + if (expires > 0) + expires += (int)time(NULL); + } + + ExpiresObj = json_get_object(json_obj, "Flush-Level"); + if (ExpiresObj != NULL) { + reset = 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 = sprintf(from_tag_buffer, LOCAL_TAG, fromtag.len, fromtag.s); + fromtag.s = from_tag_buffer; + } + + if (totag.len > 0) { + totag.len = sprintf(to_tag_buffer, REMOTE_TAG, totag.len, totag.s); + totag.s = to_tag_buffer; + } + + if (callid.len) { + + if (dbn_include_entity) { + sprintf(body, 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 { + + sprintf(body, 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 { + sprintf(body, DIALOGINFO_EMPTY_BODY, pres.len, pres.s); + } + + + sprintf(sender_buf, "sip:%s", callid.s); + sender.s = sender_buf; + sender.len = strlen(sender_buf); + + dialoginfo_body.s = body; + dialoginfo_body.len = strlen(body); + + if (dbn_pua_mode == 1) { + json_pua_update_presentity(&event, &pres_realm, &pres_user, &callid, &sender, &dialoginfo_body, expires, reset); + } + + error: + + if (body) + pkg_free(body); + + + return ret; +} + + +int json_pua_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; + + if (dbn_pua_mode != 1) { + LM_ERR("pua_mode must be 1 to publish\n"); + ret = -1; + goto error; + } + + /* extract info from json and construct xml */ + json_obj = json_parse(json); + if (json_obj == NULL) { + ret = -1; + goto error; + } + + json_extract_field(BLF_JSON_EVENT_NAME, event_name); + + if (event_name.len == 6 && strncmp(event_name.s, "update", 6) == 0) { + json_extract_field(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 = json_pua_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 = json_pua_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 = json_pua_publish_presence_to_presentity(json_obj); + } + } + +error: + if (json_obj) + json_object_put(json_obj); + + return ret; +} diff --git a/src/modules/json_pua/json_pua_publish.h b/src/modules/json_pua/json_pua_publish.h new file mode 100644 index 00000000000..05993c42cc7 --- /dev/null +++ b/src/modules/json_pua/json_pua_publish.h @@ -0,0 +1,32 @@ +/* + * JSON_PUA 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): + * Emmanuel Schmidbauer + * + */ + +#ifndef __JSON_PUA_PUBLISH_H_ +#define __JSON_PUA_PUBLISH_H_ + +int json_pua_publish(struct sip_msg* msg, char *json); + +#endif