diff --git a/conf/chatplan/default.xml b/conf/chatplan/default.xml
new file mode 100644
index 0000000000..b67bb638fa
--- /dev/null
+++ b/conf/chatplan/default.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/freeswitch.xml b/conf/freeswitch.xml
index 42eede31ee..7a1b1d3d15 100644
--- a/conf/freeswitch.xml
+++ b/conf/freeswitch.xml
@@ -46,6 +46,10 @@
+
+
diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c
index 71e7d42b2a..ead853ea46 100644
--- a/libs/esl/src/esl_event.c
+++ b/libs/esl/src/esl_event.c
@@ -270,8 +270,9 @@ ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *hea
}
return hp->value;
-
- }
+ } else if (!strcmp(header_name, "_body")) {
+ return event->body;
+ }
return NULL;
}
@@ -414,6 +415,10 @@ static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t st
int index = 0;
char *real_header_name = NULL;
+ if (!strcmp(header_name, "_body")) {
+ esl_event_set_body(event, data);
+ }
+
if ((index_ptr = strchr(header_name, '['))) {
index_ptr++;
index = atoi(index_ptr);
@@ -604,6 +609,17 @@ ESL_DECLARE(esl_status_t) esl_event_add_header_string(esl_event_t *event, esl_st
return ESL_FAIL;
}
+ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body)
+{
+ esl_safe_free(event->body);
+
+ if (body) {
+ event->body = DUP(body);
+ }
+
+ return ESL_SUCCESS;
+}
+
ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...)
{
int ret = 0;
diff --git a/libs/esl/src/include/esl_event.h b/libs/esl/src/include/esl_event.h
index d6be0470e8..1cc6134e42 100644
--- a/libs/esl/src/include/esl_event.h
+++ b/libs/esl/src/include/esl_event.h
@@ -298,6 +298,7 @@ ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char
\note the body parameter can be shadowed by the esl_event_reserve_subclass_detailed function
*/
ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...);
+ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body);
/*!
\brief Create a new event assuming it will not be custom event and therefore hiding the unused parameters
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 1591cf18cc..7f1db105f8 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -2110,7 +2110,7 @@ SWITCH_DECLARE(void) switch_cond_next(void);
SWITCH_DECLARE(switch_status_t) switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to,
const char *subject, const char *body, const char *type, const char *hint);
SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *dest_proto, switch_event_t *message_event);
-
+SWITCH_DECLARE(switch_status_t) switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event);
SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_session_t *session, const char *cmds);
diff --git a/src/include/switch_cpp.h b/src/include/switch_cpp.h
index e9f5c29d92..70e484bf51 100644
--- a/src/include/switch_cpp.h
+++ b/src/include/switch_cpp.h
@@ -156,6 +156,8 @@ SWITCH_DECLARE(bool) email(char *to, char *from, char *headers = NULL, char *bod
SWITCH_DECLARE_CONSTRUCTOR Event(const char *type, const char *subclass_name = NULL);
SWITCH_DECLARE_CONSTRUCTOR Event(switch_event_t *wrap_me, int free_me = 0);
virtual SWITCH_DECLARE_CONSTRUCTOR ~ Event();
+ SWITCH_DECLARE(int) chat_execute(const char *app, const char *data = NULL);
+ SWITCH_DECLARE(int) chat_send(const char *dest_proto = NULL);
SWITCH_DECLARE(const char *) serialize(const char *format = NULL);
SWITCH_DECLARE(bool) setPriority(switch_priority_t priority = SWITCH_PRIORITY_NORMAL);
SWITCH_DECLARE(const char *) getHeader(const char *header_name);
diff --git a/src/include/switch_event.h b/src/include/switch_event.h
index c6b1d64c35..23cd0825b5 100644
--- a/src/include/switch_event.h
+++ b/src/include/switch_event.h
@@ -103,7 +103,8 @@ struct switch_event {
};
typedef enum {
- EF_UNIQ_HEADERS = (1 << 0)
+ EF_UNIQ_HEADERS = (1 << 0),
+ EF_NO_CHAT_EXEC = (1 << 1)
} switch_event_flag_t;
@@ -157,6 +158,8 @@ _Ret_opt_z_ SWITCH_DECLARE(char *) switch_event_get_header_idx(switch_event_t *e
#define switch_event_get_header_nil(e, h) switch_str_nil(switch_event_get_header(e,h))
+SWITCH_DECLARE(switch_status_t) switch_event_rename_header(switch_event_t *event, const char *header_name, const char *new_header_name);
+
/*!
\brief Retrieve the body value from an event
\param event the event to read the body from
@@ -207,6 +210,8 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event);
*/
SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_event_t *todup);
SWITCH_DECLARE(void) switch_event_merge(switch_event_t *event, switch_event_t *tomerge);
+SWITCH_DECLARE(switch_status_t) switch_event_dup_reply(switch_event_t **event, switch_event_t *todup);
+
/*!
\brief Fire an event with full arguement list
\param file the calling file
@@ -321,6 +326,9 @@ SWITCH_DECLARE(switch_status_t) switch_event_running(void);
*/
SWITCH_DECLARE(switch_status_t) switch_event_add_body(switch_event_t *event, const char *fmt, ...) PRINTF_FUNCTION(2, 3);
#endif
+
+SWITCH_DECLARE(switch_status_t) switch_event_set_body(switch_event_t *event, const char *body);
+
SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const char *in);
SWITCH_DECLARE(switch_status_t) switch_event_create_pres_in_detailed(_In_z_ char *file, _In_z_ char *func, _In_ int line,
diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h
index 6b2a10d43f..901519f7dd 100644
--- a/src/include/switch_ivr.h
+++ b/src/include/switch_ivr.h
@@ -931,6 +931,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_sessi
SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp);
SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point);
+SWITCH_DECLARE(switch_status_t) switch_ivr_create_message_reply(switch_event_t **reply, switch_event_t *message, const char *new_proto);
+
/** @} */
SWITCH_END_EXTERN_C
diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h
index 4b81a1f25e..62fcac2343 100644
--- a/src/include/switch_loadable_module.h
+++ b/src/include/switch_loadable_module.h
@@ -55,33 +55,35 @@ SWITCH_BEGIN_EXTERN_C
struct switch_loadable_module_interface {
/*! the name of the module */
const char *module_name;
- /*! the table of endpoints the module has implmented */
+ /*! the table of endpoints the module has implemented */
switch_endpoint_interface_t *endpoint_interface;
- /*! the table of timers the module has implmented */
+ /*! the table of timers the module has implemented */
switch_timer_interface_t *timer_interface;
- /*! the table of dialplans the module has implmented */
+ /*! the table of dialplans the module has implemented */
switch_dialplan_interface_t *dialplan_interface;
- /*! the table of codecs the module has implmented */
+ /*! the table of codecs the module has implemented */
switch_codec_interface_t *codec_interface;
- /*! the table of applications the module has implmented */
+ /*! the table of applications the module has implemented */
switch_application_interface_t *application_interface;
- /*! the table of api functions the module has implmented */
+ /*! the table of chat applications the module has implemented */
+ switch_chat_application_interface_t *chat_application_interface;
+ /*! the table of api functions the module has implemented */
switch_api_interface_t *api_interface;
- /*! the table of file formats the module has implmented */
+ /*! the table of file formats the module has implemented */
switch_file_interface_t *file_interface;
- /*! the table of speech interfaces the module has implmented */
+ /*! the table of speech interfaces the module has implemented */
switch_speech_interface_t *speech_interface;
- /*! the table of directory interfaces the module has implmented */
+ /*! the table of directory interfaces the module has implemented */
switch_directory_interface_t *directory_interface;
- /*! the table of chat interfaces the module has implmented */
+ /*! the table of chat interfaces the module has implemented */
switch_chat_interface_t *chat_interface;
- /*! the table of say interfaces the module has implmented */
+ /*! the table of say interfaces the module has implemented */
switch_say_interface_t *say_interface;
- /*! the table of asr interfaces the module has implmented */
+ /*! the table of asr interfaces the module has implemented */
switch_asr_interface_t *asr_interface;
- /*! the table of management interfaces the module has implmented */
+ /*! the table of management interfaces the module has implemented */
switch_management_interface_t *management_interface;
- /*! the table of limit interfaces the module has implmented */
+ /*! the table of limit interfaces the module has implemented */
switch_limit_interface_t *limit_interface;
switch_thread_rwlock_t *rwlock;
int refs;
@@ -169,6 +171,15 @@ SWITCH_DECLARE(switch_timer_interface_t *) switch_loadable_module_get_timer_inte
*/
SWITCH_DECLARE(switch_application_interface_t *) switch_loadable_module_get_application_interface(const char *name);
+/*!
+ \brief Retrieve the chat application interface by it's registered name
+ \param name the name of the chat application
+ \return the desired chat application interface
+ */
+SWITCH_DECLARE(switch_chat_application_interface_t *) switch_loadable_module_get_chat_application_interface(const char *name);
+
+SWITCH_DECLARE(switch_status_t) switch_core_execute_chat_app(switch_event_t *message, const char *app, const char *data);
+
/*!
\brief Retrieve the API interface by it's registered name
\param name the name of the API
@@ -335,6 +346,18 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void);
break; \
}
+#define SWITCH_ADD_CHAT_APP(app_int, int_name, short_descript, long_descript, funcptr, syntax_string, app_flags) \
+ for (;;) { \
+ app_int = (switch_chat_application_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_CHAT_APPLICATION_INTERFACE); \
+ app_int->interface_name = int_name; \
+ app_int->chat_application_function = funcptr; \
+ app_int->short_desc = short_descript; \
+ app_int->long_desc = long_descript; \
+ app_int->syntax = syntax_string; \
+ app_int->flags = app_flags; \
+ break; \
+ }
+
#define SWITCH_ADD_DIALPLAN(dp_int, int_name, funcptr) \
for (;;) { \
dp_int = (switch_dialplan_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_DIALPLAN_INTERFACE); \
diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h
index 7c666ab9f4..acb85407c7 100644
--- a/src/include/switch_module_interfaces.h
+++ b/src/include/switch_module_interfaces.h
@@ -681,6 +681,27 @@ struct switch_application_interface {
struct switch_application_interface *next;
};
+/*! \brief A module interface to implement a chat application */
+struct switch_chat_application_interface {
+ /*! the name of the interface */
+ const char *interface_name;
+ /*! function the application implements */
+ switch_chat_application_function_t chat_application_function;
+ /*! the long winded description of the application */
+ const char *long_desc;
+ /*! the short and sweet description of the application */
+ const char *short_desc;
+ /*! an example of the application syntax */
+ const char *syntax;
+ /*! flags to control behaviour */
+ uint32_t flags;
+ switch_thread_rwlock_t *rwlock;
+ int refs;
+ switch_mutex_t *reflock;
+ switch_loadable_module_interface_t *parent;
+ struct switch_chat_application_interface *next;
+};
+
/*! \brief A module interface to implement an api function */
struct switch_api_interface {
/*! the name of the interface */
diff --git a/src/include/switch_regex.h b/src/include/switch_regex.h
index 27f4852966..6558299b53 100644
--- a/src/include/switch_regex.h
+++ b/src/include/switch_regex.h
@@ -74,6 +74,7 @@ SWITCH_DECLARE(void) switch_capture_regex(switch_regex_t *re, int match_count, c
int *ovector, const char *var, switch_cap_callback_t callback, void *user_data);
SWITCH_DECLARE_NONSTD(void) switch_regex_set_var_callback(const char *var, const char *val, void *user_data);
+SWITCH_DECLARE_NONSTD(void) switch_regex_set_event_header_callback(const char *var, const char *val, void *user_data);
#define switch_regex_safe_free(re) if (re) {\
switch_regex_free(re);\
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index c7e8a5f472..e0419718c1 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -325,7 +325,8 @@ typedef enum {
SWITCH_SAY_INTERFACE,
SWITCH_ASR_INTERFACE,
SWITCH_MANAGEMENT_INTERFACE,
- SWITCH_LIMIT_INTERFACE
+ SWITCH_LIMIT_INTERFACE,
+ SWITCH_CHAT_APPLICATION_INTERFACE
} switch_module_interface_name_t;
typedef enum {
@@ -495,6 +496,7 @@ typedef enum {
SWITCH_XML_SECTION_DIRECTORY = (1 << 1),
SWITCH_XML_SECTION_DIALPLAN = (1 << 2),
SWITCH_XML_SECTION_PHRASES = (1 << 3),
+ SWITCH_XML_SECTION_CHATPLAN = (1 << 4),
/* Nothing after this line */
SWITCH_XML_SECTION_MAX = (1 << 4)
@@ -1221,6 +1223,12 @@ typedef enum {
} switch_application_flag_enum_t;
typedef uint32_t switch_application_flag_t;
+typedef enum {
+ SCAF_NONE = 0
+} switch_chat_application_flag_enum_t;
+typedef uint32_t switch_chat_application_flag_t;
+
+
/*!
\enum switch_signal_t
\brief Signals to send to channels
@@ -1729,6 +1737,7 @@ typedef struct switch_timer_interface switch_timer_interface_t;
typedef struct switch_dialplan_interface switch_dialplan_interface_t;
typedef struct switch_codec_interface switch_codec_interface_t;
typedef struct switch_application_interface switch_application_interface_t;
+typedef struct switch_chat_application_interface switch_chat_application_interface_t;
typedef struct switch_api_interface switch_api_interface_t;
typedef struct switch_file_interface switch_file_interface_t;
typedef struct switch_speech_interface switch_speech_interface_t;
@@ -1780,7 +1789,8 @@ typedef switch_status_t (*switch_core_codec_fmtp_parse_func_t) (const char *fmtp
typedef switch_status_t (*switch_core_codec_destroy_func_t) (switch_codec_t *);
-
+typedef switch_status_t (*switch_chat_application_function_t) (switch_event_t *, const char *);
+#define SWITCH_STANDARD_CHAT_APP(name) static switch_status_t name (switch_event_t *message, const char *data)
typedef void (*switch_application_function_t) (switch_core_session_t *, const char *);
#define SWITCH_STANDARD_APP(name) static void name (switch_core_session_t *session, const char *data)
diff --git a/src/mod/applications/mod_sms/mod_sms.2008.vcproj b/src/mod/applications/mod_sms/mod_sms.2008.vcproj
new file mode 100644
index 0000000000..6d9109b4bb
--- /dev/null
+++ b/src/mod/applications/mod_sms/mod_sms.2008.vcproj
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mod/applications/mod_sms/mod_sms.2010.vcxproj b/src/mod/applications/mod_sms/mod_sms.2010.vcxproj
new file mode 100644
index 0000000000..4dbbf47874
--- /dev/null
+++ b/src/mod/applications/mod_sms/mod_sms.2010.vcxproj
@@ -0,0 +1,135 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ mod_sms
+ {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}
+ mod_sms
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ X64
+
+
+
+
+
+
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ X64
+
+
+
+
+
+
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+ {202d7a4e-760d-4d0e-afa1-d7459ced30ff}
+ false
+
+
+
+
+
+
diff --git a/src/mod/applications/mod_sms/mod_sms.c b/src/mod/applications/mod_sms/mod_sms.c
new file mode 100644
index 0000000000..096ee6be36
--- /dev/null
+++ b/src/mod/applications/mod_sms/mod_sms.c
@@ -0,0 +1,510 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II
+ *
+ * mod_sms.c -- Abstract SMS
+ *
+ */
+#include
+#define SMS_CHAT_PROTO "GLOBAL_SMS"
+#define MY_EVENT_SEND_MESSAGE "SMS::SEND_MESSAGE"
+
+/* Prototypes */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sms_shutdown);
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_sms_runtime);
+SWITCH_MODULE_LOAD_FUNCTION(mod_sms_load);
+SWITCH_MODULE_DEFINITION(mod_sms, mod_sms_load, mod_sms_shutdown, NULL);
+
+
+static void event_handler(switch_event_t *event)
+{
+ const char *dest_proto = switch_event_get_header(event, "dest_proto");
+ switch_core_chat_send(dest_proto, event);
+}
+
+typedef enum {
+ BREAK_ON_TRUE,
+ BREAK_ON_FALSE,
+ BREAK_ALWAYS,
+ BREAK_NEVER
+} break_t;
+
+
+
+static int parse_exten(switch_event_t *event, switch_xml_t xexten, switch_event_t **extension)
+{
+ switch_xml_t xcond, xaction, xexpression;
+ char *exten_name = (char *) switch_xml_attr(xexten, "name");
+ int proceed = 0;
+ char *expression_expanded = NULL, *field_expanded = NULL;
+ switch_regex_t *re = NULL;
+ const char *to = switch_event_get_header(event, "to");
+
+ if (!to) {
+ to = "nobody";
+ }
+
+ if (!exten_name) {
+ exten_name = "_anon_";
+ }
+
+ for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
+ char *field = NULL;
+ char *do_break_a = NULL;
+ char *expression = NULL;
+ const char *field_data = NULL;
+ int ovector[30];
+ switch_bool_t anti_action = SWITCH_TRUE;
+ break_t do_break_i = BREAK_ON_FALSE;
+
+ int time_match = switch_xml_std_datetime_check(xcond);
+
+ switch_safe_free(field_expanded);
+ switch_safe_free(expression_expanded);
+
+ if (switch_xml_child(xcond, "condition")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n");
+ proceed = 1;
+ goto done;
+ }
+
+ field = (char *) switch_xml_attr(xcond, "field");
+
+ if ((xexpression = switch_xml_child(xcond, "expression"))) {
+ expression = switch_str_nil(xexpression->txt);
+ } else {
+ expression = (char *) switch_xml_attr_soft(xcond, "expression");
+ }
+
+ if ((expression_expanded = switch_event_expand_headers(event, expression)) == expression) {
+ expression_expanded = NULL;
+ } else {
+ expression = expression_expanded;
+ }
+
+ if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) {
+ if (!strcasecmp(do_break_a, "on-true")) {
+ do_break_i = BREAK_ON_TRUE;
+ } else if (!strcasecmp(do_break_a, "on-false")) {
+ do_break_i = BREAK_ON_FALSE;
+ } else if (!strcasecmp(do_break_a, "always")) {
+ do_break_i = BREAK_ALWAYS;
+ } else if (!strcasecmp(do_break_a, "never")) {
+ do_break_i = BREAK_NEVER;
+ } else {
+ do_break_a = NULL;
+ }
+ }
+
+ if (time_match == 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s Date/Time Match (PASS) [%s] break=%s\n",
+ to, exten_name, do_break_a ? do_break_a : "on-false");
+ anti_action = SWITCH_FALSE;
+ } else if (time_match == 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s Date/Time Match (FAIL) [%s] break=%s\n",
+ to, exten_name, do_break_a ? do_break_a : "on-false");
+ }
+
+ if (field) {
+ if (strchr(field, '$')) {
+ if ((field_expanded = switch_event_expand_headers(event, field)) == field) {
+ field_expanded = NULL;
+ field_data = field;
+ } else {
+ field_data = field_expanded;
+ }
+ } else {
+ field_data = switch_event_get_header(event, field);
+ }
+ if (!field_data) {
+ field_data = "";
+ }
+
+ if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n",
+ to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
+ anti_action = SWITCH_FALSE;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n",
+ to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
+ }
+ } else if (time_match == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s Absolute Condition [%s]\n", to, exten_name);
+ anti_action = SWITCH_FALSE;
+ }
+
+ if (anti_action) {
+ for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
+ const char *application = switch_xml_attr_soft(xaction, "application");
+ const char *loop = switch_xml_attr(xaction, "loop");
+ const char *data;
+ const char *inline_ = switch_xml_attr_soft(xaction, "inline");
+ int xinline = switch_true(inline_);
+ int loop_count = 1;
+
+ if (!zstr(xaction->txt)) {
+ data = xaction->txt;
+ } else {
+ data = (char *) switch_xml_attr_soft(xaction, "data");
+ }
+
+ if (!*extension) {
+ if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
+ abort();
+ }
+ }
+
+ if (loop) {
+ loop_count = atoi(loop);
+ }
+
+ for (;loop_count > 0; loop_count--) {
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s ANTI-Action %s(%s) %s\n", to, application, data, xinline ? "INLINE" : "");
+
+ if (xinline) {
+ switch_core_execute_chat_app(event, application, data);
+ } else {
+ switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, data);
+ }
+ }
+ proceed = 1;
+ }
+ } else {
+ if (field && strchr(expression, '(')) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "DP_MATCH", NULL);
+ switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_event_header_callback, event);
+ }
+
+ for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
+ char *application = (char *) switch_xml_attr_soft(xaction, "application");
+ const char *loop = switch_xml_attr(xaction, "loop");
+ char *data = NULL;
+ char *substituted = NULL;
+ uint32_t len = 0;
+ char *app_data = NULL;
+ const char *inline_ = switch_xml_attr_soft(xaction, "inline");
+ int xinline = switch_true(inline_);
+ int loop_count = 1;
+
+ if (!zstr(xaction->txt)) {
+ data = xaction->txt;
+ } else {
+ data = (char *) switch_xml_attr_soft(xaction, "data");
+ }
+
+ if (field && strchr(expression, '(')) {
+ len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed;
+ if (!(substituted = malloc(len))) {
+ abort();
+ }
+ memset(substituted, 0, len);
+ switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector);
+ app_data = substituted;
+ } else {
+ app_data = data;
+ }
+
+ if (!*extension) {
+ if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
+ abort();
+ }
+ }
+
+ if (loop) {
+ loop_count = atoi(loop);
+ }
+ for (;loop_count > 0; loop_count--) {
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s Action %s(%s) %s\n", to, application, app_data, xinline ? "INLINE" : "");
+
+ if (xinline) {
+ switch_core_execute_chat_app(event, application, app_data);
+ } else {
+ switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, data);
+ }
+ }
+ switch_safe_free(substituted);
+ }
+ }
+ switch_regex_safe_free(re);
+
+ if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) ||
+ (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) {
+ break;
+ }
+ }
+
+ done:
+ switch_regex_safe_free(re);
+ switch_safe_free(field_expanded);
+ switch_safe_free(expression_expanded);
+ return proceed;
+}
+
+
+static switch_event_t *chatplan_hunt(switch_event_t *event)
+{
+ switch_event_t *extension = NULL;
+ switch_xml_t alt_root = NULL, cfg, xml = NULL, xcontext, xexten = NULL;
+ const char *alt_path;
+ const char *context;
+ const char *from;
+ const char *to;
+
+ if (!(context = switch_event_get_header(event, "context"))) {
+ context = "default";
+ }
+
+ if (!(from = switch_event_get_header(event, "from_user"))) {
+ from = switch_event_get_header(event, "from");
+ }
+
+ if (!(to = switch_event_get_header(event, "to_user"))) {
+ to = switch_event_get_header(event, "to");
+ }
+
+ alt_path = switch_event_get_header(event, "alt_path");
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Processing text message %s->%s in context %s\n", from, to, context);
+
+ /* get our handle to the "chatplan" section of the config */
+
+ if (!zstr(alt_path)) {
+ switch_xml_t conf = NULL, tag = NULL;
+ if (!(alt_root = switch_xml_parse_file_simple(alt_path))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of [%s] failed\n", alt_path);
+ goto done;
+ }
+
+ if ((conf = switch_xml_find_child(alt_root, "section", "name", "chatplan")) && (tag = switch_xml_find_child(conf, "chatplan", NULL, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Getting chatplan from alternate path: %s\n", alt_path);
+ xml = alt_root;
+ cfg = tag;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n");
+ goto done;
+ }
+ } else {
+ if (switch_xml_locate("chatplan", NULL, NULL, NULL, &xml, &cfg, event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n");
+ goto done;
+ }
+ }
+
+ /* get a handle to the context tag */
+ if (!(xcontext = switch_xml_find_child(cfg, "context", "name", context))) {
+ if (!(xcontext = switch_xml_find_child(cfg, "context", "name", "global"))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Context %s not found\n", context);
+ goto done;
+ }
+ }
+
+ xexten = switch_xml_child(xcontext, "extension");
+
+ while (xexten) {
+ int proceed = 0;
+ const char *cont = switch_xml_attr(xexten, "continue");
+ const char *exten_name = switch_xml_attr(xexten, "name");
+
+ if (!exten_name) {
+ exten_name = "UNKNOWN";
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
+ "Chatplan: %s parsing [%s->%s] continue=%s\n",
+ to, context, exten_name, cont ? cont : "false");
+
+ proceed = parse_exten(event, xexten, &extension);
+
+ if (proceed && !switch_true(cont)) {
+ break;
+ }
+
+ xexten = xexten->next;
+ }
+
+ switch_xml_free(xml);
+ xml = NULL;
+
+ done:
+ switch_xml_free(xml);
+ return extension;
+}
+
+
+static switch_status_t chat_send(switch_event_t *message_event)
+ {
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_event_t *exten;
+
+ if ((exten = chatplan_hunt(message_event))) {
+ switch_event_header_t *hp;
+
+ for (hp = exten->headers; hp; hp = hp->next) {
+ status = switch_core_execute_chat_app(message_event, hp->name, hp->value);
+ if (!SWITCH_READ_ACCEPTABLE(status)) {
+ break;
+ }
+ }
+
+ switch_event_destroy(&exten);
+ }
+
+
+ status = SWITCH_STATUS_BREAK;
+
+
+ return status;
+
+}
+
+SWITCH_STANDARD_CHAT_APP(stop_function)
+{
+ switch_set_flag(message, EF_NO_CHAT_EXEC);
+ return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_STANDARD_CHAT_APP(send_function)
+{
+ const char *dest_proto = data;
+
+ if (zstr(dest_proto)) {
+ dest_proto = switch_event_get_header(message, "dest_proto");
+ }
+
+ switch_core_chat_send(dest_proto, message);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_CHAT_APP(set_function)
+{
+ char *var, *val;
+
+ if (data) {
+ var = strdup(data);
+ if ((val = strchr(var, '='))) {
+ *val++ = '\0';
+ }
+
+ if (zstr(val)) {
+ switch_event_del_header(message, var);
+ } else {
+ switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, var, val);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_CHAT_APP(fire_function)
+{
+ switch_event_t *fireme;
+
+ switch_event_dup(&fireme, message);
+ switch_event_fire(&fireme);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_CHAT_APP(reply_function)
+{
+ switch_event_t *reply;
+ const char *proto = switch_event_get_header(message, "proto");
+
+ if (proto) {
+ switch_ivr_create_message_reply(&reply, message, SMS_CHAT_PROTO);
+
+ if (!zstr(data)) {
+ switch_event_add_body(reply, data);
+ }
+
+ switch_core_chat_deliver(proto, &reply);
+
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* Macro expands to: switch_status_t mod_sms_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
+SWITCH_MODULE_LOAD_FUNCTION(mod_sms_load)
+{
+ switch_chat_interface_t *chat_interface;
+ switch_chat_application_interface_t *chat_app_interface;
+
+
+ if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MY_EVENT_SEND_MESSAGE, event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
+ return SWITCH_STATUS_GENERR;
+ }
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+ SWITCH_ADD_CHAT(chat_interface, SMS_CHAT_PROTO, chat_send);
+
+ SWITCH_ADD_CHAT_APP(chat_app_interface, "reply", "reply to a message", "reply to a message", reply_function, "", SCAF_NONE);
+ SWITCH_ADD_CHAT_APP(chat_app_interface, "stop", "stop execution", "stop execution", stop_function, "", SCAF_NONE);
+ SWITCH_ADD_CHAT_APP(chat_app_interface, "set", "set a variable", "set a variable", set_function, "", SCAF_NONE);
+ SWITCH_ADD_CHAT_APP(chat_app_interface, "send", "send the message as-is", "send the message as-is", send_function, "", SCAF_NONE);
+ SWITCH_ADD_CHAT_APP(chat_app_interface, "fire", "fire the message", "fire the message", fire_function, "", SCAF_NONE);
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/*
+ Called when the system shuts down
+ Macro expands to: switch_status_t mod_sms_shutdown() */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sms_shutdown)
+{
+ switch_event_unbind_callback(event_handler);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
index 527a2a0fa2..1a7dd221ef 100644
--- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c
+++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
@@ -2929,7 +2929,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", subject);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "normal");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", hint);
if (msg) {
diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index db7aa94a3a..06b1ce496e 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -99,7 +99,10 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
//const char *subject;
const char *body;
const char *type;
- const char *hint;
+ const char *from_full;
+ char header[256] = "";
+ char *route_uri = NULL;
+ const char *network_ip = NULL, *network_port = NULL;
proto = switch_event_get_header(message_event, "proto");
from = switch_event_get_header(message_event, "from");
@@ -107,8 +110,10 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
//subject = switch_event_get_header(message_event, "subject");
body = switch_event_get_body(message_event);
type = switch_event_get_header(message_event, "type");
- hint = switch_event_get_header(message_event, "hint");
-
+ from_full = switch_event_get_header(message_event, "from_full");
+
+ network_ip = switch_event_get_header(message_event, "to_sip_ip");
+ network_port = switch_event_get_header(message_event, "to_sip_port");
if (!to) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n");
@@ -130,6 +135,10 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
user = prof;
prof = NULL;
}
+
+ if (!prof) {
+ prof = switch_event_get_header(message_event, "sip_profile");
+ }
if (!strncasecmp(user, "sip:", 4)) {
to_uri = user;
@@ -141,8 +150,9 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
} else {
host++;
}
- if (!prof)
+ if (!prof) {
prof = host;
+ }
}
if (!prof || !(profile = sofia_glue_find_profile(prof))) {
@@ -159,24 +169,34 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
}
}
+
if (to_uri) {
switch_console_push_match(&list, to_uri);
} else if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find registered user %s@%s\n", user, host);
- goto end;
+ sofia_profile_t *test;
+
+ if ((test = sofia_glue_find_profile(host))) {
+ sofia_glue_release_profile(test);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Not sending to local box for %s@%s\n", user, host);
+ /* our box let's not send it */
+ } else {
+ char *tmp;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't find registered user %s@%s\n", user, host);
+ tmp = switch_mprintf("sip:%s@%s", user, host);
+ switch_console_push_match(&list, tmp);
+ free(tmp);
+ }
+
}
if (!strcasecmp(proto, SOFIA_CHAT_PROTO)) {
- from = hint;
+ from = from_full;
} else {
char *fp, *p = NULL;
fp = strdup(from);
+ switch_assert(fp);
- if (!fp) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
- goto end;
- }
if ((p = strchr(fp, '@'))) {
*p++ = '\0';
@@ -189,12 +209,23 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
}
}
- ffrom = switch_mprintf("\"%s\" ", fp, proto, fp, p);
+ if (switch_stristr("global", proto)) {
+ ffrom = switch_mprintf("\"%s\" ", fp, fp, p);
+ } else {
+ ffrom = switch_mprintf("\"%s\" ", fp, proto, fp, p);
+ }
from = ffrom;
switch_safe_free(fp);
}
+ if (!list) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Chat proto [%s]\nfrom [%s]\nto [%s]\n%s\nNobody to send to: Profile %s\n", proto, from, to,
+ body ? body : "[no body]", prof ? prof : "NULL");
+ goto end;
+ }
+
for (m = list->head; m; m = m->next) {
if (!(dst = sofia_glue_get_destination(m->val))) {
@@ -250,21 +281,34 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
/* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */
+ //printf("DEBUG To: [%s] From: [%s] Contact: [%s] RURI [%s] ip [%s] port [%s]\n", to, from, contact, dst->route_uri, network_ip, network_port);
+
+ //DUMP_EVENT(message_event);
+
+ if (zstr(dst->route_uri) && !zstr(user) && !zstr(network_ip) && (zstr(host) || strcmp(network_ip, host))) {
+ route_uri = switch_mprintf("sip:%s@%s:%s", user, network_ip, network_port);
+ }
+
msg_nh = nua_handle(profile->nua, NULL,
- TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)),
- TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
- SIPTAG_FROM_STR(from),
- TAG_IF(contact, NUTAG_URL(contact)),
- SIPTAG_TO_STR(dup_dest),
- SIPTAG_CONTACT_STR(contact_str),
TAG_END());
nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
+ switch_snprintf(header, sizeof(header), "X-FS-Sending-Message: %s", switch_core_get_uuid());
+
nua_message(msg_nh,
+ TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)),
+ TAG_IF(route_uri, NUTAG_PROXY(route_uri)),
+ TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
+ SIPTAG_FROM_STR(from),
+ TAG_IF(contact, NUTAG_URL(contact)),
+ SIPTAG_TO_STR(dup_dest),
+ SIPTAG_CONTACT_STR(contact_str),
+
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_CONTENT_TYPE_STR(ct),
SIPTAG_PAYLOAD_STR(body),
+ SIPTAG_HEADER_STR(header),
TAG_END());
sofia_glue_free_destination(dst);
@@ -277,6 +321,7 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
end:
switch_safe_free(contact);
+ switch_safe_free(route_uri);
switch_safe_free(ffrom);
switch_safe_free(dup);
@@ -2873,13 +2918,25 @@ void sofia_presence_handle_sip_i_message(int status,
const char *to_host = NULL;
sip_payload_t *payload = sip->sip_payload;
char *msg = NULL;
+ const char *us;
+ char network_ip[80];
+ int network_port = 0;
+
+ if ((us = sofia_glue_get_unknown_header(sip, "X-FS-Sending-Message")) && !strcmp(us, switch_core_get_uuid())) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Not sending message to ourselves!\n");
+ goto end;
+ }
if (sip->sip_content_type && sip->sip_content_type->c_subtype) {
if (strstr(sip->sip_content_type->c_subtype, "composing")) {
- return;
+ goto end;
}
}
+
+ sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
+
+
if (from) {
from_user = from->a_url->url_user;
from_host = from->a_url->url_host;
@@ -2891,7 +2948,7 @@ void sofia_presence_handle_sip_i_message(int status,
}
if (!to_user) {
- return;
+ goto end;
}
if (payload) {
@@ -2924,7 +2981,7 @@ void sofia_presence_handle_sip_i_message(int status,
to_addr = switch_mprintf("%s@%s", to_user, to_host);
}
- from_addr = switch_mprintf("%s/%s@%s", profile->name, from_user, from_host);
+ from_addr = switch_mprintf("%s@%s", from_user, from_host);
if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)) {
sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip);
@@ -2936,10 +2993,22 @@ void sofia_presence_handle_sip_i_message(int status,
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", from_addr);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", from_user);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", from_host);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_user", to_user);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_host", to_host);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_sip_ip", network_ip);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from_sip_port", "%d", network_port);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to_addr);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "normal");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", full_from);
+
+
+ if (sip->sip_content_type && sip->sip_content_type->c_subtype) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", sip->sip_content_type->c_type);
+ } else {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain");
+ }
+
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", full_from);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
if (msg) {
switch_event_add_body(event, "%s", msg);
@@ -2952,7 +3021,6 @@ void sofia_presence_handle_sip_i_message(int status,
switch_core_session_queue_event(tech_pvt->session, &event);
} else {
switch_core_chat_send(proto, event);
- switch_core_chat_send("GLOBAL", event);
switch_event_destroy(&event);
}
@@ -2964,6 +3032,11 @@ void sofia_presence_handle_sip_i_message(int status,
}
}
}
+
+ end:
+
+ nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
+
}
void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip)
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index c591e9393d..ad7438e487 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -1397,7 +1397,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
/* Log line added to support Fail2Ban */
if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' "
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "SIP auth challenge (%s) on sofia profile '%s' "
"for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER",
profile->name, to_user, to_host, network_ip);
}
diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java
index c1c9ba17e7..d1adc09dc6 100644
--- a/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java
+++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java
@@ -66,6 +66,14 @@ public class Event {
this(freeswitchJNI.new_Event__SWIG_1(SWIGTYPE_p_switch_event_t.getCPtr(wrap_me), free_me), true);
}
+ public int chat_execute(String app, String data) {
+ return freeswitchJNI.Event_chat_execute(swigCPtr, this, app, data);
+ }
+
+ public int chat_send(String dest_proto) {
+ return freeswitchJNI.Event_chat_send(swigCPtr, this, dest_proto);
+ }
+
public String serialize(String format) {
return freeswitchJNI.Event_serialize(swigCPtr, this, format);
}
diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java
index 069b7eecf2..fc74914d15 100644
--- a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java
+++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java
@@ -54,6 +54,8 @@ class freeswitchJNI {
public final static native long new_Event__SWIG_0(String jarg1, String jarg2);
public final static native long new_Event__SWIG_1(long jarg1, int jarg2);
public final static native void delete_Event(long jarg1);
+ public final static native int Event_chat_execute(long jarg1, Event jarg1_, String jarg2, String jarg3);
+ public final static native int Event_chat_send(long jarg1, Event jarg1_, String jarg2);
public final static native String Event_serialize(long jarg1, Event jarg1_, String jarg2);
public final static native boolean Event_setPriority(long jarg1, Event jarg1_, long jarg2);
public final static native String Event_getHeader(long jarg1, Event jarg1_, String jarg2);
diff --git a/src/mod/languages/mod_java/switch_swig_wrap.cpp b/src/mod/languages/mod_java/switch_swig_wrap.cpp
index 4b3c9d38d1..5061dc46f6 100644
--- a/src/mod/languages/mod_java/switch_swig_wrap.cpp
+++ b/src/mod/languages/mod_java/switch_swig_wrap.cpp
@@ -1054,6 +1054,57 @@ SWIGEXPORT void JNICALL Java_org_freeswitch_swig_freeswitchJNI_delete_1Event(JNI
}
+SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_Event_1chat_1execute(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) {
+ jint jresult = 0 ;
+ Event *arg1 = (Event *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) NULL ;
+ int result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Event **)&jarg1;
+ arg2 = 0;
+ if (jarg2) {
+ arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2) return 0;
+ }
+ arg3 = 0;
+ if (jarg3) {
+ arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3) return 0;
+ }
+ result = (int)(arg1)->chat_execute((char const *)arg2,(char const *)arg3);
+ jresult = (jint)result;
+ if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
+ if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
+ return jresult;
+}
+
+
+SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_Event_1chat_1send(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ jint jresult = 0 ;
+ Event *arg1 = (Event *) 0 ;
+ char *arg2 = (char *) NULL ;
+ int result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Event **)&jarg1;
+ arg2 = 0;
+ if (jarg2) {
+ arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2) return 0;
+ }
+ result = (int)(arg1)->chat_send((char const *)arg2);
+ jresult = (jint)result;
+ if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
+ return jresult;
+}
+
+
SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_Event_1serialize(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
jstring jresult = 0 ;
Event *arg1 = (Event *) 0 ;
diff --git a/src/mod/languages/mod_lua/mod_lua.cpp b/src/mod/languages/mod_lua/mod_lua.cpp
index dc01aa9fa9..a165795cb0 100644
--- a/src/mod/languages/mod_lua/mod_lua.cpp
+++ b/src/mod/languages/mod_lua/mod_lua.cpp
@@ -430,6 +430,24 @@ SWITCH_STANDARD_API(luarun_api_function)
return SWITCH_STATUS_SUCCESS;
}
+SWITCH_STANDARD_CHAT_APP(lua_chat_function)
+{
+ lua_State *L = lua_init();
+ char *dup = NULL;
+
+ if (data) {
+ dup = strdup(data);
+ }
+
+ mod_lua_conjure_event(L, message, "message", 1);
+ lua_parse_and_execute(L, (char *)dup);
+ lua_uninit(L);
+
+ switch_safe_free(dup);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
SWITCH_STANDARD_API(lua_api_function)
{
@@ -591,6 +609,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load)
switch_api_interface_t *api_interface;
switch_application_interface_t *app_interface;
switch_dialplan_interface_t *dp_interface;
+ switch_chat_application_interface_t *chat_app_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
@@ -600,6 +619,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load)
SWITCH_ADD_APP(app_interface, "lua", "Launch LUA ivr", "Run a lua ivr on a channel", lua_function, "