Merge branch 'master' into v1.4.beta

This commit is contained in:
Ken Rice
2013-10-13 11:27:51 -05:00
85 changed files with 3372 additions and 898 deletions
+1
View File
@@ -99,6 +99,7 @@ event_handlers/mod_cdr_sqlite
#event_handlers/mod_event_multicast
event_handlers/mod_event_socket
#event_handlers/mod_event_zmq
#event_handlers/mod_format_cdr
#event_handlers/mod_json_cdr
#event_handlers/mod_radius_cdr
#event_handlers/mod_rayo
@@ -0,0 +1,88 @@
<configuration name="format_cdr.conf" description="Multi Format CDR CURL logger">
<!-- You can have multiple profiles, to allow logging to both json and cdr simultaneously, or to
different paths or servers with different settings, just be sure to use different name for
each profile. -->
<profiles>
<profile name="default">
<settings>
<!-- the format of data to send, defaults to xml -->
<!-- <param name="format" value="json|xml"/> -->
<param name="format" value="xml"/>
<!-- the url to post to if blank web posting is disabled -->
<!-- <param name="url" value="http://localhost/cdr_curl/post.php"/> -->
<!-- optional: credentials to send to web server -->
<!-- <param name="cred" value="user:pass"/> -->
<!-- the total number of retries (not counting the first 'try') to post to webserver incase of failure -->
<!-- <param name="retries" value="2"/> -->
<!-- delay between retries in seconds, default is 5 seconds -->
<!-- <param name="delay" value="1"/> -->
<!-- Log via http and on disk, default is false -->
<!-- <param name="log-http-and-disk" value="true"/> -->
<!-- optional: if not present we do not log every record to disk -->
<!-- either an absolute path, a relative path assuming ${prefix}/logs or a blank value will default to ${prefix}/logs/format_cdr -->
<param name="log-dir" value=""/>
<!-- optional: if not present we do log the b leg -->
<!-- true or false if we should create a cdr for the b leg of a call-->
<param name="log-b-leg" value="false"/>
<!-- optional: if not present, all filenames are the uuid of the call -->
<!-- true or false if a leg files are prefixed "a_" -->
<param name="prefix-a-leg" value="true"/>
<!-- encode the post data may be 'true' for url encoding, 'false' for no encoding, 'base64' for base64 encoding or 'textxml' for text/xml -->
<param name="encode" value="true"/>
<!-- optional: set to true to disable Expect: 100-continue lighttpd requires this setting -->
<!--<param name="disable-100-continue" value="true"/>-->
<!-- optional: full path to the error log dir for failed web posts if not specified its the same as log-dir -->
<!-- either an absolute path, a relative path assuming ${prefix}/logs or a blank or omitted value will default to ${prefix}/logs/format_cdr -->
<!-- <param name="err-log-dir" value="/tmp"/> -->
<!-- which auhtentification scheme to use. Supported values are: basic, digest, NTLM, GSS-NEGOTIATE or "any" for automatic detection -->
<!--<param name="auth-scheme" value="basic"/>-->
<!-- optional: this will enable the CA root certificate check by libcurl to
verify that the certificate was issued by a major Certificate Authority.
note: default value is disabled. only enable if you want this! -->
<!--<param name="enable-cacert-check" value="true"/>-->
<!-- optional: verify that the server is actually the one listed in the cert -->
<!-- <param name="enable-ssl-verifyhost" value="true"/> -->
<!-- optional: these options can be used to specify custom SSL certificates
to use for HTTPS communications. Either use both options or neither.
Specify your public key with 'ssl-cert-path' and the private key with
'ssl-key-path'. If your private key has a password, specify it with
'ssl-key-password'. -->
<!-- <param name="ssl-cert-path" value="$${base_dir}/conf/certs/public_key.pem"/> -->
<!-- <param name="ssl-key-path" value="$${base_dir}/conf/certs/private_key.pem"/> -->
<!-- <param name="ssl-key-password" value="MyPrivateKeyPassword"/> -->
<!-- optional: use a custom CA certificate in PEM format to verify the peer
with. This is useful if you are acting as your own certificate authority.
note: only makes sense if used in combination with "enable-cacert-check." -->
<!-- <param name="ssl-cacert-file" value="$${base_dir}/conf/certs/cacert.pem"/> -->
<!-- optional: specify the SSL version to force HTTPS to use. Valid options are
"SSLv3" and "TLSv1". Otherwise libcurl will auto-negotiate the version. -->
<!-- <param name="ssl-version" value="TLSv1"/> -->
<!-- optional: enables cookies and stores them in the specified file. -->
<!-- <param name="cookie-file" value="/tmp/cookie-mod_format_cdr_curl.txt"/> -->
<!-- Whether to URL encode the individual JSON values. Defaults to true, set to false for standard JSON. -->
<param name="encode-values" value="true"/>
</settings>
</profile>
</profiles>
</configuration>
+3 -3
View File
@@ -420,9 +420,9 @@ if test "$PG_CONFIG" != "no"; then
POSTGRESQL_CXXFLAGS="`$PG_CONFIG --cppflags` -I`$PG_CONFIG --includedir`"
POSTGRESQL_LDFLAGS="`$PG_CONFIG --ldflags|sed 's/ -Wl,--as-needed//g'` -L`$PG_CONFIG --libdir` -lpq"
POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##'`
POSTGRESQL_MAJOR_VERSION=`$PG_CONFIG --version | sed -re 's#PostgreSQL ([0-9]+).[0-9]+.[0-9]+#\1#'`
POSTGRESQL_MINOR_VERSION=`$PG_CONFIG --version | sed -re 's#PostgreSQL [0-9]+.([0-9]+).[0-9]+#\1#'`
POSTGRESQL_PATCH_VERSION=`$PG_CONFIG --version | sed -re 's#PostgreSQL [0-9]+.[0-9]+.([0-9]+)#\1#'`
POSTGRESQL_MAJOR_VERSION=`$PG_CONFIG --version | sed -e 's/devel//' | sed -re 's#PostgreSQL ([0-9]+).[0-9]+.?[0-9]+?#\1#'`
POSTGRESQL_MINOR_VERSION=`$PG_CONFIG --version | sed -e 's/devel//' | sed -re 's#PostgreSQL [0-9]+.([0-9]+).?[0-9]+?#\1#'`
POSTGRESQL_PATCH_VERSION=`$PG_CONFIG --version | sed -e 's/devel//' | sed -re 's#PostgreSQL [0-9]+.[0-9]+.?([0-9]+)?#\1#'`
AC_DEFINE([SWITCH_HAVE_PGSQL], [1], [Define to 1 if PostgreSQL libraries are available])
AC_DEFINE_UNQUOTED([POSTGRESQL_VERSION], "${POSTGRESQL_VERSION}", [Specifies the version of PostgreSQL we are linking against])
AC_DEFINE_UNQUOTED([POSTGRESQL_MAJOR_VERSION], ${POSTGRESQL_MAJOR_VERSION}, [Specifies the version of PostgreSQL we are linking against])
+1 -1
View File
@@ -229,7 +229,7 @@ Description: Voicemail detection
Module: applications/mod_voicemail
Description: Voicemail
This module provides a voicemail system.
Depends: mail-transport-agent
Depends: ssmtp | mail-transport-agent
Module: applications/mod_voicemail_ivr
Description: Voicemail IVR
+35 -2
View File
@@ -198,8 +198,10 @@
<voicemail>
<prompt phrase="The person at extension" filename="vm-person.wav"/>
<prompt phrase="marked urgent" filename="vm-marked-urgent.wav"/>
<prompt phrase="marked new" filename="vm-marked_new.wav"/>
<prompt phrase="emailed" filename="vm-emailed.wav"/>
<prompt phrase="you have" filename="vm-you_have.wav"/>
<prompt phrase="message from" filename="vm-from.wav"/>
<prompt phrase="please enter your i d, followed by" filename="vm-enter_id.wav"/>
<prompt phrase="please enter your password, followed by" filename="vm-enter_pass.wav"/>
<prompt phrase="login incorrect" filename="vm-fail_auth.wav"/>
@@ -218,13 +220,34 @@
<prompt phrase="urgent saved" filename="vm-urgent-saved.wav"/>
<prompt phrase="saved" filename="vm-saved.wav"/>
<prompt phrase="message" filename="vm-message.wav"/>
<prompt phrase="message" filename="vm-message_alt.wav"/>
<prompt phrase="messages" filename="vm-messages.wav"/>
<prompt phrase="messages" filename="vm-messages_alt.wav"/>
<prompt phrase="no more messages" filename="vm-no_more_messages.wav"/>
<prompt phrase="to repeat this message..." filename="vm-repeat_message.wav"/>
<prompt phrase="to delete this message..." filename="vm-delete_message.wav"/>
<prompt phrase="to save this message" filename="vm-save_message.wav"/>
<prompt phrase="to play the next message..." filename="vm-play_next_message.wav"/>
<prompt phrase="to play the previous message..." filename="vm-play_previous_message.wav"/>
<prompt phrase="to undelete this message..." filename="vm-undelete_message.wav"/>
<prompt phrase="to send this message now..." filename="vm-send_message_now.wav"/>
<prompt phrase="to hear the message envelope..." filename="vm-message_envelope.wav"/>
<prompt phrase="...has been changed to..." filename="vm-has_been_changed_to.wav"/>
<prompt phrase="press" filename="vm-press.wav"/>
<prompt phrase="received..." filename="vm-received.wav"/>
<prompt phrase="...followed by..." filename="vm-followed_by.wav"/>
<prompt phrase="That was an invalid extension." filename="vm-that_was_an_invalid_ext.wav"/>
<prompt phrase="Undeleted." filename="vm-undeleted.wav"/>
<prompt phrase="...followed by pound." filename="vm-followed_by_pound.wav"/>
<prompt phrase="next" filename="vm-next.wav"/>
<prompt phrase="to listen to new messages" filename="vm-listen_new.wav"/>
<prompt phrase="to listen to saved messages" filename="vm-listen_saved.wav"/>
<prompt phrase="for advanced options" filename="vm-advanced.wav"/>
<prompt phrase="for advanced options" filename="vm-advanced_alt.wav"/>
<prompt phrase="to exit" filename="vm-to_exit.wav"/>
<prompt phrase="to exit" filename="vm-to_exit_alt.wav"/>
<prompt phrase="to record a greeting" filename="vm-record_greeting.wav"/>
<prompt phrase="to record a greeting" filename="vm-to_record_greeting.wav"/>
<prompt phrase="to choose greeting" filename="vm-choose_greeting.wav"/>
<prompt phrase="to record your name" filename="vm-record_name2.wav"/>
<prompt phrase="for the main menu" filename="vm-main_menu.wav"/>
@@ -232,10 +255,14 @@
<prompt phrase="to save the recording" filename="vm-save_recording.wav"/>
<prompt phrase="to rerecord" filename="vm-rerecord.wav"/>
<prompt phrase="to mark this message urgent" filename="vm-mark-urgent.wav"/>
<prompt phrase="to mark this message new" filename="vm-mark_message_new.wav"/>
<prompt phrase="to continue" filename="vm-continue.wav"/>
<prompt phrase="to listen to the recording again" filename="vm-listen_to_recording_again.wav"/>
<prompt phrase="to delete the recording" filename="vm-delete_recording.wav"/>
<prompt phrase="to forward the recording to your email" filename="vm-forward_to_email.wav"/>
<prompt phrase="to forward this message to another mailbox" filename="vm-to_forward.wav"/>
<prompt phrase="Please enter the extension to forward this message to." filename="vm-forward_enter_ext.wav"/>
<prompt phrase="to add an introduction to this message..." filename="vm-forward_add_intro.wav"/>
<prompt phrase="greeting" filename="vm-greeting.wav"/>
<prompt phrase="selected" filename="vm-selected.wav"/>
<prompt phrase="is not available" filename="vm-not_available.wav"/>
@@ -260,6 +287,7 @@
<prompt phrase="Remember that your voicemail password is also your Web interface password." filename="vm-voicemail_password_is_web_password.wav"/>
<prompt phrase="Message from..." filename="vm-message_from.wav"/>
<prompt phrase="Nobody is currently leaving a message in this voicemail box." filename="vm-nobody_leaving_message.wav"/>
<prompt phrase="last" filename="vm-last.wav"/>
</voicemail>
<directory>
<prompt phrase="Please enter the first few letters of the persons" filename="dir-enter_person.wav"/>
@@ -388,7 +416,7 @@
<prompt phrase="Your estimated hold time is..." filename="ivr-estimated_hold_time.wav"/>
<prompt phrase="More than..." filename="ivr-more_than.wav"/>
<prompt phrase="Less than..." filename="ivr-less_than.wav"/>
<prompt phrase="Begin recording." filename="ivr-begin_recording.wav "/>
<prompt phrase="Begin recording." filename="ivr-begin_recording.wav"/>
<prompt phrase="Call forwarding has been cancelled." filename="ivr-call_forwarding_has_been_cancelled.wav"/>
<prompt phrase="Call forwarding has been set." filename="ivr-call_forwarding_has_been_set.wav"/>
<prompt phrase="Please enter the phone number." filename="ivr-please_enter_the_phone_number.wav"/>
@@ -443,7 +471,7 @@
<prompt phrase="Good morning." filename="ivr-good_morning.wav"/>
<prompt phrase="Good afternoon." filename="ivr-good_afternoon.wav"/>
<prompt phrase="Good evening." filename="ivr-good_evening.wav"/>
<prompt phrase="Thank you." filename="ivr-Thank_you.wav"/>
<prompt phrase="Thank you." filename="ivr-thank_you.wav"/>
<prompt phrase="For..." filename="ivr-for.wav"/>
<prompt phrase="We are experiencing longer than usual hold times." filename="ivr-longer_than_usual_hold_times.wav"/>
<prompt phrase="You are the..." filename="ivr-you_are_the.wav"/>
@@ -507,6 +535,7 @@
<prompt phrase="Unallocated number" filename="ivr-unallocated_number.wav"/>
<prompt phrase="No user response" filename="ivr-no_user_response.wav"/>
<prompt phrase="Invalid number format" filename="ivr-invalid_number_format.wav"/>
<prompt phrase="Invalid sound prompt." filename="ivr-invalid_sound_prompt.wav"/>
<prompt phrase="Gateway down" filename="ivr-gateway_down.wav"/>
<prompt phrase="No route to destination" filename="ivr-no_route_destination.wav"/>
<prompt phrase="User busy" filename="ivr-user_busy.wav"/>
@@ -598,12 +627,16 @@
<prompt phrase="...has been added to the blacklist." filename="ivr-has_been_added_to_the_blacklist.wav"/>
<prompt phrase="...has been removed from the blacklist." filename="ivr-has_been_removed_from_blacklist.wav"/>
<prompt phrase="Please enter the number to be added to the blacklist." filename="ivr-enter_number_to_add_to_blacklist.wav"/>
<prompt phrase="Please enter the number to remove from the blacklist" filename="ivr-enter_number_to_remove_from_blacklist.wav"/>
<prompt phrase="...is not on the blacklist." filename="ivr-is_not_on_the_blacklist.wav"/>
<prompt phrase="...is already on the blacklist." filename="ivr-is_already_on_the_blacklist.wav"/>
<prompt phrase="For other options, press..." filename="ivr-for_other_options.wav"/>
<prompt phrase="Your caller I.D. information is..." filename="ivr-your_caller_id_information_is.wav"/>
<prompt phrase="Call screening has been enabled." filename="ivr-call_screening_enabled.wav"/>
<prompt phrase="Call screening has been disabled." filename="ivr-call_screening_disabled.wav"/>
<prompt phrase="Prompt." filename="ivr-prompt.wav"/>
<prompt phrase="...enabled." filename="ivr-enabled.wav"/>
<prompt phrase="...disabled." filename="ivr-disabled.wav"/>
<prompt phrase="Ain't nobody got time for that!" filename="ivr-aint_nobody_got_time_for_that.wav"/>
<prompt phrase="We would support the shit out of you if only you returned our phone calls and emails." filename="ivr-we_would_support.wav"/>
<prompt phrase="...suck." filename="ivr-suck.wav"/>
+1
View File
@@ -17,6 +17,7 @@ all: ESL.so
esl_wrap.cpp:
swig -module ESL -php5 -c++ -DMULTIPLICITY -I../src/include -o esl_wrap.cpp ../ESL.i
sed -e 's/ char \*type_name;/ const char \*type_name;/' -i esl_wrap.cpp
esl_wrap.o: esl_wrap.cpp
$(CXX) $(CXX_CFLAGS) $(CXXFLAGS) $(LOCAL_CFLAGS) $(WRAP_GCC_WARNING_SILENCE) -c esl_wrap.cpp -o esl_wrap.o
+1 -1
View File
@@ -857,7 +857,7 @@ SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) {
swig_object_wrapper *value;
void *p;
int type;
char *type_name;
const char *type_name;
value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type);
if ( flags && SWIG_POINTER_DISOWN ) {
+1 -1
View File
@@ -1,4 +1,4 @@
const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n";
const char *cc = ".=======================================================================================================.\n| ____ _ ____ |\n| / ___| |_ _ ___ / ___|___ _ __ |\n| | | | | | | |/ _ \\ | / _ \\| '_ \\ |\n| | |___| | |_| | __/ |__| (_) | | | | |\n| \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |\n| |\n| _____ _ _ ____ __ |\n| |_ _|__| | ___ _ __ | |__ ___ _ __ _ _ / ___|___ _ __ / _| ___ _ __ ___ _ __ ___ ___ |\n| | |/ _ \\ |/ _ \\ '_ \\| '_ \\ / _ \\| '_ \\| | | | | | / _ \\| '_ \\| |_ / _ \\ '__/ _ \\ '_ \\ / __/ _ \\ |\n| | | __/ | __/ |_) | | | | (_) | | | | |_| | | |__| (_) | | | | _| __/ | | __/ | | | (_| __/ |\n| |_|\\___|_|\\___| .__/|_| |_|\\___/|_| |_|\\__, | \\____\\___/|_| |_|_| \\___|_| \\___|_| |_|\\___\\___| |\n| |_| |___/ |\n| _____ _ _ |\n| | ____|_ _____ _ __ _ _ / \\ _ _ __ _ _ _ ___| |_ |\n| | _| \\ \\ / / _ \\ '__| | | | / _ \\| | | |/ _` | | | / __| __| |\n| | |___ \\ V / __/ | | |_| | / ___ \\ |_| | (_| | |_| \\__ \\ |_ |\n| |_____| \\_/ \\___|_| \\__, | /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| |\n| |___/ |___/ |\n| ____ _ ____ |\n| __ ____ ____ __ / ___| |_ _ ___ / ___|___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / | | | | | | |/ _ \\ | / _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | |___| | |_| | __/ |__| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\____|_|\\__,_|\\___|\\____\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.=======================================================================================================.\n";
const char *cc_s = ".===============================================================.\n| _ |\n| ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.===============================================================.\n";
@@ -1913,6 +1913,12 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
ftdm_set_string(caller_data->dnis.digits, (char *)pevent->ring.callednum);
ftdm_set_string(caller_data->rdnis.digits, (char *)pevent->ring.redirectingnum);
caller_data->cid_num.type = pevent->ring.callingplan >> 4;
caller_data->cid_num.plan = pevent->ring.callingplan & 0x0F;
caller_data->dnis.type = pevent->ring.calledplan >> 4;
caller_data->dnis.plan = pevent->ring.calledplan & 0x0F;
if (!ftdm_strlen_zero((char *)pevent->ring.callingname)) {
ftdm_set_string(caller_data->cid_name, (char *)pevent->ring.callingname);
} else {
+1 -1
View File
@@ -1 +1 @@
Tue Sep 17 06:24:17 CDT 2013
Tue Oct 8 12:10:32 CDT 2013
@@ -1589,7 +1589,7 @@ static void parse_media_attr(sdp_parser_t *p, char *r, sdp_media_t *m,
if (p->pr_mode_manual)
;
else if (su_casematch(name, "inactive")) {
else if (m->m_port == 0 || su_casematch(name, "inactive")) {
m->m_mode = sdp_inactive;
return;
}
+10 -8
View File
@@ -640,14 +640,16 @@ static void print_media(sdp_printer_t *p,
print_key(p, m->m_key);
for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) {
if (!rm->rm_predef || p->pr_all_rtpmaps)
sdp_printf(p, "a=rtpmap:%u %s/%lu%s%s" CRLF,
rm->rm_pt, rm->rm_encoding, rm->rm_rate,
rm->rm_params ? "/" : "",
rm->rm_params ? rm->rm_params : "");
if (rm->rm_fmtp)
sdp_printf(p, "a=fmtp:%u %s" CRLF,
rm->rm_pt, rm->rm_fmtp);
if (rm->rm_encoding && *rm->rm_encoding && (!rm->rm_predef || p->pr_all_rtpmaps)) {
sdp_printf(p, "a=rtpmap:%u %s/%lu%s%s" CRLF,
rm->rm_pt, rm->rm_encoding, rm->rm_rate,
rm->rm_params ? "/" : "",
rm->rm_params ? rm->rm_params : "");
}
if (rm->rm_fmtp) {
sdp_printf(p, "a=fmtp:%u %s" CRLF,
rm->rm_pt, rm->rm_fmtp);
}
}
if (!p->pr_mode_manual && !m->m_rejected &&
@@ -116,7 +116,7 @@ static int sip_allow_update(msg_common_t *h,
k->k_bitmap = 0;
}
else {
sip_method_t method = sip_method_code(name);
int method = (int)sip_method_code(name);
if (method >= 0 && method < 32)
k->k_bitmap |= 1 << method;
@@ -130,14 +130,16 @@ int sip_is_allowed(sip_allow_t const *allow,
sip_method_t method,
char const *name)
{
if (method < sip_method_unknown || !allow)
int meth = method;
if (meth < sip_method_unknown || !allow)
return 0;
if (sip_method_unknown < method && method < 32)
if (sip_method_unknown < meth && meth < 32)
/* Well-known method */
return (allow->k_bitmap & (1 << method)) != 0;
return (allow->k_bitmap & (1 << meth)) != 0;
if (method == sip_method_unknown &&
if (meth == sip_method_unknown &&
(allow->k_bitmap & (1 << sip_method_unknown)) == 0)
return 0;
@@ -672,7 +672,7 @@ static void sip_fragment_clear_chain(sip_header_t *h)
{
void const *next;
for (h = h; h; h = h->sh_succ) {
for (; h; h = h->sh_succ) {
next = (char *)h->sh_data + h->sh_len;
sip_fragment_clear(h->sh_common);
+2 -1
View File
@@ -3322,7 +3322,8 @@ tport_t *tport_tsend(tport_t *self,
self = primary->pri_primary;
}
else if (tport_is_secondary(self) && tport_is_clear_to_send(self)) {
self = self;
/* self = self; */
;
}
/*
* Try to find an already open connection to the destination,
+21 -6
View File
@@ -223,6 +223,7 @@ int ws_handshake(wsh_t *wsh)
char key[256] = "";
char version[5] = "";
char proto[256] = "";
char proto_buf[384] = "";
char uri[256] = "";
char input[256] = "";
unsigned char output[SHA1_HASH_SIZE] = "";
@@ -242,7 +243,7 @@ int ws_handshake(wsh_t *wsh)
}
}
if (bytes > sizeof(wsh->buffer)) {
if (bytes > sizeof(wsh->buffer) -1) {
goto err;
}
@@ -273,14 +274,18 @@ int ws_handshake(wsh_t *wsh)
sha1_digest(output, input);
b64encode((unsigned char *)output, SHA1_HASH_SIZE, (unsigned char *)b64, sizeof(b64));
if (*proto) {
snprintf(proto_buf, sizeof(proto_buf), "Sec-WebSocket-Protocol: %s\r\n", proto);
}
snprintf(respond, sizeof(respond),
"HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %s\r\n"
"Sec-WebSocket-Protocol: %s\r\n\r\n",
"%s\r\n",
b64,
proto);
proto_buf);
ws_raw_write(wsh, respond, strlen(respond));
@@ -319,7 +324,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes)
#endif
} while (r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_READ && x < 100);
return r;
goto end;
}
do {
@@ -336,6 +341,12 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes)
r = -1;
}
end:
if (r > 0) {
*((char *)data + r) = '\0';
}
return r;
}
@@ -530,7 +541,7 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)
restore_socket(wsh->sock);
if (wsh->close_sock) {
if (wsh->close_sock && wsh->sock != ws_sock_invalid) {
close(wsh->sock);
}
@@ -559,7 +570,11 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
return ws_close(wsh, WS_PROTO_ERR);
}
if ((wsh->datalen = ws_raw_read(wsh, wsh->buffer, 9)) < need) {
if ((wsh->datalen = ws_raw_read(wsh, wsh->buffer, 9)) < 0) {
return ws_close(wsh, WS_PROTO_ERR);
}
if (wsh->datalen < need) {
if ((wsh->datalen += ws_raw_read(wsh, wsh->buffer + wsh->datalen, 9 - wsh->datalen)) < need) {
/* too small - protocol err */
return ws_close(wsh, WS_PROTO_ERR);
+2 -8
View File
@@ -13,6 +13,7 @@
#include <sys/socket.h>
#else
#pragma warning(disable:4996)
#include <config.h>
#endif
#include <string.h>
#include <unistd.h>
@@ -26,14 +27,7 @@
#include <openssl/ssl.h>
#ifdef _MSC_VER
#ifdef _WIN64
#define WS_SSIZE_T __int64
#elif _MSC_VER >= 1400
#define WS_SSIZE_T __int32 __w64
#else
#define WS_SSIZE_T __int32
#endif
typedef WS_SSIZE_T ssize_t
typedef intptr_t ssize_t;
#endif
+17 -47
View File
@@ -163,7 +163,8 @@ SPAN_DECLARE_NONSTD(int) fax_rx(fax_state_t *s, int16_t *amp, int len)
#endif
for (i = 0; i < len; i++)
amp[i] = dc_restore(&s->modems.dc_restore, amp[i]);
s->modems.rx_handler(s->modems.rx_user_data, amp, len);
if (s->modems.rx_handler)
s->modems.rx_handler(s->modems.rx_user_data, amp, len);
t30_timer_update(&s->t30, len);
return 0;
}
@@ -197,26 +198,6 @@ SPAN_DECLARE_NONSTD(int) fax_rx_fillin(fax_state_t *s, int len)
}
/*- End of function --------------------------------------------------------*/
static int set_next_tx_type(fax_state_t *s)
{
fax_modems_state_t *t;
t = &s->modems;
if (t->next_tx_handler)
{
fax_modems_set_tx_handler(t, t->next_tx_handler, t->next_tx_user_data);
t->next_tx_handler = NULL;
return 0;
}
/* If there is nothing else to change to, so use zero length silence */
silence_gen_alter(&t->silence_gen, 0);
fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(t, (span_tx_handler_t) NULL, NULL);
t->transmit = false;
return -1;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len)
{
int len;
@@ -226,41 +207,30 @@ SPAN_DECLARE_NONSTD(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len)
required_len = max_len;
#endif
len = 0;
if (s->modems.transmit)
while (s->modems.transmit && (len += s->modems.tx_handler(s->modems.tx_user_data, &amp[len], max_len - len)) < max_len)
{
while ((len += s->modems.tx_handler(s->modems.tx_user_data, amp + len, max_len - len)) < max_len)
{
/* Allow for a change of tx handler within a block */
if (set_next_tx_type(s) && s->modems.current_tx_type != T30_MODEM_NONE && s->modems.current_tx_type != T30_MODEM_DONE)
t30_front_end_status(&s->t30, T30_FRONT_END_SEND_STEP_COMPLETE);
if (!s->modems.transmit)
{
if (s->modems.transmit_on_idle)
{
/* Pad to the requested length with silence */
memset(amp + len, 0, (max_len - len)*sizeof(int16_t));
len = max_len;
}
break;
}
}
/* Allow for a change of tx handler within a block */
if (fax_modems_set_next_tx_type(&s->modems) && s->modems.current_tx_type != T30_MODEM_NONE && s->modems.current_tx_type != T30_MODEM_DONE)
t30_front_end_status(&s->t30, T30_FRONT_END_SEND_STEP_COMPLETE);
/*endif*/
}
else
/*endwhile*/
if (s->modems.transmit_on_idle)
{
if (s->modems.transmit_on_idle)
{
/* Pad to the requested length with silence */
memset(amp, 0, max_len*sizeof(int16_t));
len = max_len;
}
/* Pad to the requested length with silence */
memset(&amp[len], 0, (max_len - len)*sizeof(int16_t));
len = max_len;
}
/*endif*/
#if defined(LOG_FAX_AUDIO)
if (s->modems.audio_tx_log >= 0)
{
if (len < required_len)
memset(amp + len, 0, (required_len - len)*sizeof(int16_t));
memset(&amp[len], 0, (required_len - len)*sizeof(int16_t));
/*endif*/
write(s->modems.audio_tx_log, amp, required_len*sizeof(int16_t));
}
/*endif*/
#endif
return len;
}
@@ -285,7 +255,6 @@ static void fax_set_rx_type(void *user_data, int type, int bit_rate, int short_t
{
case T30_MODEM_V21:
fax_modems_start_slow_modem(t, FAX_MODEM_V21_RX);
fax_modems_set_rx_handler(t, (span_rx_handler_t) &fsk_rx, &t->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &t->v21_rx);
break;
case T30_MODEM_V17:
fax_modems_start_fast_modem(t, FAX_MODEM_V17_RX, bit_rate, short_train, use_hdlc);
@@ -316,6 +285,7 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
if (t->current_tx_type == type)
return;
switch (type)
{
case T30_MODEM_PAUSE:
+61
View File
@@ -101,6 +101,50 @@
#define HDLC_FRAMING_OK_THRESHOLD 5
SPAN_DECLARE(const char *) fax_modem_to_str(int modem)
{
switch (modem)
{
case FAX_MODEM_NONE:
return "None";
case FAX_MODEM_FLUSH:
return "Flush";
case FAX_MODEM_SILENCE_TX:
return "Silence Tx";
case FAX_MODEM_SILENCE_RX:
return "Silence Rx";
case FAX_MODEM_CED_TONE_TX:
return "CED Tx";
case FAX_MODEM_CNG_TONE_TX:
return "CNG Tx";
case FAX_MODEM_NOCNG_TONE_TX:
return "No CNG Tx";
case FAX_MODEM_CED_TONE_RX:
return "CED Rx";
case FAX_MODEM_CNG_TONE_RX:
return "CNG Rx";
case FAX_MODEM_V21_TX:
return "V.21 Tx";
case FAX_MODEM_V17_TX:
return "V.17 Tx";
case FAX_MODEM_V27TER_TX:
return "V.27ter Tx";
case FAX_MODEM_V29_TX:
return "V.29 Tx";
case FAX_MODEM_V21_RX:
return "V.21 Rx";
case FAX_MODEM_V17_RX:
return "V.17 Rx";
case FAX_MODEM_V27TER_RX:
return "V.27ter Rx";
case FAX_MODEM_V29_RX:
return "V.29 Rx";
}
/*endswitch*/
return "???";
}
/*- End of function --------------------------------------------------------*/
static void fax_modems_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok)
{
fax_modems_state_t *s;
@@ -489,6 +533,23 @@ SPAN_DECLARE(void) fax_modems_set_next_tx_handler(fax_modems_state_t *s, span_tx
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) fax_modems_set_next_tx_type(fax_modems_state_t *s)
{
if (s->next_tx_handler)
{
fax_modems_set_tx_handler(s, s->next_tx_handler, s->next_tx_user_data);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t) NULL, NULL);
return 0;
}
/* There is nothing else to change to, so use zero length silence */
silence_gen_alter(&s->silence_gen, 0);
fax_modems_set_tx_handler(s, (span_tx_handler_t) &silence_gen, &s->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t) NULL, NULL);
s->transmit = false;
return -1;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) fax_modems_set_tep_mode(fax_modems_state_t *s, int use_tep)
{
s->use_tep = use_tep;
-4
View File
@@ -24,10 +24,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
-9
View File
@@ -25,22 +25,13 @@
/*! \file */
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <memory.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#endif
typedef struct
{
@@ -24,10 +24,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
+4 -10
View File
@@ -24,10 +24,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <unistd.h>
@@ -35,22 +31,20 @@
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#endif
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include "spandsp/stdbool.h"
#endif
#include "floating_fudge.h"
#if defined(__sunos) || defined(__solaris) || defined(__sun)
#include <getopt.h>
#endif
#if defined (_MSC_VER)
#define __inline__ __inline
#endif
#include "spandsp/telephony.h"
#include "spandsp/complex.h"
#include "filter_tools.h"
+2 -5
View File
@@ -24,10 +24,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
@@ -41,12 +37,13 @@ int main(int argc, char *argv[])
int j;
int gray;
int new_gray;
int restore = 0;
int restore;
printf("static const int16_t gray_code[4096] =\n{\n");
for (i = 0; i < 4096; i++)
{
gray = i & 0x800;
restore = i;
for (j = 10; j >= 0; j--)
{
if (((i >> (j + 1)) & 1) ^ ((i >> j) & 1))
+2 -1
View File
@@ -36,9 +36,10 @@
#define SPANDSP_USE_EXPORT_CAPABILITY 1
#undef SPANDSP_SUPPORT_T42
#undef SPANDSP_SUPPORT_T43
#undef SPANDSP_SUPPORT_V32BIS
#undef SPANDSP_SUPPORT_V34
#undef SPANDSP_SUPPORT_TIFF_FX
#include <stdlib.h>
#include <msvc/inttypes.h>
+2 -2
View File
@@ -42,7 +42,7 @@ extern "C"
/*! \brief Find the bit position of the highest set bit in a word
\param bits The word to be searched
\return The bit number of the highest set bit, or -1 if the word is zero. */
static __inline__ int top_bit(unsigned int bits)
static __inline__ int top_bit(uint32_t bits)
{
#if defined(SPANDSP_USE_86_ASM)
int res;
@@ -141,7 +141,7 @@ static __inline__ int top_bit(unsigned int bits)
/*! \brief Find the bit position of the lowest set bit in a word
\param bits The word to be searched
\return The bit number of the lowest set bit, or -1 if the word is zero. */
static __inline__ int bottom_bit(unsigned int bits)
static __inline__ int bottom_bit(uint32_t bits)
{
int res;
+8
View File
@@ -59,6 +59,12 @@ extern "C"
{
#endif
/*! Convert a FAX modem type to a short text description.
\brief Convert a FAX modem type to a short text description.
\param modem The modem code.
\return A pointer to the description. */
SPAN_DECLARE(const char *) fax_modem_to_str(int modem);
/* N.B. the following are currently a work in progress */
SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], int len);
SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len);
@@ -93,6 +99,8 @@ SPAN_DECLARE(void) fax_modems_set_tx_handler(fax_modems_state_t *s, span_tx_hand
SPAN_DECLARE(void) fax_modems_set_next_tx_handler(fax_modems_state_t *s, span_tx_handler_t handler, void *user_data);
SPAN_DECLARE(int) fax_modems_set_next_tx_type(fax_modems_state_t *s);
SPAN_DECLARE(int) fax_modems_restart(fax_modems_state_t *s);
/*! Get a pointer to the logging context associated with a FAX modems context.
+6
View File
@@ -53,6 +53,12 @@ SPAN_DECLARE(void) t30_decode_dis_dtc_dcs(t30_state_t *s, const uint8_t *dis, in
\return A pointer to the description. */
SPAN_DECLARE(const char *) t30_completion_code_to_str(int result);
/*! Convert a T.30 modem type to a short text description.
\brief Convert a T.30 modem type to a short text description.
\param modem The modem code.
\return A pointer to the description. */
SPAN_DECLARE(const char *) t30_modem_to_str(int modem);
#if defined(__cplusplus)
}
#endif
+34 -25
View File
@@ -421,7 +421,7 @@ static const struct
{ 7200, T30_MODEM_V29, T30_SUPPORT_V29, (DISBIT4 | DISBIT3)},
{ 4800, T30_MODEM_V27TER, T30_SUPPORT_V27TER, DISBIT4},
{ 2400, T30_MODEM_V27TER, T30_SUPPORT_V27TER, 0},
{ 0, 0, 0, 0}
{ 0, 0, 0, 0}
};
static void queue_phase(t30_state_t *s, int phase);
@@ -437,6 +437,7 @@ static void decode_20digit_msg(t30_state_t *s, char *msg, const uint8_t *pkt, in
static void decode_url_msg(t30_state_t *s, char *msg, const uint8_t *pkt, int len);
static int decode_nsf_nss_nsc(t30_state_t *s, uint8_t *msg[], const uint8_t *pkt, int len);
static void set_min_scan_time(t30_state_t *s);
static int build_dcs(t30_state_t *s);
static void timer_t2_start(t30_state_t *s);
static void timer_t2a_start(t30_state_t *s);
static void timer_t2b_start(t30_state_t *s);
@@ -470,6 +471,27 @@ static int find_fallback_entry(int dcs_code)
}
/*- End of function --------------------------------------------------------*/
static int step_fallback_entry(t30_state_t *s)
{
while (fallback_sequence[++s->current_fallback].bit_rate)
{
if ((fallback_sequence[s->current_fallback].which & s->current_permitted_modems))
break;
}
if (fallback_sequence[s->current_fallback].bit_rate == 0)
{
/* Reset the fallback sequence */
s->current_fallback = 0;
return -1;
}
/* We need to update the minimum scan time, in case we are in non-ECM mode. */
set_min_scan_time(s);
/* Now we need to rebuild the DCS message we will send. */
build_dcs(s);
return s->current_fallback;
}
/*- End of function --------------------------------------------------------*/
static int terminate_operation_in_progress(t30_state_t *s)
{
/* Make sure any FAX in progress is tidied up. If the tidying up has
@@ -2242,23 +2264,6 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
}
/*- End of function --------------------------------------------------------*/
static int step_fallback_entry(t30_state_t *s)
{
while (fallback_sequence[++s->current_fallback].which)
{
if ((fallback_sequence[s->current_fallback].which & s->current_permitted_modems))
break;
}
if (fallback_sequence[s->current_fallback].which == 0)
return -1;
/* We need to update the minimum scan time, in case we are in non-ECM mode. */
set_min_scan_time(s);
/* Now we need to rebuild the DCS message we will send. */
build_dcs(s);
return s->current_fallback;
}
/*- End of function --------------------------------------------------------*/
static void send_dcn(t30_state_t *s)
{
queue_phase(s, T30_PHASE_D_TX);
@@ -2710,6 +2715,13 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
send_dcn(s);
return -1;
}
/* Start document transmission */
span_log(&s->logging,
SPAN_LOG_FLOW,
"Put document with modem (%d) %s at %dbps\n",
fallback_sequence[s->current_fallback].modem_type,
t30_modem_to_str(fallback_sequence[s->current_fallback].modem_type),
fallback_sequence[s->current_fallback].bit_rate);
s->retries = 0;
send_dcs_sequence(s, true);
return 0;
@@ -2773,9 +2785,10 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
/* Start document reception */
span_log(&s->logging,
SPAN_LOG_FLOW,
"Get document at %dbps, modem %d\n",
fallback_sequence[s->current_fallback].bit_rate,
fallback_sequence[s->current_fallback].modem_type);
"Get document with modem (%d) %s at %dbps\n",
fallback_sequence[s->current_fallback].modem_type,
t30_modem_to_str(fallback_sequence[s->current_fallback].modem_type),
fallback_sequence[s->current_fallback].bit_rate);
if (s->rx_file[0] == '\0')
{
span_log(&s->logging, SPAN_LOG_FLOW, "No document to receive\n");
@@ -3439,7 +3452,6 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len
if (step_fallback_entry(s) < 0)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
@@ -4091,7 +4103,6 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
if (step_fallback_entry(s) < 0)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
@@ -4152,7 +4163,6 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
if (step_fallback_entry(s) < 0)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
@@ -4186,7 +4196,6 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
if (step_fallback_entry(s) < 0)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
+30
View File
@@ -246,6 +246,36 @@ SPAN_DECLARE(const char *) t30_completion_code_to_str(int result)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(const char *) t30_modem_to_str(int modem)
{
switch (modem)
{
case T30_MODEM_NONE:
return "None";
case T30_MODEM_PAUSE:
return "Pause";
case T30_MODEM_CED:
return "CED";
case T30_MODEM_CNG:
return "CNG";
case T30_MODEM_V21:
return "V.21";
case T30_MODEM_V27TER:
return "V.27ter";
case T30_MODEM_V29:
return "V.29";
case T30_MODEM_V17:
return "V.17";
case T30_MODEM_V34HDX:
return "V.34HDX";
case T30_MODEM_DONE:
return "Done";
}
/*endswitch*/
return "???";
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(const char *) t30_frametype(uint8_t x)
{
switch (x)
+5 -21
View File
@@ -2830,7 +2830,8 @@ SPAN_DECLARE_NONSTD(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
}
/*endif*/
s->audio.modems.rx_handler(s->audio.modems.rx_user_data, amp, len);
if (s->audio.modems.rx_handler)
s->audio.modems.rx_handler(s->audio.modems.rx_user_data, amp, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
@@ -2861,23 +2862,6 @@ SPAN_DECLARE_NONSTD(int) t31_rx_fillin(t31_state_t *s, int len)
}
/*- End of function --------------------------------------------------------*/
static int set_next_tx_type(t31_state_t *s)
{
if (s->audio.next_tx_handler)
{
fax_modems_set_tx_handler(&s->audio.modems, s->audio.next_tx_handler, s->audio.next_tx_user_data);
fax_modems_set_next_tx_handler(&s->audio.modems, (span_tx_handler_t) NULL, NULL);
return 0;
}
/*endif*/
/* There is nothing else to change to, so use zero length silence */
silence_gen_alter(&s->audio.modems.silence_gen, 0);
fax_modems_set_tx_handler(&s->audio.modems, (span_tx_handler_t) &silence_gen, &s->audio.modems.silence_gen);
fax_modems_set_next_tx_handler(&s->audio.modems, (span_tx_handler_t) NULL, NULL);
return -1;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len)
{
int len;
@@ -2888,8 +2872,8 @@ SPAN_DECLARE_NONSTD(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len)
if ((len = s->audio.modems.tx_handler(s->audio.modems.tx_user_data, amp, max_len)) < max_len)
{
/* Allow for one change of tx handler within a block */
set_next_tx_type(s);
if ((len += s->audio.modems.tx_handler(s->audio.modems.tx_user_data, amp + len, max_len - len)) < max_len)
fax_modems_set_next_tx_type(&s->audio.modems);
if ((len += s->audio.modems.tx_handler(s->audio.modems.tx_user_data, &amp[len], max_len - len)) < max_len)
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
/*endif*/
}
@@ -2899,7 +2883,7 @@ SPAN_DECLARE_NONSTD(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len)
if (s->audio.modems.transmit_on_idle)
{
/* Pad to the requested length with silence */
memset(amp + len, 0, (max_len - len)*sizeof(int16_t));
memset(&amp[len], 0, (max_len - len)*sizeof(int16_t));
len = max_len;
}
/*endif*/
+6 -4
View File
@@ -2061,7 +2061,8 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], i
for (i = 0; i < len; i++)
amp[i] = dc_restore(&s->audio.modems.dc_restore, amp[i]);
/*endfor*/
s->audio.modems.rx_handler(s->audio.modems.rx_user_data, amp, len);
if (s->audio.modems.rx_handler)
s->audio.modems.rx_handler(s->audio.modems.rx_user_data, amp, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
@@ -2102,12 +2103,13 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], i
required_len = max_len;
#endif
len = 0;
if ((len = s->audio.modems.tx_handler(s->audio.modems.tx_user_data, amp, max_len)) < max_len)
{
if (set_next_tx_type(s))
{
/* Give the new handler a chance to file the remaining buffer space */
len += s->audio.modems.tx_handler(s->audio.modems.tx_user_data, amp + len, max_len - len);
len += s->audio.modems.tx_handler(s->audio.modems.tx_user_data, &amp[len], max_len - len);
if (len < max_len)
{
silence_gen_set(&s->audio.modems.silence_gen, 0);
@@ -2121,7 +2123,7 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], i
if (s->audio.modems.transmit_on_idle)
{
/* Pad to the requested length with silence */
memset(amp + len, 0, (max_len - len)*sizeof(int16_t));
memset(&amp[len], 0, (max_len - len)*sizeof(int16_t));
len = max_len;
}
/*endif*/
@@ -2129,7 +2131,7 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], i
if (s->audio.modems.audio_tx_log >= 0)
{
if (len < required_len)
memset(amp + len, 0, (required_len - len)*sizeof(int16_t));
memset(&amp[len], 0, (required_len - len)*sizeof(int16_t));
/*endif*/
write(s->audio.modems.audio_tx_log, amp, required_len*sizeof(int16_t));
}
-1
View File
@@ -41,7 +41,6 @@
#include <ctype.h>
#include <time.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <sndfile.h>
#if defined(HAVE_LIBXML_XMLMEMORY_H)
+2 -1
View File
@@ -129,7 +129,8 @@ int main(int argc, char *argv[])
}
switch_loadable_module_init(SWITCH_FALSE);
switch_loadable_module_load_module("", "CORE_PCM_MODULE", SWITCH_TRUE, &err);
for (i = 0; i < extra_modules_count; i++) {
if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) extra_modules[i], SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
fprintf(stderr, "Cannot init %s [%s]\n", extra_modules[i], err);
+1 -1
View File
@@ -1,4 +1,4 @@
const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n";
const char *cc = ".=======================================================================================================.\n| ____ _ ____ |\n| / ___| |_ _ ___ / ___|___ _ __ |\n| | | | | | | |/ _ \\ | / _ \\| '_ \\ |\n| | |___| | |_| | __/ |__| (_) | | | | |\n| \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |\n| |\n| _____ _ _ ____ __ |\n| |_ _|__| | ___ _ __ | |__ ___ _ __ _ _ / ___|___ _ __ / _| ___ _ __ ___ _ __ ___ ___ |\n| | |/ _ \\ |/ _ \\ '_ \\| '_ \\ / _ \\| '_ \\| | | | | | / _ \\| '_ \\| |_ / _ \\ '__/ _ \\ '_ \\ / __/ _ \\ |\n| | | __/ | __/ |_) | | | | (_) | | | | |_| | | |__| (_) | | | | _| __/ | | __/ | | | (_| __/ |\n| |_|\\___|_|\\___| .__/|_| |_|\\___/|_| |_|\\__, | \\____\\___/|_| |_|_| \\___|_| \\___|_| |_|\\___\\___| |\n| |_| |___/ |\n| _____ _ _ |\n| | ____|_ _____ _ __ _ _ / \\ _ _ __ _ _ _ ___| |_ |\n| | _| \\ \\ / / _ \\ '__| | | | / _ \\| | | |/ _` | | | / __| __| |\n| | |___ \\ V / __/ | | |_| | / ___ \\ |_| | (_| | |_| \\__ \\ |_ |\n| |_____| \\_/ \\___|_| \\__, | /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| |\n| |___/ |___/ |\n| ____ _ ____ |\n| __ ____ ____ __ / ___| |_ _ ___ / ___|___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / | | | | | | |/ _ \\ | / _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | |___| | |_| | __/ |__| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\____|_|\\__,_|\\___|\\____\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.=======================================================================================================.\n";
const char *cc_s = ".===============================================================.\n| _ |\n| ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.===============================================================.\n";
+4
View File
@@ -290,10 +290,14 @@ struct switch_session_manager {
switch_queue_t *thread_queue;
switch_thread_t *manager_thread;
switch_mutex_t *mutex;
switch_thread_cond_t *cond;
switch_mutex_t *cond_mutex;
switch_mutex_t *cond2_mutex;
int ready;
int running;
int busy;
int popping;
int starting;
};
extern struct switch_session_manager session_manager;
+1 -1
View File
@@ -1751,7 +1751,7 @@ SWITCH_DECLARE(void) switch_core_db_test_reactive(switch_core_db_t *db, char *te
SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, const char *func, int line,
_In_ switch_file_handle_t *fh,
_In_opt_z_ const char *file_path,
_In_ uint8_t channels,
_In_ uint32_t channels,
_In_ uint32_t rate, _In_ unsigned int flags, _In_opt_ switch_memory_pool_t *pool);
/*!
+3 -1
View File
@@ -310,7 +310,7 @@ struct switch_file_handle {
/*! the current native samplerate */
uint32_t native_rate;
/*! the number of channels */
uint8_t channels;
uint32_t channels;
/*! integer representation of the format */
unsigned int format;
/*! integer representation of the sections */
@@ -353,6 +353,8 @@ struct switch_file_handle {
const char *prefix;
int max_samples;
switch_event_t *params;
uint32_t cur_channels;
uint32_t cur_samplerate;
};
/*! \brief Abstract interface to an asr module */
+5 -2
View File
@@ -1041,7 +1041,9 @@ typedef enum {
SWITCH_STATUS_FOUND,
SWITCH_STATUS_CONTINUE,
SWITCH_STATUS_TERM,
SWITCH_STATUS_NOT_INITALIZED
SWITCH_STATUS_NOT_INITALIZED,
SWITCH_STATUS_XBREAK = 35,
SWITCH_STATUS_WINBREAK = 730035
} switch_status_t;
@@ -1615,7 +1617,8 @@ typedef enum {
SWITCH_FILE_BUFFER_DONE = (1 << 14),
SWITCH_FILE_WRITE_APPEND = (1 << 15),
SWITCH_FILE_WRITE_OVER = (1 << 16),
SWITCH_FILE_NOMUX = (1 << 17)
SWITCH_FILE_NOMUX = (1 << 17),
SWITCH_FILE_BREAK_ON_CHANGE = (1 << 18)
} switch_file_flag_enum_t;
typedef uint32_t switch_file_flag_t;
@@ -24,6 +24,7 @@
* Contributor(s):
*
* Marc Olivier Chouinard <mochouinard@moctel.com>
* Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
*
*
* mod_callcenter.c -- Call Center Module
@@ -1452,9 +1453,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_channel_process_export(member_channel, NULL, ovars, "cc_export_vars");
t_agent_called = local_epoch_time_now(NULL);
dialstr = switch_mprintf("%s", h->originate_string);
dialstr = switch_channel_expand_variables(member_channel, h->originate_string);
status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, cid_name ? cid_name : h->member_cid_name, h->member_cid_number, NULL, ovars, SOF_NONE, NULL);
switch_safe_free(dialstr);
if (dialstr != h->originate_string) {
switch_safe_free(dialstr);
}
switch_safe_free(cid_name);
switch_event_destroy(&ovars);
@@ -1329,6 +1329,8 @@ SWITCH_STANDARD_API(stun_function)
switch_port_t port = 0;
switch_memory_pool_t *pool = NULL;
char *error = "";
char *argv[3] = { 0 };
char *mycmd = NULL;
ip = ip_buf;
@@ -1337,9 +1339,15 @@ SWITCH_STANDARD_API(stun_function)
return SWITCH_STATUS_SUCCESS;
}
stun_ip = strdup(cmd);
mycmd = strdup(cmd);
switch_split(mycmd, ' ', argv);
stun_ip = argv[0];
switch_assert(stun_ip);
port = argv[1] ? atoi(argv[1]) : 0;
if ((p = strchr(stun_ip, ':'))) {
int iport;
*p++ = '\0';
@@ -1374,7 +1382,7 @@ SWITCH_STANDARD_API(stun_function)
}
switch_core_destroy_memory_pool(&pool);
free(stun_ip);
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
@@ -4608,7 +4616,6 @@ SWITCH_STANDARD_API(show_function)
char *command = NULL, *as = NULL;
switch_core_flag_t cflags = switch_core_flags();
switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *hostname = switch_core_get_switchname();
int html = 0;
char *nl = "\n";
stream_format format = { 0 };
@@ -4661,33 +4668,33 @@ SWITCH_STANDARD_API(show_function)
if (end_of(command) == 's') {
end_of(command) = '\0';
}
sprintf(sql, "select type, name, ikey from interfaces where hostname='%s' and type = '%s' order by type,name", hostname, command);
sprintf(sql, "select type, name, ikey from interfaces where hostname='%s' and type = '%s' order by type,name", switch_core_get_hostname(), command);
} else if (!strncasecmp(command, "module", 6)) {
if (argv[1] && strcasecmp(argv[1], "as")) {
sprintf(sql, "select distinct type, name, ikey, filename from interfaces where hostname='%s' and ikey = '%s' order by type,name",
hostname, argv[1]);
switch_core_get_hostname(), argv[1]);
} else {
sprintf(sql, "select distinct type, name, ikey, filename from interfaces where hostname='%s' order by type,name", hostname);
sprintf(sql, "select distinct type, name, ikey, filename from interfaces where hostname='%s' order by type,name", switch_core_get_hostname());
}
} else if (!strcasecmp(command, "interfaces")) {
sprintf(sql, "select type, name, ikey from interfaces where hostname='%s' order by type,name", hostname);
sprintf(sql, "select type, name, ikey from interfaces where hostname='%s' order by type,name", switch_core_get_hostname());
} else if (!strcasecmp(command, "interface_types")) {
sprintf(sql, "select type,count(type) as total from interfaces where hostname='%s' group by type order by type", hostname);
sprintf(sql, "select type,count(type) as total from interfaces where hostname='%s' group by type order by type", switch_core_get_switchname());
} else if (!strcasecmp(command, "tasks")) {
sprintf(sql, "select * from %s where hostname='%s'", command, hostname);
sprintf(sql, "select * from %s where hostname='%s'", command, switch_core_get_hostname());
} else if (!strcasecmp(command, "application") || !strcasecmp(command, "api")) {
if (argv[1] && strcasecmp(argv[1], "as")) {
sprintf(sql,
"select name, description, syntax, ikey from interfaces where hostname='%s' and type = '%s' and description != '' and name = '%s' order by type,name",
hostname, command, argv[1]);
switch_core_get_hostname(), command, argv[1]);
} else {
sprintf(sql, "select name, description, syntax, ikey from interfaces where hostname='%s' and type = '%s' and description != '' order by type,name", hostname, command);
sprintf(sql, "select name, description, syntax, ikey from interfaces where hostname='%s' and type = '%s' and description != '' order by type,name", switch_core_get_hostname(), command);
}
/* moved refreshable webpage show commands i.e. show calls|registrations|channels||detailed_calls|bridged_calls|detailed_bridged_calls */
} else if (!strcasecmp(command, "aliases")) {
sprintf(sql, "select * from aliases where hostname='%s' order by alias", hostname);
sprintf(sql, "select * from aliases where hostname='%s' order by alias", switch_core_get_switchname());
} else if (!strcasecmp(command, "complete")) {
sprintf(sql, "select * from complete where hostname='%s' order by a1,a2,a3,a4,a5,a6,a7,a8,a9,a10", hostname);
sprintf(sql, "select * from complete where hostname='%s' order by a1,a2,a3,a4,a5,a6,a7,a8,a9,a10", switch_core_get_switchname());
} else if (!strncasecmp(command, "help", 4)) {
char *cmdname = NULL;
@@ -4697,9 +4704,9 @@ SWITCH_STANDARD_API(show_function)
*cmdname++ = '\0';
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);
switch_core_get_hostname(), cmdname);
} else {
switch_snprintfv(sql, sizeof(sql), "select name, syntax, description, ikey from interfaces where hostname='%q' 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", switch_core_get_hostname());
}
} else if (!strcasecmp(command, "nat_map")) {
switch_snprintf(sql, sizeof(sql) - 1,
@@ -4707,7 +4714,7 @@ SWITCH_STANDARD_API(show_function)
" CASE proto "
" WHEN 0 THEN 'udp' "
" WHEN 1 THEN 'tcp' "
" ELSE 'unknown' " " END AS proto, " " proto AS proto_num, " " sticky " " FROM nat where hostname='%s' ORDER BY port, proto", hostname);
" ELSE 'unknown' " " END AS proto, " " proto AS proto_num, " " sticky " " FROM nat where hostname='%s' ORDER BY port, proto", switch_core_get_hostname());
} else {
/* from here on refreshable commands: calls|registrations|channels||detailed_calls|bridged_calls|detailed_bridged_calls */
if (holder.format->api) {
@@ -4726,18 +4733,18 @@ SWITCH_STANDARD_API(show_function)
}
if (!strcasecmp(command, "calls")) {
sprintf(sql, "select * from basic_calls where hostname='%s' order by call_created_epoch", hostname);
sprintf(sql, "select * from basic_calls where hostname='%s' order by call_created_epoch", switch_core_get_switchname());
if (argv[1] && !strcasecmp(argv[1], "count")) {
sprintf(sql, "select count(*) from basic_calls where hostname='%s'", hostname);
sprintf(sql, "select count(*) from basic_calls where hostname='%s'", switch_core_get_switchname());
holder.justcount = 1;
if (argv[3] && !strcasecmp(argv[2], "as")) {
as = argv[3];
}
}
} else if (!strcasecmp(command, "registrations")) {
sprintf(sql, "select * from registrations where hostname='%s'", hostname);
sprintf(sql, "select * from registrations where hostname='%s'", switch_core_get_switchname());
if (argv[1] && !strcasecmp(argv[1], "count")) {
sprintf(sql, "select count(*) from registrations where hostname='%s'", hostname);
sprintf(sql, "select count(*) from registrations where hostname='%s'", switch_core_get_switchname());
holder.justcount = 1;
if (argv[3] && !strcasecmp(argv[2], "as")) {
as = argv[3];
@@ -4754,39 +4761,39 @@ SWITCH_STANDARD_API(show_function)
if (strchr(argv[2], '%')) {
sprintf(sql,
"select * from channels where hostname='%s' and uuid like '%s' or name like '%s' or cid_name like '%s' or cid_num like '%s' or presence_data like '%s' order by created_epoch",
hostname, argv[2], argv[2], argv[2], argv[2], argv[2]);
switch_core_get_switchname(), argv[2], argv[2], argv[2], argv[2], argv[2]);
} else {
sprintf(sql,
"select * from channels where hostname='%s' and uuid like '%%%s%%' or name like '%%%s%%' or cid_name like '%%%s%%' or cid_num like '%%%s%%' or presence_data like '%%%s%%' order by created_epoch",
hostname, argv[2], argv[2], argv[2], argv[2], argv[2]);
switch_core_get_switchname(), argv[2], argv[2], argv[2], argv[2], argv[2]);
}
if (argv[4] && !strcasecmp(argv[3], "as")) {
as = argv[4];
}
} else {
sprintf(sql, "select * from channels where hostname='%s' order by created_epoch", hostname);
sprintf(sql, "select * from channels where hostname='%s' order by created_epoch", switch_core_get_switchname());
}
} else if (!strcasecmp(command, "channels")) {
sprintf(sql, "select * from channels where hostname='%s' order by created_epoch", hostname);
sprintf(sql, "select * from channels where hostname='%s' order by created_epoch", switch_core_get_switchname());
if (argv[1] && !strcasecmp(argv[1], "count")) {
sprintf(sql, "select count(*) from channels where hostname='%s'", hostname);
sprintf(sql, "select count(*) from channels where hostname='%s'", switch_core_get_switchname());
holder.justcount = 1;
if (argv[3] && !strcasecmp(argv[2], "as")) {
as = argv[3];
}
}
} else if (!strcasecmp(command, "detailed_calls")) {
sprintf(sql, "select * from detailed_calls where hostname='%s' order by created_epoch", hostname);
sprintf(sql, "select * from detailed_calls where hostname='%s' order by created_epoch", switch_core_get_switchname());
if (argv[2] && !strcasecmp(argv[1], "as")) {
as = argv[2];
}
} else if (!strcasecmp(command, "bridged_calls")) {
sprintf(sql, "select * from basic_calls where b_uuid is not null and hostname='%s' order by created_epoch", hostname);
sprintf(sql, "select * from basic_calls where b_uuid is not null and hostname='%s' order by created_epoch", switch_core_get_switchname());
if (argv[2] && !strcasecmp(argv[1], "as")) {
as = argv[2];
}
} else if (!strcasecmp(command, "detailed_bridged_calls")) {
sprintf(sql, "select * from detailed_calls where b_uuid is not null and hostname='%s' order by created_epoch", hostname);
sprintf(sql, "select * from detailed_calls where b_uuid is not null and hostname='%s' order by created_epoch", switch_core_get_switchname());
if (argv[2] && !strcasecmp(argv[1], "as")) {
as = argv[2];
}
@@ -286,6 +286,17 @@ struct vid_helper {
int up;
};
struct conference_obj;
/* Record Node */
typedef struct conference_record {
struct conference_obj *conference;
char *path;
switch_memory_pool_t *pool;
switch_bool_t autorec;
struct conference_record *next;
} conference_record_t;
/* Conference Object */
typedef struct conference_obj {
char *name;
@@ -352,7 +363,7 @@ typedef struct conference_obj {
int pin_retries;
int broadcast_chat_messages;
int comfort_noise_level;
int is_recording;
int auto_recording;
int record_count;
int video_running;
int ivr_dtmf_timeout;
@@ -385,6 +396,7 @@ typedef struct conference_obj {
cdr_event_mode_t cdr_event_mode;
struct vid_helper vh[2];
struct vid_helper mh;
conference_record_t *rec_node_head;
} conference_obj_t;
/* Relationship with another member */
@@ -421,6 +433,7 @@ struct conference_member {
switch_codec_t write_codec;
char *rec_path;
switch_time_t rec_time;
conference_record_t *rec;
uint8_t *frame;
uint8_t *last_frame;
uint32_t frame_size;
@@ -455,13 +468,6 @@ struct conference_member {
switch_thread_t *input_thread;
};
/* Record Node */
typedef struct conference_record {
conference_obj_t *conference;
char *path;
switch_memory_pool_t *pool;
} conference_record_t;
typedef enum {
CONF_API_SUB_ARGS_SPLIT,
CONF_API_SUB_MEMBER_TARGET,
@@ -529,7 +535,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
static switch_status_t chat_send(switch_event_t *message_event);
static void launch_conference_record_thread(conference_obj_t *conference, char *path);
static void launch_conference_record_thread(conference_obj_t *conference, char *path, switch_bool_t autorec);
static int launch_conference_video_bridge_thread(conference_member_t *member_a, conference_member_t *member_b);
typedef switch_status_t (*conf_api_args_cmd_t) (conference_obj_t *, switch_stream_handle_t *, int, char **);
@@ -547,7 +553,6 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem
static switch_status_t conf_api_sub_floor(conference_member_t *member, switch_stream_handle_t *stream, void *data);
static switch_status_t conf_api_sub_vid_floor(conference_member_t *member, switch_stream_handle_t *stream, void *data);
static switch_status_t conf_api_sub_clear_vid_floor(conference_obj_t *conference, switch_stream_handle_t *stream, void *data);
static switch_status_t conf_api_sub_enforce_floor(conference_member_t *member, switch_stream_handle_t *stream, void *data);
#define lock_member(_member) switch_mutex_lock(_member->write_mutex); switch_mutex_lock(_member->read_mutex)
@@ -1217,7 +1222,7 @@ static conference_member_t *conference_member_get(conference_obj_t *conference,
}
/* stop the specified recording */
static switch_status_t conference_record_stop(conference_obj_t *conference, char *path)
static switch_status_t conference_record_stop(conference_obj_t *conference, switch_stream_handle_t *stream, char *path)
{
conference_member_t *member = NULL;
int count = 0;
@@ -1226,10 +1231,21 @@ static switch_status_t conference_record_stop(conference_obj_t *conference, char
switch_mutex_lock(conference->member_mutex);
for (member = conference->members; member; member = member->next) {
if (switch_test_flag(member, MFLAG_NOCHANNEL) && (!path || !strcmp(path, member->rec_path))) {
if (member->rec && member->rec->autorec) {
stream->write_function(stream, "Stopped AUTO recording file %s (Auto Recording Now Disabled)\n", member->rec_path);
conference->auto_record = 0;
} else {
stream->write_function(stream, "Stopped recording file %s\n", member->rec_path);
}
switch_clear_flag_locked(member, MFLAG_RUNNING);
count++;
}
}
conference->record_count -= count;
switch_mutex_unlock(conference->member_mutex);
return count;
}
@@ -2067,7 +2083,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
globals.threads++;
switch_mutex_unlock(globals.hash_mutex);
conference->is_recording = 0;
conference->auto_recording = 0;
conference->record_count = 0;
@@ -2169,15 +2185,15 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
}
/* Start recording if there's more than one participant. */
if (conference->auto_record && !conference->is_recording && conference->count > 1) {
conference->is_recording = 1;
if (conference->auto_record && !conference->auto_recording && conference->count > 1) {
conference->auto_recording++;
conference->record_count++;
imember = conference->members;
if (imember) {
switch_channel_t *channel = switch_core_session_get_channel(imember->session);
char *rfile = switch_channel_expand_variables(channel, conference->auto_record);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto recording file: %s\n", rfile);
launch_conference_record_thread(conference, rfile);
launch_conference_record_thread(conference, rfile, SWITCH_TRUE);
if (rfile != conference->auto_record) {
conference->record_filename = switch_core_strdup(conference->pool, rfile);
switch_safe_free(rfile);
@@ -2607,13 +2623,6 @@ static void conference_loop_fn_vid_floor_force(conference_member_t *member, call
conf_api_sub_vid_floor(member, NULL, "force");
}
static void conference_loop_fn_enforce_floor(conference_member_t *member, caller_control_action_t *action)
{
if (member == NULL) return;
conf_api_sub_enforce_floor(member, NULL, NULL);
}
static void conference_loop_fn_mute_toggle(conference_member_t *member, caller_control_action_t *action)
{
if (member == NULL)
@@ -3185,7 +3194,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
return NULL;
goto end;
}
switch_assert(member != NULL);
@@ -3482,10 +3491,12 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
switch_resample_destroy(&member->read_resampler);
switch_clear_flag_locked(member, MFLAG_ITHREAD);
switch_core_session_rwunlock(session);
end:
switch_clear_flag_locked(member, MFLAG_ITHREAD);
return NULL;
}
@@ -3583,7 +3594,9 @@ static void launch_conference_loop_input(conference_member_t *member, switch_mem
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_set_flag_locked(member, MFLAG_ITHREAD);
switch_thread_create(&member->input_thread, thd_attr, conference_loop_input, member, pool);
if (switch_thread_create(&member->input_thread, thd_attr, conference_loop_input, member, pool) != SWITCH_STATUS_SUCCESS) {
switch_clear_flag_locked(member, MFLAG_ITHREAD);
}
}
/* marshall frames from the conference (or file or tts output) to the call leg */
@@ -3919,6 +3932,7 @@ static void conference_loop_output(conference_member_t *member)
switch_clear_flag_locked(member, MFLAG_RUNNING);
/* Wait for the input thread to end */
if (member->input_thread) {
switch_thread_join(&st, member->input_thread);
}
@@ -3932,11 +3946,6 @@ static void conference_loop_output(conference_member_t *member)
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
member->conference->bridge_hangup_cause = switch_channel_get_cause(channel);
}
/* Wait for the input thread to end */
while (switch_test_flag(member, MFLAG_ITHREAD)) {
switch_cond_next();
}
}
/* Sub-Routine called by a record entity inside a conference */
@@ -3945,7 +3954,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
int16_t *data_buf;
switch_file_handle_t fh = { 0 };
conference_member_t smember = { 0 }, *member;
conference_record_t *rec = (conference_record_t *) obj;
conference_record_t *rp, *last = NULL, *rec = (conference_record_t *) obj;
conference_obj_t *conference = rec->conference;
uint32_t samples = switch_samples_per_packet(conference->rate, conference->interval);
uint32_t mux_used;
@@ -3983,7 +3992,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
fh.samplerate = conference->rate;
member->id = next_member_id();
member->pool = rec->pool;
member->rec = rec;
member->frame_size = SWITCH_RECOMMENDED_BUFFER_SIZE;
member->frame = switch_core_alloc(member->pool, member->frame_size);
member->mux_frame = switch_core_alloc(member->pool, member->frame_size);
@@ -4126,8 +4135,6 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_mutex_unlock(member->audio_out_mutex);
}
conference->is_recording = 0;
switch_safe_free(data_buf);
switch_core_timer_destroy(&timer);
conference_del_member(conference, member);
@@ -4146,6 +4153,23 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_event_fire(&event);
}
if (rec->autorec && conference->auto_recording) {
conference->auto_recording--;
}
switch_mutex_lock(conference->flag_mutex);
for (rp = conference->rec_node_head; rp; rp = rp->next) {
if (rec == rp) {
if (last) {
last->next = rp->next;
} else {
conference->rec_node_head = rp->next;
}
}
}
switch_mutex_unlock(conference->flag_mutex);
if (rec->pool) {
switch_memory_pool_t *pool = rec->pool;
rec = NULL;
@@ -5390,26 +5414,6 @@ static switch_status_t conf_api_sub_vid_floor(conference_member_t *member, switc
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t conf_api_sub_enforce_floor(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
if (member == NULL)
return SWITCH_STATUS_GENERR;
switch_mutex_lock(member->conference->mutex);
if (member->conference->floor_holder != member) {
conference_set_floor_holder(member->conference, member);
if (stream != NULL) {
stream->write_function(stream, "OK floor %u\n", member->id);
}
}
switch_mutex_unlock(member->conference->mutex);
return SWITCH_STATUS_SUCCESS;
}
static switch_xml_t add_x_tag(switch_xml_t x_member, const char *name, const char *value, int off)
{
switch_size_t dlen;
@@ -6278,11 +6282,20 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
static switch_status_t conf_api_sub_check_record(conference_obj_t *conference, switch_stream_handle_t *stream, int arc, char **argv)
{
if (conference->is_recording) {
stream->write_function(stream, "Record file %s\n", conference->record_filename);
} else {
conference_record_t *rec;
int x = 0;
switch_mutex_lock(conference->flag_mutex);
for (rec = conference->rec_node_head; rec; rec = rec->next) {
stream->write_function(stream, "Record file %s%s%s\n", rec->path, rec->autorec ? " " : "", rec->autorec ? "(Auto)" : "");
x++;
}
if (!x) {
stream->write_function(stream, "Conference is not being recorded.\n");
}
switch_mutex_unlock(conference->flag_mutex);
return SWITCH_STATUS_SUCCESS;
}
@@ -6291,19 +6304,20 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_
switch_assert(conference != NULL);
switch_assert(stream != NULL);
if (argc <= 2)
if (argc <= 2) {
return SWITCH_STATUS_GENERR;
}
stream->write_function(stream, "Record file %s\n", argv[2]);
conference->record_filename = switch_core_strdup(conference->pool, argv[2]);
conference->record_count++;
launch_conference_record_thread(conference, argv[2]);
launch_conference_record_thread(conference, argv[2], SWITCH_FALSE);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
{
int all;
int all, before = conference->record_count, ttl = 0;
switch_event_t *event;
switch_assert(conference != NULL);
@@ -6313,15 +6327,10 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc
return SWITCH_STATUS_GENERR;
all = (strcasecmp(argv[2], "all") == 0);
stream->write_function(stream, "Stop recording file %s\n", argv[2]);
if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) {
if (!conference_record_stop(conference, stream, all ? NULL : argv[2]) && !all) {
stream->write_function(stream, "non-existant recording '%s'\n", argv[2]);
} else {
if (all) {
conference->record_count = 0;
} else {
conference->record_count--;
}
if (test_eflag(conference, EFLAG_RECORD) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_data(conference, event);
@@ -6332,6 +6341,9 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc
}
}
ttl = before - conference->record_count;
stream->write_function(stream, "Stopped recording %d file%s\n", ttl, ttl == 1 ? "" : "s");
return SWITCH_STATUS_SUCCESS;
}
@@ -6383,6 +6395,13 @@ static switch_status_t conf_api_sub_recording(conference_obj_t *conference, swit
switch_assert(conference != NULL);
switch_assert(stream != NULL);
if (argc > 2 && argc <= 3) {
if (strcasecmp(argv[2], "stop") == 0 || strcasecmp(argv[2], "check") == 0) {
argv[3] = "all";
argc++;
}
}
if (argc <= 3) {
/* It means that old syntax is used */
return conf_api_sub_record(conference,stream,argc,argv);
@@ -6604,8 +6623,7 @@ static api_command_t conf_api_sub_commands[] = {
{"set", (void_fn_t) & conf_api_sub_set, CONF_API_SUB_ARGS_SPLIT, "set", "<max_members|sound_prefix|caller_id_name|caller_id_number|endconf_grace_time> <value>"},
{"floor", (void_fn_t) & conf_api_sub_floor, CONF_API_SUB_MEMBER_TARGET, "floor", "<member_id|last>"},
{"vid-floor", (void_fn_t) & conf_api_sub_vid_floor, CONF_API_SUB_MEMBER_TARGET, "vid-floor", "<member_id|last> [force]"},
{"clear-vid-floor", (void_fn_t) & conf_api_sub_clear_vid_floor, CONF_API_SUB_ARGS_AS_ONE, "clear-vid-floor", ""},
{"enforce_floor", (void_fn_t) & conf_api_sub_enforce_floor, CONF_API_SUB_MEMBER_TARGET, "enforce_floor", "<member_id|last>"},
{"clear-vid-floor", (void_fn_t) & conf_api_sub_clear_vid_floor, CONF_API_SUB_ARGS_AS_ONE, "clear-vid-floor", ""}
};
#define CONFFUNCAPISIZE (sizeof(conf_api_sub_commands)/sizeof(conf_api_sub_commands[0]))
@@ -8117,9 +8135,7 @@ static int launch_conference_video_bridge_thread(conference_member_t *member_a,
}
static void launch_conference_record_thread(conference_obj_t *conference, char *path)
static void launch_conference_record_thread(conference_obj_t *conference, char *path, switch_bool_t autorec)
{
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
@@ -8138,11 +8154,15 @@ static void launch_conference_record_thread(conference_obj_t *conference, char *
return;
}
conference->is_recording = 1;
rec->conference = conference;
rec->path = switch_core_strdup(pool, path);
rec->pool = pool;
rec->autorec = autorec;
switch_mutex_lock(conference->flag_mutex);
rec->next = conference->rec_node_head;
conference->rec_node_head = rec;
switch_mutex_unlock(conference->flag_mutex);
switch_threadattr_create(&thd_attr, rec->pool);
switch_threadattr_detach_set(thd_attr, 1);
@@ -9189,8 +9209,7 @@ static struct _mapping control_mappings[] = {
{"execute_application", conference_loop_fn_exec_app},
{"floor", conference_loop_fn_floor_toggle},
{"vid-floor", conference_loop_fn_vid_floor_toggle},
{"vid-floor-force", conference_loop_fn_vid_floor_force},
{"enforce_floor", conference_loop_fn_enforce_floor},
{"vid-floor-force", conference_loop_fn_vid_floor_force}
};
#define MAPPING_LEN (sizeof(control_mappings)/sizeof(control_mappings[0]))
+124 -8
View File
@@ -283,10 +283,17 @@ SWITCH_STANDARD_APP(clear_digit_action_function)
{
//switch_channel_t *channel = switch_core_session_get_channel(session);
switch_ivr_dmachine_t *dmachine;
char *realm = switch_core_session_strdup(session, data);
char *realm = NULL;
char *target_str;
switch_digit_action_target_t target = DIGIT_TARGET_SELF;
if (zstr(realm)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "clear_digit_action called with no args");
return;
}
realm = switch_core_session_strdup(session, data);
if ((target_str = strchr(realm, ','))) {
*target_str++ = '\0';
target = str2target(target_str);
@@ -2538,8 +2545,8 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer on failure = [%s].\n", transfer_on_failure);
}
if (min_digits <= 1) {
min_digits = 1;
if (min_digits <= 0) {
min_digits = 0;
}
if (max_digits < min_digits) {
@@ -4509,8 +4516,8 @@ static switch_status_t next_file(switch_file_handle_t *handle)
}
handle->samples = context->fh.samples;
//handle->samplerate = context->fh.samplerate;
//handle->channels = context->fh.channels;
handle->cur_samplerate = context->fh.samplerate;
handle->cur_channels = context->fh.channels;
handle->format = context->fh.format;
handle->sections = context->fh.sections;
handle->seekable = context->fh.seekable;
@@ -4518,6 +4525,7 @@ static switch_status_t next_file(switch_file_handle_t *handle)
handle->interval = context->fh.interval;
handle->max_samples = 0;
if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
switch_set_flag(handle, SWITCH_FILE_NATIVE);
} else {
@@ -4602,13 +4610,19 @@ static switch_status_t file_string_file_read(switch_file_handle_t *handle, void
if ((status = next_file(handle)) != SWITCH_STATUS_SUCCESS) {
return status;
}
*len = llen;
status = switch_core_file_read(&context->fh, data, len);
if (switch_test_flag(handle, SWITCH_FILE_BREAK_ON_CHANGE)) {
*len = 0;
status = SWITCH_STATUS_BREAK;
} else {
*len = llen;
status = switch_core_file_read(&context->fh, data, len);
}
}
return status;
}
static switch_status_t file_string_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{
file_string_context_t *context = handle->private_info;
@@ -4627,10 +4641,101 @@ static switch_status_t file_string_file_write(switch_file_handle_t *handle, void
return status;
}
static switch_status_t file_url_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
{
switch_file_handle_t *fh = handle->private_info;
return switch_core_file_seek(fh, cur_sample, samples, whence);
}
static switch_status_t file_url_file_close(switch_file_handle_t *handle)
{
switch_file_handle_t *fh = handle->private_info;
if (switch_test_flag(fh, SWITCH_FILE_OPEN)) {
switch_core_file_close(fh);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t file_url_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{
switch_file_handle_t *fh = handle->private_info;
return switch_core_file_read(fh, data, len);
}
static switch_status_t file_url_file_open(switch_file_handle_t *handle, const char *path)
{
switch_file_handle_t *fh = switch_core_alloc(handle->memory_pool, sizeof(*fh));
switch_status_t status;
char *url_host;
char *url_path;
if (zstr(path)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NULL path\n");
return SWITCH_STATUS_FALSE;
}
/* parse and check host */
url_host = switch_core_strdup(handle->memory_pool, path);
if (!(url_path = strchr(url_host, '/'))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing path\n");
return SWITCH_STATUS_FALSE;
}
*url_path = '\0';
/* TODO allow this host */
if (!zstr(url_host) && strcasecmp(url_host, "localhost")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not localhost\n");
return SWITCH_STATUS_FALSE;
}
/* decode and check path */
url_path++;
if (zstr(url_path)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "empty path\n");
return SWITCH_STATUS_FALSE;
}
if (strstr(url_path, "%2f") || strstr(url_path, "%2F")) {
/* don't allow %2f or %2F encoding (/) */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "encoded slash is not allowed\n");
return SWITCH_STATUS_FALSE;
}
url_path = switch_core_sprintf(handle->memory_pool, "/%s", url_path);
switch_url_decode(url_path);
/* TODO convert to native file separators? */
handle->private_info = fh;
status = switch_core_file_open(fh, url_path, handle->channels, handle->samplerate, handle->flags, NULL);
if (status == SWITCH_STATUS_SUCCESS) {
handle->samples = fh->samples;
handle->cur_samplerate = fh->samplerate;
handle->cur_channels = fh->channels;
handle->format = fh->format;
handle->sections = fh->sections;
handle->seekable = fh->seekable;
handle->speed = fh->speed;
handle->interval = fh->interval;
handle->max_samples = 0;
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
switch_set_flag(handle, SWITCH_FILE_NATIVE);
} else {
switch_clear_flag(handle, SWITCH_FILE_NATIVE);
}
}
return status;
}
static switch_status_t file_url_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{
switch_file_handle_t *fh = handle->private_info;
return switch_core_file_write(fh, data, len);
}
/* Registration */
static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 };
static char *file_url_supported_formats[SWITCH_MAX_CODECS] = { 0 };
/* /FILE STRING INTERFACE */
@@ -5498,6 +5603,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
file_interface->file_write = file_string_file_write;
file_interface->file_seek = file_string_file_seek;
file_url_supported_formats[0] = "file";
file_interface = (switch_file_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
file_interface->extens = file_url_supported_formats;
file_interface->file_open = file_url_file_open;
file_interface->file_close = file_url_file_close;
file_interface->file_read = file_url_file_read;
file_interface->file_write = file_url_file_write;
file_interface->file_seek = file_url_file_seek;
error_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
error_endpoint_interface->interface_name = "error";
@@ -5652,7 +5768,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "unbind_meta_app", "Unbind a key from an application", "Unbind a key from an application", dtmf_unbind_function,
UNBIND_SYNTAX, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "block_dfmf", "Block DTMF", "Block DTMF", dtmf_block_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "block_dtmf", "Block DTMF", "Block DTMF", dtmf_block_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "unblock_dtmf", "Stop blocking DTMF", "Stop blocking DTMF", dtmf_unblock_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "intercept", "intercept", "intercept", intercept_function, INTERCEPT_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_MEDIA_TAP);
+5 -1
View File
@@ -1366,7 +1366,11 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
if (!switch_event_get_header(ovars, "origination_caller_id_name")) {
if ((caller_id_name = switch_event_get_header(pop, "caller-caller-id-name"))) {
if (!zstr(node->outbound_name)) {
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", "(%s) %s", node->outbound_name, caller_id_name);
if ( node->outbound_name[0] == '=' ) {
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", "%s", node->outbound_name + 1);
} else {
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", "(%s) %s", node->outbound_name, caller_id_name);
}
} else {
switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", caller_id_name);
}
+124 -16
View File
@@ -24,6 +24,7 @@
* Contributor(s):
*
* William King <william.king@quentustech.com>
* Seven Du <dujinfang@gmail.com>
*
* mod_sonar.c -- Sonar ping timer
*
@@ -40,6 +41,14 @@
#include <switch.h>
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
/* Prototypes */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sonar_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_sonar_runtime);
@@ -50,18 +59,38 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sonar_load);
*/
SWITCH_MODULE_DEFINITION(mod_sonar, mod_sonar_load, mod_sonar_shutdown, NULL);
switch_time_t start, end, diff;
struct sonar_ping_helper_s {
switch_time_t start, end, diff;
int samples[1024];
int received;
int sum, min, max;
};
typedef struct sonar_ping_helper_s sonar_ping_helper_t;
switch_bool_t sonar_ping_callback(switch_core_session_t *session, const char *app, const char *app_data){
if ( end ) {
switch_channel_t *channel = switch_core_session_get_channel(session);
sonar_ping_helper_t *ph = switch_channel_get_private(channel, "__sonar_ping__");
int diff;
if (!ph) return SWITCH_TRUE;
if ( ph->end ) {
return SWITCH_TRUE;
}
end = switch_time_now();
diff = end - start;
start = 0;
ph->end = switch_time_now();
diff = ph->end - ph->start;
ph->start = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Sonar ping took %ld milliseconds\n", (long)diff / 1000);
diff /= 1000;
ph->sum += diff;
ph->max = MAX(ph->max, diff);
ph->min = MIN(ph->min, diff);
ph->samples[ph->received++] = diff;
return SWITCH_TRUE;
}
@@ -70,15 +99,31 @@ SWITCH_STANDARD_APP(sonar_app)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
char *tone = "%(500,0,1004)";
int loops = atoi(data);
if ( ! loops ) {
const char *arg = (char *) data;
int loops;
int lost = 0;
int x;
int avg = 0, sdev = 0, mdev = 0;
int sum2;
switch_event_t *event;
sonar_ping_helper_t ph = { 0 };
if (zstr(arg)) {
loops = 5;
} else {
loops = atoi(data);
}
if (loops < 0) {
loops = 5;
} else if (loops > 1024) {
loops = 1024;
}
switch_channel_answer(channel);
switch_ivr_sleep(session, 1000, SWITCH_FALSE, NULL);
switch_channel_set_private(channel, "__sonar_ping__", &ph);
switch_ivr_tone_detect_session(session,
"ping", "1004",
"r", 0,
@@ -86,18 +131,81 @@ SWITCH_STANDARD_APP(sonar_app)
switch_ivr_sleep(session, 1000, SWITCH_FALSE, NULL);
for( int x = 0; x < loops; x++ ) {
end = 0;
start = switch_time_now();
ph.min = 999999;
for( x = 0; x < loops; x++ ) {
ph.end = 0;
ph.start = switch_time_now();
switch_ivr_gentones(session, tone, 1, NULL);
switch_ivr_sleep(session, 2000, SWITCH_FALSE, NULL);
if ( start ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Lost sonar ping\n");
if ( ph.start ) {
lost++;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Lost sonar ping\n");
}
}
switch_ivr_sleep(session, 1000, SWITCH_FALSE, NULL);
switch_ivr_stop_tone_detect_session(session);
if (loops == lost) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too bad, we lost all!\n");
return;
}
if (ph.received + lost != loops) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Race happend %d + %d != %d\n", ph.received, lost, loops);
}
if (ph.received > 0) avg = ph.sum / ph.received;
sum2 = 0;
for(x = 0; x < ph.received; x++) {
sum2 += abs(ph.samples[x] - avg);
}
if (ph.received > 0) {
mdev = sum2 / ph.received;
}
sum2 = 0;
for(x = 0; x < ph.received; x++) {
sum2 += (ph.samples[x] - avg) * (ph.samples[x] - avg);
}
if (ph.received > 1) {
sdev = sqrt(sum2 / (ph.received - 1));
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Sonar Ping (in ms): min:%d max:%d avg:%d sdev:%d mdev:%d sent:%d recv: %d lost:%d lost/send:%2.2f%%\n",
ph.min, ph.max, avg, sdev, mdev, loops, ph.received, lost, lost * 1.0 / loops);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "sonar::ping") == SWITCH_STATUS_SUCCESS) {
const char *verbose_event;
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_min", "%d", ph.min);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_max", "%d", ph.max);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_avg", "%d", avg);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_sdev", "%d", sdev);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_mdev", "%d", mdev);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_sent", "%d", loops);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_recv", "%d", ph.received);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ping_lost", "%d", lost);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lost_rate", "%2.2f%%", lost * 1.0 / loops);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "destination_number",
switch_channel_get_variable(channel, "ping_destination_number"));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sonar_ping_ref",
switch_channel_get_variable(channel, "sonar_ping_ref"));
verbose_event = switch_channel_get_variable(channel, "sonar_channel_event");
if (verbose_event && switch_true(verbose_event)) {
switch_channel_event_set_data(channel, event);
}
switch_event_fire(&event);
}
}
/* Macro expands to: switch_status_t mod_sonar_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
@@ -239,7 +239,6 @@ switch_status_t modem_init(modem_t *modem, modem_control_handler_t control_handl
modem->stty = ttyname(modem->slave);
#else
#ifdef WIN32
modem->slot = 4 + globals.NEXT_ID++; /* need work here we start at COM4 for now*/
snprintf(modem->devlink, sizeof(modem->devlink), "COM%d", modem->slot);
modem->master = CreateFile(modem->devlink,
@@ -884,6 +883,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
if (outbound_profile) {
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
caller_profile->source = switch_core_strdup(caller_profile->pool, "mod_spandsp");
caller_profile->destination_number = switch_core_strdup(caller_profile->pool, number);
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
} else {
@@ -3078,16 +3078,24 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
vm_cc_num = switch_separate_string(vm_cc_dup, ',', vm_cc_list, (sizeof(vm_cc_list) / sizeof(vm_cc_list[0])));
for (vm_cc_i=0; vm_cc_i<vm_cc_num; vm_cc_i++) {
char *cmd, *val;
const char *vm_cc_current = vm_cc_list[vm_cc_i];
char *cmd = switch_core_session_sprintf(session, "%s %s %s '%s' %s@%s %s",
vm_cc_current, file_path, caller_id_number,
caller_id_name, myid, domain_name, read_flags);
val = strdup(caller_id_name);
switch_url_decode(val);
cmd = switch_mprintf("%s %s %s '%s' %s@%s %s",
vm_cc_current, file_path, caller_id_number,
val, myid, domain_name, read_flags);
free(val);
if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Sent Carbon Copy to %s\n", vm_cc_current);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to Carbon Copy to %s\n", vm_cc_current);
}
switch_safe_free(cmd);
}
switch_safe_free(vm_cc_dup);
+5 -5
View File
@@ -15,11 +15,11 @@ install: $(LICSERVER) $(VALIDATOR) $(MOD)
$(LICSERVER) $(VALIDATOR) $(MOD): $(G729INSTALLER)
$(SHELL) $(G729INSTALLER) $(bindir) $(moddir) nobanner
$(ECHO)
$(ECHO)
$(ECHO) Now you can activate your license by running $(MAKE) mod_com_g729-activate
$(ECHO)
$(ECHO)
@echo
@echo
@echo Now you can activate your license by running $(MAKE) mod_com_g729-activate
@echo
@echo
$(G729INSTALLER):
rm -f $(top_srcdir)/libs/fsg729-*-installer*
+1 -1
View File
@@ -1,6 +1,6 @@
BASE=../../../..
OPUS=opus-1.0.2
OPUS=opus-1.0.3
OPUS_DIR=$(switch_srcdir)/libs/$(OPUS)
OPUS_BUILDDIR=$(switch_builddir)/libs/$(OPUS)
@@ -15,6 +15,11 @@
<param name="ext-voicemail" value="vmain"/>
<param name="ext-redial" value="redial"/>
<!-- <param name="ext-meetme" value="conference"/> -->
<!-- usually place this one on the directory entry for a skinny phone and not global -->
<!-- <param name="ext-pickup" value="pickup"/> -->
<!-- <param name="ext-cfwdall" value="cfwdall"/> -->
</settings>
<soft-key-set-sets>
<soft-key-set-set name="default">
@@ -173,6 +173,7 @@ switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stre
stream->write_function(stream, "Ext-Redial \t%s\n", profile->ext_redial);
stream->write_function(stream, "Ext-MeetMe \t%s\n", profile->ext_meetme);
stream->write_function(stream, "Ext-PickUp \t%s\n", profile->ext_pickup);
stream->write_function(stream, "Ext-CFwdAll \t%s\n", profile->ext_cfwdall);
stream->write_function(stream, "%s\n", line);
return SWITCH_STATUS_SUCCESS;
@@ -1939,6 +1940,10 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
if (!profile->ext_pickup || strcmp(val, profile->ext_pickup)) {
profile->ext_pickup = switch_core_strdup(profile->pool, val);
}
} else if (!strcasecmp(var, "ext-cfwdall")) {
if (!profile->ext_cfwdall || strcmp(val, profile->ext_cfwdall)) {
profile->ext_cfwdall = switch_core_strdup(profile->pool, val);
}
} else {
return SWITCH_STATUS_FALSE;
}
@@ -2039,6 +2044,10 @@ static switch_status_t load_skinny_config(void)
skinny_profile_set(profile, "ext-pickup", "pickup");
}
if (!profile->ext_cfwdall) {
skinny_profile_set(profile, "ext-pickup", "cfwdall");
}
if (profile->port == 0) {
profile->port = 2000;
}
@@ -59,6 +59,11 @@
"[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \
listener->remote_port, __VA_ARGS__)
#define skinny_log_l_ffl_msg(listener, file, func, line, level, _fmt) switch_log_printf( \
SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, level, \
"[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \
listener->remote_port)
#define skinny_log_ls(listener, session, level, _fmt, ...) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, \
"[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \
listener->remote_port, __VA_ARGS__)
@@ -125,6 +130,7 @@ struct skinny_profile {
char *ext_redial;
char *ext_meetme;
char *ext_pickup;
char *ext_cfwdall;
/* db */
char *dbname;
char *odbc_dsn;
@@ -194,6 +200,7 @@ struct listener {
char *ext_redial;
char *ext_meetme;
char *ext_pickup;
char *ext_cfwdall;
};
typedef struct listener listener_t;
+64
View File
@@ -235,6 +235,7 @@ static switch_status_t skinny_api_list_settings(const char *line, const char *cu
switch_console_push_match(&my_matches, "ext-redial");
switch_console_push_match(&my_matches, "ext-meetme");
switch_console_push_match(&my_matches, "ext-pickup");
switch_console_push_match(&my_matches, "ext-cfwdall");
if (my_matches) {
*matches = my_matches;
@@ -384,6 +385,50 @@ static switch_status_t skinny_api_cmd_profile_device_send_call_state_message(con
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_forward_stat_message(const char *profile_name, const char *device_name, const char *number, switch_stream_handle_t *stream)
{
skinny_profile_t *profile;
if ((profile = skinny_find_profile(profile_name))) {
listener_t *listener = NULL;
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
send_forward_stat(listener, number);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
} else {
stream->write_function(stream, "Profile not found!\n");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_display_prompt_status_message(const char *profile_name, const char *device_name, const char *display, switch_stream_handle_t *stream)
{
skinny_profile_t *profile;
if ((profile = skinny_find_profile(profile_name))) {
listener_t *listener = NULL;
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
send_display_prompt_status(listener, 0, display, 0, 0);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
} else {
stream->write_function(stream, "Profile not found!\n");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const char *profile_name, const char *device_name, const char *reset_type, switch_stream_handle_t *stream)
{
skinny_profile_t *profile;
@@ -497,6 +542,8 @@ SWITCH_STANDARD_API(skinny_function)
"skinny profile <profile_name> device <device_name> send SetLampMessage <stimulus> <instance> <lamp_mode>\n"
"skinny profile <profile_name> device <device_name> send SetSpeakerModeMessage <speaker_mode>\n"
"skinny profile <profile_name> device <device_name> send CallStateMessage <call_state> <line_instance> <call_id>\n"
"skinny profile <profile_name> device <device_name> send ForwardStatMessage <number>\n"
"skinny profile <profile_name> device <device_name> send DisplayPromptStatus <message>\n"
"skinny profile <profile_name> device <device_name> send <UserToDeviceDataMessage|UserToDeviceDataVersion1Message> [ <param>=<value>;... ] <data>\n"
"skinny profile <profile_name> set <name> <value>\n"
"--------------------------------------------------------------------------------\n";
@@ -560,6 +607,21 @@ SWITCH_STANDARD_API(skinny_function)
status = skinny_api_cmd_profile_device_send_call_state_message(argv[1], argv[3], argv[6], argv[7], argv[8], stream);
}
break;
case FORWARD_STAT_MESSAGE:
if (argc == 7) {
/* ForwardStatMessage <number> */
status = skinny_api_cmd_profile_device_send_forward_stat_message(argv[1], argv[3], argv[6], stream);
} else if (argc == 6) {
/* ForwardStatMessage */
status = skinny_api_cmd_profile_device_send_forward_stat_message(argv[1], argv[3], NULL, stream);
}
break;
case DISPLAY_PROMPT_STATUS_MESSAGE:
if (argc == 7) {
/* DisplayPromptStatus <display> */
status = skinny_api_cmd_profile_device_send_display_prompt_status_message(argv[1], argv[3], argv[6], stream);
}
break;
case RESET_MESSAGE:
if (argc == 7) {
/* ResetMessage <reset_type> */
@@ -610,6 +672,8 @@ switch_status_t skinny_api_register(switch_loadable_module_interface_t **module_
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetLampMessage ::skinny::list_stimuli ::skinny::list_stimulus_instances ::skinny::list_stimulus_modes");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetSpeakerModeMessage ::skinny::list_speaker_modes");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send CallStateMessage ::skinny::list_call_states ::skinny::list_line_instances ::skinny::list_call_ids");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send ForwardStatMessage");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send DisplayPromptStatusMessage");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataMessage");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataVersion1Message");
switch_console_set_complete("add skinny profile ::skinny::list_profiles set ::skinny::list_settings");
@@ -592,6 +592,38 @@ switch_status_t perform_send_set_ringer(listener_t *listener,
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
}
switch_status_t perform_send_forward_stat(listener_t *listener,
const char *file, const char *func, int line,
const char *number)
{
skinny_message_t *message;
skinny_create_message(message, FORWARD_STAT_MESSAGE, forward_stat);
if ( number && number[0] )
{
message->data.forward_stat.active_forward = 1;
message->data.forward_stat.line_instance = 1;
message->data.forward_stat.forward_all_active = 1;
message->data.forward_stat.forward_busy_active = 1;
message->data.forward_stat.forward_noanswer_active = 1;
strncpy(message->data.forward_stat.forward_all_number, number, sizeof(message->data.forward_stat.forward_all_number));
strncpy(message->data.forward_stat.forward_busy_number, number, sizeof(message->data.forward_stat.forward_all_number));
strncpy(message->data.forward_stat.forward_noanswer_number, number, sizeof(message->data.forward_stat.forward_all_number));
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
"Sending ForwardStat with Number (%s)\n", number);
}
else
{
skinny_log_l_ffl_msg(listener, file, func, line, SWITCH_LOG_DEBUG,
"Sending ForwardStat with No Number (Inactive)\n");
}
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
}
switch_status_t perform_send_set_lamp(listener_t *listener,
const char *file, const char *func, int line,
uint32_t stimulus,
@@ -1019,6 +1019,11 @@ switch_status_t perform_send_set_ringer(listener_t *listener,
uint32_t call_id);
#define send_set_ringer(listener, ...) perform_send_set_ringer(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
switch_status_t perform_send_forward_stat(listener_t *listener,
const char *file, const char *func, int line,
const char *forward_to);
#define send_forward_stat(listener, ...) perform_send_forward_stat(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
switch_status_t perform_send_set_lamp(listener_t *listener,
const char *file, const char *func, int line,
uint32_t stimulus,
+11 -3
View File
@@ -592,7 +592,6 @@ int skinny_ring_lines_callback(void *pArg, int argc, char **argv, char **columnN
device_name, device_instance, &listener);
if(listener && helper->tech_pvt->session && helper->remote_session) {
switch_channel_t *channel = switch_core_session_get_channel(helper->tech_pvt->session);
switch_channel_t *remchannel = switch_core_session_get_channel(helper->remote_session);
switch_channel_set_state(channel, CS_ROUTING);
helper->lines_count++;
switch_channel_set_variable(channel, "effective_callee_id_number", value);
@@ -632,7 +631,7 @@ int skinny_ring_lines_callback(void *pArg, int argc, char **argv, char **columnN
skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_BLINK);
send_set_ringer(listener, SKINNY_RING_INSIDE, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id);
switch_channel_ring_ready(remchannel);
switch_channel_ring_ready(channel);
}
return 0;
}
@@ -1097,6 +1096,10 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
if (!listener->ext_pickup || strcmp(value,listener->ext_pickup)) {
listener->ext_pickup = switch_core_strdup(profile->pool, value);
}
} else if (!strcasecmp(name, "ext-cfwdall")) {
if (!listener->ext_cfwdall || strcmp(value,listener->ext_cfwdall)) {
listener->ext_cfwdall = switch_core_strdup(profile->pool, value);
}
}
}
}
@@ -1256,7 +1259,7 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny
digit = '*';
} else if (request->data.keypad_button.button == 15) {
digit = '#';
} else if (request->data.keypad_button.button >= 0 && request->data.keypad_button.button <= 9) {
} else if (request->data.keypad_button.button <= 9) { /* unsigned, so guaranteed to be >= 0 */
digit = '0' + request->data.keypad_button.button;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "UNKNOW DTMF RECEIVED ON CALL %d [%d]\n", tech_pvt->call_id, request->data.keypad_button.button);
@@ -2001,6 +2004,11 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
skinny_session_process_dest(session, listener, line_instance,
empty_null2(listener->ext_pickup, listener->profile->ext_pickup), '\0', 0);
break;
case SOFTKEY_CFWDALL:
skinny_create_incoming_session(listener, &line_instance, &session);
skinny_session_process_dest(session, listener, line_instance,
empty_null2(listener->ext_cfwdall, listener->profile->ext_cfwdall), '\0', 0);
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknown SoftKeyEvent type: %d.\n", request->data.soft_key_event.event);
@@ -212,6 +212,7 @@ SKINNY_DECLARE_STR2ID(skinny_str2ring_mode, SKINNY_RING_MODES, -1)
{SKINNY_BUTTON_LAST_NUMBER_REDIAL, "LastNumberRedial"},
{SKINNY_BUTTON_SPEED_DIAL, "SpeedDial"},
{SKINNY_BUTTON_HOLD, "Hold"},
{SKINNY_BUTTON_FORWARDALL, "ForwardAll"},
{SKINNY_BUTTON_TRANSFER, "Transfer"},
{SKINNY_BUTTON_LINE, "Line"},
{SKINNY_BUTTON_VOICEMAIL, "Voicemail"},
+2 -1
View File
@@ -165,13 +165,14 @@ enum skinny_button_definition {
SKINNY_BUTTON_SPEED_DIAL = 0x02,
SKINNY_BUTTON_HOLD = 0x03,
SKINNY_BUTTON_TRANSFER = 0x04,
SKINNY_BUTTON_FORWARDALL = 0x05,
SKINNY_BUTTON_LINE = 0x09,
SKINNY_BUTTON_VOICEMAIL = 0x0F,
SKINNY_BUTTON_PRIVACY = 0x13,
SKINNY_BUTTON_SERVICE_URL = 0x14,
SKINNY_BUTTON_UNDEFINED = 0xFF,
};
extern struct skinny_table SKINNY_BUTTONS[11];
extern struct skinny_table SKINNY_BUTTONS[12];
const char *skinny_button2str(uint32_t id);
uint32_t skinny_str2button(const char *str);
#define SKINNY_PUSH_STIMULI SKINNY_DECLARE_PUSH_MATCH(SKINNY_BUTTONS)
@@ -64,6 +64,10 @@
<!-- <domain name="$${domain}" parse="true"/> -->
<!-- indicator to parse the directory for domains with parse="true" to
get gateways and alias every domain to this profile -->
<!-- This may seem like just a configuration convenience, but
aliasing has real effects on the handling of packets. If
you're sharing a profile between multiple realms, you
want to alias all realms to the shared profile. -->
<!-- <domain name="all" alias="true" parse="true"/> -->
<domain name="all" alias="true" parse="false"/>
</domains>
+174 -151
View File
@@ -1,4 +1,4 @@
/*
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
@@ -22,7 +22,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Anthony Minessale II <anthm@freeswitch.org>
* Ken Rice <krice at cometsig.com>
* Paul D. Tinsley <pdt at jackhammer.org>
@@ -65,8 +65,8 @@ static switch_status_t sofia_kill_channel(switch_core_session_t *session, int si
/* BODY OF THE MODULE */
/*************************************************************************************************************************************************************/
/*
State methods they get called when the state changes to the specific state
/*
State methods they get called when the state changes to the specific state
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
*/
@@ -375,7 +375,7 @@ switch_status_t sofia_on_destroy(switch_core_session_t *session)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA DESTROY\n", switch_channel_get_name(channel));
if (tech_pvt) {
if (tech_pvt->respond_phrase) {
switch_yield(100000);
}
@@ -402,7 +402,7 @@ switch_status_t sofia_on_destroy(switch_core_session_t *session)
sofia_profile_destroy(tech_pvt->profile);
}
}
return SWITCH_STATUS_SUCCESS;
}
@@ -552,18 +552,18 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
case 401:
case 407:
{
const char *to_host = switch_channel_get_variable(channel, "sip_challenge_realm");
const char *to_host = switch_channel_get_variable(channel, "sip_challenge_realm");
if (zstr(to_host)) {
to_host = switch_channel_get_variable(channel, "sip_to_host");
to_host = switch_channel_get_variable(channel, "sip_to_host");
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Challenging call\n");
sofia_reg_auth_challenge(tech_pvt->profile, tech_pvt->nh, NULL, REG_INVITE, to_host, 0, 0);
sofia_reg_auth_challenge(tech_pvt->profile, tech_pvt->nh, NULL, REG_INVITE, to_host, 0, 0);
*reason = '\0';
}
break;
case 484:
{
const char *to = switch_channel_get_variable(channel, "sip_to_uri");
@@ -575,13 +575,13 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
if ((p = strstr(to_uri, ":5060"))) {
*p = '\0';
}
tech_pvt->respond_dest = to_uri;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Overlap Dial with %d %s\n", sip_cause, phrase);
}
break;
@@ -590,7 +590,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
}
}
if (tech_pvt->respond_dest && !sofia_test_pflag(tech_pvt->profile, PFLAG_MANUAL_REDIRECT)) {
added_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX);
}
@@ -611,12 +611,12 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
nua_respond(tech_pvt->nh, sip_cause, phrase,
TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
TAG_IF(!zstr(resp_headers), SIPTAG_HEADER_STR(resp_headers)),
TAG_IF(!zstr(added_headers), SIPTAG_HEADER_STR(added_headers)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
TAG_IF(!zstr(resp_headers), SIPTAG_HEADER_STR(resp_headers)),
TAG_IF(!zstr(added_headers), SIPTAG_HEADER_STR(added_headers)),
TAG_IF(tech_pvt->respond_dest, SIPTAG_CONTACT_STR(tech_pvt->respond_dest)),
TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)),
TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)),
TAG_END());
switch_safe_free(resp_headers);
@@ -663,7 +663,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
int is_3pcc = 0;
char *sticky = NULL;
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if (switch_channel_test_flag(channel, CF_CONFERENCE)) {
tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;isfocus", tech_pvt->reply_contact);
}
@@ -671,7 +671,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
//switch_core_media_set_local_sdp
if(sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE)) {
// SNARK: complete hack to get final ack sent when a 3pcc invite has been passed from the other leg in bypass_media mode.
// This code handles the pass_indication sent after the 3pcc ack is received by the other leg in the is_3pcc && is_proxy case below.
// This code handles the pass_indication sent after the 3pcc ack is received by the other leg in the is_3pcc && is_proxy case below.
// Is there a better place to hang this...?
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
@@ -818,7 +818,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
if (tech_pvt->nh) {
if (tech_pvt->mparams.local_sdp_str) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local SDP %s:\n%s\n", switch_channel_get_name(channel),
@@ -853,14 +853,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && tech_pvt->mparams.early_sdp) {
char *a, *b;
/* start at the s= line to avoid some devices who update the o= between messages */
a = strstr(tech_pvt->mparams.early_sdp, "s=");
b = strstr(tech_pvt->mparams.local_sdp_str, "s=");
if (!a || !b || strcmp(a, b)) {
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
we do so in this case we will abandon the SOA rules and go rogue.
*/
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
@@ -873,7 +873,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
tech_pvt->session_refresher = nua_no_refresher;
}
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
@@ -928,7 +928,7 @@ static switch_status_t sofia_read_video_frame(switch_core_session_t *session, sw
#if 0
while (!(tech_pvt->video_read_codec.implementation && switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) {
switch_ivr_parse_all_messages(tech_pvt->session);
if (--sanity && switch_channel_ready(channel)) {
switch_yield(10000);
} else {
@@ -1110,7 +1110,7 @@ static switch_status_t sofia_send_dtmf(switch_core_session_t *session, const swi
dtmf_type = tech_pvt->mparams.dtmf_type;
/* We only can send INFO when we have no media */
if (!switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) ||
if (!switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) ||
!switch_channel_media_ready(tech_pvt->channel) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
dtmf_type = DTMF_INFO;
}
@@ -1187,7 +1187,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
break;
case SWITCH_MESSAGE_INDICATE_BRIDGE:
switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, NULL);
if (switch_true(switch_channel_get_variable(channel, "sip_auto_simplify"))) {
sofia_set_flag(tech_pvt, TFLAG_SIMPLIFY);
}
@@ -1269,8 +1269,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
if (((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) ||
(var = switch_channel_get_variable(channel, "rtp_secure_media"))) &&
if (((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) ||
(var = switch_channel_get_variable(channel, "rtp_secure_media"))) &&
(switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_80))) {
switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
}
@@ -1306,10 +1306,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (!zstr(msg->string_arg)) {
pl = msg->string_arg;
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/media_control+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
}
}
break;
case SWITCH_MESSAGE_INDICATE_BROADCAST:
@@ -1353,9 +1353,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if(zstr(tech_pvt->mparams.local_sdp_str)) {
sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE);
}
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
@@ -1416,7 +1416,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_set_variable(channel, "sip_require_timer", "false");
sofia_glue_do_invite(session);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Request to send IMAGE on channel with not t38 options.\n",
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Request to send IMAGE on channel with not t38 options.\n",
switch_channel_get_name(channel));
}
}
@@ -1477,9 +1477,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
if (!switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
"Operation not permitted on an inbound non-answered call leg!\n");
} else {
} else {
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_SUBSCRIPTION_STATE_STR("active"),
SIPTAG_EVENT_STR(event), TAG_END());
}
@@ -1546,23 +1546,23 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
"fs_send_unspported_info is deprecated in favor of correctly spelled fs_send_unsupported_info\n");
ok = 1;
}
if (switch_true(switch_channel_get_variable(channel, "fs_send_unsupported_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(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl)),
TAG_END());
@@ -1621,21 +1621,29 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
break;
case SWITCH_MESSAGE_INDICATE_DISPLAY:
{
const char *name = msg->string_array_arg[0], *number = msg->string_array_arg[1];
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
const char *name = NULL, *number = NULL;
const char *call_info = NULL;
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SEND_DISPLAY_UPDATE)) {
goto end_lock;
}
name = msg->string_array_arg[0];
number = msg->string_array_arg[1];
call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if (!zstr(name)) {
char message[256] = "";
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;
}
switch_ivr_eavesdrop_update_display(session, name, number);
if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY) && switch_channel_test_flag(channel, CF_ANSWERED)) {
@@ -1660,7 +1668,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
} else if (ua && switch_stristr("snom", ua)) {
const char *ver_str = NULL;
const char *ver_str = NULL;
int version = 0;
ver_str = switch_stristr( "/", ua);
@@ -1744,7 +1752,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_partner_uuid(channel);
@@ -1784,7 +1792,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (!zstr(msg->string_arg)) {
char message[256] = "";
const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
if (ua && switch_stristr("snom", ua)) {
snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", msg->string_arg, tech_pvt->caller_profile->destination_number);
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
@@ -1853,9 +1861,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Redirecting to %s\n", dest);
tech_pvt->respond_dest = dest;
if (argc > 1) {
tech_pvt->respond_code = 300;
tech_pvt->respond_phrase = "Multiple Choices";
@@ -1997,7 +2005,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
/* Regain lock on sofia */
switch_mutex_lock(tech_pvt->sofia_mutex);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
sofia_clear_flag(tech_pvt, TFLAG_3PCC);
sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
@@ -2102,7 +2110,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
}
} else {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) ||
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) ||
switch_core_media_codec_chosen(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) != SWITCH_STATUS_SUCCESS) {
sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION);
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
@@ -2150,11 +2158,11 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
char *cid = NULL;
cid = generate_pai_str(tech_pvt);
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
tech_pvt->mparams.early_sdp && strcmp(tech_pvt->mparams.early_sdp, tech_pvt->mparams.local_sdp_str)) {
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
we do so in this case we will abandon the SOA rules and go rogue.
*/
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
@@ -2202,7 +2210,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
case SWITCH_MESSAGE_INDICATE_UDPTL_MODE:
{
switch_t38_options_t *t38_options = switch_channel_get_private(channel, "t38_options");
if (!t38_options) {
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
}
@@ -3082,7 +3090,7 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
goto done;
}
if (!strcasecmp(argv[1], "recover")) {
if (argv[2] && !strcasecmp(argv[2], "flush")) {
sofia_glue_profile_recover(profile, SWITCH_TRUE);
@@ -3199,16 +3207,16 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
goto done;
}
if (!strcasecmp(argv[1], "capture")) {
if (argc > 2) {
int value = switch_true(argv[2]);
nua_set_params(profile->nua, TPTAG_CAPT(value ? mod_sofia_globals.capture_server : NULL), TAG_END());
stream->write_function(stream, "%s sip capturing on %s", value ? "Enabled" : "Disabled", profile->name);
} else {
stream->write_function(stream, "Usage: sofia profile <name> capture <on/off>\n");
}
goto done;
}
if (!strcasecmp(argv[1], "capture")) {
if (argc > 2) {
int value = switch_true(argv[2]);
nua_set_params(profile->nua, TPTAG_CAPT(value ? mod_sofia_globals.capture_server : NULL), TAG_END());
stream->write_function(stream, "%s sip capturing on %s", value ? "Enabled" : "Disabled", profile->name);
} else {
stream->write_function(stream, "Usage: sofia profile <name> capture <on/off>\n");
}
goto done;
}
if (!strcasecmp(argv[1], "watchdog")) {
if (argc > 2) {
@@ -3224,7 +3232,7 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
if (!strcasecmp(argv[1], "gwlist")) {
int up = 1;
if (argc > 2) {
if (!strcasecmp(argv[2], "down")) {
up = 0;
@@ -3250,13 +3258,13 @@ static int contact_callback(void *pArg, int argc, char **argv, char **columnName
{
struct cb_helper *cb = (struct cb_helper *) pArg;
char *contact;
cb->row_process++;
if (!zstr(argv[0]) && (contact = sofia_glue_get_url_from_contact(argv[0], 1))) {
if (cb->dedup) {
char *tmp = switch_mprintf("%ssofia/%s/sip:%s", argv[2], argv[1], sofia_glue_strip_proto(contact));
if (!strstr((char *)cb->stream->data, tmp)) {
cb->stream->write_function(cb->stream, "%s,", tmp);
}
@@ -3463,17 +3471,17 @@ SWITCH_STANDARD_API(sofia_username_of_function)
return SWITCH_STATUS_SUCCESS;
}
static void select_from_profile(sofia_profile_t *profile,
static void select_from_profile(sofia_profile_t *profile,
const char *user,
const char *domain,
const char *concat,
const char *exclude_contact,
const char *exclude_contact,
switch_stream_handle_t *stream,
switch_bool_t dedup)
{
struct cb_helper cb;
char *sql;
cb.row_process = 0;
cb.profile = profile;
@@ -3552,7 +3560,7 @@ SWITCH_STANDARD_API(sofia_contact_function)
if (!zstr(profile_name)) {
profile = sofia_glue_find_profile(profile_name);
}
if (!profile && !zstr(domain)) {
profile = sofia_glue_find_profile(domain);
}
@@ -3571,32 +3579,32 @@ SWITCH_STANDARD_API(sofia_contact_function)
if (!zstr(profile->domain_name) && !zstr(profile_name) && !strcmp(profile_name, profile->name)) {
domain = profile->domain_name;
}
select_from_profile(profile, user, domain, concat, exclude_contact, &mystream, SWITCH_FALSE);
sofia_glue_release_profile(profile);
} else if (!zstr(domain)) {
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
switch_hash_index_t *hi;
const void *var;
void *val;
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 ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) {
select_from_profile(profile, user, domain, concat, exclude_contact, &mystream, SWITCH_TRUE);
select_from_profile(profile, user, domain, concat, exclude_contact, &mystream, SWITCH_TRUE);
profile = NULL;
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
}
reply = (char *) mystream.data;
end:
if (zstr(reply)) {
reply = "error/user_not_registered";
} else if (end_of(reply) == ',') {
@@ -3606,7 +3614,7 @@ SWITCH_STANDARD_API(sofia_contact_function)
stream->write_function(stream, "%s", reply);
reply = NULL;
switch_safe_free(mystream.data);
switch_safe_free(mystream.data);
switch_safe_free(data);
switch_safe_free(dup_domain);
@@ -3933,12 +3941,12 @@ SWITCH_STANDARD_API(sofia_function)
mod_sofia_globals.debug_presence = 10;
stream->write_function(stream, "+OK Debugging presence\n");
}
if (strstr(argv[2], "sla")) {
mod_sofia_globals.debug_sla = 10;
stream->write_function(stream, "+OK Debugging sla\n");
}
if (strstr(argv[2], "none")) {
stream->write_function(stream, "+OK Debugging nothing\n");
mod_sofia_globals.debug_presence = 0;
@@ -3946,13 +3954,13 @@ SWITCH_STANDARD_API(sofia_function)
}
}
stream->write_function(stream, "+OK Debugging summary: presence: %s sla: %s\n",
stream->write_function(stream, "+OK Debugging summary: presence: %s sla: %s\n",
mod_sofia_globals.debug_presence ? "on" : "off",
mod_sofia_globals.debug_sla ? "on" : "off");
goto done;
}
if (!strcasecmp(argv[1], "siptrace")) {
if (argc > 2) {
ston = switch_true(argv[2]);
@@ -3966,10 +3974,10 @@ SWITCH_STANDARD_API(sofia_function)
}
if (!strcasecmp(argv[1], "capture")) {
if (argc > 2) {
cton = switch_true(argv[2]);
}
}
if (argc > 2) {
cton = switch_true(argv[2]);
}
}
if (!strcasecmp(argv[1], "watchdog")) {
if (argc > 2) {
@@ -3993,7 +4001,7 @@ SWITCH_STANDARD_API(sofia_function)
} else {
stream->write_function(stream, "-ERR Usage: siptrace <on|off>|capture <on|off>|watchdog <on|off>|debug <sla|presence|none");
}
goto done;
} else if (!strcasecmp(argv[0], "recover")) {
@@ -4097,7 +4105,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
goto error;
}
if (!(nsession = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND,
if (!(nsession = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND,
flags, pool, switch_event_get_header(var_event, "origination_uuid")))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n");
goto error;
@@ -4194,7 +4202,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
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);
@@ -4217,7 +4225,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
dest_to = NULL;
}
}
if (params) {
tech_pvt->invite_contact = switch_core_session_sprintf(nsession, "%s;%s", gateway_ptr->register_contact, params);
tech_pvt->dest = switch_core_session_sprintf(nsession, "%s;%s", tech_pvt->dest, params);
@@ -4228,10 +4236,10 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
gateway_ptr->ob_calls++;
if (!zstr(gateway_ptr->from_domain) && !switch_channel_get_variable(nchannel, "sip_invite_domain")) {
if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-full")) {
const char *sip_full_from = switch_channel_get_variable(o_channel, "sip_full_from");
if (!zstr(sip_full_from)) {
switch_channel_set_variable(nchannel, "sip_force_full_from", sip_full_from);
}
@@ -4309,7 +4317,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
}
} else {
host++;
if (!strchr(host, '.') || switch_true(switch_event_get_header(var_event, "sip_gethostbyname"))) {
struct sockaddr_in sa;
struct hostent *he = gethostbyname(host);
@@ -4318,7 +4326,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (he) {
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
ip = inet_ntoa(sa.sin_addr);
tmp = switch_string_replace(dest, host, ip);
//host = switch_core_session_strdup(nsession, ip);
//dest = switch_core_session_strdup(nsession, tmp);
@@ -4339,7 +4347,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (switch_stristr("fs_path", tech_pvt->dest)) {
char *remote_host = NULL;
const char *s;
if ((s = switch_stristr("fs_path=", tech_pvt->dest))) {
s += 8;
}
@@ -4351,7 +4359,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (!zstr(remote_host)) {
switch_split_user_domain(remote_host, NULL, &tech_pvt->mparams.remote_ip);
}
}
}
if (zstr(tech_pvt->mparams.remote_ip)) {
switch_split_user_domain(switch_core_session_strdup(nsession, tech_pvt->dest), NULL, &tech_pvt->mparams.remote_ip);
@@ -4373,7 +4381,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
switch_channel_set_variable(nchannel, "rtp_secure_media", SWITCH_RTP_CRYPTO_KEY_80);
}
if ((hval = switch_event_get_header(var_event, SOFIA_SECURE_MEDIA_VARIABLE)) ||
if ((hval = switch_event_get_header(var_event, SOFIA_SECURE_MEDIA_VARIABLE)) ||
(hval = switch_event_get_header(var_event, "rtp_secure_media"))) {
switch_channel_set_variable(nchannel, "rtp_secure_media", hval);
@@ -4384,7 +4392,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
switch_channel_set_variable(nchannel, "media_webrtc", "true");
switch_core_session_set_ice(nsession);
}
sofia_glue_attach_private(nsession, profile, tech_pvt, dest);
@@ -4518,7 +4526,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
}
if (switch_core_session_compare(session, nsession)) {
/* It's another sofia channel! so lets cache what they use as a pt for telephone event so
/* It's another sofia channel! so lets cache what they use as a pt for telephone event so
we can keep it the same
*/
private_object_t *ctech_pvt;
@@ -4680,19 +4688,19 @@ static int notify_callback(void *pArg, int argc, char **argv, char **columnNames
dst = sofia_glue_get_destination((char *) contact);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
nh = nua_handle(profile->nua, NULL, NUTAG_URL(dst->contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(profile->url), TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_notify(nh, NUTAG_NEWSUB(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
SIPTAG_EVENT_STR(es), SIPTAG_CONTENT_TYPE_STR(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_END());
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
@@ -4809,32 +4817,32 @@ static void general_event_handler(switch_event_t *event)
char *route_uri = NULL;
dst = sofia_glue_get_destination((char *) to_uri);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
nh = nua_handle(profile->nua,
NULL,
NUTAG_URL(to_uri),
NUTAG_URL(to_uri),
SIPTAG_FROM_STR(from_uri),
SIPTAG_TO_STR(to_uri),
SIPTAG_CONTACT_STR(profile->url),
TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_notify(nh,
NUTAG_NEWSUB(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
SIPTAG_EVENT_STR(es), TAG_IF(ct, SIPTAG_CONTENT_TYPE_STR(ct)), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END());
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
sofia_glue_release_profile(profile);
}
@@ -4891,7 +4899,7 @@ static void general_event_handler(switch_event_t *event)
const char *user = switch_event_get_header(event, "user");
const char *host = switch_event_get_header(event, "host");
const char *call_id = switch_event_get_header(event, "call-id");
const char *csta_event = switch_event_get_header(event, "csta-event");
const char *csta_event = switch_event_get_header(event, "Feature-Event");
char *ct = "application/x-as-feature-event+xml";
@@ -4948,8 +4956,19 @@ static void general_event_handler(switch_event_t *event)
ct = switch_mprintf("multipart/mixed; boundary=\"%s\"", boundary_string);
} else {
char *fwd_type = NULL;
char *header_name = NULL;
if ((header_name = switch_event_get_header(event, "forward_immediate"))) {
fwd_type = "forwardImmediate";
} else if ((header_name = switch_event_get_header(event, "forward_busy"))) {
fwd_type = "forwardBusy";
} else if ((header_name = switch_event_get_header(event, "forward_no_answer"))) {
fwd_type = "forwardNoAns";
}
// this will need some work to handle the different types of forwarding events
write_csta_xml_chunk(event, stream, csta_event, NULL);
write_csta_xml_chunk(event, stream, csta_event, fwd_type);
}
}
@@ -4998,7 +5017,7 @@ static void general_event_handler(switch_event_t *event)
char *contact, *p;
switch_console_callback_match_t *list = NULL;
switch_console_callback_match_node_t *m;
if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find registered user %s@%s\n", user, host);
return;
@@ -5150,7 +5169,7 @@ static void general_event_handler(switch_event_t *event)
if (!strcmp(cond, "network-external-address-change") && mod_sofia_globals.auto_restart) {
const char *old_ip4 = switch_event_get_header_nil(event, "network-external-address-previous-v4");
const char *new_ip4 = switch_event_get_header_nil(event, "network-external-address-change-v4");
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash && !zstr(old_ip4) && !zstr(new_ip4)) {
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
@@ -5168,7 +5187,7 @@ static void general_event_handler(switch_event_t *event)
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
sofia_glue_restart_all_profiles();
sofia_glue_restart_all_profiles();
} else if (!strcmp(cond, "network-address-change") && mod_sofia_globals.auto_restart) {
const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4");
const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4");
@@ -5248,30 +5267,35 @@ void write_csta_xml_chunk(switch_event_t *event, switch_stream_handle_t stream,
stream.write_function(&stream, " <doNotDisturbOn>%s</doNotDisturbOn>\n", dndstatus);
}
} else if(!strcmp(csta_event, "ForwardingEvent")) {
const char *fwdstatus = switch_event_get_header(event, "forwardStatus");
const char *fwdstatus = NULL;
const char *fwdto = NULL;
const char *ringcount = NULL;
if (strcmp("forwardImmediate", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_immediate");
} else if (strcmp("forwardBusy", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_busy");
} else if (strcmp("fowardNoAns", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_no_answer");
ringcount = switch_event_get_header(event, "ringCount");
}
if (fwdtype && !zstr(fwdtype)) {
if (!strcmp("forwardImmediate", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_immediate");
fwdstatus = switch_event_get_header(event, "forward_immediate_enabled");
} else if (!strcmp("forwardBusy", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_busy");
fwdstatus = switch_event_get_header(event, "forward_busy_enabled");
} else if (!strcmp("forwardNoAns", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_no_answer");
fwdstatus = switch_event_get_header(event, "forward_no_answer_enabled");
ringcount = switch_event_get_header(event, "ringCount");
}
if (fwdtype) {
stream.write_function(&stream, " <forwardingType>%s</forwardingType>\n", fwdtype);
}
if (fwdstatus) {
stream.write_function(&stream, " <forwardStatus>%s</forwardStatus>\n", fwdstatus);
}
if (fwdto) {
stream.write_function(&stream, " <forwardTo>%s</forwardTo>\n", fwdto);
}
if (ringcount) {
stream.write_function(&stream, " <ringCount>%s</ringCount>\n", ringcount);
if (fwdtype) {
stream.write_function(&stream, " <forwardingType>%s</forwardingType>\n", fwdtype);
}
if (fwdstatus) {
stream.write_function(&stream, " <forwardStatus>%s</forwardStatus>\n", fwdstatus);
}
if (fwdto) {
stream.write_function(&stream, " <forwardTo>%s</forwardTo>\n", fwdto);
}
if (ringcount) {
stream.write_function(&stream, " <ringCount>%s</ringCount>\n", ringcount);
}
}
}
@@ -5403,7 +5427,7 @@ SWITCH_STANDARD_APP(sofia_sla_function)
}
switch_channel_answer(channel);
if ((bargee_session = switch_core_session_locate((char *)data))) {
if (bargee_session == session) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "BARGE: %s (cannot barge on myself)\n", (char *) data);
@@ -5415,12 +5439,12 @@ SWITCH_STANDARD_APP(sofia_sla_function)
switch_channel_set_flag(tech_pvt->channel, CF_SLA_BARGE);
switch_ivr_transfer_variable(bargee_session, session, SWITCH_SIGNAL_BOND_VARIABLE);
}
if (switch_core_session_check_interface(session, sofia_endpoint_interface)) {
tech_pvt = switch_core_session_get_private(session);
switch_channel_set_flag(tech_pvt->channel, CF_SLA_BARGING);
}
switch_channel_set_variable(channel, "sip_barging_uuid", (char *)data);
}
@@ -5428,7 +5452,7 @@ SWITCH_STANDARD_APP(sofia_sla_function)
}
switch_channel_execute_on(channel, "execute_on_sip_barge");
switch_ivr_eavesdrop_session(session, data, NULL, ED_MUX_READ | ED_MUX_WRITE | ED_COPY_DISPLAY);
}
@@ -5482,12 +5506,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
/* start one message thread */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Starting initial message thread.\n");
sofia_msg_thread_start(0);
if (sofia_init() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR;
}
if (config_sofia(SOFIA_CONFIG_LOAD, NULL) != SWITCH_STATUS_SUCCESS) {
mod_sofia_globals.running = 0;
return SWITCH_STATUS_GENERR;
@@ -5573,7 +5597,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
management_interface->relative_oid = "1001";
management_interface->management_function = sofia_manage;
SWITCH_ADD_APP(app_interface, "sofia_sla", "private sofia sla function",
SWITCH_ADD_APP(app_interface, "sofia_sla", "private sofia sla function",
"private sofia sla function", sofia_sla_function, "<uuid>", SAF_NONE);
@@ -5597,7 +5621,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_console_set_complete("add sofia profile");
switch_console_set_complete("add sofia profile restart all");
switch_console_set_complete("add sofia profile ::sofia::list_profiles start");
switch_console_set_complete("add sofia profile ::sofia::list_profiles stop wait");
switch_console_set_complete("add sofia profile ::sofia::list_profiles rescan");
@@ -5709,4 +5733,3 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
include ../../../../build/modmake.rules
@@ -0,0 +1,88 @@
<configuration name="format_cdr.conf" description="Multi Format CDR CURL logger">
<!-- You can have multiple profiles, to allow logging to both json and cdr simultaneously, or to
different paths or servers with different settings, just be sure to use different name for
each profile. -->
<profiles>
<profile name="default">
<settings>
<!-- the format of data to send, defaults to xml -->
<!-- <param name="format" value="json|xml"/> -->
<param name="format" value="xml"/>
<!-- the url to post to if blank web posting is disabled -->
<!-- <param name="url" value="http://localhost/cdr_curl/post.php"/> -->
<!-- optional: credentials to send to web server -->
<!-- <param name="cred" value="user:pass"/> -->
<!-- the total number of retries (not counting the first 'try') to post to webserver incase of failure -->
<!-- <param name="retries" value="2"/> -->
<!-- delay between retries in seconds, default is 5 seconds -->
<!-- <param name="delay" value="1"/> -->
<!-- Log via http and on disk, default is false -->
<!-- <param name="log-http-and-disk" value="true"/> -->
<!-- optional: if not present we do not log every record to disk -->
<!-- either an absolute path, a relative path assuming ${prefix}/logs or a blank value will default to ${prefix}/logs/format_cdr -->
<param name="log-dir" value=""/>
<!-- optional: if not present we do log the b leg -->
<!-- true or false if we should create a cdr for the b leg of a call-->
<param name="log-b-leg" value="false"/>
<!-- optional: if not present, all filenames are the uuid of the call -->
<!-- true or false if a leg files are prefixed "a_" -->
<param name="prefix-a-leg" value="true"/>
<!-- encode the post data may be 'true' for url encoding, 'false' for no encoding, 'base64' for base64 encoding or 'textxml' for text/xml -->
<param name="encode" value="true"/>
<!-- optional: set to true to disable Expect: 100-continue lighttpd requires this setting -->
<!--<param name="disable-100-continue" value="true"/>-->
<!-- optional: full path to the error log dir for failed web posts if not specified its the same as log-dir -->
<!-- either an absolute path, a relative path assuming ${prefix}/logs or a blank or omitted value will default to ${prefix}/logs/format_cdr -->
<!-- <param name="err-log-dir" value="/tmp"/> -->
<!-- which auhtentification scheme to use. Supported values are: basic, digest, NTLM, GSS-NEGOTIATE or "any" for automatic detection -->
<!--<param name="auth-scheme" value="basic"/>-->
<!-- optional: this will enable the CA root certificate check by libcurl to
verify that the certificate was issued by a major Certificate Authority.
note: default value is disabled. only enable if you want this! -->
<!--<param name="enable-cacert-check" value="true"/>-->
<!-- optional: verify that the server is actually the one listed in the cert -->
<!-- <param name="enable-ssl-verifyhost" value="true"/> -->
<!-- optional: these options can be used to specify custom SSL certificates
to use for HTTPS communications. Either use both options or neither.
Specify your public key with 'ssl-cert-path' and the private key with
'ssl-key-path'. If your private key has a password, specify it with
'ssl-key-password'. -->
<!-- <param name="ssl-cert-path" value="$${base_dir}/conf/certs/public_key.pem"/> -->
<!-- <param name="ssl-key-path" value="$${base_dir}/conf/certs/private_key.pem"/> -->
<!-- <param name="ssl-key-password" value="MyPrivateKeyPassword"/> -->
<!-- optional: use a custom CA certificate in PEM format to verify the peer
with. This is useful if you are acting as your own certificate authority.
note: only makes sense if used in combination with "enable-cacert-check." -->
<!-- <param name="ssl-cacert-file" value="$${base_dir}/conf/certs/cacert.pem"/> -->
<!-- optional: specify the SSL version to force HTTPS to use. Valid options are
"SSLv3" and "TLSv1". Otherwise libcurl will auto-negotiate the version. -->
<!-- <param name="ssl-version" value="TLSv1"/> -->
<!-- optional: enables cookies and stores them in the specified file. -->
<!-- <param name="cookie-file" value="/tmp/cookie-mod_format_cdr_curl.txt"/> -->
<!-- Whether to URL encode the individual JSON values. Defaults to true, set to false for standard JSON. -->
<param name="encode-values" value="true"/>
</settings>
</profile>
</profiles>
</configuration>
@@ -0,0 +1,289 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="mod_format_cdr"
ProjectGUID="{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}"
RootNamespace="mod_format_cdr"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalLibraryDirectories=""
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
AdditionalLibraryDirectories=""
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\mod_format_cdr.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,149 @@
<?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_format_cdr</ProjectName>
<ProjectGuid>{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}</ProjectGuid>
<RootNamespace>mod_format_cdr</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" />
<Import Project="..\..\..\..\w32\curl.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" />
<Import Project="..\..\..\..\w32\curl.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" />
<Import Project="..\..\..\..\w32\curl.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" />
<Import Project="..\..\..\..\w32\curl.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_format_cdr.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\win32\apr\libapr.2010.vcxproj">
<Project>{f6c55d93-b927-4483-bb69-15aef3dd2dff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\curl\curllib.2010.vcxproj">
<Project>{87ee9da4-de1e-4448-8324-183c98dca588}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<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>
@@ -0,0 +1,149 @@
<?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_format_cdr</ProjectName>
<ProjectGuid>{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}</ProjectGuid>
<RootNamespace>mod_format_cdr</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>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</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>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_format_cdr.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\win32\apr\libapr.2012.vcxproj">
<Project>{f6c55d93-b927-4483-bb69-15aef3dd2dff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\curl\curllib.2012.vcxproj">
<Project>{87ee9da4-de1e-4448-8324-183c98dca588}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2012.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,812 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, 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):
*
* Brian West <brian@freeswitch.org>
* Bret McDanel <trixter AT 0xdecafbad.com>
* Justin Cassidy <xachenant@hotmail.com>
*
* mod_format_cdr.c -- XML CDR Module to files or curl
*
*/
#include <sys/stat.h>
#include <switch.h>
#include <switch_curl.h>
#define MAX_URLS 20
#define MAX_ERR_DIRS 20
#define ENCODING_NONE 0
#define ENCODING_DEFAULT 1
#define ENCODING_BASE64 2
#define ENCODING_TEXTXML 3
#define ENCODING_APPLJSON 4
static struct {
switch_hash_t *profile_hash;
switch_memory_pool_t *pool;
switch_event_node_t *node;
switch_mutex_t *mutex;
uint32_t shutdown;
} globals;
struct cdr_profile {
char *name;
char *format;
char *cred;
char *urls[MAX_URLS + 1];
int url_count;
int url_index;
switch_thread_rwlock_t *log_path_lock;
char *base_log_dir;
char *base_err_log_dir[MAX_ERR_DIRS];
char *log_dir;
char *err_log_dir[MAX_ERR_DIRS];
int err_dir_count;
uint32_t delay;
uint32_t retries;
uint32_t enable_cacert_check;
char *ssl_cert_file;
char *ssl_key_file;
char *ssl_key_password;
char *ssl_version;
char *ssl_cacert_file;
uint32_t enable_ssl_verifyhost;
int encode;
int encode_values;
int log_http_and_disk;
int log_b;
int prefix_a;
int disable100continue;
int rotate;
int auth_scheme;
int timeout;
switch_memory_pool_t *pool;
};
typedef struct cdr_profile cdr_profile_t;
SWITCH_MODULE_LOAD_FUNCTION(mod_format_cdr_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_format_cdr_shutdown);
SWITCH_MODULE_DEFINITION(mod_format_cdr, mod_format_cdr_load, mod_format_cdr_shutdown, NULL);
/* this function would have access to the HTML returned by the webserver, we don't need it
* and the default curl activity is to print to stdout, something not as desirable
* so we have a dummy function here
*/
static size_t httpCallBack(char *buffer, size_t size, size_t nitems, void *outstream)
{
return size * nitems;
}
static switch_status_t set_format_cdr_log_dirs(cdr_profile_t *profile)
{
switch_time_exp_t tm;
char *path = NULL;
char date[80] = "";
switch_size_t retsize;
switch_status_t status = SWITCH_STATUS_SUCCESS, dir_status;
int err_dir_index;
switch_time_exp_lt(&tm, switch_micro_time_now());
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rotating log file paths\n");
if (!zstr(profile->base_log_dir)) {
if (profile->rotate) {
if ((path = switch_mprintf("%s%s%s", profile->base_log_dir, SWITCH_PATH_SEPARATOR, date))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rotating log file path to %s\n", path);
dir_status = SWITCH_STATUS_SUCCESS;
if (switch_directory_exists(path, profile->pool) != SWITCH_STATUS_SUCCESS) {
dir_status = switch_dir_make(path, SWITCH_FPROT_OS_DEFAULT, profile->pool);
}
if (dir_status == SWITCH_STATUS_SUCCESS) {
switch_thread_rwlock_wrlock(profile->log_path_lock);
switch_safe_free(profile->log_dir);
profile->log_dir = path;
switch_thread_rwlock_unlock(profile->log_path_lock);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new mod_format_cdr log_dir path\n");
switch_safe_free(path);
status = SWITCH_STATUS_FALSE;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to generate new mod_format_cdr log_dir path\n");
status = SWITCH_STATUS_FALSE;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Setting log file path to %s\n", profile->base_log_dir);
if ((path = switch_safe_strdup(profile->base_log_dir))) {
switch_thread_rwlock_wrlock(profile->log_path_lock);
switch_safe_free(profile->log_dir);
switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, profile->pool);
profile->log_dir = path;
switch_thread_rwlock_unlock(profile->log_path_lock);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set log_dir path\n");
status = SWITCH_STATUS_FALSE;
}
}
}
for (err_dir_index = 0; err_dir_index < profile->err_dir_count; err_dir_index++) {
if (profile->rotate) {
if ((path = switch_mprintf("%s%s%s", profile->base_err_log_dir[err_dir_index], SWITCH_PATH_SEPARATOR, date))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rotating err log file path to %s\n", path);
dir_status = SWITCH_STATUS_SUCCESS;
if (switch_directory_exists(path, profile->pool) != SWITCH_STATUS_SUCCESS) {
dir_status = switch_dir_make(path, SWITCH_FPROT_OS_DEFAULT, profile->pool);
}
if (dir_status == SWITCH_STATUS_SUCCESS) {
switch_thread_rwlock_wrlock(profile->log_path_lock);
switch_safe_free(profile->err_log_dir[err_dir_index]);
profile->err_log_dir[err_dir_index] = path;
switch_thread_rwlock_unlock(profile->log_path_lock);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new mod_format_cdr err_log_dir path\n");
switch_safe_free(path);
status = SWITCH_STATUS_FALSE;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to generate new mod_format_cdr err_log_dir path\n");
status = SWITCH_STATUS_FALSE;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Setting err log file path to %s\n", profile->base_err_log_dir[err_dir_index]);
if ((path = switch_safe_strdup(profile->base_err_log_dir[err_dir_index]))) {
switch_thread_rwlock_wrlock(profile->log_path_lock);
switch_safe_free(profile->err_log_dir[err_dir_index]);
switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, profile->pool);
profile->err_log_dir[err_dir_index] = path;
switch_thread_rwlock_unlock(profile->log_path_lock);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set err_log_dir path\n");
status = SWITCH_STATUS_FALSE;
}
}
}
return status;
}
static switch_status_t my_on_reporting_cb(switch_core_session_t *session, cdr_profile_t *profile)
{
switch_xml_t xml_cdr = NULL;
cJSON *json_cdr = NULL;
char *cdr_text = NULL;
char *dpath = NULL;
char *path = NULL;
char *curl_cdr_text = NULL;
const char *logdir = NULL;
char *cdr_text_escaped = NULL;
int fd = -1;
uint32_t cur_try;
long httpRes;
switch_CURL *curl_handle = 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;
const char *a_prefix = "";
if (globals.shutdown) {
return SWITCH_STATUS_SUCCESS;
}
is_b = channel && switch_channel_get_originator_caller_profile(channel);
if (!profile->log_b && is_b) {
const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE);
if (!switch_true(force_cdr)) {
return SWITCH_STATUS_SUCCESS;
}
}
if (!is_b && profile->prefix_a)
a_prefix = "a_";
if ( ! strcasecmp(profile->format, "json") ) {
if (switch_ivr_generate_json_cdr(session, &json_cdr, profile->encode_values == ENCODING_DEFAULT) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating JSON Data!\n");
return SWITCH_STATUS_FALSE;
}
/* build the JSON */
cdr_text = cJSON_PrintUnformatted(json_cdr);
if (!cdr_text) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error generating JSON!\n");
goto error;
}
} else if ( ! strcasecmp(profile->format, "xml") ) {
if (switch_ivr_generate_xml_cdr(session, &xml_cdr) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating XML Data!\n");
return SWITCH_STATUS_FALSE;
}
/* build the XML */
cdr_text = switch_xml_toxml(xml_cdr, SWITCH_TRUE);
if (!cdr_text) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error generating XML!\n");
goto error;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unhandled format for mod_format_cdr!\n");
goto error;
}
switch_thread_rwlock_rdlock(profile->log_path_lock);
if (!(logdir = switch_channel_get_variable(channel, "format_cdr_base"))) {
logdir = profile->log_dir;
}
if (!zstr(logdir) && (profile->log_http_and_disk || !profile->url_count)) {
dpath = switch_mprintf("%s%s%s", logdir, SWITCH_PATH_SEPARATOR, a_prefix);
path = switch_mprintf("%s%s%s%s.cdr.%s", logdir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session),
profile->format);
switch_thread_rwlock_unlock(profile->log_path_lock);
if (path) {
if (switch_directory_exists(dpath, profile->pool) != SWITCH_STATUS_SUCCESS) {
switch_dir_make_recursive(dpath, SWITCH_FPROT_OS_DEFAULT, profile->pool);
}
#ifdef _MSC_VER
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
#else
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) {
#endif
int wrote;
wrote = write(fd, cdr_text, (unsigned) strlen(cdr_text));
wrote++;
close(fd);
fd = -1;
} else {
char ebuf[512] = { 0 };
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s][%s]\n",
path, switch_strerror_r(errno, ebuf, sizeof(ebuf)));
}
switch_safe_free(path);
switch_safe_free(dpath);
}
} else {
switch_thread_rwlock_unlock(profile->log_path_lock);
}
/* try to post it to the web server */
if (profile->url_count) {
char *destUrl = NULL;
curl_handle = switch_curl_easy_init();
if (profile->encode == ENCODING_TEXTXML) {
headers = switch_curl_slist_append(headers, "Content-Type: text/xml");
} else if (profile->encode == ENCODING_APPLJSON) {
headers = switch_curl_slist_append(headers, "Content-Type: application/json");
} else if (profile->encode) {
switch_size_t need_bytes = strlen(cdr_text) * 3 + 1;
cdr_text_escaped = malloc(need_bytes);
switch_assert(cdr_text_escaped);
memset(cdr_text_escaped, 0, need_bytes);
if (profile->encode == ENCODING_DEFAULT) {
headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
switch_url_encode(cdr_text, cdr_text_escaped, need_bytes);
} else {
headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded");
switch_b64_encode((unsigned char *) cdr_text, need_bytes / 3, (unsigned char *) cdr_text_escaped, need_bytes);
}
switch_safe_free(cdr_text);
cdr_text = cdr_text_escaped;
} else {
headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-plaintext");
}
if (profile->encode == ENCODING_TEXTXML) {
curl_cdr_text = cdr_text;
} else if (profile->encode == ENCODING_APPLJSON) {
curl_cdr_text = cdr_text;
} else if (!(curl_cdr_text = switch_mprintf("cdr=%s", cdr_text))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
goto error;
}
if (!zstr(profile->cred)) {
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, profile->auth_scheme);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, profile->cred);
}
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_cdr_text);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-format-cdr/1.0");
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack);
if (profile->disable100continue) {
slist = switch_curl_slist_append(slist, "Expect:");
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
}
if (profile->ssl_cert_file) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, profile->ssl_cert_file);
}
if (profile->ssl_key_file) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, profile->ssl_key_file);
}
if (profile->ssl_key_password) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, profile->ssl_key_password);
}
if (profile->ssl_version) {
if (!strcasecmp(profile->ssl_version, "SSLv3")) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
} else if (!strcasecmp(profile->ssl_version, "TLSv1")) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
}
}
if (profile->ssl_cacert_file) {
switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, profile->ssl_cacert_file);
}
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, profile->timeout);
/* these were used for testing, optionally they may be enabled if someone desires
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level
*/
for (cur_try = 0; cur_try < profile->retries; cur_try++) {
if (cur_try > 0) {
switch_yield(profile->delay * 1000000);
}
destUrl = switch_mprintf("%s?uuid=%s%s", profile->urls[profile->url_index], a_prefix, switch_core_session_get_uuid(session));
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl);
if (!strncasecmp(destUrl, "https", 5)) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
if (profile->enable_cacert_check) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE);
}
if (profile->enable_ssl_verifyhost) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
}
switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_safe_free(destUrl);
if (httpRes >= 200 && httpRes <= 299) {
goto success;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Got error [%ld] posting to web server [%s]\n",
httpRes, profile->urls[profile->url_index]);
profile->url_index++;
switch_assert(profile->url_count <= MAX_URLS);
if (profile->url_index >= profile->url_count) {
profile->url_index = 0;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retry will be with url [%s]\n", profile->urls[profile->url_index]);
}
}
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;
/* if we are here the web post failed for some reason */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to post to web server, writing to file\n");
switch_thread_rwlock_rdlock(profile->log_path_lock);
dpath = switch_mprintf("%s%s%s", profile->err_log_dir, SWITCH_PATH_SEPARATOR, a_prefix);
path = switch_mprintf("%s%s%s%s.cdr.%s", profile->err_log_dir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session),
profile->format);
switch_thread_rwlock_unlock(profile->log_path_lock);
if (path) {
if (switch_directory_exists(dpath, profile->pool) != SWITCH_STATUS_SUCCESS) {
switch_dir_make_recursive(dpath, SWITCH_FPROT_OS_DEFAULT, profile->pool);
}
#ifdef _MSC_VER
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
#else
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) {
#endif
int wrote;
wrote = write(fd, cdr_text, (unsigned) strlen(cdr_text));
wrote++;
close(fd);
fd = -1;
} else {
char ebuf[512] = { 0 };
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error![%s]\n",
switch_strerror_r(errno, ebuf, sizeof(ebuf)));
}
switch_safe_free(path);
switch_safe_free(dpath);
}
}
success:
status = SWITCH_STATUS_SUCCESS;
error:
if (curl_handle) {
switch_curl_easy_cleanup(curl_handle);
}
if (headers) {
switch_curl_slist_free_all(headers);
}
if (slist) {
switch_curl_slist_free_all(slist);
}
if (curl_cdr_text != cdr_text) {
switch_safe_free(curl_cdr_text);
}
switch_safe_free(cdr_text);
switch_safe_free(path);
switch_safe_free(dpath);
if ( xml_cdr )
{
switch_xml_free(xml_cdr);
}
if ( json_cdr )
{
cJSON_Delete(json_cdr);
}
return status;
}
static switch_status_t my_on_reporting(switch_core_session_t *session)
{
switch_hash_index_t *hi;
void *val;
switch_status_t status, tmpstatus;
status = SWITCH_STATUS_SUCCESS;
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
cdr_profile_t *profile;
switch_hash_this(hi, NULL, NULL, &val);
profile = (cdr_profile_t *) val;
tmpstatus = my_on_reporting_cb(session, profile);
if ( tmpstatus != SWITCH_STATUS_SUCCESS ) {
status = tmpstatus;
}
}
return status;
}
static void event_handler(switch_event_t *event)
{
switch_hash_index_t *hi;
void *val;
const char *sig = switch_event_get_header(event, "Trapped-Signal");
if (sig && !strcmp(sig, "HUP")) {
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
cdr_profile_t *profile;
switch_hash_this(hi, NULL, NULL, &val);
profile = (cdr_profile_t *) val;
if (profile->rotate) {
set_format_cdr_log_dirs(profile);
}
}
}
}
static switch_state_handler_table_t state_handlers = {
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ NULL,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_hibernate */ NULL,
/*.on_reset */ NULL,
/*.on_park */ NULL,
/*.on_reporting */ my_on_reporting
};
switch_status_t mod_format_cdr_load_profile_xml(switch_xml_t xprofile)
{
switch_memory_pool_t *pool = NULL;
cdr_profile_t *profile = NULL;
switch_xml_t settings, param;
char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name");
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n");
return SWITCH_STATUS_TERM;
}
profile = switch_core_alloc(pool, sizeof(cdr_profile_t));
memset(profile, 0, sizeof(cdr_profile_t));
profile->pool = pool;
profile->name = switch_core_strdup(profile->pool, profile_name);
profile->log_http_and_disk = 0;
profile->log_b = 1;
profile->disable100continue = 0;
profile->auth_scheme = CURLAUTH_BASIC;
switch_thread_rwlock_create(&profile->log_path_lock, pool);
if ((settings = switch_xml_child(xprofile, "settings"))) {
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "cred") && !zstr(val)) {
profile->cred = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "format") && !zstr(val)) {
profile->format = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "url") && !zstr(val)) {
if (profile->url_count >= MAX_URLS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "maximum urls configured!\n");
} else {
profile->urls[profile->url_count++] = switch_core_strdup(profile->pool, val);
}
} else if (!strcasecmp(var, "log-http-and-disk")) {
profile->log_http_and_disk = switch_true(val);
} else if (!strcasecmp(var, "timeout")) {
int tmp = atoi(val);
if (tmp >= 0) {
profile->timeout = tmp;
} else {
profile->timeout = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
}
} else if (!strcasecmp(var, "delay") && !zstr(val)) {
profile->delay = switch_atoui(val);
} else if (!strcasecmp(var, "log-b-leg")) {
profile->log_b = switch_true(val);
} else if (!strcasecmp(var, "prefix-a-leg")) {
profile->prefix_a = switch_true(val);
} else if (!strcasecmp(var, "disable-100-continue") && switch_true(val)) {
profile->disable100continue = 1;
} else if (!strcasecmp(var, "encode") && !zstr(val)) {
if (!strcasecmp(val, "base64")) {
profile->encode = ENCODING_BASE64;
} else if (!strcasecmp(val, "textxml")) {
profile->encode = ENCODING_TEXTXML;
} else if (!strcasecmp(val, "appljson")) {
profile->encode = ENCODING_APPLJSON;
} else {
profile->encode = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE;
}
} else if (!strcasecmp(var, "retries") && !zstr(val)) {
profile->retries = switch_atoui(val);
} else if (!strcasecmp(var, "rotate") && !zstr(val)) {
profile->rotate = switch_true(val);
} else if (!strcasecmp(var, "log-dir")) {
if (zstr(val)) {
profile->base_log_dir = switch_core_sprintf(profile->pool, "%s%sformat_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
} else {
if (switch_is_file_path(val)) {
profile->base_log_dir = switch_core_strdup(profile->pool, val);
} else {
profile->base_log_dir = switch_core_sprintf(profile->pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val);
}
}
} else if (!strcasecmp(var, "err-log-dir")) {
if (profile->err_dir_count >= MAX_ERR_DIRS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "maximum error directories configured!\n");
} else {
if (zstr(val)) {
profile->base_err_log_dir[profile->err_dir_count++] = switch_core_sprintf(profile->pool, "%s%sformat_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
} else {
if (switch_is_file_path(val)) {
profile->base_err_log_dir[profile->err_dir_count++] = switch_core_strdup(profile->pool, val);
} else {
profile->base_err_log_dir[profile->err_dir_count++] = switch_core_sprintf(profile->pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val);
}
}
}
} else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) {
profile->enable_cacert_check = 1;
} else if (!strcasecmp(var, "ssl-cert-path")) {
profile->ssl_cert_file = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "ssl-key-path")) {
profile->ssl_key_file = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "ssl-key-password")) {
profile->ssl_key_password = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "ssl-version")) {
profile->ssl_version = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "ssl-cacert-file")) {
profile->ssl_cacert_file = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) {
profile->enable_ssl_verifyhost = 1;
} else if (!strcasecmp(var, "auth-scheme")) {
if (*val == '=') {
profile->auth_scheme = 0;
val++;
}
if (!strcasecmp(val, "basic")) {
profile->auth_scheme |= CURLAUTH_BASIC;
} else if (!strcasecmp(val, "digest")) {
profile->auth_scheme |= CURLAUTH_DIGEST;
} else if (!strcasecmp(val, "NTLM")) {
profile->auth_scheme |= CURLAUTH_NTLM;
} else if (!strcasecmp(val, "GSS-NEGOTIATE")) {
profile->auth_scheme |= CURLAUTH_GSSNEGOTIATE;
} else if (!strcasecmp(val, "any")) {
profile->auth_scheme = CURLAUTH_ANY;
}
} else if (!strcasecmp(var, "encode-values") && !zstr(val)) {
profile->encode_values = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE;
}
}
if (!profile->err_dir_count) {
if (!zstr(profile->base_log_dir)) {
profile->base_err_log_dir[profile->err_dir_count++] = switch_core_strdup(profile->pool, profile->base_log_dir);
} else {
profile->base_err_log_dir[profile->err_dir_count++] = switch_core_sprintf(profile->pool, "%s%sformat_cdr",
SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
}
}
}
if (profile->retries && profile->delay == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retries set but delay 0 setting to 5 seconds\n");
profile->delay = 5;
}
if ( ! profile->format || (strcasecmp(profile->format,"json") && strcasecmp(profile->format,"xml")) )
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No valid format_cdr format specified, defaulting to xml.\n");
profile->format = switch_core_strdup(profile->pool,"xml");
}
profile->retries++;
switch_mutex_lock(globals.mutex);
switch_core_hash_insert(globals.profile_hash, profile->name, profile);
switch_mutex_unlock(globals.mutex);
set_format_cdr_log_dirs(profile);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_format_cdr_load)
{
char *cf = "format_cdr.conf";
switch_xml_t cfg, xml, xprofiles, xprofile;
switch_status_t status = SWITCH_STATUS_SUCCESS;
/* test global state handlers */
switch_core_add_state_handler(&state_handlers);
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
memset(&globals, 0, sizeof(globals));
if (switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY,
event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
return SWITCH_STATUS_GENERR;
}
globals.pool = pool;
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_core_hash_init(&globals.profile_hash, globals.pool);
/* parse the config */
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
return SWITCH_STATUS_TERM;
}
switch_mutex_lock(globals.mutex);
if ((xprofiles = switch_xml_child(cfg, "profiles"))) {
for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) {
char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name");
if (zstr(profile_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"<profile> is missing name attribute\n");
continue;
}
mod_format_cdr_load_profile_xml(xprofile);
}
}
switch_xml_free(xml);
switch_mutex_unlock(globals.mutex);
return status;
}
void mod_format_cdr_profile_shutdown(cdr_profile_t *profile)
{
int err_dir_index = 0;
for (err_dir_index = 0; err_dir_index < profile->err_dir_count; err_dir_index++) {
switch_safe_free(profile->err_log_dir[err_dir_index]);
}
switch_safe_free(profile->log_dir);
switch_thread_rwlock_destroy(profile->log_path_lock);
switch_core_destroy_memory_pool(&profile->pool);
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_format_cdr_shutdown)
{
switch_hash_index_t *hi;
void *val;
globals.shutdown = 1;
switch_event_unbind(&globals.node);
switch_core_remove_state_handler(&state_handlers);
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
cdr_profile_t *profile;
switch_hash_this(hi, NULL, NULL, &val);
profile = (cdr_profile_t *) val;
if ( profile ) {
mod_format_cdr_profile_shutdown(profile);
}
}
switch_core_hash_destroy(&globals.profile_hash);
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="mod_format_cdr"
ProjectGUID="{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}"
RootNamespace="mod_format_cdr"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet="2"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
UsePrecompiledHeader="0"
/>
<Tool
Name="VCLinkerTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet="2"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
UsePrecompiledHeader="0"
/>
<Tool
Name="VCLinkerTool"
AdditionalLibraryDirectories=""
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\mod_format_cdr.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+109 -46
View File
@@ -128,6 +128,8 @@ struct rayo_call {
switch_time_t idle_start_time;
/** 1 if joined to call, 2 if joined to mixer */
int joined;
/** pending join */
iks *pending_join_request;
/** ID of joined party TODO this will be many mixers / calls */
const char *joined_id;
/** set if response needs to be sent to IQ request */
@@ -937,6 +939,14 @@ static void rayo_call_cleanup(struct rayo_actor *actor)
RAYO_SEND_MESSAGE_DUP(actor, rayo_call_get_dcp_jid(call), revent);
}
/* lost the race: pending join failed... send IQ result to client now. */
if (call->pending_join_request) {
iks *result = iks_new_error_detailed(call->pending_join_request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended");
RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result);
iks_delete(call->pending_join_request);
call->pending_join_request = NULL;
}
iks_delete(revent);
switch_event_destroy(&event);
}
@@ -1068,6 +1078,7 @@ static struct rayo_call *rayo_call_init(struct rayo_call *call, switch_memory_po
call->joined = 0;
call->joined_id = NULL;
call->ringing_sent = 0;
call->pending_join_request = NULL;
switch_core_hash_init(&call->pcps, pool);
switch_safe_free(call_jid);
@@ -1292,6 +1303,17 @@ static struct rayo_peer_server *rayo_peer_server_create(const char *jid)
return rserver;
}
/**
* Check if message sender has control of offered call.
* @param call the Rayo call
* @param msg the message
* @return 1 if sender has call control, 0 if sender does not have control
*/
static int has_call_control(struct rayo_call *call, struct rayo_message *msg)
{
return (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg));
}
/**
* Check if message sender has control of offered call. Take control if nobody else does.
* @param call the Rayo call
@@ -1299,7 +1321,7 @@ static struct rayo_peer_server *rayo_peer_server_create(const char *jid)
* @param msg the message
* @return 1 if sender has call control
*/
static int has_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg)
static int take_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg)
{
int control = 0;
@@ -1313,7 +1335,7 @@ static int has_call_control(struct rayo_call *call, switch_core_session_t *sessi
control = 1;
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", rayo_call_get_dcp_jid(call));
}
} else if (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg)) {
} else if (has_call_control(call, msg)) {
control = 1;
}
@@ -1358,7 +1380,7 @@ static iks *rayo_call_command_ok(struct rayo_call *call, switch_core_session_t *
if (bad) {
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
} else if (!has_call_control(call, session, msg)) {
} else if (!take_call_control(call, session, msg)) {
response = iks_new_error(node, STANZA_ERROR_CONFLICT);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(call));
}
@@ -1711,13 +1733,14 @@ static iks *on_rayo_hangup(struct rayo_actor *call, struct rayo_message *msg, vo
* Join calls together
* @param call the call that joins
* @param session the session
* @param node the join request
* @param msg the rayo join message
* @param call_uri to join
* @param media mode (direct/bridge)
* @return the response
*/
static iks *join_call(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *call_uri, const char *media)
static iks *join_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri, const char *media)
{
iks *node = msg->payload;
iks *response = NULL;
/* take call out of media path if media = "direct" */
const char *bypass = !strcmp("direct", media) ? "true" : "false";
@@ -1727,6 +1750,9 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik
if (!b_call) {
/* not a rayo call */
response = iks_new_error_detailed(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "b-leg is not a rayo call");
} else if (!has_call_control(b_call, msg)) {
/* not allowed to join to this call */
response = iks_new_error(node, STANZA_ERROR_NOT_ALLOWED);
} else if (b_call->joined) {
/* don't support multiple joined calls */
response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "multiple joined calls not supported");
@@ -1737,10 +1763,11 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik
if (switch_false(bypass)) {
switch_channel_pre_answer(switch_core_session_get_channel(session));
}
if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) == SWITCH_STATUS_SUCCESS) {
response = iks_new_iq_result(node);
} else {
call->pending_join_request = iks_copy(node);
if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) != SWITCH_STATUS_SUCCESS) {
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to bridge call");
iks_delete(call->pending_join_request);
call->pending_join_request = NULL;
}
RAYO_UNLOCK(b_call);
}
@@ -1763,13 +1790,14 @@ static void exec_conference_api(switch_core_session_t *session, const char *conf
* Join call to a mixer
* @param call the call that joins
* @param session the session
* @param node the join request
* @param msg the join request
* @param mixer_name the mixer to join
* @param direction the media direction
* @return the response
*/
static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *mixer_name, const char *direction)
static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name, const char *direction)
{
iks *node = msg->payload;
iks *response = NULL;
if (call->joined_id) {
@@ -1806,14 +1834,13 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, i
* Handle <iq><join> request
* @param call the Rayo call
* @param session the session
* @param node the <iq> node
* @param msg the rayo join message
*/
static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
{
iks *node = msg->payload;
switch_core_session_t *session = (switch_core_session_t *)session_data;
iks *response = NULL;
iks *join = iks_find(node, "join");
iks *join = iks_find(msg->payload, "join");
const char *join_id;
const char *mixer_name;
const char *call_uri;
@@ -1821,7 +1848,7 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void
/* validate input attributes */
if (!VALIDATE_RAYO_JOIN(join)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad join attrib\n");
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST);
goto done;
}
mixer_name = iks_find_attrib(join, "mixer-name");
@@ -1835,29 +1862,35 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void
/* can't join both mixer and call */
if (!zstr(mixer_name) && !zstr(call_uri)) {
response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "mixer-name and call-uri are mutually exclusive");
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name and call-uri are mutually exclusive");
goto done;
}
/* need to join *something* */
if (zstr(mixer_name) && zstr(call_uri)) {
response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "mixer-name or call-uri is required");
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name or call-uri is required");
goto done;
}
if ((RAYO_CALL(call)->joined == JOINED_CALL) ||
(RAYO_CALL(call)->joined == JOINED_MIXER && strcmp(RAYO_CALL(call)->joined_id, join_id))) {
/* already joined */
response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "call is already joined");
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_CONFLICT, "call is already joined");
goto done;
}
if (RAYO_CALL(call)->pending_join_request) {
/* don't allow concurrent join requests */
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending");
goto done;
}
if (!zstr(mixer_name)) {
/* join conference */
response = join_mixer(RAYO_CALL(call), session, node, mixer_name, iks_find_attrib(join, "direction"));
response = join_mixer(RAYO_CALL(call), session, msg, mixer_name, iks_find_attrib(join, "direction"));
} else {
/* bridge calls */
response = join_call(RAYO_CALL(call), session, node, call_uri, iks_find_attrib(join, "media"));
response = join_call(RAYO_CALL(call), session, msg, call_uri, iks_find_attrib(join, "media"));
}
done:
@@ -1868,12 +1901,13 @@ done:
* unjoin call to a bridge
* @param call the call that unjoined
* @param session the session
* @param node the unjoin request
* @param msg the unjoin request
* @param call_uri the b-leg xmpp URI
* @return the response
*/
static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *call_uri)
static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri)
{
iks *node = msg->payload;
iks *response = NULL;
const char *bleg_uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_BRIDGE_UUID_VARIABLE);
const char *bleg_uri = switch_core_session_sprintf(session, "xmpp:%s@%s", bleg_uuid ? bleg_uuid : "", RAYO_JID(globals.server));
@@ -1881,7 +1915,7 @@ static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session,
/* bleg must match call_uri */
if (!zstr(bleg_uri) && !strcmp(bleg_uri, call_uri)) {
/* unbridge call */
response = iks_new_iq_result(node);
call->pending_join_request = iks_copy(node);
switch_ivr_park_session(session);
} else {
/* not bridged or wrong b-leg URI */
@@ -1895,15 +1929,16 @@ static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session,
* unjoin call to a mixer
* @param call the call that unjoined
* @param session the session
* @param node the unjoin request
* @param msg the unjoin request
* @param mixer_name the mixer name
* @return the response
*/
static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *mixer_name)
static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *conf_member_id = switch_channel_get_variable(channel, "conference_member_id");
const char *conf_name = switch_channel_get_variable(channel, "conference_name");
iks *node = msg->payload;
iks *response = NULL;
/* not conferenced, or wrong conference */
@@ -1935,31 +1970,33 @@ done:
*/
static iks *on_rayo_unjoin(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
{
iks *node = msg->payload;
switch_core_session_t *session = (switch_core_session_t *)session_data;
iks *response = NULL;
iks *unjoin = iks_find(node, "unjoin");
iks *unjoin = iks_find(msg->payload, "unjoin");
const char *call_uri = iks_find_attrib(unjoin, "call-uri");
const char *mixer_name = iks_find_attrib(unjoin, "mixer-name");
if (!zstr(call_uri) && !zstr(mixer_name)) {
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST);
} else if (RAYO_CALL(call)->pending_join_request) {
/* need to let pending request finish first */
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending");
} else if (!RAYO_CALL(call)->joined) {
/* not joined to anything */
response = iks_new_error(node, STANZA_ERROR_SERVICE_UNAVAILABLE);
response = iks_new_error(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE);
} else if (!zstr(call_uri)) {
response = unjoin_call(RAYO_CALL(call), session, node, call_uri);
response = unjoin_call(RAYO_CALL(call), session, msg, call_uri);
} else if (!zstr(mixer_name)) {
response = unjoin_mixer(RAYO_CALL(call), session, node, mixer_name);
response = unjoin_mixer(RAYO_CALL(call), session, msg, mixer_name);
} else {
/* unjoin everything */
if (RAYO_CALL(call)->joined == JOINED_MIXER) {
response = unjoin_mixer(RAYO_CALL(call), session, node, RAYO_CALL(call)->joined_id);
response = unjoin_mixer(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id);
} else if (RAYO_CALL(call)->joined == JOINED_CALL) {
response = unjoin_call(RAYO_CALL(call), session, node, RAYO_CALL(call)->joined_id);
response = unjoin_call(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id);
} else {
/* shouldn't happen */
response = iks_new_error(node, STANZA_ERROR_INTERNAL_SERVER_ERROR);
response = iks_new_error(msg->payload, STANZA_ERROR_INTERNAL_SERVER_ERROR);
}
}
@@ -2661,16 +2698,29 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev
struct rayo_call *b_call;
if (call) {
/* send A-leg event */
iks *revent = iks_new_presence("joined", RAYO_NS,
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
iks *joined = iks_find(revent, "joined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
iks *revent;
iks *joined;
call->joined = JOINED_CALL;
call->joined_id = switch_core_strdup(RAYO_POOL(call), b_uuid);
/* send IQ result to client now. */
switch_mutex_lock(RAYO_ACTOR(call)->mutex);
if (call->pending_join_request) {
iks *result = iks_new_iq_result(call->pending_join_request);
RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result);
iks_delete(call->pending_join_request);
call->pending_join_request = NULL;
}
switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
/* send A-leg event */
revent = iks_new_presence("joined", RAYO_NS,
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
joined = iks_find(revent, "joined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
/* send B-leg event */
@@ -2703,17 +2753,30 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t *
struct rayo_call *b_call;
if (call) {
/* send A-leg event */
iks *revent = iks_new_presence("unjoined", RAYO_NS,
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
iks *joined = iks_find(revent, "unjoined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
iks *revent;
iks *joined;
call->joined = 0;
call->joined_id = NULL;
/* send IQ result to client now. */
switch_mutex_lock(RAYO_ACTOR(call)->mutex);
if (call->pending_join_request) {
iks *result = iks_new_iq_result(call->pending_join_request);
RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result);
iks_delete(call->pending_join_request);
call->pending_join_request = NULL;
}
switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
/* send A-leg event */
revent = iks_new_presence("unjoined", RAYO_NS,
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
joined = iks_find(revent, "unjoined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
/* send B-leg event */
b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid);
if (b_call) {
@@ -642,7 +642,7 @@ static switch_status_t fileman_file_open(switch_file_handle_t *handle, const cha
switch_mutex_unlock(fileman_globals.mutex);
context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL);
switch_zmalloc(context->abuf, FILE_STARTBYTES);
switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf));
if (!context->fh.audio_buffer) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n");
+1 -1
View File
@@ -435,7 +435,7 @@ static const char usage[] =
"\t-version -- print the version and exit\n"
"\t-rp -- enable high(realtime) priority settings\n"
"\t-lp -- enable low priority settings\n"
"\t-np -- enable normal priority settings (system defaults)\n"
"\t-np -- enable normal priority settings\n"
"\t-vg -- run under valgrind\n"
"\t-nosql -- disable internal sql scoreboard\n"
"\t-heavy-timer -- Heavy Timer, possibly more accurate but at a cost\n"
+6 -6
View File
@@ -717,7 +717,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_connect(switch_socket_t *sock, swi
SWITCH_DECLARE(switch_status_t) switch_socket_send(switch_socket_t *sock, const char *buf, switch_size_t *len)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
int status = SWITCH_STATUS_SUCCESS;
switch_size_t req = *len, wrote = 0, need = *len;
int to_count = 0;
@@ -737,7 +737,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_send(switch_socket_t *sock, const
}
*len = wrote;
return status;
return (switch_status_t)status;
}
SWITCH_DECLARE(switch_status_t) switch_socket_send_nonblock(switch_socket_t *sock, const char *buf, switch_size_t *len)
@@ -760,7 +760,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_sendto(switch_socket_t *sock, swit
SWITCH_DECLARE(switch_status_t) switch_socket_recv(switch_socket_t *sock, char *buf, switch_size_t *len)
{
switch_status_t r;
int r;
r = apr_socket_recv(sock, buf, len);
@@ -768,7 +768,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_recv(switch_socket_t *sock, char *
r = SWITCH_STATUS_BREAK;
}
return r;
return (switch_status_t)r;
}
SWITCH_DECLARE(switch_status_t) switch_sockaddr_create(switch_sockaddr_t **sa, switch_memory_pool_t *pool)
@@ -866,7 +866,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_atmark(switch_socket_t *sock, int
SWITCH_DECLARE(switch_status_t) switch_socket_recvfrom(switch_sockaddr_t *from, switch_socket_t *sock, int32_t flags, char *buf, size_t *len)
{
apr_status_t r = SWITCH_STATUS_GENERR;
int r = SWITCH_STATUS_GENERR;
if (from && sock && (r = apr_socket_recvfrom(from, sock, flags, buf, len)) == APR_SUCCESS) {
from->port = ntohs(from->sa.sin.sin_port);
@@ -879,7 +879,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_recvfrom(switch_sockaddr_t *from,
r = SWITCH_STATUS_BREAK;
}
return r;
return (switch_status_t)r;
}
/* poll stubs */
+8 -7
View File
@@ -798,7 +798,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch
if (h.words == 0) {
sql = switch_mprintf("select distinct name from interfaces where type='api' and name like '%q%%' and hostname='%q' order by name",
buf, switch_core_get_switchname());
buf, switch_core_get_hostname());
}
if (sql) {
@@ -826,7 +826,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch
if (h.words == 0) {
stream.write_function(&stream, "select distinct a1 from complete where " "a1 not in (select name from interfaces where hostname='%s') %s ",
switch_core_get_switchname(), argc ? "and" : "");
switch_core_get_hostname(), argc ? "and" : "");
} else {
if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) {
stream.write_function(&stream, "select distinct a%d,'%q','%q' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp));
@@ -855,7 +855,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch
}
}
stream.write_function(&stream, " and hostname='%s' order by a%d", switch_core_get_switchname(), h.words + 1);
stream.write_function(&stream, " and hostname='%s' order by a%d", switch_core_get_hostname(), h.words + 1);
switch_cache_db_execute_sql_callback(db, stream.data, comp_callback, &h, &errmsg);
@@ -1859,7 +1859,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string)
}
}
}
mystream.write_function(&mystream, " '%s')", switch_core_get_switchname());
mystream.write_function(&mystream, " '%s')", switch_core_get_hostname());
switch_core_sql_exec(mystream.data);
status = SWITCH_STATUS_SUCCESS;
} else if (!strcasecmp(argv[0], "add")) {
@@ -1875,14 +1875,15 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string)
}
}
}
mystream.write_function(&mystream, " '%s')", switch_core_get_switchname());
mystream.write_function(&mystream, " '%s')", switch_core_get_hostname());
switch_core_sql_exec(mystream.data);
status = SWITCH_STATUS_SUCCESS;
} else if (!strcasecmp(argv[0], "del")) {
char *what = argv[1];
if (!strcasecmp(what, "*")) {
switch_core_sql_exec("delete from complete");
mystream.write_function(&mystream, "delete from complete where hostname='%s'", switch_core_get_hostname());
switch_core_sql_exec(mystream.data);
} else {
mystream.write_function(&mystream, "delete from complete where ");
for (x = 0; x < argc - 1; x++) {
@@ -1892,7 +1893,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string)
mystream.write_function(&mystream, "a%d = '%w'%w", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and ");
}
}
mystream.write_function(&mystream, " and hostname='%s'", switch_core_get_switchname());
mystream.write_function(&mystream, " and hostname='%s'", switch_core_get_hostname());
switch_core_sql_exec(mystream.data);
}
status = SWITCH_STATUS_SUCCESS;
+5 -2
View File
@@ -1659,6 +1659,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
runtime.console = stdout;
}
SSL_library_init();
switch_ssl_init_ssl_locks();
switch_curl_init();
@@ -1792,6 +1793,7 @@ static void switch_load_core_config(const char *file)
switch_core_hash_insert(runtime.ptimes, "isac", &d_30);
switch_core_hash_insert(runtime.ptimes, "G723", &d_30);
if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) {
switch_xml_t settings, param;
@@ -1964,7 +1966,7 @@ static void switch_load_core_config(const char *file)
} else if (!strcasecmp(var, "tipping-point") && !zstr(val)) {
runtime.tipping_point = atoi(val);
} else if (!strcasecmp(var, "events-use-dispatch") && !zstr(val)) {
runtime.events_use_dispatch = 1;
runtime.events_use_dispatch = switch_true(val);
} else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) {
int tmp;
@@ -2086,6 +2088,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t
}
runtime.runlevel++;
runtime.events_use_dispatch = 1;
switch_core_set_signal_handlers();
switch_load_network_lists(SWITCH_FALSE);
@@ -2611,7 +2614,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
switch_nat_shutdown();
}
switch_xml_destroy();
switch_core_session_uninit();
switch_console_shutdown();
switch_channel_global_uninit();
@@ -2621,6 +2623,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
switch_log_shutdown();
switch_core_session_uninit();
switch_core_unset_variables();
switch_core_memory_stop();
+12 -3
View File
@@ -39,7 +39,7 @@
SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, const char *func, int line,
switch_file_handle_t *fh,
const char *file_path,
uint8_t channels, uint32_t rate, unsigned int flags, switch_memory_pool_t *pool)
uint32_t channels, uint32_t rate, unsigned int flags, switch_memory_pool_t *pool)
{
char *ext;
switch_status_t status = SWITCH_STATUS_FALSE;
@@ -292,7 +292,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh,
rlen = asis ? fh->pre_buffer_datalen : fh->pre_buffer_datalen / 2;
if (switch_buffer_inuse(fh->pre_buffer) < rlen * 2) {
if ((status = fh->file_interface->file_read(fh, fh->pre_buffer_data, &rlen)) != SWITCH_STATUS_SUCCESS || !rlen) {
if ((status = fh->file_interface->file_read(fh, fh->pre_buffer_data, &rlen)) == SWITCH_STATUS_BREAK) {
return SWITCH_STATUS_BREAK;
}
if (status != SWITCH_STATUS_SUCCESS || !rlen) {
switch_set_flag(fh, SWITCH_FILE_BUFFER_DONE);
} else {
fh->samples_in += rlen;
@@ -316,7 +321,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh,
} else {
if ((status = fh->file_interface->file_read(fh, data, len)) != SWITCH_STATUS_SUCCESS || !*len) {
if ((status = fh->file_interface->file_read(fh, data, len)) == SWITCH_STATUS_BREAK) {
return SWITCH_STATUS_BREAK;
}
if (status != SWITCH_STATUS_SUCCESS || !*len) {
switch_set_flag(fh, SWITCH_FILE_DONE);
goto top;
}
+1 -1
View File
@@ -773,7 +773,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0);
}
if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
if (read_frame->datalen && (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen))) {
status = SWITCH_STATUS_MEMERR;
goto done;
}
+67 -16
View File
@@ -721,6 +721,10 @@ static const char *message_names[] = {
"AUDIO_DATA",
"BLIND_TRANSFER_RESPONSE",
"STUN_ERROR",
"MEDIA_RENEG",
"ANSWER_EVENT",
"PROGRESS_EVENT",
"RING_EVENT",
"INVALID"
};
@@ -1390,7 +1394,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
switch_channel_get_name((*session)->channel), switch_channel_state_name(switch_channel_get_state((*session)->channel)));
switch_core_session_reset(*session, TRUE, SWITCH_TRUE);
switch_core_session_reset(*session, SWITCH_TRUE, SWITCH_TRUE);
switch_core_media_bug_remove_all(*session);
switch_ivr_deactivate_unicast(*session);
@@ -1584,6 +1588,7 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_worker(switch_th
int check = 0;
switch_mutex_lock(session_manager.mutex);
session_manager.starting--;
session_manager.running++;
switch_mutex_unlock(session_manager.mutex);
#ifdef DEBUG_THREAD_POOL
@@ -1678,6 +1683,33 @@ static void thread_launch_failure(void)
switch_mutex_unlock(session_manager.mutex);
}
static int wake_queue(void)
{
switch_status_t status;
int tries = 0;
top:
status = switch_mutex_trylock(session_manager.cond_mutex);
if (status == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(session_manager.cond);
switch_mutex_unlock(session_manager.cond_mutex);
return 1;
} else {
if (switch_mutex_trylock(session_manager.cond2_mutex) == SWITCH_STATUS_SUCCESS) {
switch_mutex_unlock(session_manager.cond2_mutex);
} else {
if (++tries < 10) {
switch_cond_next();
goto top;
}
}
}
return 0;
}
static switch_status_t check_queue(void)
{
switch_status_t status = SWITCH_STATUS_FALSE;
@@ -1686,7 +1718,7 @@ static switch_status_t check_queue(void)
switch_mutex_lock(session_manager.mutex);
ttl = switch_queue_size(session_manager.thread_queue);
x = (session_manager.running - session_manager.busy);
x = ((session_manager.running + session_manager.starting) - session_manager.busy);
switch_mutex_unlock(session_manager.mutex);
@@ -1713,6 +1745,10 @@ static switch_status_t check_queue(void)
} else {
status = SWITCH_STATUS_SUCCESS;
}
switch_mutex_lock(session_manager.mutex);
session_manager.starting++;
switch_mutex_unlock(session_manager.mutex);
x++;
}
@@ -1722,12 +1758,20 @@ static switch_status_t check_queue(void)
static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_manager(switch_thread_t *thread, void *obj)
{
int x = 0;
uint32_t sleep = 10000000;
switch_time_t next = switch_micro_time_now() + sleep;
switch_mutex_lock(session_manager.cond_mutex);
while(session_manager.ready) {
switch_yield(100000);
int check = 1;
if (++x == 300) {
switch_mutex_lock(session_manager.cond2_mutex);
switch_thread_cond_timedwait(session_manager.cond, session_manager.cond_mutex, sleep);
switch_mutex_unlock(session_manager.cond2_mutex);
if (switch_micro_time_now() >= next) {
if (session_manager.popping) {
#ifdef DEBUG_THREAD_POOL
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10,
@@ -1735,17 +1779,20 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_manager(switch_t
#endif
switch_queue_interrupt_all(session_manager.thread_queue);
x--;
continue;
sleep = 100000;
check = 0;
} else {
x = 0;
sleep = 10000000;
}
}
check_queue();
if (check) check_queue();
next = switch_micro_time_now() + sleep;
}
switch_mutex_unlock(session_manager.cond_mutex);
while(session_manager.running) {
switch_queue_interrupt_all(session_manager.thread_queue);
switch_yield(20000);
@@ -1766,7 +1813,7 @@ SWITCH_DECLARE(switch_status_t) switch_thread_pool_launch_thread(switch_thread_d
*tdp = NULL;
switch_queue_push(session_manager.thread_queue, td);
check_queue();
wake_queue();
return status;
}
@@ -1789,7 +1836,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_thread_pool_launch(switch_co
td->obj = session;
td->func = switch_core_session_thread;
switch_queue_push(session_manager.thread_queue, td);
check_queue();
wake_queue();
}
switch_mutex_unlock(session->mutex);
@@ -2434,11 +2481,14 @@ void switch_core_session_init(switch_memory_pool_t *pool)
switch_threadattr_t *thd_attr;
switch_mutex_init(&session_manager.mutex, SWITCH_MUTEX_NESTED, session_manager.memory_pool);
switch_thread_cond_create(&session_manager.cond, session_manager.memory_pool);
switch_mutex_init(&session_manager.cond_mutex, SWITCH_MUTEX_NESTED, session_manager.memory_pool);
switch_mutex_init(&session_manager.cond2_mutex, SWITCH_MUTEX_NESTED, session_manager.memory_pool);
switch_queue_create(&session_manager.thread_queue, 100000, session_manager.memory_pool);
switch_threadattr_create(&thd_attr, session_manager.memory_pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&session_manager.manager_thread, thd_attr, switch_core_session_thread_pool_manager, NULL, session_manager.memory_pool);
session_manager.ready = 1;
switch_thread_create(&session_manager.manager_thread, thd_attr, switch_core_session_thread_pool_manager, NULL, session_manager.memory_pool);
}
}
@@ -2448,15 +2498,16 @@ void switch_core_session_uninit(void)
int sanity = 100;
switch_status_t st = SWITCH_STATUS_FALSE;
switch_core_hash_destroy(&session_manager.session_table);
session_manager.ready = 0;
switch_thread_join(&st, session_manager.manager_thread);
wake_queue();
while(session_manager.running && --sanity > 0) {
switch_queue_interrupt_all(session_manager.thread_queue);
switch_yield(100000);
}
switch_thread_join(&st, session_manager.manager_thread);
switch_core_hash_destroy(&session_manager.session_table);
}
+20 -10
View File
@@ -2012,7 +2012,7 @@ static void core_event_handler(switch_event_t *event)
new_sql() = switch_mprintf("insert into tasks values(%q,'%q','%q',%q, '%q')",
id,
switch_event_get_header_nil(event, "task-desc"),
switch_event_get_header_nil(event, "task-group"), manager ? manager : "0", switch_core_get_switchname()
switch_event_get_header_nil(event, "task-group"), manager ? manager : "0", switch_core_get_hostname()
);
}
}
@@ -2020,7 +2020,7 @@ static void core_event_handler(switch_event_t *event)
case SWITCH_EVENT_DEL_SCHEDULE:
case SWITCH_EVENT_EXE_SCHEDULE:
new_sql() = switch_mprintf("delete from tasks where task_id=%q and hostname='%q'",
switch_event_get_header_nil(event, "task-id"), switch_core_get_switchname());
switch_event_get_header_nil(event, "task-id"), switch_core_get_hostname());
break;
case SWITCH_EVENT_RE_SCHEDULE:
{
@@ -2031,7 +2031,7 @@ static void core_event_handler(switch_event_t *event)
new_sql() = switch_mprintf("update tasks set task_desc='%q',task_group='%q', task_sql_manager=%q where task_id=%q and hostname='%q'",
switch_event_get_header_nil(event, "task-desc"),
switch_event_get_header_nil(event, "task-group"), manager ? manager : "0", id,
switch_core_get_switchname());
switch_core_get_hostname());
}
}
break;
@@ -2317,7 +2317,7 @@ static void core_event_handler(switch_event_t *event)
new_sql() = switch_mprintf("delete from channels where hostname='%q';"
"delete from interfaces where hostname='%q';"
"delete from calls where hostname='%q'",
switch_core_get_switchname(), switch_core_get_switchname(), switch_core_get_switchname()
switch_core_get_switchname(), switch_core_get_hostname(), switch_core_get_switchname()
);
break;
case SWITCH_EVENT_LOG:
@@ -2335,7 +2335,7 @@ static void core_event_handler(switch_event_t *event)
switch_mprintf
("insert into interfaces (type,name,description,syntax,ikey,filename,hostname) values('%q','%q','%q','%q','%q','%q','%q')", type, name,
switch_str_nil(description), switch_str_nil(syntax), switch_str_nil(key), switch_str_nil(filename),
switch_core_get_switchname()
switch_core_get_hostname()
);
}
break;
@@ -2346,7 +2346,7 @@ static void core_event_handler(switch_event_t *event)
const char *name = switch_event_get_header_nil(event, "name");
if (!zstr(type) && !zstr(name)) {
new_sql() = switch_mprintf("delete from interfaces where type='%q' and name='%q' and hostname='%q'", type, name,
switch_core_get_switchname());
switch_core_get_hostname());
}
break;
}
@@ -2369,12 +2369,12 @@ static void core_event_handler(switch_event_t *event)
if (!strcmp("add", op)) {
new_sql() = switch_mprintf("insert into nat (port, proto, sticky, hostname) values (%s, %s, %d,'%q')",
switch_event_get_header_nil(event, "port"),
switch_event_get_header_nil(event, "proto"), sticky, switch_core_get_switchname()
switch_event_get_header_nil(event, "proto"), sticky, switch_core_get_hostname()
);
} else if (!strcmp("del", op)) {
new_sql() = switch_mprintf("delete from nat where port=%s and proto=%s and hostname='%q'",
switch_event_get_header_nil(event, "port"),
switch_event_get_header_nil(event, "proto"), switch_core_get_switchname());
switch_event_get_header_nil(event, "proto"), switch_core_get_hostname());
} else if (!strcmp("status", op)) {
/* call show nat api */
} else if (!strcmp("status_response", op)) {
@@ -3106,7 +3106,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
case SCDB_TYPE_ODBC:
if (switch_test_flag((&runtime), SCF_CLEAR_SQL)) {
char sql[512] = "";
char *tables[] = { "channels", "calls", "interfaces", "tasks", NULL };
char *tables[] = { "channels", "calls", "tasks", NULL };
int i;
const char *hostname = switch_core_get_switchname();
@@ -3265,8 +3265,18 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
break;
}
if (switch_test_flag((&runtime), SCF_CLEAR_SQL)) {
char sql[512] = "";
char *tables[] = { "complete", "interfaces", NULL };
int i;
const char *hostname = switch_core_get_hostname();
for (i = 0; tables[i]; i++) {
switch_snprintfv(sql, sizeof(sql), "delete from %q where hostname='%q'", tables[i], hostname);
switch_cache_db_execute_sql(sql_manager.dbh, sql, NULL);
}
}
switch_cache_db_execute_sql(sql_manager.dbh, "delete from complete where sticky=0", NULL);
switch_cache_db_execute_sql(sql_manager.dbh, "delete from aliases where sticky=0", NULL);
switch_cache_db_execute_sql(sql_manager.dbh, "delete from nat where sticky=0", NULL);
switch_cache_db_execute_sql(sql_manager.dbh, "create index alias1 on aliases (alias)", NULL);
+24 -19
View File
@@ -571,6 +571,25 @@ SWITCH_DECLARE(switch_status_t) switch_event_shutdown(void)
return SWITCH_STATUS_SUCCESS;
}
static void check_dispatch(void)
{
if (!EVENT_DISPATCH_QUEUE) {
switch_mutex_lock(BLOCK);
if (!EVENT_DISPATCH_QUEUE) {
switch_queue_create(&EVENT_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN * MAX_DISPATCH, THRUNTIME_POOL);
switch_event_launch_dispatch_threads(1);
while (!THREAD_COUNT) {
switch_cond_next();
}
}
switch_mutex_unlock(BLOCK);
}
}
SWITCH_DECLARE(void) switch_event_launch_dispatch_threads(uint32_t max)
{
switch_threadattr_t *thd_attr;
@@ -580,6 +599,8 @@ SWITCH_DECLARE(void) switch_event_launch_dispatch_threads(uint32_t max)
switch_memory_pool_t *pool = RUNTIME_POOL;
check_dispatch();
if (max > MAX_DISPATCH) {
return;
}
@@ -644,30 +665,12 @@ SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool)
switch_find_local_ip(guess_ip_v6, sizeof(guess_ip_v6), NULL, AF_INET6);
//switch_queue_create(&EVENT_QUEUE[0], POOL_COUNT_MAX + 10, THRUNTIME_POOL);
//switch_queue_create(&EVENT_QUEUE[1], POOL_COUNT_MAX + 10, THRUNTIME_POOL);
//switch_queue_create(&EVENT_QUEUE[2], POOL_COUNT_MAX + 10, THRUNTIME_POOL);
#ifdef SWITCH_EVENT_RECYCLE
switch_queue_create(&EVENT_RECYCLE_QUEUE, 250000, THRUNTIME_POOL);
switch_queue_create(&EVENT_HEADER_RECYCLE_QUEUE, 250000, THRUNTIME_POOL);
#endif
//switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
if (runtime.events_use_dispatch) {
switch_queue_create(&EVENT_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN * MAX_DISPATCH, pool);
switch_event_launch_dispatch_threads(1);
}
//switch_thread_create(&EVENT_QUEUE_THREADS[0], thd_attr, switch_event_thread, EVENT_QUEUE[0], RUNTIME_POOL);
//switch_thread_create(&EVENT_QUEUE_THREADS[1], thd_attr, switch_event_thread, EVENT_QUEUE[1], RUNTIME_POOL);
//switch_thread_create(&EVENT_QUEUE_THREADS[2], thd_attr, switch_event_thread, EVENT_QUEUE[2], RUNTIME_POOL);
if (runtime.events_use_dispatch) {
while (!THREAD_COUNT) {
switch_cond_next();
}
}
check_dispatch();
switch_mutex_lock(EVENT_QUEUE_MUTEX);
SYSTEM_RUNNING = 1;
@@ -1921,6 +1924,8 @@ SWITCH_DECLARE(switch_status_t) switch_event_fire_detailed(const char *file, con
if (runtime.events_use_dispatch) {
check_dispatch();
if (switch_event_queue_dispatch_event(event) != SWITCH_STATUS_SUCCESS) {
switch_event_destroy(event);
return SWITCH_STATUS_FALSE;
+9 -8
View File
@@ -1204,20 +1204,21 @@ static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, s
switch_channel_set_variable(channel, "RECORD_DISCARDED", "true");
switch_file_remove(rh->file, switch_core_session_get_pool(session));
}
}
if (read_impl.actual_samples_per_second) {
switch_channel_set_variable_printf(channel, "record_seconds", "%d", rh->fh->samples_out / read_impl.actual_samples_per_second);
switch_channel_set_variable_printf(channel, "record_ms", "%d", rh->fh->samples_out / (read_impl.actual_samples_per_second / 1000));
}
switch_channel_set_variable_printf(channel, "record_samples", "%d", rh->fh->samples_out);
}
if (switch_event_create(&event, SWITCH_EVENT_RECORD_STOP) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", rh->file);
switch_event_fire(&event);
}
if (read_impl.actual_samples_per_second) {
switch_channel_set_variable_printf(channel, "record_seconds", "%d", rh->fh->samples_out / read_impl.actual_samples_per_second);
switch_channel_set_variable_printf(channel, "record_ms", "%d", rh->fh->samples_out / (read_impl.actual_samples_per_second / 1000));
}
switch_channel_set_variable_printf(channel, "record_samples", "%d", rh->fh->samples_out);
switch_channel_execute_on(channel, SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE);
if ((var = switch_channel_get_variable(channel, SWITCH_RECORD_POST_PROCESS_EXEC_API_VARIABLE))) {
+3
View File
@@ -1122,6 +1122,9 @@ static switch_status_t signal_bridge_on_hangup(switch_core_session_t *session)
}
switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
} else {
if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
switch_channel_handle_cause(other_channel, switch_channel_get_cause(channel));
}
switch_channel_set_state(other_channel, CS_EXECUTE);
}
} else {
+2 -2
View File
@@ -927,7 +927,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error!\n");
if (caller_channel) {
switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
switch_channel_hangup(caller_channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL);
}
read_codec = NULL;
goto done;
@@ -1254,7 +1254,7 @@ static switch_status_t setup_ringback(originate_global_t *oglobals, originate_st
switch_core_session_set_read_codec(oglobals->session, write_codec);
} else {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_ERROR, "Codec Error!\n");
switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
switch_channel_hangup(caller_channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL);
read_codec = NULL;
switch_goto_status(SWITCH_STATUS_BREAK, end);
}
+22 -3
View File
@@ -1049,6 +1049,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
int more_data = 0;
switch_event_t *event;
uint32_t test_native = 0, last_native = 0;
uint32_t buflen = 0;
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
@@ -1110,6 +1111,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
fh->samples = 0;
}
for (cur = 0; switch_channel_ready(channel) && !done && cur < argc; cur++) {
file = argv[cur];
eof = 0;
@@ -1255,9 +1259,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
if (!abuf) {
switch_zmalloc(abuf, FILE_STARTSAMPLES * sizeof(*abuf));
buflen = write_frame.buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->channels;
switch_zmalloc(abuf, write_frame.buflen);
write_frame.data = abuf;
write_frame.buflen = FILE_STARTSAMPLES;
}
if (sample_start > 0) {
@@ -1454,6 +1458,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
}
}
buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->cur_channels;
if (buflen > write_frame.buflen) {
abuf = realloc(abuf, buflen);
write_frame.data = abuf;
write_frame.buflen = buflen;
}
if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
if (framelen > FILE_STARTSAMPLES) {
framelen = FILE_STARTSAMPLES;
@@ -1493,6 +1505,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
} else {
switch_status_t rstatus;
if (eof) {
break;
}
@@ -1500,7 +1514,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
olen /= 2;
}
if (switch_core_file_read(fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
switch_set_flag(fh, SWITCH_FILE_BREAK_ON_CHANGE);
if ((rstatus = switch_core_file_read(fh, abuf, &olen)) == SWITCH_STATUS_BREAK) {
continue;
}
if (rstatus != SWITCH_STATUS_SUCCESS) {
eof++;
continue;
}
+13 -10
View File
@@ -3961,6 +3961,10 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
if (*bytes) {
rtp_session->missed_count = 0;
}
if (check_rtcp_and_ice(rtp_session) == -1) {
return SWITCH_STATUS_GENERR;
}
@@ -4641,7 +4645,15 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
ret = -1;
goto end;
}
if (rtp_session->max_missed_packets && read_loops == 1 && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
if (bytes) {
rtp_session->missed_count = 0;
} else if (++rtp_session->missed_count >= rtp_session->max_missed_packets) {
ret = -2;
goto end;
}
}
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "Read bytes (%i) %ld\n", status, bytes);
@@ -4837,15 +4849,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
goto end;
}
if (rtp_session->max_missed_packets && read_loops == 1 && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
if (bytes) {
rtp_session->missed_count = 0;
} else if (++rtp_session->missed_count >= rtp_session->max_missed_packets) {
ret = -2;
goto end;
}
}
check = !bytes;
if (rtp_session->flags[SWITCH_RTP_FLAG_FLUSH]) {
Executable
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/perl
my $pager = `which less` || `which more`;
my $tmpdir = "/tmp/FSJIRA";
system("mkdir -p $tmpdir");
my $cmd = "git log " . join(" ", @ARGV);
open(CMD, "$cmd |");
open(PAGER, "|$pager");
select PAGER;
while(my $line = <CMD>) {
print $line;
if ($line =~ /([A-Z]+\-[0-9]+)/) {
my $bug = $1;
my $txt = bugtxt($bug);
if ($txt) {
print "=" x 80 . "\n";
print $txt;
print "=" x 80 . "\n";
}
}
}
close(CMD);
close(PAGER);
sub catfile($) {
my $file = shift;
open(I, $file) or return;
$/ = undef;
my $txt = <I>;
$/ = "\n";
close(I);
return $txt;
}
sub bugtxt($)
{
my $bug = shift or return "";
my $now = time;
my $tmp;
$bug =~ s/\.\.//g;
$bug =~ s/^\///g;
$bug =~ s/~//g;
$bug =~ s/[^a-zA-Z0-9\-]//g;
$tmp = "$tmpdir/$bug.txt";
if(-f $tmp) {
return catfile($tmp);
}
my $cmd = "wget -q http://jira.freeswitch.org/si/jira.issueviews:issue-xml/$bug/$bug.xml -O $tmp";
system($cmd);
my $txt = catfile($tmp);
my ($a,$title) = $txt =~ /\<title\>(.*?)\<\/title\>/smg;
my ($status) = $txt =~ /\<status.*?\>(.*?)\<\/status\>/smg;
my ($a,$des) = $txt =~ /\<description\>(.*?)\<\/description\>/smg;
my ($alogin, $aname) = $txt =~ /\<assignee username=\"([^\"]+)\"\>(.*?)\<\/assignee\>/smg;
my ($rlogin, $rname) = $txt =~ /\<reporter username=\"([^\"]+)\"\>(.*?)\<\/reporter\>/smg;
if ($rname && $aname) {
my $data = "$title\nReporter: $rname [$rlogin]\nAssignee: $aname [$alogin]\nStatus: $status\nhttp://jira.freeswitch.org/browse/$bug\n";
open(O, ">$tmp");
print O $data;
close(O);
return $data;
} else {
unlink($tmp);
}
}