Merge branch 'master' into smgmaster

Conflicts:
	build/modules.conf.in
	libs/esl/fs_cli.c
This commit is contained in:
Moises Silva
2011-12-17 17:25:36 -05:00
305 changed files with 15668 additions and 6219 deletions
-2
View File
@@ -253,8 +253,6 @@ struct switch_runtime {
int multiple_registrations;
uint32_t max_db_handles;
uint32_t db_handle_timeout;
int curl_count;
int ssl_count;
int cpu_count;
};
+1
View File
@@ -109,6 +109,7 @@
#include "switch_platform.h"
#include "switch_types.h"
#include "switch_apr.h"
#include "switch_curl.h"
#include "switch_mprintf.h"
#include "switch_core_db.h"
#include "switch_dso.h"
+3
View File
@@ -120,6 +120,9 @@ typedef struct profile_node_s {
struct switch_caller_profile *next;
switch_call_direction_t direction;
profile_node_t *soft;
char *uuid_str;
char *clone_of;
char *transfer_source;
};
/*! \brief An Abstract Representation of a dialplan Application */
+5 -2
View File
@@ -88,8 +88,8 @@ SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_
#define switch_channel_up(_channel) (switch_channel_check_signal(_channel, SWITCH_TRUE) || switch_channel_get_state(_channel) < CS_HANGUP)
#define switch_channel_down(_channel) (switch_channel_check_signal(_channel, SWITCH_TRUE) || switch_channel_get_state(_channel) >= CS_HANGUP)
#define switch_channel_up_nosig(_channel) switch_channel_get_state(_channel) < CS_HANGUP
#define switch_channel_down_nosig(_channel) switch_channel_get_state(_channel) >= CS_HANGUP
#define switch_channel_up_nosig(_channel) (switch_channel_get_state(_channel) < CS_HANGUP)
#define switch_channel_down_nosig(_channel) (switch_channel_get_state(_channel) >= CS_HANGUP)
#define switch_channel_media_ack(_channel) (!switch_channel_test_cap(_channel, CC_MEDIA_ACK) || switch_channel_test_flag(_channel, CF_MEDIA_ACK))
@@ -271,6 +271,8 @@ SWITCH_DECLARE(const char *) switch_channel_get_variable_partner(switch_channel_
SWITCH_DECLARE(const char *) switch_channel_get_hold_music(switch_channel_t *channel);
SWITCH_DECLARE(const char *) switch_channel_get_hold_music_partner(switch_channel_t *channel);
SWITCH_DECLARE(uint32_t) switch_channel_del_variable_prefix(switch_channel_t *channel, const char *prefix);
#define switch_channel_set_variable(_channel, _var, _val) switch_channel_set_variable_var_check(_channel, _var, _val, SWITCH_TRUE)
#define switch_channel_set_variable_partner(_channel, _var, _val) switch_channel_set_variable_partner_var_check(_channel, _var, _val, SWITCH_TRUE)
@@ -387,6 +389,7 @@ SWITCH_DECLARE(uint32_t) switch_channel_test_flag_partner(switch_channel_t *chan
\param flag flag to set
*/
SWITCH_DECLARE(void) switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flag);
SWITCH_DECLARE(void) switch_channel_clear_state_flag(switch_channel_t *channel, switch_channel_flag_t flag);
/*!
\brief Clear given flag(s) from a channel
+16 -6
View File
@@ -25,7 +25,7 @@
*
* Anthony Minessale II <anthm@freeswitch.org>
* Luke Dashjr <luke@openmethods.com> (OpenMethods, LLC)
*
* Joseph Sullivan <jossulli@amazon.com>
*
* switch_core.h -- Core Library
*
@@ -436,9 +436,6 @@ SWITCH_DECLARE(void) switch_core_session_rwunlock(_In_ switch_core_session_t *se
*/
SWITCH_DECLARE(int) switch_core_add_state_handler(_In_ const switch_state_handler_table_t *state_handler);
SWITCH_DECLARE(int) switch_core_curl_count(int *val);
SWITCH_DECLARE(int) switch_core_ssl_count(int *val);
/*!
\brief Remove a global state handler
\param state_handler the state handler to remove
@@ -467,6 +464,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(_Out_ switch
*/
#define switch_core_new_memory_pool(p) switch_core_perform_new_memory_pool(p, __FILE__, __SWITCH_FUNC__, __LINE__)
SWITCH_DECLARE(int) switch_core_session_sync_clock(void);
SWITCH_DECLARE(switch_status_t) switch_core_perform_destroy_memory_pool(_Inout_ switch_memory_pool_t **pool,
_In_z_ const char *file, _In_z_ const char *func, _In_ int line);
/*!
@@ -1307,11 +1305,11 @@ SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(_In_ switch_hash_t *hash, _I
/*!
\brief Gets the first element of a hashtable
\param depricate_me [deprecated] NULL
\param deprecate_me [deprecated] NULL
\param hash the hashtable to use
\return The element, or NULL if it wasn't found
*/
SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *depricate_me, _In_ switch_hash_t *hash);
SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *deprecate_me, _In_ switch_hash_t *hash);
/*!
\brief Gets the next element of a hashtable
@@ -1957,6 +1955,18 @@ SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel);
*/
SWITCH_DECLARE(switch_bool_t) switch_core_ready(void);
/*!
\brief Determines if the core is ready to take inbound calls
\return SWITCH_TRUE or SWITCH_FALSE
*/
SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void);
/*!
\brief Determines if the core is ready to place outbound calls
\return SWITCH_TRUE or SWITCH_FALSE
*/
SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void);
/*!
\brief return core flags
\return core flags
+5 -1
View File
@@ -65,6 +65,10 @@ Note that the first parameter to the new operator is implicitly handled by c++..
*/
SWITCH_DECLARE(void) setGlobalVariable(char *var_name, char *var_val);
SWITCH_DECLARE(char *) getGlobalVariable(char *var_name);
SWITCH_DECLARE(void) consoleLog(char *level_str, char *msg);
SWITCH_DECLARE(void) consoleCleanLog(char *msg);
@@ -185,7 +189,7 @@ SWITCH_DECLARE(bool) email(char *to, char *from, char *headers = NULL, char *bod
SWITCH_DECLARE_CONSTRUCTOR EventConsumer(const char *event_name = NULL, const char *subclass_name = "");
SWITCH_DECLARE_CONSTRUCTOR ~ EventConsumer();
SWITCH_DECLARE(int) bind(const char *event_name, const char *subclass_name = "");
SWITCH_DECLARE(Event *) pop(int block = 0);
SWITCH_DECLARE(Event *) pop(int block = 0, int timeout = 0);
};
#ifdef SWIG
+17 -24
View File
@@ -30,34 +30,27 @@
#ifndef __SWITCH_CURL_H
#define __SWITCH_CURL_H
#include "curl/curl.h"
#include <curl/curl.h>
#include <switch_ssl.h>
static inline void switch_curl_init(void)
{
int curl_count = switch_core_curl_count(NULL);
typedef void switch_CURL;
typedef struct curl_slist switch_curl_slist_t;
typedef int switch_CURLINFO;
typedef int switch_CURLcode;
typedef int switch_CURLoption;
if (curl_count == 0) {
curl_global_init(CURL_GLOBAL_ALL);
}
curl_count++;
switch_core_curl_count(&curl_count);
}
static inline void switch_curl_destroy()
{
int curl_count = switch_core_curl_count(NULL);
curl_count--;
if (curl_count == 0) {
curl_global_cleanup();
}
switch_core_curl_count(&curl_count);
}
SWITCH_DECLARE(switch_CURL *) switch_curl_easy_init(void);
SWITCH_DECLARE(switch_CURLcode) switch_curl_easy_perform(switch_CURL *handle);
SWITCH_DECLARE(switch_CURLcode) switch_curl_easy_getinfo(switch_CURL *curl, switch_CURLINFO info, ... );
SWITCH_DECLARE(void) switch_curl_easy_cleanup(switch_CURL *handle);
SWITCH_DECLARE(switch_curl_slist_t *) switch_curl_slist_append(switch_curl_slist_t * list, const char * string );
SWITCH_DECLARE(void) switch_curl_slist_free_all(switch_curl_slist_t * list);
SWITCH_DECLARE(switch_CURLcode) switch_curl_easy_setopt(CURL *handle, switch_CURLoption option, ...);
SWITCH_DECLARE(const char *) switch_curl_easy_strerror(switch_CURLcode errornum );
SWITCH_DECLARE(void) switch_curl_init(void);
SWITCH_DECLARE(void) switch_curl_destroy(void);
#endif
+18
View File
@@ -155,6 +155,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess
const char *terminators, char *terminator,
uint32_t first_timeout, uint32_t digit_timeout, uint32_t abs_timeout);
/*!
\brief play a file to the session while doing speech recognition.
\param session the session to play and detect on
\param file the path to the file
\param mod_name the module name of the ASR library
\param grammar the grammar text, URI, or local file name
\param result of speech recognition, allocated from the session pool
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_play_and_detect_speech(switch_core_session_t *session,
const char *file,
const char *mod_name,
const char *grammar,
char **result);
/*!
\brief Engage background Speech detection on a session
\param session the session to attach
@@ -896,6 +911,7 @@ SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid);
SWITCH_DECLARE(const char *) switch_ivr_dmachine_get_name(switch_ivr_dmachine_t *dmachine);
SWITCH_DECLARE(void) switch_ivr_dmachine_set_match_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t match_callback);
SWITCH_DECLARE(void) switch_ivr_dmachine_set_nonmatch_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t nonmatch_callback);
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p,
@@ -932,6 +948,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *ses
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_DECLARE(char *) switch_ivr_check_presence_mapping(const char *exten_name, const char *domain_name);
SWITCH_DECLARE(switch_status_t) switch_ivr_kill_uuid(const char *uuid, switch_call_cause_t cause);
/** @} */
+17
View File
@@ -38,7 +38,20 @@
#include <switch.h>
#define MAX_REPORT_BLOCKS 5
SWITCH_BEGIN_EXTERN_C
struct switch_rtcp_report_block_frame {
uint32_t ssrc; /* The SSRC identifier of the source to which the information in this reception report block pertains. */
uint8_t fraction; /* The fraction of RTP data packets from source SSRC_n lost since the previous SR or RR packet was sent */
uint32_t lost; /* The total number of RTP data packets from source SSRC_n that have been lost since the beginning of reception */
uint32_t highest_sequence_number_received;
uint32_t jitter; /* An estimate of the statistical variance of the RTP data packet interarrival time, measured in timestamp units and expressed as an unsigned integer. */
uint32_t lsr; /* The middle 32 bits out of 64 in the NTP timestamp */
uint32_t dlsr; /* The delay, expressed in units of 1/65536 seconds, between receiving the last SR packet from source SSRC_n and sending this reception report block */
};
/*! \brief An abstraction of a rtcp frame */
struct switch_rtcp_frame {
@@ -58,6 +71,10 @@ SWITCH_BEGIN_EXTERN_C
uint32_t octect_count;
uint32_t nb_reports;
struct switch_rtcp_report_block_frame reports[MAX_REPORT_BLOCKS];
};
SWITCH_END_EXTERN_C
+3 -10
View File
@@ -36,7 +36,7 @@
static switch_mutex_t **ssl_mutexes;
static switch_memory_pool_t *ssl_pool = NULL;
static int ssl_count = 0;
static inline void switch_ssl_ssl_lock_callback(int mode, int type, char *file, int line)
{
@@ -56,7 +56,6 @@ static inline unsigned long switch_ssl_ssl_thread_id(void)
static inline void switch_ssl_init_ssl_locks(void)
{
int ssl_count = switch_core_ssl_count(NULL);
int i, num;
if (ssl_count == 0) {
@@ -77,17 +76,13 @@ static inline void switch_ssl_init_ssl_locks(void)
}
ssl_count++;
switch_core_ssl_count(&ssl_count);
}
static inline void switch_ssl_destroy_ssl_locks()
{
int i;
int ssl_count = switch_core_ssl_count(NULL);
ssl_count--;
if (ssl_count == 0) {
if (ssl_count == 1) {
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < CRYPTO_num_locks(); i++) {
if (ssl_mutexes[i]) {
@@ -96,10 +91,8 @@ static inline void switch_ssl_destroy_ssl_locks()
}
OPENSSL_free(ssl_mutexes);
ssl_count--;
}
switch_core_ssl_count(&ssl_count);
}
#else
static inline void switch_ssl_init_ssl_locks(void) { return; }
+63 -22
View File
@@ -25,6 +25,7 @@
*
* Anthony Minessale II <anthm@freeswitch.org>
* Bret McDanel <trixter AT 0xdecafbad dot com>
* Joseph Sullivan <jossulli@amazon.com>
*
* switch_types.h -- Data Types
*
@@ -131,6 +132,8 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_COPY_XML_CDR_VARIABLE "copy_xml_cdr"
#define SWITCH_CURRENT_APPLICATION_VARIABLE "current_application"
#define SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE "proto_specific_hangup_cause"
#define SWITCH_TRANSFER_HISTORY_VARIABLE "transfer_history"
#define SWITCH_TRANSFER_SOURCE_VARIABLE "transfer_source"
#define SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE "execute_on_answer"
#define SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE "execute_on_pre_answer"
@@ -291,23 +294,27 @@ typedef uint32_t switch_eavesdrop_flag_t;
typedef enum {
SCF_NONE = 0,
SCF_USE_SQL = (1 << 0),
SCF_NO_NEW_SESSIONS = (1 << 1),
SCF_SHUTTING_DOWN = (1 << 2),
SCF_VG = (1 << 3),
SCF_RESTART = (1 << 4),
SCF_SHUTDOWN_REQUESTED = (1 << 5),
SCF_USE_AUTO_NAT = (1 << 6),
SCF_EARLY_HANGUP = (1 << 7),
SCF_CALIBRATE_CLOCK = (1 << 8),
SCF_USE_HEAVY_TIMING = (1 << 9),
SCF_USE_CLOCK_RT = (1 << 10),
SCF_VERBOSE_EVENTS = (1 << 11),
SCF_USE_WIN32_MONOTONIC = (1 << 12),
SCF_AUTO_SCHEMAS = (1 << 13),
SCF_MINIMAL = (1 << 14),
SCF_USE_NAT_MAPPING = (1 << 15),
SCF_CLEAR_SQL = (1 << 16),
SCF_THREADED_SYSTEM_EXEC = (1 << 17)
SCF_NO_NEW_OUTBOUND_SESSIONS = (1 << 1),
SCF_NO_NEW_INBOUND_SESSIONS = (1 << 2),
SCF_NO_NEW_SESSIONS = (SCF_NO_NEW_OUTBOUND_SESSIONS | SCF_NO_NEW_INBOUND_SESSIONS),
SCF_SHUTTING_DOWN = (1 << 3),
SCF_VG = (1 << 4),
SCF_RESTART = (1 << 5),
SCF_SHUTDOWN_REQUESTED = (1 << 6),
SCF_USE_AUTO_NAT = (1 << 7),
SCF_EARLY_HANGUP = (1 << 8),
SCF_CALIBRATE_CLOCK = (1 << 9),
SCF_USE_HEAVY_TIMING = (1 << 10),
SCF_USE_CLOCK_RT = (1 << 11),
SCF_VERBOSE_EVENTS = (1 << 12),
SCF_USE_WIN32_MONOTONIC = (1 << 13),
SCF_AUTO_SCHEMAS = (1 << 14),
SCF_MINIMAL = (1 << 15),
SCF_USE_NAT_MAPPING = (1 << 16),
SCF_CLEAR_SQL = (1 << 17),
SCF_THREADED_SYSTEM_EXEC = (1 << 18),
SCF_SYNC_CLOCK_REQUESTED = (1 << 19),
SCF_CORE_ODBC_REQ = (1 << 20)
} switch_core_flag_enum_t;
typedef uint32_t switch_core_flag_t;
@@ -347,7 +354,8 @@ typedef enum {
SSM_NA,
SSM_PRONOUNCED,
SSM_ITERATED,
SSM_COUNTED
SSM_COUNTED,
SSM_PRONOUNCED_YEAR
} switch_say_method_t;
/* WARNING, Do not forget to update *SAY_TYPE_NAMES[] in src/switch_ivr_say.c */
@@ -685,7 +693,7 @@ typedef enum {
*/
RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7)
RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7),
/*
Oracle's Contact Center Anywhere (CCA) likes to use a single RTP socket to send all its outbound audio.
@@ -694,6 +702,21 @@ typedef enum {
*/
RTP_BUG_GEN_ONE_GEN_ALL = (1 << 8)
/*
Some RTP endpoints (and by some we mean *cough* _SONUS_!) do not like it when the timestamps jump forward or backwards in time.
So say you are generating a file that says "please wait for me to complete your call, or generating ringback"
Now you place and outbound call and you are bridging. Well, while you were playing the file, you were generating your own RTP timestamps.
But, now that you have a remote RTP stream, you'd rather send those timestamps as-is in case they will be fed to a remote jitter buffer......
Ok, so this causes the audio to completely fade out despite the fact that we send the mark bit which should give them heads up its happening.
Sigh, This flag will tell FreeSWITCH that if it ever generates even one RTP packet itself, to continue to generate all of them and ignore the
actual timestamps in the frames.
*/
} switch_rtp_bug_flag_t;
#ifdef _MSC_VER
@@ -852,6 +875,8 @@ typedef enum {
SWITCH_MESSAGE_INDICATE_JITTER_BUFFER,
SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH,
SWITCH_MESSAGE_INDICATE_SIGNAL_DATA,
SWITCH_MESSAGE_INDICATE_INFO,
SWITCH_MESSAGE_INDICATE_AUDIO_DATA,
SWITCH_MESSAGE_INVALID
} switch_core_session_message_types_t;
@@ -1163,6 +1188,7 @@ typedef enum {
CF_BRIDGE_NOWRITE,
CF_RECOVERED,
CF_JITTERBUFFER,
CF_JITTERBUFFER_PLC,
CF_DIALPLAN,
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
CF_CNG_PLC,
@@ -1171,6 +1197,8 @@ typedef enum {
CF_SIGNAL_DATA,
CF_SIMPLIFY,
CF_ZOMBIE_EXEC,
CF_INTERCEPT,
CF_INTERCEPTED,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
CF_FLAG_MAX
@@ -1374,6 +1402,9 @@ SMBF_READ_REPLACE - Replace the Read Stream
SMBF_STEREO - Record in stereo
SMBF_ANSWER_RECORD_REQ - Don't record until the channel is answered
SMBF_THREAD_LOCK - Only let the same thread who created the bug remove it.
SMBF_PRUNE -
SMBF_NO_PAUSE -
SMBF_STEREO_SWAP - Record in stereo: Write Stream - left channel, Read Stream - right channel
</pre>
*/
typedef enum {
@@ -1387,7 +1418,8 @@ typedef enum {
SMBF_ANSWER_REQ = (1 << 6),
SMBF_THREAD_LOCK = (1 << 7),
SMBF_PRUNE = (1 << 8),
SMBF_NO_PAUSE = (1 << 9)
SMBF_NO_PAUSE = (1 << 9),
SMBF_STEREO_SWAP = (1 << 10)
} switch_media_bug_flag_enum_t;
typedef uint32_t switch_media_bug_flag_t;
@@ -1659,11 +1691,17 @@ typedef enum {
SWITCH_CAUSE_MEDIA_TIMEOUT = 604,
SWITCH_CAUSE_PICKED_OFF = 605,
SWITCH_CAUSE_USER_NOT_REGISTERED = 606,
SWITCH_CAUSE_PROGRESS_TIMEOUT = 607
SWITCH_CAUSE_PROGRESS_TIMEOUT = 607,
SWITCH_CAUSE_INVALID_GATEWAY = 608,
SWITCH_CAUSE_GATEWAY_DOWN = 609,
SWITCH_CAUSE_INVALID_URL = 610,
SWITCH_CAUSE_INVALID_PROFILE = 611
} switch_call_cause_t;
typedef enum {
SCSC_PAUSE_INBOUND,
SCSC_PAUSE_OUTBOUND,
SCSC_PAUSE_ALL,
SCSC_HUPALL,
SCSC_SHUTDOWN,
SCSC_CHECK_RUNNING,
@@ -1689,9 +1727,12 @@ typedef enum {
SCSC_MIN_IDLE_CPU,
SCSC_VERBOSE_EVENTS,
SCSC_SHUTDOWN_CHECK,
SCSC_PAUSE_INBOUND_CHECK,
SCSC_PAUSE_OUTBOUND_CHECK,
SCSC_PAUSE_CHECK,
SCSC_READY_CHECK,
SCSC_THREADED_SYSTEM_EXEC
SCSC_THREADED_SYSTEM_EXEC,
SCSC_SYNC_CLOCK_WHEN_IDLE
} switch_session_ctl_t;
typedef enum {
+4
View File
@@ -240,6 +240,7 @@ SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switc
SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone);
SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool);
/*!
\brief Evaluate the truthfullness of a string expression
@@ -830,6 +831,9 @@ SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domai
SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size);
#endif
SWITCH_DECLARE(char *) switch_uuid_str(char *buf, switch_size_t len);
SWITCH_DECLARE(char *) switch_format_number(const char *num);
SWITCH_END_EXTERN_C
#endif
/* For Emacs:
+1 -1
View File
@@ -421,7 +421,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_unbind_search_function_ptr(_In_ switc
///\return the section mask
SWITCH_DECLARE(switch_xml_section_t) switch_xml_parse_section_string(_In_opt_z_ const char *str);
SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond);
SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond, int *offset);
SWITCH_DECLARE(switch_status_t) switch_xml_locate_language(switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_xml_t *language, switch_xml_t *phrases, switch_xml_t *macros, const char *str_language);
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mod_blacklist</ProjectName>
<ProjectGuid>{50AAC2CE-BFC9-4912-87CC-C6381850D735}</ProjectGuid>
<RootNamespace>mod_blacklist</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_blacklist.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -166,6 +166,7 @@ static switch_status_t do_config(switch_bool_t reload)
"blacklist check <listname> <item>\n" \
"blacklist add <listname> <item>\n" \
"blacklist del <listname> <item>\n" \
"blacklist save <listname>\n" \
"blacklist reload\n" \
"blacklist help\n"
@@ -249,7 +250,7 @@ SWITCH_STANDARD_API(blacklist_api_function)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Removed [%s] from list [%s]\n", argv[2], argv[1]);
switch_mutex_unlock(bl->list_mutex);
stream->write_function(stream, "+OK\n");
} else if (!strcasecmp(argv[0], "dump")) {
} else if (!strcasecmp(argv[0], "save")) {
switch_hash_index_t *hi;
void *val;
const void *var;
@@ -276,15 +277,19 @@ SWITCH_STANDARD_API(blacklist_api_function)
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Dumping %s to %s\n", argv[1], filename);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Saving %s to %s\n", argv[1], filename);
switch_mutex_lock(globals.lists_mutex);
if (switch_file_open(&fd, filename, SWITCH_FOPEN_WRITE, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, globals.pool) == SWITCH_STATUS_SUCCESS) {
if (switch_file_open(&fd, filename, SWITCH_FOPEN_WRITE | SWITCH_FOPEN_TRUNCATE | SWITCH_FOPEN_CREATE, SWITCH_FPROT_OS_DEFAULT, globals.pool)
== SWITCH_STATUS_SUCCESS) {
for (hi = switch_hash_first(NULL, bl->list); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
switch_file_printf(fd, "%s\n", (char *)var);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "adding %s to the dump file\n", (char *)var);
}
stream->write_function(stream, "+OK\n");
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "couldn't open %s for writing\n", filename);
}
switch_mutex_unlock(globals.lists_mutex);
} else if (!strcasecmp(argv[0], "reload")) {
@@ -1433,6 +1433,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_side", "%s", "agent");
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout", "false");
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout_on_execute", "false");
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
t_agent_called = local_epoch_time_now(NULL);
@@ -1496,8 +1498,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
if ((other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid))) {
switch_channel_t *other_loopback_channel = switch_core_session_get_channel(other_loopback_session);
const char *real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE);
const char *real_uuid = NULL;
/* Wait for the real channel to be fully bridged */
switch_channel_wait_for_flag(other_loopback_channel, CF_BRIDGED, SWITCH_TRUE, 5000, member_channel);
real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE);
switch_channel_set_variable(other_loopback_channel, "cc_member_pre_answer_uuid", NULL);
/* Switch the agent session */
@@ -1507,9 +1513,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
agent_uuid = switch_core_session_get_uuid(agent_session);
agent_channel = switch_core_session_get_channel(agent_session);
/* Wait for the real channel to be fully bridged */
switch_channel_wait_for_flag(agent_channel, CF_BRIDGED, SWITCH_TRUE, 5000, member_channel);
if (!switch_channel_test_flag(agent_channel, CF_BRIDGED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Timeout waiting for real channel to be bridged (agent '%s')\n", h->agent_name);
} else {
@@ -2281,9 +2284,20 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
}
/* Will drop the caller if no agent was found for more than X seconds */
if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - queue->max_wait_time_with_no_agent_time_reached &&
queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait with no agent time\n", m->member_cid_name, m->member_cid_number, m->queue_name);
if (queue->max_wait_time_with_no_agent > 0 &&
(queue->last_agent_exist >= m->t_member_called || queue->max_wait_time_with_no_agent_time_reached == 0) &&
queue->last_agent_exist_check - queue->last_agent_exist > queue->max_wait_time_with_no_agent) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait of %d sec. with no agent\n", m->member_cid_name, m->member_cid_number, m->queue_name, queue->max_wait_time_with_no_agent);
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT;
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
/* Will drop the NEW caller if no agent was found for more than X seconds once they join */
if (queue->max_wait_time_with_no_agent_time_reached > 0 &&
queue->last_agent_exist < m->t_member_called &&
queue->last_agent_exist_check - queue->last_agent_exist > queue->max_wait_time_with_no_agent &&
queue->last_agent_exist_check - m->t_member_called >= queue->max_wait_time_with_no_agent_time_reached) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait of %d sec. with no agent plus join grace period of %d sec.\n", m->member_cid_name, m->member_cid_number, m->queue_name, queue->max_wait_time_with_no_agent, queue->max_wait_time_with_no_agent_time_reached);
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT;
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
@@ -1,4 +1,3 @@
WANT_CURL=yes
BASE=../../../..
include $(BASE)/build/modmake.rules
@@ -30,7 +30,7 @@
*/
#include <switch.h>
#include <curl/curl.h>
#include <switch_curl.h>
#define SWITCH_REWIND_STREAM(s) s.end = s.data
@@ -360,7 +360,7 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
}
static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, char **response, const char *query, struct curl_httppost *post,
struct curl_slist *headers, int timeout)
switch_curl_slist_t *headers, int timeout)
{
switch_time_t start_time = switch_micro_time_now();
switch_time_t time_diff = 0;
@@ -375,49 +375,49 @@ static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, cha
SWITCH_STANDARD_STREAM(http_data.stream);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "url: %s\n", query);
curl_handle = curl_easy_init();
curl_handle = switch_curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0);
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
if (!strncasecmp(query, "https", 5)) {
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
if (post) {
curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, post);
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, post);
} else {
curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);
}
if (headers) {
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
}
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
/*
TIMEOUT_MS is introduced in 7.16.2, we have 7.16.0 in tree
*/
#ifdef CURLOPT_TIMEOUT_MS
if (timeout > 0) {
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout);
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout);
} else {
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, globals.curl_timeout);
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, globals.curl_timeout);
}
#else
if (timeout > 0) {
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, timeout);
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, timeout);
} else {
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.curl_timeout / 1000);
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.curl_timeout / 1000);
}
#endif
curl_easy_setopt(curl_handle, CURLOPT_URL, query);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &http_data);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-cidlookup/1.0");
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, query);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &http_data);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-cidlookup/1.0");
curl_easy_perform(curl_handle);
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
curl_easy_cleanup(curl_handle);
switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_curl_easy_cleanup(curl_handle);
if (http_data.stream.data && !zstr((char *) http_data.stream.data) && strcmp(" ", http_data.stream.data)) {
@@ -852,7 +852,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cidlookup_load)
Macro expands to: switch_status_t mod_cidlookup_shutdown() */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cidlookup_shutdown)
{
switch_event_unbind(&reload_xml_event);
return SWITCH_STATUS_SUCCESS;
}
+116 -22
View File
@@ -32,6 +32,7 @@
* Cesar Cepeda <cesar@auronix.com>
* Massimo Cetra <devel@navynet.it>
* Rupa Schomaker <rupa@rupa.com>
* Joseph Sullivan <jossulli@amazon.com>
*
*
* mod_commands.c -- Misc. Command Module
@@ -45,6 +46,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_commands_shutdown);
SWITCH_MODULE_DEFINITION(mod_commands, mod_commands_load, mod_commands_shutdown, NULL);
static switch_mutex_t *reload_mutex = NULL;
struct cb_helper {
uint32_t row_process;
@@ -1791,7 +1793,7 @@ SWITCH_STANDARD_API(status_function)
return SWITCH_STATUS_SUCCESS;
}
#define CTL_SYNTAX "[send_sighup|hupall|pause|resume|shutdown [cancel|elegant|asap|now|restart]|sps|sync_clock|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]"
#define CTL_SYNTAX "[send_sighup|hupall|pause [inbound|outbound]|resume [inbound|outbound]|shutdown [cancel|elegant|asap|now|restart]|sps|sync_clock|sync_clock_when_idle|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]"
SWITCH_STANDARD_API(ctl_function)
{
int argc;
@@ -1814,16 +1816,32 @@ SWITCH_STANDARD_API(ctl_function)
switch_core_session_ctl(SCSC_FLUSH_DB_HANDLES, NULL);
stream->write_function(stream, "+OK\n");
} else if (!strcasecmp(argv[0], "pause")) {
switch_session_ctl_t command = SCSC_PAUSE_ALL;
arg = 1;
switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg);
if (argv[1]) {
if (!strcasecmp(argv[1], "inbound")) {
command = SCSC_PAUSE_INBOUND;
} else if (!strcasecmp(argv[1], "outbound")) {
command = SCSC_PAUSE_OUTBOUND;
}
}
switch_core_session_ctl(command, &arg);
stream->write_function(stream, "+OK\n");
} else if (!strcasecmp(argv[0], "send_sighup")) {
arg = 1;
switch_core_session_ctl(SCSC_SEND_SIGHUP, &arg);
stream->write_function(stream, "+OK\n");
} else if (!strcasecmp(argv[0], "resume")) {
switch_session_ctl_t command = SCSC_PAUSE_ALL;
arg = 0;
switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg);
if (argv[1]) {
if (!strcasecmp(argv[1], "inbound")) {
command = SCSC_PAUSE_INBOUND;
} else if (!strcasecmp(argv[1], "outbound")) {
command = SCSC_PAUSE_OUTBOUND;
}
}
switch_core_session_ctl(command, &arg);
stream->write_function(stream, "+OK\n");
} else if (!strcasecmp(argv[0], "calibrate_clock")) {
switch_core_session_ctl(SCSC_CALIBRATE_CLOCK, NULL);
@@ -1854,7 +1872,15 @@ SWITCH_STANDARD_API(ctl_function)
switch_core_session_ctl(SCSC_SAVE_HISTORY, NULL);
stream->write_function(stream, "+OK\n");
} else if (!strcasecmp(argv[0], "pause_check")) {
switch_core_session_ctl(SCSC_PAUSE_CHECK, &arg);
switch_session_ctl_t command = SCSC_PAUSE_CHECK;
if (argv[1]) {
if (!strcasecmp(argv[1], "inbound")) {
command = SCSC_PAUSE_INBOUND_CHECK;
} else if (!strcasecmp(argv[1], "outbound")) {
command = SCSC_PAUSE_OUTBOUND_CHECK;
}
}
switch_core_session_ctl(command, &arg);
stream->write_function(stream, arg ? "true" : "false");
} else if (!strcasecmp(argv[0], "ready_check")) {
switch_core_session_ctl(SCSC_READY_CHECK, &arg);
@@ -1972,6 +1998,14 @@ SWITCH_STANDARD_API(ctl_function)
arg = 0;
switch_core_session_ctl(SCSC_SYNC_CLOCK, &arg);
stream->write_function(stream, "+OK clock synchronized\n");
} else if (!strcasecmp(argv[0], "sync_clock_when_idle")) {
arg = 0;
switch_core_session_ctl(SCSC_SYNC_CLOCK_WHEN_IDLE, &arg);
if (arg) {
stream->write_function(stream, "+OK clock synchronized\n");
} else {
stream->write_function(stream, "+OK clock will synchronize when there are no more calls\n");
}
} else {
stream->write_function(stream, "-ERR INVALID COMMAND\nUSAGE: fsctl %s", CTL_SYNTAX);
goto end;
@@ -1996,6 +2030,8 @@ SWITCH_STANDARD_API(load_function)
return SWITCH_STATUS_SUCCESS;
}
switch_mutex_lock(reload_mutex);
if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Reloading XML\n");
}
@@ -2006,6 +2042,8 @@ SWITCH_STANDARD_API(load_function)
stream->write_function(stream, "-ERR [%s]\n", err);
}
switch_mutex_unlock(reload_mutex);
return SWITCH_STATUS_SUCCESS;
}
@@ -2045,12 +2083,16 @@ SWITCH_STANDARD_API(unload_function)
return SWITCH_STATUS_SUCCESS;
}
switch_mutex_lock(reload_mutex);
if (switch_loadable_module_unload_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, force, &err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "-ERR [%s]\n", err);
}
switch_mutex_unlock(reload_mutex);
return SWITCH_STATUS_SUCCESS;
}
@@ -2088,6 +2130,8 @@ SWITCH_STANDARD_API(reload_function)
return SWITCH_STATUS_SUCCESS;
}
switch_mutex_lock(reload_mutex);
if (switch_loadable_module_unload_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, force, &err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK module unloaded\n");
} else {
@@ -2104,6 +2148,8 @@ SWITCH_STANDARD_API(reload_function)
stream->write_function(stream, "-ERR loading module [%s]\n", err);
}
switch_mutex_unlock(reload_mutex);
return SWITCH_STATUS_SUCCESS;
}
@@ -2120,7 +2166,6 @@ SWITCH_STANDARD_API(reload_xml_function)
#define KILL_SYNTAX "<uuid> [cause]"
SWITCH_STANDARD_API(kill_function)
{
switch_core_session_t *ksession = NULL;
char *mycmd = NULL, *kcause = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
@@ -2131,17 +2176,14 @@ SWITCH_STANDARD_API(kill_function)
if ((kcause = strchr(mycmd, ' '))) {
*kcause++ = '\0';
}
if (zstr(mycmd) || !(ksession = switch_core_session_locate(mycmd))) {
stream->write_function(stream, "-ERR No Such Channel!\n");
} else {
switch_channel_t *channel = switch_core_session_get_channel(ksession);
if (!zstr(kcause)) {
cause = switch_channel_str2cause(kcause);
}
switch_channel_hangup(channel, cause);
switch_core_session_rwunlock(ksession);
}
}
if (switch_ivr_kill_uuid(mycmd, cause) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "-ERR No Such Channel!\n");
} else {
stream->write_function(stream, "+OK\n");
}
@@ -2435,12 +2477,11 @@ SWITCH_STANDARD_API(tone_detect_session_function)
SWITCH_STANDARD_API(uuid_function)
{
switch_uuid_t uuid;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_uuid_get(&uuid);
switch_uuid_format(uuid_str, &uuid);
stream->write_function(stream, "%s", uuid_str);
switch_uuid_str(uuid_str, sizeof(uuid_str));
stream->write_function(stream, "%s", uuid_str);
return SWITCH_STATUS_SUCCESS;
}
@@ -3006,6 +3047,44 @@ SWITCH_STANDARD_API(uuid_phone_event_function)
return SWITCH_STATUS_SUCCESS;
}
#define INFO_SYNTAX "<uuid>"
SWITCH_STANDARD_API(uuid_send_info_function)
{
switch_status_t status = SWITCH_STATUS_FALSE;
char *mycmd = NULL, *argv[2] = { 0 };
int argc = 0;
if (!zstr(cmd) && (mycmd = strdup(cmd))) {
argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 1) {
stream->write_function(stream, "-USAGE: %s\n", INFO_SYNTAX);
} else {
switch_core_session_message_t msg = { 0 };
switch_core_session_t *lsession = NULL;
msg.message_id = SWITCH_MESSAGE_INDICATE_INFO;
msg.string_array_arg[2] = argv[1];
msg.from = __FILE__;
if ((lsession = switch_core_session_locate(argv[0]))) {
status = switch_core_session_receive_message(lsession, &msg);
switch_core_session_rwunlock(lsession);
}
}
if (status == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Success\n");
} else {
stream->write_function(stream, "-ERR Operation Failed\n");
}
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
#define DEBUG_AUDIO_SYNTAX "<uuid> <read|write|both> <on|off>"
SWITCH_STANDARD_API(uuid_debug_audio_function)
@@ -3412,11 +3491,16 @@ SWITCH_STANDARD_API(originate_function)
uint8_t machine = 1;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (session || zstr(cmd)) {
if (zstr(cmd)) {
stream->write_function(stream, "-USAGE %s\n", ORIGINATE_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
/* log warning if part of ongoing session, as we'll block the session */
if (session){
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Originate can take 60 seconds to complete, and blocks the existing session. Do not confuse with a lockup.\n");
}
mycmd = strdup(cmd);
switch_assert(mycmd);
argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
@@ -4078,11 +4162,11 @@ SWITCH_STANDARD_API(show_function)
holder.print_title = 0;
if ((cmdname = strchr(command, ' ')) && strcasecmp(cmdname, "as")) {
*cmdname++ = '\0';
switch_snprintf(sql, sizeof(sql) - 1,
"select name, syntax, description, ikey from interfaces where hostname='%s' and type = 'api' and name = '%s' order by name",
switch_snprintfv(sql, sizeof(sql),
"select name, syntax, description, ikey from interfaces where hostname='%s' and type = 'api' and name = '%q' order by name",
hostname, cmdname);
} else {
switch_snprintf(sql, sizeof(sql) - 1, "select name, syntax, description, ikey from interfaces where hostname='%s' and type = 'api' order by name", hostname);
switch_snprintfv(sql, sizeof(sql), "select name, syntax, description, ikey from interfaces where hostname='%q' and type = 'api' order by name", hostname);
}
} else if (!strcasecmp(command, "nat_map")) {
switch_snprintf(sql, sizeof(sql) - 1,
@@ -5235,6 +5319,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_thread_rwlock_create(&bgapi_rwlock, pool);
switch_mutex_init(&reload_mutex, SWITCH_MUTEX_NESTED, pool);
SWITCH_ADD_API(commands_api_interface, "acl", "compare an ip to an acl list", acl_function, "<ip> <list_name>");
SWITCH_ADD_API(commands_api_interface, "alias", "Alias", alias_function, ALIAS_SYNTAX);
@@ -5326,6 +5412,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_send_info", "Send info to the endpoint", uuid_send_info_function, INFO_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_outgoing_answer", "Answer Outgoing Channel", outgoing_answer_function, OUTGOING_ANSWER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_limit", "Increase limit resource", uuid_limit_function, LIMIT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX);
@@ -5374,13 +5461,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add fsctl max_sessions");
switch_console_set_complete("add fsctl min_dtmf_duration");
switch_console_set_complete("add fsctl pause");
switch_console_set_complete("add fsctl pause inbound");
switch_console_set_complete("add fsctl pause outbound");
switch_console_set_complete("add fsctl reclaim_mem");
switch_console_set_complete("add fsctl resume");
switch_console_set_complete("add fsctl resume inbound");
switch_console_set_complete("add fsctl resume outbound");
switch_console_set_complete("add fsctl calibrate_clock");
switch_console_set_complete("add fsctl crash");
switch_console_set_complete("add fsctl verbose_events");
switch_console_set_complete("add fsctl save_history");
switch_console_set_complete("add fsctl pause_check");
switch_console_set_complete("add fsctl pause_check inbound");
switch_console_set_complete("add fsctl pause_check outbound");
switch_console_set_complete("add fsctl ready_check");
switch_console_set_complete("add fsctl shutdown_check");
switch_console_set_complete("add fsctl shutdown");
@@ -5452,6 +5545,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid");
switch_console_set_complete("add uuid_getvar ::console::list_uuid");
switch_console_set_complete("add uuid_hold ::console::list_uuid");
switch_console_set_complete("add uuid_send_info ::console::list_uuid");
switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid");
switch_console_set_complete("add uuid_kill ::console::list_uuid");
switch_console_set_complete("add uuid_outgoing_answer ::console::list_uuid");
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1,6 +1,5 @@
json-c=json-c-0.9
BASE=../../../..
WANT_CURL=yes
JSON_DIR=$(switch_srcdir)/libs/$(json-c)
JSON_BUILDDIR=$(switch_builddir)/libs/$(json-c)
+9 -10
View File
@@ -30,7 +30,7 @@
*/
#include <switch.h>
#include <curl/curl.h>
#include <switch_curl.h>
#include <json.h>
/* Prototypes */
@@ -57,7 +57,7 @@ struct http_data_obj {
int err;
long http_response_code;
char *http_response;
struct curl_slist *headers;
switch_curl_slist_t *headers;
};
typedef struct http_data_obj http_data_t;
@@ -94,7 +94,7 @@ static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data)
switch_copy_string(header, ptr, realsize);
header[realsize] = '\0';
http_data->headers = curl_slist_append(http_data->headers, header);
http_data->headers = switch_curl_slist_append(http_data->headers, header);
return realsize;
}
@@ -102,7 +102,7 @@ static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data)
static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, const char *method, const char *data)
{
CURL *curl_handle = NULL;
switch_CURL *curl_handle = NULL;
long httpRes = 0;
http_data_t *http_data = NULL;
@@ -165,7 +165,7 @@ static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data)
struct json_object *top = NULL;
struct json_object *headers = NULL;
char *data = NULL;
struct curl_slist *header = http_data->headers;
switch_curl_slist_t *header = http_data->headers;
top = json_object_new_object();
headers = json_object_new_array();
@@ -240,7 +240,7 @@ SWITCH_STANDARD_APP(curl_app_function)
switch_bool_t do_headers = SWITCH_FALSE;
switch_bool_t do_json = SWITCH_FALSE;
http_data_t *http_data = NULL;
struct curl_slist *slist = NULL;
switch_curl_slist_t *slist = NULL;
switch_stream_handle_t stream = { 0 };
int i = 0;
@@ -308,7 +308,7 @@ SWITCH_STANDARD_APP(curl_app_function)
done:
switch_safe_free(stream.data);
if (http_data && http_data->headers) {
curl_slist_free_all(http_data->headers);
switch_curl_slist_free_all(http_data->headers);
}
if (!session && pool) {
switch_core_destroy_memory_pool(&pool);
@@ -326,7 +326,7 @@ SWITCH_STANDARD_API(curl_function)
char *postdata = NULL;
switch_bool_t do_headers = SWITCH_FALSE;
switch_bool_t do_json = SWITCH_FALSE;
struct curl_slist *slist = NULL;
switch_curl_slist_t *slist = NULL;
http_data_t *http_data = NULL;
int i = 0;
@@ -391,7 +391,7 @@ SWITCH_STANDARD_API(curl_function)
done:
if (http_data && http_data->headers) {
curl_slist_free_all(http_data->headers);
switch_curl_slist_free_all(http_data->headers);
}
switch_safe_free(mydata);
if (!session && pool) {
@@ -426,7 +426,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_curl_load)
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_curl_shutdown)
{
/* Cleanup dynamically allocated config settings */
return SWITCH_STATUS_SUCCESS;
}
+139 -25
View File
@@ -30,6 +30,7 @@
* Bret McDanel <trixter AT 0xdecafbad dot com>
* Luke Dashjr <luke@openmethods.com> (OpenMethods, LLC)
* Cesar Cepeda <cesar@auronix.com>
* Chris Rienzo <chris@rienzo.net>
*
* mod_dptools.c -- Raw Audio File Streaming Application Module
*
@@ -155,10 +156,13 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match)
switch_event_t *event;
switch_status_t status;
int exec = 0;
int api = 0;
char *string = act->string;
switch_channel_t *channel;
switch_core_session_t *use_session = act->session;
int x = 0;
char *flags = "";
if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER || act->target == DIGIT_TARGET_PEER || act->target == DIGIT_TARGET_BOTH) {
if (switch_core_session_get_partner(act->session, &use_session) != SWITCH_STATUS_SUCCESS) {
use_session = act->session;
@@ -168,8 +172,9 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match)
top:
x++;
string = act->string;
string = switch_core_session_strdup(use_session, act->string);
exec = 0;
api = 0;
channel = switch_core_session_get_channel(use_session);
@@ -180,28 +185,69 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s]\n",
switch_channel_get_name(channel), act->string, act->value);
if (!strncasecmp(string, "exec:", 5)) {
string += 5;
exec = 1;
if (!strncasecmp(string, "exec", 4)) {
char *e;
string += 4;
if (*string == ':') {
string++;
exec = 1;
} else if (*string == '[') {
flags = string;
if ((e = switch_find_end_paren(flags, '[', ']'))) {
if (e && *++e == ':') {
flags++;
*e++ = '\0';
string = e;
exec = strchr(flags, 'i') ? 2 : 1;
}
}
}
} else if (!strncasecmp(string, "api:", 4)) {
string += 4;
api = 1;
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, string, act->value);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "digits", match->match_digits);
if (exec) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 2 ? "non-blocking" : "blocking");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 1 ? "non-blocking" : "blocking");
}
if ((status = switch_core_session_queue_event(use_session, &event)) != SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&event);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue faiure.\n",
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue failure.\n",
switch_core_session_get_name(use_session));
}
}
if (exec) {
char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value);
switch_ivr_broadcast_in_thread(use_session, cmd, SMF_ECHO_ALEG | (act->target == DIGIT_TARGET_BOTH ? 0 : SMF_HOLD_BLEG));
if (exec == 2) {
switch_core_session_execute_application(use_session, string, act->value);
} else {
char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value);
switch_media_flag_enum_t exec_flags = SMF_ECHO_ALEG;
if (act->target != DIGIT_TARGET_BOTH && !strchr(flags, 'H')) {
exec_flags |= SMF_HOLD_BLEG;
}
switch_ivr_broadcast_in_thread(use_session, cmd, exec_flags);
}
} else if (api) {
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
switch_api_execute(string, act->value, NULL, &stream);
if (stream.data) {
switch_channel_set_variable(channel, "bind_digit_action_api_result", (char *)stream.data);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s] api executed, %s\n",
switch_core_session_get_name(use_session), act->string, act->value, (char *)stream.data);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s] api executed\n",
switch_core_session_get_name(use_session), act->string, act->value);
}
switch_safe_free(stream.data);
}
@@ -247,6 +293,7 @@ SWITCH_STANDARD_APP(clear_digit_action_function)
if ((dmachine = switch_core_session_get_dmachine(session, target))) {
if (zstr(realm) || !strcasecmp(realm, "all")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: Clearing all realms\n", switch_ivr_dmachine_get_name(dmachine));
switch_core_session_set_dmachine(session, NULL, target);
switch_ivr_dmachine_destroy(&dmachine);
} else {
@@ -322,7 +369,7 @@ static void bind_to_session(switch_core_session_t *session,
switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act);
}
#define BIND_DIGIT_ACTION_USAGE "<realm>,<digits|~regex>,<string>,<value>[,<dtmf target leg>][,<event target leg>]"
#define BIND_DIGIT_ACTION_USAGE "<realm>,<digits|~regex>,<string>[,<value>][,<dtmf target leg>][,<event target leg>]"
SWITCH_STANDARD_APP(bind_digit_action_function)
{
@@ -331,6 +378,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function)
char *argv[6] = { 0 };
switch_digit_action_target_t target, bind_target;
char *target_str = "self", *bind_target_str = "self";
char *value = "";
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE);
@@ -340,12 +388,16 @@ SWITCH_STANDARD_APP(bind_digit_action_function)
mydata = switch_core_session_strdup(session, data);
argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 4 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2]) || zstr(argv[3])) {
if (argc < 3 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2])) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE);
return;
}
if (argv[3]) {
value = argv[3];
}
if (argv[4]) {
target_str = argv[4];
}
@@ -360,14 +412,14 @@ SWITCH_STANDARD_APP(bind_digit_action_function)
switch(target) {
case DIGIT_TARGET_PEER:
bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_PEER, bind_target);
bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_PEER, bind_target);
break;
case DIGIT_TARGET_BOTH:
bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_PEER, bind_target);
bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_SELF, bind_target);
bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_PEER, bind_target);
bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_SELF, bind_target);
break;
default:
bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_SELF, bind_target);
bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_SELF, bind_target);
break;
}
}
@@ -409,6 +461,51 @@ SWITCH_STANDARD_APP(detect_speech_function)
}
}
#define PLAY_AND_DETECT_SPEECH_SYNTAX "<file> detect:<engine> {param1=val1,param2=val2}<grammar>"
SWITCH_STANDARD_APP(play_and_detect_speech_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
char *argv[2];
char *lbuf = NULL;
const char *response = "DONE";
char *detect = NULL;
switch_channel_set_variable(channel, "detect_speech_result", "");
if (zstr(data) || !(lbuf = switch_core_session_strdup(session, data)) || !(detect = strstr(lbuf, "detect:"))) {
/* bad input */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX);
response = "USAGE ERROR";
goto done;
}
/* split input at "detect:" */
detect[0] = '\0';
detect += 7;
if (zstr(detect)) {
/* bad input */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX);
response = "USAGE ERROR";
goto done;
}
/* need to have at 2 parameters for detect */
if (switch_separate_string(detect, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) == 2) {
char *file = lbuf;
char *engine = argv[0];
char *grammar = argv[1];
char *result = NULL;
switch_ivr_play_and_detect_speech(session, file, engine, grammar, &result);
switch_channel_set_variable(channel, "detect_speech_result", result);
} else {
/* bad input */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX);
response = "USAGE ERROR";
}
done:
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response);
}
#define SCHED_HEARTBEAT_SYNTAX "[0|<seconds>]"
SWITCH_STANDARD_APP(sched_heartbeat_function)
@@ -1080,6 +1177,19 @@ SWITCH_STANDARD_APP(redirect_function)
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(send_info_function)
{
switch_core_session_message_t msg = { 0 };
/* Tell the channel to send info */
msg.from = __FILE__;
msg.string_arg = data;
msg.message_id = SWITCH_MESSAGE_INDICATE_INFO;
msg.string_array_arg[2] = data;
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(jitterbuffer_function)
{
switch_core_session_message_t msg = { 0 };
@@ -1561,7 +1671,7 @@ SWITCH_STANDARD_API(chat_api_function)
if (!zstr(cmd) && (lbuf = strdup(cmd))
&& (argc = switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0])))) >= 4) {
if (switch_core_chat_send_args(argv[0], "dp", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "") == SWITCH_STATUS_SUCCESS) {
if (switch_core_chat_send_args(argv[0], "global", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "") == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "Sent");
} else {
stream->write_function(stream, "Error! Message Not Sent");
@@ -3133,7 +3243,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
switch_xml_t xml = NULL, x_user = NULL, x_param, x_params;
switch_xml_t x_user = NULL, x_param, x_params;
char *user = NULL, *domain = NULL, *dup_domain = NULL;
const char *dest = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
@@ -3298,8 +3408,8 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
switch_safe_free(d_dest);
}
}
if (new_channel && xml) {
if (new_channel && x_user) {
if ((x_params = switch_xml_child(x_user, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
@@ -3311,7 +3421,9 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
done:
switch_xml_free(xml);
if (x_user) {
switch_xml_free(x_user);
}
if (params) {
switch_event_destroy(&params);
@@ -3729,8 +3841,8 @@ static int next_file(switch_file_handle_t *handle)
}
handle->samples = context->fh.samples;
handle->samplerate = context->fh.samplerate;
handle->channels = context->fh.channels;
//handle->samplerate = context->fh.samplerate;
//handle->channels = context->fh.channels;
handle->format = context->fh.format;
handle->sections = context->fh.sections;
handle->seekable = context->fh.seekable;
@@ -3970,9 +4082,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "detect_speech", "Detect speech", "Detect speech on a channel.", detect_speech_function, DETECT_SPEECH_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "play_and_detect_speech", "Play and do speech recognition", "Play and do speech recognition", play_and_detect_speech_function, PLAY_AND_DETECT_SPEECH_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "<menu_name>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "<redirect_data>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_info", "Send info", "Send info", send_info_function, "<info>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.",
jitterbuffer_function, "<jitterbuffer_data>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "<text>",
@@ -3985,7 +4099,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_dtmf", "Send dtmf to be sent", "Send dtmf to be sent from a session", send_dtmf_function, "<dtmf_data>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "sched_cencel", "cancel scheduled tasks", "cancel scheduled tasks", sched_cancel_function, "[group]",
SWITCH_ADD_APP(app_interface, "sched_cancel", "cancel scheduled tasks", "cancel scheduled tasks", sched_cancel_function, "[group]",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "sched_hangup", SCHED_HANGUP_DESCR, SCHED_HANGUP_DESCR, sched_hangup_function, "[+]<time> [<cause>]",
SAF_SUPPORT_NOMEDIA);
@@ -4049,7 +4163,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "bridge", "Bridge Audio", "Bridge the audio between two sessions", audio_bridge_function, "<channel_url>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "system", "Execute a system command", "Execute a system command", system_session_function, "<command>",
SAF_SUPPORT_NOMEDIA);
SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "say", "say", "say", say_function, SAY_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "wait_for_silence", "wait_for_silence", "wait_for_silence", wait_for_silence_function, WAIT_FOR_SILENCE_SYNTAX,
+42 -5
View File
@@ -356,15 +356,25 @@ static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t
if (service && regex && replace) {
switch_regex_t *re = NULL, *re2 = NULL;
int proceed = 0, ovector[30];
char substituted[1024] = "";
char rbuf[1024] = "";
char *substituted = NULL;
char *substituted_2 = NULL;
char *uri;
char *uri_expanded = NULL;
enum_route_t *route;
int supported = 0;
uint32_t len = 0;
if ((proceed = switch_regex_perform(number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
if (strchr(regex, '(')) {
switch_perform_substitution(re, proceed, replace, number, substituted, sizeof(substituted), ovector);
len = (uint32_t) (strlen(number) + strlen(replace) + 10) * proceed;
if (!(substituted = malloc(len))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
switch_regex_safe_free(re);
goto end;
}
memset(substituted, 0, len);
switch_perform_substitution(re, proceed, replace, number, substituted, len, ovector);
uri = substituted;
} else {
uri = replace;
@@ -377,15 +387,41 @@ static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t
}
if ((proceed = switch_regex_perform(uri, route->regex, &re2, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
switch_event_t *event = NULL;
if (strchr(route->regex, '(')) {
switch_perform_substitution(re2, proceed, route->replace, uri, rbuf, sizeof(rbuf), ovector);
uri = rbuf;
len = (uint32_t) (strlen(uri) + strlen(route->replace) + 10) * proceed;
if (!(substituted_2 = malloc(len))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
switch_safe_free(substituted);
switch_regex_safe_free(re);
switch_regex_safe_free(re2);
switch_mutex_unlock(MUTEX);
goto end;
}
memset(substituted_2, 0, len);
switch_perform_substitution(re2, proceed, route->replace, uri, substituted_2, len, ovector);
uri = substituted_2;
} else {
uri = route->replace;
}
switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
uri_expanded = switch_event_expand_headers(event, uri);
switch_event_destroy(&event);
if (uri_expanded == uri) {
uri_expanded = NULL;
} else {
uri = uri_expanded;
}
supported++;
add_result(results, order, preference, service, uri, supported);
}
switch_safe_free(uri_expanded);
switch_safe_free(substituted_2);
switch_regex_safe_free(re2);
}
switch_mutex_unlock(MUTEX);
@@ -394,6 +430,7 @@ static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t
add_result(results, order, preference, service, uri, 0);
}
switch_safe_free(substituted);
switch_regex_safe_free(re);
}
}
+184 -138
View File
@@ -37,7 +37,7 @@ SWITCH_MODULE_DEFINITION(mod_fifo, mod_fifo_load, mod_fifo_shutdown, NULL);
#define MANUAL_QUEUE_NAME "manual_calls"
#define FIFO_EVENT "fifo::info"
#define FIFO_DELAY_DESTROY 100
static switch_status_t load_config(int reload, int del_all);
#define MAX_PRI 10
@@ -298,6 +298,7 @@ struct fifo_node {
int caller_count;
int consumer_count;
int ring_consumer_count;
int member_count;
switch_time_t start_waiting;
uint32_t importance;
switch_thread_rwlock_t *rwlock;
@@ -311,6 +312,8 @@ struct fifo_node {
outbound_strategy_t outbound_strategy;
int ring_timeout;
int default_lag;
char *domain_name;
struct fifo_node *next;
};
typedef struct fifo_node fifo_node_t;
@@ -520,13 +523,16 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session
char buf[25] = "";
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *caller_exit_key = switch_channel_get_variable(channel, "fifo_caller_exit_key");
switch_status_t status = SWITCH_STATUS_SUCCESS;
args.input_callback = moh_on_dtmf;
args.buf = buf;
args.buflen = sizeof(buf);
args.read_frame_callback = chime_read_frame_callback;
args.user_data = user_data;
if (switch_ivr_play_file(session, NULL, cd->list[cd->index], &args) != SWITCH_STATUS_SUCCESS) {
status = switch_ivr_play_file(session, NULL, cd->list[cd->index], &args);
if (!SWITCH_READ_ACCEPTABLE(status)) {
return SWITCH_STATUS_BREAK;
}
@@ -563,6 +569,8 @@ static switch_status_t consumer_read_frame_callback(switch_core_session_t *sessi
return SWITCH_STATUS_SUCCESS;
}
struct fifo_node;
static struct {
switch_hash_t *caller_orig_hash;
switch_hash_t *consumer_orig_hash;
@@ -586,6 +594,7 @@ static struct {
int threads;
switch_thread_t *node_thread;
int debug;
struct fifo_node *nodes;
} globals;
@@ -633,9 +642,6 @@ static void cancel_caller_outbound_call(const char *key, switch_call_cause_t cau
*cancel_cause = cause;
}
switch_mutex_unlock(globals.caller_orig_mutex);
fifo_caller_del(key);
}
@@ -814,7 +820,8 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu
char outbound_count[80] = "";
callback_t cbt = { 0 };
char *sql = NULL;
char *domain_name = NULL;
if (!globals.running) {
return NULL;
}
@@ -826,6 +833,12 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu
node->pool = pool;
node->outbound_strategy = default_strategy;
node->name = switch_core_strdup(node->pool, name);
if (!strchr(name, '@')) {
domain_name = switch_core_get_variable_dup("domain");
node->domain_name = switch_core_strdup(node->pool, domain_name);
}
for (x = 0; x < MAX_PRI; x++) {
fifo_queue_create(&node->fifo_list[x], 1000, node->pool);
switch_assert(node->fifo_list[x]);
@@ -839,16 +852,25 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu
cbt.len = sizeof(outbound_count);
sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name);
fifo_execute_sql_callback(mutex, sql, sql2str_callback, &cbt);
if (atoi(outbound_count) > 0) {
node->member_count = atoi(outbound_count);
if (node->member_count > 0) {
node->has_outbound = 1;
}
} else {
node->has_outbound = 0;
}
switch_safe_free(sql);
node->importance = importance;
switch_mutex_lock(globals.mutex);
switch_core_hash_insert(globals.fifo_hash, name, node);
node->next = globals.nodes;
globals.nodes = node;
switch_mutex_unlock(globals.mutex);
switch_safe_free(domain_name);
return node;
}
@@ -1202,6 +1224,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
switch_mutex_lock(globals.mutex);
node = switch_core_hash_find(globals.fifo_hash, node_name);
switch_thread_rwlock_rdlock(node->rwlock);
switch_mutex_unlock(globals.mutex);
for (i = 0; i < cbh->rowcount; i++) {
@@ -1487,6 +1510,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
node->ring_consumer_count = 0;
node->busy = 0;
switch_mutex_unlock(node->update_mutex);
switch_thread_rwlock_unlock(node->rwlock);
}
@@ -1543,6 +1567,7 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_mutex_lock(globals.mutex);
node = switch_core_hash_find(globals.fifo_hash, h->node_name);
switch_thread_rwlock_rdlock(node->rwlock);
switch_mutex_unlock(globals.mutex);
if (node) {
@@ -1592,7 +1617,7 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
if (status != SWITCH_STATUS_SUCCESS) {
sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1, "
"outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag + 1 where uuid='%q' and use_count > 0",
"outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag + 1 where uuid='%q'",
(long) switch_epoch_time_now(NULL), h->uuid);
fifo_execute_sql(sql, globals.sql_mutex);
switch_safe_free(sql);
@@ -1650,6 +1675,7 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
}
node->busy = 0;
switch_mutex_unlock(node->update_mutex);
switch_thread_rwlock_unlock(node->rwlock);
}
switch_core_destroy_memory_pool(&h->pool);
@@ -1781,73 +1807,88 @@ static void find_consumers(fifo_node_t *node)
static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *obj)
{
fifo_node_t *node;
fifo_node_t *node, *last, *this_node;
int cur_priority = 1;
globals.node_thread_running = 1;
while (globals.node_thread_running == 1) {
switch_hash_index_t *hi;
void *val;
const void *var;
int ppl_waiting, consumer_total, idle_consumers, found = 0;
switch_mutex_lock(globals.mutex);
if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Trying priority: %d\n", cur_priority);
last = NULL;
node = globals.nodes;
restart:
while(node) {
int x = 0;
switch_event_t *pop;
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((node = (fifo_node_t *) val)) {
int x = 0;
switch_event_t *pop;
this_node = node;
node = node->next;
if (node->ready == FIFO_DELAY_DESTROY) {
if (switch_thread_rwlock_trywrlock(node->rwlock) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
}
}
node->ready = 0;
switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->mutex);
switch_mutex_unlock(node->update_mutex);
switch_thread_rwlock_unlock(node->rwlock);
switch_core_destroy_memory_pool(&node->pool);
goto restart;
if (this_node->ready == 0) {
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(this_node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
const char *caller_uuid = switch_event_get_header(pop, "unique-id");
switch_ivr_kill_uuid(caller_uuid, SWITCH_CAUSE_MANAGER_REQUEST);
switch_event_destroy(&pop);
}
}
}
if (node->outbound_priority == 0) node->outbound_priority = 5;
if (node->has_outbound && node->ready && !node->busy && node->outbound_priority == cur_priority) {
ppl_waiting = node_caller_count(node);
consumer_total = node->consumer_count;
idle_consumers = node_idle_consumers(node);
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"%s waiting %d consumer_total %d idle_consumers %d ring_consumers %d pri %d\n",
node->name, ppl_waiting, consumer_total, idle_consumers, node->ring_consumer_count, node->outbound_priority);
if (this_node->ready == 0 && switch_thread_rwlock_trywrlock(this_node->rwlock) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", this_node->name);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(this_node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
}
}
if (last) {
last->next = this_node->next;
} else {
globals.nodes = this_node->next;
}
switch_core_hash_destroy(&this_node->consumer_hash);
switch_mutex_unlock(this_node->mutex);
switch_mutex_unlock(this_node->update_mutex);
switch_thread_rwlock_unlock(this_node->rwlock);
switch_core_destroy_memory_pool(&this_node->pool);
continue;
}
last = this_node;
if (this_node->outbound_priority == 0) this_node->outbound_priority = 5;
if (this_node->has_outbound && !this_node->busy && this_node->outbound_priority == cur_priority) {
ppl_waiting = node_caller_count(this_node);
consumer_total = this_node->consumer_count;
idle_consumers = node_idle_consumers(this_node);
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"%s waiting %d consumer_total %d idle_consumers %d ring_consumers %d pri %d\n",
this_node->name, ppl_waiting, consumer_total, idle_consumers, this_node->ring_consumer_count, this_node->outbound_priority);
}
if ((ppl_waiting - node->ring_consumer_count > 0) && (!consumer_total || !idle_consumers)) {
found++;
find_consumers(node);
switch_yield(1000000);
}
if ((ppl_waiting - this_node->ring_consumer_count > 0) && (!consumer_total || !idle_consumers)) {
found++;
find_consumers(this_node);
switch_yield(1000000);
}
}
}
if (++cur_priority > 10) {
cur_priority = 1;
@@ -1885,20 +1926,6 @@ static int stop_node_thread(void)
return 0;
}
static void check_ocancel(switch_core_session_t *session)
{
//switch_channel_t *channel;
//const char *var;
switch_assert(session);
//channel = switch_core_session_get_channel(session);
cancel_caller_outbound_call(switch_core_session_get_uuid(session), SWITCH_CAUSE_ORIGINATOR_CANCEL);
}
static void check_cancel(fifo_node_t *node)
{
int ppl_waiting;
@@ -1928,9 +1955,16 @@ static void send_presence(fifo_node_t *node)
}
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "park");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", node->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", node->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "queue");
if (node->domain_name) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s@%s", node->name, node->domain_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", node->name, node->domain_name);
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", node->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", node->name);
}
if ((wait_count = node_caller_count(node)) > 0) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d waiting)", wait_count);
} else {
@@ -1952,39 +1986,52 @@ static void send_presence(fifo_node_t *node)
static void pres_event_handler(switch_event_t *event)
{
char *to = switch_event_get_header(event, "to");
char *dup_to = NULL, *node_name;
char *domain_name = NULL;
char *dup_to = NULL, *node_name , *dup_node_name;
fifo_node_t *node;
if (!globals.running) {
return;
}
if (!to || strncasecmp(to, "park+", 5)) {
if (!to || strncasecmp(to, "queue+", 6) || !strchr(to, '@')) {
return;
}
dup_to = strdup(to);
switch_assert(dup_to);
node_name = dup_to + 5;
node_name = dup_to + 6;
if ((domain_name = strchr(node_name, '@'))) {
*domain_name++ = '\0';
}
dup_node_name = switch_mprintf("%q@%q", node_name, domain_name);
switch_mutex_lock(globals.mutex);
if (!(node = switch_core_hash_find(globals.fifo_hash, node_name))) {
if (!(node = switch_core_hash_find(globals.fifo_hash, node_name)) && !(node = switch_core_hash_find(globals.fifo_hash, dup_node_name))) {
node = create_node(node_name, 0, globals.sql_mutex);
node->domain_name = switch_core_strdup(node->pool, domain_name);
node->ready = 1;
}
switch_thread_rwlock_rdlock(node->rwlock);
send_presence(node);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(globals.mutex);
switch_safe_free(dup_to);
switch_safe_free(dup_node_name);
}
static uint32_t fifo_add_outbound(const char *node_name, const char *url, uint32_t priority)
{
fifo_node_t *node;
switch_event_t *call_event;
uint32_t i = 0;
if (priority >= MAX_PRI) {
priority = MAX_PRI - 1;
@@ -1998,6 +2045,8 @@ static uint32_t fifo_add_outbound(const char *node_name, const char *url, uint32
node = create_node(node_name, 0, globals.sql_mutex);
}
switch_thread_rwlock_rdlock(node->rwlock);
switch_mutex_unlock(globals.mutex);
switch_event_create(&call_event, SWITCH_EVENT_CHANNEL_DATA);
@@ -2006,7 +2055,11 @@ static uint32_t fifo_add_outbound(const char *node_name, const char *url, uint32
fifo_queue_push(node->fifo_list[priority], call_event);
call_event = NULL;
return fifo_queue_size(node->fifo_list[priority]);
i = fifo_queue_size(node->fifo_list[priority]);
switch_thread_rwlock_unlock(node->rwlock);
return i;
}
@@ -2228,11 +2281,11 @@ SWITCH_STANDARD_APP(fifo_function)
char *list_string;
int nlist_count;
char *nlist[MAX_NODES_PER_CONSUMER];
int consumer = 0;
int consumer = 0, in_table = 0;
const char *arg_fifo_name = NULL;
const char *arg_inout = NULL;
const char *serviced_uuid = NULL;
if (!globals.running) {
return;
}
@@ -2405,6 +2458,7 @@ SWITCH_STANDARD_APP(fifo_function)
fifo_queue_push(node->fifo_list[p], call_event);
fifo_caller_add(node, session);
in_table = 1;
call_event = NULL;
switch_snprintf(tmp, sizeof(tmp), "%d", fifo_queue_size(node->fifo_list[p]));
@@ -2501,8 +2555,6 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG);
fifo_caller_del(switch_core_session_get_uuid(session));
if (!aborted && switch_channel_ready(channel)) {
switch_channel_set_state(channel, CS_HIBERNATE);
goto done;
@@ -2534,10 +2586,13 @@ SWITCH_STANDARD_APP(fifo_function)
if (orbit_ann) {
switch_ivr_play_file(session, NULL, orbit_ann, NULL);
}
switch_ivr_session_transfer(session, cd.orbit_exten, cd.orbit_dialplan, cd.orbit_context);
if (strcmp(cd.orbit_exten, "_continue_")) {
switch_ivr_session_transfer(session, cd.orbit_exten, cd.orbit_dialplan, cd.orbit_context);
}
}
check_ocancel(session);
cancel_caller_outbound_call(switch_core_session_get_uuid(session), SWITCH_CAUSE_ORIGINATOR_CANCEL);
goto done;
@@ -3148,6 +3203,10 @@ SWITCH_STANDARD_APP(fifo_function)
done:
if (!consumer && in_table) {
fifo_caller_del(switch_core_session_get_uuid(session));
}
if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use"))) {
do_destroy = 1;
}
@@ -3159,7 +3218,7 @@ SWITCH_STANDARD_APP(fifo_function)
}
switch_thread_rwlock_unlock(node->rwlock);
if (node->ready == 1 && do_destroy) {
node->ready = FIFO_DELAY_DESTROY;
node->ready = 0;
}
}
switch_mutex_unlock(globals.mutex);
@@ -3677,7 +3736,6 @@ void node_dump(switch_stream_handle_t *stream)
#define FIFO_API_SYNTAX "list|list_verbose|count|debug|status|importance [<fifo name>]|reparse [del_all]"
SWITCH_STANDARD_API(fifo_api_function)
{
int len = 0;
fifo_node_t *node;
char *data = NULL;
int argc = 0;
@@ -3736,6 +3794,7 @@ SWITCH_STANDARD_API(fifo_api_function)
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
switch_mutex_lock(node->mutex);
list_node(node, x_report, &x, verbose);
switch_mutex_unlock(node->mutex);
@@ -3772,9 +3831,8 @@ SWITCH_STANDARD_API(fifo_api_function)
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), len);
stream->write_function(stream, "%s:%d:%d:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), node->member_count, node->ring_consumer_count, node_idle_consumers(node));
switch_mutex_unlock(node->update_mutex);
x++;
}
@@ -3783,9 +3841,8 @@ SWITCH_STANDARD_API(fifo_api_function)
stream->write_function(stream, "none\n");
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), len);
stream->write_function(stream, "%s:%d:%d:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), node->member_count, node->ring_consumer_count, node_idle_consumers(node));
switch_mutex_unlock(node->update_mutex);
} else {
stream->write_function(stream, "none\n");
@@ -3795,7 +3852,6 @@ SWITCH_STANDARD_API(fifo_api_function)
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", (char *) var, node->has_outbound);
switch_mutex_unlock(node->update_mutex);
@@ -3806,7 +3862,6 @@ SWITCH_STANDARD_API(fifo_api_function)
stream->write_function(stream, "none\n");
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", argv[1], node->has_outbound);
switch_mutex_unlock(node->update_mutex);
@@ -3979,8 +4034,8 @@ static switch_status_t load_config(int reload, int del_all)
switch_mutex_lock(globals.mutex);
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
if ((node = (fifo_node_t *) val) && node->is_static) {
node->ready = 0;
if ((node = (fifo_node_t *) val) && node->is_static && node->ready == 1) {
node->ready = -1;
}
}
switch_mutex_unlock(globals.mutex);
@@ -3997,6 +4052,7 @@ static switch_status_t load_config(int reload, int del_all)
if (!(node = switch_core_hash_find(globals.fifo_hash, MANUAL_QUEUE_NAME))) {
node = create_node(MANUAL_QUEUE_NAME, 0, globals.sql_mutex);
node->ready = 2;
node->is_static = 0;
}
@@ -4149,7 +4205,7 @@ static switch_status_t load_config(int reload, int del_all)
free(sql);
free(name_dup);
node->has_outbound = 1;
node->member_count++;
}
node->ready = 1;
node->is_static = 1;
@@ -4164,41 +4220,18 @@ static switch_status_t load_config(int reload, int del_all)
done:
if (reload) {
switch_hash_index_t *hi;
void *val;
switch_event_t *pop;
fifo_node_t *node;
switch_mutex_lock(globals.mutex);
top:
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
int x = 0;
switch_hash_this(hi, NULL, NULL, &val);
if (!(node = (fifo_node_t *) val) || !node->is_static || node->ready) {
continue;
}
if (node_caller_count(node) || node->consumer_count || node_idle_consumers(node)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s removal delayed, still in use.\n", node->name);
node->ready = FIFO_DELAY_DESTROY;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_mutex_lock(node->update_mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
}
}
for (node = globals.nodes; node; node = node->next) {
if (node->ready == -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s queued for removal\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
goto top;
node->ready = 0;
}
}
fifo_caller_del(NULL);
switch_mutex_unlock(globals.mutex);
fifo_caller_del(NULL);
}
@@ -4211,6 +4244,8 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
{
char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 };
char *sql, *name_dup, *p;
char outbound_count[80] = "";
callback_t cbt = { 0 };
fifo_node_t *node = NULL;
if (!fifo_name) return;
@@ -4234,8 +4269,6 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
}
switch_mutex_unlock(globals.mutex);
node->has_outbound = 1;
name_dup = strdup(fifo_name);
if ((p = strchr(name_dup, '@'))) {
*p = '\0';
@@ -4252,6 +4285,17 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
free(sql);
free(name_dup);
cbt.buf = outbound_count;
cbt.len = sizeof(outbound_count);
sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", fifo_name);
fifo_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt);
node->member_count = atoi(outbound_count);
if (node->member_count > 0) {
node->has_outbound = 1;
} else {
node->has_outbound = 0;
}
switch_safe_free(sql);
}
static void fifo_member_del(char *fifo_name, char *originate_string)
@@ -4287,10 +4331,11 @@ static void fifo_member_del(char *fifo_name, char *originate_string)
cbt.len = sizeof(outbound_count);
sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", node->name);
fifo_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt);
if (atoi(outbound_count) > 0) {
node->has_outbound = 1;
node->member_count = atoi(outbound_count);
if (node->member_count > 0) {
node->has_outbound = 1;
} else {
node->has_outbound = 0;
node->has_outbound = 0;
}
switch_safe_free(sql);
}
@@ -4446,10 +4491,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
*/
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
{
switch_hash_index_t *hi;
void *val;
switch_event_t *pop = NULL;
fifo_node_t *node;
fifo_node_t *node, *this_node;
switch_mutex_t *mutex = globals.mutex;
switch_event_unbind(&globals.node);
@@ -4466,24 +4509,27 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
switch_cond_next();
}
node = globals.nodes;
while ((hi = switch_hash_first(NULL, globals.fifo_hash))) {
while(node) {
int x = 0;
switch_hash_this(hi, NULL, NULL, &val);
node = (fifo_node_t *) val;
switch_mutex_lock(node->update_mutex);
switch_mutex_lock(node->mutex);
this_node = node;
node = node->next;
switch_mutex_lock(this_node->update_mutex);
switch_mutex_lock(this_node->mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
while (fifo_queue_pop(this_node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
}
}
switch_mutex_unlock(node->mutex);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
switch_mutex_unlock(this_node->mutex);
switch_core_hash_delete(globals.fifo_hash, this_node->name);
switch_core_hash_destroy(&this_node->consumer_hash);
switch_mutex_unlock(this_node->update_mutex);
switch_core_destroy_memory_pool(&this_node->pool);
}
switch_core_hash_destroy(&globals.fifo_hash);
+2 -1
View File
@@ -4,9 +4,10 @@ MODNAME=mod_hash
ESL_DIR=$(switch_srcdir)/libs/esl
mod_LTLIBRARIES = mod_hash.la
mod_hash_la_DEPENDENCIES = $(ESL_DIR)/libesl.so
mod_hash_la_SOURCES = mod_hash.c
mod_hash_la_CFLAGS = $(AM_CFLAGS) -I$(ESL_DIR)/src/include
mod_hash_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(ESL_DIR)/libesl.so
mod_hash_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_hash_la_LDFLAGS = -avoid-version -module -no-undefined -shared -L$(ESL_DIR) -lesl
$(ESL_DIR)/libesl.so:
+56 -2
View File
@@ -407,7 +407,7 @@ SWITCH_LIMIT_STATUS(limit_status_hash)
/* CORE HASH STUFF */
#define HASH_USAGE "[insert|delete]/<realm>/<key>/<val>"
#define HASH_USAGE "[insert|insert_ifempty|delete|delete_ifmatch]/<realm>/<key>/<val>"
#define HASH_DESC "save data"
SWITCH_STANDARD_APP(hash_function)
@@ -443,11 +443,33 @@ SWITCH_STANDARD_APP(hash_function)
value = strdup(argv[3]);
switch_assert(value);
switch_core_hash_insert(globals.db_hash, hash_key, value);
} else if (!strcasecmp(argv[0], "insert_ifempty")) {
if (argc < 4) {
goto usage;
}
if (!(value = switch_core_hash_find(globals.db_hash, hash_key))) {
value = strdup(argv[3]);
switch_assert(value);
switch_core_hash_insert(globals.db_hash, hash_key, value);
} else {
switch_safe_free(value);
}
} else if (!strcasecmp(argv[0], "delete")) {
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
switch_safe_free(value);
switch_core_hash_delete(globals.db_hash, hash_key);
}
} else if (!strcasecmp(argv[0], "delete_ifmatch")) {
if (argc < 4) {
goto usage;
}
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
if(!strcmp(argv[3], value)) {
switch_core_hash_delete(globals.db_hash, hash_key);
}
switch_safe_free(value);
}
} else {
goto usage;
}
@@ -463,7 +485,7 @@ SWITCH_STANDARD_APP(hash_function)
switch_safe_free(hash_key);
}
#define HASH_API_USAGE "insert|select|delete/realm/key[/value]"
#define HASH_API_USAGE "insert|insert_ifempty|select|delete|delete_ifmatch/realm/key[/value]"
SWITCH_STANDARD_API(hash_api_function)
{
int argc = 0;
@@ -498,6 +520,21 @@ SWITCH_STANDARD_API(hash_api_function)
switch_core_hash_insert(globals.db_hash, hash_key, value);
stream->write_function(stream, "+OK\n");
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
} else if (!strcasecmp(argv[0], "insert_ifempty")) {
if (argc < 4) {
goto usage;
}
switch_thread_rwlock_wrlock(globals.db_hash_rwlock);
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
stream->write_function(stream, "-ERR key already exists\n");
switch_safe_free(value);
} else {
value = strdup(argv[3]);
switch_assert(value);
switch_core_hash_insert(globals.db_hash, hash_key, value);
stream->write_function(stream, "+OK\n");
}
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
} else if (!strcasecmp(argv[0], "delete")) {
switch_thread_rwlock_wrlock(globals.db_hash_rwlock);
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
@@ -508,6 +545,23 @@ SWITCH_STANDARD_API(hash_api_function)
stream->write_function(stream, "-ERR Not found\n");
}
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
} else if (!strcasecmp(argv[0], "delete_ifmatch")) {
if (argc < 4) {
goto usage;
}
switch_thread_rwlock_wrlock(globals.db_hash_rwlock);
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
if(!strcmp(argv[3],value)) {
switch_core_hash_delete(globals.db_hash, hash_key);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "-ERR Doesn't match\n");
}
switch_safe_free(value);
} else {
stream->write_function(stream, "-ERR Not found\n");
}
switch_thread_rwlock_unlock(globals.db_hash_rwlock);
} else if (!strcasecmp(argv[0], "select")) {
switch_thread_rwlock_rdlock(globals.db_hash_rwlock);
if ((value = switch_core_hash_find(globals.db_hash, hash_key))) {
@@ -0,0 +1,4 @@
BASE=../../../..
include $(BASE)/build/modmake.rules
File diff suppressed because it is too large Load Diff
+29 -2
View File
@@ -605,6 +605,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
char *key = NULL;
int i = 0;
int r = 0;
switch_bool_t lcr_skipped = SWITCH_TRUE; /* assume we'll throw it away, paranoid about leak */
switch_memory_pool_t *pool = cbt->pool;
@@ -625,6 +626,8 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
if (!argv[i] || zstr(argv[i])) {
/* maybe we want to consider saying which carriers have null rate fields... maybe they can run the query and find out */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "rate field is null, skipping\n");
/* kill prev/next pointers */
/* additional->prev = NULL; */
goto end;
}
additional->rate = (float)atof(switch_str_nil(argv[i]));
@@ -661,6 +664,13 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
additional->dialstring = get_bridge_data(pool, cbt->lookup_number, cbt->cid, additional, cbt->profile, cbt->session);
if (cbt->head == NULL) {
if (cbt->max_rate && (cbt->max_rate < additional->rate)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Skipping [%s] because [%f] is higher than the max_rate of [%f]\n",
additional->carrier_name, additional->rate, cbt->max_rate);
lcr_skipped = SWITCH_FALSE;
r = 0; goto end;
}
key = switch_core_sprintf(pool, "%s:%s", additional->gw_prefix, additional->gw_suffix);
additional->next = cbt->head;
cbt->head = additional;
@@ -669,6 +679,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n");
r = -1; goto end;
}
lcr_skipped = SWITCH_FALSE;
r = 0; goto end;
}
@@ -698,6 +709,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n");
r = -1; goto end;
}
lcr_skipped = SWITCH_FALSE;
break;
}
} else {
@@ -719,6 +731,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n");
r = -1; goto end;
}
lcr_skipped = SWITCH_FALSE;
break;
} else if (current->next == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "adding %s to end of list after %s\n",
@@ -729,6 +742,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n");
r = -1; goto end;
}
lcr_skipped = SWITCH_FALSE;
break;
}
}
@@ -736,8 +750,21 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
end:
/* event is freed in lcr_destroy() switch_event_destroy(&additional->fields); */
/* lcr was not added to any lists, so destroy lcr object here */
if (lcr_skipped == SWITCH_TRUE) {
/* complain loudly if we're asked to destroy a route that is
added to the route list */
if (additional && additional->prev != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"additional->prev != NULL\n");
}
if (current && current->next == additional) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"current->next == additional\n");
}
lcr_destroy(additional);
}
return r;
}
@@ -1,8 +1,6 @@
MEMCACHED=libmemcached-0.32
BASE=../../../..
WANT_CURL=yes
MEMCACHED_DIR=$(switch_srcdir)/libs/$(MEMCACHED)
MEMCACHED_BUILDDIR=$(switch_builddir)/libs/$(MEMCACHED)
+4 -4
View File
@@ -49,7 +49,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function)
conn = mongo_connection_pool_get(globals.conn_pool);
if (conn) {
conn->runCommand(conn->nsGetDB(ns), cmd.done(), out);
mongo_connection_pool_put(globals.conn_pool, conn);
mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE);
stream->write_function(stream, "-OK\n%s\n", out.toString().c_str());
} else {
@@ -57,7 +57,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function)
}
} catch (DBException &e) {
if (conn) {
mongo_connection_destroy(&conn);
mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_TRUE);
}
stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str());
}
@@ -97,7 +97,7 @@ SWITCH_STANDARD_API(mongo_find_one_function)
conn = mongo_connection_pool_get(globals.conn_pool);
if (conn) {
BSONObj res = conn->findOne(ns, Query(query), &fields);
mongo_connection_pool_put(globals.conn_pool, conn);
mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE);
stream->write_function(stream, "-OK\n%s\n", res.toString().c_str());
} else {
@@ -105,7 +105,7 @@ SWITCH_STANDARD_API(mongo_find_one_function)
}
} catch (DBException &e) {
if (conn) {
mongo_connection_destroy(&conn);
mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_TRUE);
}
stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str());
}
+1 -1
View File
@@ -30,7 +30,7 @@ void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool);
DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool);
switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn);
switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn, switch_bool_t destroy);
#endif
+12 -9
View File
@@ -15,23 +15,27 @@ switch_status_t mongo_connection_create(DBClientBase **connection, const char *c
DBClientBase *conn = NULL;
string conn_string(conn_str), err_msg;
ConnectionString cs = ConnectionString::parse(conn_string, err_msg);
switch_status_t status = SWITCH_STATUS_FALSE;
if (!cs.isValid()) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't parse url: %s\n", err_msg.c_str());
return SWITCH_STATUS_GENERR;
return status;
}
try {
conn = cs.connect(err_msg);
} catch (DBException &e) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]: %s\n", conn_str, err_msg.c_str());
return SWITCH_STATUS_GENERR;
return status;
}
*connection = conn;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", conn_str);
if (conn) {
*connection = conn;
status = SWITCH_STATUS_SUCCESS;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", conn_str);
}
return SWITCH_STATUS_SUCCESS;
return status;
}
void mongo_connection_destroy(DBClientBase **conn)
@@ -75,7 +79,7 @@ switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool
for (cpool->size = 0; cpool->size < min_connections; cpool->size++) {
if (mongo_connection_create(&conn, conn_str) == SWITCH_STATUS_SUCCESS) {
mongo_connection_pool_put(cpool, conn);
mongo_connection_pool_put(cpool, conn, SWITCH_FALSE);
} else {
break;
}
@@ -89,7 +93,6 @@ switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool
switch_core_destroy_memory_pool(&pool);
}
return status;
}
@@ -137,7 +140,7 @@ DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool)
return conn;
}
switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn)
switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn, switch_bool_t destroy)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
@@ -145,7 +148,7 @@ switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DB
switch_assert(conn != NULL);
switch_mutex_lock(conn_pool->mutex);
if (conn_pool->size > conn_pool->max_connections) {
if (destroy || conn_pool->size > conn_pool->max_connections) {
#ifdef MONGO_POOL_DEBUG
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn);
#endif
File diff suppressed because it is too large Load Diff
+29 -2
View File
@@ -42,6 +42,7 @@ 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_event_add_header(event, SWITCH_STACK_BOTTOM, "skip_global_process", "true");
switch_core_chat_send(dest_proto, event);
}
@@ -80,7 +81,7 @@ static int parse_exten(switch_event_t *event, switch_xml_t xexten, switch_event_
switch_bool_t anti_action = SWITCH_TRUE;
break_t do_break_i = BREAK_ON_FALSE;
int time_match = switch_xml_std_datetime_check(xcond);
int time_match = switch_xml_std_datetime_check(xcond, NULL);
switch_safe_free(field_expanded);
switch_safe_free(expression_expanded);
@@ -367,7 +368,31 @@ static switch_status_t chat_send(switch_event_t *message_event)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_event_t *exten;
int forwards = 0;
const char *var;
var = switch_event_get_header(message_event, "max_forwards");
if (!var) {
forwards = 70;
} else {
forwards = atoi(var);
if (forwards) {
forwards--;
}
if (!forwards) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max forwards reached\n");
DUMP_EVENT(message_event);
return SWITCH_STATUS_FALSE;
}
}
if (forwards) {
switch_event_add_header(message_event, SWITCH_STACK_BOTTOM, "max_forwards", "%d", forwards);
}
if ((exten = chatplan_hunt(message_event))) {
switch_event_header_t *hp;
@@ -401,6 +426,8 @@ SWITCH_STANDARD_CHAT_APP(send_function)
dest_proto = switch_event_get_header(message, "dest_proto");
}
switch_event_add_header(message, SWITCH_STACK_BOTTOM, "skip_global_process", "true");
switch_core_chat_send(dest_proto, message);
return SWITCH_STATUS_SUCCESS;
+1 -1
View File
@@ -1,5 +1,5 @@
BASE=../../../..
VERSION=soundtouch-1.5.0
VERSION=soundtouch-1.6.0
SNDT_SRC=$(switch_srcdir)/libs/soundtouch
SNDT_BUILD=$(switch_builddir)/libs/soundtouch
LA=$(SNDT_BUILD)/source/SoundTouch/.libs/libSoundTouch.a
+4 -4
View File
@@ -4,15 +4,15 @@ MODNAME=mod_spandsp
TIFF_DIR=$(switch_srcdir)/libs/tiff-3.8.2
TIFF_BUILDDIR=$(switch_builddir)/libs/tiff-3.8.2
TIFF_LA=$(TIFF_BUILDDIR)/libtiff/libtiff.la
BUILD_CFLAGS=
SPANDSP_DIR=$(switch_srcdir)/libs/spandsp
SPANDSP_BUILDDIR=$(switch_builddir)/libs/spandsp
SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la
mod_LTLIBRARIES = mod_spandsp.la
mod_spandsp_la_SOURCES = mod_spandsp.c udptl.c mod_spandsp_fax.c mod_spandsp_dsp.c mod_spandsp_codecs.c
mod_spandsp_la_CFLAGS = $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -I.
mod_spandsp_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -ljpeg -lz
mod_spandsp_la_SOURCES = mod_spandsp.c udptl.c mod_spandsp_fax.c mod_spandsp_dsp.c mod_spandsp_codecs.c mod_spandsp_modem.c
mod_spandsp_la_CFLAGS = $(BUILD_CFLAGS) $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -I.
mod_spandsp_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -ljpeg -lz -lutil
mod_spandsp_la_LDFLAGS = -avoid-version -module -no-undefined -shared
$(SPANDSP_LA): $(TIFF_LA) $(SPANDSP_DIR) $(SPANDSP_DIR)/.update
@@ -301,6 +301,10 @@
RelativePath=".\mod_spandsp_fax.c"
>
</File>
<File
RelativePath=".\mod_spandsp_modem.c"
>
</File>
<File
RelativePath=".\udptl.c"
>
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@@ -129,6 +129,7 @@
<ClCompile Include="mod_spandsp_codecs.c" />
<ClCompile Include="mod_spandsp_dsp.c" />
<ClCompile Include="mod_spandsp_fax.c" />
<ClCompile Include="mod_spandsp_modem.c" />
<ClCompile Include="udptl.c" />
</ItemGroup>
<ItemGroup>
@@ -148,4 +149,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+299 -11
View File
@@ -36,11 +36,14 @@
#include "mod_spandsp.h"
#include <spandsp/version.h>
#include "mod_spandsp_modem.h"
/* **************************************************************************
FREESWITCH MODULE DEFINITIONS
************************************************************************* */
struct spandsp_globals spandsp_globals = { 0 };
#define SPANFAX_RX_USAGE "<filename>"
#define SPANFAX_TX_USAGE "<filename>"
@@ -74,25 +77,35 @@ SWITCH_STANDARD_APP(stop_dtmf_session_function)
SWITCH_STANDARD_APP(spandsp_fax_detect_session_function)
{
int argc = 0;
char *argv[3] = { 0 };
char *argv[4] = { 0 };
char *dupdata;
const char *app = NULL, *arg = NULL;
int timeout = 0;
int tone_type = MODEM_CONNECT_TONES_FAX_CNG;
if (!zstr(data) && (dupdata = switch_core_session_strdup(session, data))) {
if ((argc = switch_split(dupdata, ' ', argv)) == 3) {
if ((argc = switch_split(dupdata, ' ', argv)) >= 2) {
app = argv[0];
arg = argv[1];
timeout = atoi(argv[2]);
if (timeout < 0) {
timeout = 0;
}
if (argc > 2) {
timeout = atoi(argv[2]);
if (timeout < 0) {
timeout = 0;
}
}
if (argc > 3) {
if (!strcmp(argv[3], "ced")) {
tone_type = MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE;
} else {
tone_type = MODEM_CONNECT_TONES_FAX_CNG;
}
}
}
}
if (app) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Enabling fax detection '%s' '%s'\n", argv[0], argv[1]);
spandsp_fax_detect_session(session, "rw", timeout, 1, app, arg, NULL);
spandsp_fax_detect_session(session, "rw", timeout, tone_type, 1, app, arg, NULL);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot Enable fax detection '%s' '%s'\n", argv[0], argv[1]);
}
@@ -106,10 +119,9 @@ SWITCH_STANDARD_APP(spandsp_stop_fax_detect_session_function)
static void event_handler(switch_event_t *event)
{
mod_spandsp_fax_event_handler(event);
load_configuration(1);
}
SWITCH_STANDARD_APP(t38_gateway_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
@@ -151,7 +163,7 @@ SWITCH_STANDARD_APP(t38_gateway_function)
}
//switch_ivr_tone_detect_session(session, "t38", "1100.0", "rw", timeout, 1, direction, NULL, t38_gateway_start);
spandsp_fax_detect_session(session, "rw", timeout, 1, direction, NULL, t38_gateway_start);
spandsp_fax_detect_session(session, "rw", timeout, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, 1, direction, NULL, t38_gateway_start);
}
}
@@ -251,12 +263,274 @@ SWITCH_STANDARD_API(stop_tone_detect_api)
return status;
}
void mod_spandsp_indicate_data(switch_core_session_t *session, switch_bool_t self, switch_bool_t on)
{
switch_core_session_t *target_session = NULL;
int locked = 0;
if (self) {
target_session = session;
} else {
if (switch_core_session_get_partner(session, &target_session) == SWITCH_STATUS_SUCCESS) {
locked = 1;
} else {
target_session = NULL;
}
}
if (target_session) {
switch_core_session_message_t *msg;
msg = switch_core_session_alloc(target_session, sizeof(*msg));
MESSAGE_STAMP_FFL(msg);
msg->message_id = SWITCH_MESSAGE_INDICATE_AUDIO_DATA;
msg->from = __FILE__;
msg->numeric_arg = on;
switch_core_session_queue_message(target_session, msg);
if (locked) {
switch_core_session_rwunlock(target_session);
locked = 0;
}
}
}
/* **************************************************************************
CONFIGURATION
************************************************************************* */
switch_status_t load_configuration(switch_bool_t reload)
{
switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL, callprogress = NULL, xdescriptor = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_mutex_lock(spandsp_globals.mutex);
if (spandsp_globals.tones) {
switch_core_hash_destroy(&spandsp_globals.tones);
}
if (spandsp_globals.config_pool) {
switch_core_destroy_memory_pool(&spandsp_globals.config_pool);
}
switch_core_new_memory_pool(&spandsp_globals.config_pool);
switch_core_hash_init(&spandsp_globals.tones, spandsp_globals.config_pool);
spandsp_globals.modem_dialplan = "XML";
spandsp_globals.modem_context = "default";
spandsp_globals.modem_count = 0;
spandsp_globals.enable_t38 = 1;
spandsp_globals.total_sessions = 0;
spandsp_globals.verbose = 0;
spandsp_globals.use_ecm = 1;
spandsp_globals.disable_v17 = 0;
spandsp_globals.prepend_string = switch_core_strdup(spandsp_globals.config_pool, "fax");
spandsp_globals.spool = switch_core_strdup(spandsp_globals.config_pool, "/tmp");
spandsp_globals.ident = "SpanDSP Fax Ident";
spandsp_globals.header = "SpanDSP Fax Header";
spandsp_globals.timezone = "";
/* TODO make configuration param */
spandsp_globals.tonedebug = 1;
if ((xml = switch_xml_open_cfg("spandsp.conf", &cfg, NULL)) || (xml = switch_xml_open_cfg("fax.conf", &cfg, NULL))) {
status = SWITCH_STATUS_SUCCESS;
if ((x_lists = switch_xml_child(cfg, "modem-settings"))) {
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
const char *name = switch_xml_attr(x_list, "name");
const char *value = switch_xml_attr(x_list, "value");
if (zstr(name)) {
continue;
}
if (zstr(value)) {
continue;
}
if (!reload && !strcmp(name, "total-modems")) {
int tmp = atoi(value);
if (tmp > -1 && tmp < MAX_MODEMS) {
spandsp_globals.modem_count = tmp;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%d] for total-modems\n", tmp);
}
} else if (!strcmp(name, "dialplan")) {
spandsp_globals.modem_dialplan = switch_core_strdup(spandsp_globals.config_pool, value);
} else if (!strcmp(name, "context")) {
spandsp_globals.modem_context = switch_core_strdup(spandsp_globals.config_pool, value);
} else if (!strcmp(name, "verbose")) {
if (switch_true(value)) {
spandsp_globals.modem_verbose = 1;
} else {
spandsp_globals.modem_verbose = 0;
}
}
}
}
if ((x_lists = switch_xml_child(cfg, "fax-settings")) || (x_lists = switch_xml_child(cfg, "settings"))) {
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
const char *name = switch_xml_attr(x_list, "name");
const char *value = switch_xml_attr(x_list, "value");
if (zstr(name)) {
continue;
}
if (zstr(value)) {
continue;
}
if (!strcmp(name, "use-ecm")) {
if (switch_true(value))
spandsp_globals.use_ecm = 1;
else
spandsp_globals.use_ecm = 0;
} else if (!strcmp(name, "verbose")) {
if (switch_true(value))
spandsp_globals.verbose = 1;
else
spandsp_globals.verbose = 0;
} else if (!strcmp(name, "disable-v17")) {
if (switch_true(value))
spandsp_globals.disable_v17 = 1;
else
spandsp_globals.disable_v17 = 0;
} else if (!strcmp(name, "enable-t38")) {
if (switch_true(value)) {
spandsp_globals.enable_t38= 1;
} else {
spandsp_globals.enable_t38 = 0;
}
} else if (!strcmp(name, "enable-t38-request")) {
if (switch_true(value)) {
spandsp_globals.enable_t38_request = 1;
} else {
spandsp_globals.enable_t38_request = 0;
}
} else if (!strcmp(name, "ident")) {
spandsp_globals.ident = switch_core_strdup(spandsp_globals.config_pool, value);
} else if (!strcmp(name, "header")) {
spandsp_globals.header = switch_core_strdup(spandsp_globals.config_pool, value);
} else if (!strcmp(name, "spool-dir")) {
spandsp_globals.spool = switch_core_strdup(spandsp_globals.config_pool, value);
} else if (!strcmp(name, "file-prefix")) {
spandsp_globals.prepend_string = switch_core_strdup(spandsp_globals.config_pool, value);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter %s\n", name);
}
}
}
/* Configure call progress detector */
if ((callprogress = switch_xml_child(cfg, "descriptors"))) {
for (xdescriptor = switch_xml_child(callprogress, "descriptor"); xdescriptor; xdescriptor = switch_xml_next(xdescriptor)) {
const char *name = switch_xml_attr(xdescriptor, "name");
const char *tone_name = NULL;
switch_xml_t tone = NULL, element = NULL;
tone_descriptor_t *descriptor = NULL;
/* create descriptor */
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <descriptor> name\n");
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s\n", name);
if (tone_descriptor_create(&descriptor, name, spandsp_globals.config_pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to allocate tone_descriptor: %s\n", name);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
switch_core_hash_insert(spandsp_globals.tones, name, descriptor);
/* add tones to descriptor */
for (tone = switch_xml_child(xdescriptor, "tone"); tone; tone = switch_xml_next(tone)) {
int id = 0;
tone_name = switch_xml_attr(tone, "name");
if (zstr(tone_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <tone> name for <descriptor> %s\n", name);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
id = tone_descriptor_add_tone(descriptor, tone_name);
if (id == -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unable to add tone_descriptor: %s, tone: %s. (too many tones)\n", name, tone_name);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Adding tone_descriptor: %s, tone: %s(%d)\n", name, tone_name, id);
/* add elements to tone */
for (element = switch_xml_child(tone, "element"); element; element = switch_xml_next(element)) {
const char *freq1_attr = switch_xml_attr(element, "freq1");
const char *freq2_attr = switch_xml_attr(element, "freq2");
const char *min_attr = switch_xml_attr(element, "min");
const char *max_attr = switch_xml_attr(element, "max");
int freq1, freq2, min, max;
if (zstr(freq1_attr)) {
freq1 = 0;
} else {
freq1 = atoi(freq1_attr);
}
if (zstr(freq2_attr)) {
freq2 = 0;
} else {
freq2 = atoi(freq2_attr);
}
if (zstr(min_attr)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Missing min in <element> of <descriptor> %s <tone> %s(%d)\n", name, tone_name, id);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
min = atoi(min_attr);
if (zstr(max_attr)) {
max = 0;
} else {
max = atoi(max_attr);
}
/* check params */
if ((freq1 < 0 || freq2 < 0 || min < 0 || max < 0) || (freq1 == 0 && min == 0 && max == 0)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid element param.\n");
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Adding tone_descriptor: %s, tone: %s(%d), element (%d, %d, %d, %d)\n", name, tone_name, id, freq1, freq2, min, max);
tone_descriptor_add_tone_element(descriptor, id, freq1, freq2, min, max);
}
}
}
}
done:
switch_xml_free(xml);
}
switch_mutex_unlock(spandsp_globals.mutex);
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
{
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
memset(&spandsp_globals, 0, sizeof(spandsp_globals));
spandsp_globals.pool = pool;
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_mutex_init(&spandsp_globals.mutex, SWITCH_MUTEX_NESTED, pool);
SWITCH_ADD_APP(app_interface, "t38_gateway", "Convert to T38 Gateway if tones are heard", "Convert to T38 Gateway if tones are heard",
t38_gateway_function, "", SAF_MEDIA_TAP);
@@ -270,14 +544,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
SWITCH_ADD_APP(app_interface, "spandsp_start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP);
SWITCH_ADD_APP(app_interface, "spandsp_start_fax_detect", "start fax detect", "start fax detect", spandsp_fax_detect_session_function,
"<app>[ <arg>][ <timeout>]", SAF_NONE);
"<app>[ <arg>][ <timeout>][ <tone_type>]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "spandsp_stop_fax_detect", "stop fax detect", "stop fax detect", spandsp_stop_fax_detect_session_function, "", SAF_NONE);
load_configuration(0);
mod_spandsp_fax_load(pool);
mod_spandsp_codecs_load(module_interface, pool);
if (mod_spandsp_dsp_load(module_interface, pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't load or process spandsp.conf, not adding tone_detect applications\n");
} else {
@@ -292,6 +568,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
/* Not such severe to prevent loading */
}
modem_global_init(module_interface, pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mod_spandsp loaded, using spandsp library version [%s]\n", SPANDSP_RELEASE_DATETIME_STRING);
return SWITCH_STATUS_SUCCESS;
@@ -303,6 +582,15 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_spandsp_shutdown)
mod_spandsp_fax_shutdown();
mod_spandsp_dsp_shutdown();
modem_global_shutdown();
if (spandsp_globals.tones) {
switch_core_hash_destroy(&spandsp_globals.tones);
}
if (spandsp_globals.config_pool) {
switch_core_destroy_memory_pool(&spandsp_globals.config_pool);
}
return SWITCH_STATUS_UNLOAD;
}
+67 -1
View File
@@ -42,9 +42,41 @@ typedef HANDLE zap_socket_t;
typedef int zap_socket_t;
#endif
#define MAX_MODEMS 1024
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
#include <spandsp.h>
/* The global stuff */
struct spandsp_globals {
switch_memory_pool_t *pool;
switch_memory_pool_t *config_pool;
switch_mutex_t *mutex;
uint32_t total_sessions;
short int use_ecm;
short int verbose;
short int disable_v17;
short int enable_t38;
short int enable_t38_request;
short int enable_t38_insist;
char *ident;
char *header;
char *timezone;
char *prepend_string;
char *spool;
switch_thread_cond_t *cond;
switch_mutex_t *cond_mutex;
int modem_count;
int modem_verbose;
char *modem_context;
char *modem_dialplan;
switch_hash_t *tones;
int tonedebug;
};
extern struct spandsp_globals spandsp_globals;
typedef enum {
FUNCTION_TX,
@@ -52,6 +84,37 @@ typedef enum {
FUNCTION_GW
} mod_spandsp_fax_application_mode_t;
/******************************************************************************
* TONE DETECTION WITH CADENCE
*/
#define MAX_TONES 32
#define STRLEN 128
/**
* Tone descriptor
*
* Defines a set of tones to look for
*/
struct tone_descriptor {
/** The name of this descriptor set */
const char *name;
/** Describes the tones to watch */
super_tone_rx_descriptor_t *spandsp_tone_descriptor;
/** The mapping of tone id to key */
char tone_keys[MAX_TONES][STRLEN];
int idx;
};
typedef struct tone_descriptor tone_descriptor_t;
switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool);
int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *name);
switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max);
void mod_spandsp_fax_load(switch_memory_pool_t *pool);
switch_status_t mod_spandsp_codecs_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool);
switch_status_t mod_spandsp_dsp_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool);
@@ -70,7 +133,10 @@ switch_status_t callprogress_detector_start(switch_core_session_t *session, cons
switch_status_t callprogress_detector_stop(switch_core_session_t *session);
switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
const char *flags, time_t timeout,
const char *flags, int timeout, int tone_type,
int hits, const char *app, const char *data, switch_tone_detect_callback_t callback);
switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session);
void spanfax_log_message(int level, const char *msg);
switch_status_t load_configuration(switch_bool_t reload);
void mod_spandsp_indicate_data(switch_core_session_t *session, switch_bool_t self, switch_bool_t on);
@@ -155,48 +155,7 @@ switch_status_t spandsp_inband_dtmf_session(switch_core_session_t *session)
/* private channel data */
#define TONE_PRIVATE "mod_tone_detect_bug"
/**
* Module global variables
*/
struct globals {
/** Memory pool */
switch_memory_pool_t *pool;
/** Call progress tones mapped by descriptor name */
switch_hash_t *tones;
/** Default debug level */
int debug;
};
typedef struct globals globals_t;
static globals_t globals;
/******************************************************************************
* TONE DETECTION WITH CADENCE
*/
#define MAX_TONES 32
#define STRLEN 128
/**
* Tone descriptor
*
* Defines a set of tones to look for
*/
struct tone_descriptor {
/** The name of this descriptor set */
const char *name;
/** Describes the tones to watch */
super_tone_rx_descriptor_t *spandsp_tone_descriptor;
/** The mapping of tone id to key */
char tone_keys[MAX_TONES][STRLEN];
int idx;
};
typedef struct tone_descriptor tone_descriptor_t;
static switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool);
static int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *name);
static switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max);
/**
* Tone detector
@@ -232,7 +191,7 @@ static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bu
* @param memory_pool the pool to use
* @return SWITCH_STATUS_SUCCESS if successful
*/
static switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool)
switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, const char *name, switch_memory_pool_t *memory_pool)
{
tone_descriptor_t *ldescriptor = NULL;
ldescriptor = switch_core_alloc(memory_pool, sizeof(tone_descriptor_t));
@@ -253,7 +212,7 @@ static switch_status_t tone_descriptor_create(tone_descriptor_t **descriptor, co
* @param key the tone key - this will be returned by the detector upon match
* @return the tone ID
*/
static int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *key)
int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *key)
{
int id = super_tone_rx_add_tone(descriptor->spandsp_tone_descriptor);
if (id >= MAX_TONES) {
@@ -279,7 +238,7 @@ static int tone_descriptor_add_tone(tone_descriptor_t *descriptor, const char *k
* @param max the maximum tone duration in ms
* @return SWITCH_STATUS_SUCCESS if successful
*/
static switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max)
switch_status_t tone_descriptor_add_tone_element(tone_descriptor_t *descriptor, int tone_id, int freq1, int freq2, int min, int max)
{
if (super_tone_rx_add_element(descriptor->spandsp_tone_descriptor, tone_id, freq1, freq2, min, max) == 0) {
return SWITCH_STATUS_SUCCESS;
@@ -337,7 +296,7 @@ static switch_status_t tone_detector_create(tone_detector_t **detector, tone_des
}
memset(ldetector, 0, sizeof(tone_detector_t));
ldetector->descriptor = descriptor;
ldetector->debug = globals.debug;
ldetector->debug = spandsp_globals.tonedebug;
*detector = ldetector;
return SWITCH_STATUS_SUCCESS;
}
@@ -409,7 +368,7 @@ switch_status_t callprogress_detector_start(switch_core_session_t *session, cons
}
/* find the tone descriptor with the matching name and create the detector */
descriptor = switch_core_hash_find(globals.tones, name);
descriptor = switch_core_hash_find(spandsp_globals.tones, name);
if (!descriptor) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "(%s) no tone descriptor defined with name '%s'. Update configuration. \n", switch_channel_get_name(channel), name);
return SWITCH_STATUS_FALSE;
@@ -509,116 +468,11 @@ switch_status_t callprogress_detector_stop(switch_core_session_t *session)
return SWITCH_STATUS_SUCCESS;
}
/**
* Process configuration file
*/
static switch_status_t do_config(void)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_xml_t cfg = NULL, xml = NULL, callprogress = NULL, xdescriptor = NULL;
if (!(xml = switch_xml_open_cfg("spandsp.conf", &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not open spandsp.conf\n");
status = SWITCH_STATUS_FALSE;
goto done;
}
/* TODO make configuration param */
globals.debug = 1;
/* Configure call progress detector */
if ((callprogress = switch_xml_child(cfg, "descriptors"))) {
for (xdescriptor = switch_xml_child(callprogress, "descriptor"); xdescriptor; xdescriptor = switch_xml_next(xdescriptor)) {
const char *name = switch_xml_attr(xdescriptor, "name");
const char *tone_name = NULL;
switch_xml_t tone = NULL, element = NULL;
tone_descriptor_t *descriptor = NULL;
/* create descriptor */
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <descriptor> name\n");
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s\n", name);
if (tone_descriptor_create(&descriptor, name, globals.pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to allocate tone_descriptor: %s\n", name);
return SWITCH_STATUS_FALSE;
}
switch_core_hash_insert(globals.tones, name, descriptor);
/* add tones to descriptor */
for (tone = switch_xml_child(xdescriptor, "tone"); tone; tone = switch_xml_next(tone)) {
int id = 0;
tone_name = switch_xml_attr(tone, "name");
if (zstr(tone_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing <tone> name for <descriptor> %s\n", name);
return SWITCH_STATUS_FALSE;
}
id = tone_descriptor_add_tone(descriptor, tone_name);
if (id == -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to add tone_descriptor: %s, tone: %s. (too many tones)\n", name, tone_name);
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s, tone: %s(%d)\n", name, tone_name, id);
/* add elements to tone */
for (element = switch_xml_child(tone, "element"); element; element = switch_xml_next(element)) {
const char *freq1_attr = switch_xml_attr(element, "freq1");
const char *freq2_attr = switch_xml_attr(element, "freq2");
const char *min_attr = switch_xml_attr(element, "min");
const char *max_attr = switch_xml_attr(element, "max");
int freq1, freq2, min, max;
if (zstr(freq1_attr)) {
freq1 = 0;
} else {
freq1 = atoi(freq1_attr);
}
if (zstr(freq2_attr)) {
freq2 = 0;
} else {
freq2 = atoi(freq2_attr);
}
if (zstr(min_attr)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing min in <element> of <descriptor> %s <tone> %s(%d)\n", name, tone_name, id);
return SWITCH_STATUS_FALSE;
}
min = atoi(min_attr);
if (zstr(max_attr)) {
max = 0;
} else {
max = atoi(max_attr);
}
/* check params */
if ((freq1 < 0 || freq2 < 0 || min < 0 || max < 0) || (freq1 == 0 && min == 0 && max == 0)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid element param.\n");
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s, tone: %s(%d), element (%d, %d, %d, %d)\n", name, tone_name, id, freq1, freq2, min, max);
tone_descriptor_add_tone_element(descriptor, id, freq1, freq2, min, max);
}
}
}
}
done:
if (xml) {
switch_xml_free(xml);
}
return status;
}
/**
* Called when FreeSWITCH loads the module
*/
switch_status_t mod_spandsp_dsp_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool)
{
memset(&globals, 0, sizeof(globals_t));
globals.pool = pool;
switch_core_hash_init(&globals.tones, globals.pool);
if (do_config() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
@@ -628,7 +482,7 @@ switch_status_t mod_spandsp_dsp_load(switch_loadable_module_interface_t **module
*/
void mod_spandsp_dsp_shutdown(void)
{
switch_core_hash_destroy(&globals.tones);
return;
}
+269 -146
View File
@@ -39,10 +39,19 @@
#define LOCAL_FAX_MAX_DATAGRAM 400
#define MAX_FEC_ENTRIES 4
#define MAX_FEC_SPAN 4
#define DEFAULT_FEC_ENTRIES 3
#define DEFAULT_FEC_SPAN 3
#define SPANDSP_EVENT_TXFAXRESULT "spandsp::txfaxresult"
#define SPANDSP_EVENT_RXFAXRESULT "spandsp::rxfaxresult"
#define SPANDSP_EVENT_TXFAXPAGERESULT "spandsp::txfaxpageresult"
#define SPANDSP_EVENT_RXFAXPAGERESULT "spandsp::rxfaxpageresult"
#define SPANDSP_EVENT_TXFAXNEGOCIATERESULT "spandsp::txfaxnegociateresult"
#define SPANDSP_EVENT_RXFAXNEGOCIATERESULT "spandsp::rxfaxnegociateresult"
/*****************************************************************************
OUR DEFINES AND STRUCTS
*****************************************************************************/
@@ -60,26 +69,6 @@ typedef enum {
T38_MODE_REFUSED = -1,
} t38_mode_t;
/* The global stuff */
static struct {
switch_memory_pool_t *pool;
switch_mutex_t *mutex;
uint32_t total_sessions;
short int use_ecm;
short int verbose;
short int disable_v17;
short int enable_t38;
short int enable_t38_request;
short int enable_t38_insist;
char ident[20];
char header[50];
char *prepend_string;
char *spool;
switch_thread_cond_t *cond;
switch_mutex_t *cond_mutex;
} globals;
struct pvt_s {
switch_core_session_t *session;
@@ -96,6 +85,7 @@ struct pvt_s {
char *filename;
char *ident;
char *header;
char *timezone;
int use_ecm;
int disable_v17;
@@ -128,13 +118,13 @@ static struct {
static void wake_thread(int force)
{
if (force) {
switch_thread_cond_signal(globals.cond);
switch_thread_cond_signal(spandsp_globals.cond);
return;
}
if (switch_mutex_trylock(globals.cond_mutex) == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(globals.cond);
switch_mutex_unlock(globals.cond_mutex);
if (switch_mutex_trylock(spandsp_globals.cond_mutex) == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(spandsp_globals.cond);
switch_mutex_unlock(spandsp_globals.cond_mutex);
}
}
@@ -206,7 +196,7 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
goto end;
}
switch_mutex_lock(globals.cond_mutex);
switch_mutex_lock(spandsp_globals.cond_mutex);
while(t38_state_list.thread_running) {
@@ -214,7 +204,7 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
if (!t38_state_list.head) {
switch_mutex_unlock(t38_state_list.mutex);
switch_thread_cond_wait(globals.cond, globals.cond_mutex);
switch_thread_cond_wait(spandsp_globals.cond, spandsp_globals.cond_mutex);
switch_core_timer_sync(&timer);
continue;
}
@@ -230,7 +220,7 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
switch_core_timer_next(&timer);
}
switch_mutex_unlock(globals.cond_mutex);
switch_mutex_unlock(spandsp_globals.cond_mutex);
end:
@@ -252,9 +242,9 @@ static void launch_timer_thread(void)
switch_threadattr_t *thd_attr = NULL;
switch_threadattr_create(&thd_attr, globals.pool);
switch_threadattr_create(&thd_attr, spandsp_globals.pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&t38_state_list.thread, thd_attr, timer_thread_run, NULL, globals.pool);
switch_thread_create(&t38_state_list.thread, thd_attr, timer_thread_run, NULL, spandsp_globals.pool);
}
@@ -264,12 +254,12 @@ static void launch_timer_thread(void)
static void counter_increment(void)
{
switch_mutex_lock(globals.mutex);
globals.total_sessions++;
switch_mutex_unlock(globals.mutex);
switch_mutex_lock(spandsp_globals.mutex);
spandsp_globals.total_sessions++;
switch_mutex_unlock(spandsp_globals.mutex);
}
static void spanfax_log_message(int level, const char *msg)
void spanfax_log_message(int level, const char *msg)
{
int fs_log_level;
@@ -297,6 +287,170 @@ static void spanfax_log_message(int level, const char *msg)
}
}
static int phase_b_handler(t30_state_t *s, void *user_data, int result)
{
t30_stats_t t30_stats;
switch_core_session_t *session;
switch_channel_t *channel;
const char *local_ident;
const char *far_ident;
char *fax_transfer_rate = NULL;
pvt_t *pvt;
switch_event_t *event;
pvt = (pvt_t *) user_data;
switch_assert(pvt);
session = pvt->session;
switch_assert(session);
channel = switch_core_session_get_channel(session);
switch_assert(channel);
t30_get_transfer_statistics(s, &t30_stats);
local_ident = switch_str_nil(t30_get_tx_ident(s));
far_ident = switch_str_nil(t30_get_rx_ident(s));
fax_transfer_rate = switch_core_session_sprintf(session, "%i", t30_stats.bit_rate);
if (fax_transfer_rate) {
switch_channel_set_variable(channel, "fax_transfer_rate", fax_transfer_rate);
}
switch_channel_set_variable(channel, "fax_ecm_used", (t30_stats.error_correcting_mode) ? "on" : "off");
switch_channel_set_variable(channel, "fax_local_station_id", local_ident);
switch_channel_set_variable(channel, "fax_remote_station_id", far_ident);
switch_channel_set_variable(channel, "fax_remote_country", switch_str_nil(t30_get_rx_country(s)));
switch_channel_set_variable(channel, "fax_remote_vendor", switch_str_nil(t30_get_rx_vendor(s)));
switch_channel_set_variable(channel, "fax_remote_model", switch_str_nil(t30_get_rx_model(s)));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "=== Negotiation Result =======================================================\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote station id: %s\n", far_ident);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local station id: %s\n", local_ident);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer Rate: %i\n", t30_stats.bit_rate);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "ECM status %s\n", (t30_stats.error_correcting_mode) ? "on" : "off");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(s)));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(s)));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(s)));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==============================================================================\n");
switch_channel_execute_on(channel, "execute_on_fax_phase_b");
/* Fire event */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXNEGOCIATERESULT : SPANDSP_EVENT_RXFAXNEGOCIATERESULT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t30_stats.error_correcting_mode) ? "on" : "off");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-station-id", far_ident);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-country", switch_str_nil(t30_get_rx_country(s)));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-vendor", switch_str_nil(t30_get_rx_vendor(s)));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-model", switch_str_nil(t30_get_rx_model(s)));
switch_event_fire(&event);
}
return T30_ERR_OK;
}
static int phase_d_handler(t30_state_t *s, void *user_data, int msg)
{
t4_stats_t t4_stats;
char *fax_image_resolution = NULL;
char *fax_image_size = NULL;
char *fax_image_pixel_size = NULL;
char *fax_bad_rows = NULL;
char *fax_encoding = NULL;
char *fax_longest_bad_row_run = NULL;
char *fax_document_transferred_pages = NULL;
switch_core_session_t *session;
switch_channel_t *channel;
pvt_t *pvt;
switch_event_t *event;
pvt = (pvt_t *) user_data;
switch_assert(pvt);
session = pvt->session;
switch_assert(session);
channel = switch_core_session_get_channel(session);
switch_assert(channel);
if (pvt->app_mode == FUNCTION_TX) {
t4_tx_get_transfer_statistics(&s->t4.tx, &t4_stats);
} else {
t4_rx_get_transfer_statistics(&s->t4.rx, &t4_stats);
}
/* Set Channel Variable */
fax_image_resolution = switch_core_session_sprintf(session, "%ix%i", t4_stats.x_resolution, t4_stats.y_resolution);
if (fax_image_resolution) {
switch_channel_set_variable(channel, "fax_image_resolution", fax_image_resolution);
}
fax_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t4_stats.width, t4_stats.length);
if (fax_image_pixel_size) {
switch_channel_set_variable(channel, "fax_image_pixel_size", fax_image_pixel_size);;
}
fax_image_size = switch_core_session_sprintf(session, "%d", t4_stats.line_image_size);
if (fax_image_size) {
switch_channel_set_variable(channel, "fax_image_size", fax_image_size);
}
fax_bad_rows = switch_core_session_sprintf(session, "%d", t4_stats.bad_rows);
if (fax_bad_rows) {
switch_channel_set_variable(channel, "fax_bad_rows", fax_bad_rows);
}
fax_longest_bad_row_run = switch_core_session_sprintf(session, "%d", t4_stats.longest_bad_row_run);
if (fax_longest_bad_row_run) {
switch_channel_set_variable(channel, "fax_longest_bad_row_run", fax_longest_bad_row_run);
}
fax_encoding = switch_core_session_sprintf(session, "%d", t4_stats.encoding);
if (fax_encoding) {
switch_channel_set_variable(channel, "fax_encoding", fax_encoding);
}
switch_channel_set_variable(channel, "fax_encoding_name", t4_encoding_to_str(t4_stats.encoding));
fax_document_transferred_pages = switch_core_session_sprintf(session, "%d", t4_stats.pages_transferred);
if (fax_document_transferred_pages) {
switch_channel_set_variable(channel, "fax_document_transferred_pages", fax_document_transferred_pages);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==== Page %s===========================================================\n", pvt->app_mode == FUNCTION_TX ? "Sent ====": "Received ");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Page no = %d\n", t4_stats.pages_transferred);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image size = %d x %d pixels\n", t4_stats.width, t4_stats.length);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image resolution = %d/m x %d/m\n", t4_stats.x_resolution, t4_stats.y_resolution);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compression = %s (%d)\n", t4_encoding_to_str(t4_stats.encoding), t4_stats.encoding);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compressed image size = %d bytes\n", t4_stats.line_image_size);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad rows = %d\n", t4_stats.bad_rows);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Longest bad row run = %d\n", t4_stats.longest_bad_row_run);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==============================================================================\n");
switch_channel_execute_on(channel, "execute_on_fax_phase_d");
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXPAGERESULT : SPANDSP_EVENT_RXFAXPAGERESULT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_image_resolution);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-pixel-size", fax_image_pixel_size);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-bad-rows", fax_bad_rows);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-longest-bad-row-run", fax_longest_bad_row_run);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-encoding", fax_encoding);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-encoding-name", t4_encoding_to_str(t4_stats.encoding));
switch_event_fire(&event);
}
return T30_ERR_OK; /* I don't think this does anything */
}
/*
* Called at the end of the document
*/
@@ -316,6 +470,8 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result)
char *fax_transfer_rate = NULL;
char *fax_result_code = NULL;
switch_event_t *event;
const char *var;
char *expanded;
pvt = (pvt_t *) user_data;
switch_assert(pvt);
@@ -432,14 +588,36 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result)
switch_event_fire(&event);
}
if ((var = switch_channel_get_variable(channel, "system_on_fax_result"))) {
expanded = switch_channel_expand_variables(channel, var);
switch_system(expanded, SWITCH_FALSE);
if (expanded != var) {
free(expanded);
}
}
switch_channel_execute_on(channel, "execute_on_fax_result");
if (result == T30_ERR_OK) {
if ((var = switch_channel_get_variable(channel, "system_on_fax_success"))) {
expanded = switch_channel_expand_variables(channel, var);
switch_system(expanded, SWITCH_FALSE);
if (expanded != var) {
free(expanded);
}
}
switch_channel_execute_on(channel, "execute_on_fax_success");
} else {
if ((var = switch_channel_get_variable(channel, "system_on_fax_failure"))) {
expanded = switch_channel_expand_variables(channel, var);
switch_system(expanded, SWITCH_FALSE);
if (expanded != var) {
free(expanded);
}
}
switch_channel_execute_on(channel, "execute_on_fax_failure");
}
}
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
@@ -494,6 +672,9 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
fax_state_t *fax;
t38_terminal_state_t *t38;
t30_state_t *t30;
const char *tmp;
int fec_entries = DEFAULT_FEC_ENTRIES;
int fec_span = DEFAULT_FEC_SPAN;
session = (switch_core_session_t *) pvt->session;
@@ -502,6 +683,13 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
channel = switch_core_session_get_channel(session);
switch_assert(channel);
if ((tmp = switch_channel_get_variable(channel, "t38_gateway_redundancy"))) {
int tmp_value;
tmp_value = atoi(tmp);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FAX changing redundancy from %d:%d to %d:%d\n", fec_span, fec_entries, tmp_value, tmp_value );
fec_entries = tmp_value;
fec_span = tmp_value;
}
switch (trans_mode) {
case AUDIO_MODE:
@@ -562,7 +750,7 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3,
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, fec_span, fec_entries,
(udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
return SWITCH_STATUS_FALSE;
@@ -607,7 +795,7 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
pvt->t38_core = t38_gateway_get_t38_core_state(pvt->t38_gateway_state);
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3,
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, fec_span, fec_entries,
(udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
t38_gateway_free(pvt->t38_gateway_state);
@@ -655,8 +843,12 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
/* All the things which are common to audio and T.38 FAX setup */
t30_set_tx_ident(t30, pvt->ident);
t30_set_tx_page_header_info(t30, pvt->header);
if (pvt->timezone && pvt->timezone[0])
t30_set_tx_page_header_tz(t30, pvt->timezone);
t30_set_phase_e_handler(t30, phase_e_handler, pvt);
t30_set_phase_d_handler(t30, phase_d_handler, pvt);
t30_set_phase_b_handler(t30, phase_b_handler, pvt);
t30_set_supported_image_sizes(t30,
T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
@@ -797,7 +989,7 @@ static t38_mode_t negotiate_t38(pvt_t *pvt)
} else if ((v = switch_channel_get_variable(channel, "fax_enable_t38"))) {
enabled = switch_true(v);
} else {
enabled = globals.enable_t38;
enabled = spandsp_globals.enable_t38;
}
if (!(enabled && t38_options)) {
@@ -831,9 +1023,11 @@ static t38_mode_t negotiate_t38(pvt_t *pvt)
t38_options->T38MaxBitRate = (pvt->disable_v17) ? 9600 : 14400;
/* cisco gets mad when we set this to one in a response where they set it to 0, are we allowed to hardcode this to 1 on responses? */
/*
if (!zstr(t38_options->sdp_o_line) && !switch_stristr("cisco", t38_options->sdp_o_line)) {
t38_options->T38FaxFillBitRemoval = 1;
}
*/
t38_options->T38FaxTranscodingMMR = 0;
t38_options->T38FaxTranscodingJBIG = 0;
@@ -853,7 +1047,7 @@ static t38_mode_t negotiate_t38(pvt_t *pvt)
if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist"))) {
insist = switch_true(v);
} else {
insist = globals.enable_t38_insist;
insist = spandsp_globals.enable_t38_insist;
}
/* This will send the options back in a response */
@@ -883,14 +1077,14 @@ static t38_mode_t request_t38(pvt_t *pvt)
} else if ((v = switch_channel_get_variable(channel, "fax_enable_t38"))) {
enabled = switch_true(v);
} else {
enabled = globals.enable_t38;
enabled = spandsp_globals.enable_t38;
}
if (enabled) {
if ((v = switch_channel_get_variable(channel, "fax_enable_t38_request"))) {
enabled = switch_true(v);
} else {
enabled = globals.enable_t38_request;
enabled = spandsp_globals.enable_t38_request;
}
}
@@ -898,7 +1092,7 @@ static t38_mode_t request_t38(pvt_t *pvt)
if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist"))) {
insist = switch_true(v);
} else {
insist = globals.enable_t38_insist;
insist = spandsp_globals.enable_t38_insist;
}
if ((t38_options = switch_channel_get_private(channel, "t38_options"))) {
@@ -980,19 +1174,19 @@ static pvt_t *pvt_init(switch_core_session_t *session, mod_spandsp_fax_applicati
if ((tmp = switch_channel_get_variable(channel, "fax_use_ecm"))) {
pvt->use_ecm = switch_true(tmp);
} else {
pvt->use_ecm = globals.use_ecm;
pvt->use_ecm = spandsp_globals.use_ecm;
}
if ((tmp = switch_channel_get_variable(channel, "fax_disable_v17"))) {
pvt->disable_v17 = switch_true(tmp);
} else {
pvt->disable_v17 = globals.disable_v17;
pvt->disable_v17 = spandsp_globals.disable_v17;
}
if ((tmp = switch_channel_get_variable(channel, "fax_verbose"))) {
pvt->verbose = switch_true(tmp);
} else {
pvt->verbose = globals.verbose;
pvt->verbose = spandsp_globals.verbose;
}
if ((tmp = switch_channel_get_variable(channel, "fax_force_caller"))) {
@@ -1012,7 +1206,7 @@ static pvt_t *pvt_init(switch_core_session_t *session, mod_spandsp_fax_applicati
switch_safe_free(data);
} else {
pvt->ident = switch_core_session_strdup(session, globals.ident);
pvt->ident = switch_core_session_strdup(session, spandsp_globals.ident);
}
if ((tmp = switch_channel_get_variable(channel, "fax_header"))) {
@@ -1024,7 +1218,19 @@ static pvt_t *pvt_init(switch_core_session_t *session, mod_spandsp_fax_applicati
switch_safe_free(data);
} else {
pvt->header = switch_core_session_strdup(session, globals.header);
pvt->header = switch_core_session_strdup(session, spandsp_globals.header);
}
if ((tmp = switch_channel_get_variable(channel, "fax_timezone"))) {
char *data = NULL;
data = strdup(tmp);
switch_url_decode(data);
pvt->timezone = switch_core_session_strdup(session, data);
switch_safe_free(data);
} else {
pvt->timezone = switch_core_session_strdup(session, spandsp_globals.timezone);
}
if (pvt->app_mode == FUNCTION_TX) {
@@ -1094,10 +1300,10 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
time = switch_time_now();
if (!(prefix = switch_channel_get_variable(channel, "fax_prefix"))) {
prefix = globals.prepend_string;
prefix = spandsp_globals.prepend_string;
}
if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%ld.tif", globals.spool, prefix, globals.total_sessions, time))) {
if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%ld.tif", spandsp_globals.spool, prefix, spandsp_globals.total_sessions, time))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot automatically set fax RX destination file\n");
goto done;
}
@@ -1314,108 +1520,18 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
}
}
/* **************************************************************************
CONFIGURATION
************************************************************************* */
void load_configuration(switch_bool_t reload)
{
switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;
if ((xml = switch_xml_open_cfg("fax.conf", &cfg, NULL))) {
if ((x_lists = switch_xml_child(cfg, "settings"))) {
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
const char *name = switch_xml_attr(x_list, "name");
const char *value = switch_xml_attr(x_list, "value");
if (zstr(name)) {
continue;
}
if (zstr(value)) {
continue;
}
if (!strcmp(name, "use-ecm")) {
if (switch_true(value))
globals.use_ecm = 1;
else
globals.use_ecm = 0;
} else if (!strcmp(name, "verbose")) {
if (switch_true(value))
globals.verbose = 1;
else
globals.verbose = 0;
} else if (!strcmp(name, "disable-v17")) {
if (switch_true(value))
globals.disable_v17 = 1;
else
globals.disable_v17 = 0;
} else if (!strcmp(name, "enable-t38")) {
if (switch_true(value)) {
globals.enable_t38= 1;
} else {
globals.enable_t38 = 0;
}
} else if (!strcmp(name, "enable-t38-request")) {
if (switch_true(value)) {
globals.enable_t38_request = 1;
} else {
globals.enable_t38_request = 0;
}
} else if (!strcmp(name, "ident")) {
strncpy(globals.ident, value, sizeof(globals.ident) - 1);
} else if (!strcmp(name, "header")) {
strncpy(globals.header, value, sizeof(globals.header) - 1);
} else if (!strcmp(name, "spool-dir")) {
globals.spool = switch_core_strdup(globals.pool, value);
} else if (!strcmp(name, "file-prefix")) {
globals.prepend_string = switch_core_strdup(globals.pool, value);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter %s\n", name);
}
}
}
switch_xml_free(xml);
}
}
void mod_spandsp_fax_event_handler(switch_event_t *event)
{
load_configuration(1);
}
void mod_spandsp_fax_load(switch_memory_pool_t *pool)
{
uint32_t sanity = 200;
memset(&globals, 0, sizeof(globals));
memset(&t38_state_list, 0, sizeof(t38_state_list));
globals.pool = pool;
switch_mutex_init(&spandsp_globals.mutex, SWITCH_MUTEX_NESTED, spandsp_globals.pool);
switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, spandsp_globals.pool);
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_mutex_init(&globals.cond_mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_thread_cond_create(&globals.cond, globals.pool);
switch_mutex_init(&spandsp_globals.cond_mutex, SWITCH_MUTEX_NESTED, spandsp_globals.pool);
switch_thread_cond_create(&spandsp_globals.cond, spandsp_globals.pool);
globals.enable_t38 = 1;
globals.total_sessions = 0;
globals.verbose = 1;
globals.use_ecm = 1;
globals.disable_v17 = 0;
globals.prepend_string = switch_core_strdup(globals.pool, "fax");
globals.spool = switch_core_strdup(globals.pool, "/tmp");
strncpy(globals.ident, "SpanDSP Fax Ident", sizeof(globals.ident) - 1);
strncpy(globals.header, "SpanDSP Fax Header", sizeof(globals.header) - 1);
load_configuration(0);
launch_timer_thread();
while(--sanity && !t38_state_list.thread_running) {
@@ -1430,7 +1546,7 @@ void mod_spandsp_fax_shutdown(void)
t38_state_list.thread_running = 0;
wake_thread(1);
switch_thread_join(&tstatus, t38_state_list.thread);
memset(&globals, 0, sizeof(globals));
memset(&spandsp_globals, 0, sizeof(spandsp_globals));
}
static const switch_state_handler_table_t t38_gateway_state_handlers;
@@ -1861,6 +1977,7 @@ typedef struct {
char *data;
char *key;
int up;
int tone_type;
int total_hits;
int hits;
int sleep;
@@ -1910,7 +2027,7 @@ static switch_bool_t tone_detect_callback(switch_media_bug_t *bug, void *user_da
case SWITCH_ABC_TYPE_INIT:
if (cont) {
cont->bug_running = 1;
modem_connect_tones_rx_init(&cont->rx_tones, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
modem_connect_tones_rx_init(&cont->rx_tones, cont->tone_type, NULL, NULL);
}
break;
case SWITCH_ABC_TYPE_CLOSE:
@@ -2018,17 +2135,22 @@ switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session)
}
switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
const char *flags, time_t timeout,
const char *flags, int timeout, int tone_type,
int hits, const char *app, const char *data, switch_tone_detect_callback_t callback)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status;
time_t to = 0;
spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
switch_media_bug_flag_t bflags = 0;
const char *var;
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
if (timeout) {
to = switch_epoch_time_now(NULL) + timeout;
}
if (cont) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max Tones Reached!\n");
return SWITCH_STATUS_FALSE;
@@ -2046,6 +2168,7 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
cont->data = switch_core_session_strdup(session, data);
}
cont->tone_type = tone_type;
cont->callback = callback;
cont->up = 1;
cont->session = session;
@@ -2089,7 +2212,7 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
if ((status = switch_core_media_bug_add(session, "fax_tone_detect", "",
tone_detect_callback, cont, timeout, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
tone_detect_callback, cont, to, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
cont->bug_running = 0;
return status;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,156 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* 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 mod_fax.
*
* The Initial Developer of the Original Code is
* Massimo Cetra <devel@navynet.it>
*
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Brian West <brian@freeswitch.org>
* Anthony Minessale II <anthm@freeswitch.org>
* Steve Underwood <steveu@coppice.org>
* mod_spandsp_modem.h -- Fax modem applications provided by SpanDSP
*
*/
#ifndef WIN32
#include "switch_private.h"
#endif
#if defined(HAVE_OPENPTY) || defined(HAVE_DEV_PTMX) || defined(HAVE_POSIX_OPENPT) || WIN32
#define MODEM_SUPPORT 1
#if !defined(HAVE_POSIX_OPENPT) && !defined(HAVE_DEV_PTMX) && !defined(WIN32)
#define USE_OPENPTY 1
#endif
#ifndef _MOD_SPANDSP_MODEM_H
#define _MOD_SPANDSP_MODEM_H
#include <stdio.h>
#include <string.h>
#ifndef WIN32
#ifdef __APPLE__
#include <util.h>
#include <sys/ioctl.h>
#else
#include <pty.h>
#endif
#include <unistd.h>
#endif
#include <fcntl.h>
#include <errno.h>
#ifndef WIN32
#ifdef __UCLIBC__
#else
#if defined(HAVE_BYTESWAP_H)
#include <byteswap.h>
#elif defined(USE_SYS_ENDIAN_H)
#include <sys/endian.h>
#elif defined (__APPLE__)
#include <libkern/OSByteOrder.h>
#define bswap_16 OSSwapInt16
#define bswap_32 OSSwapInt32
#define bswap_64 OSSwapInt64
#else
#define bswap_16(value) \
((((value) & 0xff) << 8) | ((value) >> 8))
#define bswap_32(value) \
(((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \
(uint32_t)bswap_16((uint16_t)((value) >> 16)))
#define bswap_64(value) \
(((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) \
<< 32) | \
(uint64_t)bswap_32((uint32_t)((value) >> 32)))
#endif
#include <sys/time.h>
#include <sys/signal.h>
#endif
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <stdint.h>
#endif
#include <tiffio.h>
#include <spandsp.h>
typedef enum {
MODEM_STATE_INIT,
MODEM_STATE_ONHOOK,
MODEM_STATE_OFFHOOK,
MODEM_STATE_ACQUIRED,
MODEM_STATE_RINGING,
MODEM_STATE_ANSWERED,
MODEM_STATE_DIALING,
MODEM_STATE_CONNECTED,
MODEM_STATE_HANGUP,
MODEM_STATE_LAST
} modem_state_t;
struct modem;
typedef int (*modem_control_handler_t)(struct modem *, const char *, int);
typedef enum {
MODEM_FLAG_RUNNING = ( 1 << 0),
MODEM_FLAG_XOFF = ( 1 << 1)
} modem_flags;
struct modem {
t31_state_t *t31_state;
char digits[512];
modem_flags flags;
#ifndef WIN32
int master;
#else
HANDLE master;
HANDLE threadAbort;
#endif
int slave;
char *stty;
char devlink[128];
int id;
modem_state_t state;
modem_control_handler_t control_handler;
void *user_data;
switch_mutex_t *mutex;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_time_t last_event;
int slot;
switch_thread_cond_t *cond;
switch_mutex_t *cond_mutex;
};
typedef struct modem modem_t;
char *modem_state2name(int state);
int modem_close(struct modem *fm);
switch_status_t modem_init(struct modem *fm, modem_control_handler_t control_handler);
#endif //MODEM_SUPPORT
switch_status_t modem_global_init(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool);
void modem_global_shutdown(void);
#endif //_MOD_SPANDSP_MODEM_H
@@ -30,6 +30,9 @@
*/
#include <switch.h>
#define VALET_EVENT "valet_parking::info"
#define VALET_PROTO "park"
#define TOKEN_FREQ 5
/* Prototypes */
SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load);
@@ -42,6 +45,8 @@ typedef struct {
char ext[256];
char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
time_t timeout;
int bridged;
time_t start_time;
} valet_token_t;
typedef struct {
@@ -49,18 +54,21 @@ typedef struct {
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
time_t last_timeout_check;
char *name;
} valet_lot_t;
static valet_lot_t globals = { 0 };
static valet_lot_t *valet_find_lot(const char *name)
static valet_lot_t *valet_find_lot(const char *name, switch_bool_t create)
{
valet_lot_t *lot;
switch_mutex_lock(globals.mutex);
if (!(lot = switch_core_hash_find(globals.hash, name))) {
lot = switch_core_hash_find(globals.hash, name);
if (!lot && create) {
switch_zmalloc(lot, sizeof(*lot));
lot->name = strdup(name);
switch_mutex_init(&lot->mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_core_hash_init(&lot->hash, NULL);
switch_core_hash_insert(globals.hash, name, lot);
@@ -105,7 +113,7 @@ static void check_timeouts(void)
now = switch_epoch_time_now(NULL);
switch_mutex_lock(globals.mutex);
if (now - globals.last_timeout_check < 30) {
if (now - globals.last_timeout_check < TOKEN_FREQ) {
switch_mutex_unlock(globals.mutex);
return;
}
@@ -121,7 +129,7 @@ static void check_timeouts(void)
if (matches) {
for (m = matches->head; m; m = m->next) {
lot = valet_find_lot(m->val);
lot = valet_find_lot(m->val, SWITCH_FALSE);
switch_mutex_lock(lot->mutex);
top:
@@ -130,6 +138,7 @@ static void check_timeouts(void)
switch_hash_this(i_hi, &i_var, NULL, &i_val);
i_ext = (char *) i_var;
token = (valet_token_t *) i_val;
if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) {
switch_core_hash_delete(lot->hash, i_ext);
switch_safe_free(token);
@@ -145,6 +154,34 @@ static void check_timeouts(void)
}
static int find_longest(valet_lot_t *lot, int min, int max)
{
switch_hash_index_t *i_hi;
const void *i_var;
void *i_val;
valet_token_t *token;
int longest = 0, cur = 0, longest_ext = 0;
time_t now = switch_epoch_time_now(NULL);
switch_mutex_lock(lot->mutex);
for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) {
int i;
switch_hash_this(i_hi, &i_var, NULL, &i_val);
token = (valet_token_t *) i_val;
cur = (now - token->start_time);
i = atoi(token->ext);
if (cur > longest && i >= min && i <= max) {
longest = cur;
longest_ext = i;
}
}
switch_mutex_unlock(lot->mutex);
return longest_ext;
}
static valet_token_t *next_id(switch_core_session_t *session, valet_lot_t *lot, int min, int max, int in)
{
int i, r = 0;
@@ -156,11 +193,31 @@ static valet_token_t *next_id(switch_core_session_t *session, valet_lot_t *lot,
}
switch_mutex_lock(globals.mutex);
if (!in) {
int longest = find_longest(lot, min, max);
if (longest > 0) {
switch_snprintf(buf, sizeof(buf), "%d", longest);
switch_mutex_lock(lot->mutex);
token = (valet_token_t *) switch_core_hash_find(lot->hash, buf);
switch_mutex_unlock(lot->mutex);
if (token) {
goto end;
}
}
}
for (i = min; (i < max || max == 0); i++) {
switch_snprintf(buf, sizeof(buf), "%d", i);
switch_mutex_lock(lot->mutex);
token = (valet_token_t *) switch_core_hash_find(lot->hash, buf);
if ((in && !token) || (!in && token && !token->timeout)) {
switch_mutex_unlock(lot->mutex);
if ((!in && token && !token->timeout)) {
goto end;
}
if (in && !token) {
r = i;
break;
}
@@ -173,14 +230,169 @@ static valet_token_t *next_id(switch_core_session_t *session, valet_lot_t *lot,
switch_zmalloc(token, sizeof(*token));
switch_set_string(token->uuid, switch_core_session_get_uuid(session));
switch_set_string(token->ext, buf);
token->start_time = switch_epoch_time_now(NULL);
switch_mutex_lock(lot->mutex);
switch_core_hash_insert(lot->hash, buf, token);
switch_mutex_unlock(lot->mutex);
}
end:
switch_mutex_unlock(globals.mutex);
return token;
}
static int valet_lot_count(valet_lot_t *lot)
{
switch_hash_index_t *i_hi;
const void *i_var;
void *i_val;
valet_token_t *token;
int count = 0;
time_t now;
now = switch_epoch_time_now(NULL);
switch_mutex_lock(lot->mutex);
for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) {
switch_hash_this(i_hi, &i_var, NULL, &i_val);
token = (valet_token_t *) i_val;
if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) {
continue;
}
count++;
}
switch_mutex_unlock(lot->mutex);
return count;
}
static int EC = 0;
static void valet_send_presence(const char *lot_name, valet_lot_t *lot, valet_token_t *token, switch_bool_t in)
{
char *domain_name, *dup_lot_name = NULL, *dup_domain_name = NULL;
switch_event_t *event;
int count;
dup_lot_name = strdup(lot_name);
lot_name = dup_lot_name;
if ((domain_name = strchr(dup_lot_name, '@'))) {
*domain_name++ = '\0';
}
if (zstr(domain_name)) {
dup_domain_name = switch_core_get_variable_dup("domain");
domain_name = dup_domain_name;
}
if (zstr(domain_name)) {
domain_name = "cluecon.com";
}
count = valet_lot_count(lot);
if (count > 0) {
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d caller%s)", count, count == 1 ? "" : "s");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "active");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
switch_event_fire(&event);
}
} else {
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
switch_event_fire(&event);
}
}
if (in) {
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", token->ext);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", token->ext, domain_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", token->bridged == 0 ? "Holding" : "Active");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "active");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", token->ext);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", token->bridged == 0 ? "outbound" : "inbound");
switch_event_fire(&event);
}
} else {
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", token->ext);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", token->ext, domain_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", token->ext);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
switch_event_fire(&event);
}
}
switch_safe_free(dup_domain_name);
switch_safe_free(dup_lot_name);
}
struct read_frame_data {
const char *dp;
const char *exten;
const char *context;
long to;
};
static switch_status_t read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
{
struct read_frame_data *rf = (struct read_frame_data *) user_data;
if (--rf->to <= 0) {
rf->to = -1;
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS;
}
#define VALET_APP_SYNTAX "<lotname> <extension>|[ask [<min>] [<max>] [<to>] [<prompt>]|auto in [min] [max]]"
SWITCH_STANDARD_APP(valet_parking_function)
@@ -193,7 +405,8 @@ SWITCH_STANDARD_APP(valet_parking_function)
int is_auto = 0, play_announce = 1;
const char *var;
valet_token_t *token = NULL;
struct read_frame_data rf = { 0 };
long to_val = 0;
check_timeouts();
@@ -213,15 +426,16 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_input_args_t args = { 0 };
char dbuf[10];
char *dest;
int in = -1;
lot = valet_find_lot(lot_name);
lot = valet_find_lot(lot_name, SWITCH_TRUE);
switch_assert(lot);
if (!strcasecmp(ext, "auto")) {
const char *io = argv[2];
const char *min = argv[3];
const char *max = argv[4];
int min_i, max_i, in = -1;
int min_i, max_i;
if (argc < 5) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", VALET_APP_SYNTAX);
@@ -239,7 +453,6 @@ SWITCH_STANDARD_APP(valet_parking_function)
if (in < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", VALET_APP_SYNTAX);
switch_mutex_unlock(lot->mutex);
return;
}
@@ -248,12 +461,13 @@ SWITCH_STANDARD_APP(valet_parking_function)
if (!(token = next_id(session, lot, min_i, max_i, in))) {
switch_ivr_phrase_macro(session, in ? "valet_lot_full" : "valet_lot_empty", "", NULL, NULL);
switch_mutex_unlock(lot->mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s lot is %s.\n", switch_channel_get_name(channel), in ? "full" : "empty");
return;
}
switch_snprintf(dtmf_buf, sizeof(dtmf_buf), "%s", token->ext);
ext = dtmf_buf;
} else if (!strcasecmp(ext, "ask")) {
const char *prompt = "ivr/ivr-enter_ext_pound.wav";
int min = 1;
@@ -298,9 +512,15 @@ SWITCH_STANDARD_APP(valet_parking_function)
}
}
if (!token) {
switch_mutex_lock(lot->mutex);
if ((token = (valet_token_t *) switch_core_hash_find(lot->hash, ext))) {
if (!token || !in) {
if (!token) {
switch_mutex_lock(lot->mutex);
token = (valet_token_t *) switch_core_hash_find(lot->hash, ext);
switch_mutex_unlock(lot->mutex);
}
if (token && !token->bridged) {
switch_core_session_t *b_session;
if (token->timeout) {
@@ -329,18 +549,29 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_event_fire(&event);
switch_core_session_rwunlock(b_session);
token->timeout = 0;
token->bridged = 1;
switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), token->uuid);
switch_mutex_unlock(lot->mutex);
return;
}
}
}
token = NULL;
switch_zmalloc(token, sizeof(*token));
if (token) {
switch_mutex_lock(lot->mutex);
switch_core_hash_delete(lot->hash, token->ext);
switch_mutex_unlock(lot->mutex);
memset(token, 0, sizeof(*token));
} else {
switch_zmalloc(token, sizeof(*token));
}
switch_set_string(token->uuid, switch_core_session_get_uuid(session));
switch_set_string(token->ext, ext);
token->start_time = switch_epoch_time_now(NULL);
switch_mutex_lock(lot->mutex);
switch_core_hash_insert(lot->hash, ext, token);
switch_mutex_unlock(lot->mutex);
}
if (!(tmp = switch_channel_get_variable(channel, "valet_hold_music"))) {
@@ -367,13 +598,12 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_core_session_t *b_session;
if ((b_session = switch_core_session_locate(uuid))) {
token->timeout = switch_epoch_time_now(NULL) + 10;
token->timeout = switch_epoch_time_now(NULL) + TOKEN_FREQ;
if (play_announce) {
switch_ivr_sleep(session, 1500, SWITCH_TRUE, NULL);
switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL);
}
switch_ivr_session_transfer(b_session, dest, "inline", NULL);
switch_mutex_unlock(lot->mutex);
switch_core_session_rwunlock(b_session);
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
goto end;
@@ -395,23 +625,61 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_event_fire(&event);
}
valet_send_presence(lot_name, lot, token, SWITCH_TRUE);
if ((rf.exten = switch_channel_get_variable(channel, "valet_parking_orbit_exten"))) {
to_val = 60;
}
if ((var = switch_channel_get_variable(channel, "valet_parking_timeout"))) {
long tmp = atol(var);
if (tmp > 0) {
to_val = tmp;
}
}
if (to_val) {
switch_codec_implementation_t read_impl;
switch_core_session_get_read_impl(session, &read_impl);
rf.to = (1000 / (read_impl.microseconds_per_packet / 1000)) * to_val;
rf.dp = switch_channel_get_variable(channel, "valet_parking_orbit_dialplan");
rf.context = switch_channel_get_variable(channel, "valet_parking_orbit_context");
}
args.input_callback = valet_on_dtmf;
args.buf = dbuf;
args.buflen = sizeof(dbuf);
switch_mutex_unlock(lot->mutex);
if (rf.to) {
args.read_frame_callback = read_frame_callback;
args.user_data = &rf;
}
while(switch_channel_ready(channel)) {
switch_status_t pstatus = switch_ivr_play_file(session, NULL, music, &args);
if (rf.to == -1) {
if (!zstr(rf.exten)) {
switch_ivr_session_transfer(session, rf.exten, rf.dp, rf.context);
}
break;
}
if (pstatus == SWITCH_STATUS_BREAK || pstatus == SWITCH_STATUS_TIMEOUT) {
break;
}
}
if (token) {
token->timeout = 1;
valet_send_presence(lot_name, lot, token, SWITCH_FALSE);
token = NULL;
}
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext);
@@ -428,7 +696,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
if (token) {
token->timeout = 1;
}
}
SWITCH_STANDARD_API(valet_info_function)
@@ -447,7 +715,6 @@ SWITCH_STANDARD_API(valet_info_function)
const void *i_var;
void *i_val;
char *i_ext;
char *i_uuid;
switch_hash_this(hi, &var, NULL, &val);
name = (char *) var;
@@ -458,12 +725,20 @@ SWITCH_STANDARD_API(valet_info_function)
stream->write_function(stream, " <lot name=\"%s\">\n", name);
switch_mutex_lock(lot->mutex);
for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) {
valet_token_t *token;
switch_hash_this(i_hi, &i_var, NULL, &i_val);
i_ext = (char *) i_var;
i_uuid = (char *) i_val;
stream->write_function(stream, " <extension uuid=\"%s\">%s</extension>\n", i_uuid, i_ext);
token = (valet_token_t *) i_val;
if (!token->timeout) {
stream->write_function(stream, " <extension uuid=\"%s\">%s</extension>\n", token->uuid, i_ext);
}
}
switch_mutex_unlock(lot->mutex);
stream->write_function(stream, " </lot>\n");
}
@@ -474,6 +749,143 @@ SWITCH_STANDARD_API(valet_info_function)
return SWITCH_STATUS_SUCCESS;
}
static void pres_event_handler(switch_event_t *event)
{
char *to = switch_event_get_header(event, "to");
char *dup_to = NULL, *lot_name, *dup_lot_name = NULL, *domain_name;
valet_lot_t *lot;
int found = 0;
if (!to || strncasecmp(to, "park+", 5) || !strchr(to, '@')) {
return;
}
if (!(dup_to = strdup(to))) {
return;
}
lot_name = dup_to + 5;
if ((domain_name = strchr(lot_name, '@'))) {
*domain_name++ = '\0';
}
dup_lot_name = switch_mprintf("%q@%q", lot_name, domain_name);
if ((lot = valet_find_lot(lot_name, SWITCH_FALSE)) || (dup_lot_name && (lot = valet_find_lot(dup_lot_name, SWITCH_FALSE)))) {
int count = valet_lot_count(lot);
if (count) {
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d caller%s)", count, count == 1 ? "" : "s");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "active");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
switch_event_fire(&event);
}
found++;
}
} else {
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
switch_event_fire(&event);
}
}
} else {
switch_console_callback_match_t *matches = NULL;
switch_console_callback_match_node_t *m;
switch_hash_index_t *hi;
const void *var;
void *val;
const char *nvar;
switch_mutex_lock(globals.mutex);
for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
nvar = (const char *) var;
if (!strchr(nvar, '@') || switch_stristr(domain_name, nvar)) {
switch_console_push_match(&matches, nvar);
}
}
switch_mutex_unlock(globals.mutex);
if (matches) {
valet_token_t *token;
for (m = matches->head; !found && m; m = m->next) {
lot = valet_find_lot(m->val, SWITCH_FALSE);
switch_mutex_lock(lot->mutex);
if ((token = (valet_token_t *) switch_core_hash_find(lot->hash, lot_name)) && !token->timeout) {
found++;
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", token->bridged == 0 ? "Holding" : "Active");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", token->bridged == 0 ? "early" : "confirmed");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", token->bridged == 0 ? "outbound" : "inbound");
switch_event_fire(&event);
}
}
switch_mutex_unlock(lot->mutex);
}
}
}
if (!found && switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
switch_event_fire(&event);
}
switch_safe_free(dup_to);
switch_safe_free(dup_lot_name);
}
/* Macro expands to: switch_status_t mod_valet_parking_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load)
{
@@ -486,6 +898,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load)
return SWITCH_STATUS_TERM;
}
switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, pres_event_handler, NULL);
memset(&globals, 0, sizeof(globals));
globals.pool = pool;
@@ -303,6 +303,8 @@ static char *vm_index_list[] = {
"create index voicemail_msgs_idx5 on voicemail_msgs(in_folder)",
"create index voicemail_msgs_idx6 on voicemail_msgs(read_flags)",
"create index voicemail_msgs_idx7 on voicemail_msgs(forwarded_by)",
"create index voicemail_msgs_idx8 on voicemail_msgs(read_epoch)",
"create index voicemail_msgs_idx9 on voicemail_msgs(flags)",
"create index voicemail_prefs_idx1 on voicemail_prefs(username)",
"create index voicemail_prefs_idx2 on voicemail_prefs(domain)",
NULL
@@ -625,7 +627,7 @@ vm_profile_t *profile_set_config(vm_profile_t *profile)
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "email_email-from", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->email_from, NULL, &profile->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "email_date-fmt", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->date_fmt, "%A, %B %d %Y, %I %M %p", &profile->config_str_pool, NULL, NULL);
&profile->date_fmt, "%A, %B %d %Y, %I:%M %p", &profile->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "odbc-dsn", SWITCH_CONFIG_STRING, 0, &profile->odbc_dsn, NULL, &profile->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM_CALLBACK(profile->config[i++], "email_template-file", SWITCH_CONFIG_CUSTOM, CONFIG_RELOADABLE,
NULL, NULL, profile, vm_config_email_callback, NULL, NULL);
@@ -911,8 +913,17 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
if (dtmf->digit == *cc->profile->rew_key) {
int samps = -48000;
switch_core_file_seek(fh, &pos, samps, SEEK_CUR);
return SWITCH_STATUS_SUCCESS;
int target_pos = fh->offset_pos + samps;
if (target_pos < 1) {
/* too close to beginning of the file, just restart instead of rewind */
unsigned int seekpos = 0;
fh->speed = 0;
switch_core_file_seek(fh, &seekpos, 0, SEEK_SET);
return SWITCH_STATUS_SUCCESS;
} else {
switch_core_file_seek(fh, &pos, samps, SEEK_CUR);
return SWITCH_STATUS_SUCCESS;
}
}
}
break;
@@ -1684,7 +1695,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
switch_time_t l_duration = 0;
switch_core_time_duration_t duration;
char duration_str[80];
char *formatted_cid_num = NULL;
if (!strcasecmp(cbt->read_flags, URGENT_FLAG_STRING)) {
priority = 1;
}
@@ -1695,6 +1706,8 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
switch_time_exp_lt(&tm, switch_time_make(atol(cbt->created_epoch), 0));
switch_strftime(date, &retsize, sizeof(date), profile->date_fmt, &tm);
formatted_cid_num = switch_format_number(cbt->cid_number);
switch_snprintf(tmp, sizeof(tmp), "%d", total_new_messages);
switch_channel_set_variable(channel, "voicemail_total_new_messages", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", total_saved_messages);
@@ -1707,6 +1720,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
switch_channel_set_variable(channel, "voicemail_account", cbt->user);
switch_channel_set_variable(channel, "voicemail_domain", cbt->domain);
switch_channel_set_variable(channel, "voicemail_caller_id_number", cbt->cid_number);
switch_channel_set_variable(channel, "voicemail_formatted_caller_id_number", formatted_cid_num);
switch_channel_set_variable(channel, "voicemail_caller_id_name", cbt->cid_name);
switch_channel_set_variable(channel, "voicemail_file_path", cbt->file_path);
switch_channel_set_variable(channel, "voicemail_read_flags", cbt->read_flags);
@@ -1714,6 +1728,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
switch_snprintf(tmp, sizeof(tmp), "%d", priority);
switch_channel_set_variable(channel, "voicemail_priority", tmp);
message_len = atoi(cbt->message_len);
switch_safe_free(formatted_cid_num);
l_duration = switch_time_make(atol(cbt->message_len), 0);
switch_core_measure_time(l_duration, &duration);
@@ -1847,6 +1862,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
switch_input_args_t args = { 0 };
const char *caller_id_name = NULL;
const char *caller_id_number = NULL;
int auth_only = 0, authed = 0;
if (!(caller_id_name = switch_channel_get_variable(channel, "effective_caller_id_name"))) {
caller_id_name = caller_profile->caller_id_name;
@@ -1856,6 +1872,13 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
caller_id_number = caller_profile->caller_id_number;
}
if (auth == 2) {
auth_only = 1;
auth = 0;
} else {
auth_only = switch_true(switch_channel_get_variable(channel, "vm_auth_only"));
}
timeout = profile->digit_timeout;
attempts = profile->max_login_attempts;
status = switch_ivr_phrase_macro(session, VM_HELLO_MACRO, NULL, NULL, &args);
@@ -1946,7 +1969,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
if (!informed) {
switch_snprintf(msg_count, sizeof(msg_count), "0:new");
TRY_CODE(switch_ivr_phrase_macro(session, VM_MESSAGE_COUNT_MACRO, msg_count, NULL, &folder_args));
switch_snprintf(msg_count, sizeof(msg_count), "%d:saved", total_saved_messages + total_saved_urgent_messages);
switch_snprintf(msg_count, sizeof(msg_count), "%d:saved", total_saved_messages);
TRY_CODE(switch_ivr_phrase_macro(session, VM_MESSAGE_COUNT_MACRO, msg_count, NULL, &folder_args));
informed++;
}
@@ -2016,10 +2039,10 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
"username='%s' and domain='%s' and flags='save'",
(long) switch_epoch_time_now(NULL), myid, domain_name);
vm_execute_sql(profile, sql, profile->mutex);
switch_snprintf(sql, sizeof(sql), "select file_path from voicemail_msgs where username='%s' and domain='%s' and flags='delete'", myid,
switch_snprintfv(sql, sizeof(sql), "select file_path from voicemail_msgs where username='%q' and domain='%q' and flags='delete'", myid,
domain_name);
vm_execute_sql_callback(profile, profile->mutex, sql, unlink_callback, NULL);
switch_snprintf(sql, sizeof(sql), "delete from voicemail_msgs where username='%s' and domain='%s' and flags='delete'", myid, domain_name);
switch_snprintfv(sql, sizeof(sql), "delete from voicemail_msgs where username='%q' and domain='%q' and flags='delete'", myid, domain_name);
vm_execute_sql(profile, sql, profile->mutex);
vm_check_state = VM_CHECK_FOLDER_SUMMARY;
@@ -2265,6 +2288,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
switch_event_create(&params, SWITCH_EVENT_GENERAL);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "voicemail-lookup");
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "destination_number", caller_profile->destination_number);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "caller_id_number", caller_id_number);
@@ -2305,7 +2329,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
}
thepass = thehash = NULL;
switch_snprintf(sql, sizeof(sql), "select * from voicemail_prefs where username='%s' and domain='%s'", myid, domain_name);
switch_snprintfv(sql, sizeof(sql), "select * from voicemail_prefs where username='%q' and domain='%q'", myid, domain_name);
vm_execute_sql_callback(profile, profile->mutex, sql, prefs_callback, &cbt);
x_params = switch_xml_child(x_user, "variables");
@@ -2431,6 +2455,10 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
}
}
authed = 1;
if (auth_only) goto end;
vm_check_state = VM_CHECK_FOLDER_SUMMARY;
} else {
goto failed;
@@ -2463,7 +2491,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
tmp_file_path = NULL;
}
if (switch_channel_ready(channel)) {
if (switch_channel_ready(channel) && (!auth_only || !authed)) {
if (failed) {
status = switch_ivr_phrase_macro(session, VM_ABORT_MACRO, NULL, NULL, NULL);
}
@@ -2474,6 +2502,15 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
switch_xml_free(x_user);
x_user = NULL;
}
if (auth_only) {
if (authed) {
switch_channel_set_variable(channel, "user_pin_authenticated", "true");
} else {
switch_channel_hangup(channel, SWITCH_CAUSE_USER_CHALLENGE);
}
}
}
@@ -2677,6 +2714,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
switch_time_exp_t tm;
char date[80] = "";
switch_size_t retsize;
char *formatted_cid_num = NULL;
message_count(profile, myid, domain_name, myfolder, &total_new_messages, &total_saved_messages,
&total_new_urgent_messages, &total_saved_urgent_messages);
@@ -2686,6 +2724,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
switch_strftime(date, &retsize, sizeof(date), profile->date_fmt, &tm);
}
formatted_cid_num = switch_format_number(caller_id_number);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_current_folder", myfolder);
switch_snprintf(tmpvar, sizeof(tmpvar), "%d", total_new_messages);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_total_new_messages", tmpvar);
@@ -2698,11 +2737,14 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_account", myid);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_domain", domain_name);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_caller_id_number", caller_id_number);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_formatted_caller_id_number", formatted_cid_num);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_caller_id_name", caller_id_name);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_file_path", file_path);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_read_flags", read_flags);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_time", date);
switch_safe_free(formatted_cid_num);
switch_snprintf(tmpvar, sizeof(tmpvar), "%d", priority);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_priority", tmpvar);
if (vm_email) {
@@ -3129,10 +3171,10 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
int ok = 1;
switch_event_t *locate_params = NULL;
const char *email_addr = NULL;
switch_event_create(&locate_params, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(locate_params);
switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "action", "voicemail-lookup");
if (switch_xml_locate_user_merged("id", id, domain_name, switch_channel_get_variable(channel, "network_addr"),
&x_user, locate_params) == SWITCH_STATUS_SUCCESS) {
@@ -3225,7 +3267,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
goto end;
}
switch_snprintf(sql, sizeof(sql), "select * from voicemail_prefs where username='%s' and domain='%s'", id, domain_name);
switch_snprintfv(sql, sizeof(sql), "select * from voicemail_prefs where username='%q' and domain='%q'", id, domain_name);
vm_execute_sql_callback(profile, profile->mutex, sql, prefs_callback, &cbt);
if (!vm_ext) {
@@ -3327,7 +3369,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
callback.buf = disk_usage;
callback.len = sizeof(disk_usage);
switch_snprintf(sqlstmt, sizeof(sqlstmt), "select sum(message_len) from voicemail_msgs where username='%s' and domain='%s'", id, domain_name);
switch_snprintfv(sqlstmt, sizeof(sqlstmt), "select sum(message_len) from voicemail_msgs where username='%q' and domain='%q'", id, domain_name);
vm_execute_sql_callback(profile, profile->mutex, sqlstmt, sql2str_callback, &callback);
if (atoi(disk_usage) >= disk_quota) {
@@ -3441,6 +3483,9 @@ SWITCH_STANDARD_APP(voicemail_function)
} else if (argv[x] && !strcasecmp(argv[x], "auth")) {
auth++;
x++;
} else if (argv[x] && !strcasecmp(argv[x], "auth_only")) {
auth = 2;
x++;
} else {
break;
}
@@ -3633,7 +3678,7 @@ SWITCH_STANDARD_API(prefs_api_function)
}
switch_snprintf(sql, sizeof(sql), "select * from voicemail_prefs where username='%s' and domain='%s'", id, domain);
switch_snprintfv(sql, sizeof(sql), "select * from voicemail_prefs where username='%q' and domain='%q'", id, domain);
vm_execute_sql_callback(profile, profile->mutex, sql, prefs_callback, &cbt);
if (!strcasecmp(how, "greeting_path")) {
@@ -4895,13 +4940,6 @@ SWITCH_STANDARD_API(vm_fsdb_pref_recname_set_function)
vm_execute_sql2str(profile, profile->mutex, sql, res, sizeof(res));
switch_safe_free(sql);
if (atoi(res) == 0) {
sql = switch_mprintf("INSERT INTO voicemail_prefs (username, domain, name_path) VALUES('%q', '%q', '%q')", id, domain, file_path);
} else {
sql = switch_mprintf("UPDATE voicemail_prefs SET name_path = '%q' WHERE username = '%q' AND domain = '%q'", file_path, id, domain);
}
vm_execute_sql(profile, sql, profile->mutex);
switch_safe_free(sql);
{
char *dir_path = switch_core_sprintf(pool, "%s%svoicemail%s%s%s%s%s%s", SWITCH_GLOBAL_dirs.storage_dir,
SWITCH_PATH_SEPARATOR,
@@ -4916,6 +4954,14 @@ SWITCH_STANDARD_API(vm_fsdb_pref_recname_set_function)
}
switch_file_rename(file_path, final_file_path, pool);
if (atoi(res) == 0) {
sql = switch_mprintf("INSERT INTO voicemail_prefs (username, domain, name_path) VALUES('%q', '%q', '%q')", id, domain, final_file_path);
} else {
sql = switch_mprintf("UPDATE voicemail_prefs SET name_path = '%q' WHERE username = '%q' AND domain = '%q'", final_file_path, id, domain);
}
vm_execute_sql(profile, sql, profile->mutex);
switch_safe_free(sql);
}
profile_rwunlock(profile);
@@ -4990,14 +5036,14 @@ done:
/* Message API */
#define VM_FSDB_MSG_LIST_USAGE "<format> <profile> <domain> <user>"
#define VM_FSDB_MSG_LIST_USAGE "<format> <profile> <domain> <user> <folder> <filter>"
SWITCH_STANDARD_API(vm_fsdb_msg_list_function)
{
char *sql;
msg_lst_callback_t cbt = { 0 };
char *ebuf = NULL;
const char *id = NULL, *domain = NULL, *profile_name = NULL;
const char *id = NULL, *domain = NULL, *profile_name = NULL, *folder = NULL, *msg_type = NULL;
vm_profile_t *profile = NULL;
char *argv[6] = { 0 };
@@ -5018,8 +5064,12 @@ SWITCH_STANDARD_API(vm_fsdb_msg_list_function)
domain = argv[2];
if (argv[3])
id = argv[3];
if (argv[4])
folder = argv[4]; /* TODO add Support */
if (argv[5])
msg_type = argv[5];
if (!profile_name || !domain || !id) {
if (!profile_name || !domain || !id || !folder || !msg_type) {
stream->write_function(stream, "-ERR Missing Arguments\n");
goto done;
}
@@ -5028,8 +5078,15 @@ SWITCH_STANDARD_API(vm_fsdb_msg_list_function)
stream->write_function(stream, "-ERR Profile not found\n");
goto done;
}
sql = switch_mprintf("SELECT uuid FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND read_epoch = 0 ORDER BY read_flags, created_epoch", id, domain);
if (!strcasecmp(msg_type, "not-read")) {
sql = switch_mprintf("SELECT uuid FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND read_epoch = 0 ORDER BY read_flags, created_epoch", id, domain);
} else if (!strcasecmp(msg_type, "new")) {
sql = switch_mprintf("SELECT uuid FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND flags='' ORDER BY read_flags, created_epoch", id, domain);
} else if (!strcasecmp(msg_type, "save")) {
sql = switch_mprintf("SELECT uuid FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND flags='save' ORDER BY read_flags, created_epoch", id, domain);
} else {
sql = switch_mprintf("SELECT uuid FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND read_epoch != 0 ORDER BY read_flags, created_epoch", id, domain);
}
memset(&cbt, 0, sizeof(cbt));
switch_event_create(&cbt.my_params, SWITCH_EVENT_REQUEST_PARAMS);
@@ -5529,7 +5586,7 @@ done:
return SWITCH_STATUS_SUCCESS;
}
#define VM_FSDB_MSG_COUNT_USAGE "<format> <profile> <domain> <user>"
#define VM_FSDB_MSG_COUNT_USAGE "<format> <profile> <domain> <user> <folder>"
SWITCH_STANDARD_API(vm_fsdb_msg_count_function)
{
char *sql;
@@ -5537,7 +5594,7 @@ SWITCH_STANDARD_API(vm_fsdb_msg_count_function)
switch_event_t *my_params = NULL;
char *ebuf = NULL;
const char *id = NULL, *domain = NULL, *profile_name = NULL;
const char *id = NULL, *domain = NULL, *profile_name = NULL, *folder = NULL;
vm_profile_t *profile = NULL;
char *argv[6] = { 0 };
@@ -5558,8 +5615,10 @@ SWITCH_STANDARD_API(vm_fsdb_msg_count_function)
domain = argv[2];
if (argv[3])
id = argv[3];
if (argv[4])
folder = argv[4];
if (!profile_name || !domain || !id) {
if (!profile_name || !domain || !id || !folder) {
stream->write_function(stream, "-ERR Missing Arguments\n");
goto done;
}
@@ -5570,11 +5629,11 @@ SWITCH_STANDARD_API(vm_fsdb_msg_count_function)
}
sql = switch_mprintf(
"SELECT 1, read_flags, count(read_epoch) FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND in_folder = '%q' AND read_epoch = 0 GROUP BY read_flags "
"SELECT 1, read_flags, count(read_epoch) FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND in_folder = '%q' AND flags = '' AND in_folder = '%q' GROUP BY read_flags "
"UNION "
"SELECT 0, read_flags, count(read_epoch) FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND in_folder = '%q' AND read_epoch <> 0 GROUP BY read_flags;",
id, domain, "inbox",
id, domain, "inbox");
"SELECT 0, read_flags, count(read_epoch) FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND in_folder = '%q' AND flags = 'save' AND in_folder= '%q' GROUP BY read_flags;",
id, domain, "inbox", folder,
id, domain, "inbox", folder);
vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt);
+5 -5
View File
@@ -1,7 +1,7 @@
FLITE=flite-1.3.99
FLITE=flite-1.5.1
FLITE_DIR=$(switch_srcdir)/libs/$(FLITE)
FLITE_BUILDDIR=$(switch_builddir)/libs/$(FLITE)
FLITE_DIR=$(switch_srcdir)/libs/$(FLITE)-current
FLITE_BUILDDIR=$(switch_builddir)/libs/$(FLITE)-current
FLITE_LIBDIR=$(FLITE_BUILDDIR)/build/libs
FLITE_A=$(FLITE_LIBDIR)/libflite_cmu_us_awb.a \
@@ -18,11 +18,11 @@ include $(BASE)/build/modmake.rules
$(MODNAME).lo: $(FLITE_A)
$(FLITE_DIR):
$(GETLIB) $(FLITE)-latest.tar.gz
$(GETLIB) $(FLITE)-current.tar.bz2
$(FLITE_BUILDDIR)/Makefile: $(FLITE_DIR)
mkdir -p $(FLITE_BUILDDIR)
cd $(FLITE_BUILDDIR) && $(DEFAULT_VARS) $(FLITE_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(FLITE_DIR) --without-audio --with-pic --disable-shared
cd $(FLITE_BUILDDIR) && $(DEFAULT_VARS) $(FLITE_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(FLITE_DIR) --with-audio=none --with-pic --disable-shared
$(TOUCH_TARGET)
$(FLITE_A): $(FLITE_DIR) $(FLITE_BUILDDIR)/Makefile
+1 -1
View File
@@ -7,5 +7,5 @@ LOCAL_LIBADD=$(SILK_LA)
include $(BASE)/build/modmake.rules
$(SILK_LA): $(SILK_DIR)/.update
cd $(SILK_BUILDDIR) && $(MAKE)
cd $(SILK_BUILDDIR) && ./configure --disable-shared && make clean && $(MAKE)
$(TOUCH_TARGET)
+4 -1
View File
@@ -271,7 +271,7 @@ void printSilkError(SKP_int16 ret){
message = "unknown";
break;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR," Silk Error message= %s\n",message);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR," Silk Error: %s\n",message);
}
static switch_status_t switch_silk_encode(switch_codec_t *codec,
@@ -298,6 +298,7 @@ static switch_status_t switch_silk_encode(switch_codec_t *codec,
if (ret) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Encode returned %d!\n", ret);
printSilkError(ret);
return SWITCH_STATUS_FALSE;
}
*encoded_data_len += nBytes;
samples-=pktsz;
@@ -332,6 +333,8 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
&len);
if (ret){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Decode returned %d!\n", ret);
printSilkError(ret);
return SWITCH_STATUS_FALSE;
}
target += len;
@@ -81,12 +81,20 @@ static switch_status_t exec_app(switch_core_session_t *session, const char *app,
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension)
{
switch_xml_t xcond, xaction, xexpression;
switch_xml_t xcond, xaction, xexpression, xregex;
switch_channel_t *channel = switch_core_session_get_channel(session);
char *exten_name = (char *) switch_xml_attr(xexten, "name");
int proceed = 0;
int proceed = 0, save_proceed = 0;
char *expression_expanded = NULL, *field_expanded = NULL;
switch_regex_t *re = NULL;
switch_regex_t *re = NULL, *save_re = NULL;
int offset = 0;
const char *tzoff = switch_channel_get_variable(channel, "tod_tz_offset");
if (!zstr(tzoff) && switch_is_number(tzoff)) {
offset = atoi(tzoff);
} else {
tzoff = NULL;
}
if (!exten_name) {
exten_name = "_anon_";
@@ -95,13 +103,14 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
char *field = NULL;
char *do_break_a = NULL;
char *expression = NULL;
char *expression = NULL, *save_expression = NULL, *save_field_data = NULL;
char *regex_rule = 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);
int time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL);
switch_safe_free(field_expanded);
switch_safe_free(expression_expanded);
@@ -114,17 +123,6 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
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_channel_expand_variables(channel, 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")) {
@@ -147,41 +145,188 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
anti_action = SWITCH_FALSE;
} else if (time_match == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Date/Time Match (FAIL) [%s] break=%s\n",
"Dialplan: %s Date/TimeMatch (FAIL) [%s] break=%s\n",
switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
}
if ((regex_rule = (char *) switch_xml_attr(xcond, "regex"))) {
int all = !strcasecmp(regex_rule, "all");
int xor = !strcasecmp(regex_rule, "xor");
int pass = 0;
int fail = 0;
int total = 0;
if (field) {
if (strchr(field, '$')) {
if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
field_expanded = NULL;
field_data = field;
switch_channel_del_variable_prefix(channel, "DP_REGEX_MATCH");
for (xregex = switch_xml_child(xcond, "regex"); xregex; xregex = xregex->next) {
time_match = switch_xml_std_datetime_check(xregex, tzoff ? &offset : NULL);
if (time_match == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Date/Time Match (PASS) [%s]\n",
switch_channel_get_name(channel), exten_name);
anti_action = SWITCH_FALSE;
} else if (time_match == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Date/TimeMatch (FAIL) [%s]\n",
switch_channel_get_name(channel), exten_name);
}
if ((xexpression = switch_xml_child(xregex, "expression"))) {
expression = switch_str_nil(xexpression->txt);
} else {
field_data = field_expanded;
expression = (char *) switch_xml_attr_soft(xregex, "expression");
}
if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
expression_expanded = NULL;
} else {
expression = expression_expanded;
}
total++;
field = (char *) switch_xml_attr(xregex, "field");
if (field) {
if (strchr(field, '$')) {
if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
field_expanded = NULL;
field_data = field;
} else {
field_data = field_expanded;
}
} else {
field_data = switch_caller_get_field_by_name(caller_profile, 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_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ match=%s\n",
switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
pass++;
if (!all && !xor) break;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ match=%s\n",
switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
fail++;
if (all && !xor) break;
}
} else if (time_match == -1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Absolute Condition [%s] match=%s\n", switch_channel_get_name(channel), exten_name, all ? "all" : "any");
pass++;
if (!all && !xor) break;
} else if (time_match == 1) {
pass++;
if (!all && !xor) break;
}
if (field && strchr(expression, '(')) {
char var[256];
switch_snprintf(var, sizeof(var), "DP_REGEX_MATCH_%d", total);
switch_channel_set_variable(channel, var, NULL);
switch_capture_regex(re, proceed, field_data, ovector, var, switch_regex_set_var_callback, session);
switch_safe_free(save_expression);
switch_safe_free(save_field_data);
switch_regex_safe_free(save_re);
save_expression = strdup(expression);
save_field_data = strdup(field_data);
save_re = re;
save_proceed = proceed;
re = NULL;
}
switch_regex_safe_free(re);
switch_safe_free(field_expanded);
switch_safe_free(expression_expanded);
}
if (xor) {
if (pass == 1) {
anti_action = SWITCH_FALSE;
}
} else {
field_data = switch_caller_get_field_by_name(caller_profile, field);
}
if (!field_data) {
field_data = "";
if ((all && !fail) || (!all && pass)) {
anti_action = SWITCH_FALSE;
}
}
if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n",
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
anti_action = SWITCH_FALSE;
switch_safe_free(field_expanded);
switch_safe_free(expression_expanded);
} else {
if ((xexpression = switch_xml_child(xcond, "expression"))) {
expression = switch_str_nil(xexpression->txt);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n",
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
expression = (char *) switch_xml_attr_soft(xcond, "expression");
}
} else if (time_match == -1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Absolute Condition [%s]\n", switch_channel_get_name(channel), exten_name);
anti_action = SWITCH_FALSE;
if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
expression_expanded = NULL;
} else {
expression = expression_expanded;
}
if (field) {
if (strchr(field, '$')) {
if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
field_expanded = NULL;
field_data = field;
} else {
field_data = field_expanded;
}
} else {
field_data = switch_caller_get_field_by_name(caller_profile, 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_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n",
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
anti_action = SWITCH_FALSE;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n",
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
}
} else if (time_match == -1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: %s Absolute Condition [%s]\n", switch_channel_get_name(channel), exten_name);
anti_action = SWITCH_FALSE;
}
}
if (save_re) {
re = save_re;
save_re = NULL;
expression = expression_expanded = save_expression;
save_expression = NULL;
field_data = field_expanded = save_field_data;
field = (char *) field_data;
save_field_data = NULL;
proceed = save_proceed;
}
if (anti_action) {
for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
const char *application = switch_xml_attr_soft(xaction, "application");
@@ -145,6 +145,12 @@
<Project>{e727e8f6-935d-46fe-8b0e-37834748a0e3}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\openssl\libeay32.2010.vcxproj">
<Project>{d331904d-a00a-4694-a5a3-fcff64ab5dbe}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\openssl\ssleay32.2010.vcxproj">
<Project>{b4b62169-5ad4-4559-8707-3d933ac5db39}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
@@ -40,6 +40,7 @@
#define DL_EVENT_LOGIN_FAILURE "dingaling::login_failure"
#define DL_EVENT_CONNECTED "dingaling::connected"
#define MDL_CHAT_PROTO "jingle"
#define MDL_CHAT_FROM_GUESS "auto_from"
SWITCH_MODULE_LOAD_FUNCTION(mod_dingaling_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_dingaling_shutdown);
@@ -495,18 +496,24 @@ static switch_status_t chat_send(switch_event_t *message_event)
mdl_profile_t *profile = NULL;
const char *proto;
const char *from;
const char *from_full;
const char *to_full;
const char *to;
const char *body;
const char *hint;
const char *profile_name;
proto = switch_event_get_header(message_event, "proto");
from = switch_event_get_header(message_event, "from");
from_full = switch_event_get_header(message_event, "from_full");
to_full = switch_event_get_header(message_event, "to_full");
to = switch_event_get_header(message_event, "to");
body = switch_event_get_body(message_event);
hint = switch_event_get_header(message_event, "hint");
profile_name = switch_event_get_header(message_event, "ldl_profile");
switch_assert(proto != NULL);
if (from && (f_user = strdup(from))) {
if ((f_host = strchr(f_user, '@'))) {
*f_host++ = '\0';
@@ -516,12 +523,18 @@ static switch_status_t chat_send(switch_event_t *message_event)
}
}
if (to && (user = strdup(to))) {
if ((profile_name && (profile = switch_core_hash_find(globals.profile_hash, profile_name)))) {
from = from_full;
to = to_full;
ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body));
} else if (to && (user = strdup(to))) {
if ((host = strchr(user, '@'))) {
*host++ = '\0';
}
if (f_host && (profile = switch_core_hash_find(globals.profile_hash, f_host))) {
if (f_host && ((profile_name && (profile = switch_core_hash_find(globals.profile_hash, profile_name)))
|| (profile = switch_core_hash_find(globals.profile_hash, f_host)))) {
if (!strcmp(proto, MDL_CHAT_PROTO)) {
from = hint;
@@ -538,7 +551,12 @@ static switch_status_t chat_send(switch_event_t *message_event)
*p = '\0';
}
}
ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body));
if (!(profile->user_flags & LDL_FLAG_COMPONENT) && !strcmp(f_user, MDL_CHAT_FROM_GUESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using auto_from jid address for profile %s\n", profile->name);
ldl_handle_send_msg(profile->handle, NULL, (char *) to, NULL, switch_str_nil(body));
} else {
ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body));
}
switch_safe_free(ffrom);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\n", f_host ? f_host : "NULL");
@@ -1585,8 +1603,10 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
channel_answer_channel(session);
break;
case SWITCH_MESSAGE_INDICATE_BRIDGE:
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_STICK);
break;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK);
break;
default:
break;
@@ -2931,6 +2951,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", subject);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", hint);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", hint);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ldl_profile", profile->name);
if (msg) {
switch_event_add_body(event, "%s", msg);
@@ -2941,12 +2963,14 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
switch_safe_free(from_user);
if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */
switch_core_chat_send(proto, event);
if (!zstr(msg)) {
if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */
switch_core_chat_send(proto, event);
}
switch_core_chat_send("GLOBAL", event);
}
switch_core_chat_send("GLOBAL", event);
switch_event_destroy(&event);
switch_safe_free(pproto);
+1
View File
@@ -31,5 +31,6 @@ Enjoy
-giovanni
< gmaruzz at gmail dot com >
+2
View File
@@ -1,3 +1,5 @@
fix stale calls then fax send/recv in some circumstance
remove SWITCH_RTP_FLAG_AUTO_CNG - works incorrectly.
moves the switch_rtp_request_port() call from the contructor to FSH323Connection::CreateRealTimeLogicalChannel() - fix
rtp port leak. tnx to Peter Olsson.
fix log printing
+26 -8
View File
@@ -33,7 +33,7 @@
*
* mod_h323.cpp -- H323 endpoint
*
* Version 0.0.57
* Version 0.0.58
*/
//#define DEBUG_RTP_PACKETS
@@ -201,10 +201,14 @@ SWITCH_END_EXTERN_C
void h_timer(unsigned sec)
{
#ifdef WIN32
switch_sleep(sec * 1000000);
#else
timeval timeout;
timeout.tv_sec = sec;
timeout.tv_usec = 0;
select(0, NULL, NULL, NULL, &timeout);
#endif
}
@@ -1098,7 +1102,7 @@ bool FSH323Connection::OnSendReleaseComplete(H323SignalPDU & pdu)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"======>FSH323Connection::OnSendReleaseComplete cause = %u\n",(switch_call_cause_t)pdu.GetQ931().GetCause());
switch_channel_hangup(m_fsChannel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
switch_channel_hangup(m_fsChannel, (switch_call_cause_t) pdu.GetQ931().GetCause());
return H323Connection::OnSendReleaseComplete(pdu);
}
@@ -1333,7 +1337,19 @@ void FSH323Connection::OnModeChanged(const H245_ModeDescription & newMode)
const char *uuid = switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE);
if (uuid != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"uuid:%s\n",uuid);
switch_channel_set_private(switch_core_session_get_channel(switch_core_session_locate(switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE))), "t38_options", t38_options);
switch_core_session_t *session = switch_core_session_locate(switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE));
if (session) {
switch_channel_t * channel = switch_core_session_get_channel(session);
if (channel) {
switch_channel_set_private(channel, "t38_options", t38_options);
}else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no channel?\n");
}
switch_core_session_rwunlock(session);
}else{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no session\n");
}
switch_core_session_message_t msg = { 0 };
@@ -1887,6 +1903,7 @@ FSH323_ExternalRTPChannel::FSH323_ExternalRTPChannel(FSH323Connection& connectio
, m_capability(&capability)
, m_RTPlocalPort(dataPort)
, m_sessionID(sessionID)
, m_rtp_resetting(0)
{
m_RTPlocalIP = (const char *)ip.AsString();
SetExternalAddress(H323TransportAddress(ip, dataPort), H323TransportAddress(ip, dataPort+1));
@@ -2046,9 +2063,6 @@ PBoolean FSH323_ExternalRTPChannel::Start()
, GetMainTypes[m_capability->GetMainType()],(const char*)(m_capability->GetFormatName()),this);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"%s Unsupported ptime of %u on %s %s codec %s for connection [%p]\n",switch_channel_get_name(m_fsChannel),((GetDirection() == IsReceiver)? " read" : " write")
, GetMainTypes[m_capability->GetMainType()],(const char*)(m_capability->GetFormatName()),this);
if (GetDirection() == IsReceiver) {
//m_readFrame.rate = tech_pvt->read_codec.implementation->actual_samples_per_second;
@@ -2113,7 +2127,7 @@ PBoolean FSH323_ExternalRTPChannel::Start()
bool ch_port = false;
if (tech_pvt->rtp_session != NULL){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------------->old remot port = %d new remote port = %d\n",switch_rtp_get_remote_port(tech_pvt->rtp_session),m_RTPremotePort);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------------->old remote port = %d new remote port = %d\n",switch_rtp_get_remote_port(tech_pvt->rtp_session),m_RTPremotePort);
if ((switch_rtp_get_remote_port(tech_pvt->rtp_session) != m_RTPremotePort) && (GetDirection() != IsReceiver) && (m_conn->m_rtp_resetting == 1)){
ch_port = true;
m_conn->m_startRTP = false;
@@ -2131,7 +2145,7 @@ PBoolean FSH323_ExternalRTPChannel::Start()
}
if ((!m_conn->m_startRTP)) {
flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT|SWITCH_RTP_FLAG_AUTO_CNG|SWITCH_RTP_FLAG_RAW_WRITE);
flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT|SWITCH_RTP_FLAG_RAW_WRITE);
if (mod_h323_globals.use_rtp_timer) {
flags |= SWITCH_RTP_FLAG_USE_TIMER;
@@ -2401,9 +2415,13 @@ static switch_status_t on_hangup(switch_core_session_t *session)
switch_mutex_lock(tech_pvt->h323_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->h323_mutex_unlock\n");
switch_mutex_unlock(tech_pvt->h323_mutex);
while (tech_pvt->active_connection){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Wait clear h323 connection\n");
h_timer(1);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "H323 connection was cleared successfully\n");
return SWITCH_STATUS_SUCCESS;
}
+1 -1
View File
@@ -32,7 +32,7 @@
*
* mod_h323.h -- H323 endpoint
*
* Version 0.0.57
* Version 0.0.58
*/
#if defined(__GNUC__) && defined(HAVE_VISIBILITY)
@@ -1399,6 +1399,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
case SWITCH_CAUSE_INVALID_GATEWAY:
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
@@ -1430,7 +1432,9 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
case SWITCH_CAUSE_INVALID_PROFILE:
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_GATEWAY_DOWN:
case SWITCH_CAUSE_FACILITY_REJECTED:
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
@@ -1448,6 +1452,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
case SWITCH_CAUSE_INVALID_GATEWAY:
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
@@ -1480,6 +1486,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_GATEWAY_DOWN:
case SWITCH_CAUSE_FACILITY_REJECTED:
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
@@ -1497,6 +1504,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
case SWITCH_CAUSE_INVALID_GATEWAY:
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
@@ -1529,6 +1538,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_GATEWAY_DOWN:
case SWITCH_CAUSE_FACILITY_REJECTED:
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
@@ -1553,6 +1563,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
case SWITCH_CAUSE_INVALID_GATEWAY:
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
@@ -1585,6 +1597,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_GATEWAY_DOWN:
case SWITCH_CAUSE_FACILITY_REJECTED:
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
@@ -1622,6 +1635,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
case SWITCH_CAUSE_INVALID_GATEWAY:
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED:
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
@@ -1629,6 +1644,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause)
case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE:
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_GATEWAY_DOWN:
case SWITCH_CAUSE_FACILITY_REJECTED:
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED:
+44 -14
View File
@@ -84,6 +84,7 @@ struct private_object {
char *other_uuid;
switch_queue_t *frame_queue;
int64_t packet_count;
int first_cng;
};
typedef struct private_object private_t;
@@ -115,6 +116,7 @@ static void clear_queue(private_t *tech_pvt)
switch_frame_t *frame = (switch_frame_t *) pop;
switch_frame_free(&frame);
}
}
static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, switch_codec_t *codec)
@@ -174,7 +176,7 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses
tech_pvt->cng_frame.datalen = 2;
tech_pvt->bowout_frame_count = (tech_pvt->read_codec.implementation->actual_samples_per_second /
tech_pvt->read_codec.implementation->samples_per_packet) * 3;
tech_pvt->read_codec.implementation->samples_per_packet) * 2;
switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
@@ -594,11 +596,16 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
*frame = tech_pvt->write_frame;
tech_pvt->packet_count++;
switch_clear_flag(tech_pvt->write_frame, SFF_CNG);
tech_pvt->first_cng = 0;
} else {
*frame = &tech_pvt->cng_frame;
tech_pvt->cng_frame.codec = &tech_pvt->read_codec;
tech_pvt->cng_frame.datalen = tech_pvt->read_codec.implementation->decoded_bytes_per_packet;
switch_set_flag((&tech_pvt->cng_frame), SFF_CNG);
if (!tech_pvt->first_cng) {
switch_yield(tech_pvt->read_codec.implementation->samples_per_packet);
tech_pvt->first_cng = 1;
}
}
@@ -644,33 +651,56 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
switch_channel_test_flag(tech_pvt->channel, CF_BRIDGED) &&
switch_channel_test_flag(tech_pvt->other_channel, CF_BRIDGED) &&
switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) &&
switch_channel_test_flag(tech_pvt->other_channel, CF_ANSWERED) && !--tech_pvt->bowout_frame_count <= 0) {
switch_channel_test_flag(tech_pvt->other_channel, CF_ANSWERED) && --tech_pvt->bowout_frame_count <= 0) {
const char *a_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
const char *b_uuid = switch_channel_get_variable(tech_pvt->other_channel, SWITCH_SIGNAL_BOND_VARIABLE);
const char *vetoa, *vetob;
switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT);
switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT);
vetoa = switch_channel_get_variable(tech_pvt->channel, "loopback_bowout");
vetob = switch_channel_get_variable(tech_pvt->other_tech_pvt->channel, "loopback_bowout");
if ((!vetoa || switch_true(vetoa)) && (!vetob || switch_true(vetob))) {
switch_clear_flag_locked(tech_pvt, TFLAG_WRITE);
switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE);
switch_core_session_t *br_a, *br_b;
switch_channel_t *ch_a = NULL, *ch_b = NULL;
int good_to_go = 0;
if ((br_a = switch_core_session_locate(a_uuid))) {
ch_a = switch_core_session_get_channel(br_a);
}
switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT_USED);
switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT_USED);
if ((br_b = switch_core_session_locate(b_uuid))) {
ch_b = switch_core_session_get_channel(br_b);
}
if (ch_a && ch_b && switch_channel_test_flag(ch_a, CF_BRIDGED) && switch_channel_test_flag(ch_b, CF_BRIDGED)) {
switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT);
switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT);
if (a_uuid && b_uuid) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s detected bridge on both ends, attempting direct connection.\n", switch_channel_get_name(channel));
switch_clear_flag_locked(tech_pvt, TFLAG_WRITE);
switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE);
/* channel_masquerade eat your heart out....... */
switch_ivr_uuid_bridge(a_uuid, b_uuid);
switch_mutex_unlock(tech_pvt->mutex);
switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT_USED);
switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT_USED);
if (a_uuid && b_uuid) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s detected bridge on both ends, attempting direct connection.\n", switch_channel_get_name(channel));
/* channel_masquerade eat your heart out....... */
switch_ivr_uuid_bridge(a_uuid, b_uuid);
good_to_go = 1;
switch_mutex_unlock(tech_pvt->mutex);
}
}
if (br_a) switch_core_session_rwunlock(br_a);
if (br_b) switch_core_session_rwunlock(br_b);
if (good_to_go) {
return SWITCH_STATUS_SUCCESS;
}
}
}
+1 -1
View File
@@ -93,7 +93,7 @@ static int iblockingIOCallback(const void *inputBuffer, void *outputBuffer,
}
if (PaUtil_WriteRingBuffer(&data->inFIFOs[c], chanSamples, numBytes) != numBytes) {
PaUtil_FlushRingBuffer(&data->inFIFOs[c]);
PaUtil_WriteRingBuffer(&data->inFIFOs[c], inputBuffer, numBytes);
PaUtil_WriteRingBuffer(&data->inFIFOs[c], chanSamples, numBytes);
}
}
}
+8 -7
View File
@@ -266,10 +266,6 @@ switch_status_t rtmp_on_hangup(switch_core_session_t *session)
rtmp_notify_call_state(session);
rtmp_send_onhangup(session);
switch_mutex_lock(tech_pvt->rtmp_session->count_mutex);
tech_pvt->rtmp_session->active_sessions--;
switch_mutex_unlock(tech_pvt->rtmp_session->count_mutex);
switch_core_hash_delete_wrlock(tech_pvt->rtmp_session->session_hash, switch_core_session_get_uuid(session), tech_pvt->rtmp_session->session_rwlock);
switch_mutex_lock(tech_pvt->rtmp_session->profile->mutex);
@@ -279,6 +275,10 @@ switch_status_t rtmp_on_hangup(switch_core_session_t *session)
}
switch_mutex_unlock(tech_pvt->rtmp_session->profile->mutex);
switch_mutex_lock(tech_pvt->rtmp_session->count_mutex);
tech_pvt->rtmp_session->active_sessions--;
switch_mutex_unlock(tech_pvt->rtmp_session->count_mutex);
#ifndef RTMP_DONT_HOLD
if (switch_channel_test_flag(channel, CF_HOLD)) {
switch_channel_mark_hold(channel, SWITCH_FALSE);
@@ -407,6 +407,7 @@ switch_status_t rtmp_read_frame(switch_core_session_t *session, switch_frame_t *
return SWITCH_STATUS_SUCCESS;
cng:
data = (switch_byte_t *) tech_pvt->read_frame.data;
data[0] = 65;
data[1] = 0;
@@ -414,7 +415,7 @@ cng:
tech_pvt->read_frame.flags = SFF_CNG;
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
switch_core_timer_sync(&tech_pvt->timer);
//switch_core_timer_sync(&tech_pvt->timer);
*frame = &tech_pvt->read_frame;
@@ -515,13 +516,13 @@ switch_status_t rtmp_receive_message(switch_core_session_t *session, switch_core
const char *name = msg->string_array_arg[0], *number = msg->string_array_arg[1];
char *arg = NULL;
char *argv[2] = { 0 };
int argc;
//int argc;
if (zstr(name) && !zstr(msg->string_arg)) {
arg = strdup(msg->string_arg);
switch_assert(arg);
argc = switch_separate_string(arg, '|', argv, (sizeof(argv) / sizeof(argv[0])));
switch_separate_string(arg, '|', argv, (sizeof(argv) / sizeof(argv[0])));
name = argv[0];
number = argv[1];
+1
View File
@@ -520,6 +520,7 @@ struct rtmp_private {
const char *auth;
uint16_t maxlen;
int over_size;
};
struct rtmp_reg;
+41 -4
View File
@@ -23,6 +23,7 @@
* Contributor(s):
*
* Mathieu Rene <mrene@avgs.ca>
* Joao Mesquita <jmesquita@freeswitch.org>
*
* rtmp.c -- RTMP Protocol Handler
*
@@ -104,7 +105,9 @@ void rtmp_handle_control(rtmp_session_t *rsession, int amfnumber)
void rtmp_handle_invoke(rtmp_session_t *rsession, int amfnumber)
{
rtmp_state_t *state = &rsession->amfstate[amfnumber];
//amf0_data *dump;
#ifdef RTMP_DEBUG_IO
amf0_data *dump;
#endif
int i = 0;
buffer_helper_t helper = { state->buf, 0, state->origlen };
int64_t transaction_id;
@@ -188,6 +191,7 @@ switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, cons
switch_xml_t xml = NULL, x_param, x_params;
switch_bool_t allow_empty_password = SWITCH_FALSE;
const char *passwd = NULL;
switch_bool_t disallow_multiple_registration = SWITCH_FALSE;
switch_event_t *locate_params;
switch_event_create(&locate_params, SWITCH_EVENT_GENERAL);
@@ -211,6 +215,9 @@ switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, cons
if (!strcasecmp(var, "allow-empty-password")) {
allow_empty_password = switch_true(val);
}
if (!strcasecmp(var, "disallow-multiple-registration")) {
disallow_multiple_registration = switch_true(val);
}
}
}
@@ -231,6 +238,28 @@ switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, cons
} else {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Authentication failed for %s@%s\n", user, domain);
}
if (disallow_multiple_registration) {
switch_hash_index_t *hi;
switch_thread_rwlock_rdlock(rsession->profile->session_rwlock);
for (hi = switch_hash_first(NULL, rsession->profile->session_hash); hi; hi = switch_hash_next(hi)) {
void *val;
const void *key;
switch_ssize_t keylen;
rtmp_session_t *item;
switch_hash_this(hi, &key, &keylen, &val);
item = (rtmp_session_t *)val;
if (rtmp_session_check_user(item, user, domain) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Logging out %s@%s on RTMP sesssion [%s]\n", user, domain, item->uuid);
if (rtmp_session_logout(item, user, domain) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_ERROR, "Unable to logout %s@%s on RTMP sesssion [%s]\n", user, domain, item->uuid);
}
}
}
switch_thread_rwlock_unlock(rsession->profile->session_rwlock);
}
done:
if (xml) {
@@ -612,7 +641,7 @@ switch_status_t rtmp_send_message(rtmp_session_t *rsession, uint8_t amfnumber, u
}
end:
switch_mutex_unlock(rsession->socket_mutex);
return SWITCH_STATUS_SUCCESS;
return status;
}
/* Returns SWITCH_STATUS_SUCCESS of the connection is still active or SWITCH_STATUS_FALSE to tear it down */
@@ -858,10 +887,18 @@ switch_status_t rtmp_handle_data(rtmp_session_t *rsession)
uint16_t len = state->origlen;
switch_mutex_lock(rsession->tech_pvt->readbuf_mutex);
if (rsession->tech_pvt->maxlen && switch_buffer_inuse(rsession->tech_pvt->readbuf) > rsession->tech_pvt->maxlen * 3) {
if (rsession->tech_pvt->maxlen && switch_buffer_inuse(rsession->tech_pvt->readbuf) > rsession->tech_pvt->maxlen * 40) {
rsession->tech_pvt->over_size++;
} else {
rsession->tech_pvt->over_size = 0;
}
if (rsession->tech_pvt->over_size > 10) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"%s buffer > %u for 10 consecutive packets... Flushing buffer\n",
switch_core_session_get_name(rsession->tech_pvt->session), rsession->tech_pvt->maxlen * 40);
switch_buffer_zero(rsession->tech_pvt->readbuf);
#ifdef RTMP_DEBUG_IO
fprintf(rsession->io_debug_in, "[chunk_stream=%d type=0x%x ts=%d stream_id=0x%x] FLUSH BUFFER [exceeded %u]\n", rsession->amfnumber, state->type, (int)state->ts, state->stream_id, rsession->tech_pvt->maxlen * 3);
fprintf(rsession->io_debug_in, "[chunk_stream=%d type=0x%x ts=%d stream_id=0x%x] FLUSH BUFFER [exceeded %u]\n", rsession->amfnumber, state->type, (int)state->ts, state->stream_id, rsession->tech_pvt->maxlen * 5);
#endif
}
switch_buffer_write(rsession->tech_pvt->readbuf, &len, 2);
+13 -3
View File
@@ -85,7 +85,10 @@ static switch_status_t rtmp_tcp_read(rtmp_session_t *rsession, unsigned char *bu
switch_size_t olen = *len;
#endif
switch_assert(*len > 0 && *len < 1024000);
status = switch_socket_recv(io_pvt->socket, (char*)buf, len);
do {
status = switch_socket_recv(io_pvt->socket, (char*)buf, len);
} while(status != SWITCH_STATUS_SUCCESS && SWITCH_STATUS_IS_BREAK(status));
#ifdef RTMP_DEBUG_IO
{
@@ -197,10 +200,10 @@ void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj)
switch_mutex_unlock(io->mutex);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n");
continue;
} else if (status == SWITCH_STATUS_TIMEOUT) {
switch_yield(1);
switch_cond_next();
}
for (i = 0; i < numfds; i++) {
@@ -219,6 +222,10 @@ void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj)
if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n");
}
if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n");
}
if (rtmp_session_request(io->base.profile, &newsession) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n");
@@ -314,6 +321,9 @@ switch_status_t rtmp_tcp_init(rtmp_profile_t *profile, const char *bindaddr, rtm
if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_REUSEADDR, 1)) {
goto fail;
}
if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_TCP_NODELAY, 1)) {
goto fail;
}
if (switch_socket_bind(io_tcp->listen_socket, sa)) {
goto fail;
}
@@ -146,7 +146,11 @@ struct skypopen_listitem {
/* The list of devices, and a lock to protect it */
static LIST_HEAD(skypopen_c_list);
#ifdef WANT_DEFINE_SPINLOCK
static DEFINE_SPINLOCK(skypopen_c_lock);
#else // WANT_DEFINE_SPINLOCK
static spinlock_t skypopen_c_lock = SPIN_LOCK_UNLOCKED;
#endif // WANT_DEFINE_SPINLOCK
/* Look for a device or create one if missing */
static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key)
@@ -31,6 +31,10 @@
#define WANT_HRTIMER
#endif /* HRTIMER */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
#define WANT_DEFINE_SPINLOCK
#endif /* DEFINE_SPINLOCK */
#define SKYPOPEN_BLK 1920
#define SKYPOPEN_SLEEP 20
+1 -1
View File
@@ -9,7 +9,7 @@ SOFIAUA_BUILDDIR=$(SOFIA_BUILDDIR)/libsofia-sip-ua
SOFIALA=$(SOFIAUA_BUILDDIR)/libsofia-sip-ua.la
mod_LTLIBRARIES = mod_sofia.la
mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_sla.c sip-dig.c mod_sofia.h
mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sip-dig.c mod_sofia.h
mod_sofia_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_CMD_LINE_CFLAGS)
mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/bnf -I$(SOFIAUA_BUILDDIR)/bnf
mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/http -I$(SOFIAUA_BUILDDIR)/http
@@ -321,10 +321,6 @@
RelativePath=".\sofia_reg.c"
>
</File>
<File
RelativePath=".\sofia_sla.c"
>
</File>
</Files>
<Globals>
</Globals>
@@ -143,7 +143,6 @@
<ClCompile Include="sofia_glue.c" />
<ClCompile Include="sofia_presence.c" />
<ClCompile Include="sofia_reg.c" />
<ClCompile Include="sofia_sla.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="mod_sofia.h" />
+211 -59
View File
@@ -250,6 +250,11 @@ char *generate_pai_str(private_object_t *tech_pvt)
const char *callee_name = NULL, *callee_number = NULL;
const char *var, *header, *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
char *pai = NULL;
const char *host = switch_channel_get_variable(tech_pvt->channel, "sip_to_host");
if (zstr(host)) {
host = tech_pvt->profile->sipip;
}
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID) || !sofia_test_pflag(tech_pvt->profile, PFLAG_CID_IN_1XX) ||
((var = switch_channel_get_variable(tech_pvt->channel, "sip_cid_in_1xx")) && switch_false(var))) {
@@ -276,7 +281,7 @@ char *generate_pai_str(private_object_t *tech_pvt)
callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name));
if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("polycom", ua))) {
callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, tech_pvt->profile->sipip);
callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host);
}
header = (tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua)) ? "Remote-Party-ID" : "P-Asserted-Identity";
@@ -321,8 +326,11 @@ static int hangup_cause_to_sip(switch_call_cause_t cause)
case SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION:
return 410;
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
case SWITCH_CAUSE_INVALID_PROFILE:
return 502;
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_INVALID_GATEWAY:
return 484;
case SWITCH_CAUSE_FACILITY_REJECTED:
return 501;
@@ -333,6 +341,7 @@ static int hangup_cause_to_sip(switch_call_cause_t cause)
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE:
case SWITCH_CAUSE_SWITCH_CONGESTION:
case SWITCH_CAUSE_GATEWAY_DOWN:
return 503;
case SWITCH_CAUSE_OUTGOING_CALL_BARRED:
case SWITCH_CAUSE_INCOMING_CALL_BARRED:
@@ -484,11 +493,12 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
const char *val = NULL;
val = switch_channel_get_variable(tech_pvt->channel, "disable_q850_reason");
if (!val || switch_true(val)) {
if (cause > 0 && cause < 128) {
switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
} else if (cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) {
if (switch_false(val)) {
if (switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) {
switch_snprintf(reason, sizeof(reason), "SIP;cause=200;text=\"Call completed elsewhere\"");
} else if (cause > 0 && cause < 128) {
switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
} else {
switch_snprintf(reason, sizeof(reason), "%s;cause=%d;text=\"%s\"", tech_pvt->profile->username, cause, switch_channel_cause2str(cause));
}
@@ -952,7 +962,6 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) {
switch_ivr_parse_all_messages(tech_pvt->session);
if (--sanity && switch_channel_up(channel)) {
switch_yield(10000);
} else {
@@ -1009,39 +1018,66 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
switch_event_t *event;
if (switch_event_create(&event, SWITCH_EVENT_RECV_RTCP_MESSAGE) == SWITCH_STATUS_SUCCESS) {
char buf[30];
char value[30];
char header[50];
int i;
char *uuid = switch_core_session_get_uuid(session);
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
}
snprintf(buf, sizeof(buf), "%.8x", rtcp_frame.ssrc);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", buf);
snprintf(value, sizeof(value), "%.8x", rtcp_frame.ssrc);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_msw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_msw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_lsw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_lsw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.packet_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.packet_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.octect_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.octect_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", value);
snprintf(buf, sizeof(buf), "%" SWITCH_SIZE_T_FMT, tech_pvt->read_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", buf);
snprintf(value, sizeof(value), "%" SWITCH_SIZE_T_FMT, tech_pvt->read_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", value);
snprintf(buf, sizeof(buf), "%u", tech_pvt->read_frame.rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", buf);
snprintf(value, sizeof(value), "%u", tech_pvt->read_frame.rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", value);
snprintf(buf, sizeof(buf), "%" SWITCH_TIME_T_FMT, switch_time_now());
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", buf);
snprintf(value, sizeof(value), "%" SWITCH_TIME_T_FMT, switch_time_now());
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", value);
// Add sources info
for (i = 0; i < rtcp_frame.report_count; i++) {
snprintf(header, sizeof(header), "Source%u-SSRC", i);
snprintf(value, sizeof(value), "%.8x", rtcp_frame.reports[i].ssrc);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Fraction", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].fraction);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Lost", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lost);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Highest-Sequence-Number-Received", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].highest_sequence_number_received);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Jitter", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].jitter);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-LSR", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lsr);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-DLSR", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].dlsr);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
}
switch_event_fire(&event);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Dispatched RTCP event\n");
@@ -1504,6 +1540,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames) (%d max drift)\n",
len, qlen, maxqlen, max_drift);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) {
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
@@ -1782,6 +1821,28 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
break;
case SWITCH_MESSAGE_INDICATE_AUDIO_DATA:
{
if (switch_rtp_ready(tech_pvt->rtp_session)) {
if (msg->numeric_arg) {
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE);
sofia_set_flag(tech_pvt, TFLAG_JB_PAUSED);
}
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK);
} else {
if (sofia_test_flag(tech_pvt, TFLAG_JB_PAUSED)) {
sofia_clear_flag(tech_pvt, TFLAG_JB_PAUSED);
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE);
}
}
}
}
}
break;
case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT:
{
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Sending media re-direct:\n%s\n",
@@ -1793,7 +1854,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
switch_channel_set_flag(channel, CF_REQ_MEDIA);
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_glue_do_invite(session);
}
break;
@@ -1854,7 +1918,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
sofia_glue_set_image_sdp(tech_pvt, t38_options, msg->numeric_arg);
switch_channel_set_flag(channel, CF_REQ_MEDIA);
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
sofia_glue_do_invite(session);
}
@@ -1892,7 +1958,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1);
if (send_invite) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_glue_do_invite(session);
} else {
status = SWITCH_STATUS_FALSE;
@@ -1918,6 +1986,43 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
} else {
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR(event), TAG_END());
}
}
case SWITCH_MESSAGE_INDICATE_INFO:
{
char *ct = "freeswitch/data";
int ok = 0;
if (!zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) {
ct = switch_core_session_sprintf(session, "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]);
ok = 1;
}
if (switch_stristr("send_info", tech_pvt->x_freeswitch_support_remote)) {
ok = 1;
}
if (switch_true(switch_channel_get_variable(channel, "fs_send_unspported_info"))) {
ok = 1;
}
if (ok) {
char *headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX);
const char *pl = NULL;
if (!zstr(msg->string_array_arg[2])) {
pl = msg->string_array_arg[2];
}
nua_info(tech_pvt->nh,
SIPTAG_CONTENT_TYPE_STR(ct),
TAG_IF(!zstr(headers), SIPTAG_HEADER_STR(headers)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl)),
TAG_END());
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send_info is not supported.\n", switch_channel_get_name(channel));
}
}
break;
case SWITCH_MESSAGE_INDICATE_SIMPLIFY:
@@ -1989,6 +2094,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
switch_event_t *event;
check_decode(name, tech_pvt->session);
if (zstr(number)) {
number = tech_pvt->caller_profile->destination_number;
}
@@ -2306,7 +2414,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
sofia_glue_tech_patch_sdp(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
}
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
@@ -2569,7 +2677,7 @@ static switch_status_t sofia_receive_event(switch_core_session_t *session, switc
switch_mutex_lock(tech_pvt->sofia_mutex);
msg_nh = nua_handle(tech_pvt->profile->nua, NULL,
SIPTAG_FROM_STR(tech_pvt->chat_from),
NUTAG_URL(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to), SIPTAG_CONTACT_STR(tech_pvt->profile->url), TAG_END());
NUTAG_URL(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to), TAG_END());
nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR("text/html"), SIPTAG_PAYLOAD_STR(body), TAG_END());
switch_mutex_unlock(tech_pvt->sofia_mutex);
@@ -2867,7 +2975,6 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
stream->write_function(stream, "CALLS-OUT \t%u\n", profile->ob_calls);
stream->write_function(stream, "FAILED-CALLS-OUT \t%u\n", profile->ob_failed_calls);
}
stream->write_function(stream, "\nRegistrations:\n%s\n", line);
cb.profile = profile;
cb.stream = stream;
@@ -2884,6 +2991,12 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host"
" from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host"
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
char *dup = strdup(argv[3]);
char *host = NULL, *user = NULL;
@@ -2914,20 +3027,18 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
switch_safe_free(sqlextra);
}
if (!sql) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host"
" from sip_registrations where profile_name='%q'", profile->name);
if (sql) {
stream->write_function(stream, "\nRegistrations:\n%s\n", line);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb);
switch_safe_free(sql);
stream->write_function(stream, "Total items returned: %d\n", cb.row_process);
stream->write_function(stream, "%s\n", line);
}
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb);
switch_safe_free(sql);
stream->write_function(stream, "Total items returned: %d\n", cb.row_process);
stream->write_function(stream, "%s\n", line);
sofia_glue_release_profile(profile);
} else {
stream->write_function(stream, "Invalid Profile!\n");
}
@@ -4070,7 +4181,7 @@ SWITCH_STANDARD_API(sofia_function)
" siptrace <on|off>\n"
" capture <on|off>\n"
" watchdog <on|off>\n\n"
"sofia <status|xmlstatus> profile <name> [reg <contact str>] | [pres <pres str>] | [user <user@domain>]\n"
"sofia <status|xmlstatus> profile <name> [reg [<contact str>]] | [pres <pres str>] | [user <user@domain>]\n"
"sofia <status|xmlstatus> gateway <name>\n\n"
"sofia loglevel <all|default|tport|iptsec|nea|nta|nth_client|nth_server|nua|soa|sresolv|stun> [0-9]\n"
"sofia tracelevel <console|alert|crit|err|warning|notice|info|debug>\n\n"
@@ -4130,6 +4241,7 @@ SWITCH_STANDARD_API(sofia_function)
int ston = -1;
int cton = -1;
int wdon = -1;
int stbyon = -1;
if (argc > 1) {
if (!strcasecmp(argv[1], "debug")) {
@@ -4165,6 +4277,12 @@ SWITCH_STANDARD_API(sofia_function)
}
}
if (!strcasecmp(argv[1], "standby")) {
if (argc > 2) {
stbyon = switch_true(argv[2]);
}
}
if (!strcasecmp(argv[1], "capture")) {
if (argc > 2) {
cton = switch_true(argv[2]);
@@ -4182,11 +4300,14 @@ SWITCH_STANDARD_API(sofia_function)
sofia_glue_global_siptrace(ston);
stream->write_function(stream, "+OK Global siptrace %s", ston ? "on" : "off");
} else if (cton != -1) {
sofia_glue_global_capture(cton);
stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off");
sofia_glue_global_capture(cton);
stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off");
} else if (wdon != -1) {
sofia_glue_global_watchdog(wdon);
stream->write_function(stream, "+OK Global watchdog %s", wdon ? "on" : "off");
} else if (stbyon != -1) {
sofia_glue_global_standby(stbyon);
stream->write_function(stream, "+OK Global standby %s", stbyon ? "on" : "off");
} else {
stream->write_function(stream, "-ERR Usage: siptrace <on|off>|capture <on|off>|watchdog <on|off>|debug <sla|presence|none");
}
@@ -4199,10 +4320,23 @@ SWITCH_STANDARD_API(sofia_function)
stream->write_function(stream, "Flushing recovery database.\n");
} else {
int x = sofia_glue_recover(SWITCH_FALSE);
switch_event_t *event = NULL;
if (x) {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,
MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "recovered_calls", "%d", x);
switch_event_fire(&event);
}
stream->write_function(stream, "Recovered %d call(s)\n", x);
} else {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,
MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "recovered_calls", "0");
switch_event_fire(&event);
}
stream->write_function(stream, "No calls to recover.\n");
}
}
@@ -4275,7 +4409,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
*new_session = NULL;
if (!outbound_profile || zstr(outbound_profile->destination_number)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid Destination\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid Empty Destination\n");
goto error;
}
@@ -4312,30 +4446,30 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
char *gw, *params;
if (!(gw = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", profile_name);
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*gw++ = '\0';
if (!(dest = strchr(gw, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", gw);
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*dest++ = '\0';
if (!(gateway_ptr = sofia_reg_find_gateway(gw))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Gateway\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Gateway \'%s\'\n", gw);
cause = SWITCH_CAUSE_INVALID_GATEWAY;
goto error;
}
if (gateway_ptr->status != SOFIA_GATEWAY_UP) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway is down!\n");
cause = SWITCH_CAUSE_NETWORK_OUT_OF_ORDER;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway \'%s\' is down!\n", gw);
cause = SWITCH_CAUSE_GATEWAY_DOWN;
gateway_ptr->ob_failed_calls++;
goto error;
}
@@ -4375,6 +4509,13 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
}
profile = gateway_ptr->profile;
if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n");
cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
goto error;
}
tech_pvt->gateway_name = switch_core_session_strdup(nsession, gateway_ptr->name);
switch_channel_set_variable(nchannel, "sip_gateway_name", gateway_ptr->name);
@@ -4442,14 +4583,20 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
} else {
if (!(dest = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*dest++ = '\0';
if (!(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Profile\n");
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
cause = SWITCH_CAUSE_INVALID_PROFILE;
goto error;
}
if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n");
cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
goto error;
}
@@ -4562,6 +4709,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (profile->pres_type) {
char *sql;
time_t now;
const char *presence_id = switch_channel_get_variable(nchannel, "presence_id");
const char *presence_data = switch_channel_get_variable(nchannel, "presence_data");
@@ -4573,9 +4722,10 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
presence_data = switch_event_get_header(var_event, "presence_data");
}
sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname) "
"values ('%q', '%q', '%q', '%q', '%q')", switch_core_session_get_uuid(nsession),
switch_str_nil(presence_id), switch_str_nil(presence_data), profile->name, mod_sofia_globals.hostname);
now = switch_epoch_time_now(NULL);
sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname,rcd) "
"values ('%q', '%q', '%q', '%q', '%q', %ld)", switch_core_session_get_uuid(nsession),
switch_str_nil(presence_id), switch_str_nil(presence_data), profile->name, mod_sofia_globals.hostname, (long) now);
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
switch_safe_free(sql);
}
@@ -5381,6 +5531,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug");
switch_console_set_complete("add sofia global siptrace ::[on:off");
switch_console_set_complete("add sofia global standby ::[on:off");
switch_console_set_complete("add sofia global capture ::[on:off");
switch_console_set_complete("add sofia global watchdog ::[on:off");
@@ -5495,3 +5646,4 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
+23 -23
View File
@@ -87,6 +87,7 @@ typedef struct private_object private_object_t;
#define MY_EVENT_GATEWAY_DEL "sofia::gateway_delete"
#define MY_EVENT_RECOVERY "sofia::recovery_recv"
#define MY_EVENT_RECOVERY_SEND "sofia::recovery_send"
#define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered"
#define MULTICAST_EVENT "multicast::event"
#define SOFIA_REPLACES_HEADER "_sofia_replaces_"
@@ -95,6 +96,8 @@ typedef struct private_object private_object_t;
#define SOFIA_MULTIPART_PREFIX "sip_mp_"
#define SOFIA_MULTIPART_PREFIX_T "~sip_mp_"
#define SOFIA_SIP_HEADER_PREFIX "sip_h_"
#define SOFIA_SIP_INFO_HEADER_PREFIX "sip_info_h_"
#define SOFIA_SIP_INFO_HEADER_PREFIX_T "~sip_info_h_"
#define SOFIA_SIP_RESPONSE_HEADER_PREFIX "sip_rh_"
#define SOFIA_SIP_RESPONSE_HEADER_PREFIX_T "~sip_rh_"
#define SOFIA_SIP_BYE_HEADER_PREFIX "sip_bye_h_"
@@ -109,7 +112,7 @@ typedef struct private_object private_object_t;
#define SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE "sip_secure_media_confirmed"
#define SOFIA_HAS_CRYPTO_VARIABLE "sip_has_crypto"
#define SOFIA_CRYPTO_MANDATORY_VARIABLE "sip_crypto_mandatory"
#define FREESWITCH_SUPPORT "update_display"
#define FREESWITCH_SUPPORT "update_display,send_info"
#include <switch_stun.h>
#include <sofia-sip/nua.h>
@@ -128,6 +131,9 @@ typedef struct private_object private_object_t;
#include "sofia-sip/sip_parser.h"
#include "sofia-sip/tport_tag.h"
#include <sofia-sip/msg.h>
#ifndef WIN32
#include <sofia-sip/uniqueid.h>
#endif
typedef enum {
DTMF_2833,
@@ -200,6 +206,7 @@ typedef enum {
PFLAG_WORKER_RUNNING,
PFLAG_UNREG_OPTIONS_FAIL,
PFLAG_DISABLE_TIMER,
PFLAG_ENABLE_RFC5626,
PFLAG_DISABLE_100REL,
PFLAG_AGGRESSIVE_NAT_DETECTION,
PFLAG_RECIEVED_IN_NAT_REG_CONTACT,
@@ -214,7 +221,7 @@ typedef enum {
PFLAG_UUID_AS_CALLID,
PFLAG_SCROOGE,
PFLAG_MANAGE_SHARED_APPEARANCE,
PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO,
PFLAG_STANDBY,
PFLAG_DISABLE_SRV,
PFLAG_DISABLE_SRV503,
PFLAG_DISABLE_NAPTR,
@@ -230,6 +237,7 @@ typedef enum {
PFLAG_AUTO_NAT,
PFLAG_SIPCOMPACT,
PFLAG_SQL_IN_TRANS,
PFLAG_PRESENCE_PRIVACY,
PFLAG_PASS_CALLEE_ID,
PFLAG_LOG_AUTH_FAIL,
PFLAG_FORWARD_MWI_NOTIFY,
@@ -253,6 +261,8 @@ typedef enum {
PFLAG_AUTO_ASSIGN_PORT,
PFLAG_AUTO_ASSIGN_TLS_PORT,
PFLAG_SHUTDOWN,
PFLAG_PRESENCE_MAP,
PFLAG_OPTIONS_RESPOND_503_ON_BUSY,
/* No new flags below this line */
PFLAG_MAX
} PFLAGS;
@@ -472,6 +482,7 @@ struct sofia_gateway {
int32_t retry_seconds;
int32_t reg_timeout_seconds;
int32_t failure_status;
sub_state_t sub_state;
reg_state_t state;
switch_memory_pool_t *pool;
int deleted;
@@ -543,6 +554,7 @@ struct sofia_profile {
char *record_template;
char *record_path;
char *presence_hosts;
char *presence_privacy;
char *challenge_realm;
char *rtcp_audio_interval_msec;
char *rtcp_video_interval_msec;
@@ -625,6 +637,8 @@ struct sofia_profile {
uint32_t event_timeout;
int watchdog_enabled;
switch_mutex_t *gw_mutex;
uint32_t queued_events;
uint32_t cseq_base;
};
struct private_object {
@@ -790,6 +804,7 @@ typedef enum {
AUTH_OK,
AUTH_FORBIDDEN,
AUTH_STALE,
AUTH_RENEWED,
} auth_res_t;
typedef struct {
@@ -830,6 +845,8 @@ switch_mutex_unlock(obj->flag_mutex);
/* Function Prototypes */
/*************************************************************************************************************************************************************/
void sofia_glue_global_standby(switch_bool_t on);
switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_flag_t myflags);
void sofia_glue_deactivate_rtp(private_object_t *tech_pvt);
@@ -1033,7 +1050,7 @@ int sofia_glue_transport_has_tls(const sofia_transport_t tp);
const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name);
switch_status_t sofia_glue_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction);
void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt);
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt);
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str);
void sofia_presence_event_thread_start(void);
void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot);
void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id);
@@ -1055,24 +1072,6 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout);
void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist);
/*
* SLA (shared line appearance) entrypoints
*/
void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const *sip,
sofia_dispatch_event_t *de, long exptime, const char *full_contact);
void sofia_sla_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, tagi_t tags[]);
void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, tagi_t tags[]);
void sofia_sla_handle_sip_r_subscribe(int status,
char const *phrase,
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
sofia_dispatch_event_t *de,
tagi_t tags[]);
void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, tagi_t tags[]);
/*
* Logging control functions
*/
@@ -1104,7 +1103,7 @@ void sofia_glue_free_destination(sofia_destination_t *dst);
switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *user, const char *host, const char *event, const char *contenttype,
const char *body, const char *o_contact, const char *network_ip);
char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix);
void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix);
void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix);
void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg);
void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t send);
void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number);
@@ -1135,4 +1134,5 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np);
void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on);
void sofia_process_dispatch_event(sofia_dispatch_event_t **dep);
char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool);
void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now);
+421 -91
View File
@@ -31,6 +31,7 @@
* Norman Brandinger
* Raymond Chandler <intralanman@gmail.com>
* Nathan Patrick <npatrick at corp.sonic.net>
* Joseph Sullivan <jossulli@amazon.com>
*
*
* sofia.c -- SOFIA SIP Endpoint (sofia code)
@@ -89,7 +90,8 @@ void sofia_handle_sip_r_notify(switch_core_session_t *session, int status,
if (status >= 300 && sip && sip->sip_call_id && (!sofia_private || !sofia_private->is_call)) {
char *sql;
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id);
sql = switch_mprintf("update sip_subscriptions set expires=%ld where call_id='%q'", (long) switch_epoch_time_now(NULL), sip->sip_call_id->i_id);
switch_assert(sql != NULL);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
nua_handle_destroy(nh);
@@ -182,15 +184,78 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip,
su_free(nh->nh_home, full);
}
}
if (sip->sip_via) {
if ((full = sip_header_as_string(nh->nh_home, (void *) sip->sip_via))) {
const char *v = switch_channel_get_variable(channel, "sip_full_via");
if (!v) {
switch_channel_set_variable(channel, "sip_full_via", full);
}
su_free(nh->nh_home, full);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (sip->sip_contact) {
char *c = sip_header_as_string(nh->nh_home, (void *) sip->sip_contact);
switch_channel_set_variable(channel, "sip_recover_contact", c);
su_free(nh->nh_home, c);
}
}
if (sip->sip_record_route) {
sip_record_route_t *rrp;
switch_stream_handle_t stream = { 0 };
int x = 0;
SWITCH_STANDARD_STREAM(stream);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
char *tmp[128] = { 0 };
int y = 0;
for(rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) {
char *rr = sip_header_as_string(nh->nh_home, (void *) rrp);
tmp[y++] = rr;
if (y == 127) break;
}
y--;
while(y >= 0) {
stream.write_function(&stream, x == 0 ? "%s" : ",%s", tmp[y]);
su_free(nh->nh_home, tmp[y]);
y--;
x++;
}
} else {
for(rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) {
char *rr = sip_header_as_string(nh->nh_home, (void *) rrp);
stream.write_function(&stream, x == 0 ? "%s" : ",%s", rr);
su_free(nh->nh_home, rr);
x++;
}
}
switch_channel_set_variable(channel, "sip_invite_record_route", (char *)stream.data);
free(stream.data);
}
if (sip->sip_via) {
sip_via_t *vp;
switch_stream_handle_t stream = { 0 };
int x = 0;
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
SWITCH_STANDARD_STREAM(stream);
for(vp = sip->sip_via; vp; vp = vp->v_next) {
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
stream.write_function(&stream, x == 0 ? "%s" : ",%s", v);
su_free(nh->nh_home, v);
x++;
}
switch_channel_set_variable(channel, "sip_recover_via", (char *)stream.data);
free(stream.data);
}
}
if (sip->sip_from) {
char *p = strip_quotes(sip->sip_from->a_display);
@@ -203,6 +268,7 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip,
su_free(nh->nh_home, full);
}
}
if (sip->sip_to) {
char *p = strip_quotes(sip->sip_to->a_display);
@@ -274,21 +340,6 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
goto error;
}
/* the following could be refactored back to the calling event handler here in sofia.c XXX MTK */
/* potentially interesting note: for Linksys shared appearance, we'll probably have to set up to get bare notifies
* and pass them inward to the sla handler. we'll have to set NUTAG_APPL_METHOD("NOTIFY") when creating
* nua, and also pick them off special elsewhere here in sofia.c - MTK
* *and* for Linksys, I believe they use "sa" as their magic appearance agent name for those blind notifies, so
* we'll probably have to change to match
*/
if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
if (sip->sip_request->rq_url->url_user && !strncmp(sip->sip_request->rq_url->url_user, "sla-agent", sizeof("sla-agent"))) {
sofia_sla_handle_sip_i_notify(nua, profile, nh, sip, de, tags);
goto end;
}
}
/* Automatically return a 200 OK for Event: keep-alive */
if (!strcasecmp(sip->sip_event->o_type, "keep-alive")) {
/* XXX MTK - is this right? in this case isn't sofia is already sending a 200 itself also? */
@@ -413,7 +464,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
/* dispatch freeswitch event */
if (switch_event_create(&s_event, SWITCH_EVENT_NOTIFY_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event", sip->sip_event->o_type);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "pl_data", sip->sip_payload->pl_data);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "pl_data", sip->sip_payload ? sip->sip_payload->pl_data : "");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_content_type", sip->sip_content_type->c_type);
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", sofia_private->gateway->profile->sip_port);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
@@ -545,7 +596,6 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status,
switch_snprintf(st, sizeof(st), "%d", status);
switch_channel_set_variable(channel, "sip_term_status", st);
switch_snprintf(st, sizeof(st), "sip:%d", status);
switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
if (phrase) {
@@ -556,7 +606,7 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status,
switch_channel_set_variable(channel, "sip_term_cause", st);
extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX);
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
if (!(vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) || switch_true(vval)) {
switch_core_session_t *nsession = NULL;
@@ -695,6 +745,7 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro
if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Display-Name"))) {
name = (char *) val;
check_decode(name, session);
fs++;
}
@@ -806,8 +857,7 @@ static void our_sofia_event_callback(nua_event_t event,
int locked = 0;
int check_destroy = 1;
if (sofia_private && sofia_private->de) {
if (sofia_private && sofia_private->is_call && sofia_private->de) {
sofia_dispatch_event_t *qde = sofia_private->de;
sofia_private->de = NULL;
sofia_process_dispatch_event(&qde);
@@ -874,7 +924,7 @@ static void our_sofia_event_callback(nua_event_t event,
uint32_t sess_count = switch_core_session_count();
uint32_t sess_max = switch_core_session_limit(0);
if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready()) {
if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound()) {
nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No more sessions allowed at this time.\n");
@@ -883,7 +933,8 @@ static void our_sofia_event_callback(nua_event_t event,
}
}
if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) {
if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip && (event < nua_r_set_params || event > nua_r_authenticate)) {
sip_authorization_t const *authorization = NULL;
if (sip->sip_authorization) {
@@ -900,7 +951,7 @@ static void our_sofia_event_callback(nua_event_t event,
REG_INVITE, NULL, NULL, NULL);
}
if (auth_res != AUTH_OK) {
if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
//switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
nua_respond(nh, SIP_401_UNAUTHORIZED, TAG_END());
goto done;
@@ -1136,7 +1187,8 @@ void sofia_process_dispatch_event(sofia_dispatch_event_t **dep)
sofia_dispatch_event_t *de = *dep;
nua_handle_t *nh = de->nh;
nua_t *nua = de->nua;
sofia_profile_t *profile = de->profile;
*dep = NULL;
our_sofia_event_callback(de->data->e_event, de->data->e_status, de->data->e_phrase, de->nua, de->profile,
@@ -1144,6 +1196,10 @@ void sofia_process_dispatch_event(sofia_dispatch_event_t **dep)
nua_destroy_event(de->event);
su_free(nh->nh_home, de);
switch_mutex_lock(profile->flag_mutex);
profile->queued_events--;
switch_mutex_unlock(profile->flag_mutex);
nua_handle_unref(nh);
nua_stack_unref(nua);
@@ -1244,6 +1300,19 @@ void sofia_event_callback(nua_event_t event,
{
sofia_dispatch_event_t *de;
if (sofia_test_pflag(profile, PFLAG_STANDBY)) {
if (event < nua_r_set_params || event > nua_r_authenticate) {
nua_respond(nh, 503, "System Paused", TAG_END());
}
return;
}
switch_mutex_lock(profile->flag_mutex);
profile->queued_events++;
switch_mutex_unlock(profile->flag_mutex);
de = su_alloc(nh->nh_home, sizeof(*de));
memset(de, 0, sizeof(*de));
nua_save_event(nua, de->event);
@@ -1524,6 +1593,12 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
/* While we're running, or there is a pending sql statment that we haven't appended to sqlbuf yet, because of a lack of buffer space */
while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) || sql) {
if (sofia_test_pflag(profile, PFLAG_STANDBY)) {
switch_yield(1000000);
continue;
}
if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) {
/* Do we have enough statements or is the timeout expired */
while (sql || (sofia_test_pflag(profile, PFLAG_RUNNING) && mod_sofia_globals.running == 1 &&
@@ -1745,6 +1820,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
switch_event_t *s_event;
int use_100rel = !sofia_test_pflag(profile, PFLAG_DISABLE_100REL);
int use_timer = !sofia_test_pflag(profile, PFLAG_DISABLE_TIMER);
int use_rfc_5626 = sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626);
const char *supported = NULL;
int sanity;
switch_thread_t *worker_thread;
@@ -1766,7 +1842,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
goto end;
}
supported = switch_core_sprintf(profile->pool, "%s%sprecondition, path, replaces", use_100rel ? "100rel, " : "", use_timer ? "timer, " : "");
supported = switch_core_sprintf(profile->pool, "%s%s%sprecondition, path, replaces", use_100rel ? "100rel, " : "", use_timer ? "timer, " : "", use_rfc_5626 ? "outbound, " : "");
if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_nat_get_type()) {
if (switch_nat_add_mapping(profile->sip_port, SWITCH_NAT_UDP, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
@@ -1971,7 +2047,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
nua_shutdown(profile->nua);
sanity = 10;
while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN)) {
while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN) || profile->queued_events > 0) {
su_root_step(profile->s_root, 1000);
if (!--sanity) {
break;
@@ -2231,7 +2307,7 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
if ((gateway = switch_core_alloc(profile->pool, sizeof(*gateway)))) {
const char *sipip, *format;
switch_uuid_t uuid;
uint32_t ping_freq = 0, extension_in_contact = 0, distinct_to = 0;
uint32_t ping_freq = 0, extension_in_contact = 0, distinct_to = 0, rfc_5626 = 0;
int ping_max = 1, ping_min = -1;
char *register_str = "true", *scheme = "Digest",
*realm = NULL,
@@ -2246,7 +2322,8 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
*retry_seconds = "30",
*timeout_seconds = "60",
*from_user = "", *from_domain = NULL, *outbound_proxy = NULL, *register_proxy = NULL, *contact_host = NULL,
*contact_params = NULL, *params = NULL, *register_transport = NULL;
*contact_params = NULL, *params = NULL, *register_transport = NULL,
*reg_id = NULL, *str_rfc_5626 = NULL;
if (!context) {
context = "default";
@@ -2369,6 +2446,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
outbound_proxy = val;
} else if (!strcmp(var, "distinct-to")) {
distinct_to = switch_true(val);
} else if (!strcmp(var, "rfc-5626")) {
rfc_5626 = switch_true(val);
} else if (!strcmp(var, "reg-id")) {
reg_id = val;
} else if (!strcmp(var, "contact-params")) {
contact_params = val;
} else if (!strcmp(var, "register-transport")) {
@@ -2382,6 +2463,17 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
gateway->register_transport = transport;
}
}
#ifndef WIN32
/* Windows todo figure this out! */
/* RFC 5626 enable in the GW profile and the UA profile */
if (rfc_5626 && sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626)) {
char str_guid[su_guid_strlen + 1];
su_guid_t guid[1];
su_guid_generate(guid);
su_guid_sprintf(str_guid, su_guid_strlen + 1, guid);
str_rfc_5626 = switch_core_sprintf(gateway->pool, ";reg-id=%s;+sip.instance=\"<urn:uuid:%s>\"",reg_id,str_guid);
}
#endif
if (ping_freq) {
if (ping_freq >= 5) {
@@ -2406,14 +2498,16 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
}
}
if (zstr(username)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: username param is REQUIRED!\n");
goto skip;
}
if (switch_true(register_str)) {
if (zstr(username)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: username param is REQUIRED!\n");
goto skip;
}
if (zstr(password)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: password param is REQUIRED!\n");
goto skip;
if (zstr(password)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: password param is REQUIRED!\n");
goto skip;
}
}
if (zstr(from_user)) {
@@ -2546,17 +2640,36 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
}
if (extension_in_contact) {
format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d%s>" : "<sip:%s@%s:%d%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params);
if (rfc_5626) {
format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d>%s" : "<sip:%s@%s:%d%s>%s";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params, str_rfc_5626);
} else {
format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d%s>" : "<sip:%s@%s:%d%s%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params,contact_params);
}
} else {
format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>" : "<sip:gw+%s@%s:%d%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params);
if (rfc_5626) {
format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>%s" : "<sip:gw+%s@%s:%d%s>%s";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params, str_rfc_5626);
} else {
format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>" : "<sip:gw+%s@%s:%d%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params);
}
}
gateway->expires_str = switch_core_strdup(gateway->pool, expire_seconds);
@@ -2766,6 +2879,7 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
/* you could change profile->foo here if it was a minor change like context or dialplan ... */
profile->acl_count = 0;
profile->nat_acl_count = 0;
profile->reg_acl_count = 0;
profile->proxy_acl_count = 0;
sofia_set_pflag(profile, PFLAG_STUN_ENABLED);
@@ -2861,6 +2975,18 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL);
}
} else if (!strcasecmp(var, "presence-proto-lookup")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_MAP);
} else {
sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP);
}
} else if (!strcasecmp(var, "profile-standby")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_STANDBY);
} else {
sofia_clear_pflag(profile, PFLAG_STANDBY);
}
} else if (!strcasecmp(var, "liberal-dtmf")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF);
@@ -3079,6 +3205,8 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
profile->user_agent_filter = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "max-registrations-per-extension")) {
profile->max_registrations_perext = atoi(val);
} else if (!strcasecmp(var,"presence-privacy")) {
profile->presence_privacy = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "rfc2833-pt")) {
profile->te = (switch_payload_t) atoi(val);
} else if (!strcasecmp(var, "cng-pt") && !(sofia_test_pflag(profile, PFLAG_SUPPRESS_CNG))) {
@@ -3292,6 +3420,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
profile->timer_t4 = 4000;
}
nua_set_params(profile->nua, NTATAG_SIP_T4(profile->timer_t4), TAG_END());
} else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
} else {
sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
}
}
}
}
@@ -3524,8 +3658,9 @@ switch_status_t config_sofia(int reload, char *profile_name)
profile->contact_user = SOFIA_DEFAULT_CONTACT_USER;
sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER);
sofia_set_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER);
sofia_set_pflag(profile, PFLAG_SQL_IN_TRANS);
sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
profile->shutdown_type = "false";
profile->local_network = "localnet.auto";
sofia_set_flag(profile, TFLAG_ENABLE_SOA);
@@ -3576,6 +3711,18 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL);
}
} else if (!strcasecmp(var, "presence-proto-lookup")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_MAP);
} else {
sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP);
}
} else if (!strcasecmp(var, "profile-standby")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_STANDBY);
} else {
sofia_clear_pflag(profile, PFLAG_STANDBY);
}
} else if (!strcasecmp(var, "liberal-dtmf")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF);
@@ -3632,7 +3779,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
}
} else if (!strcasecmp(var, "send-presence-on-register")) {
if (switch_true(val)) {
if (switch_true(val) || !strcasecmp(val, "all")) {
sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
} else if (!strcasecmp(val, "first-only")) {
sofia_clear_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
@@ -3968,6 +4115,10 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else if (switch_true(val)) {
profile->pres_type = PRES_TYPE_FULL;
}
} else if (!strcasecmp(var, "presence-privacy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_PRIVACY);
}
} else if (!strcasecmp(var, "manage-shared-appearance")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE);
@@ -3975,8 +4126,9 @@ switch_status_t config_sofia(int reload, char *profile_name)
sofia_set_pflag(profile, PFLAG_MULTIREG);
} else if (!strcasecmp(val, "sylantro")) {
profile->sla_contact = switch_core_sprintf(profile->pool, "sla-agent");
sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Sylantro support has been removed.\n"
"It was incomplete anyway, and we fully support the broadsoft SCA shared line spec.");
}
} else if (!strcasecmp(var, "disable-srv")) {
if (switch_true(val)) {
@@ -4125,6 +4277,10 @@ switch_status_t config_sofia(int reload, char *profile_name)
if (!switch_true(val)) {
sofia_set_pflag(profile, PFLAG_DISABLE_TIMER);
}
} else if (!strcasecmp(var, "enable-rfc-5626")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_ENABLE_RFC5626);
}
} else if (!strcasecmp(var, "minimum-session-expires")) {
profile->minimum_session_expires = atoi(val);
/* per RFC 4028: minimum_session_expires must be > 90 */
@@ -4288,6 +4444,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
profile->timer_t4 = 4000;
}
} else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
} else {
sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
}
} else if (!strcasecmp(var, "reuse-connections")) {
switch_bool_t value = switch_true(val);
if (!value) {
@@ -4510,6 +4672,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
switch_caller_profile_t *caller_profile = NULL;
int has_t38 = 0;
switch_channel_clear_flag(channel, CF_REQ_MEDIA);
if (status >= 900) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s status %d received.\n",
switch_channel_get_name(channel), status);
return;
}
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
switch_channel_set_variable_printf(channel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip);
@@ -4523,8 +4693,6 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
caller_profile->network_addr = switch_core_strdup(caller_profile->pool, network_ip);
}
switch_channel_clear_flag(channel, CF_REQ_MEDIA);
tech_pvt->last_sdp_str = NULL;
if (!sofia_use_soa(tech_pvt) && sip->sip_payload && sip->sip_payload->pl_data) {
tech_pvt->last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
@@ -4609,9 +4777,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
const char *vval;
if (status > 199) {
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
} else {
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
}
@@ -4814,10 +4982,15 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
if (sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) {
if (!switch_channel_test_flag(channel, CF_PROXY_MODE) &&
sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) {
has_t38 = 1;
}
if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU);
}
if (switch_channel_test_flag(channel, CF_PROXY_MODE) ||
switch_channel_test_flag(channel, CF_PROXY_MEDIA) ||
(sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && (has_t38 || status > 299))) {
@@ -4835,9 +5008,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) {
tech_pvt->remote_sdp_str = switch_core_session_strdup(tech_pvt->session, sip->sip_payload->pl_data);
r_sdp = tech_pvt->remote_sdp_str;
sofia_glue_tech_proxy_remote_addr(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase);
if (status > 299) {
@@ -4950,6 +5123,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
!switch_channel_test_flag(channel, CF_RING_READY)) {
const char *from_user = "", *from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = "";
const char *user_agent = "", *call_id = "";
const char *to_tag = "";
const char *from_tag = "";
char *sql = NULL;
if (sip->sip_user_agent) {
@@ -4962,12 +5137,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
if (to) {
from_user = switch_str_nil(to->url_user);
from_tag = switch_str_nil(sip->sip_to->a_tag);
}
if (from) {
from_host = switch_str_nil(from->url_host);
to_user = switch_str_nil(from->url_user);
to_host = switch_str_nil(from->url_host);
to_tag = switch_str_nil(sip->sip_from->a_tag);
}
if (contact) {
@@ -4980,7 +5157,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
const char *presence_id = switch_channel_get_variable(channel, "presence_id");
char *full_contact = "";
char *p = NULL;
time_t now;
if (sip->sip_contact) {
full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact);
}
@@ -4988,16 +5166,19 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
if (call_info && (p = strchr(call_info, ';'))) {
p++;
}
now = switch_epoch_time_now(NULL);
sql = switch_mprintf("insert into sip_dialogs "
"(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,contact_user,"
"contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info) "
"values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')",
"(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user,"
"contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info,rcd) "
"values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)",
call_id,
switch_core_session_get_uuid(session),
to_user, to_host, from_user, from_host, contact_user,
to_user, to_host, to_tag, from_user, from_host, from_tag, contact_user,
contact_host, astate, "outbound", user_agent,
profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact),
switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p));
switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), (long) now);
switch_assert(sql);
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
@@ -5080,6 +5261,83 @@ static void launch_media_on_hold(switch_core_session_t *session)
switch_thread_create(&thread, thd_attr, media_on_hold_thread_run, session, switch_core_session_get_pool(session));
}
static void mark_transfer_record(switch_core_session_t *session, const char *br_a, const char *br_b)
{
switch_core_session_t *br_b_session, *br_a_session;
switch_channel_t *channel;
const char *uvar1, *dvar1, *uvar2, *dvar2;
channel = switch_core_session_get_channel(session);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
uvar1 = "sip_from_user";
dvar1 = "sip_from_host";
} else {
uvar1 = "sip_to_user";
dvar1 = "sip_to_host";
}
if ((br_b_session = switch_core_session_locate(br_b)) ) {
switch_channel_t *br_b_channel = switch_core_session_get_channel(br_b_session);
switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_b_channel);
if (switch_channel_direction(br_b_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
uvar2 = "sip_from_user";
dvar2 = "sip_from_host";
} else {
uvar2 = "sip_to_user";
dvar2 = "sip_to_host";
}
cp->transfer_source = switch_core_sprintf(cp->pool,
"%ld:%s:att_xfer:%s@%s/%s@%s",
(long) switch_epoch_time_now(NULL),
cp->uuid_str,
switch_channel_get_variable(channel, uvar1),
switch_channel_get_variable(channel, dvar1),
switch_channel_get_variable(br_b_channel, uvar2),
switch_channel_get_variable(br_b_channel, dvar2));
switch_channel_add_variable_var_check(br_b_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
switch_channel_set_variable(br_b_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source);
switch_core_session_rwunlock(br_b_session);
}
if ((br_a_session = switch_core_session_locate(br_a)) ) {
switch_channel_t *br_a_channel = switch_core_session_get_channel(br_a_session);
switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_a_channel);
if (switch_channel_direction(br_a_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
uvar2 = "sip_from_user";
dvar2 = "sip_from_host";
} else {
uvar2 = "sip_to_user";
dvar2 = "sip_to_host";
}
cp->transfer_source = switch_core_sprintf(cp->pool,
"%ld:%s:att_xfer:%s@%s/%s@%s",
(long) switch_epoch_time_now(NULL),
cp->uuid_str,
switch_channel_get_variable(channel, uvar1),
switch_channel_get_variable(channel, dvar1),
switch_channel_get_variable(br_a_channel, uvar2),
switch_channel_get_variable(br_a_channel, dvar2));
switch_channel_add_variable_var_check(br_a_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
switch_channel_set_variable(br_a_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source);
switch_core_session_rwunlock(br_a_session);
}
}
static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
char const *phrase,
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
@@ -5212,6 +5470,19 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
status = 183;
}
if (channel && profile->pres_type && ss_state == nua_callstate_ready && status == 200) {
const char* to_tag = "";
char *sql = NULL;
to_tag = switch_str_nil(switch_channel_get_variable(channel, "sip_to_tag"));
sql = switch_mprintf("update sip_dialogs set sip_to_tag='%q' "
"where uuid='%q' and sip_to_tag = ''", to_tag, switch_core_session_get_uuid(session));
if (mod_sofia_globals.debug_presence > 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "QUERY SQL %s\n", sql);
}
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
const char *val;
if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) {
@@ -5401,15 +5672,17 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
const char *br_b = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
char *br_a = b_private->uuid;
if (br_b) {
switch_core_session_t *tmp;
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) &&
switch_core_session_t *tmp;
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) &&
(tmp = switch_core_session_locate(br_a))) {
switch_core_media_bug_transfer_recordings(session, tmp);
switch_core_session_rwunlock(tmp);
}
mark_transfer_record(session, br_a, br_b);
switch_ivr_uuid_bridge(br_a, br_b);
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
@@ -5582,6 +5855,15 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
goto done;
}
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if (sofia_glue_tech_proxy_remote_addr(tech_pvt, r_sdp) == SWITCH_STATUS_SUCCESS) {
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed, NOT proxying re-invite.\n");
switch_core_session_rwunlock(other_session);
goto done;
}
}
msg = switch_core_session_alloc(other_session, sizeof(*msg));
msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
msg->from = __FILE__;
@@ -5902,12 +6184,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_snprintf(st, sizeof(st), "%d", status);
switch_channel_set_variable(channel, "sip_term_status", st);
switch_snprintf(st, sizeof(st), "sip:%d", status);
switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
if (phrase) {
switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase);
}
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
}
switch_snprintf(st, sizeof(st), "%d", cause);
switch_channel_set_variable(channel, "sip_term_cause", st);
@@ -5973,12 +6254,13 @@ void *SWITCH_THREAD_FUNC nightmare_xfer_thread_run(switch_thread_t *thread, void
if ((status = switch_ivr_originate(NULL, &tsession, &cause, nhelper->exten_with_params, timeout, NULL, NULL, NULL,
switch_channel_get_caller_profile(channel_a), nhelper->vars, SOF_NONE, NULL)) == SWITCH_STATUS_SUCCESS) {
if (switch_channel_up(channel_a)) {
if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer"))) {
switch_core_media_bug_transfer_recordings(session, a_session);
}
tuuid_str = switch_core_session_get_uuid(tsession);
mark_transfer_record(session, nhelper->bridge_to_uuid, tuuid_str);
switch_ivr_uuid_bridge(nhelper->bridge_to_uuid, tuuid_str);
switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
@@ -6342,6 +6624,8 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_core_session_rwunlock(tmp);
}
mark_transfer_record(session, br_b, br_a);
switch_ivr_uuid_bridge(br_b, br_a);
switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
@@ -6739,9 +7023,44 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
if (session) {
/* Get the channel */
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *vval;
/* Barf if we didn't get our private */
assert(switch_core_session_get_private(session));
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_INFO_HEADER_PREFIX);
if (sip && sip->sip_content_type && sip->sip_content_type->c_type && !strcasecmp(sip->sip_content_type->c_type, "freeswitch/data")) {
char *data = NULL;
if (sip->sip_payload && sip->sip_payload->pl_data) {
data = sip->sip_payload->pl_data;
}
if ((vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) && switch_true(vval)) {
switch_core_session_t *nsession = NULL;
switch_core_session_get_partner(session, &nsession);
if (nsession) {
switch_core_session_message_t *msg;
switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_INFO_HEADER_PREFIX_T);
msg = switch_core_session_alloc(nsession, sizeof(*msg));
MESSAGE_STAMP_FFL(msg);
msg->message_id = SWITCH_MESSAGE_INDICATE_INFO;
msg->string_array_arg[2] = switch_core_session_strdup(nsession, data);
msg->from = __FILE__;
switch_core_session_queue_message(nsession, msg);
switch_core_session_rwunlock(nsession);
}
}
}
if (sip && sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type &&
!strncasecmp(sip->sip_content_type->c_type, "message", 7) &&
@@ -7229,7 +7548,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
transport = sofia_glue_url2transport(sip->sip_contact->m_url);
tech_pvt->record_route =
tech_pvt->record_route=
switch_core_session_sprintf(session,
"sip:%s@%s%s%s:%d;transport=%s",
sip->sip_contact->m_url->url_user,
@@ -7276,16 +7595,12 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
}
if (sip->sip_from && sip->sip_from->a_url) {
char *tmp;
from_user = sip->sip_from->a_url->url_user;
from_host = sip->sip_from->a_url->url_host;
channel_name = url_set_chanvars(session, sip->sip_from->a_url, sip_from);
if (sip->sip_from->a_url->url_params && (tmp = sofia_glue_find_parameter(sip->sip_from->a_url->url_params, "isup-oli="))) {
aniii = switch_core_session_strdup(session, tmp + 9);
if ((tmp = strchr(aniii, ';'))) {
tmp = '\0';
}
if (sip->sip_from->a_url->url_params) {
aniii = switch_find_parameter(sip->sip_from->a_url->url_params, "isup-oli", switch_core_session_get_pool(session));
}
if (!zstr(from_user)) {
@@ -7627,7 +7942,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (sip->sip_request->rq_url->url_params) {
gw_param_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw=");
gw_param_name = switch_find_parameter(sip->sip_request->rq_url->url_params, "gw", switch_core_session_get_pool(session));
}
if (strstr(destination_number, "gw+")) {
@@ -7971,6 +8286,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
const char *dialog_from_user = "", *dialog_from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = "";
const char *user_agent = "", *call_id = "";
url_t *from = NULL, *to = NULL, *contact = NULL;
const char *to_tag = "";
const char *from_tag = "";
char *sql = NULL;
if (sip->sip_to) {
@@ -7994,11 +8311,13 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (to) {
to_user = switch_str_nil(to->url_user);
to_host = switch_str_nil(to->url_host);
to_tag = switch_str_nil(sip->sip_to->a_tag);
}
if (from) {
dialog_from_user = switch_str_nil(from->url_user);
dialog_from_host = switch_str_nil(from->url_host);
from_tag = switch_str_nil(sip->sip_from->a_tag);
}
if (contact) {
@@ -8011,7 +8330,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
const char *presence_id = switch_channel_get_variable(channel, "presence_id");
char *full_contact = "";
char *p = NULL;
time_t now;
if (sip->sip_contact) {
full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact);
@@ -8025,17 +8344,18 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
}
}
now = switch_epoch_time_now(NULL);
sql = switch_mprintf("insert into sip_dialogs "
"(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,contact_user,"
"contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info) "
"values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')",
"(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user,"
"contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info,rcd) "
"values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)",
call_id,
tech_pvt->sofia_private->uuid,
to_user, to_host, dialog_from_user, dialog_from_host,
to_user, to_host, to_tag, dialog_from_user, dialog_from_host, from_tag,
contact_user, contact_host, "confirmed", "inbound", user_agent,
profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact),
switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p));
switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), now);
switch_assert(sql);
@@ -8088,7 +8408,16 @@ void sofia_handle_sip_i_options(int status,
sofia_dispatch_event_t *de,
tagi_t tags[])
{
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
uint32_t sess_count = switch_core_session_count();
uint32_t sess_max = switch_core_session_limit(0);
if (sofia_test_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY) &&
(sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound())) {
nua_respond(nh, 503, "Maximum Calls In Progress", NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
} else {
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
}
}
void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg)
@@ -8119,6 +8448,7 @@ void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t
if (zstr(acp->caller_id_name)) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", acp->caller_id_number, acp->caller_id_number);
} else {
check_decode(acp->caller_id_name, aleg);
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", acp->caller_id_name, acp->caller_id_number);
}
+199 -52
View File
@@ -1374,7 +1374,7 @@ char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char
}
#define RA_PTR_LEN 512
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str)
{
const char *err;
char rip[RA_PTR_LEN] = "";
@@ -1383,29 +1383,34 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *pe;
int x;
const char *val;
if (zstr(tech_pvt->remote_sdp_str)) {
return SWITCH_STATUS_FALSE;
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(sdp_str)) {
sdp_str = tech_pvt->remote_sdp_str;
}
if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->remote_sdp_str))) {
if (zstr(sdp_str)) {
goto end;
}
if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) {
ip_ptr = p + 9;
}
if ((p = (char *) switch_stristr("m=audio ", tech_pvt->remote_sdp_str))) {
if ((p = (char *) switch_stristr("m=audio ", sdp_str))) {
port_ptr = p + 8;
}
if ((p = (char *) switch_stristr("m=image ", tech_pvt->remote_sdp_str))) {
if ((p = (char *) switch_stristr("m=image ", sdp_str))) {
port_ptr = p + 8;
}
if ((p = (char *) switch_stristr("m=video ", tech_pvt->remote_sdp_str))) {
if ((p = (char *) switch_stristr("m=video ", sdp_str))) {
vid_port_ptr = p + 8;
}
if (!(ip_ptr && port_ptr)) {
return SWITCH_STATUS_FALSE;
goto end;
}
p = ip_ptr;
@@ -1415,7 +1420,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
rip[x++] = *p;
p++;
if (p >= pe) {
return SWITCH_STATUS_FALSE;
goto end;
}
}
@@ -1425,7 +1430,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
rp[x++] = *p;
p++;
if (p >= pe) {
return SWITCH_STATUS_FALSE;
goto end;
}
}
@@ -1435,13 +1440,13 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
rvp[x++] = *p;
p++;
if (p >= pe) {
return SWITCH_STATUS_FALSE;
goto end;
}
}
if (!(*rip && *rp)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "invalid SDP\n");
return SWITCH_STATUS_FALSE;
goto end;
}
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, rip);
@@ -1496,7 +1501,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
return SWITCH_STATUS_SUCCESS;
switch_goto_status(SWITCH_STATUS_BREAK, end);
}
if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"))) {
@@ -1507,6 +1512,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip,
tech_pvt->remote_sdp_audio_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
status = SWITCH_STATUS_GENERR;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
@@ -1518,10 +1524,13 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) {
tech_pvt->check_frames = 0;
}
status = SWITCH_STATUS_SUCCESS;
}
}
return SWITCH_STATUS_SUCCESS;
end:
return status;
}
@@ -1899,11 +1908,14 @@ char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix
return extra_headers;
}
void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix)
void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix)
{
sip_unknown_t *un;
char name[512] = "";
switch_channel_t *channel = switch_core_session_get_channel(session);
char *pstr;
if (!sip || !channel) {
return;
}
@@ -1916,6 +1928,13 @@ void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, c
}
}
}
pstr = switch_core_session_sprintf(session, "execute_on_%sprefix", prefix);
switch_channel_execute_on(channel, pstr);
switch_channel_api_on(channel, pstr);
switch_channel_execute_on(channel, "execute_on_sip_extra_headers");
switch_channel_api_on(channel, "api_on_sip_extra_headers");
}
@@ -1941,7 +1960,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
sofia_destination_t *dst = NULL;
sofia_cid_type_t cid_type = tech_pvt->profile->cid_type;
sip_cseq_t *cseq = NULL;
const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
const char *invite_record_route = switch_channel_get_variable(tech_pvt->channel, "sip_invite_record_route");
const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from");
const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
@@ -1950,6 +1969,23 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
const char *force_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_from");
const char *force_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_to");
char *mp = NULL, *mp_type = NULL;
char *record_route = NULL;
const char *recover_via = NULL;
if (sofia_test_flag(tech_pvt, TFLAG_RECOVERING)) {
const char *recover_contact = switch_channel_get_variable(tech_pvt->channel, "sip_recover_contact");
recover_via = switch_channel_get_variable(tech_pvt->channel, "sip_recover_via");
if (!zstr(invite_record_route)) {
record_route = switch_core_session_sprintf(session, "Record-Route: %s", invite_record_route);
}
if (recover_contact) {
char *tmp = switch_core_session_strdup(session, recover_contact);
tech_pvt->redirected = sofia_glue_get_url_from_contact(tmp, 0);
}
}
rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
@@ -1959,6 +1995,12 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
caller_profile = switch_channel_get_caller_profile(channel);
if (!caller_profile) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
}
cid_name = caller_profile->caller_id_name;
cid_num = caller_profile->caller_id_number;
sofia_glue_tech_prepare_codecs(tech_pvt);
@@ -2051,7 +2093,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
if (!zstr(tech_pvt->gateway_from_str)) {
rpid_domain = switch_core_session_strdup(session, tech_pvt->gateway_from_str);
} else if (!zstr(tech_pvt->from_str)) {
rpid_domain = switch_core_session_strdup(session, tech_pvt->from_str);
rpid_domain = switch_core_session_strdup(session, use_from_str);
}
sofia_glue_get_url_from_contact(rpid_domain, 0);
@@ -2214,10 +2256,14 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
}
switch_channel_set_variable(channel, "sip_req_uri", s);
}
switch_channel_set_variable(channel, "sip_to_host", sofia_glue_get_host(to_str, switch_core_session_get_pool(session)));
switch_channel_set_variable(channel, "sip_from_host", sofia_glue_get_host(from_str, switch_core_session_get_pool(session)));
if (!(tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL,
NUTAG_URL(url_str),
TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
TAG_IF(!zstr(record_route), SIPTAG_HEADER_STR(record_route)),
SIPTAG_TO_STR(to_str), SIPTAG_FROM_STR(from_str), SIPTAG_CONTACT_STR(invite_contact), TAG_END()))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT,
@@ -2376,7 +2422,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if (switch_rtp_ready(tech_pvt->rtp_session)) {
sofia_glue_tech_proxy_remote_addr(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
}
sofia_glue_tech_patch_sdp(tech_pvt);
}
@@ -2441,7 +2487,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)),
TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)),
TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)),
TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)),
TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)),
@@ -2475,7 +2521,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)),
TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)),
TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)),
TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)),
TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)),
@@ -3144,9 +3190,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) {
goto end;
}
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
!((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
@@ -3247,7 +3291,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs | tech_pvt->profile->manual_rtp_bugs);
if ((vad_in && inb) || (vad_out && !inb)) {
switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING);
switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING | SWITCH_VAD_FLAG_EVENTS_TALK | SWITCH_VAD_FLAG_EVENTS_NOTALK);
sofia_set_flag(tech_pvt, TFLAG_VAD);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n",
switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : "");
@@ -3318,6 +3362,9 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) {
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
@@ -3464,9 +3511,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) {
goto end;
}
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
!((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
@@ -4423,26 +4468,33 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
int pass = sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU);
if (var) {
pass = switch_true(var);
if (!(pass = switch_true(var))) {
if (!strcasecmp(var, "once")) {
pass = 2;
}
}
}
/* can't remember if this is necessary but its causing a bug so i'll leave this comment here to remind me
if (sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) {
pass = 0;
}
*/
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) || !switch_rtp_ready(tech_pvt->rtp_session)) {
if ((pass == 2 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) ||
!sofia_test_flag(tech_pvt, TFLAG_REINVITE) ||
switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) ||
!switch_rtp_ready(tech_pvt->rtp_session)) {
pass = 0;
}
if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
switch_core_session_message_t *msg;
char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
char tmp[32] = "";
if (switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean")) &&
switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_pass_broken_boolean"))) {
switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
}
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, t38_options->remote_ip);
tech_pvt->remote_sdp_audio_port = t38_options->remote_port;
@@ -4469,7 +4521,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
}
sofia_glue_copy_t38_options(t38_options, other_session);
@@ -5260,6 +5312,30 @@ void sofia_glue_global_siptrace(switch_bool_t on)
}
void sofia_glue_global_standby(switch_bool_t on)
{
switch_hash_index_t *hi;
const void *var;
void *val;
sofia_profile_t *pptr;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((pptr = (sofia_profile_t *) val)) {
if (on) {
sofia_set_pflag_locked(pptr, PFLAG_STANDBY);
} else {
sofia_clear_pflag_locked(pptr, PFLAG_STANDBY);
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
void sofia_glue_global_capture(switch_bool_t on)
{
switch_hash_index_t *hi;
@@ -5355,6 +5431,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
switch_channel_t *channel;
private_object_t *tech_pvt = NULL;
const char *tmp;
const char *rr;
xml = switch_xml_parse_str_dynamic(argv[3], SWITCH_TRUE);
@@ -5362,7 +5439,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
return 0;
if (!(session = switch_core_session_request_xml(sofia_endpoint_interface, NULL, xml))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "skipping non-bridged entry\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid cdr data, call not recovered\n");
return 0;
}
@@ -5395,20 +5472,22 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
}
}
rr = switch_channel_get_variable(channel, "sip_invite_record_route");
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_req_uri"));
switch_channel_set_variable(channel, "sip_invite_full_via", switch_channel_get_variable(channel, "sip_full_via"));
switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, "sip_full_from"));
switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, "sip_full_to"));
} else {
tech_pvt->redirected = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_contact_uri"));
switch_channel_set_variable_printf(channel, "sip_invite_route_uri", "<sip:%s@%s:%s;lr>",
switch_channel_get_variable(channel, "sip_from_user"),
switch_channel_get_variable(channel, "sip_network_ip"), switch_channel_get_variable(channel, "sip_network_port")
);
if (zstr(rr)) {
switch_channel_set_variable_printf(channel, "sip_invite_route_uri", "<sip:%s@%s:%s;lr>",
switch_channel_get_variable(channel, "sip_from_user"),
switch_channel_get_variable(channel, "sip_network_ip"), switch_channel_get_variable(channel, "sip_network_port")
);
}
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_from_uri"));
@@ -5421,6 +5500,10 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
}
}
if (rr) {
switch_channel_set_variable(channel, "sip_invite_route_uri", rr);
}
tech_pvt->dest_to = tech_pvt->dest;
sofia_glue_attach_private(session, h->profile, tech_pvt, NULL);
@@ -5615,6 +5698,8 @@ int sofia_glue_recover(switch_bool_t flush)
h.profile = profile;
h.total = 0;
sofia_clear_pflag_locked(profile, PFLAG_STANDBY);
if (flush) {
sql = switch_mprintf("delete from sip_recovery where profile_name='%q'", profile->name);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
@@ -5818,7 +5903,10 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
" call_info_state VARCHAR(255),\n"
" expires INTEGER default 0,\n"
" status VARCHAR(255),\n"
" rpid VARCHAR(255)\n"
" rpid VARCHAR(255),\n"
" sip_to_tag VARCHAR(255),\n"
" sip_from_tag VARCHAR(255),\n"
" rcd INTEGER not null default 0\n"
");\n";
char sub_sql[] =
@@ -5841,7 +5929,9 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
" hostname VARCHAR(255),\n"
" network_port VARCHAR(6),\n"
" network_ip VARCHAR(255),\n"
" version INTEGER DEFAULT 0 NOT NULL\n"
" version INTEGER DEFAULT 0 NOT NULL,\n"
" orig_proto VARCHAR(255),\n"
" full_to VARCHAR(255)\n"
");\n";
char auth_sql[] =
@@ -5881,6 +5971,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
"create index sr_call_id on sip_registrations (call_id)",
"create index sr_sip_user on sip_registrations (sip_user)",
"create index sr_sip_host on sip_registrations (sip_host)",
"create index sr_mwi_user on sip_registrations (mwi_user)",
"create index sr_mwi_host on sip_registrations (mwi_host)",
"create index sr_profile_name on sip_registrations (profile_name)",
"create index sr_presence_hosts on sip_registrations (presence_hosts)",
"create index sr_contact on sip_registrations (contact)",
@@ -5903,15 +5995,37 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
"create index ss_proto on sip_subscriptions (proto)",
"create index ss_sub_to_user on sip_subscriptions (sub_to_user)",
"create index ss_sub_to_host on sip_subscriptions (sub_to_host)",
"create index ss_expires on sip_subscriptions (expires)",
"create index ss_orig_proto on sip_subscriptions (orig_proto)",
"create index ss_network_port on sip_subscriptions (network_port)",
"create index ss_profile_name on sip_subscriptions (profile_name)",
"create index ss_version on sip_subscriptions (version)",
"create index ss_full_from on sip_subscriptions (full_from)",
"create index ss_contact on sip_subscriptions (contact)",
"create index sd_uuid on sip_dialogs (uuid)",
"create index sd_hostname on sip_dialogs (hostname)",
"create index sd_presence_data on sip_dialogs (presence_data)",
"create index sd_call_info on sip_dialogs (call_info)",
"create index sd_call_info_state on sip_dialogs (call_info_state)",
"create index sd_expires on sip_dialogs (expires)",
"create index sd_rcd on sip_dialogs (rcd)",
"create index sd_sip_to_tag on sip_dialogs (sip_to_tag)",
"create index sd_sip_from_user on sip_dialogs (sip_from_user)",
"create index sd_sip_from_host on sip_dialogs (sip_from_host)",
"create index sd_sip_to_host on sip_dialogs (sip_to_host)",
"create index sd_presence_id on sip_dialogs (presence_id)",
"create index sd_call_id on sip_dialogs (call_id)",
"create index sd_sip_from_tag on sip_dialogs (sip_from_tag)",
"create index sp_hostname on sip_presence (hostname)",
"create index sp_open_closed on sip_presence (open_closed)",
"create index sp_sip_user on sip_presence (sip_user)",
"create index sp_sip_host on sip_presence (sip_host)",
"create index sp_profile_name on sip_presence (profile_name)",
"create index sp_expires on sip_presence (expires)",
"create index sa_nonce on sip_authentication (nonce)",
"create index sa_hostname on sip_authentication (hostname)",
"create index sa_expires on sip_authentication (expires)",
"create index sa_last_nc on sip_authentication (last_nc)",
"create index ssa_hostname on sip_shared_appearance_subscriptions (hostname)",
"create index ssa_network_ip on sip_shared_appearance_subscriptions (network_ip)",
"create index ssa_subscriber on sip_shared_appearance_subscriptions (subscriber)",
@@ -5960,13 +6074,13 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
free(test_sql);
test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and version < 0 and network_ip like '%%' and network_port like '%%'",
mod_sofia_globals.hostname);
test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and full_to='XXX'", mod_sofia_globals.hostname);
switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_subscriptions", sub_sql);
free(test_sql);
test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and expires <> -9999 or rpid=''", mod_sofia_globals.hostname);
test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and (expires <> -9999 or rpid='' or sip_from_tag='' or rcd > 0)",
mod_sofia_globals.hostname);
switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_dialogs", dialog_sql);
@@ -6577,6 +6691,14 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str
if (switch_stristr("~ACCEPT_ANY_PACKETS", str)) {
*flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS;
}
if (switch_stristr("GEN_ONE_GEN_ALL", str)) {
*flag_pole |= RTP_BUG_GEN_ONE_GEN_ALL;
}
if (switch_stristr("~GEN_ONE_GEN_ALL", str)) {
*flag_pole &= ~RTP_BUG_GEN_ONE_GEN_ALL;
}
}
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np)
@@ -6703,6 +6825,31 @@ char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sof
return contact_str;
}
char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool)
{
char *s, *p;
if ((p = strchr(str, '@'))) {
p++;
} else {
return NULL;
}
if (pool) {
s = switch_core_strdup(pool, p);
} else {
s = strdup(p);
}
for (p = s; p && *p; p++) {
if ((*p == ';') || (*p == '>')) {
*p = '\0';
break;
}
}
return s;
}
/* For Emacs:
File diff suppressed because it is too large Load Diff
+172 -124
View File
@@ -65,10 +65,73 @@ static void sofia_reg_new_handle(sofia_gateway_t *gateway_ptr, int attach)
}
}
static void sofia_reg_new_sub_handle(sofia_gateway_t *gateway_ptr, int attach)
{
char *user_via = NULL;
char *register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
int ss_state = nua_callstate_authenticating;
/* check for NAT and place a Via header if necessary (hostname or non-local IP) */
if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
}
if (gateway_ptr->sub_nh) {
nua_handle_bind(gateway_ptr->sub_nh, NULL);
nua_handle_destroy(gateway_ptr->sub_nh);
gateway_ptr->sub_nh = NULL;
sofia_private_free(gateway_ptr->sofia_private);
}
gateway_ptr->sub_nh = nua_handle(gateway_ptr->profile->nua, NULL,
NUTAG_URL(gateway_ptr->register_proxy),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_TO_STR(gateway_ptr->register_to),
NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END());
if (attach) {
if (!gateway_ptr->sofia_private) {
gateway_ptr->sofia_private = malloc(sizeof(*gateway_ptr->sofia_private));
switch_assert(gateway_ptr->sofia_private);
}
memset(gateway_ptr->sofia_private, 0, sizeof(*gateway_ptr->sofia_private));
gateway_ptr->sofia_private->gateway = gateway_ptr;
nua_handle_bind(gateway_ptr->sub_nh, gateway_ptr->sofia_private);
}
switch_safe_free(register_host);
switch_safe_free(user_via);
}
static void sofia_reg_kill_sub(sofia_gateway_t *gateway_ptr)
{
if (gateway_ptr->sub_nh) {
nua_handle_bind(gateway_ptr->sub_nh, NULL);
}
if (gateway_ptr->sub_state != SUB_STATE_SUBED && gateway_ptr->sub_state != SUB_STATE_UNSUBSCRIBE) {
if (gateway_ptr->sub_nh) {
nua_handle_destroy(gateway_ptr->sub_nh);
gateway_ptr->sub_nh = NULL;
}
return;
}
if (gateway_ptr->sub_nh) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Subbing %s\n", gateway_ptr->name);
nua_unsubscribe(gateway_ptr->sub_nh, NUTAG_URL(gateway_ptr->register_url), TAG_END());
}
}
static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr)
{
if (gateway_ptr->state != REG_STATE_REGED) {
if (gateway_ptr->nh) {
nua_handle_bind(gateway_ptr->nh, NULL);
}
if (gateway_ptr->state != REG_STATE_REGED && gateway_ptr->state != REG_STATE_UNREGISTER) {
if (gateway_ptr->nh) {
nua_handle_destroy(gateway_ptr->nh);
gateway_ptr->nh = NULL;
@@ -76,19 +139,10 @@ static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr)
return;
}
/*
if (!gateway_ptr->nh) {
sofia_reg_new_handle(gateway_ptr, SWITCH_FALSE);
}
*/
if (gateway_ptr->nh) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Registering %s\n", gateway_ptr->name);
nua_unregister(gateway_ptr->nh, NUTAG_URL(gateway_ptr->register_url), NUTAG_REGISTRAR(gateway_ptr->register_proxy), TAG_END());
}
}
void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase)
@@ -111,9 +165,15 @@ void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int sta
void sofia_reg_unregister(sofia_profile_t *profile)
{
sofia_gateway_t *gateway_ptr;
sofia_gateway_subscription_t *gw_sub_ptr;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
if (gateway_ptr->nh) {
nua_handle_bind(gateway_ptr->nh, NULL);
}
if (gateway_ptr->sofia_private) {
sofia_private_free(gateway_ptr->sofia_private);
}
@@ -122,6 +182,12 @@ void sofia_reg_unregister(sofia_profile_t *profile)
sofia_reg_kill_reg(gateway_ptr);
}
for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
if (gw_sub_ptr->state == SUB_STATE_SUBED) {
sofia_reg_kill_sub(gateway_ptr);
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
@@ -140,24 +206,14 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
sofia_gateway_subscription_t *gw_sub_ptr;
for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
int ss_state = nua_callstate_authenticating;
sub_state_t ostate = gw_sub_ptr->state;
char *user_via = NULL;
char *register_host = NULL;
if (!now) {
gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED;
gw_sub_ptr->expires_str = "0";
}
register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
/* check for NAT and place a Via header if necessary (hostname or non-local IP) */
if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
}
switch_safe_free(register_host);
gateway_ptr->sub_state = gw_sub_ptr->state;
switch (ostate) {
case SUB_STATE_NOSUB:
@@ -168,37 +224,17 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
break;
case SUB_STATE_UNSUBSCRIBE:
gw_sub_ptr->state = SUB_STATE_NOSUB;
/* not tested .. */
nua_unsubscribe(gateway_ptr->nh,
NUTAG_URL(gateway_ptr->register_url),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_EVENT_STR(gw_sub_ptr->event),
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
SIPTAG_TO_STR(gateway_ptr->register_from),
SIPTAG_FROM_STR(gateway_ptr->register_from), SIPTAG_CONTACT_STR(gateway_ptr->register_contact), TAG_NULL());
sofia_reg_kill_sub(gateway_ptr);
break;
case SUB_STATE_UNSUBED:
gateway_ptr->sub_nh = nua_handle(gateway_ptr->profile->nua, NULL,
NUTAG_URL(gateway_ptr->register_proxy),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_TO_STR(gateway_ptr->register_to),
NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END());
sofia_reg_new_sub_handle(gateway_ptr, 1);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "subscribing to [%s] on gateway [%s]\n", gw_sub_ptr->event, gateway_ptr->name);
gateway_ptr->sofia_private = malloc(sizeof(*gateway_ptr->sofia_private));
switch_assert(gateway_ptr->sofia_private);
memset(gateway_ptr->sofia_private, 0, sizeof(*gateway_ptr->sofia_private));
gateway_ptr->sofia_private->gateway = gateway_ptr;
nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private);
if (now) {
nua_subscribe(gateway_ptr->sub_nh,
NUTAG_URL(gateway_ptr->register_url),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_EVENT_STR(gw_sub_ptr->event),
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
SIPTAG_TO_STR(gateway_ptr->register_from),
@@ -210,7 +246,6 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
} else {
nua_unsubscribe(gateway_ptr->sub_nh,
NUTAG_URL(gateway_ptr->register_url),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_EVENT_STR(gw_sub_ptr->event),
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
SIPTAG_FROM_STR(gateway_ptr->register_from),
@@ -233,7 +268,7 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
}
break;
}
switch_safe_free(user_via);
}
}
switch_mutex_unlock(profile->gw_mutex);
@@ -676,10 +711,10 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
@@ -687,11 +722,11 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
if (now) {
switch_snprintf(sql, sizeof(sql), "select call_id from sip_shared_appearance_dialogs where hostname='%s' "
switch_snprintfv(sql, sizeof(sql), "select call_id from sip_shared_appearance_dialogs where hostname='%q' "
"and profile_name='%s' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sla_dialog_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%s' and expires <= %ld",
switch_snprintfv(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%q' and expires <= %ld",
mod_sofia_globals.hostname, (long) now);
@@ -700,19 +735,19 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and expires <= %ld and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and expires <= %ld and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
@@ -722,27 +757,20 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
"select call_id from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'", (long) now,
mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%q'",
mod_sofia_globals.hostname);
}
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
sofia_presence_check_subscriptions(profile, now);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
@@ -833,24 +861,24 @@ void sofia_reg_check_sync(sofia_profile_t *profile)
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%q'",
mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_mutex_unlock(profile->ireg_mutex);
@@ -871,10 +899,10 @@ char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const c
cbt.len = len;
if (host) {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')",
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, host, host);
} else {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s'", user);
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q'", user);
}
@@ -900,10 +928,10 @@ switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *p
}
if (host) {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')",
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, host, host);
} else {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s'", user);
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q'", user);
}
@@ -924,10 +952,10 @@ switch_console_callback_match_t *sofia_reg_find_reg_url_with_positive_expires_mu
}
if (host) {
switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')",
switch_snprintfv(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, host, host);
} else {
switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s'", user);
switch_snprintfv(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%q'", user);
}
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_find_reg_with_positive_expires_callback, &cbt);
@@ -1011,7 +1039,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
char contact_str[1024] = "";
uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 0;
uint8_t stale = 0, forbidden = 0;
auth_res_t auth_res;
auth_res_t auth_res = AUTH_OK;
long exptime = 300;
switch_event_t *event;
const char *rpid = "unknown";
@@ -1343,7 +1371,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
}
if (auth_res != AUTH_OK && !stale) {
if (auth_res != AUTH_OK && auth_res != AUTH_RENEWED && !stale) {
if (auth_res == AUTH_FORBIDDEN) {
nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
forbidden = 1;
@@ -1401,7 +1429,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_DEBUG10, "SIP auth challenge (%s) on sofia profile '%s' "
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "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);
}
@@ -1455,38 +1483,51 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
const char *realm = reg_host;
char *url = NULL;
char *contact = NULL;
switch_bool_t update_registration = SWITCH_FALSE;
if (auth_params) {
username = switch_event_get_header(auth_params, "sip_auth_username");
realm = switch_event_get_header(auth_params, "sip_auth_realm");
}
if (auth_res != AUTH_RENEWED) {
if (multi_reg) {
if (multi_reg) {
if (delete_subs) {
if (reg_count == 1) {
sql = switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q' and contact='%q'",
(long) switch_epoch_time_now(NULL), to_user, sub_host, contact_str);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
}
if (delete_subs) {
if (reg_count == 1) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'",
to_user, sub_host, contact_str);
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
}
} else {
if (delete_subs) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
}
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
}
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
} else {
if (delete_subs) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
char buf[32] = "";
sql = switch_mprintf("select count(*) from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
switch_safe_free(sql);
if (atoi(buf) > 0) {
update_registration = SWITCH_TRUE;
}
sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
}
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
@@ -1499,21 +1540,25 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(url);
switch_safe_free(contact);
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
"user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm,"
"mwi_user,mwi_host, orig_server_host, orig_hostname) "
"values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q')",
call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : reg_host,
contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime + 60,
agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm,
mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname);
if (!update_registration) {
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
"user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm,"
"mwi_user,mwi_host, orig_server_host, orig_hostname) "
"values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q')",
call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : reg_host,
contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime + 60,
agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm,
mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname);
} else {
sql = switch_mprintf("update sip_registrations set expires = %ld where sip_user='%q' and sip_host='%q' and contact='%q'", (long) switch_epoch_time_now(NULL) + (long) exptime + 60, to_user, reg_host, contact_str);
}
if (sql) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
if (sofia_reg_reg_count(profile, to_user, reg_host) == 1) {
if (!update_registration && sofia_reg_reg_count(profile, to_user, reg_host) == 1) {
sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' and profile_name='%q' and open_closed='closed'",
to_user, reg_host, profile->name);
if (mod_sofia_globals.debug_presence > 0) {
@@ -1563,7 +1608,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event);
}
#else
if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) ||
(reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) {
@@ -1600,6 +1645,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
(sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-source", "register");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event);
}
@@ -1628,9 +1674,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (delete_subs) {
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q' and contact='%q'",
(long) switch_epoch_time_now(NULL), to_user, sub_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
sql = switch_mprintf("update sip_subscriptions set expires=%ld where call_id='%q'", (long) switch_epoch_time_now(NULL), call_id);
}
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
@@ -1648,7 +1695,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(icontact);
} else {
if (delete_subs) {
if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
if ((sql = switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q'",
(long) switch_epoch_time_now(NULL), to_user, sub_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
}
@@ -1681,7 +1729,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
(reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) {
if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", mwi_user, mwi_host);
switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name);
switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Pofile", profile->name);
switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id);
}
}
@@ -1697,6 +1745,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_fire(&s_event);
}
@@ -1704,6 +1753,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered");
@@ -1774,10 +1824,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_fire(&s_mwi_event);
}
if (contact && *contact_str && sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO)) {
sofia_sla_handle_register(nua, profile, sip, de, exptime, contact_str);
}
switch_goto_int(r, 1, end);
}
@@ -2098,7 +2144,7 @@ void sofia_reg_handle_sip_r_challenge(int status,
switch_event_create(&locate_params, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(locate_params);
switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "Action", "reverse-auth-lookup");
switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "action", "reverse-auth-lookup");
if (switch_xml_locate_user_merged("id", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, NULL,
&x_user, locate_params) == SWITCH_STATUS_SUCCESS) {
@@ -2626,8 +2672,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_safe_free(input2);
skip_auth:
if (first && ret == AUTH_OK) {
if (first && (ret == AUTH_OK || ret == AUTH_RENEWED)) {
if (v_event) {
switch_event_create_plain(v_event, SWITCH_EVENT_REQUEST_PARAMS);
}
@@ -2753,6 +2798,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_assert(sql != NULL);
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
switch_safe_free(sql);
if (ret == AUTH_OK)
ret = AUTH_RENEWED;
}
switch_event_destroy(&params);
@@ -2772,7 +2820,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_safe_free(response);
if (reg_count && !*reg_count) {
if (ret == AUTH_OK) {
if ((ret == AUTH_OK || ret == AUTH_RENEWED)) {
if (ncl) {
*reg_count = ncl;
} else {
-413
View File
@@ -1,413 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* 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 <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
* Ken Rice, Asteria Solutions Group, Inc <ken@asteriasgi.com>
* Paul D. Tinsley <pdt at jackhammer.org>
* Bret McDanel <trixter AT 0xdecafbad.com>
* Brian West <brian@freeswitch.org>
*
* sofia_sla.c -- SOFIA SIP Endpoint (support for shared line appearance)
* This file (and calls into it) developed by Matthew T Kaufman <matthew@matthew.at>
*
*/
#include "mod_sofia.h"
static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **columnNames);
struct sla_helper {
char call_id[1024];
};
static int get_call_id_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct sla_helper *sh = (struct sla_helper *) pArg;
switch_set_string(sh->call_id, argv[0]);
return 0;
}
int sofia_sla_supported(sip_t const *sip)
{
if (sip && sip->sip_user_agent && sip->sip_user_agent->g_string) {
const char *ua = sip->sip_user_agent->g_string;
if (switch_stristr("polycom", ua)) {
return 1;
}
if (switch_stristr("snom", ua)) {
return 1;
}
}
return 0;
}
void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const *sip,
sofia_dispatch_event_t *de, long exptime, const char *full_contact)
{
nua_handle_t *nh = NULL;
char exp_str[256] = "";
char my_contact[256] = "";
char *sql;
struct sla_helper sh = { {0} };
char *contact_str = sofia_glue_strip_uri(full_contact);
sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
char network_ip[80];
int network_port = 0;
sofia_destination_t *dst;
char *route_uri = NULL;
char port_str[25] = "";
nua_handle_t *fnh = NULL;
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
sql = switch_mprintf("select call_id from sip_shared_appearance_dialogs where hostname='%q' and profile_name='%q' and contact_str='%q'",
mod_sofia_globals.hostname, profile->name, contact_str);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, get_call_id_callback, &sh);
free(sql);
if (*sh.call_id) {
if ((nh = nua_handle_by_call_id(profile->nua, sh.call_id))) {
fnh = nh;
} else {
if ((sql = switch_mprintf("delete from sip_shared_appearance_dialogs where hostname='%q' and profile_name='%q' and contact_str='%q'",
mod_sofia_globals.hostname, profile->name, contact_str))) {
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
}
}
if (!nh) {
nh = nua_handle(nua, NULL, NUTAG_URL(sip->sip_contact->m_url), TAG_NULL());
}
nua_handle_bind(nh, &mod_sofia_globals.keep_private);
switch_snprintf(exp_str, sizeof(exp_str), "%ld", exptime + 30);
switch_snprintf(port_str, sizeof(port_str), ":%ld", sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port);
if (sofia_glue_check_nat(profile, network_ip)) {
switch_snprintf(my_contact, sizeof(my_contact), "<sip:%s@%s%s;transport=%s>;expires=%s", profile->sla_contact,
profile->extsipip, port_str, sofia_glue_transport2str(transport), exp_str);
} else {
switch_snprintf(my_contact, sizeof(my_contact), "<sip:%s@%s%s;transport=%s>;expires=%s", profile->sla_contact,
profile->sipip, port_str, sofia_glue_transport2str(transport), exp_str);
}
dst = sofia_glue_get_destination((char *) full_contact);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
nua_subscribe(nh,
TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
SIPTAG_TO(sip->sip_to),
SIPTAG_FROM(sip->sip_to),
SIPTAG_CONTACT_STR(my_contact),
SIPTAG_EXPIRES_STR(exp_str),
SIPTAG_EVENT_STR("dialog;sla;include-session-description"), SIPTAG_ACCEPT_STR("application/dialog-info+xml"), TAG_NULL());
if (fnh) {
nua_handle_unref(fnh);
}
sofia_glue_free_destination(dst);
free(contact_str);
}
void sofia_sla_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, tagi_t tags[])
{
/* at present there's no SLA versions that we deal with that do publish. to be safe, we say "OK" */
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
}
void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, tagi_t tags[])
{
char *aor = NULL;
char *subscriber = NULL;
char *sql = NULL;
char *route_uri = NULL;
char *sla_contact = NULL;
char network_ip[80];
int network_port = 0;
char port_str[25] = "";
sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
/*
* XXX MTK FIXME - we don't look at the tag to see if NUTAG_SUBSTATE(nua_substate_terminated) or
* a Subscription-State header with state "terminated" and/or expiration of 0. So we never forget
* about them here.
* likewise, we also don't have a hook against nua_r_notify events, so we can't see nua_substate_terminated there.
*/
/*
* extracting AOR is weird...
* the From is the main extension, not the third-party one...
* and the contact has the phone's own network address, not the AOR address
* so we do what openser's pua_bla does and...
*/
/* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */
aor = switch_mprintf("sip:%s@%s", sip->sip_contact->m_url->url_user, profile->sipip);
/*
* ok, and now that we HAVE the AOR, we REALLY should go check in the XML config and see if this particular
* extension is set up to have shared appearances managed. right now it is all-or-nothing on the profile,
* which won't be sufficient for real life. FIXME XXX MTK
*/
/* then the subscriber is the user at their network location... this is arguably the wrong way, but works so far... */
subscriber = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_from->a_url->url_user,
sip->sip_contact->m_url->url_host, sofia_glue_transport2str(transport));
if ((sql =
switch_mprintf("delete from sip_shared_appearance_subscriptions where subscriber='%q' and profile_name='%q' and hostname='%q'",
subscriber, profile->name, mod_sofia_globals.hostname))) {
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
if ((sql =
switch_mprintf("insert into sip_shared_appearance_subscriptions (subscriber, call_id, aor, profile_name, hostname, contact_str, network_ip) "
"values ('%q','%q','%q','%q','%q','%q','%q')",
subscriber, sip->sip_call_id->i_id, aor, profile->name, mod_sofia_globals.hostname, contact_str, network_ip))) {
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
if (strstr(contact_str, ";fs_nat")) {
char *p;
route_uri = sofia_glue_get_url_from_contact((char *) contact_str, 1);
if ((p = strstr(contact_str, ";fs_"))) {
*p = '\0';
}
}
if (route_uri) {
char *p;
while (route_uri && *route_uri && (*route_uri == '<' || *route_uri == ' ')) {
route_uri++;
}
if ((p = strchr(route_uri, '>'))) {
*p++ = '\0';
}
}
switch_snprintf(port_str, sizeof(port_str), ":%ld", sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port);
if (sofia_glue_check_nat(profile, network_ip)) {
sla_contact = switch_mprintf("<sip:%s@%s%s;transport=%s>", profile->sla_contact, profile->extsipip, port_str, sofia_glue_transport2str(transport));
} else {
sla_contact = switch_mprintf("<sip:%s@%s%s;transport=%s>", profile->sla_contact, profile->sipip, port_str, sofia_glue_transport2str(transport));
}
nua_respond(nh, SIP_202_ACCEPTED, SIPTAG_CONTACT_STR(sla_contact), NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_IF(route_uri, NUTAG_PROXY(route_uri)), SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=300"), /* you thought the OTHER time was fake... need delta here FIXME XXX MTK */
SIPTAG_EXPIRES_STR("300"), /* likewise, totally fake - FIXME XXX MTK */
/* sofia_presence says something about needing TAG_IF(sticky, NUTAG_PROXY(sticky)) for NAT stuff? */
TAG_END());
switch_safe_free(aor);
switch_safe_free(subscriber);
switch_safe_free(route_uri);
switch_safe_free(sla_contact);
switch_safe_free(sql);
}
struct sla_notify_helper {
sofia_profile_t *profile;
char *payload;
};
void sofia_sla_handle_sip_r_subscribe(int status,
char const *phrase,
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
sofia_dispatch_event_t *de,
tagi_t tags[])
{
if (status >= 300) {
nua_handle_destroy(nh);
sofia_private_free(sofia_private);
} else {
char *full_contact = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_contact);
time_t expires = switch_epoch_time_now(NULL);
char *sql;
char *contact_str = sofia_glue_strip_uri(full_contact);
if (sip && sip->sip_expires) {
expires += sip->sip_expires->ex_delta + 30;
}
if ((sql = switch_mprintf("insert into sip_shared_appearance_dialogs (profile_name, hostname, contact_str, call_id, expires) "
"values ('%q','%q','%q','%q','%ld')",
profile->name, mod_sofia_globals.hostname, contact_str, sip->sip_call_id->i_id, (long) expires))) {
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
free(contact_str);
}
}
void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, tagi_t tags[])
{
char *sql = NULL;
struct sla_notify_helper helper;
char *aor = NULL;
char *contact = NULL;
sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
/*
* things we know we don't do:
* draft-anil-sipping-bla says we should look and see if the specific appearance is in use and if it is
* return an error for the i_notify, to handle the initial line-seize for dialing out case.
* to do that we would need to really track all the appearances *and* override sofia's autoresponder for i_notify
* because at this point, it already sent the 200 for us.
* and we simply don't track all the appearance status by decoding the XML payload out and recording that in
* an SQL line appearance database yet. we'll need to do that in order to do the above, and in order to make
* interoperation possible between devices that disagree on the dialog xml payload OR don't even do it that
* way and instead use things like call-info/line-seize events like the old Broadsoft spec.
* instead we cheat and just reflect the entire payload back to the subscribers (who, because we don't
* yet check each AOR as it comes in to see if it is to be managed, is more subscribers than we probably
* should have). for the current prototype stage, this works ok anyway.
* and because we don't parse the XML, we even reflect it right back to the notifier/sender (which is called
* "target" in the payload XML, of course).
* also because we don't track on a per-appearance basis, there IS NOT a hook back from sofia_glue to add
* an appearance index to the outbound invite for the "next free appearance". this can lead to race
* conditions where a call shows up on slightly different line key numbers at different phones, making
* "pick up on line X" meaningless if such a race occurs. again, it is a prototype. we can fix it later.
*/
/* the dispatcher calls us just because it is aimed at us, so check to see if it is dialog;sla at the very least... */
if ((!sip->sip_event)
|| (strcasecmp(sip->sip_event->o_type, "dialog"))
|| !msg_params_find(sip->sip_event->o_params, "sla")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "sent to sla-agent but not dialog;sla\n");
return;
}
/* calculate the AOR we're trying to tell people about. should probably double-check before derferencing XXX MTK */
/* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */
aor = switch_mprintf("sip:%s@%s", sip->sip_to->a_url->url_user, profile->sipip);
/* this isn't sufficient because on things like the polycom, the subscriber is the 'main' ext number, but the
* 'main' ext number isn't in ANY of the headers they send us in the notify. of course.
* as a side effect, the subscriber<>'%q' below isn't sufficient to prevent reflecting the event back
* at a phone that has the ext # != third-party#. see above, can only fix by parsing the XML for the 'target'
* so we don't reflect it back at anyone who is the "boss" config, but we do reflect it back at the "secretary"
* config. if that breaks the phone, just set them all up as the "boss" config where ext#==third-party#
*/
contact = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_contact->m_url->url_user,
sip->sip_contact->m_url->url_host, sofia_glue_transport2str(transport));
if (sip->sip_payload && sip->sip_payload->pl_data) {
sql = switch_mprintf("select subscriber,call_id,aor,profile_name,hostname,contact_str,network_ip from sip_shared_appearance_subscriptions where "
"aor='%q' and profile_name='%q' and hostname='%q'", aor, profile->name, mod_sofia_globals.hostname);
helper.profile = profile;
helper.payload = sip->sip_payload->pl_data; /* could just send the WHOLE payload. you'd get the type that way. */
/* which mutex if any is correct to hold in this callback? XXX MTK FIXME */
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_sla_sub_callback, &helper);
switch_safe_free(sql);
switch_safe_free(aor);
switch_safe_free(contact);
}
}
static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct sla_notify_helper *helper = pArg;
/* char *subscriber = argv[0]; */
char *call_id = argv[1];
/* char *aor = argv[2]; */
/* char *profile_name = argv[3]; */
/* char *hostname = argv[4]; */
char *contact_str = argv[5];
char *network_ip = argv[6];
nua_handle_t *nh;
char *route_uri = NULL;
char *xml_fixup = NULL;
char *fixup = NULL;
nh = nua_handle_by_call_id(helper->profile->nua, call_id); /* that's all you need to find the subscription's nh */
if (nh) {
if (strstr(contact_str, ";fs_nat")) {
char *p;
route_uri = sofia_glue_get_url_from_contact(contact_str, 1);
if ((p = strstr(contact_str, ";fs_"))) {
*p = '\0';
}
}
if (route_uri) {
char *p;
while (route_uri && *route_uri && (*route_uri == '<' || *route_uri == ' ')) {
route_uri++;
}
if ((p = strchr(route_uri, '>'))) {
*p++ = '\0';
}
}
if (helper->profile->extsipip) {
if (sofia_glue_check_nat(helper->profile, network_ip)) {
fixup = switch_string_replace(helper->payload, helper->profile->sipip, helper->profile->extsipip);
} else {
fixup = switch_string_replace(helper->payload, helper->profile->extsipip, helper->profile->sipip);
}
xml_fixup = fixup;
} else {
xml_fixup = helper->payload;
}
nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=300"), /* XXX MTK FIXME - this is totally fake calculation */
TAG_IF(route_uri, NUTAG_PROXY(route_uri)), SIPTAG_CONTENT_TYPE_STR("application/dialog-info+xml"), /* could've just kept the type from the payload */
SIPTAG_PAYLOAD_STR(xml_fixup), TAG_END());
switch_safe_free(route_uri);
if (fixup && fixup != helper->payload) {
free(fixup);
}
nua_handle_unref(nh);
}
return 0;
}
@@ -164,6 +164,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
write_cdr(sql);
switch_safe_free(sql);
if (expanded_vars != template_str) {
switch_safe_free(expanded_vars);
}
return status;
}
@@ -26,6 +26,8 @@
* Anthony Minessale II <anthm@freeswitch.org>
* Andrew Thompson <andrew@hijacked.us>
* Rob Charlton <rob.charlton@savageminds.com>
* Darren Schreiber <d@d-man.org>
* Mike Jerris <mike@jerris.com>
*
*
* handle_msg.c -- handle messages received from erlang nodes
@@ -590,13 +592,29 @@ static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_
static switch_status_t handle_msg_api(listener_t *listener, erlang_msg * msg, int arity, ei_x_buff * buf, ei_x_buff * rbuf)
{
char api_cmd[MAXATOMLEN];
char arg[1024];
if (arity < 3 || ei_decode_atom(buf->buff, &buf->index, api_cmd) || ei_decode_string(buf->buff, &buf->index, arg)) {
ei_x_encode_tuple_header(rbuf, 2);
ei_x_encode_atom(rbuf, "error");
ei_x_encode_atom(rbuf, "badarg");
return SWITCH_STATUS_SUCCESS;
} else {
int type;
int size;
char *arg;
switch_bool_t fail = SWITCH_FALSE;
if (arity < 3) {
fail = SWITCH_TRUE;
}
ei_get_type(buf->buff, &buf->index, &type, &size);
if ((size > (sizeof(api_cmd) - 1)) || ei_decode_atom(buf->buff, &buf->index, api_cmd)) {
fail = SWITCH_TRUE;
}
ei_get_type(buf->buff, &buf->index, &type, &size);
arg = malloc(size + 1);
if (ei_decode_string(buf->buff, &buf->index, arg)) {
fail = SWITCH_TRUE;
}
if (!fail) {
struct api_command_struct acs = { 0 };
acs.listener = listener;
acs.api_cmd = api_cmd;
@@ -604,8 +622,17 @@ static switch_status_t handle_msg_api(listener_t *listener, erlang_msg * msg, in
acs.bg = 0;
acs.pid = msg->from;
api_exec(NULL, (void *) &acs);
switch_safe_free(arg);
/* don't reply */
return SWITCH_STATUS_FALSE;
} else {
ei_x_encode_tuple_header(rbuf, 2);
ei_x_encode_atom(rbuf, "error");
ei_x_encode_atom(rbuf, "badarg");
return SWITCH_STATUS_SUCCESS;
}
}
@@ -670,18 +697,38 @@ static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_
if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) ||
switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) {
char key[1024];
char value[1024];
char *value;
int type;
int size;
int i = 0;
switch_bool_t fail = SWITCH_FALSE;
while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) {
i++;
if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) {
ei_get_type(buf->buff, &buf->index, &type, &size);
if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) {
fail = SWITCH_TRUE;
break;
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value);
ei_get_type(buf->buff, &buf->index, &type, &size);
value = malloc(size + 1);
if (ei_decode_string(buf->buff, &buf->index, value)) {
fail = SWITCH_TRUE;
break;
}
if (!fail && !strcmp(key, "body")) {
switch_safe_free(event->body);
event->body = value;
} else if (!fail) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value);
}
/* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */
}
if (headerlength != i || fail) {
@@ -715,16 +762,32 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_
if (switch_event_create(&event, SWITCH_EVENT_SEND_MESSAGE) == SWITCH_STATUS_SUCCESS) {
char key[1024];
char value[1024];
char *value;
int type;
int size;
int i = 0;
switch_bool_t fail = SWITCH_FALSE;
while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) {
i++;
if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) {
ei_get_type(buf->buff, &buf->index, &type, &size);
if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) {
fail = SWITCH_TRUE;
break;
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value);
ei_get_type(buf->buff, &buf->index, &type, &size);
value = malloc(size + 1);
if (ei_decode_string(buf->buff, &buf->index, value)) {
fail = SWITCH_TRUE;
break;
}
if (!fail) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value);
}
}
if (headerlength != i || fail) {
@@ -389,6 +389,7 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c
if (!ptr->listener) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NULL pointer binding!\n");
switch_thread_rwlock_unlock(globals.bindings_rwlock);
goto cleanup; /* our pointer is trash */
}
@@ -1818,7 +1819,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_erlang_event_runtime)
#else
errno = 0;
#endif
if ((clientfd = ei_accept_tmo(&ec, (int) listen_list.sockfd, &conn, 100)) == ERL_ERROR) {
if ((clientfd = ei_accept_tmo(&ec, (int) listen_list.sockfd, &conn, 500)) == ERL_ERROR) {
if (prefs.done) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
} else if (erl_errno == ETIMEDOUT) {
@@ -94,6 +94,7 @@ struct listener {
char remote_ip[50];
switch_port_t remote_port;
switch_event_t *filters;
time_t linger_timeout;
struct listener *next;
};
@@ -1095,7 +1096,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load)
static switch_status_t read_packet(listener_t *listener, switch_event_t **event, uint32_t timeout)
{
switch_size_t mlen, bytes = 0;
char mbuf[2048] = "";
char *mbuf = NULL;
char buf[1024] = "";
switch_size_t len;
switch_status_t status = SWITCH_STATUS_SUCCESS;
@@ -1105,16 +1106,20 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
void *pop;
char *ptr;
uint8_t crcount = 0;
uint32_t max_len = sizeof(mbuf);
uint32_t max_len = 10485760, block_len = 2048, buf_len = 0;
switch_channel_t *channel = NULL;
int clen = 0;
*event = NULL;
if (prefs.done) {
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
switch_zmalloc(mbuf, block_len);
switch_assert(mbuf);
buf_len = block_len;
start = switch_epoch_time_now(NULL);
ptr = mbuf;
@@ -1126,10 +1131,24 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
uint8_t do_sleep = 1;
mlen = 1;
if (bytes == buf_len - 1) {
char *tmp;
int pos;
pos = (ptr - mbuf);
buf_len += block_len;
tmp = realloc(mbuf, buf_len);
switch_assert(tmp);
mbuf = tmp;
memset(mbuf + bytes, 0, buf_len - bytes);
ptr = (mbuf + pos);
}
status = switch_socket_recv(listener->sock, ptr, &mlen);
if (prefs.done || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) {
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
if (mlen) {
@@ -1198,7 +1217,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
if (prefs.done || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) {
free(body);
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
/*
@@ -1230,7 +1249,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
elapsed = (uint32_t) (switch_epoch_time_now(NULL) - start);
if (elapsed >= timeout) {
switch_clear_flag_locked(listener, LFLAG_RUNNING);
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
}
@@ -1325,6 +1344,12 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
}
}
if (switch_test_flag(listener, LFLAG_HANDLE_DISCO) && switch_epoch_time_now(NULL) > listener->linger_timeout) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session), SWITCH_LOG_DEBUG, "linger timeout, closing socket\n");
status = SWITCH_STATUS_FALSE;
break;
}
if (channel && switch_channel_down(channel) && !switch_test_flag(listener, LFLAG_HANDLE_DISCO)) {
switch_set_flag_locked(listener, LFLAG_HANDLE_DISCO);
if (switch_test_flag(listener, LFLAG_LINGER)) {
@@ -1354,6 +1379,9 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
}
}
end:
switch_safe_free(mbuf);
return status;
}
@@ -2239,8 +2267,15 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even
}
} else if (!strncasecmp(cmd, "linger", 6)) {
if (listener->session) {
uint32_t linger_time = 600; /* sounds reasonable? */
if (*(cmd+6) == ' ' && *(cmd+7)) { /*how long do you want to linger?*/
linger_time = (uint32_t)atoi(cmd+7);
}
/*do we need a mutex to update linger_timeout ?*/
listener->linger_timeout = switch_epoch_time_now(NULL) + linger_time;
switch_set_flag_locked(listener, LFLAG_LINGER);
switch_snprintf(reply, reply_len, "+OK will linger");
switch_snprintf(reply, reply_len, "+OK will linger %d seconds", linger_time);
} else {
switch_snprintf(reply, reply_len, "-ERR not controlling a session");
}
+1 -1
View File
@@ -1,6 +1,6 @@
json-c=json-c-0.9
BASE=../../../..
WANT_CURL=yes
JSON_DIR=$(switch_srcdir)/libs/$(json-c)
JSON_BUILDDIR=$(switch_builddir)/libs/$(json-c)
@@ -32,7 +32,7 @@
*/
#include <sys/stat.h>
#include <switch.h>
#include <curl/curl.h>
#include <switch_curl.h>
#include <json.h>
#define MAX_URLS 20
@@ -72,6 +72,7 @@ static struct {
int auth_scheme;
switch_memory_pool_t *pool;
switch_event_node_t *node;
int encode_values;
} globals;
SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load);
@@ -249,24 +250,27 @@ static void set_json_chan_vars(struct json_object *json, switch_channel_t *chann
for (; hi; hi = hi->next) {
if (!zstr(hi->name) && !zstr(hi->value)) {
char *data;
switch_size_t dlen = strlen(hi->value) * 3;
char *data = hi->value;
if (globals.encode_values == ENCODING_DEFAULT) {
switch_size_t dlen = strlen(hi->value) * 3;
if ((data = malloc(dlen))) {
memset(data, 0, dlen);
switch_url_encode(hi->value, data, dlen);
variable = json_object_new_string(data);
if (!is_error(variable)) {
json_object_object_add(json, hi->name, variable);
if ((data = malloc(dlen))) {
memset(data, 0, dlen);
switch_url_encode(hi->value, data, dlen);
}
free(data);
}
variable = json_object_new_string(data);
if (!is_error(variable)) {
json_object_object_add(json, hi->name, variable);
}
if (data != hi->value) {
switch_safe_free(data);
}
}
}
switch_channel_variable_last(channel);
return;
}
@@ -610,8 +614,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
uint32_t cur_try;
long httpRes;
CURL *curl_handle = NULL;
struct curl_slist *headers = NULL;
struct curl_slist *slist = NULL;
switch_curl_slist_t *headers = NULL;
switch_curl_slist_t *slist = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_FALSE;
int is_b;
@@ -663,6 +667,9 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
wrote = write(fd, json_text, (unsigned) strlen(json_text));
close(fd);
fd = -1;
if(wrote < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path);
}
} else {
char ebuf[512] = { 0 };
#ifdef WIN32
@@ -681,7 +688,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
/* try to post it to the web server */
if (globals.url_count) {
char *destUrl = NULL;
curl_handle = curl_easy_init();
curl_handle = switch_curl_easy_init();
if (globals.encode) {
switch_size_t need_bytes = strlen(json_text) * 3;
@@ -690,10 +697,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
switch_assert(json_text_escaped);
memset(json_text_escaped, 0, need_bytes);
if (globals.encode == ENCODING_DEFAULT) {
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
switch_url_encode(json_text, json_text_escaped, need_bytes);
} else {
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded");
headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded");
switch_b64_encode((unsigned char *) json_text, need_bytes / 3, (unsigned char *) json_text_escaped, need_bytes);
}
@@ -705,54 +712,55 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
}
} else {
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-plaintext");
headers = switch_curl_slist_append(headers, "Content-Type: application/json");
curl_json_text = (char *)json_text;
}
if (!zstr(globals.cred)) {
curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, globals.auth_scheme);
curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred);
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, globals.auth_scheme);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred);
}
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_POST, 1);
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_json_text);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-json/1.0");
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack);
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
switch_curl_easy_setopt(curl_handle, CURLOPT_POST, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_json_text);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-json/1.0");
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack);
if (globals.disable100continue) {
slist = curl_slist_append(slist, "Expect:");
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
slist = switch_curl_slist_append(slist, "Expect:");
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
}
if (globals.ssl_cert_file) {
curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, globals.ssl_cert_file);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, globals.ssl_cert_file);
}
if (globals.ssl_key_file) {
curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, globals.ssl_key_file);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, globals.ssl_key_file);
}
if (globals.ssl_key_password) {
curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, globals.ssl_key_password);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, globals.ssl_key_password);
}
if (globals.ssl_version) {
if (!strcasecmp(globals.ssl_version, "SSLv3")) {
curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
} else if (!strcasecmp(globals.ssl_version, "TLSv1")) {
curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
}
}
if (globals.ssl_cacert_file) {
curl_easy_setopt(curl_handle, CURLOPT_CAINFO, globals.ssl_cacert_file);
switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, globals.ssl_cacert_file);
}
/* these were used for testing, optionally they may be enabled if someone desires
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 120); // tcp timeout
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 120); // tcp timeout
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level
*/
for (cur_try = 0; cur_try < globals.retries; cur_try++) {
@@ -761,25 +769,25 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
}
destUrl = switch_mprintf("%s?uuid=%s", globals.urls[globals.url_index], switch_core_session_get_uuid(session));
curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl);
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl);
if (!strncasecmp(destUrl, "https", 5)) {
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
if (globals.enable_cacert_check) {
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE);
}
if (globals.enable_ssl_verifyhost) {
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
}
curl_easy_perform(curl_handle);
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_safe_free(destUrl);
if (httpRes == 200) {
if (httpRes >= 200 && httpRes < 300) {
goto success;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Got error [%ld] posting to web server [%s]\n",
@@ -792,9 +800,9 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retry will be with url [%s]\n", globals.urls[globals.url_index]);
}
}
curl_easy_cleanup(curl_handle);
curl_slist_free_all(headers);
curl_slist_free_all(slist);
switch_curl_easy_cleanup(curl_handle);
switch_curl_slist_free_all(headers);
switch_curl_slist_free_all(slist);
slist = NULL;
headers = NULL;
curl_handle = NULL;
@@ -816,6 +824,9 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
wrote = write(fd, json_text, (unsigned) strlen(json_text));
close(fd);
fd = -1;
if(wrote < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path);
}
break;
} else {
char ebuf[512] = { 0 };
@@ -837,13 +848,13 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
error:
if (curl_handle) {
curl_easy_cleanup(curl_handle);
switch_curl_easy_cleanup(curl_handle);
}
if (headers) {
curl_slist_free_all(headers);
switch_curl_slist_free_all(headers);
}
if (slist) {
curl_slist_free_all(slist);
switch_curl_slist_free_all(slist);
}
if (curl_json_text != json_text) {
switch_safe_free(curl_json_text);
@@ -903,6 +914,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load)
globals.disable100continue = 0;
globals.pool = pool;
globals.auth_scheme = CURLAUTH_BASIC;
globals.encode_values = ENCODING_DEFAULT;
switch_thread_rwlock_create(&globals.log_path_lock, pool);
@@ -1002,6 +1014,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load)
} else if (!strcasecmp(val, "any")) {
globals.auth_scheme = CURLAUTH_ANY;
}
} else if (!strcasecmp(var, "encode-values") && !zstr(val)) {
globals.encode_values = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE;
}
}
+1 -3
View File
@@ -1,10 +1,8 @@
LAME=lame-3.97
LAME=lame-3.98.4
SHOUT=libshout-2.2.2
MPG123=mpg123-1.13.2
BASE=../../../..
WANT_CURL=yes
LAME_DIR=$(switch_srcdir)/libs/$(LAME)
SHOUT_DIR=$(switch_srcdir)/libs/$(SHOUT)
MPG123_DIR=$(switch_srcdir)/libs/$(MPG123)
+22 -20
View File
@@ -445,30 +445,30 @@ static size_t stream_callback(void *ptr, size_t size, size_t nmemb, void *data)
#define MY_BLOCK_SIZE MY_BUF_LEN
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj)
{
CURL *curl_handle = NULL;
CURLcode cc;
switch_CURL *curl_handle = NULL;
switch_CURLcode cc;
shout_context_t *context = (shout_context_t *) obj;
switch_thread_rwlock_rdlock(context->rwlock);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, context->stream_url);
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, stream_callback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) context);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "FreeSWITCH(mod_shout)/1.0");
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 30); /* eventually timeout connect */
curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_LIMIT, 100); /* handle trickle connections */
curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_TIME, 30);
curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, context->curl_error_buff);
cc = curl_easy_perform(curl_handle);
curl_handle = switch_curl_easy_init();
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, context->stream_url);
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, stream_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) context);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "FreeSWITCH(mod_shout)/1.0");
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 30); /* eventually timeout connect */
switch_curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_LIMIT, 100); /* handle trickle connections */
switch_curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_TIME, 30);
switch_curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, context->curl_error_buff);
cc = switch_curl_easy_perform(curl_handle);
if (cc && cc != CURLE_WRITE_ERROR) { /* write error is ok, we just exited from callback early */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "CURL returned error:[%d] %s : %s [%s]\n", cc, curl_easy_strerror(cc),
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "CURL returned error:[%d] %s : %s [%s]\n", cc, switch_curl_easy_strerror(cc),
context->curl_error_buff, context->stream_url);
}
curl_easy_cleanup(curl_handle);
switch_curl_easy_cleanup(curl_handle);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Read Thread Done\n");
context->eof++;
@@ -836,6 +836,11 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
goto error;
}
if (!context->lame_ready) {
lame_init_params(context->gfp);
lame_print_config(context->gfp);
context->lame_ready = 1;
}
}
}
@@ -1545,8 +1550,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_shout_load)
supported_formats[0] = "shout";
supported_formats[1] = "mp3";
switch_curl_init();
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
@@ -1572,7 +1575,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_shout_load)
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_shout_shutdown)
{
switch_curl_destroy();
mpg123_exit();
return SWITCH_STATUS_SUCCESS;
}
+4 -4
View File
@@ -42,7 +42,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.97/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.98.4/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
PreprocessorDefinitions="CURL_STATICLIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -114,7 +114,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.97/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.98.4/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
PreprocessorDefinitions="CURL_STATICLIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -188,7 +188,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.97/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.98.4/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
PreprocessorDefinitions="CURL_STATICLIB"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
@@ -263,7 +263,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.97/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
AdditionalIncludeDirectories="../../../../libs/curl/include;&quot;../../../../libs/lame-3.98.4/include&quot;;..\..\..\..\libs\win32\libshout;&quot;..\..\..\..\libs\libshout-2.2.2\include&quot;;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
PreprocessorDefinitions="CURL_STATICLIB"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
+4 -4
View File
@@ -67,7 +67,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -89,7 +89,7 @@
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -109,7 +109,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -133,7 +133,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -146,6 +146,9 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
context->sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM;
context->sfinfo.channels = 1;
context->sfinfo.samplerate = 8000;
} else if (!strcmp(ext, "oga")) {
context->sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
context->sfinfo.samplerate = handle->samplerate;
}
if ((mode & SFM_WRITE) && sf_format_check(&context->sfinfo) == 0) {
+1 -1
View File
@@ -1,5 +1,5 @@
%module freeswitch
%include ../../../../swig_common.i
/** insert the following includes into generated code so it compiles */
%{
#include "switch_cpp.h"
@@ -99,8 +99,8 @@ public class EventConsumer {
return freeswitchJNI.EventConsumer_bind(swigCPtr, this, event_name, subclass_name);
}
public Event pop(int block) {
long cPtr = freeswitchJNI.EventConsumer_pop(swigCPtr, this, block);
public Event pop(int block, int timeout) {
long cPtr = freeswitchJNI.EventConsumer_pop(swigCPtr, this, block, timeout);
return (cPtr == 0) ? null : new Event(cPtr, true);
}
@@ -9,6 +9,14 @@
package org.freeswitch.swig;
public class freeswitch {
public static void setGlobalVariable(String var_name, String var_val) {
freeswitchJNI.setGlobalVariable(var_name, var_val);
}
public static String getGlobalVariable(String var_name) {
return freeswitchJNI.getGlobalVariable(var_name);
}
public static void consoleLog(String level_str, String msg) {
freeswitchJNI.consoleLog(level_str, msg);
}
@@ -9,6 +9,8 @@
package org.freeswitch.swig;
class freeswitchJNI {
public final static native void setGlobalVariable(String jarg1, String jarg2);
public final static native String getGlobalVariable(String jarg1);
public final static native void consoleLog(String jarg1, String jarg2);
public final static native void consoleCleanLog(String jarg1);
public final static native boolean email(String jarg1, String jarg2, String jarg3, String jarg4, String jarg5, String jarg6, String jarg7);
@@ -82,7 +84,7 @@ class freeswitchJNI {
public final static native long new_EventConsumer(String jarg1, String jarg2);
public final static native void delete_EventConsumer(long jarg1);
public final static native int EventConsumer_bind(long jarg1, EventConsumer jarg1_, String jarg2, String jarg3);
public final static native long EventConsumer_pop(long jarg1, EventConsumer jarg1_, int jarg2);
public final static native long EventConsumer_pop(long jarg1, EventConsumer jarg1_, int jarg2, int jarg3);
public final static native void delete_CoreSession(long jarg1);
public final static native void CoreSession_session_set(long jarg1, CoreSession jarg1_, long jarg2);
public final static native long CoreSession_session_get(long jarg1, CoreSession jarg1_);
@@ -207,6 +207,48 @@ static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionC
extern "C" {
#endif
SWIGEXPORT void JNICALL Java_org_freeswitch_swig_freeswitchJNI_setGlobalVariable(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) {
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return ;
}
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return ;
}
setGlobalVariable(arg1,arg2);
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
}
SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_getGlobalVariable(JNIEnv *jenv, jclass jcls, jstring jarg1) {
jstring jresult = 0 ;
char *arg1 = (char *) 0 ;
char *result = 0 ;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1) return 0;
}
result = (char *)getGlobalVariable(arg1);
if(result) jresult = jenv->NewStringUTF((const char *)result);
if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1);
free(result);
return jresult;
}
SWIGEXPORT void JNICALL Java_org_freeswitch_swig_freeswitchJNI_consoleLog(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) {
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
@@ -1611,10 +1653,11 @@ SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1bi
}
SWIGEXPORT jlong JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1pop(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
SWIGEXPORT jlong JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1pop(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3) {
jlong jresult = 0 ;
EventConsumer *arg1 = (EventConsumer *) 0 ;
int arg2 = (int) 0 ;
int arg3 = (int) 0 ;
Event *result = 0 ;
(void)jenv;
@@ -1622,7 +1665,8 @@ SWIGEXPORT jlong JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1p
(void)jarg1_;
arg1 = *(EventConsumer **)&jarg1;
arg2 = (int)jarg2;
result = (Event *)(arg1)->pop(arg2);
arg3 = (int)jarg3;
result = (Event *)(arg1)->pop(arg2,arg3);
*(Event **)&jresult = result;
return jresult;
}
+1
View File
@@ -1,4 +1,5 @@
%module freeswitch
%include ../../../../swig_common.i
//%include "cstring.i"
/**
+5
View File
@@ -135,9 +135,14 @@ static int lua_parse_and_execute(lua_State * L, char *input_code)
return 1;
}
while(input_code && (*input_code == ' ' || *input_code == '\n' || *input_code == '\r')) input_code++;
if (*input_code == '~') {
char *buff = input_code + 1;
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1, 0); //lua_pcall(L, 0, 0, 0);
} else if (!strncasecmp(input_code, "#!/lua", 6)) {
char *buff = input_code + 6;
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1, 0); //lua_pcall(L, 0, 0, 0);
} else {
char *args = strchr(input_code, ' ');
if (args) {
+54 -2
View File
@@ -1539,6 +1539,51 @@ typedef struct{} LANGUAGE_OBJ;
#ifdef __cplusplus
extern "C" {
#endif
static int _wrap_setGlobalVariable(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
SWIG_check_num_args("setGlobalVariable",2,2)
if(!lua_isstring(L,1)) SWIG_fail_arg("setGlobalVariable",1,"char *");
if(!lua_isstring(L,2)) SWIG_fail_arg("setGlobalVariable",2,"char *");
arg1 = (char *)lua_tostring(L, 1);
arg2 = (char *)lua_tostring(L, 2);
setGlobalVariable(arg1,arg2);
SWIG_arg=0;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_getGlobalVariable(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
char *result = 0 ;
SWIG_check_num_args("getGlobalVariable",1,1)
if(!lua_isstring(L,1)) SWIG_fail_arg("getGlobalVariable",1,"char *");
arg1 = (char *)lua_tostring(L, 1);
result = (char *)getGlobalVariable(arg1);
SWIG_arg=0;
lua_pushstring(L,(const char*)result); SWIG_arg++;
free(result);
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_consoleLog(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
@@ -3746,11 +3791,13 @@ static int _wrap_EventConsumer_pop(lua_State* L) {
int SWIG_arg = -1;
EventConsumer *arg1 = (EventConsumer *) 0 ;
int arg2 = (int) 0 ;
int arg3 = (int) 0 ;
Event *result = 0 ;
SWIG_check_num_args("pop",1,2)
SWIG_check_num_args("pop",1,3)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("pop",1,"EventConsumer *");
if(lua_gettop(L)>=2 && !lua_isnumber(L,2)) SWIG_fail_arg("pop",2,"int");
if(lua_gettop(L)>=3 && !lua_isnumber(L,3)) SWIG_fail_arg("pop",3,"int");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_EventConsumer,0))){
SWIG_fail_ptr("EventConsumer_pop",1,SWIGTYPE_p_EventConsumer);
@@ -3759,7 +3806,10 @@ static int _wrap_EventConsumer_pop(lua_State* L) {
if(lua_gettop(L)>=2){
arg2 = (int)lua_tonumber(L, 2);
}
result = (Event *)(arg1)->pop(arg2);
if(lua_gettop(L)>=3){
arg3 = (int)lua_tonumber(L, 3);
}
result = (Event *)(arg1)->pop(arg2,arg3);
SWIG_arg=0;
SWIG_NewPointerObj(L,result,SWIGTYPE_p_Event,1); SWIG_arg++;
return SWIG_arg;
@@ -7642,6 +7692,8 @@ static swig_lua_class _wrap_class_LUA_Dbh = { "Dbh", &SWIGTYPE_p_LUA__Dbh,_wrap_
#endif
static const struct luaL_reg swig_commands[] = {
{ "setGlobalVariable", _wrap_setGlobalVariable},
{ "getGlobalVariable", _wrap_getGlobalVariable},
{ "consoleLog", _wrap_consoleLog},
{ "consoleCleanLog", _wrap_consoleCleanLog},
{ "email", _wrap_email},
+3 -3
View File
@@ -1,6 +1,6 @@
LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono --cflags
LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono --libs
#MOD_CFLAGS=-D_REENTRANT -pthread -I/opt/mono-1.9/lib/pkgconfig/../../include/mono-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lmono
LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono-2 --cflags
LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono-2 --libs
#MOD_CFLAGS=-D_REENTRANT -pthread -I/usr/lib/mono -lmono
BASE=../../../..
VERBOSE=1
include $(BASE)/build/modmake.rules
+2 -1
View File
@@ -1,5 +1,7 @@
%module freeswitch
%include ../../../../swig_common.i
/** String fix - copied from csharphead.swg with fix for multiple appdomains **/
/* Must pass -DSWIG_CSHARP_NO_STRING_HELPER to swig */
@@ -8,7 +10,6 @@
/* Callback for returning strings to C# without leaking memory */
#ifndef _MANAGED
#include <glib.h>
#include <mono/jit/jit.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/mono-config.h>
@@ -40,7 +40,6 @@ typedef void (*hangupFunction) (void);
typedef char *(*inputFunction) (void *, switch_input_type_t);
#ifndef _MANAGED
#include <glib.h>
#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/environment.h>
@@ -73,7 +72,7 @@ extern mod_managed_globals globals;
#ifdef WIN32
#define RESULT_FREE(x) CoTaskMemFree(x)
#else
#define RESULT_FREE(x) g_free(x)
#define RESULT_FREE(x) mono_free(x)
#endif
SWITCH_END_EXTERN_C
@@ -270,7 +270,6 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_freeswitch(
/* Callback for returning strings to C# without leaking memory */
#ifndef _MANAGED
#include <glib.h>
#include <mono/jit/jit.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/mono-config.h>
@@ -1071,6 +1070,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE
}
SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TRANSFER_HISTORY_VARIABLE_get() {
char * jresult ;
char *result = 0 ;
result = (char *)("transfer_history");
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get() {
char * jresult ;
char *result = 0 ;
@@ -3838,6 +3847,35 @@ SWIGEXPORT unsigned short SWIGSTDCALL CSharp_switch_t38_options_t_local_port_get
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_t38_options_t_sdp_o_line_set(void * jarg1, char * jarg2) {
switch_t38_options_t *arg1 = (switch_t38_options_t *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_t38_options_t *)jarg1;
arg2 = (char *)jarg2;
{
if (arg2) {
arg1->sdp_o_line = (char const *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->sdp_o_line, (const char *)arg2);
} else {
arg1->sdp_o_line = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_t38_options_t_sdp_o_line_get(void * jarg1) {
char * jresult ;
switch_t38_options_t *arg1 = (switch_t38_options_t *) 0 ;
char *result = 0 ;
arg1 = (switch_t38_options_t *)jarg1;
result = (char *) ((arg1)->sdp_o_line);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_t38_options_t() {
void * jresult ;
switch_t38_options_t *result = 0 ;
@@ -5320,6 +5358,18 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_regex_set_var_callback(char * jarg1, c
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_regex_set_event_header_callback(char * jarg1, char * jarg2, void * jarg3) {
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
void *arg3 = (void *) 0 ;
arg1 = (char *)jarg1;
arg2 = (char *)jarg2;
arg3 = (void *)jarg3;
switch_regex_set_event_header_callback((char const *)arg1,(char const *)arg2,arg3);
}
SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_MAX_CORE_THREAD_SESSION_OBJS_get() {
int jresult ;
int result;
@@ -6809,30 +6859,6 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_state_handler(void * jarg1) {
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_curl_count(void * jarg1) {
int jresult ;
int *arg1 = (int *) 0 ;
int result;
arg1 = (int *)jarg1;
result = (int)switch_core_curl_count(arg1);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_ssl_count(void * jarg1) {
int jresult ;
int *arg1 = (int *) 0 ;
int result;
arg1 = (int *)jarg1;
result = (int)switch_core_ssl_count(arg1);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_remove_state_handler(void * jarg1) {
switch_state_handler_table_t *arg1 = (switch_state_handler_table_t *) 0 ;
@@ -6881,6 +6907,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_perform_new_memory_pool(void * jar
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_sync_clock() {
int jresult ;
int result;
result = (int)switch_core_session_sync_clock();
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_perform_destroy_memory_pool(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
int jresult ;
switch_memory_pool_t **arg1 = (switch_memory_pool_t **) 0 ;
@@ -10240,6 +10276,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, void * jar
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_deliver(char * jarg1, void * jarg2) {
int jresult ;
char *arg1 = (char *) 0 ;
switch_event_t **arg2 = (switch_event_t **) 0 ;
switch_status_t result;
arg1 = (char *)jarg1;
arg2 = (switch_event_t **)jarg2;
result = (switch_status_t)switch_core_chat_deliver((char const *)arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_preprocess_session(void * jarg1, char * jarg2) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
@@ -11072,6 +11122,28 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_interface_applicatio
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_loadable_module_interface_chat_application_interface_set(void * jarg1, void * jarg2) {
switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ;
switch_chat_application_interface_t *arg2 = (switch_chat_application_interface_t *) 0 ;
arg1 = (switch_loadable_module_interface *)jarg1;
arg2 = (switch_chat_application_interface_t *)jarg2;
if (arg1) (arg1)->chat_application_interface = arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_interface_chat_application_interface_get(void * jarg1) {
void * jresult ;
switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ;
switch_chat_application_interface_t *result = 0 ;
arg1 = (switch_loadable_module_interface *)jarg1;
result = (switch_chat_application_interface_t *) ((arg1)->chat_application_interface);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_loadable_module_interface_api_interface_set(void * jarg1, void * jarg2) {
switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ;
switch_api_interface_t *arg2 = (switch_api_interface_t *) 0 ;
@@ -11481,6 +11553,34 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_get_application_inte
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_get_chat_application_interface(char * jarg1) {
void * jresult ;
char *arg1 = (char *) 0 ;
switch_chat_application_interface_t *result = 0 ;
arg1 = (char *)jarg1;
result = (switch_chat_application_interface_t *)switch_loadable_module_get_chat_application_interface((char const *)arg1);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_execute_chat_app(void * jarg1, char * jarg2, char * jarg3) {
int jresult ;
switch_event_t *arg1 = (switch_event_t *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
switch_status_t result;
arg1 = (switch_event_t *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
result = (switch_status_t)switch_core_execute_chat_app(arg1,(char const *)arg2,(char const *)arg3);
jresult = result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_get_api_interface(char * jarg1) {
void * jresult ;
char *arg1 = (char *) 0 ;
@@ -12497,6 +12597,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_number(char * jarg1) {
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_find_parameter(char * jarg1, char * jarg2, void * jarg3) {
char * jresult ;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
switch_memory_pool_t *arg3 = (switch_memory_pool_t *) 0 ;
char *result = 0 ;
arg1 = (char *)jarg1;
arg2 = (char *)jarg2;
arg3 = (switch_memory_pool_t *)jarg3;
result = (char *)switch_find_parameter((char const *)arg1,(char const *)arg2,arg3);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_true(char * jarg1) {
int jresult ;
char *arg1 = (char *) 0 ;
@@ -12791,6 +12907,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_clean_name_string(char * jarg1) {
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_safe_atoi(char * jarg1, int jarg2) {
int jresult ;
char *arg1 = (char *) 0 ;
int arg2 ;
int result;
arg1 = (char *)jarg1;
arg2 = (int)jarg2;
result = (int)switch_safe_atoi((char const *)arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_safe_strdup(char * jarg1) {
char * jresult ;
char *arg1 = (char *) 0 ;
@@ -13471,6 +13601,38 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_split_user_domain(char * jarg1, void *
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_uuid_str(char * jarg1, void * jarg2) {
char * jresult ;
char *arg1 = (char *) 0 ;
switch_size_t arg2 ;
switch_size_t *argp2 ;
char *result = 0 ;
arg1 = (char *)jarg1;
argp2 = (switch_size_t *)jarg2;
if (!argp2) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null switch_size_t", 0);
return 0;
}
arg2 = *argp2;
result = (char *)switch_uuid_str(arg1,arg2);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_format_number(char * jarg1) {
char * jresult ;
char *arg1 = (char *) 0 ;
char *result = 0 ;
arg1 = (char *)jarg1;
result = (char *)switch_format_number((char const *)arg1);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_profile_node_t_var_set(void * jarg1, char * jarg2) {
profile_node_t *arg1 = (profile_node_t *) 0 ;
char *arg2 = (char *) 0 ;
@@ -14456,6 +14618,96 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_caller_profile_soft_get(void * jarg1
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_uuid_str_set(void * jarg1, char * jarg2) {
switch_caller_profile *arg1 = (switch_caller_profile *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_caller_profile *)jarg1;
arg2 = (char *)jarg2;
{
if (arg1->uuid_str) delete [] arg1->uuid_str;
if (arg2) {
arg1->uuid_str = (char *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->uuid_str, (const char *)arg2);
} else {
arg1->uuid_str = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_uuid_str_get(void * jarg1) {
char * jresult ;
switch_caller_profile *arg1 = (switch_caller_profile *) 0 ;
char *result = 0 ;
arg1 = (switch_caller_profile *)jarg1;
result = (char *) ((arg1)->uuid_str);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_clone_of_set(void * jarg1, char * jarg2) {
switch_caller_profile *arg1 = (switch_caller_profile *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_caller_profile *)jarg1;
arg2 = (char *)jarg2;
{
if (arg1->clone_of) delete [] arg1->clone_of;
if (arg2) {
arg1->clone_of = (char *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->clone_of, (const char *)arg2);
} else {
arg1->clone_of = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_clone_of_get(void * jarg1) {
char * jresult ;
switch_caller_profile *arg1 = (switch_caller_profile *) 0 ;
char *result = 0 ;
arg1 = (switch_caller_profile *)jarg1;
result = (char *) ((arg1)->clone_of);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_transfer_source_set(void * jarg1, char * jarg2) {
switch_caller_profile *arg1 = (switch_caller_profile *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_caller_profile *)jarg1;
arg2 = (char *)jarg2;
{
if (arg1->transfer_source) delete [] arg1->transfer_source;
if (arg2) {
arg1->transfer_source = (char *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->transfer_source, (const char *)arg2);
} else {
arg1->transfer_source = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_transfer_source_get(void * jarg1) {
char * jresult ;
switch_caller_profile *arg1 = (switch_caller_profile *) 0 ;
char *result = 0 ;
arg1 = (switch_caller_profile *)jarg1;
result = (char *) ((arg1)->transfer_source);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_caller_profile() {
void * jresult ;
switch_caller_profile *result = 0 ;
@@ -22566,6 +22818,294 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_application_interface(void * ja
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_interface_name_set(void * jarg1, char * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (char *)jarg2;
{
if (arg2) {
arg1->interface_name = (char const *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->interface_name, (const char *)arg2);
} else {
arg1->interface_name = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_interface_name_get(void * jarg1) {
char * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (char *) ((arg1)->interface_name);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_chat_application_function_set(void * jarg1, void * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_chat_application_function_t arg2 = (switch_chat_application_function_t) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (switch_chat_application_function_t)jarg2;
if (arg1) (arg1)->chat_application_function = arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_chat_application_function_get(void * jarg1) {
void * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_chat_application_function_t result;
arg1 = (switch_chat_application_interface *)jarg1;
result = (switch_chat_application_function_t) ((arg1)->chat_application_function);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_long_desc_set(void * jarg1, char * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (char *)jarg2;
{
if (arg2) {
arg1->long_desc = (char const *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->long_desc, (const char *)arg2);
} else {
arg1->long_desc = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_long_desc_get(void * jarg1) {
char * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (char *) ((arg1)->long_desc);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_short_desc_set(void * jarg1, char * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (char *)jarg2;
{
if (arg2) {
arg1->short_desc = (char const *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->short_desc, (const char *)arg2);
} else {
arg1->short_desc = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_short_desc_get(void * jarg1) {
char * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (char *) ((arg1)->short_desc);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_syntax_set(void * jarg1, char * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (char *)jarg2;
{
if (arg2) {
arg1->syntax = (char const *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->syntax, (const char *)arg2);
} else {
arg1->syntax = 0;
}
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_syntax_get(void * jarg1) {
char * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
char *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (char *) ((arg1)->syntax);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_flags_set(void * jarg1, unsigned long jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
uint32_t arg2 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (uint32_t)jarg2;
if (arg1) (arg1)->flags = arg2;
}
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_chat_application_interface_flags_get(void * jarg1) {
unsigned long jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
uint32_t result;
arg1 = (switch_chat_application_interface *)jarg1;
result = (uint32_t) ((arg1)->flags);
jresult = (unsigned long)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_rwlock_set(void * jarg1, void * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_thread_rwlock_t *arg2 = (switch_thread_rwlock_t *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (switch_thread_rwlock_t *)jarg2;
if (arg1) (arg1)->rwlock = arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_rwlock_get(void * jarg1) {
void * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_thread_rwlock_t *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (switch_thread_rwlock_t *) ((arg1)->rwlock);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_refs_set(void * jarg1, int jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
int arg2 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (int)jarg2;
if (arg1) (arg1)->refs = arg2;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_chat_application_interface_refs_get(void * jarg1) {
int jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
int result;
arg1 = (switch_chat_application_interface *)jarg1;
result = (int) ((arg1)->refs);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_reflock_set(void * jarg1, void * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_mutex_t *arg2 = (switch_mutex_t *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (switch_mutex_t *)jarg2;
if (arg1) (arg1)->reflock = arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_reflock_get(void * jarg1) {
void * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_mutex_t *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (switch_mutex_t *) ((arg1)->reflock);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_parent_set(void * jarg1, void * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_loadable_module_interface_t *arg2 = (switch_loadable_module_interface_t *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (switch_loadable_module_interface_t *)jarg2;
if (arg1) (arg1)->parent = arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_parent_get(void * jarg1) {
void * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_loadable_module_interface_t *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (switch_loadable_module_interface_t *) ((arg1)->parent);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_next_set(void * jarg1, void * jarg2) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_chat_application_interface *arg2 = (switch_chat_application_interface *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
arg2 = (switch_chat_application_interface *)jarg2;
if (arg1) (arg1)->next = arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_next_get(void * jarg1) {
void * jresult ;
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
switch_chat_application_interface *result = 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
result = (switch_chat_application_interface *) ((arg1)->next);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_chat_application_interface() {
void * jresult ;
switch_chat_application_interface *result = 0 ;
result = (switch_chat_application_interface *)new switch_chat_application_interface();
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_chat_application_interface(void * jarg1) {
switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ;
arg1 = (switch_chat_application_interface *)jarg1;
delete arg1;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_api_interface_interface_name_set(void * jarg1, char * jarg2) {
switch_api_interface *arg1 = (switch_api_interface *) 0 ;
char *arg2 = (char *) 0 ;
@@ -23802,6 +24342,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void
}
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_del_variable_prefix(void * jarg1, char * jarg2) {
unsigned long jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
char *arg2 = (char *) 0 ;
uint32_t result;
arg1 = (switch_channel_t *)jarg1;
arg2 = (char *)jarg2;
result = (uint32_t)switch_channel_del_variable_prefix(arg1,(char const *)arg2);
jresult = (unsigned long)result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
@@ -25747,6 +26301,22 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_event_get_header_idx(void * jarg1, c
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_rename_header(void * jarg1, char * jarg2, char * jarg3) {
int jresult ;
switch_event_t *arg1 = (switch_event_t *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
switch_status_t result;
arg1 = (switch_event_t *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
result = (switch_status_t)switch_event_rename_header(arg1,(char const *)arg2,(char const *)arg3);
jresult = result;
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_event_get_body(void * jarg1) {
char * jresult ;
switch_event_t *arg1 = (switch_event_t *) 0 ;
@@ -25855,6 +26425,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_event_merge(void * jarg1, void * jarg2
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_dup_reply(void * jarg1, void * jarg2) {
int jresult ;
switch_event_t **arg1 = (switch_event_t **) 0 ;
switch_event_t *arg2 = (switch_event_t *) 0 ;
switch_status_t result;
arg1 = (switch_event_t **)jarg1;
arg2 = (switch_event_t *)jarg2;
result = (switch_status_t)switch_event_dup_reply(arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_fire_detailed(char * jarg1, char * jarg2, int jarg3, void * jarg4, void * jarg5) {
int jresult ;
char *arg1 = (char *) 0 ;
@@ -26087,6 +26671,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_running() {
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_set_body(void * jarg1, char * jarg2) {
int jresult ;
switch_event_t *arg1 = (switch_event_t *) 0 ;
char *arg2 = (char *) 0 ;
switch_status_t result;
arg1 = (switch_event_t *)jarg1;
arg2 = (char *)jarg2;
result = (switch_status_t)switch_event_set_body(arg1,(char const *)arg2);
jresult = result;
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_event_expand_headers(void * jarg1, char * jarg2) {
char * jresult ;
switch_event_t *arg1 = (switch_event_t *) 0 ;
@@ -27225,6 +27823,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_collect_digits_count(void * jarg1,
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_play_and_detect_speech(void * jarg1, char * jarg2, char * jarg3, char * jarg4, void * jarg5) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
char *arg4 = (char *) 0 ;
char **arg5 = (char **) 0 ;
switch_status_t result;
arg1 = (switch_core_session_t *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
arg4 = (char *)jarg4;
arg5 = (char **)jarg5;
result = (switch_status_t)switch_ivr_play_and_detect_speech(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_detect_speech(void * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, void * jarg6) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
@@ -28785,6 +29403,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_uuid_exists(char * jarg1) {
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_ivr_dmachine_get_name(void * jarg1) {
char * jresult ;
switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ;
char *result = 0 ;
arg1 = (switch_ivr_dmachine_t *)jarg1;
result = (char *)switch_ivr_dmachine_get_name(arg1);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_ivr_dmachine_set_match_callback(void * jarg1, void * jarg2) {
switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ;
switch_ivr_dmachine_callback_t arg2 = (switch_ivr_dmachine_callback_t) 0 ;
@@ -29043,6 +29673,50 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_insert_file(void * jarg1, char * ja
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_create_message_reply(void * jarg1, void * jarg2, char * jarg3) {
int jresult ;
switch_event_t **arg1 = (switch_event_t **) 0 ;
switch_event_t *arg2 = (switch_event_t *) 0 ;
char *arg3 = (char *) 0 ;
switch_status_t result;
arg1 = (switch_event_t **)jarg1;
arg2 = (switch_event_t *)jarg2;
arg3 = (char *)jarg3;
result = (switch_status_t)switch_ivr_create_message_reply(arg1,arg2,(char const *)arg3);
jresult = result;
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_ivr_check_presence_mapping(char * jarg1, char * jarg2) {
char * jresult ;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
char *result = 0 ;
arg1 = (char *)jarg1;
arg2 = (char *)jarg2;
result = (char *)switch_ivr_check_presence_mapping((char const *)arg1,(char const *)arg2);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_kill_uuid(char * jarg1, int jarg2) {
int jresult ;
char *arg1 = (char *) 0 ;
switch_call_cause_t arg2 ;
switch_status_t result;
arg1 = (char *)jarg1;
arg2 = (switch_call_cause_t)jarg2;
result = (switch_status_t)switch_ivr_kill_uuid((char const *)arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_RTP_MAX_BUF_LEN_get() {
int jresult ;
int result;
@@ -31536,13 +32210,15 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_xml_parse_section_string(char
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_xml_std_datetime_check(void * jarg1) {
SWIGEXPORT int SWIGSTDCALL CSharp_switch_xml_std_datetime_check(void * jarg1, void * jarg2) {
int jresult ;
switch_xml_t arg1 = (switch_xml_t) 0 ;
int *arg2 = (int *) 0 ;
int result;
arg1 = (switch_xml_t)jarg1;
result = (int)switch_xml_std_datetime_check(arg1);
arg2 = (int *)jarg2;
result = (int)switch_xml_std_datetime_check(arg1,arg2);
jresult = result;
return jresult;
}
@@ -33550,6 +34226,29 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_config_next_pair(void * jarg1, void * j
}
SWIGEXPORT void SWIGSTDCALL CSharp_setGlobalVariable(char * jarg1, char * jarg2) {
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
arg1 = (char *)jarg1;
arg2 = (char *)jarg2;
setGlobalVariable(arg1,arg2);
}
SWIGEXPORT char * SWIGSTDCALL CSharp_getGlobalVariable(char * jarg1) {
char * jresult ;
char *arg1 = (char *) 0 ;
char *result = 0 ;
arg1 = (char *)jarg1;
result = (char *)getGlobalVariable(arg1);
jresult = SWIG_csharp_string_callback((const char *)result);
free(result);
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_consoleLog(char * jarg1, char * jarg2) {
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
@@ -34070,6 +34769,36 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_Event(void * jarg1) {
}
SWIGEXPORT int SWIGSTDCALL CSharp_Event_chat_execute(void * jarg1, char * jarg2, char * jarg3) {
int jresult ;
Event *arg1 = (Event *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) NULL ;
int result;
arg1 = (Event *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
result = (int)(arg1)->chat_execute((char const *)arg2,(char const *)arg3);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_Event_chat_send(void * jarg1, char * jarg2) {
int jresult ;
Event *arg1 = (Event *) 0 ;
char *arg2 = (char *) NULL ;
int result;
arg1 = (Event *)jarg1;
arg2 = (char *)jarg2;
result = (int)(arg1)->chat_send((char const *)arg2);
jresult = result;
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_Event_Serialize(void * jarg1, char * jarg2) {
char * jresult ;
Event *arg1 = (Event *) 0 ;
@@ -34412,15 +35141,17 @@ SWIGEXPORT int SWIGSTDCALL CSharp_EventConsumer_bind(void * jarg1, char * jarg2,
}
SWIGEXPORT void * SWIGSTDCALL CSharp_EventConsumer_pop(void * jarg1, int jarg2) {
SWIGEXPORT void * SWIGSTDCALL CSharp_EventConsumer_pop(void * jarg1, int jarg2, int jarg3) {
void * jresult ;
EventConsumer *arg1 = (EventConsumer *) 0 ;
int arg2 = (int) 0 ;
int arg3 = (int) 0 ;
Event *result = 0 ;
arg1 = (EventConsumer *)jarg1;
arg2 = (int)jarg2;
result = (Event *)(arg1)->pop(arg2);
arg3 = (int)jarg3;
result = (Event *)(arg1)->pop(arg2,arg3);
jresult = (void *)result;
return jresult;
}

Some files were not shown because too many files have changed in this diff Show More