mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 12:42:02 +00:00
Merge branch 'master' into v1.4.beta
This commit is contained in:
@@ -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
@@ -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])
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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 @@
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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, &[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(&[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(&[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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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, &[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(&[len], 0, (max_len - len)*sizeof(int16_t));
|
||||
len = max_len;
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
@@ -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, &[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(&[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(&[len], 0, (required_len - len)*sizeof(int16_t));
|
||||
/*endif*/
|
||||
write(s->audio.modems.audio_tx_log, amp, required_len*sizeof(int16_t));
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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";
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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]))
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user