mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 20:51:58 +00:00
Merge branch 'master' into smgmaster
Conflicts: build/modules.conf.in libs/esl/fs_cli.c
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(¶ms);
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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,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,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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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(¶ms, 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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -31,5 +31,6 @@ Enjoy
|
||||
|
||||
-giovanni
|
||||
|
||||
|
||||
< gmaruzz at gmail dot com >
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -520,6 +520,7 @@ struct rtmp_private {
|
||||
const char *auth;
|
||||
|
||||
uint16_t maxlen;
|
||||
int over_size;
|
||||
};
|
||||
|
||||
struct rtmp_reg;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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(¶ms);
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,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,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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
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="../../../../libs/curl/include;"../../../../libs/lame-3.98.4/include";..\..\..\..\libs\win32\libshout;"..\..\..\..\libs\libshout-2.2.2\include";..\..\..\..\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;"../../../../libs/lame-3.97/include";..\..\..\..\libs\win32\libshout;"..\..\..\..\libs\libshout-2.2.2\include";..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
|
||||
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"
|
||||
PreprocessorDefinitions="CURL_STATICLIB"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
@@ -188,7 +188,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
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="../../../../libs/curl/include;"../../../../libs/lame-3.98.4/include";..\..\..\..\libs\win32\libshout;"..\..\..\..\libs\libshout-2.2.2\include";..\..\..\..\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;"../../../../libs/lame-3.97/include";..\..\..\..\libs\win32\libshout;"..\..\..\..\libs\libshout-2.2.2\include";..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123"
|
||||
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"
|
||||
PreprocessorDefinitions="CURL_STATICLIB"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
|
||||
@@ -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,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,4 +1,5 @@
|
||||
%module freeswitch
|
||||
%include ../../../../swig_common.i
|
||||
//%include "cstring.i"
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user