From 7333d46d5b90bc5d94a2bf83169997f2c2322112 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Sep 2011 14:31:10 -0500 Subject: [PATCH 1/4] add new chatplan concept and mod_sms. Apps for chat messages: copy new base freeswitch.xml and chatplan dir if you are upgrading on existing config base --- conf/chatplan/default.xml | 14 + conf/freeswitch.xml | 4 + libs/esl/src/esl_event.c | 20 +- libs/esl/src/include/esl_event.h | 1 + src/include/switch_core.h | 2 +- src/include/switch_cpp.h | 2 + src/include/switch_event.h | 10 +- src/include/switch_ivr.h | 2 + src/include/switch_loadable_module.h | 51 +- src/include/switch_module_interfaces.h | 21 + src/include/switch_regex.h | 1 + src/include/switch_types.h | 14 +- .../applications/mod_sms/mod_sms.2008.vcproj | 287 ++++ .../applications/mod_sms/mod_sms.2010.vcxproj | 135 ++ src/mod/applications/mod_sms/mod_sms.c | 510 +++++++ .../endpoints/mod_dingaling/mod_dingaling.c | 2 +- src/mod/endpoints/mod_sofia/sofia_presence.c | 121 +- src/mod/endpoints/mod_sofia/sofia_reg.c | 2 +- .../src/org/freeswitch/swig/Event.java | 8 + .../org/freeswitch/swig/freeswitchJNI.java | 2 + .../languages/mod_java/switch_swig_wrap.cpp | 51 + src/mod/languages/mod_lua/mod_lua.cpp | 20 + src/mod/languages/mod_lua/mod_lua_wrap.cpp | 65 + .../languages/mod_managed/freeswitch_wrap.cxx | 463 ++++++ src/mod/languages/mod_managed/managed/swig.cs | 1316 +++++++++++------ src/mod/languages/mod_perl/freeswitch.pm | 2 + src/mod/languages/mod_perl/mod_perl_wrap.cpp | 95 ++ src/mod/languages/mod_python/freeswitch.py | 2 + .../languages/mod_python/mod_python_wrap.cpp | 86 ++ src/switch_cpp.cpp | 13 + src/switch_event.c | 107 +- src/switch_ivr.c | 13 + src/switch_loadable_module.c | 380 ++++- src/switch_regex.c | 7 + src/switch_xml.c | 1 + 35 files changed, 3263 insertions(+), 567 deletions(-) create mode 100644 conf/chatplan/default.xml create mode 100644 src/mod/applications/mod_sms/mod_sms.2008.vcproj create mode 100644 src/mod/applications/mod_sms/mod_sms.2010.vcxproj create mode 100644 src/mod/applications/mod_sms/mod_sms.c 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, "