From 90c156243c89f582d242f13f332a6360659812e6 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 10:10:26 -0600 Subject: [PATCH 01/97] FS-2862: fix seg --- src/mod/endpoints/mod_sofia/sofia.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index e749abdc01..580334a46f 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5959,7 +5959,9 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t /* Barf if we didn't get our private */ assert(switch_core_session_get_private(session)); - if (!strncasecmp(sip->sip_content_type->c_type, "message", 7) && !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { + if (sip->sip_content_type && + !strncasecmp(sip->sip_content_type->c_type, "message", 7) && + !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { sofia_update_callee_id(session, profile, sip, SWITCH_TRUE); goto end; } From cf398e1a442bc54c05d68837fcad6258cecc7dfe Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 14:59:25 -0600 Subject: [PATCH 02/97] FS-535: tested but please test MORE. --- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia_glue.c | 36 +++++++++++++++++++++++- src/mod/endpoints/mod_sofia/sofia_reg.c | 33 +++++++++++++++++++--- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 750fb60c15..c1244c05f1 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -957,6 +957,7 @@ void sofia_presence_event_thread_start(void); void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot); switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt, int force); switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force); +char *sofia_glue_get_register_host(const char *uri); const char *sofia_glue_strip_proto(const char *uri); switch_status_t reconfig_sofia(sofia_profile_t *profile); void sofia_glue_del_gateway(sofia_gateway_t *gp); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index fa828607bd..23d3f2904e 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5734,6 +5734,41 @@ char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex return ret; } +char *sofia_glue_get_register_host(const char *uri) +{ + char *register_host = NULL; + const char *s; + char *p = NULL; + + if ((s = switch_stristr("sip:", uri))) { + s += 4; + } else if ((s = switch_stristr("sips:", uri))) { + s += 5; + } + + if (!s) { + return NULL; + } + + register_host = strdup(s); + + /* remove port for register_host for testing nat acl take into account + ipv6 addresses which are required to have brackets around the addr + */ + if ((p = strchr(register_host, ']')) && (*(p + 1) == ':')) { + *(p + 1) = '\0'; + } else { + if ((p = strrchr(register_host, ':'))) { + *p = '\0'; + } + } + + /* register_proxy should always start with "sip:" or "sips:" */ + assert(register_host); + + return register_host; +} + const char *sofia_glue_strip_proto(const char *uri) { char *p; @@ -5983,7 +6018,6 @@ void sofia_glue_tech_simplify(private_object_t *tech_pvt) } } - void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl) { switch_core_session_message_t *msg; diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 4bb879659c..14a7bfdd2c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -142,16 +142,22 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) int ss_state = nua_callstate_authenticating; sub_state_t ostate = gw_sub_ptr->state; char *user_via = NULL; + char *register_host = NULL; if (!now) { gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED; gw_sub_ptr->expires_str = "0"; } - if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) { + register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); + + /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ + if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } + switch_safe_free(register_host); + switch (ostate) { case SUB_STATE_NOSUB: break; @@ -189,7 +195,15 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private); if (now) { - nua_subscribe(gateway_ptr->sub_nh, NUTAG_URL(gateway_ptr->register_url), TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), SIPTAG_EVENT_STR(gw_sub_ptr->event), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type), SIPTAG_TO_STR(gateway_ptr->register_from), SIPTAG_FROM_STR(gateway_ptr->register_from), SIPTAG_CONTACT_STR(gateway_ptr->register_contact), SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str), // sofia stack bases its auto-refresh stuff on this + nua_subscribe(gateway_ptr->sub_nh, + NUTAG_URL(gateway_ptr->register_url), + TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), + SIPTAG_EVENT_STR(gw_sub_ptr->event), + SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type), + SIPTAG_TO_STR(gateway_ptr->register_from), + SIPTAG_FROM_STR(gateway_ptr->register_from), + SIPTAG_CONTACT_STR(gateway_ptr->register_contact), + SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str), /* sofia stack bases its auto-refresh stuff on this */ TAG_NULL()); gw_sub_ptr->retry = now + gw_sub_ptr->retry_seconds; } else { @@ -266,6 +280,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) { reg_state_t ostate = gateway_ptr->state; char *user_via = NULL; + char *register_host = NULL; if (!now) { gateway_ptr->state = ostate = REG_STATE_UNREGED; @@ -277,10 +292,15 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) nua_handle_t *nh = nua_handle(profile->nua, NULL, NUTAG_URL(gateway_ptr->register_url), TAG_END()); sofia_private_t *pvt; - if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) { + register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); + + /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ + if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } + switch_safe_free(register_host); + pvt = malloc(sizeof(*pvt)); switch_assert(pvt); memset(pvt, 0, sizeof(*pvt)); @@ -335,10 +355,15 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) sofia_reg_new_handle(gateway_ptr, now ? 1 : 0); } - if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) { + register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); + + /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ + if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } + switch_safe_free(register_host); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Registering %s\n", gateway_ptr->name); if (now) { From 22047f93377fac0c763934603001085428f74d3e Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 15:24:22 -0600 Subject: [PATCH 03/97] FS-2862: fix seg more --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 580334a46f..32d25d0ad6 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5959,7 +5959,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t /* Barf if we didn't get our private */ assert(switch_core_session_get_private(session)); - if (sip->sip_content_type && + if (sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type && !strncasecmp(sip->sip_content_type->c_type, "message", 7) && !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { sofia_update_callee_id(session, profile, sip, SWITCH_TRUE); From 87edbed6bbcdb351b9502f66e78b01116ae1ab00 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 15:32:23 -0600 Subject: [PATCH 04/97] FS-535: be more careful and catch ipv6 edge case --- src/mod/endpoints/mod_sofia/sofia_glue.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 23d3f2904e..57a2bfaa6a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5740,6 +5740,10 @@ char *sofia_glue_get_register_host(const char *uri) const char *s; char *p = NULL; + if (zstr(uri)) { + return NULL; + } + if ((s = switch_stristr("sip:", uri))) { s += 4; } else if ((s = switch_stristr("sips:", uri))) { @@ -5755,9 +5759,12 @@ char *sofia_glue_get_register_host(const char *uri) /* remove port for register_host for testing nat acl take into account ipv6 addresses which are required to have brackets around the addr */ - if ((p = strchr(register_host, ']')) && (*(p + 1) == ':')) { - *(p + 1) = '\0'; - } else { + + if ((p = strchr(register_host, ']'))) { + if (*(p + 1) == ':') { + *(p + 1) = '\0'; + } + } else { if ((p = strrchr(register_host, ':'))) { *p = '\0'; } From 89dbe0b0a09fa52f47f24884c969d1ed3ef6b6e8 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 17:06:59 -0600 Subject: [PATCH 05/97] ESL-52 --- .../event_handlers/mod_event_socket/mod_event_socket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index 941db22c84..ee7cfc9eaf 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -691,7 +691,7 @@ SWITCH_STANDARD_API(event_sink_function) switch_mutex_lock(listener->filter_mutex); if (!listener->filters) { - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } if (!strcasecmp(action, "delete")) { @@ -702,7 +702,7 @@ SWITCH_STANDARD_API(event_sink_function) if (!strcasecmp(header_val, "all")) { switch_event_destroy(&listener->filters); - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } else { switch_event_del_header(listener->filters, header_val); } @@ -1744,7 +1744,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even switch_mutex_lock(listener->filter_mutex); if (!listener->filters) { - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } if (!strcasecmp(header_name, "delete") && header_val) { @@ -1754,7 +1754,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even } if (!strcasecmp(header_name, "all")) { switch_event_destroy(&listener->filters); - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } else { switch_event_del_header_val(listener->filters, header_name, header_val); } From c109a89e4e81c57963c3cde28774243fce4203ed Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 22 Nov 2010 21:49:33 -0600 Subject: [PATCH 06/97] VS2010 fix initial build dependency --- libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj index c6aaba5cd6..b3931497c7 100644 --- a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj +++ b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj @@ -127,6 +127,11 @@ + + + {70a49bc2-7500-41d0-b75d-edcc5be987a0} + + From ec8f2c2bc2b65457ab6c6684769463f54125d62e Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Mon, 22 Nov 2010 22:00:36 -0800 Subject: [PATCH 07/97] scripts: add_user - cmd line utility that lets admin create new users very easily. --- scripts/perl/add_user | 306 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100755 scripts/perl/add_user diff --git a/scripts/perl/add_user b/scripts/perl/add_user new file mode 100755 index 0000000000..d16ebb5efe --- /dev/null +++ b/scripts/perl/add_user @@ -0,0 +1,306 @@ +#!/usr/bin/perl +# +# add_user +# +# Add one or more users to the XML directory +# +# + +use strict; +use warnings; +use Getopt::Long; +use Data::Dumper; + +## Useful items +my $path_sep; +my $config_path; +my @dir_elem; +my $user_template = &get_user_template; +my $new_user_count = 0; + +## Command line args +my $users; +my $domain; +my $dirpath; +my $help; + +## Misc items somewhat related to cmd line args +my $start; +my $end; +my $user; + +## Check for Windows vs. *nix +if ( $^O =~ m/^win/i ) { + ## Detected Windows (probably) + $path_sep = "\\"; # single backslash (\) + use File::Spec::Win32; +} else { + $path_sep = '/'; # single slash (/) + use File::Spec; +} + +GetOptions( + 'h' => \$help, + 'help' => \$help, + 'domain=s' => \$domain, + 'users=s' => \$users, + 'confpath=s' => \$config_path, +); + +if ( $help ) { + usage(); + exit(0); +} + +if ( ! $domain ) { + $domain='default'; +} + +## Validate users if specified on command line +if ( $users ) { + ($start,$end) = split /-/,$users; + if ( ! $start && ! $end ) { + die "Please specify both a start and end range, separated by a hyphen:\n add_user --users=xxxx-yyyy\n"; + } + + unless ( $start =~ m/[1-9]\d+/ ) { + die "Start of range '$start' is not numeric or is too short\n"; + } + + unless ( $end =~ m/[1-9]\d+/ ) { + die "End of range '$end' is not numberic or is too short\n"; + } + + if ( $end <= $start ) { + die "End of range needs to be greater than start of range\n"; + } +} else { + ## Look for user id in $ARGV[0] + if ( ! $ARGV[0] ) { + die "You must specify user id as a command line argument to add user, or use the --users option.\n"; + } + unless ( $ARGV[0] =~ m/^[1-9]\d+$/ ) { + die "User id must be numeric, be at least 2 digits long, and cannot begin with the digit zero.\n" + } + $user = $ARGV[0]; +} + +if ( ! $config_path ) { + $config_path = '/usr/local/freeswitch/conf'; +} + +## Check to make sure the directories in question exists +unless ( -d $config_path ) { + die "Configuration path '$config_path' does not exist.\n"; +} + +my $directory_path = $config_path . $path_sep . 'directory'; +unless ( -d $directory_path ) { + die "Directory path '$directory_path' does not exist.\n"; +} + +## Now check domain pathname and test existence +if ( ! $domain ) { + $domain = 'default'; +} + +## Full directory path includes the domain name +my $full_dir_path = $directory_path . $path_sep . $domain; +unless ( -d $full_dir_path ) { + die "Full path to directory and domain '$full_dir_path' does not exist. \n"; +} + +unless ( -w $full_dir_path ) { + die "This user does not have write access to '$full_dir_path'.\n"; +} +print "\n"; + +## Regexp assemble items to show user what a PCRE might look like for his new users +my $ra_present; +my $ra_new; +my $ra_all; +eval { require Regexp::Assemble; }; +if ( ! $@ ) { + ## If Regexp::Assemble is available flag it for later building regexes + $ra_present = 'true'; + $ra_new = Regexp::Assemble->new( # new user regex + reduce => 1, + flags => 0, +); + $ra_all = Regexp::Assemble->new( # all users regex w/ new users thrown in + reduce => 1, + flags => 0, +); +} + +## If we're this far then we can read in the existing users and put them in a hash +## Later we can check hash to avoid adding duplicate users +my %current_users; +my @CURRENT_USER_FILES = glob($full_dir_path . $path_sep . '*.xml'); +foreach ( @CURRENT_USER_FILES ) { + #print "User: $_\n"; + open(FILEIN,'<',$_); + while() { + next unless m/user id|number-alias/; + m/user id="(\d+)"/; + my $user_id = $1; + if ( ! $user_id ) { + m/alias="(\d+)"/; + $user_id = $1; + } + + next unless $user_id; + $current_users{$user_id}++; + + if ( $ra_present && $user_id =~ m/^\d+$/ ) { + #print "Adding $user_id to \$re_all...\n"; + $ra_all->add($user_id)->anchor_line_begin->anchor_line_end; + } + last; + } + close(FILEIN); +} + +#print Dumper(%current_users) . "\n"; +if ( $start && $end ) { + ## Add range of users + foreach $user ($start .. $end) { + &add_user($user); + } +} else { + ## Add single user + &add_user($user); +} + +print "\nOperation complete. "; +if ( $new_user_count == 0 ) { + print "No users added.\n"; + exit(0); +} else { + printf "%d user%s added.\n", $new_user_count, $new_user_count==1 ? "" : "s"; + print "Be sure to reloadxml.\n\n"; +} + +if ( $ra_present ) { + print "Regular expression information:\n\n"; + ## Regexp::Assemble adds some stuff we really don't need + ## These lines just make the regexp pattern a bit more readable + my $tmp = $ra_new->as_string; + $tmp =~ s/\?://g; + $tmp =~ s/^\(\?\-xism:\^/^(/; + $tmp =~ s/\$\)$/)\$/; + $tmp =~ s/\\d/[0-9]/g; # [0-9] is sometimes easier to read than \d + print " Sample regex for all new users: " . $tmp . "\n"; + $tmp = $ra_all->as_string; + $tmp =~ s/\?://g; + $tmp =~ s/^\(\?\-xism:\^/^(/; + $tmp =~ s/\$\)$/)\$/; + $tmp =~ s/\\d/[0-9]/g; # [0-9] is sometimes easier to read than \d + print "Sample regex for all new AND current users: " . $tmp . "\n\n"; + print "In the default configuration you can modify the expression in the condition for 'Local_Extension'.\n"; + print "" +} else { + print "If CPAN module Regexp::Assemble were installed this program would be able to suggest a regex for your new users.\n" +} + +exit(0); + +sub add_user { + my $user_id = shift; + if ( exists( $current_users{$user_id} ) ) { + warn "User id $user_id already exists, skipping...\n"; + } else { + my $new_user = $user_template; + $new_user =~ s/__USERID__/$user_id/g; + #print "Adding user id '$user_id' with this XML:\n"; + #print $new_user . "\n"; + + ## Attempt to create the user file + my $user_file_name = $full_dir_path . $path_sep . $user_id . '.xml'; + + ## Does it already exist? + if ( -f $user_file_name ) { + warn "$user_file_name exists, skipping...\n"; + } + my $fh; + open($fh,'>',$user_file_name); + if ( ! $fh ) { + warn "Unable to open '$user_file_name' - $!\n"; + warn "Skipping...\n"; + next; + } + + print $fh $new_user; + close($fh); + print "Added $user_id in file $user_file_name \n"; + $new_user_count++; + if ( $ra_present ) { + $ra_new->add($user_id)->anchor_line_begin->anchor_line_end; + $ra_all->add($user_id)->anchor_line_begin->anchor_line_end; + } + } + +} + +sub get_user_template { + my $templ = < + + + + + + + + + + + + + + + + + + +ENDUSERTEMPLATE + + return $templ; +} + +sub usage { + print < [--domain=] [--confpath=] + add_user --users=- [--domain=] [--confpath=] + +In its simplest form, add_user will simply add the user_id specified at the command line. +By default, users are added to the "default" domain. Use the --domain option to specify +a different domain for the user(s) that are added. + +To specify a range of user IDs use the --users option. Separate the beginning and +end of the range with a hyphen (-) character. + +By default add_user will look for the XML directory in its default location of +/usr/local/freeswitch/conf/directory. Use the --confpath (configuration path) +option to specify an alternate directory location. + + + NOTES: + +add_user assumes +User IDs must be numeric and cannot begin with zero. +User IDs must be at least two digits long and have no specific length limit. +If a user ID exists it will be skipped. +If a domain specified does not exist no users will be created. + +ENDUSAGE + +} From 38f994206f075acf461b399f0e512ec5795b0083 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 23 Nov 2010 09:54:50 -0600 Subject: [PATCH 08/97] FS-535: additional checks and use the right contact for registers inside and outside of nat --- src/mod/endpoints/mod_sofia/sofia.c | 34 +++++++++++++++++-------- src/mod/endpoints/mod_sofia/sofia_reg.c | 6 ++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 32d25d0ad6..4d992b0ea1 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2156,6 +2156,30 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) sipip = profile->sipip; } + gateway->extension = switch_core_strdup(gateway->pool, extension); + + + if (!strncasecmp(proxy, "sip:", 4)) { + gateway->register_proxy = switch_core_strdup(gateway->pool, proxy); + gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy + 4); + } else { + gateway->register_proxy = switch_core_sprintf(gateway->pool, "sip:%s", proxy); + gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy); + } + + /* This checks to make sure we provide the right contact on register for targets behind nat with us. */ + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { + char *register_host = NULL; + + register_host = sofia_glue_get_register_host(gateway->register_proxy); + + if (register_host && !sofia_glue_check_nat(profile, register_host)) { + sipip = profile->sipip; + } + + switch_safe_free(register_host); + } + if (extension_in_contact) { format = strchr(sipip, ':') ? "" : ""; gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension, @@ -2170,16 +2194,6 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) profile->tls_sip_port : profile->sip_port, params); } - gateway->extension = switch_core_strdup(gateway->pool, extension); - - if (!strncasecmp(proxy, "sip:", 4)) { - gateway->register_proxy = switch_core_strdup(gateway->pool, proxy); - gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy + 4); - } else { - gateway->register_proxy = switch_core_sprintf(gateway->pool, "sip:%s", proxy); - gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy); - } - gateway->expires_str = switch_core_strdup(gateway->pool, expire_seconds); if ((gateway->freq = atoi(gateway->expires_str)) < 5) { diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 14a7bfdd2c..7390378fc8 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -152,7 +152,7 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ - if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { + if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } @@ -295,7 +295,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ - if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { + if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } @@ -358,7 +358,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ - if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { + if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } From 8966b4ba6e84f54b8b8262d5cf30a65b686c136e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 10:07:07 -0600 Subject: [PATCH 09/97] FS-2867 --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 7558e1b1b8..f5d515c8d4 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -602,7 +602,7 @@ static void ipchanged_event_handler(switch_event_t *event) for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, NULL, NULL, &val); profile = (mdl_profile_t *) val; - if (old_ip4 && !strcmp(profile->extip, old_ip4)) { + if (old_ip4 && profile->extip && !strcmp(profile->extip, old_ip4)) { tmp = profile->extip; profile->extip = strdup(new_ip4); switch_safe_free(tmp); From 21c2a74840ee5413b822b254786310a14f2100f2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 13:18:50 -0600 Subject: [PATCH 10/97] uncomment --- src/mod/endpoints/mod_sofia/sofia_presence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index dc02ca47ae..4b853de6b1 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1616,7 +1616,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } - /* commenting to test + if (helper->event){ const char *uuid = switch_event_get_header_nil(helper->event, "unique-id"); @@ -1625,7 +1625,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); } } - */ + nua_handle_bind(nh, &mod_sofia_globals.keep_private); From 10cb487cb02917dfb563872a8146a67af88b20d9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 15:50:17 -0600 Subject: [PATCH 11/97] FS-2868 --- src/mod/applications/mod_hash/mod_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 29a056104f..2609b6cb87 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -130,7 +130,7 @@ SWITCH_LIMIT_INCR(limit_incr_hash) { switch_channel_t *channel = switch_core_session_get_channel(session); char *hashkey = NULL; - switch_bool_t status = SWITCH_STATUS_SUCCESS; + switch_status_t status = SWITCH_STATUS_SUCCESS; limit_hash_item_t *item = NULL; time_t now = switch_epoch_time_now(NULL); limit_hash_private_t *pvt = NULL; From eb109a85d5b54b47e54567893cd714b857865984 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Tue, 23 Nov 2010 17:00:08 -0500 Subject: [PATCH 12/97] mod_dingaling: fix leak in chat_send --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index f5d515c8d4..480f2bdf52 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -521,6 +521,7 @@ static switch_status_t chat_send(const char *proto, const char *from, const char } } ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body)); + switch_safe_free(ffrom); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\n", f_host ? f_host : "NULL"); return SWITCH_STATUS_FALSE; From 58c28aabc8c0ef3cd00087dbd67640cc85d34a71 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Tue, 23 Nov 2010 17:26:32 -0500 Subject: [PATCH 13/97] mod_dingaling: use the login as message source when not in component mode. (chat_send) --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 480f2bdf52..75329a0848 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -514,8 +514,13 @@ static switch_status_t chat_send(const char *proto, const char *from, const char from = hint; } else { char *p; - ffrom = switch_mprintf("%s+%s", proto, from); - from = ffrom; + + if (!(profile->user_flags & LDL_FLAG_COMPONENT)) { + from = ffrom = strdup(profile->login); + } else { + from = ffrom = switch_mprintf("%s+%s", proto, from); + } + if ((p = strchr(from, '/'))) { *p = '\0'; } From 0bd8d187e0a58c708667416f63f30e30c344c295 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 18:03:56 -0600 Subject: [PATCH 14/97] clear controlled flag on recovered calls --- src/switch_ivr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index f076f6cb9f..df88451a3d 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -763,6 +763,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, write_frame.samples = write_frame.datalen / sizeof(int16_t); } + if (switch_channel_test_flag(channel, CF_RECOVERED) && switch_channel_test_flag(channel, CF_CONTROLLED)) { + switch_channel_clear_flag(channel, CF_CONTROLLED); + } + if (switch_channel_test_flag(channel, CF_CONTROLLED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot park channels that are under control already.\n"); return SWITCH_STATUS_FALSE; From dad92067daa6d882a640cccfbf503ec2f800085d Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 23 Nov 2010 18:35:45 -0600 Subject: [PATCH 15/97] FS-535: fix issue in is_lan_addr where 172.2 would match 172.250.x.x which is not RFC1918 this also fixes an chicken egg issue --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- src/switch_utils.c | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 4d992b0ea1..4d9bd7fd7b 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2173,7 +2173,7 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) register_host = sofia_glue_get_register_host(gateway->register_proxy); - if (register_host && !sofia_glue_check_nat(profile, register_host)) { + if (register_host && switch_is_lan_addr(register_host)) { sipip = profile->sipip; } diff --git a/src/switch_utils.c b/src/switch_utils.c index 75be02a31f..1a29e2b715 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -726,18 +726,31 @@ SWITCH_DECLARE(switch_bool_t) switch_is_lan_addr(const char *ip) if (zstr(ip)) return SWITCH_FALSE; - return (strncmp(ip, "10.", 3) && - strncmp(ip, "192.168.", 8) && - strncmp(ip, "127.", 4) && + return (strncmp(ip, "10.", 3) && /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */ + strncmp(ip, "192.168.", 8) && /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */ + strncmp(ip, "127.", 4) && /* 127.0.0.0 - 127.255.255.255 (127/8 prefix) */ strncmp(ip, "255.", 4) && - strncmp(ip, "0.", 2) && + strncmp(ip, "0.", 2) && strncmp(ip, "1.", 2) && strncmp(ip, "2.", 2) && - strncmp(ip, "172.16.", 7) && + strncmp(ip, "172.16.", 7) && /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */ strncmp(ip, "172.17.", 7) && strncmp(ip, "172.18.", 7) && strncmp(ip, "172.19.", 7) && - strncmp(ip, "172.2", 5) && strncmp(ip, "172.30.", 7) && strncmp(ip, "172.31.", 7) && strncmp(ip, "192.0.2.", 8) && strncmp(ip, "169.254.", 8) + strncmp(ip, "172.20.", 7) && + strncmp(ip, "172.21.", 7) && + strncmp(ip, "172.22.", 7) && + strncmp(ip, "172.23.", 7) && + strncmp(ip, "172.24.", 7) && + strncmp(ip, "172.25.", 7) && + strncmp(ip, "172.26.", 7) && + strncmp(ip, "172.27.", 7) && + strncmp(ip, "172.28.", 7) && + strncmp(ip, "172.29.", 7) && + strncmp(ip, "172.30.", 7) && + strncmp(ip, "172.31.", 7) && + strncmp(ip, "192.0.2.", 8) && /* 192.0.2.0 - 192.0.2.255 (192.0.2/24 prefix) */ + strncmp(ip, "169.254.", 8) /* 169.254.0.0 - 169.254.255.255 (169.254/16 prefix) */ )? SWITCH_FALSE : SWITCH_TRUE; } From 61bc810bf8f252bb33946cb23a8d66a78036569b Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Tue, 23 Nov 2010 17:17:46 -0800 Subject: [PATCH 16/97] Fix usage formatting in logger.pl --- libs/esl/perl/logger.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/esl/perl/logger.pl b/libs/esl/perl/logger.pl index d0dbb1750e..08213c033f 100644 --- a/libs/esl/perl/logger.pl +++ b/libs/esl/perl/logger.pl @@ -17,13 +17,13 @@ my $USAGE = " FreeSWITCH Logger Utility USAGE: --h --helpThis help +-h --help This help -p --port Choose port -P -pass Choose password -f --file Output file -pb --paste-bin Post to FreeSWITCH Paste Bin -sp --sip-profiles List of SIP profiles to trace --sd --sip-debug Set SIP debug level +-sd --sip-debug Set SIP debug level No arguments given will trace profile 'internal' to STDOUT "; From 364c156cdc3f078ba423208bc5c6bf0af85a471c Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 24 Nov 2010 03:46:06 +0000 Subject: [PATCH 17/97] update .gitignore --- .gitignore | 2 ++ src/mod/.gitignore | 1 + 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index adcfda37f4..304b42c1f9 100644 --- a/.gitignore +++ b/.gitignore @@ -70,10 +70,12 @@ config.status configure.lineno /freeswitch /fs_cli +/fs_encode /fs_ivrd /libtool /modules.conf /quiet_libtool +/tone2wav /scripts/fsxs /scripts/gentls_cert /a.out.dSYM diff --git a/src/mod/.gitignore b/src/mod/.gitignore index 47cdbafa70..b6e7842a50 100644 --- a/src/mod/.gitignore +++ b/src/mod/.gitignore @@ -7,6 +7,7 @@ /applications/mod_spandsp/mod_spandsp.log /applications/mod_commands/Makefile /applications/mod_conference/Makefile +/applications/mod_db/Makefile /applications/mod_dptools/Makefile /applications/mod_enum/Makefile /applications/mod_enum/Makefile.in From 89245dc5a1f6c4938fff0d760c4660e0bf7974c5 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 24 Nov 2010 03:58:22 +0000 Subject: [PATCH 18/97] remove ignored file from tree --- libs/libsndfile/M4/lt~obsolete.m4 | 98 ------------------------------- 1 file changed, 98 deletions(-) delete mode 100644 libs/libsndfile/M4/lt~obsolete.m4 diff --git a/libs/libsndfile/M4/lt~obsolete.m4 b/libs/libsndfile/M4/lt~obsolete.m4 deleted file mode 100644 index c573da90c5..0000000000 --- a/libs/libsndfile/M4/lt~obsolete.m4 +++ /dev/null @@ -1,98 +0,0 @@ -# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004. -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 5 lt~obsolete.m4 - -# These exist entirely to fool aclocal when bootstrapping libtool. -# -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) -# which have later been changed to m4_define as they aren't part of the -# exported API, or moved to Autoconf or Automake where they belong. -# -# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN -# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us -# using a macro with the same name in our local m4/libtool.m4 it'll -# pull the old libtool.m4 in (it doesn't see our shiny new m4_define -# and doesn't know about Autoconf macros at all.) -# -# So we provide this file, which has a silly filename so it's always -# included after everything else. This provides aclocal with the -# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything -# because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. -# -# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. -# Yes, that means every name once taken will need to remain here until -# we give up compatibility with versions before 1.7, at which point -# we need to keep only those names which we still refer to. - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) - -m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) -m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) -m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) -m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) -m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) -m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) -m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) -m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) -m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) -m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) -m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) -m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) -m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) -m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) -m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) -m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) -m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) -m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) -m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) -m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) -m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) -m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) -m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) -m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) -m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) -m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) -m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) -m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) -m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) -m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) -m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) -m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) -m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) -m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) -m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) -m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) -m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) -m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) -m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) -m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) -m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) -m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) -m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) -m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) -m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) -m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) -m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) -m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) -m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) From e82828231e7634a06d0230df865bbcf5496f57b7 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 24 Nov 2010 06:07:21 +0000 Subject: [PATCH 19/97] spelling corrections --- src/include/switch_channel.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index a1f13edd85..d6bce5e8bf 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -179,8 +179,8 @@ SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_caller_profile(switch_channel_t *channel); @@ -195,8 +195,8 @@ SWITCH_DECLARE(void) switch_channel_set_originator_caller_profile(switch_channel SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's originator caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's originator caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_profile(switch_channel_t *channel); @@ -209,8 +209,8 @@ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_p SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's originatee caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's originatee caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel); @@ -223,16 +223,16 @@ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_p SWITCH_DECLARE(void) switch_channel_set_origination_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's origination caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's origination caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_origination_caller_profile(switch_channel_t *channel); /*! - \brief Retrive the given channel's unique id - \param channel channel to retrive the unique id from + \brief Retrieve the given channel's unique id + \param channel channel to retrieve the unique id from \return the unique id */ SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel); @@ -241,7 +241,7 @@ SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel); \brief Set a variable on a given channel \param channel channel to set variable on \param varname the name of the variable - \param value the vaule of the variable + \param value the value of the variable \returns SWITCH_STATUS_SUCCESS if successful */ From 6a948bd98bc29156774d09210fe07548fed3388b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 24 Nov 2010 09:50:50 -0600 Subject: [PATCH 20/97] add mono 2.8 patch file see FS-2774 --- src/mod/languages/mod_managed/mono28.patch | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/mod/languages/mod_managed/mono28.patch diff --git a/src/mod/languages/mod_managed/mono28.patch b/src/mod/languages/mod_managed/mono28.patch new file mode 100644 index 0000000000..7ec60f596c --- /dev/null +++ b/src/mod/languages/mod_managed/mono28.patch @@ -0,0 +1,75 @@ +diff --git a/src/mod/languages/mod_managed/Makefile b/src/mod/languages/mod_managed/Makefile +index 0ac49b4..ec44ff5 100644 +--- a/src/mod/languages/mod_managed/Makefile ++++ b/src/mod/languages/mod_managed/Makefile +@@ -1,6 +1,6 @@ +-LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono --cflags +-LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono --libs +-#MOD_CFLAGS=-D_REENTRANT -pthread -I/opt/mono-1.9/lib/pkgconfig/../../include/mono-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lmono ++LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono-2 --cflags ++LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono-2 --libs ++#MOD_CFLAGS=-D_REENTRANT -pthread -I/usr/lib/mono -lmono + BASE=../../../.. + VERBOSE=1 + include $(BASE)/build/modmake.rules +diff --git a/src/mod/languages/mod_managed/freeswitch.i b/src/mod/languages/mod_managed/freeswitch.i +index ffbdf9b..117d58c 100644 +--- a/src/mod/languages/mod_managed/freeswitch.i ++++ b/src/mod/languages/mod_managed/freeswitch.i +@@ -8,7 +8,6 @@ + + /* Callback for returning strings to C# without leaking memory */ + #ifndef _MANAGED +-#include + #include + #include + #include +diff --git a/src/mod/languages/mod_managed/freeswitch_managed.h b/src/mod/languages/mod_managed/freeswitch_managed.h +index 1d0b6a7..13ffe5d 100644 +--- a/src/mod/languages/mod_managed/freeswitch_managed.h ++++ b/src/mod/languages/mod_managed/freeswitch_managed.h +@@ -40,7 +40,6 @@ typedef void (*hangupFunction) (void); + typedef char *(*inputFunction) (void *, switch_input_type_t); + + #ifndef _MANAGED +-#include + #include + #include + #include +@@ -73,7 +72,7 @@ extern mod_managed_globals globals; + #ifdef WIN32 + #define RESULT_FREE(x) CoTaskMemFree(x) + #else +-#define RESULT_FREE(x) g_free(x) ++#define RESULT_FREE(x) mono_free(x) + #endif + + SWITCH_END_EXTERN_C +diff --git a/src/mod/languages/mod_managed/mod_managed.cpp b/src/mod/languages/mod_managed/mod_managed.cpp +index ec2d866..87e831f 100644 +--- a/src/mod/languages/mod_managed/mod_managed.cpp ++++ b/src/mod/languages/mod_managed/mod_managed.cpp +@@ -208,18 +208,13 @@ switch_status_t loadRuntime() + } + + /* Already loaded? */ +- MonoAssemblyName name; +- name.name = MOD_MANAGED_ASM_NAME; +- name.major = MOD_MANAGED_ASM_V1; +- name.minor = MOD_MANAGED_ASM_V2; +- name.revision = MOD_MANAGED_ASM_V3; +- name.build = MOD_MANAGED_ASM_V4; +- name.culture = ""; +- name.hash_value = ""; +- ++ MonoAssemblyName *name = mono_assembly_name_new (MOD_MANAGED_ASM_NAME); ++ //Note also that it can't be allocated on the stack anymore and you'll need to create and destroy it with the following API: ++ //mono_assembly_name_free (name); ++ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_assembly_loaded.\n"); + +- if (!(globals.mod_mono_asm = mono_assembly_loaded(&name))) { ++ if (!(globals.mod_mono_asm = mono_assembly_loaded(name))) { + /* Open the assembly */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_domain_assembly_open.\n"); + globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename); From d73cd50e99529ad9572b5d2892736db292d8367f Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 24 Nov 2010 10:34:02 -0600 Subject: [PATCH 21/97] sofia_reg.c lets make this fail2ban stuff better --- src/mod/endpoints/mod_sofia/sofia_reg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 7390378fc8..262aff1dda 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1139,9 +1139,14 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } if (auth_res != AUTH_OK && !stale) { + if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' " + "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip); + } + if (profile->debug) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s] from ip '%s'\n", - forbidden ? "forbidden" : "challenge", to_user, to_host, network_ip); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s]\n", + forbidden ? "forbidden" : "challenge", to_user, to_host); } if (auth_res == AUTH_FORBIDDEN) { nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END()); From 17efb68d1d31deb7cc8d6fcabfc145e4d65da3f1 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 24 Nov 2010 10:53:01 -0600 Subject: [PATCH 22/97] woops don't log reg twice --- src/mod/endpoints/mod_sofia/sofia_reg.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 262aff1dda..216f808e4f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1140,8 +1140,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (auth_res != AUTH_OK && !stale) { if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' " - "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip); + if (regtype == REG_REGISTER) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' " + "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip); + } } if (profile->debug) { @@ -1150,13 +1152,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } if (auth_res == AUTH_FORBIDDEN) { nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END()); - + /* Log line added to support Fail2Ban */ if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - if (regtype == REG_REGISTER) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (REGISTER) on sofia profile '%s' " - "for [%s@%s] from ip %s\n", profile->name, to_user, to_host, network_ip); - } else if (regtype == REG_INVITE) { + if (regtype == REG_INVITE) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (INVITE) on sofia profile '%s' " "for [%s@%s] from ip %s\n", profile->name, to_user, to_host, network_ip); } From a697462a589cab5f70e5608e33837bd6e4ada14c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 24 Nov 2010 12:30:58 -0500 Subject: [PATCH 23/97] freetdm: ftmod_libpri - Do not unlock the channel until all states pending have been cleared. This should fix issues with state transitions being ignored. --- libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 669e85218a..cf84dbeebd 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -727,15 +727,13 @@ static __inline__ void check_state(ftdm_span_t *span) for (j = 1; j <= ftdm_span_get_chan_count(span); j++) { ftdm_channel_t *chan = ftdm_span_get_channel(span, j); - if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_channel_lock(chan); - + ftdm_channel_lock(chan); + while (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE); state_advance(chan); ftdm_channel_complete_state(chan); - - ftdm_channel_unlock(chan); } + ftdm_channel_unlock(chan); } } } From 8b61fe440031ae1c66729c3d9f611a91511c8c8e Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 24 Nov 2010 16:13:52 -0500 Subject: [PATCH 24/97] mod_sangoma_codec: update sample config --- conf/autoload_configs/sangoma_codec.conf.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/conf/autoload_configs/sangoma_codec.conf.xml b/conf/autoload_configs/sangoma_codec.conf.xml index 05d70de0a7..eed9d673e1 100644 --- a/conf/autoload_configs/sangoma_codec.conf.xml +++ b/conf/autoload_configs/sangoma_codec.conf.xml @@ -4,14 +4,15 @@ From b017931c5eb6ea4065060e9b7f22e28274c87c15 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Wed, 24 Nov 2010 17:22:16 -0500 Subject: [PATCH 25/97] add -lresolv when its present so modules don't have to link to it --- configure.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.in b/configure.in index de7261266e..77df2a614c 100644 --- a/configure.in +++ b/configure.in @@ -373,6 +373,11 @@ if test "x$have_libz" = "xyes" ; then APR_ADDTO(SWITCH_AM_LDFLAGS, -lz) fi +AC_CHECK_LIB(resolv, res_init, have_libresolv=yes, have_libresolv=no) +if test "x$have_libresolv" = "xyes" ; then +APR_ADDTO(SWITCH_AM_LDFLAGS, -lresolv) +fi + ESL_LDFLAGS= PLATFORM_CORE_DEPLIBS= # tweak platform specific flags From 03dc3b7b8d734e5a916c0dd48c408e78e6f66f55 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 24 Nov 2010 21:25:24 -0200 Subject: [PATCH 26/97] freetdm: ftdm_channel_read_event() to retrieve events from a channel, removed from ftmod_r2: ftdm_r2_sig_read(), FTDM_R2_PROCESSING flag and locks for ftdmchan --- libs/freetdm/src/ftdm_io.c | 45 +++++ libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 145 ++++++-------- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 184 +++++++++++++++++- libs/freetdm/src/include/freetdm.h | 4 + libs/freetdm/src/include/private/ftdm_core.h | 17 ++ 5 files changed, 311 insertions(+), 84 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 64233a97ac..0065d779f6 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -988,6 +988,51 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t * return status; } +FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event) +{ + ftdm_status_t status = FTDM_FAIL; + ftdm_sigmsg_t sigmsg; + ftdm_span_t *span = ftdmchan->span; + ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n"); + + if (!span->fio->channel_next_event) { + ftdm_log(FTDM_LOG_ERROR, "channel_next_event method not implemented in module %s!", span->fio->name); + return FTDM_NOTIMPL; + } + + status = span->fio->channel_next_event(ftdmchan, event); + if (status != FTDM_SUCCESS) { + return status; + } + + /* before returning the event to the user we do some core operations with certain OOB events */ + memset(&sigmsg, 0, sizeof(sigmsg)); + sigmsg.span_id = span->span_id; + sigmsg.chan_id = (*event)->channel->chan_id; + sigmsg.channel = (*event)->channel; + switch ((*event)->enum_id) { + case FTDM_OOB_ALARM_CLEAR: + { + sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR; + ftdm_clear_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM); + ftdm_span_send_signal(span, &sigmsg); + } + break; + case FTDM_OOB_ALARM_TRAP: + { + sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP; + ftdm_set_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM); + ftdm_span_send_signal(span, &sigmsg); + } + break; + default: + /* NOOP */ + break; + } + + return status; +} + static ftdm_status_t ftdmchan_fsk_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data) { ftdm_channel_t *ftdmchan = (ftdm_channel_t *) user_data; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 30de78857a..7c5f4a46af 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -57,8 +57,7 @@ typedef enum { } ftdm_r2_flag_t; typedef enum { - FTDM_R2_PROCESSING = (1 << 0), - FTDM_R2_WAITING_ACK = (1 << 1), + FTDM_R2_WAITING_ACK = (1 << 0), } ftdm_r2_call_flag_t; /* private call information stored in ftdmchan->call_data void* ptr */ @@ -398,44 +397,26 @@ static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span) return FTDM_SUCCESS; } -static ftdm_status_t ftdm_r2_sig_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size) -{ - openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; - if (!openr2_chan_get_read_enabled(r2chan)) { - ftdm_mutex_lock(ftdmchan->mutex); - //openr2_chan_process_input(r2chan, data, size); - ftdm_mutex_unlock(ftdmchan->mutex); - } - return FTDM_SUCCESS; -} - /* always called from the monitor thread */ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) { - //ftdm_status_t status; ftdm_r2_call_t *r2call; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - //ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Received request to start call\n"); - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Cannot start call when channel is in use (state = %s)\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_mutex_unlock(ftdmchan->mutex); return; } if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot handle request to start call in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_mutex_unlock(ftdmchan->mutex); return; } if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open channel during incoming call! [%s]\n", ftdmchan->last_error); - ftdm_mutex_unlock(ftdmchan->mutex); return; } @@ -448,7 +429,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) /* clean the call data structure but keep the R2 processing flag on! */ ft_r2_clean_call(ftdmchan->call_data); r2call = R2CALL(ftdmchan); - ftdm_set_flag(r2call, FTDM_R2_PROCESSING); if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; @@ -457,7 +437,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) } ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - ftdm_mutex_unlock(ftdmchan->mutex); } /* only called for incoming calls when the ANI, DNIS etc is complete and the user has to decide either to accept or reject the call */ @@ -574,11 +553,8 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err ftdm_r2_data_t *r2data; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Got protocol error when we're already down!\n"); - ftdm_mutex_unlock(ftdmchan->mutex); } ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n"); @@ -587,7 +563,6 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err if (!R2CALL(ftdmchan)->ftdm_started) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - ftdm_mutex_unlock(ftdmchan->mutex); return; } @@ -602,8 +577,6 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err r2data = ftdmchan->span->signal_data; ftdm_span_send_signal(ftdmchan->span, &sigev); - - ftdm_mutex_unlock(ftdmchan->mutex); } static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan) @@ -867,9 +840,37 @@ static int ftdm_r2_io_setup(openr2_chan_t *r2chan) static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *event) { - *event = 0; - ftdm_log(FTDM_LOG_ERROR, "I should not be called (I/O get oob event)!!\n"); - return 0; + ftdm_status_t status; + ftdm_event_t *fevent = NULL; + ftdm_channel_t *ftdmchan = openr2_chan_get_fd(r2chan); + + *event = OR2_OOB_EVENT_NONE; + status = ftdm_channel_read_event(ftdmchan, &fevent); + if (status != FTDM_SUCCESS) { + //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n"); + return -1; + } + if (fevent->e_type != FTDM_EVENT_OOB) + return 0; + switch (fevent->enum_id) { + case FTDM_OOB_CAS_BITS_CHANGE: + { + *event = OR2_OOB_EVENT_CAS_CHANGE; + } + break; + case FTDM_OOB_ALARM_TRAP: + { + *event = OR2_OOB_EVENT_ALARM_ON; + } + break; + case FTDM_OOB_ALARM_CLEAR: + { + *event = OR2_OOB_EVENT_ALARM_OFF; + } + break; + } + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "returning event: %s\n", ftdm_signal_event2str(*event)); + return 0; } static openr2_io_interface_t ftdm_r2_io_iface = { @@ -1137,7 +1138,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) span->start = ftdm_r2_start; span->stop = ftdm_r2_stop; - span->sig_read = ftdm_r2_sig_read; + span->sig_read = NULL; span->signal_cb = sig_cb; span->signal_type = FTDM_SIGTYPE_R2; @@ -1350,6 +1351,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) int ms; struct timeval start, end; short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); + ftdm_event_t *event = NULL; #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); @@ -1401,63 +1403,44 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) continue; } - if (FTDM_SUCCESS == status) { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - if (event->enum_id == FTDM_OOB_CAS_BITS_CHANGE) { - r2call = R2CALL(event->channel); - r2chan = r2call->r2chan; + /* XXX + * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span. + * is it possible to know on which channels those events are pending, without traversing the span? + * XXX */ + for (i = 1; i <= span->chan_count; i++) { + r2chan = R2CALL(span->channels[i])->r2chan; + r2call = R2CALL(ftdmchan); + ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", openr2_chan_get_number(r2chan)); - // we only expect CAS and other OOB events on this thread/loop, once a call is started - // the MF events (in-band signaling) are handled in the call thread - openr2_chan_process_cas_signaling(r2chan); - } else { - ftdm_log(FTDM_LOG_DEBUG, "Ignoring event %d on channel %d.\n", event->enum_id, openr2_chan_get_number(r2chan)); - // XXX TODO: handle alarms here XXX + status = ftdm_channel_read_event(ftdmchan, &event); + ftdm_mutex_lock(ftdmchan->mutex); + if (status == FTDM_SUCCESS) { + switch (event->enum_id) { + case FTDM_OOB_CAS_BITS_CHANGE: + { + ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", i); + openr2_chan_process_cas_signaling(r2chan); + } + break; + case FTDM_OOB_ALARM_TRAP: + case FTDM_OOB_ALARM_CLEAR: + { + ftdm_log(FTDM_LOG_DEBUG, "OOB EVENT: %s\n", ftdm_signal_event2str(event->enum_id)); + openr2_chan_process_oob_events(r2chan); + } + break; } } - /* XXX - * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span. - * is it possible to know on which channels those events are pending, without traversing the span? - * XXX */ - for (i = 1; i <= span->chan_count; i++) { - r2chan = R2CALL(span->channels[i])->r2chan; - ftdmchan = openr2_chan_get_client_data(r2chan); - r2call = R2CALL(ftdmchan); - - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_set_flag(r2call, FTDM_R2_PROCESSING); - - if (ftdm_r2_state_advance(ftdmchan)) { - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } - - /* handle timeout events first if any */ - openr2_chan_run_schedule(r2chan); - - /* process mf tones, if any */ - if (openr2_chan_get_read_enabled(r2chan)) { - openr2_chan_process_mf_signaling(r2chan); - } - - if (ftdm_r2_state_advance(ftdmchan)) { - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } - - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); + if (!ftdm_r2_state_advance(ftdmchan)) { + ftdm_mutex_unlock(ftdmchan->mutex); + } + openr2_chan_process_signaling(r2chan); + if (!ftdm_r2_state_advance(ftdmchan)) { ftdm_mutex_unlock(ftdmchan->mutex); } - } else if (status != FTDM_TIMEOUT) { - ftdm_log(FTDM_LOG_ERROR, "ftdm_span_poll_event returned %d.\n", status); } ftdm_span_trigger_signals(span); - ftdm_sleep(20); } for (i = 1; i <= span->chan_count; i++) { diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c13455dd21..ae46852300 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -35,6 +35,7 @@ * Moises Silva * David Yat Sin * Nenad Corbic + * Arnaldo Pereira * */ @@ -99,7 +100,8 @@ static struct { /* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); -FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event); +FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event); +FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event); /** * \brief Poll for event on a wanpipe socket @@ -1110,13 +1112,188 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) return FTDM_SUCCESS; } +/** + * \brief Retrieves an event from a wanpipe channel + * \param channel Channel to retrieve event from + * \param event FreeTDM event to return + * \return Success or failure + */ +FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) +{ + ftdm_status_t status; + ftdm_oob_event_t event_id; + wanpipe_tdm_api_t tdm_api; + ftdm_span_t *span = ftdmchan->span; + + if (ftdmchan->last_event_time && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { + uint32_t diff = (uint32_t)(ftdm_current_time_in_ms() - ftdmchan->last_event_time); + /* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)ftdmchan->last_event_time); */ + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) { + if (diff > wp_globals.wink_ms) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); + event_id = FTDM_OOB_OFFHOOK; + goto event; + } + } + + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) { + if (diff > wp_globals.flash_ms) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); + event_id = FTDM_OOB_ONHOOK; + + if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) { + wanpipe_tdm_api_t tdm_api; + memset(&tdm_api, 0, sizeof(tdm_api)); + + sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api); + } + goto event; + } + } + } + + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) + return FTDM_FAIL; + + memset(&tdm_api, 0, sizeof(tdm_api)); + status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); + if (status != FTDM_SUCCESS) { + snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno)); + return FTDM_FAIL; + } + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); + switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { + + case WP_TDMAPI_EVENT_LINK_STATUS: + { + switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) { + case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: + event_id = FTDM_OOB_ALARM_CLEAR; + break; + default: + event_id = FTDM_OOB_ALARM_TRAP; + break; + }; + } + break; + + case WP_TDMAPI_EVENT_RXHOOK: + { + if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) { + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK; + if (event_id == FTDM_OOB_OFFHOOK) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + event_id = FTDM_OOB_FLASH; + goto event; + } else { + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + } + } else { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + event_id = FTDM_OOB_WINK; + goto event; + } else { + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + } + } + break; + } else { + wanpipe_tdm_api_t onhook_tdm_api; + memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api)); + status = sangoma_tdm_txsig_onhook(ftdmchan->sockfd, &onhook_tdm_api); + if (status) { + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed"); + return FTDM_FAIL; + } + event_id = onhook_tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP; + } + } + break; + case WP_TDMAPI_EVENT_RING_DETECT: + { + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP; + } + break; + /* + disabled this ones when configuring, we don't need them, do we? + case WP_TDMAPI_EVENT_RING_TRIP_DETECT: + { + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK; + } + break; + */ + case WP_TDMAPI_EVENT_RBS: + { + event_id = FTDM_OOB_CAS_BITS_CHANGE; + ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); + } + break; + case WP_TDMAPI_EVENT_DTMF: + { + char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; + event_id = FTDM_OOB_NOOP; + + if (tmp_dtmf[0] == 'f') { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c, fax tones will be passed through!\n", tmp_dtmf[0]); + break; + } + + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) { + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE); + } + + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]); + ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf); + } + } + } + break; + case WP_TDMAPI_EVENT_ALARM: + { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm); + event_id = FTDM_OOB_ALARM_TRAP; + } + break; + default: + { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); + event_id = FTDM_OOB_INVALID; + } + break; + } + +event: + + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); + + ftdmchan->last_event_time = 0; + span->event_header.e_type = FTDM_EVENT_OOB; + span->event_header.enum_id = event_id; + span->event_header.channel = ftdmchan; + *event = &span->event_header; + return FTDM_SUCCESS; +} + /** * \brief Retrieves an event from a wanpipe span * \param span Span to retrieve event from * \param event FreeTDM event to return * \return Success or failure */ -FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) +FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) { uint32_t i,err; ftdm_oob_event_t event_id; @@ -1348,7 +1525,8 @@ static FIO_IO_LOAD_FUNCTION(wanpipe_init) wanpipe_interface.read = wanpipe_read; wanpipe_interface.write = wanpipe_write; wanpipe_interface.poll_event = wanpipe_poll_event; - wanpipe_interface.next_event = wanpipe_next_event; + wanpipe_interface.next_event = wanpipe_span_next_event; + wanpipe_interface.channel_next_event = wanpipe_channel_next_event; wanpipe_interface.channel_destroy = wanpipe_channel_destroy; wanpipe_interface.get_alarms = wanpipe_get_alarms; *fio = &wanpipe_interface; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 508c6996d5..9ce213c962 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -465,6 +465,7 @@ struct ftdm_memory_handler { #define FIO_SPAN_GET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t *status) #define FIO_SPAN_POLL_EVENT_ARGS (ftdm_span_t *span, uint32_t ms, short *poll_events) #define FIO_SPAN_NEXT_EVENT_ARGS (ftdm_span_t *span, ftdm_event_t **event) +#define FIO_CHANNEL_NEXT_EVENT_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t **event) #define FIO_SIGNAL_CB_ARGS (ftdm_sigmsg_t *sigmsg) #define FIO_EVENT_CB_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t *event) #define FIO_CONFIGURE_SPAN_ARGS (ftdm_span_t *span, const char *str, ftdm_chan_type_t type, char *name, char *number) @@ -496,6 +497,7 @@ typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS; typedef ftdm_status_t (*fio_span_get_sig_status_t) FIO_SPAN_GET_SIG_STATUS_ARGS; typedef ftdm_status_t (*fio_span_poll_event_t) FIO_SPAN_POLL_EVENT_ARGS ; typedef ftdm_status_t (*fio_span_next_event_t) FIO_SPAN_NEXT_EVENT_ARGS ; +typedef ftdm_status_t (*fio_channel_next_event_t) FIO_CHANNEL_NEXT_EVENT_ARGS ; typedef ftdm_status_t (*fio_signal_cb_t) FIO_SIGNAL_CB_ARGS ; typedef ftdm_status_t (*fio_event_cb_t) FIO_EVENT_CB_ARGS ; typedef ftdm_status_t (*fio_configure_span_t) FIO_CONFIGURE_SPAN_ARGS ; @@ -528,6 +530,7 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ; #define FIO_SPAN_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_GET_SIG_STATUS_ARGS #define FIO_SPAN_POLL_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_POLL_EVENT_ARGS #define FIO_SPAN_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_NEXT_EVENT_ARGS +#define FIO_CHANNEL_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_NEXT_EVENT_ARGS #define FIO_SIGNAL_CB_FUNCTION(name) ftdm_status_t name FIO_SIGNAL_CB_ARGS #define FIO_EVENT_CB_FUNCTION(name) ftdm_status_t name FIO_EVENT_CB_ARGS #define FIO_CONFIGURE_SPAN_FUNCTION(name) ftdm_status_t name FIO_CONFIGURE_SPAN_ARGS @@ -566,6 +569,7 @@ struct ftdm_io_interface { fio_write_t write; /*!< Write data to the channel */ fio_span_poll_event_t poll_event; /*!< Poll for events on the whole span */ fio_span_next_event_t next_event; /*!< Retrieve an event from the span */ + fio_channel_next_event_t channel_next_event; /*!< Retrieve an event from channel */ fio_api_t api; /*!< Execute a text command */ }; diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 06f899c8c9..7d3ee68176 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -615,6 +615,23 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan); */ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event); +/*! + * \brief Retrieves an event from the span + * + * \note + * This function is non-reentrant and not thread-safe. + * The event returned may be modified if the function is called again + * from a different thread or even the same. It is recommended to + * handle events from the same span in a single thread. + * + * \param span The channel to retrieve the event from + * \param event Pointer to store the pointer to the event + * + * \retval FTDM_SUCCESS success (at least one event available) + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event); + /*! * \brief Enqueue a DTMF string into the channel * From a5d53b8a38b770f702fa55d72e996ed54a32f181 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 24 Nov 2010 22:14:06 -0200 Subject: [PATCH 27/97] freetdm: removed wrong main loop code --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 30 +++------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 7c5f4a46af..8a4a826906 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -847,7 +847,7 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e *event = OR2_OOB_EVENT_NONE; status = ftdm_channel_read_event(ftdmchan, &fevent); if (status != FTDM_SUCCESS) { - //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n"); return -1; } if (fevent->e_type != FTDM_EVENT_OOB) @@ -1412,33 +1412,11 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) r2call = R2CALL(ftdmchan); ftdmchan = openr2_chan_get_client_data(r2chan); - status = ftdm_channel_read_event(ftdmchan, &event); ftdm_mutex_lock(ftdmchan->mutex); - if (status == FTDM_SUCCESS) { - switch (event->enum_id) { - case FTDM_OOB_CAS_BITS_CHANGE: - { - ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", i); - openr2_chan_process_cas_signaling(r2chan); - } - break; - case FTDM_OOB_ALARM_TRAP: - case FTDM_OOB_ALARM_CLEAR: - { - ftdm_log(FTDM_LOG_DEBUG, "OOB EVENT: %s\n", ftdm_signal_event2str(event->enum_id)); - openr2_chan_process_oob_events(r2chan); - } - break; - } - } - - if (!ftdm_r2_state_advance(ftdmchan)) { - ftdm_mutex_unlock(ftdmchan->mutex); - } + ftdm_r2_state_advance(ftdmchan); openr2_chan_process_signaling(r2chan); - if (!ftdm_r2_state_advance(ftdmchan)) { - ftdm_mutex_unlock(ftdmchan->mutex); - } + ftdm_r2_state_advance(ftdmchan); + ftdm_mutex_unlock(ftdmchan->mutex); } ftdm_span_trigger_signals(span); } From 2b0189becad007b0683272a0a3d46a952cc520ed Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 24 Nov 2010 22:58:05 -0200 Subject: [PATCH 28/97] freetdm: now wanpipe_channel_next_event() doesn't expect the flag FTDM_CHANNEL_EVENT to be set. If it is, it just clears it. Also removed unused code from wanpipe_channel_next_event() --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 39 ++----------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index ae46852300..1a43c4db50 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1125,45 +1125,16 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) wanpipe_tdm_api_t tdm_api; ftdm_span_t *span = ftdmchan->span; - if (ftdmchan->last_event_time && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { - uint32_t diff = (uint32_t)(ftdm_current_time_in_ms() - ftdmchan->last_event_time); - /* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)ftdmchan->last_event_time); */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) { - if (diff > wp_globals.wink_ms) { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_OFFHOOK; - goto event; - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) { - if (diff > wp_globals.flash_ms) { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_ONHOOK; - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) { - wanpipe_tdm_api_t tdm_api; - memset(&tdm_api, 0, sizeof(tdm_api)); - - sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api); - } - goto event; - } - } - } - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) - return FTDM_FAIL; + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); memset(&tdm_api, 0, sizeof(tdm_api)); status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); if (status != FTDM_SUCCESS) { +#if 0 snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno)); +#endif return FTDM_FAIL; } @@ -1277,8 +1248,6 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) event: - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); - ftdmchan->last_event_time = 0; span->event_header.e_type = FTDM_EVENT_OOB; span->event_header.enum_id = event_id; From b814dc17ce5aefded953fc7e30db257088f70475 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 24 Nov 2010 20:04:43 -0500 Subject: [PATCH 29/97] freetdm: ISDN Changes to better match SIP-to-TDM states --- libs/freetdm/mod_freetdm/mod_freetdm.c | 15 ++- libs/freetdm/src/ftdm_io.c | 16 +-- .../src/ftmod/ftmod_analog/ftmod_analog.c | 16 +-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 66 +++++++++-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 26 ++++- .../ftmod_sangoma_isdn_cfg.c | 9 ++ .../ftmod_sangoma_isdn_stack_hndl.c | 108 +++++++++++++----- .../ftmod_sangoma_isdn_stack_out.c | 85 ++++++++++++-- .../ftmod_sangoma_isdn_support.c | 18 +++ libs/freetdm/src/include/freetdm.h | 8 +- libs/freetdm/src/include/private/ftdm_types.h | 8 +- libs/freetdm/src/testanalog.c | 2 +- 12 files changed, 303 insertions(+), 74 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 8d961123cb..27dc8d8c92 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -425,8 +425,11 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); + assert(tech_pvt->ftdmchan != NULL); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); + + ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED); return SWITCH_STATUS_SUCCESS; } @@ -852,7 +855,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_RINGING: { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS); + ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING); } break; case SWITCH_MESSAGE_INDICATE_PROGRESS: @@ -935,7 +938,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio !switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_RING_READY) ) { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RING); + ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING); switch_channel_mark_ring_ready(channel); } break; @@ -2133,7 +2136,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) spanid, chanid, (uuid) ? uuid : "N/A"); } } - break; + break; case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus; @@ -2141,6 +2144,10 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) spanid, chanid, ftdm_signaling_status2str(sigstatus)); } break; + case FTDM_SIGEVENT_PROCEED: + case FTDM_SIGEVENT_MSG: + /* FS does not have handlers for these messages, so ignore them for now */ + break; default: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n", diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 64233a97ac..ede3ff8fc8 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2033,7 +2033,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char goto done; } - if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } @@ -2202,14 +2201,19 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch switch (indication) { /* FIXME: ring and busy cannot be used with all signaling stacks * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */ - case FTDM_CHANNEL_INDICATE_RING: - ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RING, 1); + case FTDM_CHANNEL_INDICATE_RINGING: + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1); break; - case FTDM_CHANNEL_INDICATE_BUSY: ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1); break; - + case FTDM_CHANNEL_INDICATE_PROCEED: + if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) { + if (ftdmchan->state == FTDM_CHANNEL_STATE_RING) { + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1); + } + } + break; case FTDM_CHANNEL_INDICATE_PROGRESS: if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); @@ -2217,7 +2221,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } break; - case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA: if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); @@ -2236,7 +2239,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); } break; - default: ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication); status = FTDM_FAIL; diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index fc9bea6ef0..99d256655a 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -438,7 +438,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) { if (state_counter > 5000 || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) { ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); } } break; @@ -492,8 +492,8 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && - (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE - || ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) { + (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE + || ftdmchan->last_state >= FTDM_CHANNEL_STATE_RING)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); } else { ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; @@ -535,7 +535,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } } case FTDM_CHANNEL_STATE_UP: - case FTDM_CHANNEL_STATE_IDLE: + case FTDM_CHANNEL_STATE_RING: { ftdm_sleep(interval); continue; @@ -599,7 +599,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) ftdm_channel_use(ftdmchan); } break; - case FTDM_CHANNEL_STATE_IDLE: + case FTDM_CHANNEL_STATE_RING: { ftdm_channel_use(ftdmchan); sig.event_id = FTDM_SIGEVENT_START; @@ -669,7 +669,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) continue; } break; - case FTDM_CHANNEL_STATE_RING: + case FTDM_CHANNEL_STATE_RINGING: { ftdm_buffer_zero(dt_buffer); teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]); @@ -732,7 +732,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); last_digit = 0; collecting = 0; } @@ -890,7 +890,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) { ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID); } else { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING); } event->channel->ring_count = 1; ftdm_mutex_unlock(event->channel->mutex); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 77ad917bf1..6f5f838590 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -115,7 +115,19 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_RING, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END} + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROCEED, FTDM_END}, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_RINGING, FTDM_END}, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}, }, { ZSD_INBOUND, @@ -189,9 +201,17 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_DOWN, FTDM_END} + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, + FTDM_CHANNEL_STATE_DOWN, FTDM_END} }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROCEED, FTDM_END}, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}, + }, { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, @@ -604,13 +624,15 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_GET_CALLERID: { - sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); - sngisdn_snd_proceed(ftdmchan); + if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { + sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); + sngisdn_snd_proceed(ftdmchan); + } /* Wait in this state until we get FACILITY msg */ } break; case FTDM_CHANNEL_STATE_RING: /* incoming call request */ - { + { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits); /* we have enough information to inform FTDM of the call*/ @@ -635,6 +657,25 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) } } break; + case FTDM_CHANNEL_STATE_PROCEED: + { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + /*OUTBOUND...so we were told by the line of this so noifiy the user*/ + sigev.event_id = FTDM_SIGEVENT_PROCEED; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } else { + if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { + sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); + sngisdn_snd_proceed(ftdmchan); + } + } + } + break; + case FTDM_CHANNEL_STATE_RINGING: + { + sngisdn_snd_alert(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + } + break; case FTDM_CHANNEL_STATE_PROGRESS: { /*check if the channel is inbound or outbound*/ @@ -642,9 +683,12 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) /*OUTBOUND...so we were told by the line of this so noifiy the user*/ sigev.event_id = FTDM_SIGEVENT_PROGRESS; ftdm_span_send_signal(ftdmchan->span, &sigev); - } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { - sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); - sngisdn_snd_proceed(ftdmchan); + } else { + /* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */ + if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) { + /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */ + sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + } } } break; @@ -654,7 +698,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; ftdm_span_send_signal(ftdmchan->span, &sigev); } else { - sngisdn_snd_progress(ftdmchan); + /* Send a progress message, indicating: In-band information/pattern available */ + sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_IB_AVAIL); } } break; @@ -992,6 +1037,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) span->state_map = &sangoma_isdn_state_map; ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); + ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE); if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || span->trunk_type == FTDM_TRUNK_BRI) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 81a98cf0d3..25ffef85e5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -75,7 +75,8 @@ typedef enum { FLAG_DELAYED_REL = (1 << 7), FLAG_SENT_PROCEED = (1 << 8), FLAG_SEND_DISC = (1 << 9), - FLAG_ACTIVATING = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */ + /* Used for BRI only, flag is set after we request line CONNECTED */ + FLAG_ACTIVATING = (1 << 10), } sngisdn_flag_t; @@ -135,6 +136,21 @@ typedef enum { SNGISDN_EVENT_RST_IND, } ftdm_sngisdn_event_id_t; +typedef enum { + /* Call is not end-to-end ISDN */ + SNGISDN_PROGIND_NETE_ISDN = 1, + /* Destination address is non-ISDN */ + SNGISDN_PROGIND_DEST_NISDN, + /* Origination address is non-ISDN */ + SNGISDN_PROGIND_ORIG_NISDN, + /* Call has returned to the ISDN */ + SNGISDN_PROGIND_RET_ISDN, + /* Interworking as occured and has resulted in a telecommunication service change */ + SNGISDN_PROGIND_SERV_CHANGE, + /* In-band information or an appropriate pattern is now available */ + SNGISDN_PROGIND_IB_AVAIL, +} ftdm_sngisdn_progind_t; + /* Only timers that can be cancelled are listed here */ #define SNGISDN_NUM_TIMERS 1 /* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */ @@ -181,6 +197,7 @@ typedef struct sngisdn_span_data { uint8_t trace_flags; /* TODO: change to flags, so we can use ftdm_test_flag etc.. */ uint8_t overlap_dial; uint8_t setup_arb; + uint8_t facility_ie_decode; uint8_t facility; int8_t facility_timeout; uint8_t num_local_numbers; @@ -288,13 +305,14 @@ void stack_pst_init(Pst *pst); void sngisdn_snd_setup(ftdm_channel_t *ftdmchan); void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan); void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan); -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan); -void sngisdn_snd_alert(ftdm_channel_t *ftdmchan); +void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind); +void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind); void sngisdn_snd_connect(ftdm_channel_t *ftdmchan); void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan); void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare); void sngisdn_snd_reset(ftdm_channel_t *ftdmchan); void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan); +void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan); void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan); void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan); void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len); @@ -362,6 +380,8 @@ ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgP ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display); +ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); + ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 3b264ae02f..657aa5e206 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -190,6 +190,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->min_digits = 8; signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; + signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; signal_data->timer_t3 = 8; signal_data->link_id = span->span_id; @@ -289,6 +290,14 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ if (signal_data->facility_timeout < 0) { signal_data->facility_timeout = 0; } + } else if (!strcasecmp(var, "facility-ie-decode")) { + if (!strcasecmp(val, "yes")) { + signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; + } else if (!strcasecmp(val, "no")) { + signal_data->facility_ie_decode = SNGISDN_OPT_FALSE; + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); + } } else { ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 3fe0422a4e..209284a8b6 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -144,31 +144,35 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); } } - - if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) { - /* Verify whether the Caller Name will come in a subsequent FACILITY message */ - uint16_t ret_val; - char retrieved_str[255]; - - ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); - /* - return values for "sng_isdn_retrieve_facility_information_following": - If there will be no information following, or fails to decode IE, returns -1 - If there will be no information following, but current FACILITY IE contains a caller name, returns 0 - If there will be information following, returns 1 - */ - if (ret_val == 1) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); - /* Launch timer in case we never get a FACILITY msg */ - if (signal_data->facility_timeout) { - ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, - sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); + if (conEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); + } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + /* Verify whether the Caller Name will come in a subsequent FACILITY message */ + uint16_t ret_val; + char retrieved_str[255]; + + ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); + /* + return values for "sng_isdn_retrieve_facility_information_following": + If there will be no information following, or fails to decode IE, returns -1 + If there will be no information following, but current FACILITY IE contains a caller name, returns 0 + If there will be information following, returns 1 + */ + + if (ret_val == 1) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); + /* Launch timer in case we never get a FACILITY msg */ + if (signal_data->facility_timeout) { + ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, + sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); + } + break; + } else if (ret_val == 0) { + strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } - break; - } else if (ret_val == 0) { - strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } } } @@ -269,6 +273,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { switch(ftdmchan->state) { + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_DIALING: @@ -367,8 +372,10 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) case MI_CALLPROC: switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_DIALING: - if (evntType == MI_PROGRESS || + case FTDM_CHANNEL_STATE_DIALING: + if (evntType == MI_CALLPROC) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); + } else if (evntType == MI_PROGRESS || (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { @@ -417,6 +424,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) } break; case FTDM_CHANNEL_STATE_RING: + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_UP: @@ -446,6 +454,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) uint32_t spInstId = sngisdn_event->spInstId; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt; @@ -454,12 +463,20 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - switch (ftdmchan->state) { + switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_RING: case FTDM_CHANNEL_STATE_DIALING: + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: + case FTDM_CHANNEL_STATE_UP: + if (discEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); + } else { + /* Call libsng_isdn facility decode function and copy variables here */ + } + } if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) { ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val; } else { @@ -503,6 +520,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) uint32_t spInstId = sngisdn_event->spInstId; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; RelEvnt *relEvnt = &sngisdn_event->event.relEvnt; @@ -538,6 +556,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); } /* fall-through */ + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_UP: @@ -547,6 +566,15 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */ if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId || ((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) { + + if (relEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); + } else { + /* Call libsng_isdn facility decode function and copy variables here */ + } + } + if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) { ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause); @@ -725,15 +753,16 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_GET_CALLERID: /* Update the caller ID Name */ + if (facEvnt->facElmt.facStr.pres) { char retrieved_str[255]; - + /* return values for "sng_isdn_retrieve_facility_information_following": If there will be no information following, or fails to decode IE, returns -1 If there will be no information following, but current FACILITY IE contains a caller name, returns 0 If there will be information following, returns 1 */ - + if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) { strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } else { @@ -751,6 +780,25 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) /* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n"); break; + case FTDM_CHANNEL_STATE_UP: + { + ftdm_sigmsg_t sigev; + if (facEvnt->facElmt.facStr.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); + } else { + /* Call libsng_isdn facility decode function and copy variables here */ + } + } + memset(&sigev, 0, sizeof(sigev)); + sigev.chan_id = ftdmchan->chan_id; + sigev.span_id = ftdmchan->span_id; + sigev.channel = ftdmchan; + + sigev.event_id = FTDM_SIGEVENT_MSG; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } + break; default: /* We do not support other FACILITY types for now, so do nothing */ break; @@ -865,6 +913,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n"); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); break; + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n"); @@ -882,6 +931,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) break; case 3: switch (ftdmchan->state) { + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: /* T310 timer has expired */ ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 2853335efc..385d1eba9d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -34,6 +34,9 @@ #include "ftmod_sangoma_isdn.h" +static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prod_ind); +static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); + void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { ConEvnt conEvnt; @@ -138,6 +141,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data); cpy_calling_name_from_user(&conEvnt, ftdmchan); + sngisdn_set_facilityStr(ftdmchan, &conEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) { @@ -323,14 +328,14 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan) return; } -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan) +void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind) { CnStEvnt cnStEvnt; sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); @@ -351,7 +356,8 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan) cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - cnStEvnt.progInd.progDesc.val = IN_PD_IBAVAIL; + + sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) { @@ -360,14 +366,14 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan) return; } -void sngisdn_snd_alert(ftdm_channel_t *ftdmchan) +void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind) { CnStEvnt cnStEvnt; sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); @@ -382,7 +388,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan) cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; + sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -456,6 +462,27 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) return; } +void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan) +{ + FacEvnt facEvnt; + + sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending FACILITY, but no call data, ignoring (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); + return; + } + + memset(&facEvnt, 0, sizeof(facEvnt)); + + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); + + if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused FACILITY request\n"); + } + return; +} void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan) { @@ -510,7 +537,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); @@ -531,6 +558,8 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) discEvnt.causeDgn[0].recommend.pres = NOTPRSNT; discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; + sngisdn_set_facilityStr(ftdmchan, &discEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n"); @@ -575,6 +604,8 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) spInstId = sngisdn_info->spInstId; } + sngisdn_set_facilityStr(ftdmchan, &relEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId); if (glare) { @@ -589,6 +620,46 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) return; } +static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind) +{ + switch(prog_ind) { + case SNGISDN_PROGIND_NETE_ISDN: + progInd->progDesc.val = IN_PD_NOTETEISDN; + break; + case SNGISDN_PROGIND_DEST_NISDN: + progInd->progDesc.val = IN_PD_DSTNOTISDN; + break; + case SNGISDN_PROGIND_ORIG_NISDN: + progInd->progDesc.val = IN_PD_ORGNOTISDN; + break; + case SNGISDN_PROGIND_RET_ISDN: + progInd->progDesc.val = IN_PD_CALLRET; + break; + case SNGISDN_PROGIND_SERV_CHANGE: + /* Trillium defines do not match ITU-T Q931 Progress descriptions, + indicate a delayed response for now */ + progInd->progDesc.val = IN_PD_DELRESP; + break; + case SNGISDN_PROGIND_IB_AVAIL: + progInd->progDesc.val = IN_PD_IBAVAIL; + break; + } + return; +} + +static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) +{ + const char *facility_str = NULL; + + facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); + if (facility_str) { + facilityStr->eh.pres = PRSNT_NODEF; + facilityStr->facilityStr.len = strlen(facility_str); + memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); + } + return; +} + /* We received an incoming frame on the d-channel, send data to the stack */ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 056bf66ef2..379c481c0e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -229,6 +229,24 @@ ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *dis return FTDM_SUCCESS; } +ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) +{ + if (data_len > sizeof(caller_data->raw_data)-2) { + ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n"); + return FTDM_FAIL; + } + + memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data)); + /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */ + caller_data->raw_data[0] = 0x1C; + caller_data->raw_data[1] = data_len; + + memcpy(&caller_data->raw_data[2], data, data_len); + caller_data->raw_data_len = data_len+2; + + return FTDM_SUCCESS; +} + ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->cid_num.digits); diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 508c6996d5..87da5d1dd0 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -289,7 +289,8 @@ typedef enum { FTDM_SIGEVENT_STOP, /*!< Hangup */ FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */ FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */ - FTDM_SIGEVENT_FLASH, /*< Flash event (typically on-hook/off-hook for analog devices) */ + FTDM_SIGEVENT_FLASH, /*!< Flash event (typically on-hook/off-hook for analog devices) */ + FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */ FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */ FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */ FTDM_SIGEVENT_ALARM_TRAP, /*!< Hardware alarm ON */ @@ -299,9 +300,10 @@ typedef enum { FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */ FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */ FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */ + FTDM_SIGEVENT_MSG, /* !< We received an in-call msg */ FTDM_SIGEVENT_INVALID } ftdm_signal_event_t; -#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROGRESS", \ +#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \ "PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \ "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "INVALID" @@ -581,7 +583,7 @@ typedef enum { * This is used during incoming calls when you want to request the signaling stack * to notify about indications occurring locally */ typedef enum { - FTDM_CHANNEL_INDICATE_RING, + FTDM_CHANNEL_INDICATE_RINGING, FTDM_CHANNEL_INDICATE_PROCEED, FTDM_CHANNEL_INDICATE_PROGRESS, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA, diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index d9cefc3c6f..f265cb1a3d 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -181,6 +181,8 @@ typedef enum { * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal * for later delivery */ FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10), + /* If this flag is set, channel will be moved to proceed state when calls goes to routing */ + FTDM_SPAN_USE_PROCEED_STATE = (1 << 11), } ftdm_span_flag_t; /*! \brief Channel supported features */ @@ -204,6 +206,7 @@ typedef enum { FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, + FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_BUSY, FTDM_CHANNEL_STATE_ATTN, FTDM_CHANNEL_STATE_GENRING, @@ -211,6 +214,7 @@ typedef enum { FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_CALLWAITING, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, @@ -223,8 +227,8 @@ typedef enum { FTDM_CHANNEL_STATE_INVALID } ftdm_channel_state_t; #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \ - "RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ - "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \ + "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ + "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \ "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID" FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t) diff --git a/libs/freetdm/src/testanalog.c b/libs/freetdm/src/testanalog.c index 84d09f73c9..326bb5aec5 100644 --- a/libs/freetdm/src/testanalog.c +++ b/libs/freetdm/src/testanalog.c @@ -50,7 +50,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_signal) switch(sigmsg->event_id) { case FTDM_SIGEVENT_START: - ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RING); + ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RINGING); ftdm_log(FTDM_LOG_DEBUG, "launching thread and indicating ring\n"); ftdm_thread_create_detached(test_call, sigmsg->channel); break; From 9fbecc60bee1601cf7a53775ecaa7e97229cca43 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 00:36:01 -0200 Subject: [PATCH 30/97] freetdm: on ftmod_r2, fixed flags for correctly polling the span, now freeing poll_events pointer, enabling/disabling channel reading flag when needed. also removed the test for FTDM_CHANNEL_OPEN flag on ftdm_channel_wait(). --- libs/freetdm/src/ftdm_io.c | 5 ----- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 18 ++++++++++++------ .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 2 -- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0065d779f6..23ed68c45a 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2869,11 +2869,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_ assert(ftdmchan != NULL); assert(ftdmchan->fio != NULL); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open"); - return FTDM_FAIL; - } - if (!ftdmchan->fio->wait) { snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented"); return FTDM_FAIL; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 8a4a826906..52c0f86e6c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -781,7 +781,7 @@ static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block) int32_t timeout; ftdm_wait_flag_t ftdmflags = 0; - ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan); + ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan); timeout = block ? -1 : 0; if (*flags & OR2_IO_READ) { @@ -794,9 +794,10 @@ static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block) ftdmflags |= FTDM_EVENTS; } - status = ftdm_channel_wait(ftdm_chan, &ftdmflags, timeout); + status = ftdm_channel_wait(fchan, &ftdmflags, timeout); if (FTDM_SUCCESS != status && FTDM_TIMEOUT != status) { + ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to wait for events on channel\n"); return -1; } @@ -869,7 +870,6 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e } break; } - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "returning event: %s\n", ftdm_signal_event2str(*event)); return 0; } @@ -1212,6 +1212,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); ftdm_assert(interval != 0, "Invalid interval!"); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval); + openr2_chan_enable_read(r2chan); } break; @@ -1223,6 +1224,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_assert(interval != 0, "Invalid interval!"); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval); + openr2_chan_enable_read(r2chan); } break; @@ -1289,7 +1291,6 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) { openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); - openr2_chan_enable_read(r2chan); if (!R2CALL(ftdmchan)->disconnect_rcvd) { /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ openr2_chan_disconnect_call(r2chan, disconnect_cause); @@ -1304,7 +1305,6 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) case FTDM_CHANNEL_STATE_CANCEL: { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Unable to receive call\n"); - openr2_chan_enable_read(r2chan); openr2_chan_disconnect_call(r2chan, OR2_CAUSE_OUT_OF_ORDER); } break; @@ -1316,6 +1316,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) if (R2CALL(ftdmchan)->txdrops) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "dropped %d tx packets\n", R2CALL(ftdmchan)->txdrops); } + openr2_chan_disable_read(r2chan); ret = 1; } break; @@ -1385,7 +1386,10 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) for (i = 0; i < span->chan_count; i++) { r2chan = R2CALL(span->channels[(i+1)])->r2chan; ftdmchan = openr2_chan_get_client_data(r2chan); - poll_events[i] = ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ? POLLPRI : (POLLPRI | POLLIN | POLLOUT); + poll_events[i] = POLLPRI; + if (openr2_chan_get_read_enabled(r2chan)) { + poll_events[i] |= POLLIN; + } } status = ftdm_span_poll_event(span, waitms, poll_events); @@ -1426,6 +1430,8 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) openr2_chan_set_blocked(r2chan); } + ftdm_safe_free(poll_events); + ftdm_clear_flag(r2data, FTDM_R2_RUNNING); ftdm_log(FTDM_LOG_DEBUG, "R2 thread ending.\n"); diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 1a43c4db50..c55d42e8b0 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1131,10 +1131,8 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) memset(&tdm_api, 0, sizeof(tdm_api)); status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); if (status != FTDM_SUCCESS) { -#if 0 snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno)); -#endif return FTDM_FAIL; } From 8b0e7d2496e53fd78aae4764c222e2dddfc4bc2a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Nov 2010 21:25:58 -0600 Subject: [PATCH 31/97] FS-2880 --- src/switch_odbc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/switch_odbc.c b/src/switch_odbc.c index 36c3c996e8..a1c476e4a1 100644 --- a/src/switch_odbc.c +++ b/src/switch_odbc.c @@ -364,7 +364,6 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec_string(switch_odbc_ goto done; } - result = SQLExecute(stmt); result = SQLFetch(stmt); if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) { From f987903e5ee275ff4afd27245f322e4b8d9eb8f3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Nov 2010 21:36:21 -0600 Subject: [PATCH 32/97] fix single domain assumption in default config to be more portable *cough* bkw *cough* --- conf/dialplan/default.xml | 2 +- conf/directory/default.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index 42a3bcc31f..a19f68399e 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -265,7 +265,7 @@ - + diff --git a/conf/directory/default.xml b/conf/directory/default.xml index 1e583033a9..8af7aea135 100644 --- a/conf/directory/default.xml +++ b/conf/directory/default.xml @@ -21,7 +21,7 @@ - + From 143949941c6a1e4ae68c7ebd86957525caf2242a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Nov 2010 21:39:08 -0600 Subject: [PATCH 33/97] add presence-probe-on-register sofia param to send a probe on register instead of presence to deal with some broken phones and add some general improvements to allow multi homed presence --- conf/sip_profiles/internal.xml | 2 + src/mod/endpoints/mod_sofia/mod_sofia.c | 3 +- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 18 ++++++-- src/mod/endpoints/mod_sofia/sofia_presence.c | 47 +++++++++++++------- src/mod/endpoints/mod_sofia/sofia_reg.c | 40 ++++++++--------- 6 files changed, 70 insertions(+), 41 deletions(-) diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 93558a3584..3e756a85c0 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -132,6 +132,8 @@ + + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 3c8404dd6b..3bb926adf3 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3936,7 +3936,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session dest_num = p + 5; } } -#endif + if (profile->pres_type) { char *sql; @@ -3957,6 +3957,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_safe_free(sql); } +#endif caller_profile = switch_caller_profile_clone(nsession, outbound_profile); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index c1244c05f1..6970a7ab05 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -224,6 +224,7 @@ typedef enum { PFLAG_IN_DIALOG_CHAT, PFLAG_DEL_SUBS_ON_REG, PFLAG_IGNORE_183NOSDP, + PFLAG_PRESENCE_PROBE_ON_REGISTER, /* No new flags below this line */ PFLAG_MAX } PFLAGS; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 4d9bd7fd7b..e20d868548 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2405,6 +2405,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP); } + } else if (!strcasecmp(var, "presence-probe-on-register")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } } else if (!strcasecmp(var, "cid-in-1xx")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_CID_IN_1XX); @@ -3070,6 +3076,12 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP); } + } else if (!strcasecmp(var, "presence-probe-on-register")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } } else if (!strcasecmp(var, "cid-in-1xx")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_CID_IN_1XX); @@ -4420,7 +4432,6 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status contact_host, astate, "outbound", user_agent, profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact), switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p)); - switch_assert(sql); sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); @@ -6872,8 +6883,9 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ sql = switch_mprintf - ("select call_id from sip_dialogs where call_info='%q' and sip_from_user='%q' and sip_from_host='%q' and call_id is not null", - switch_str_nil(p), user, host); + ("select call_id from sip_dialogs where call_info='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_id is not null", + switch_str_nil(p), user, host, user, host); if ((str = sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, cid, sizeof(cid)))) { bnh = nua_handle_by_call_id(nua, str); diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 4b853de6b1..95ea913a61 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -567,7 +567,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { - sql = switch_mprintf("select status,rpid from sip_dialogs where sip_from_user='%q' and sip_from_host='%q'", probe_euser, probe_host); + sql = switch_mprintf("select status,rpid from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", + probe_euser, probe_host, probe_euser, probe_host); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); h.profile = profile; @@ -591,9 +592,11 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "'%q','%q' " "from sip_registrations left join sip_dialogs on " - "(sip_dialogs.sip_from_user = sip_registrations.sip_user " - "and (sip_dialogs.sip_from_host = sip_registrations.orig_server_host or " - "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) " + "sip_dialogs.presence_id = sip_registrations.sip_user || '@' || sip_registrations.sip_host " + + + "or (sip_dialogs.sip_from_user = sip_registrations.sip_user " + "and sip_dialogs.sip_from_host = sip_registrations.sip_host) " "left join sip_presence on " "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and " @@ -601,7 +604,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "where sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " "or sip_registrations.presence_hosts like '%%%q%%'))", - dh.status, dh.rpid, probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); + dh.status, dh.rpid, + probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); switch_assert(sql); if (mod_sofia_globals.debug_presence > 0) { @@ -711,9 +715,10 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' where hostname='%q' and uuid='%q'", call_info, call_info_state, mod_sofia_globals.hostname, uuid); } else { - sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and sip_dialogs.sip_from_user='%q' " - "and sip_dialogs.sip_from_host='%q' and call_info='%q'", - call_info, call_info_state, mod_sofia_globals.hostname, euser, host, call_info); + sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and " + "((sip_dialogs.sip_from_user='%q' and sip_dialogs.sip_from_host='%q') or presence_id='%q@%q') and call_info='%q'", + + call_info, call_info_state, mod_sofia_globals.hostname, euser, host, euser, host, call_info); } @@ -737,7 +742,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } - sql = switch_mprintf("select status,rpid from sip_dialogs where sip_from_user='%q' and sip_from_host='%q'", euser, host); + sql = switch_mprintf("select status,rpid from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", + euser, host, euser, host); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); switch_safe_free(sql); @@ -753,17 +759,20 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and " "sip_subscriptions.profile_name=sip_presence.profile_name) " "left join sip_dialogs on " + + "sip_dialogs.presence_id = sip_subscriptions.sub_to_user || '@' || sip_subscriptions.sub_to_host or " + "(sip_dialogs.sip_from_user = sip_subscriptions.sub_to_user " "and sip_dialogs.sip_from_host = sip_subscriptions.sub_to_host) " "where sip_subscriptions.expires > -1 and " - "(event='%q' or event='%q') and (sub_to_user='%q' or sip_dialogs.presence_id like '%q@%%') " + "(event='%q' or event='%q') and sub_to_user='%q' " "and (sub_to_host='%q' or presence_hosts like '%%%q%%') " "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host)", switch_str_nil(status), switch_str_nil(rpid), host, dh.status,dh.rpid, - event_type, alt_event_type, euser, euser, host, host, profile->name))) { + event_type, alt_event_type, euser, host, host, profile->name))) { struct presence_helper helper = { 0 }; @@ -1918,7 +1927,8 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where hostname='%q' " "and sip_from_user='%q' and sip_from_host='%q' ", mod_sofia_globals.hostname, to_user, to_host); + "where hostname='%q' " "and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')' ", + mod_sofia_globals.hostname, to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { @@ -1954,7 +1964,8 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * if (clear) { - sql = switch_mprintf("delete from sip_dialogs where sip_from_user='%q' and sip_from_host='%q' and call_info_state='seized'", to_user, to_host); + sql = switch_mprintf("delete from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_info_state='seized'", to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { @@ -2326,8 +2337,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CANCEL LINE SEIZE\n"); } - sql = switch_mprintf("delete from sip_dialogs where sip_from_user='%q' and sip_from_host='%q' and call_info_state='seized'", - to_user, to_host); + sql = switch_mprintf("delete from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_info_state='seized'", + to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { @@ -2360,8 +2372,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, - sql = switch_mprintf("delete from sip_dialogs where sip_from_user='%q' and sip_from_host='%q' and call_info_state='seized'", - to_user, to_host); + sql = switch_mprintf("delete from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_info_state='seized'", + to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 216f808e4f..e93bdaac08 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1445,27 +1445,27 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } } - -#if 0 - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_fire(&s_event); + if (sofia_test_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER)) { + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_fire(&s_event); + } + } else { + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); + switch_event_fire(&s_event); + } } -#else - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); - switch_event_fire(&s_event); - } -#endif + } else { if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); From 6a9a27b791a231b970b37eadb1ebf927b0c30bea Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 24 Nov 2010 22:13:12 -0600 Subject: [PATCH 34/97] VS2010 fix output paths --- src/mod/codecs/mod_celt/mod_celt.vcxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mod/codecs/mod_celt/mod_celt.vcxproj b/src/mod/codecs/mod_celt/mod_celt.vcxproj index 01c55d4217..ee8a70ca3f 100644 --- a/src/mod/codecs/mod_celt/mod_celt.vcxproj +++ b/src/mod/codecs/mod_celt/mod_celt.vcxproj @@ -62,10 +62,6 @@ <_ProjectFileVersion>10.0.30319.1 - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ From 75bd5642105532f80101fc84849b96996d710a04 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 25 Nov 2010 09:35:14 -0500 Subject: [PATCH 35/97] freetdm: wait for state change to be cleared when placing outgoing calls this fixes a race where the call is hangup even before the state DIALING is processed and therefore the HANGUP state change is ignored. --- libs/freetdm/src/ftdm_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0aeaeedce4..bcceba58ca 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2270,6 +2270,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char UNREFERENCED_PARAMETER(line); #endif + ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100); + ftdm_channel_unlock(ftdmchan); return status; From 37ce4003e129097e179f213c86e00b3307cc1738 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 14:31:30 -0200 Subject: [PATCH 36/97] freetdm: eliminated some warnings from ftmod_r2 windows build --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 52c0f86e6c..bfe49fd8ca 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -889,7 +889,7 @@ static openr2_io_interface_t ftdm_r2_io_iface = { static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) //ftdm_status_t (ftdm_span_t *span, fio_signal_cb_t sig_cb, va_list ap) { - int i = 0; + unsigned int i = 0; int conf_failure = 0; char *var = NULL; char *val = NULL; @@ -1107,11 +1107,6 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) openr2_chan_set_log_level(r2chan, r2conf.loglevel); if (r2conf.call_files) { openr2_chan_enable_call_files(r2chan); -#if 0 - if (r2conf.mf_files) { - openr2_chan_enable_mf_files(r2chan); - } -#endif } r2call = ftdm_malloc(sizeof(*r2call)); @@ -1348,8 +1343,8 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_r2_data_t *r2data = span->signal_data; int waitms = 20; - int i, res; - int ms; + unsigned int i; + int res, ms; struct timeval start, end; short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); ftdm_event_t *event = NULL; @@ -1413,8 +1408,8 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) * XXX */ for (i = 1; i <= span->chan_count; i++) { r2chan = R2CALL(span->channels[i])->r2chan; - r2call = R2CALL(ftdmchan); ftdmchan = openr2_chan_get_client_data(r2chan); + r2call = R2CALL(ftdmchan); ftdm_mutex_lock(ftdmchan->mutex); ftdm_r2_state_advance(ftdmchan); @@ -1487,8 +1482,8 @@ static FIO_API_FUNCTION(ftdm_r2_api) char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; int span_id = 0; - int chan_id = 0; - int i = 0; + unsigned int chan_id = 0; + unsigned int i = 0; ftdm_r2_data_t *r2data = NULL; openr2_chan_t *r2chan = NULL; openr2_context_t *r2context = NULL; From c57c17604c175e9c154d2552c608087a4e98807d Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 25 Nov 2010 10:40:20 -0600 Subject: [PATCH 37/97] Update mod_cepstral for windows vs2010 --- src/mod/asr_tts/mod_cepstral/WinReadme.txt | 4 ++++ .../mod_cepstral/mod_cepstral.2010.vcxproj | 19 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 src/mod/asr_tts/mod_cepstral/WinReadme.txt diff --git a/src/mod/asr_tts/mod_cepstral/WinReadme.txt b/src/mod/asr_tts/mod_cepstral/WinReadme.txt new file mode 100644 index 0000000000..56b4e79a39 --- /dev/null +++ b/src/mod/asr_tts/mod_cepstral/WinReadme.txt @@ -0,0 +1,4 @@ +The Cepstral SDK for Windows should be placed in c:\dev\cepstral +ex. C:\dev\cepstral\sdk\include +This SDK can be obtained from http://cepstral.com/ +If you want a prebuilt version you may download one from http://files.freeswitch.org/windows/installer/ \ No newline at end of file diff --git a/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj b/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj index 2bc46efdca..b7e42eb850 100644 --- a/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj +++ b/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj @@ -66,13 +66,13 @@ - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows;%(AdditionalLibraryDirectories) false @@ -83,13 +83,13 @@ X64 - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows_x64;%(AdditionalLibraryDirectories) false @@ -98,13 +98,13 @@ - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows;%(AdditionalLibraryDirectories) false @@ -115,13 +115,13 @@ X64 - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows_x64;%(AdditionalLibraryDirectories) false @@ -132,9 +132,8 @@ - + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} - false From b7c82d4c2efa974e8c867826253732139f9fb385 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 15:40:44 -0200 Subject: [PATCH 38/97] freetdm: moved ftdm_channel_read_event() to freetdm.h --- libs/freetdm/src/include/freetdm.h | 17 +++++++++++++++++ libs/freetdm/src/include/private/ftdm_core.h | 17 ----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 9ce213c962..eff6305913 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -888,6 +888,23 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_chann /*! \brief Remove the channel from a hunt group */ FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan); +/*! + * \brief Retrieves an event from the span + * + * \note + * This function is non-reentrant and not thread-safe. + * The event returned may be modified if the function is called again + * from a different thread or even the same. It is recommended to + * handle events from the same span in a single thread. + * + * \param span The channel to retrieve the event from + * \param event Pointer to store the pointer to the event + * + * \retval FTDM_SUCCESS success (at least one event available) + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event); + /*! \brief Find a hunt group by id */ FT_DECLARE(ftdm_status_t) ftdm_group_find(uint32_t id, ftdm_group_t **group); diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 7d3ee68176..06f899c8c9 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -615,23 +615,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan); */ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event); -/*! - * \brief Retrieves an event from the span - * - * \note - * This function is non-reentrant and not thread-safe. - * The event returned may be modified if the function is called again - * from a different thread or even the same. It is recommended to - * handle events from the same span in a single thread. - * - * \param span The channel to retrieve the event from - * \param event Pointer to store the pointer to the event - * - * \retval FTDM_SUCCESS success (at least one event available) - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event); - /*! * \brief Enqueue a DTMF string into the channel * From ffbded67fdd5dc177d950be82951d3fa6208cf24 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 25 Nov 2010 12:33:36 -0500 Subject: [PATCH 39/97] freetdm: ftmod_libpri - lock the channel in libpri on_ring callback this should fix potential call_data pointer corruption --- .../freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index cf84dbeebd..c8e865214c 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -495,6 +495,7 @@ static ftdm_state_map_t isdn_state_map = { /** * \brief Handler for channel state change * \param ftdmchan Channel to handle + * \note This function MUST be called with the channel locked */ static __inline__ void state_advance(ftdm_channel_t *chan) { @@ -989,7 +990,16 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event if (!chan) { ftdm_log(FTDM_LOG_ERROR, "-- Unable to get channel %d:%d\n", ftdm_span_get_id(span), pevent->ring.channel); - goto done; + return ret; + } + + ftdm_channel_lock(chan); + + if (chan->call_data) { + /* we could drop the incoming call, but most likely the pointer is just a ghost of the past, + * this check is just to detect potentially unreleased pointers */ + ftdm_log_chan(chan, FTDM_LOG_ERROR, "channel already has call %p!\n", chan->call_data); + chan->call_data = NULL; } if (ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) { @@ -1049,9 +1059,10 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event /* hurr, this is valid as along as nobody releases the call */ chan->call_data = pevent->ring.call; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING); + ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING); done: + ftdm_channel_unlock(chan); return ret; } From 7433a1e5786f91f07f3b13f392596943062b4a13 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 13:16:44 -0500 Subject: [PATCH 40/97] Fix for caller ID not received properly on BRI --- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 20 +-- .../ftmod_sangoma_isdn_stack_hndl.c | 22 +-- .../ftmod_sangoma_isdn_stack_out.c | 30 ++--- .../ftmod_sangoma_isdn_support.c | 125 +++++++++++------- libs/freetdm/src/include/freetdm.h | 6 +- 5 files changed, 115 insertions(+), 88 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 25ffef85e5..a82ed283e1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -376,16 +376,18 @@ void sngisdn_rcv_cc_ind(CcMngmt *status); void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); void sngisdn_rcv_sng_assert(char *message); -ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); -ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); -ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); -ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display); -ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); +ftdm_status_t get_calling_num(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); +ftdm_status_t get_called_num(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); +ftdm_status_t get_redir_num(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); +ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *ftdm, Display *display); +ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *ftdm, UsrUsr *usrUsr); +ftdm_status_t get_facility_ie(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); -ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability); uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 209284a8b6..a541a655d8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -127,10 +127,14 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1"); #endif /* Fill in call information */ - cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); - cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); - cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display); - cpy_redir_num_from_stack(&ftdmchan->caller_data, &conEvnt->redirNmb); + get_calling_num(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); + get_called_num(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); + get_redir_num(&ftdmchan->caller_data, &conEvnt->redirNmb); + + if (get_calling_name_from_display(&ftdmchan->caller_data, &conEvnt->display) != FTDM_SUCCESS) { + get_calling_name_from_usr_usr(&ftdmchan->caller_data, &conEvnt->usrUsr); + } + ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); if (conEvnt->bearCap[0].eh.pres) { @@ -147,7 +151,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) if (conEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); + get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); } else if (signal_data->facility == SNGISDN_OPT_TRUE) { /* Verify whether the Caller Name will come in a subsequent FACILITY message */ uint16_t ret_val; @@ -413,7 +417,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits; ftdm_size_t num_digits; - cpy_called_num_from_stack(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); + get_called_num(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); num_digits = strlen(ftdmchan->caller_data.dnis.digits); if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) { @@ -472,7 +476,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_UP: if (discEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); + get_facility_ie(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -569,7 +573,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) if (relEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); + get_facility_ie(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -785,7 +789,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) ftdm_sigmsg_t sigev; if (facEvnt->facElmt.facStr.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); + get_facility_ie(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 385d1eba9d..36c6782a97 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -35,7 +35,6 @@ #include "ftmod_sangoma_isdn.h" static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prod_ind); -static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { @@ -136,12 +135,11 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) } ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); - cpy_called_num_from_user(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); - cpy_calling_num_from_user(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); - cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data); - cpy_calling_name_from_user(&conEvnt, ftdmchan); - - sngisdn_set_facilityStr(ftdmchan, &conEvnt.facilityStr); + set_called_num(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); + set_calling_num(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); + set_redir_num(&conEvnt.redirNmb, &ftdmchan->caller_data); + set_calling_name(&conEvnt, ftdmchan); + set_facility_ie(ftdmchan, &conEvnt.facilityStr); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -558,7 +556,8 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) discEvnt.causeDgn[0].recommend.pres = NOTPRSNT; discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; - sngisdn_set_facilityStr(ftdmchan, &discEvnt.facilityStr); + set_facility_ie(ftdmchan, &discEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { @@ -604,7 +603,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) spInstId = sngisdn_info->spInstId; } - sngisdn_set_facilityStr(ftdmchan, &relEvnt.facilityStr); + set_facility_ie(ftdmchan, &relEvnt.facilityStr); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId); @@ -647,19 +646,6 @@ static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prog_ return; } -static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ - const char *facility_str = NULL; - - facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); - if (facility_str) { - facilityStr->eh.pres = PRSNT_NODEF; - facilityStr->facilityStr.len = strlen(facility_str); - memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); - } - return; -} - /* We received an incoming frame on the d-channel, send data to the stack */ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 379c481c0e..4ddb90bbd3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -147,76 +147,79 @@ ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) +ftdm_status_t get_calling_num(ftdm_caller_data_t *caller_data, CgPtyNmb *cgPtyNmb) { if (cgPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) { - ftdm->screen = cgPtyNmb->screenInd.val; + caller_data->screen = cgPtyNmb->screenInd.val; } if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) { - ftdm->pres = cgPtyNmb->presInd0.val; + caller_data->pres = cgPtyNmb->presInd0.val; } if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - ftdm->cid_num.plan = cgPtyNmb->nmbPlanId.val; + caller_data->cid_num.plan = cgPtyNmb->nmbPlanId.val; } + if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) { - ftdm->cid_num.type = cgPtyNmb->typeNmb1.val; + caller_data->cid_num.type = cgPtyNmb->typeNmb1.val; } if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) { - ftdm_copy_string(ftdm->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1); + ftdm_copy_string(caller_data->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1); } + memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani)); return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) +ftdm_status_t get_called_num(ftdm_caller_data_t *caller_data, CdPtyNmb *cdPtyNmb) { if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - ftdm->dnis.plan = cdPtyNmb->nmbPlanId.val; + caller_data->dnis.plan = cdPtyNmb->nmbPlanId.val; } if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) { - ftdm->dnis.type = cdPtyNmb->typeNmb0.val; + caller_data->dnis.type = cdPtyNmb->typeNmb0.val; } if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) { - unsigned i = strlen(ftdm->dnis.digits); + /* In overlap receive mode, append the new digits to the existing dnis */ + unsigned i = strlen(caller_data->dnis.digits); - ftdm_copy_string(&ftdm->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1); + ftdm_copy_string(&caller_data->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1); } return FTDM_SUCCESS; } -ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) +ftdm_status_t get_redir_num(ftdm_caller_data_t *caller_data, RedirNmb *redirNmb) { if (redirNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) { - ftdm->rdnis.plan = redirNmb->nmbPlanId.val; + caller_data->rdnis.plan = redirNmb->nmbPlanId.val; } if (redirNmb->typeNmb.pres == PRSNT_NODEF) { - ftdm->rdnis.type = redirNmb->typeNmb.val; + caller_data->rdnis.type = redirNmb->typeNmb.val; } if (redirNmb->nmbDigits.pres == PRSNT_NODEF) { - ftdm_copy_string(ftdm->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1); + ftdm_copy_string(caller_data->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1); } return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display) +ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *caller_data, Display *display) { if (display->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -225,11 +228,29 @@ ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *dis return FTDM_FAIL; } - ftdm_copy_string(ftdm->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1); + ftdm_copy_string(caller_data->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1); return FTDM_SUCCESS; } -ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) +ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *caller_data, UsrUsr *usrUsr) +{ + if (usrUsr->eh.pres != PRSNT_NODEF) { + return FTDM_FAIL; + } + + if (usrUsr->protocolDisc.val != PD_IA5) { + return FTDM_FAIL; + } + + if (usrUsr->usrInfo.pres != PRSNT_NODEF) { + return FTDM_FAIL; + } + + ftdm_copy_string(caller_data->cid_name, (const char*)usrUsr->usrInfo.val, usrUsr->usrInfo.len+1); + return FTDM_SUCCESS; +} + +ftdm_status_t get_facility_ie(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) { if (data_len > sizeof(caller_data->raw_data)-2) { ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n"); @@ -247,67 +268,67 @@ ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *caller_data, uint8_ return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *caller_data) { - uint8_t len = strlen(ftdm->cid_num.digits); + uint8_t len = strlen(caller_data->cid_num.digits); if (!len) { return FTDM_SUCCESS; } cgPtyNmb->eh.pres = PRSNT_NODEF; cgPtyNmb->screenInd.pres = PRSNT_NODEF; - cgPtyNmb->screenInd.val = ftdm->screen; + cgPtyNmb->screenInd.val = caller_data->screen; cgPtyNmb->presInd0.pres = PRSNT_NODEF; - cgPtyNmb->presInd0.val = ftdm->pres; - + cgPtyNmb->presInd0.val = caller_data->pres; + cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - cgPtyNmb->nmbPlanId.val = ftdm->cid_num.plan; + cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan; cgPtyNmb->typeNmb1.pres = PRSNT_NODEF; - cgPtyNmb->typeNmb1.val = ftdm->cid_num.type; + cgPtyNmb->typeNmb1.val = caller_data->cid_num.type; cgPtyNmb->nmbDigits.pres = PRSNT_NODEF; cgPtyNmb->nmbDigits.len = len; - memcpy(cgPtyNmb->nmbDigits.val, ftdm->cid_num.digits, len); + memcpy(cgPtyNmb->nmbDigits.val, caller_data->cid_num.digits, len); return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *caller_data) { - uint8_t len = strlen(ftdm->dnis.digits); + uint8_t len = strlen(caller_data->dnis.digits); if (!len) { return FTDM_SUCCESS; } cdPtyNmb->eh.pres = PRSNT_NODEF; cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - if (ftdm->dnis.plan == FTDM_NPI_INVALID) { + if (caller_data->dnis.plan == FTDM_NPI_INVALID) { cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN; } else { - cdPtyNmb->nmbPlanId.val = ftdm->dnis.plan; + cdPtyNmb->nmbPlanId.val = caller_data->dnis.plan; } cdPtyNmb->typeNmb0.pres = PRSNT_NODEF; - if (ftdm->dnis.type == FTDM_TON_INVALID) { + if (caller_data->dnis.type == FTDM_TON_INVALID) { cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN; } else { - cdPtyNmb->typeNmb0.val = ftdm->dnis.type; + cdPtyNmb->typeNmb0.val = caller_data->dnis.type; } cdPtyNmb->nmbDigits.pres = PRSNT_NODEF; cdPtyNmb->nmbDigits.len = len; - memcpy(cdPtyNmb->nmbDigits.val, ftdm->dnis.digits, len); + memcpy(cdPtyNmb->nmbDigits.val, caller_data->dnis.digits, len); return FTDM_SUCCESS; } -ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *caller_data) { - uint8_t len = strlen(ftdm->rdnis.digits); + uint8_t len = strlen(caller_data->rdnis.digits); if (!len) { return FTDM_SUCCESS; } @@ -315,36 +336,36 @@ ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ft redirNmb->eh.pres = PRSNT_NODEF; redirNmb->nmbPlanId.pres = PRSNT_NODEF; - if (ftdm->rdnis.plan == FTDM_NPI_INVALID) { + if (caller_data->rdnis.plan == FTDM_NPI_INVALID) { redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN; } else { - redirNmb->nmbPlanId.val = ftdm->rdnis.plan; + redirNmb->nmbPlanId.val = caller_data->rdnis.plan; } redirNmb->typeNmb.pres = PRSNT_NODEF; - if (ftdm->rdnis.type == FTDM_TON_INVALID) { + if (caller_data->rdnis.type == FTDM_TON_INVALID) { redirNmb->typeNmb.val = FTDM_TON_UNKNOWN; } else { - redirNmb->typeNmb.val = ftdm->rdnis.type; + redirNmb->typeNmb.val = caller_data->rdnis.type; } redirNmb->nmbDigits.pres = PRSNT_NODEF; redirNmb->nmbDigits.len = len; - memcpy(redirNmb->nmbDigits.val, ftdm->rdnis.digits, len); + memcpy(redirNmb->nmbDigits.val, caller_data->rdnis.digits, len); return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) { uint8_t len; - ftdm_caller_data_t *ftdm = &ftdmchan->caller_data; + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; /* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - len = strlen(ftdm->cid_name); + len = strlen(caller_data->cid_name); if (!len) { return FTDM_SUCCESS; } @@ -359,7 +380,7 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc conEvnt->usrUsr.usrInfo.len = len; /* in sangoma_brid we used to send usr-usr info as !, change to previous style if current one does not work */ - memcpy(conEvnt->usrUsr.usrInfo.val, ftdm->cid_name, len); + memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len); } else { switch (signal_data->switchtype) { case SNGISDN_SWITCH_NI2: @@ -377,7 +398,7 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc conEvnt->display.eh.pres = PRSNT_NODEF; conEvnt->display.dispInfo.pres = PRSNT_NODEF; conEvnt->display.dispInfo.len = len; - memcpy(conEvnt->display.dispInfo.val, ftdm->cid_name, len); + memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len); break; case SNGISDN_SWITCH_QSIG: /* It seems like QSIG does not support Caller ID Name */ @@ -390,6 +411,20 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc return FTDM_SUCCESS; } +ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) +{ + const char *facility_str = NULL; + + facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); + if (facility_str) { + facilityStr->eh.pres = PRSNT_NODEF; + facilityStr->facilityStr.len = strlen(facility_str); + memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); + return FTDM_SUCCESS; + } + return FTDM_FAIL; +} + void sngisdn_t3_timeout(void* p_sngisdn_info) { sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 87da5d1dd0..014eeef852 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -285,7 +285,7 @@ typedef enum { /*! \brief Signaling messages sent by the stacks */ typedef enum { - FTDM_SIGEVENT_START, /*!< Incoming call (ie: incoming SETUP msg or Ring) */ + FTDM_SIGEVENT_START,/*!< Incoming call (ie: incoming SETUP msg or Ring) */ FTDM_SIGEVENT_STOP, /*!< Hangup */ FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */ FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */ @@ -300,12 +300,12 @@ typedef enum { FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */ FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */ FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */ - FTDM_SIGEVENT_MSG, /* !< We received an in-call msg */ + FTDM_SIGEVENT_MSG, /*!< We received an in-call msg */ FTDM_SIGEVENT_INVALID } ftdm_signal_event_t; #define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \ "PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \ - "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "INVALID" + "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "MSG", "INVALID" /*! \brief Move from string to ftdm_signal_event_t and viceversa */ FTDM_STR2ENUM_P(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t) From c9fa092a9ef7a48ee702a729da2d8c30f62e7d65 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 25 Nov 2010 13:22:41 -0600 Subject: [PATCH 41/97] VS2010 add mod_cepstral to Setup --- w32/Setup/Setup.wixproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/w32/Setup/Setup.wixproj b/w32/Setup/Setup.wixproj index 7d11c90a4b..fa6c832777 100644 --- a/w32/Setup/Setup.wixproj +++ b/w32/Setup/Setup.wixproj @@ -336,6 +336,15 @@ Binaries;Content;Satellites MODLOCATION + + mod_cepstral + {692f6330-4d87-4c82-81df-40db5892636e} + True + + + Binaries;Content;Satellites + MODLOCATION + mod_pocketsphinx {2286da73-9fc5-45bc-a508-85994c3317ab} From b8fb8acca152a5850b4a0fa4c0625f0094909059 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 16:16:36 -0500 Subject: [PATCH 42/97] freetdm: ISDN allow change state from PROCEED to UP --- libs/freetdm/src/ftdm_io.c | 7 ++++++- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 3 ++- .../ftmod_sangoma_isdn_stack_hndl.c | 11 +++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index ede3ff8fc8..6f543304a2 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2033,6 +2033,11 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char goto done; } +#if 0 + /* DAVIDY - We will fail RFC's if we do that, but some modules apart from ftmod_sangoma_isdn + * expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so + * remove this only in netborder branch for now */ + if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } @@ -2052,7 +2057,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n"); goto done; } - +#endif ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1); done: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 6f5f838590..9aa52f816c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -121,7 +121,8 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_PROCEED, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,FTDM_END} + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, + FTDM_CHANNEL_STATE_UP, FTDM_END} }, { ZSD_INBOUND, diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index a541a655d8..f10fa766e3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -377,18 +377,17 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) switch(ftdmchan->state) { case FTDM_CHANNEL_STATE_DIALING: - if (evntType == MI_CALLPROC) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); - } else if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + } else if (evntType == MI_CALLPROC) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); } else { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); } break; + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: - if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } break; From 2973776b6480309a5fe95aa8b2a3ba5151288c6b Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 16:36:49 -0500 Subject: [PATCH 43/97] changed set_facility_ie --- Freeswitch.2008.sln | 20 +++++-------------- .../ftmod_sangoma_isdn_support.c | 12 +++++------ 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 01a4cf43c1..4ffd66abac 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -36,7 +36,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Default", "Default", "{3B08FEFD-4D3D-4C16-BA94-EE83509E32A0}" ProjectSection(SolutionItems) = preProject conf\freeswitch.xml = conf\freeswitch.xml - conf\vars.xml = conf\vars.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Release", "Release", "{7BFD517E-7F8F-4A40-A78E-8D3632738227}" @@ -57,7 +56,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Build System", "_Build Sys bootstrap.sh = bootstrap.sh build\buildlib.sh = build\buildlib.sh configure.in = configure.in - Makefile.am = Makefile.am build\modmake.rules.in = build\modmake.rules.in build\modules.conf.in = build\modules.conf.in libs\win32\util.vbs = libs\win32\util.vbs @@ -92,15 +90,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa conf\autoload_configs\limit.conf.xml = conf\autoload_configs\limit.conf.xml conf\autoload_configs\local_stream.conf.xml = conf\autoload_configs\local_stream.conf.xml conf\autoload_configs\logfile.conf.xml = conf\autoload_configs\logfile.conf.xml - conf\autoload_configs\modules.conf.xml = conf\autoload_configs\modules.conf.xml conf\autoload_configs\openmrcp.conf.xml = conf\autoload_configs\openmrcp.conf.xml conf\autoload_configs\portaudio.conf.xml = conf\autoload_configs\portaudio.conf.xml conf\autoload_configs\rss.conf.xml = conf\autoload_configs\rss.conf.xml conf\autoload_configs\sofia.conf.xml = conf\autoload_configs\sofia.conf.xml conf\autoload_configs\spidermonkey.conf.xml = conf\autoload_configs\spidermonkey.conf.xml - conf\autoload_configs\switch.conf.xml = conf\autoload_configs\switch.conf.xml conf\autoload_configs\syslog.conf.xml = conf\autoload_configs\syslog.conf.xml - conf\autoload_configs\voicemail.conf.xml = conf\autoload_configs\voicemail.conf.xml conf\autoload_configs\wanpipe.conf.xml = conf\autoload_configs\wanpipe.conf.xml conf\autoload_configs\woomera.conf.xml = conf\autoload_configs\woomera.conf.xml conf\autoload_configs\xml_cdr.conf.xml = conf\autoload_configs\xml_cdr.conf.xml @@ -111,7 +106,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{C7E2382E-2C22-4D18-BF93-80C6A1FFA7AC}" ProjectSection(SolutionItems) = preProject - conf\dialplan\default.xml = conf\dialplan\default.xml conf\dialplan\public.xml = conf\dialplan\public.xml EndProjectSection EndProject @@ -123,7 +117,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sip_profiles", "sip_profiles", "{8E2E8798-8B6F-4A55-8E4F-4E6FDE40ED26}" ProjectSection(SolutionItems) = preProject conf\sip_profiles\external.xml = conf\sip_profiles\external.xml - conf\sip_profiles\internal.xml = conf\sip_profiles\internal.xml conf\sip_profiles\nat.xml = conf\sip_profiles\nat.xml EndProjectSection EndProject @@ -308,9 +301,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{23874F4B-C0AF-4587-9F7E-DB0F06DE8CB4}" - ProjectSection(SolutionItems) = preProject - conf\dialplan\default.xml = conf\dialplan\default.xml - EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "directory", "directory", "{19ED97F6-30D8-4FCE-AE1D-8B7FCB170D40}" ProjectSection(SolutionItems) = preProject @@ -1271,15 +1261,15 @@ Global {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|Win32.Build.0 = Release|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.Build.0 = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.Build.0 = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.Build.0 = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.Build.0 = Debug|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.Build.0 = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.Build.0 = Release|x64 diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 4ddb90bbd3..c9aa3f035c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -412,14 +412,12 @@ ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) } ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ - const char *facility_str = NULL; - - facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); - if (facility_str) { +{ + if (ftdmchan->caller_data.raw_data_len && + ftdmchan->caller_data.raw_data[0] == 0x1C) { facilityStr->eh.pres = PRSNT_NODEF; - facilityStr->facilityStr.len = strlen(facility_str); - memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); + facilityStr->facilityStr.len = ftdmchan->caller_data.raw_data_len-2; + memcpy(facilityStr->facilityStr.val, &ftdmchan->caller_data.raw_data[2], facilityStr->facilityStr.len); return FTDM_SUCCESS; } return FTDM_FAIL; From 5c747b699cfe3b2e19a3dc66a815cf7bfc9574a0 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 18:54:15 -0500 Subject: [PATCH 44/97] Fix for receiving/transmitting facility IE --- .../ftmod_sangoma_isdn_stack_hndl.c | 23 ++++++++++--------- .../ftmod_sangoma_isdn_stack_out.c | 2 -- .../ftmod_sangoma_isdn_support.c | 4 +++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index f10fa766e3..f3fc23e317 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -142,21 +142,22 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); } - if (signal_data->switchtype == SNGISDN_SWITCH_NI2) { - if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { - if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { - snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); - } + + if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { + if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { + snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); } + } - if (conEvnt->facilityStr.eh.pres) { - if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); - } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + if (conEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); + } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + if (signal_data->switchtype == SNGISDN_SWITCH_NI2) { /* Verify whether the Caller Name will come in a subsequent FACILITY message */ uint16_t ret_val; char retrieved_str[255]; - + ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); /* return values for "sng_isdn_retrieve_facility_information_following": @@ -170,7 +171,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); /* Launch timer in case we never get a FACILITY msg */ if (signal_data->facility_timeout) { - ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, + ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); } break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 36c6782a97..1b906a2004 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -412,7 +412,6 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - cnStEvnt.chanId.eh.pres = PRSNT_NODEF; cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF; cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE; @@ -557,7 +556,6 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; set_facility_ie(ftdmchan, &discEvnt.facilityStr); - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index c9aa3f035c..241bb43a90 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -412,14 +412,16 @@ ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) } ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ +{ if (ftdmchan->caller_data.raw_data_len && ftdmchan->caller_data.raw_data[0] == 0x1C) { facilityStr->eh.pres = PRSNT_NODEF; + facilityStr->facilityStr.pres = PRSNT_NODEF; facilityStr->facilityStr.len = ftdmchan->caller_data.raw_data_len-2; memcpy(facilityStr->facilityStr.val, &ftdmchan->caller_data.raw_data[2], facilityStr->facilityStr.len); return FTDM_SUCCESS; } + return FTDM_FAIL; } From 1bd4de4fd95c4dc33a379f537f93ab36f4134d5f Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 22:11:20 -0200 Subject: [PATCH 45/97] freetdm: when protocol errors occurs on ftmod_r2, the channel state is properly set as down now --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 42 +++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index bfe49fd8ca..f089846fae 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -67,9 +67,9 @@ typedef struct ftdm_r2_call_t { ftdm_r2_call_flag_t flags; int accepted:1; int answer_pending:1; - int state_ack_pending:1; int disconnect_rcvd:1; int ftdm_started:1; + int protocol_error:1; ftdm_channel_state_t chanstate; ftdm_size_t dnis_index; ftdm_size_t ani_index; @@ -456,10 +456,12 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m openr2_chan_disable_read(r2chan); R2CALL(ftdmchan)->accepted = 1; if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { - R2CALL(ftdmchan)->state_ack_pending = 1; + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); + ftdm_channel_complete_state(ftdmchan); if (R2CALL(ftdmchan)->answer_pending) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answer was pending, answering now.\n"); ft_r2_answer_call(ftdmchan); + R2CALL(ftdmchan)->answer_pending = 0; return; } } else { @@ -522,7 +524,7 @@ static void ftdm_r2_on_call_end(openr2_chan_t *r2chan) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call finished\n"); /* the call is done as far as the stack is concerned, lets move to down here */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); /* in some circumstances openr2 can call on_call_init right after this, so let's advance the state right here */ ftdm_r2_state_advance(ftdmchan); @@ -560,6 +562,7 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n"); R2CALL(ftdmchan)->disconnect_rcvd = 1; + R2CALL(ftdmchan)->protocol_error = 1; if (!R2CALL(ftdmchan)->ftdm_started) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); @@ -1173,13 +1176,13 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ret = 0; - if (R2CALL(ftdmchan)->state_ack_pending) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); - R2CALL(ftdmchan)->state_ack_pending = 0; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) { + /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept + * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this + * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting + * to complete (the processing is media-bound) + * */ + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) + && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); R2CALL(ftdmchan)->chanstate = ftdmchan->state; @@ -1188,10 +1191,15 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS || ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || ftdmchan->state == FTDM_CHANNEL_STATE_UP) ) { - /* if an accept ack will be required we should not acknowledge the state change just yet, - it will be done below after processing the MF signals, otherwise we have a race condition between freetdm calling - openr2_chan_answer_call and openr2 accepting the call first, if freetdm calls openr2_chan_answer_call before the accept cycle - completes, openr2 will fail to answer the call */ + /* + Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call, and accepting + the call in R2 means sending a tone, then waiting for the acknowledge from the other end, + since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100) + which means during that time the user should not try to perform any operations like answer, hangup or anything + else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block + the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag, + otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first, + if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state)); } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); @@ -1289,9 +1297,12 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) if (!R2CALL(ftdmchan)->disconnect_rcvd) { /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ openr2_chan_disconnect_call(r2chan, disconnect_cause); - } else { + } else if (!R2CALL(ftdmchan)->protocol_error) { /* just ack the hangup, on_call_end will be called by openr2 right after */ openr2_chan_disconnect_call(r2chan, disconnect_cause); + } else { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Clearing call due to protocol error\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } } break; @@ -1347,7 +1358,6 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) int res, ms; struct timeval start, end; short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); - ftdm_event_t *event = NULL; #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); From 54a3c95cb0aeb52ca1b8f6cbb80ca0e5d0afdf39 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 25 Nov 2010 23:42:36 -0500 Subject: [PATCH 46/97] freetdm: add r2 loop timing statistics --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 64 +++++++++++++++++----- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index f089846fae..06d1abdc04 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -123,11 +123,13 @@ typedef struct ftdm_r2_data_s { /* whether accept the call when offered, or wait until the user decides to accept */ int accept_on_offer:1; /* max time spent in ms doing real work in a single loop */ - int jobmax; - /* total working loops */ - unsigned long loops; + int32_t jobmax; + /* Total number of loops performed so far */ + uint64_t total_loops; + /* number of loops per 10ms increment from 0-9ms, 10-19ms .. 100ms and above */ + uint64_t loops[11]; /* LWP */ - unsigned long monitor_thread_id; + uint32_t monitor_thread_id; } ftdm_r2_data_t; /* one element per span will be stored in g_mod_data_hash global var to keep track of them @@ -1356,8 +1358,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) int waitms = 20; unsigned int i; int res, ms; + int index = 0; struct timeval start, end; - short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); + short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); @@ -1374,14 +1377,20 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) memset(&start, 0, sizeof(start)); memset(&end, 0, sizeof(end)); while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) { - r2data->loops++; res = gettimeofday(&end, NULL); if (start.tv_sec) { ms = ((end.tv_sec - start.tv_sec) * 1000) + ((( 1000000 + end.tv_usec - start.tv_usec) / 1000) - 1000); + if (ms < 0) { + ms = 0; + } if (ms > r2data->jobmax) { r2data->jobmax = ms; } + index = (ms / 10); + index = (index > 10) ? 10 : index; + r2data->loops[index]++; + r2data->total_loops++; } #ifndef WIN32 @@ -1576,7 +1585,7 @@ static FIO_API_FUNCTION(ftdm_r2_api) goto done; } if (!(r2data = span->signal_data)) { - stream->write_function(stream, "-ERR invalid span. No R2 singal data in span.\n"); + stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n"); goto done; } r2context = r2data->r2context; @@ -1587,19 +1596,17 @@ static FIO_API_FUNCTION(ftdm_r2_api) "Max DNIS: %d\n" "ANI First: %s\n" "Immediate Accept: %s\n" - "Side: %s\n" + "Job Thread: %lu\n" "Job Max ms: %d\n" - "Job Loops: %lu\n" - "Monitor Thread: %lu\n", + "Job Loops: %lu\n", openr2_proto_get_variant_string(r2variant), openr2_context_get_max_ani(r2context), openr2_context_get_max_dnis(r2context), openr2_context_get_ani_first(r2context) ? "Yes" : "No", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", - "no side", + r2data->monitor_thread_id, r2data->jobmax, - r2data->loops, - r2data->monitor_thread_id); + r2data->total_loops); stream->write_function(stream, "\n"); stream->write_function(stream, "%4s %-12.12s %-12.12s\n", "Channel", "Tx CAS", "Rx CAS"); for (i = 1; i <= span->chan_count; i++) { @@ -1618,6 +1625,37 @@ static FIO_API_FUNCTION(ftdm_r2_api) } } + if (!strcasecmp(argv[0], "loopstats")) { + int range; + span_id = atoi(argv[1]); + + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { + if (span->start != ftdm_r2_start) { + stream->write_function(stream, "-ERR not an R2 span.\n"); + goto done; + } + if (!(r2data = span->signal_data)) { + stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n"); + goto done; + } + range = 0; + for (i = 0; i < ftdm_array_len(r2data->loops); i++) { + if ((i + 1) == ftdm_array_len(r2data->loops)) { + stream->write_function(stream, ">= %dms: %llu\n", range, r2data->loops[i]); + } else { + stream->write_function(stream, "%d-%dms: %llu\n", range, range + 9, r2data->loops[i]); + } + range += 10; + } + stream->write_function(stream, "\n"); + stream->write_function(stream, "+OK.\n"); + goto done; + } else { + stream->write_function(stream, "-ERR invalid span.\n"); + goto done; + } + } + } if (argc == 1) { From c7aefe934fc6d603b7756406528f6881af198b0b Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Fri, 26 Nov 2010 06:44:57 -0600 Subject: [PATCH 47/97] gsmopen: retry serial initialization if failed, zeroing audio buffers, slower retry on soundcard busy (EAGAIN) --- src/mod/endpoints/mod_gsmopen/gsmopen.h | 2 +- .../mod_gsmopen/gsmopen_protocol.cpp | 20 +++++++++++--- src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp | 27 +++++++++++++------ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen.h b/src/mod/endpoints/mod_gsmopen/gsmopen.h index fd94bccc2a..05ef1641bf 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen.h +++ b/src/mod/endpoints/mod_gsmopen/gsmopen.h @@ -158,7 +158,7 @@ typedef enum { #define WARNINGA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "rev "GSMOPEN_SVN_VERSION "[%p|%-7lx][WARNINGA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ ); #define NOTICA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "rev "GSMOPEN_SVN_VERSION "[%p|%-7lx][NOTICA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ ); -#define GSMOPEN_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->phone_callflow : -1 +#define GSMOPEN_P_LOG (void *)NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->phone_callflow : -1 /*********************************/ #define GSMOPEN_CAUSE_NORMAL 1 diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp index e4bb6b9200..76d32ac3f0 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp @@ -3294,12 +3294,18 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) time_t now_timestamp; /* size_t frames = 0; */ snd_pcm_state_t state; - snd_pcm_sframes_t delayp1; - snd_pcm_sframes_t delayp2; + snd_pcm_sframes_t delayp1=0; + snd_pcm_sframes_t delayp2=0; if(tech_pvt->no_sound==1){ return res; } + + + memset(sizbuf, 255, sizeof(sizbuf)); + memset(sizbuf2, 255, sizeof(sizbuf)); + memset(silencebuf, 255, sizeof(sizbuf)); + //ERRORA("data=%p, datalen=%d\n", GSMOPEN_P_LOG, (void *)data, datalen); /* We have to digest the frame in 160-byte portions */ if (datalen > sizeof(sizbuf) - sizpos) { @@ -3307,8 +3313,11 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) res = -1; } else { memcpy(sizbuf + sizpos, data, datalen); + memset(data, 255, datalen); len += datalen; pos = 0; + + #ifdef ALSA_MONITOR alsa_monitor_write(sizbuf, len); #endif @@ -3456,6 +3465,7 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) if (res == -ESTRPIPE) { ERRORA("You've got some big problems\n", GSMOPEN_P_LOG); } else if (res == -EAGAIN) { + DEBUGA_GSMOPEN("Momentarily busy\n", GSMOPEN_P_LOG); res = 0; } else if (res < 0) { ERRORA("Error %d on audio write: \"%s\"\n", GSMOPEN_P_LOG, res, snd_strerror(res)); @@ -3572,9 +3582,11 @@ int alsa_read(private_t * tech_pvt, short *data, int datalen) return r; } else if (r == -EAGAIN) { - DEBUGA_GSMOPEN("ALSA read -EAGAIN, the soundcard is not ready to be read by gsmopen\n", GSMOPEN_P_LOG); + int count=0; while (r == -EAGAIN) { - gsmopen_sleep(1000); + gsmopen_sleep(10000); + DEBUGA_GSMOPEN("%d ALSA read -EAGAIN, the soundcard is not ready to be read by gsmopen\n", GSMOPEN_P_LOG, count); + count++; if (tech_pvt->alsa_capture_is_mono) { r = snd_pcm_readi(tech_pvt->alsac, buf + readpos, left); diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index cb440d3bcb..7e20b7c25e 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -1904,14 +1904,25 @@ static switch_status_t load_config(int reload_type) if (globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol != PROTOCOL_NO_SERIAL) { res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]); if (res) { - ERRORA("gsmopen_serial_config failed\n", GSMOPEN_P_LOG); - ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id); - //return SWITCH_STATUS_FALSE; - globals.GSMOPEN_INTERFACES[interface_id].running=0; - alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed"); - globals.GSMOPEN_INTERFACES[interface_id].active=0; - globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0'; - continue; + int count = 0; + ERRORA("gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG); + while(res && count < 5){ + switch_sleep(100000); //0.1 seconds + res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]); + count++; + if (res) { + ERRORA("%d: gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG, count); + } + } + if (res) { + ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id); + //return SWITCH_STATUS_FALSE; + globals.GSMOPEN_INTERFACES[interface_id].running=0; + alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed"); + globals.GSMOPEN_INTERFACES[interface_id].active=0; + globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0'; + continue; + } } } From 599a200509e4f164aa494e1798f61e8138d5d20a Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Fri, 26 Nov 2010 07:05:16 -0600 Subject: [PATCH 48/97] skypopen: adding osscuse directory, lot of news to come in some days ;) --- .../mod_skypopen/osscuse/98-osscuse.rules | 7 + .../endpoints/mod_skypopen/osscuse/LICENSE | 339 +++ .../endpoints/mod_skypopen/osscuse/Makefile | 69 + src/mod/endpoints/mod_skypopen/osscuse/README | 119 + .../mod_skypopen/osscuse/ossp-alsap.c | 613 +++++ .../mod_skypopen/osscuse/ossp-slave.c | 250 ++ .../mod_skypopen/osscuse/ossp-slave.h | 28 + .../mod_skypopen/osscuse/ossp-util.c | 369 +++ .../mod_skypopen/osscuse/ossp-util.h | 609 +++++ src/mod/endpoints/mod_skypopen/osscuse/ossp.c | 83 + src/mod/endpoints/mod_skypopen/osscuse/ossp.h | 117 + .../endpoints/mod_skypopen/osscuse/osspd.c | 2374 +++++++++++++++++ 12 files changed, 4977 insertions(+) create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/LICENSE create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/Makefile create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/README create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp.h create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/osspd.c diff --git a/src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules b/src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules new file mode 100644 index 0000000000..c1430fd5c0 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules @@ -0,0 +1,7 @@ +# Since these devices are not part of 'sound' subsystem the group is forced +# to audio by name +# /dev/cuse can stay mode 0660 root:root since osspd is run as root +# and drops privileges to user level when opened by user +KERNEL=="dsp", GROUP="audio" +KERNEL=="mixer", GROUP="audio" +KERNEL=="adsp", GROUP="audio" diff --git a/src/mod/endpoints/mod_skypopen/osscuse/LICENSE b/src/mod/endpoints/mod_skypopen/osscuse/LICENSE new file mode 100644 index 0000000000..d511905c16 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/src/mod/endpoints/mod_skypopen/osscuse/Makefile b/src/mod/endpoints/mod_skypopen/osscuse/Makefile new file mode 100644 index 0000000000..a42d37a8a3 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/Makefile @@ -0,0 +1,69 @@ +# These can be overridden if needed +# DESTDIR is completely respected +CC := gcc +AR := ar +CFLAGS := -Wall $(CFLAGS) +XLDFLAGS := $(LDFLAGS) +LDFLAGS := -L. -lossp $(LDFLAGS) +prefix := /usr/local +DESTDIR := +UDEVDIR := /etc/udev/rules.d + +ifeq "$(origin OSSPD_CFLAGS)" "undefined" +OSSPD_CFLAGS := $(shell pkg-config --cflags fuse) +endif + +ifeq "$(origin OSSPD_LDFLAGS)" "undefined" +OSSPD_LDFLAGS := $(shell pkg-config --libs fuse) +endif + +ifeq "$(origin OSSP_PADSP_CFLAGS)" "undefined" +OSSP_PADSP_CFLAGS := $(shell pkg-config --cflags libpulse) +endif + +ifeq "$(origin OSSP_PADSP_LDFLAGS)" "undefined" +OSSP_PADSP_LDFLAGS := $(shell pkg-config --libs libpulse) +endif + +ifeq "$(origin OSSP_ALSAP_CFLAGS)" "undefined" +OSSP_ALSAP_CFLAGS := $(shell pkg-config --libs alsa) +endif + +ifeq "$(origin OSSP_ALSAP_LDFLAGS)" "undefined" +OSSP_ALSAP_LDFLAGS := $(shell pkg-config --libs alsa) +endif + +headers := ossp.h ossp-util.h ossp-slave.h + +#all: osspd ossp-padsp ossp-alsap +all: osspd ossp-alsap + +install: + mkdir -p $(DESTDIR)$(prefix)/sbin + install -m755 osspd ossp-padsp ossp-alsap $(DESTDIR)$(prefix)/sbin + mkdir -p $(DESTDIR)$(UDEVDIR) + install -m644 98-osscuse.rules $(DESTDIR)$(UDEVDIR) + +libossp.a: ossp.c ossp.h ossp-util.c ossp-util.h ossp-slave.c ossp-slave.h + $(CC) $(CFLAGS) -c -o ossp.o ossp.c + $(CC) $(CFLAGS) -c -o ossp-util.o ossp-util.c + $(CC) $(CFLAGS) -c -o ossp-slave.o ossp-slave.c + $(AR) rc $@ ossp.o ossp-util.o ossp-slave.o + +osspd: osspd.c libossp.a $(headers) + $(CC) $(CFLAGS) $(OSSPD_CFLAGS) -o $@ $< $(OSSPD_LDFLAGS) $(LDFLAGS) + +ossp-padsp: ossp-padsp.c libossp.a $(headers) + $(CC) $(CFLAGS) $(OSSP_PADSP_CFLAGS) -o $@ $< $(OSSP_PADSP_LDFLAGS) $(LDFLAGS) + +ossp-alsap: ossp-alsap.c libossp.a $(headers) + $(CC) $(CFLAGS) $(OSSP_ALSAP_CFLAGS) -o $@ $< $(OSSP_ALSAP_LDFLAGS) $(LDFLAGS) + +osstest: osstest.c + $(CC) $(CFLAGS) -o $@ $< $(XLDFLAGS) + +test: osstest + @./osstest + +clean: + rm -f *.o *.a osspd ossp-padsp ossp-alsap osstest diff --git a/src/mod/endpoints/mod_skypopen/osscuse/README b/src/mod/endpoints/mod_skypopen/osscuse/README new file mode 100644 index 0000000000..6b716c76e4 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/README @@ -0,0 +1,119 @@ + + OSS Proxy - emulate OSS device using CUSE + + Copyright (C) 2008-2009 SUSE Linux Products GmbH + Copyright (C) 2008-2009 Tejun Heo + +1. What is it? +-------------- + +Well, first, OSS refers to Open Sound System. If it still doesn't +ring a bell, think /dev/dsp, /dev/adsp and /dev/mixer. + +Currently, Linux supports two audio programming interface - ALSA and +OSS. The latter one is deprecated and has been that way for a long +time but there still are applications which still use them including +UML (usermode Linux) host sound support. + +ALSA contains OSS emulation but sadly the emulation is behind +multiplexing layer (which is in userland) which means that if your +sound card doesn't support multiple audio streams, only either one of +ALSA or OSS interface would be usable at any given moment. + +There have been also attempts to emulate OSS in userland using dynamic +library preloading - aoss and more recently padsp. This works for +many applications but it's just not easy to emulate everything using +the technique. Things like polling, signals, forking, privilege +changes make it very difficult to emulate things reliably. + +OSS Proxy uses CUSE (extension of FUSE allowing character devices to +be implemented in userspace) to implement OSS interface - /dev/dsp, +/dev/adsp and /dev/mixer. From the POV of the applications, these +devices are proper character devices and behave exactly the same way +so it can be made quite versatile. + + +2. Hmmm... So, how does the whole thing work? +--------------------------------------------- + +The OSS Proxy daemon - osspd - should be started first. Note that +osspd will fail to start if sound device number regions are already +occupied. You'll need to turn off OSS or its emulation[1]. + +On startup, osspd creates /dev/dsp, /dev/adsp and /dev/mixer using +CUSE. When an application access one of the devices, all IOs are +redirected to osspd via CUSE. Upon receiving a new DSP open request, +osspd creates a slave process which drops the root privilege and +assumes the opening process's credentials. After handshaking, osspd +forwards all relevant IOs to the slave which is responsible for +actually playing the sound. + +Currently there's only one slave implemented - ossp-padsp, which as +the name suggests forwards (again) the sound to pulseaudio. To sum +up, the whole pipe looks like the following. + + App <-> /dev/dsp <-> CUSE <-> osspd <-> ossp-padsp <-> pulseaudio + +Which is a lot of forwarding, but on modern machines, it won't be too +noticeable. + + +3. What works? +-------------- + +Well, MIDI part isn't implemented and I doubt it will be in any near +future but except that everything should work. Playing, recording, +5.1ch, A-V syncing, all should work. If not, it's a bug, so please +report. + +The mixer behaves a bit differently tho. In the original OSS, +/dev/mixer is the hardware mixer, so adjusting volumes there affects +all audio streams. When using ossp, each process group gets its own +mixer and the mixer always contains only two knobs - PCM and IGAIN. +Combined with per-stream volume control of pulseaudio, this scheme +works quite well for applications with embedded volume control +although it makes standalone OSS mixer programs virtually useless[2]. + + +4. How do I use it? +------------------- + +First you need CUSE support in kernel which might land on 2.6.28 with +sufficient luck[3] and then you also need libfuse which supports +CUSE[4]. Once you have both, it should be easy. First build it by +running `make'. You can set OSSPD_CFLAGS, OSSPD_LDFLAGS, +OSSP_PADSP_CFLAGS and OSSP_PADSP_LDFLAGS if you have stuff at +non-default locations. + +After build completes, there will be two executables - `osspd' and +`ossp-padsp'. Just copy them to where other system executables live. +Specific location doesn't matter as long as both files end up in the +same directory. + +Execute `osspd'. It will create the device files and you're all set. +`osspd' uses syslog with LOG_DAEMON facility, so if something doesn't +work take a look at what osspd complains about. + + +[1] As of this writing, turning on any sound support makes the + soundcore module claim OSS device regions. Patch to make it claim + OSS device regions only when OSS support or emulation is enabled + is scheduled for 2.6.28. Even with the patch, soundcore will + claim OSS device regions if OSS support or ALSA OSS emulation is + enabled. Make sure they're turned off. + +[2] If you have a strong reason to use standalone OSS mixer program, + you can play some shell tricks to put it into the same process + group as the target audio application. e.g. To use aumix with + mpg123 - `(mpg123 asdf.mp3 > /dev/null 2>&1 & aumix)', but + seriously, just use PA or ALSA one. + +[3] For the time being, here's the git tree with all the necessary + changes. This tree is base on top of 2.6.27-rc3. + + http://git.kernel.org/?p=linux/kernel/git/tj/misc.git;a=shortlog;h=cuse + git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git cuse + +[4] And libfuse with the modifications can be found at... + + http://userweb.kernel.org/~tj/ossp/fuse-cuse.tar.gz diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c new file mode 100644 index 0000000000..607e05ca84 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c @@ -0,0 +1,613 @@ +/* + * ossp-alsap - ossp DSP slave which forwards to alsa + * + * Copyright (C) 2009 Maarten Lankhorst + * + * This file is released under the GPLv2. + * + * Why an alsa plugin as well? Just to show how much + * the alsa userspace api sucks ;-) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ossp-slave.h" + +enum { + AFMT_FLOAT = 0x00004000, + AFMT_S32_LE = 0x00001000, + AFMT_S32_BE = 0x00002000, +}; + +static size_t page_size; + +/* alsa structures */ +static snd_pcm_t *pcm[2]; +static snd_pcm_hw_params_t *hw_params; +static snd_pcm_sw_params_t *sw_params; +static int block; + +static unsigned int byte_counter[2]; +static snd_pcm_uframes_t mmap_pos[2]; +static int stream_corked[2]; +static int stream_notify; + +static struct format { + snd_pcm_format_t format; + snd_pcm_sframes_t rate; + int channels; +} hw_format = { SND_PCM_FORMAT_U8, 8000, 1 }; + +#if 0 +/* future mmap stuff */ +static size_t mmap_raw_size, mmap_size; +static int mmap_fd[2] = { -1, -1 }; +static void *mmap_map[2]; +static uint64_t mmap_idx[2]; /* mmap pointer */ +static uint64_t mmap_last_idx[2]; /* last idx for get_ptr */ +static struct ring_buf mmap_stg[2]; /* staging ring buffer */ +static size_t mmap_lead[2]; /* lead bytes */ +static int mmap_sync[2]; /* sync with backend stream */ +#endif + +static snd_pcm_format_t fmt_oss_to_alsa(int fmt) +{ + switch (fmt) { + case AFMT_U8: return SND_PCM_FORMAT_U8; + case AFMT_A_LAW: return SND_PCM_FORMAT_A_LAW; + case AFMT_MU_LAW: return SND_PCM_FORMAT_MU_LAW; + case AFMT_S16_LE: return SND_PCM_FORMAT_S16_LE; + case AFMT_S16_BE: return SND_PCM_FORMAT_S16_BE; + case AFMT_FLOAT: return SND_PCM_FORMAT_FLOAT; + case AFMT_S32_LE: return SND_PCM_FORMAT_S32_LE; + case AFMT_S32_BE: return SND_PCM_FORMAT_S32_BE; + default: return SND_PCM_FORMAT_U8; + } +} + +static int fmt_alsa_to_oss(snd_pcm_format_t fmt) +{ + switch (fmt) { + case SND_PCM_FORMAT_U8: return AFMT_U8; + case SND_PCM_FORMAT_A_LAW: return AFMT_A_LAW; + case SND_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; + case SND_PCM_FORMAT_S16_LE: return AFMT_S16_LE; + case SND_PCM_FORMAT_S16_BE: return AFMT_S16_BE; + case SND_PCM_FORMAT_FLOAT: return AFMT_FLOAT; + case SND_PCM_FORMAT_S32_LE: return AFMT_S32_LE; + case SND_PCM_FORMAT_S32_BE: return AFMT_S32_BE; + default: return AFMT_U8; + } +} + +static void flush_streams(int drain) +{ + /* FIXME: snd_pcm_drain appears to be able to deadlock, + * always drop or check state? */ + if (drain) { + if (pcm[PLAY]) + snd_pcm_drain(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_drain(pcm[REC]); + } else { + if (pcm[PLAY]) + snd_pcm_drop(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_drop(pcm[REC]); + } + + /* XXX: Really needed? */ +#if 0 + if (pcm[PLAY]) { + snd_pcm_close(pcm[PLAY]); + snd_pcm_open(&pcm[PLAY], "default", + SND_PCM_STREAM_PLAYBACK, block); + } + if (pcm[REC]) { + snd_pcm_close(pcm[REC]); + snd_pcm_open(&pcm[REC], "default", + SND_PCM_STREAM_CAPTURE, block); + } +#endif +} + +static void kill_streams(void) +{ + flush_streams(0); +} + +static int trigger_streams(int play, int rec) +{ + int ret = 0; + + if (pcm[PLAY] && play >= 0) { + ret = snd_pcm_sw_params_set_start_threshold(pcm[PLAY], sw_params, + play ? 1 : -1); + if (ret >= 0) + snd_pcm_sw_params(pcm[PLAY], sw_params); + } + if (ret >= 0 && pcm[REC] && rec >= 0) { + ret = snd_pcm_sw_params_set_start_threshold(pcm[REC], sw_params, + rec ? 1 : -1); + if (ret >= 0) + snd_pcm_sw_params(pcm[REC], sw_params); + } + + return ret; +} + +static ssize_t alsap_mixer(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ +return -EBUSY; +} + +static int set_hw_params(snd_pcm_t *pcm) +{ + int ret; + unsigned rate; + + ret = snd_pcm_hw_params_any(pcm, hw_params); + if (ret >= 0) + ret = snd_pcm_hw_params_set_access(pcm, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED); + rate = hw_format.rate; + if (ret >= 0) + ret = snd_pcm_hw_params_set_rate_minmax(pcm, hw_params, + &rate, NULL, + &rate, NULL); + if (ret >= 0) + ret = snd_pcm_hw_params_set_format(pcm, hw_params, hw_format.format); + if (ret >= 0) + ret = snd_pcm_hw_params_set_channels(pcm, hw_params, + hw_format.channels); + if (ret >= 0) + ret = snd_pcm_hw_params(pcm, hw_params); + if (ret >= 0) + ret = snd_pcm_sw_params_current(pcm, sw_params); + if (ret >= 0) + ret = snd_pcm_sw_params(pcm, sw_params); + return ret; +} + +static ssize_t alsap_open(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + struct ossp_dsp_open_arg *arg = carg; + int ret; + block = arg->flags & O_NONBLOCK ? SND_PCM_NONBLOCK : 0; + int access; +// block |= SND_PCM_ASYNC; + /* Woop dee dooo.. I love handling things in SIGIO (PAIN!!) + * Probably needed for MMAP + */ + + if (!hw_params) + ret = snd_pcm_hw_params_malloc(&hw_params); + if (ret < 0) + return ret; + + if (!sw_params) + ret = snd_pcm_sw_params_malloc(&sw_params); + if (ret < 0) + return ret; + + if (pcm[PLAY]) + snd_pcm_close(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_close(pcm[REC]); + pcm[REC] = pcm[PLAY] = NULL; + + access = arg->flags & O_ACCMODE; + if (access == O_WRONLY || access == O_RDWR) { + ret = snd_pcm_open(&pcm[PLAY], "default", + SND_PCM_STREAM_PLAYBACK, block); + if (ret >= 0) + ret = set_hw_params(pcm[PLAY]); + } + + if (ret >= 0 && (access == O_RDONLY || access == O_RDWR)) { + ret = snd_pcm_open(&pcm[REC], "default", + SND_PCM_STREAM_CAPTURE, block); + if (ret >= 0) + ret = set_hw_params(pcm[REC]); + } + + if (ret < 0) { + if (pcm[PLAY]) + snd_pcm_close(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_close(pcm[REC]); + pcm[REC] = pcm[PLAY] = NULL; + return ret; + } + return 0; +} + +#define GIOVANNI +#ifdef GIOVANNI + +#define GIOVA_SLEEP 40000 +#define GIOVA_BLK 3840 +static ssize_t alsap_write(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + usleep((GIOVA_SLEEP/GIOVA_BLK)* din_sz); + return din_sz; +} +static ssize_t alsap_read(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + usleep((GIOVA_SLEEP/GIOVA_BLK)* *dout_szp); + return *dout_szp; +} +#else// GIOVANNI +static ssize_t alsap_write(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ +// struct ossp_dsp_rw_arg *arg = carg; + int ret, insize; + + insize = snd_pcm_bytes_to_frames(pcm[PLAY], din_sz); + + if (snd_pcm_state(pcm[PLAY]) == SND_PCM_STATE_SETUP) + snd_pcm_prepare(pcm[PLAY]); + +// snd_pcm_start(pcm[PLAY]); + ret = snd_pcm_writei(pcm[PLAY], din, insize); + if (ret < 0) + ret = snd_pcm_recover(pcm[PLAY], ret, 1); + + if (ret >= 0) + return snd_pcm_frames_to_bytes(pcm[PLAY], ret); + else + return ret; +} + +static ssize_t alsap_read(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ +// struct ossp_dsp_rw_arg *arg = carg; + int ret, outsize; + + outsize = snd_pcm_bytes_to_frames(pcm[REC], *dout_szp); + + if (snd_pcm_state(pcm[REC]) == SND_PCM_STATE_SETUP) + snd_pcm_prepare(pcm[REC]); + + ret = snd_pcm_readi(pcm[REC], dout, outsize); + if (ret < 0) + ret = snd_pcm_recover(pcm[REC], ret, 1); + if (ret >= 0) + *dout_szp = ret = snd_pcm_frames_to_bytes(pcm[REC], ret); + else + *dout_szp = 0; + + return ret; +} +#endif// GIOVANNI + +static ssize_t alsap_poll(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + unsigned revents = 0; + + stream_notify |= *(int *)carg; + + if (pcm[PLAY]) + revents |= POLLOUT; + if (pcm[REC]) + revents |= POLLIN; + + *(unsigned *)rarg = revents; + return 0; +} + + +static ssize_t alsap_flush(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + flush_streams(opcode == OSSP_DSP_SYNC); + return 0; +} + +static ssize_t alsap_post(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + int ret; + + ret = trigger_streams(1, 1); + if (ret >= 0 && pcm[PLAY]) + ret = snd_pcm_start(pcm[PLAY]); + if (pcm[REC]) + ret = snd_pcm_start(pcm[REC]); + return ret; +} + +static ssize_t alsap_get_param(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int tfd) +{ + int v = 0; + + switch (opcode) { + case OSSP_DSP_GET_RATE: + return hw_format.rate; + + case OSSP_DSP_GET_CHANNELS: + return hw_format.channels; + + case OSSP_DSP_GET_FORMAT: { + v = fmt_alsa_to_oss(hw_format.format); + break; + } + + case OSSP_DSP_GET_BLKSIZE: { + snd_pcm_uframes_t psize; + snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL); + v = psize; + break; + } + + case OSSP_DSP_GET_FORMATS: + v = AFMT_U8 | AFMT_A_LAW | AFMT_MU_LAW | AFMT_S16_LE | + AFMT_S16_BE | AFMT_FLOAT | AFMT_S32_LE | AFMT_S32_BE; + break; + + case OSSP_DSP_GET_TRIGGER: + if (!stream_corked[PLAY]) + v |= PCM_ENABLE_OUTPUT; + if (!stream_corked[REC]) + v |= PCM_ENABLE_INPUT; + break; + + default: + assert(0); + } + + *(int *)rarg = v; + + return 0; +} + +static ssize_t alsap_set_param(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int tfd) +{ + int v = *(int *)carg; + int ret = 0; + + /* kill the streams before changing parameters */ + kill_streams(); + + switch (opcode) { + case OSSP_DSP_SET_RATE: { + hw_format.rate = v; + break; + } + + case OSSP_DSP_SET_CHANNELS: { + hw_format.channels = v; + break; + } + + case OSSP_DSP_SET_FORMAT: { + snd_pcm_format_t format = fmt_oss_to_alsa(v); + hw_format.format = format; + break; + } + + case OSSP_DSP_SET_SUBDIVISION: + if (!v) + v = 1; +#if 0 + if (!v) { + v = user_subdivision ?: 1; + break; + } + user_frag_size = 0; + user_subdivision = v; + break; + + case OSSP_DSP_SET_FRAGMENT: + user_subdivision = 0; + user_frag_size = 1 << (v & 0xffff); + user_max_frags = (v >> 16) & 0xffff; + if (user_frag_size < 4) + user_frag_size = 4; + if (user_max_frags < 2) + user_max_frags = 2; +#else + case OSSP_DSP_SET_FRAGMENT: +#endif + break; + default: + assert(0); + } + + if (pcm[PLAY]) + ret = set_hw_params(pcm[PLAY]); + if (ret >= 0 && pcm[REC]) + ret = set_hw_params(pcm[REC]); + + if (rarg) + *(int *)rarg = v; + return 0; +} + +static ssize_t alsap_set_trigger(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int fd) +{ + int enable = *(int *)carg; + + stream_corked[PLAY] = !!(enable & PCM_ENABLE_OUTPUT); + stream_corked[REC] = !!(enable & PCM_ENABLE_INPUT); + + return trigger_streams(enable & PCM_ENABLE_OUTPUT, + enable & PCM_ENABLE_INPUT); +} + +static ssize_t alsap_get_space(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + int dir = (opcode == OSSP_DSP_GET_OSPACE) ? PLAY : REC; + int underrun = 0; + struct audio_buf_info info = { }; + unsigned long bufsize; + snd_pcm_uframes_t avail, fragsize; + snd_pcm_state_t state; + + if (!pcm[dir]) + return -EINVAL; + + state = snd_pcm_state(pcm[dir]); + if (state == SND_PCM_STATE_XRUN) { + snd_pcm_recover(pcm[dir], -EPIPE, 0); + underrun = 1; + } else if (state == SND_PCM_STATE_SUSPENDED) { + snd_pcm_recover(pcm[dir], -ESTRPIPE, 0); + underrun = 1; + } + + snd_pcm_hw_params_current(pcm[dir], hw_params); + snd_pcm_hw_params_get_period_size(hw_params, &fragsize, NULL); + snd_pcm_hw_params_get_buffer_size(hw_params, &bufsize); + info.fragsize = snd_pcm_frames_to_bytes(pcm[dir], fragsize); + info.fragstotal = bufsize / fragsize; + if (!underrun) { + avail = snd_pcm_avail_update(pcm[dir]); + info.fragments = avail / fragsize; + } else + info.fragments = info.fragstotal; + + info.bytes = info.fragsize * info.fragments; + + *(struct audio_buf_info *)rarg = info; + return 0; +} + +static ssize_t alsap_get_ptr(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + int dir = (opcode == OSSP_DSP_GET_OPTR) ? PLAY : REC; + struct count_info info = { }; + + if (!pcm[dir]) + return -EIO; + + snd_pcm_hw_params_current(pcm[dir], hw_params); + info.bytes = byte_counter[dir]; + snd_pcm_hw_params_get_periods(hw_params, (unsigned int *)&info.blocks, NULL); + info.ptr = mmap_pos[dir]; + + *(struct count_info *)rarg = info; + return 0; +} + +static ssize_t alsap_get_odelay(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int fd) +{ + snd_pcm_sframes_t delay; + + if (!pcm[PLAY]) + return -EIO; + + if (snd_pcm_delay(pcm[PLAY], &delay) < 0) + return -EIO; + + *(int *)rarg = snd_pcm_frames_to_bytes(pcm[PLAY], delay); + return 0; +} + +static ossp_action_fn_t action_fn_tbl[OSSP_NR_OPCODES] = { + [OSSP_MIXER] = alsap_mixer, + [OSSP_DSP_OPEN] = alsap_open, + [OSSP_DSP_READ] = alsap_read, + [OSSP_DSP_WRITE] = alsap_write, + [OSSP_DSP_POLL] = alsap_poll, +#if 0 + [OSSP_DSP_MMAP] = alsap_mmap, + [OSSP_DSP_MUNMAP] = alsap_munmap, +#endif + [OSSP_DSP_RESET] = alsap_flush, + [OSSP_DSP_SYNC] = alsap_flush, + [OSSP_DSP_POST] = alsap_post, + [OSSP_DSP_GET_RATE] = alsap_get_param, + [OSSP_DSP_GET_CHANNELS] = alsap_get_param, + [OSSP_DSP_GET_FORMAT] = alsap_get_param, + [OSSP_DSP_GET_BLKSIZE] = alsap_get_param, + [OSSP_DSP_GET_FORMATS] = alsap_get_param, + [OSSP_DSP_SET_RATE] = alsap_set_param, + [OSSP_DSP_SET_CHANNELS] = alsap_set_param, + [OSSP_DSP_SET_FORMAT] = alsap_set_param, + [OSSP_DSP_SET_SUBDIVISION] = alsap_set_param, + [OSSP_DSP_SET_FRAGMENT] = alsap_set_param, + [OSSP_DSP_GET_TRIGGER] = alsap_get_param, + [OSSP_DSP_SET_TRIGGER] = alsap_set_trigger, + [OSSP_DSP_GET_OSPACE] = alsap_get_space, + [OSSP_DSP_GET_ISPACE] = alsap_get_space, + [OSSP_DSP_GET_OPTR] = alsap_get_ptr, + [OSSP_DSP_GET_IPTR] = alsap_get_ptr, + [OSSP_DSP_GET_ODELAY] = alsap_get_odelay, +}; + +static int action_pre(void) +{ + return 0; +} + +static void action_post(void) +{ +} + +int main(int argc, char **argv) +{ + int rc; + + ossp_slave_init(argc, argv); + + page_size = sysconf(_SC_PAGE_SIZE); + + /* Okay, now we're open for business */ + rc = 0; + do { + rc = ossp_slave_process_command(ossp_cmd_fd, action_fn_tbl, + action_pre, action_post); + } while (rc > 0); + + return rc ? 1 : 0; +} diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c new file mode 100644 index 0000000000..4c5cb2d129 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c @@ -0,0 +1,250 @@ +/* + * ossp-slave - OSS Proxy: Common codes for slaves + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ossp-slave.h" + +static const char *usage = +"usage: ossp-SLAVE [options]\n" +"\n" +"proxies commands from osspd to pulseaudio\n" +"\n" +"options:\n" +" -u UID uid to use\n" +" -g GID gid to use\n" +" -c CMD_FD fd to receive commands from osspd\n" +" -n NOTIFY_FD fd to send async notifications to osspd\n" +" -m MMAP_FD fd to use for mmap\n" +" -o MMAP_OFFSET mmap offset\n" +" -s MMAP_SIZE mmap size\n" +" -l LOG_LEVEL set log level\n" +" -t enable log timestamps\n"; + +char ossp_user_name[OSSP_USER_NAME_LEN]; +int ossp_cmd_fd = -1, ossp_notify_fd = -1; +void *ossp_mmap_addr[2]; + +void ossp_slave_init(int argc, char **argv) +{ + int have_uid = 0, have_gid = 0; + uid_t uid; + gid_t gid; + int mmap_fd = -1; + off_t mmap_off = 0; + size_t mmap_size = 0; + int opt; + struct passwd *pw, pw_buf; + struct sigaction sa; + char pw_sbuf[sysconf(_SC_GETPW_R_SIZE_MAX)]; + + while ((opt = getopt(argc, argv, "u:g:c:n:m:o:s:l:t")) != -1) { + switch (opt) { + case 'u': + have_uid = 1; + uid = strtol(optarg, NULL, 0); + break; + case 'g': + have_gid = 1; + gid = strtol(optarg, NULL, 0); + break; + case 'c': + ossp_cmd_fd = strtol(optarg, NULL, 0); + break; + case 'n': + ossp_notify_fd = strtol(optarg, NULL, 0); + break; + case 'm': + mmap_fd = strtol(optarg, NULL, 0); + break; + case 'o': + mmap_off = strtoull(optarg, NULL, 0); + break; + case 's': + mmap_size = strtoul(optarg, NULL, 0); + break; + case 'l': + ossp_log_level = strtol(optarg, NULL, 0); + break; + case 't': + ossp_log_timestamp = 1; + break; + } + } + + if (!have_uid || !have_gid || ossp_cmd_fd < 0 || ossp_notify_fd < 0) { + fprintf(stderr, usage); + _exit(1); + } + + snprintf(ossp_user_name, sizeof(ossp_user_name), "uid%d", uid); + if (getpwuid_r(uid, &pw_buf, pw_sbuf, sizeof(pw_sbuf), &pw) == 0) + snprintf(ossp_user_name, sizeof(ossp_user_name), "%s", + pw->pw_name); + + snprintf(ossp_log_name, sizeof(ossp_log_name), "ossp-padsp[%s:%d]", + ossp_user_name, getpid()); + + if (mmap_fd >= 0) { + void *p; + + if (!mmap_off || !mmap_size) { + fprintf(stderr, usage); + _exit(1); + } + + p = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, + mmap_fd, mmap_off); + if (p == MAP_FAILED) + fatal_e(-errno, "mmap failed"); + + ossp_mmap_addr[PLAY] = p; + ossp_mmap_addr[REC] = p + mmap_size / 2; + close(mmap_fd); + } + + /* mmap done, drop privileges */ + if (setresgid(gid, gid, gid) || setresuid(uid, uid, uid)) + fatal_e(-errno, "failed to drop privileges"); + + /* block SIGPIPE */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + if (sigaction(SIGPIPE, &sa, NULL)) + fatal_e(-errno, "failed to ignore SIGPIPE"); +} + +int ossp_slave_process_command(int cmd_fd, + ossp_action_fn_t const *action_fn_tbl, + int (*action_pre_fn)(void), + void (*action_post_fn)(void)) +{ + static struct sized_buf carg_sbuf = { }, rarg_sbuf = { }; + static struct sized_buf din_sbuf = { }, dout_sbuf = { }; + struct ossp_cmd cmd; + int fd = -1; + char cmsg_buf[CMSG_SPACE(sizeof(fd))]; + struct iovec iov = { &cmd, sizeof(cmd) }; + struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, + .msg_control = cmsg_buf, + .msg_controllen = sizeof(cmsg_buf) }; + struct cmsghdr *cmsg; + size_t carg_size, din_size, rarg_size, dout_size; + char *carg = NULL, *din = NULL, *rarg = NULL, *dout = NULL; + struct ossp_reply reply = { .magic = OSSP_REPLY_MAGIC }; + ssize_t ret; + + ret = recvmsg(cmd_fd, &msg, 0); + if (ret == 0) + return 0; + if (ret < 0) { + ret = -errno; + err_e(ret, "failed to read command channel"); + return ret; + } + + if (ret != sizeof(cmd)) { + err("command struct size mismatch (%zu, should be %zu)", + ret, sizeof(cmd)); + return -EINVAL; + } + + if (cmd.magic != OSSP_CMD_MAGIC) { + err("illegal command magic 0x%x", cmd.magic); + return -EINVAL; + } + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) + fd = *(int *)CMSG_DATA(cmsg); + else { + err("unknown cmsg %d:%d received (opcode %d)", + cmsg->cmsg_level, cmsg->cmsg_type, cmd.opcode); + return -EINVAL; + } + } + + if (cmd.opcode >= OSSP_NR_OPCODES) { + err("unknown opcode %d", cmd.opcode); + return -EINVAL; + } + + carg_size = ossp_arg_sizes[cmd.opcode].carg_size; + din_size = cmd.din_size; + rarg_size = ossp_arg_sizes[cmd.opcode].rarg_size; + dout_size = cmd.dout_size; + + if ((fd >= 0) != ossp_arg_sizes[cmd.opcode].has_fd) { + err("fd=%d unexpected for opcode %d", fd, cmd.opcode); + return -EINVAL; + } + + if (ensure_sbuf_size(&carg_sbuf, carg_size) || + ensure_sbuf_size(&din_sbuf, din_size) || + ensure_sbuf_size(&rarg_sbuf, rarg_size) || + ensure_sbuf_size(&dout_sbuf, dout_size)) { + err("failed to allocate command buffers"); + return -ENOMEM; + } + + if (carg_size) { + carg = carg_sbuf.buf; + ret = read_fill(cmd_fd, carg, carg_size); + if (ret < 0) + return ret; + } + if (din_size) { + din = din_sbuf.buf; + ret = read_fill(cmd_fd, din, din_size); + if (ret < 0) + return ret; + } + if (rarg_size) + rarg = rarg_sbuf.buf; + if (dout_size) + dout = dout_sbuf.buf; + + ret = -EINVAL; + if (action_fn_tbl[cmd.opcode]) { + ret = action_pre_fn(); + if (ret == 0) { + ret = action_fn_tbl[cmd.opcode](cmd.opcode, carg, + din, din_size, rarg, + dout, &dout_size, fd); + action_post_fn(); + } + } + + reply.result = ret; + if (ret >= 0) + reply.dout_size = dout_size; + else { + rarg_size = 0; + dout_size = 0; + } + + if (write_fill(cmd_fd, &reply, sizeof(reply)) < 0 || + write_fill(cmd_fd, rarg, rarg_size) < 0 || + write_fill(cmd_fd, dout, dout_size) < 0) + return -EIO; + + return 1; +} diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h new file mode 100644 index 0000000000..10c22cdb02 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h @@ -0,0 +1,28 @@ +/* + * ossp-slave - OSS Proxy: Common codes for slaves + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#ifndef _OSSP_SLAVE_H +#define _OSSP_SLAVE_H + +#include "ossp.h" +#include "ossp-util.h" + +#define OSSP_USER_NAME_LEN 128 + +extern char ossp_user_name[OSSP_USER_NAME_LEN]; +extern int ossp_cmd_fd, ossp_notify_fd; +extern void *ossp_mmap_addr[2]; + +void ossp_slave_init(int argc, char **argv); +int ossp_slave_process_command(int cmd_fd, + ossp_action_fn_t const *action_fn_tbl, + int (*action_pre_fn)(void), + void (*action_post_fn)(void)); + +#endif /* _OSSP_SLAVE_H */ diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c new file mode 100644 index 0000000000..325cefd5fd --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c @@ -0,0 +1,369 @@ +/* + * ossp-util - OSS Proxy: Common utilities + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ossp-util.h" + +#define BIT(nr) (1UL << (nr)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) + +char ossp_log_name[OSSP_LOG_NAME_LEN]; +int ossp_log_level = OSSP_LOG_DFL; +int ossp_log_timestamp; + +static const char *severity_strs[] = { + [OSSP_LOG_CRIT] = "CRIT", + [OSSP_LOG_ERR] = " ERR", + [OSSP_LOG_WARN] = "WARN", + [OSSP_LOG_INFO] = NULL, + [OSSP_LOG_DBG0] = "DBG0", + [OSSP_LOG_DBG1] = "DBG1", +}; + +static int severity_map[] = { + [OSSP_LOG_CRIT] = LOG_ERR, + [OSSP_LOG_ERR] = LOG_ERR, + [OSSP_LOG_WARN] = LOG_WARNING, + [OSSP_LOG_INFO] = LOG_INFO, + [OSSP_LOG_DBG0] = LOG_DEBUG, + [OSSP_LOG_DBG1] = LOG_DEBUG, +}; + +void log_msg(int severity, const char *fmt, ...) +{ + static int syslog_opened = 0; + char buf[1024]; + size_t len = sizeof(buf), off = 0; + va_list ap; + + if (severity > abs(ossp_log_level)) + return; + + if (ossp_log_level < 0 && !syslog_opened) + openlog(ossp_log_name, 0, LOG_DAEMON); + + assert(severity >= 0 && severity < ARRAY_SIZE(severity_strs)); + + if (ossp_log_timestamp) { + static uint64_t start; + uint64_t now; + struct timeval tv; + gettimeofday(&tv, NULL); + now = tv.tv_sec * 1000 + tv.tv_usec / 1000; + if (!start) + start = now; + + off += snprintf(buf + off, len - off, "<%08"PRIu64"> ", + now - start); + } + + if (ossp_log_level > 0) { + char sev_buf[16] = ""; + if (severity_strs[severity]) + snprintf(sev_buf, sizeof(sev_buf), " %s", + severity_strs[severity]); + off += snprintf(buf + off, len - off, "%s%s: ", + ossp_log_name, sev_buf); + } else if (severity_strs[severity]) + off += snprintf(buf + off, len - off, "%s ", + severity_strs[severity]); + + va_start(ap, fmt); + off += vsnprintf(buf + off, len - off, fmt, ap); + va_end(ap); + + off += snprintf(buf + off, len - off, "\n"); + + if (ossp_log_level > 0) + fputs(buf, stderr); + else + syslog(severity_map[severity], "%s", buf); +} + +int read_fill(int fd, void *buf, size_t size) +{ + while (size) { + ssize_t ret; + int rc; + + ret = read(fd, buf, size); + if (ret <= 0) { + if (ret == 0) + rc = -EIO; + else + rc = -errno; + err_e(rc, "failed to read_fill %zu bytes from fd %d", + size, fd); + return rc; + } + buf += ret; + size -= ret; + } + return 0; +} + +int write_fill(int fd, const void *buf, size_t size) +{ + while (size) { + ssize_t ret; + int rc; + + ret = write(fd, buf, size); + if (ret <= 0) { + if (ret == 0) + rc = -EIO; + else + rc = -errno; + err_e(rc, "failed to write_fill %zu bytes to fd %d", + size, fd); + return rc; + } + buf += ret; + size -= ret; + } + return 0; +} + +void ring_fill(struct ring_buf *ring, const void *buf, size_t size) +{ + size_t tail; + + assert(ring_space(ring) >= size); + + tail = (ring->head + ring->size - ring->bytes) % ring->size; + + if (ring->head >= tail) { + size_t todo = min(size, ring->size - ring->head); + + memcpy(ring->buf + ring->head, buf, todo); + ring->head = (ring->head + todo) % ring->size; + ring->bytes += todo; + buf += todo; + size -= todo; + } + + assert(ring->size - ring->head >= size); + memcpy(ring->buf + ring->head, buf, size); + ring->head += size; + ring->bytes += size; +} + +void *ring_data(struct ring_buf *ring, size_t *sizep) +{ + size_t tail; + + if (!ring->bytes) + return NULL; + + tail = (ring->head + ring->size - ring->bytes) % ring->size; + + *sizep = min(ring->bytes, ring->size - tail); + return ring->buf + tail; +} + +int ring_resize(struct ring_buf *ring, size_t new_size) +{ + struct ring_buf new_ring = { .size = new_size }; + void *p; + size_t size; + + if (ring_bytes(ring) > new_size) + return -ENOSPC; + + new_ring.buf = calloc(1, new_size); + if (new_size && !new_ring.buf) + return -ENOMEM; + + while ((p = ring_data(ring, &size))) { + ring_fill(&new_ring, p, size); + ring_consume(ring, size); + } + + free(ring->buf); + *ring = new_ring; + return 0; +} + +int ensure_sbuf_size(struct sized_buf *sbuf, size_t size) +{ + char *new_buf; + + if (sbuf->size >= size) + return 0; + + new_buf = realloc(sbuf->buf, size); + if (size && !new_buf) + return -ENOMEM; + + sbuf->buf = new_buf; + sbuf->size = size; + return 0; +} + +static unsigned long __ffs(unsigned long word) +{ + int num = 0; + + if (BITS_PER_LONG == 64) { + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } + } + + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +#define ffz(x) __ffs(~(x)) + +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (BITS_PER_LONG - offset); + if (size < BITS_PER_LONG) + goto found_first; + if (~tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if (~(tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} + +void __set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p |= mask; +} + +void __clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p &= ~mask; +} + +int get_proc_self_info(pid_t pid, pid_t *ppid_r, + char *cmd_buf, size_t cmd_buf_sz) + +{ + char path[64], buf[4096]; + int fd = -1; + char *cmd_start, *cmd_end, *ppid_start, *end; + ssize_t ret; + pid_t ppid; + int i, rc; + + snprintf(path, sizeof(path), "/proc/%ld/stat", (long)pid); + fd = open(path, O_RDONLY); + if (fd < 0) { + rc = -errno; + goto out; + } + + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) + goto out; + if (ret == sizeof(buf)) { + rc = -EOVERFLOW; + goto out; + } + buf[ret] = '\0'; + + rc = -EINVAL; + cmd_start = strchr(buf, '('); + cmd_end = strrchr(buf, ')'); + if (!cmd_start || !cmd_end) + goto out; + cmd_start++; + + ppid_start = cmd_end; + for (i = 0; i < 3; i++) { + ppid_start = strchr(ppid_start, ' '); + if (!ppid_start) + goto out; + ppid_start++; + } + + ppid = strtoul(ppid_start, &end, 10); + if (end == ppid_start || *end != ' ') + goto out; + + if (ppid_r) + *ppid_r = ppid; + if (cmd_buf) { + size_t len = min_t(size_t, cmd_end - cmd_start, cmd_buf_sz - 1); + memcpy(cmd_buf, cmd_start, len); + cmd_buf[len] = '\0'; + } + + rc = 0; + out: + close(fd); + + return rc; +} diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h new file mode 100644 index 0000000000..f48d02257a --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h @@ -0,0 +1,609 @@ +/* + * ossp-util - OSS Proxy: Common utilities + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#ifndef _OSSP_UTIL_H +#define _OSSP_UTIL_H + +#include +#include +#include +#include +#include +#include +#include "ossp.h" + +#define OSSP_LOG_NAME_LEN 128 + +enum { + OSSP_LOG_CRIT = 1, + OSSP_LOG_ERR, + OSSP_LOG_WARN, + OSSP_LOG_INFO, + OSSP_LOG_DFL = OSSP_LOG_INFO, /* default log level */ + OSSP_LOG_DBG0, + OSSP_LOG_DBG1, + OSSP_LOG_MAX = OSSP_LOG_DBG1, +}; + +extern char ossp_log_name[OSSP_LOG_NAME_LEN]; +extern int ossp_log_level; +extern int ossp_log_timestamp; + +#define BITS_PER_BYTE 8 +#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long)) +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) + +/* ARRAY_SIZE and min/max macros stolen from linux/kernel.h */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + +#define max(x, y) ({ \ + typeof(x) _max1 = (x); \ + typeof(y) _max2 = (y); \ + (void) (&_max1 == &_max2); \ + _max1 > _max2 ? _max1 : _max2; }) + +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1: __min2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1: __max2; }) + +void log_msg(int severity, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +#define fatal(fmt, args...) do { \ + log_msg(OSSP_LOG_CRIT, fmt , ##args); \ + _exit(1); \ +} while (0) +#define err(fmt, args...) log_msg(OSSP_LOG_ERR, fmt , ##args) +#define warn(fmt, args...) log_msg(OSSP_LOG_WARN, fmt , ##args) +#define info(fmt, args...) log_msg(OSSP_LOG_INFO, fmt , ##args) +#define dbg0(fmt, args...) log_msg(OSSP_LOG_DBG0, fmt , ##args) +#define dbg1(fmt, args...) log_msg(OSSP_LOG_DBG1, fmt , ##args) + +#define fatal_e(e, fmt, args...) \ + fatal(fmt" (%s)" , ##args, strerror(-(e))) +#define err_e(e, fmt, args...) \ + err(fmt" (%s)" , ##args, strerror(-(e))) +#define warn_e(e, fmt, args...) \ + warn(fmt" (%s)" , ##args, strerror(-(e))) +#define info_e(e, fmt, args...) \ + info(fmt" (%s)" , ##args, strerror(-(e))) +#define dbg0_e(e, fmt, args...) \ + dbg0(fmt" (%s)" , ##args, strerror(-(e))) +#define dbg1_e(e, fmt, args...) \ + dbg1(fmt" (%s)" , ##args, strerror(-(e))) + +struct ring_buf { + char *buf; + size_t size; + size_t head; + size_t bytes; +}; + +static inline size_t ring_size(struct ring_buf *ring) +{ + return ring->size; +} + +static inline size_t ring_bytes(struct ring_buf *ring) +{ + return ring->bytes; +} + +static inline size_t ring_space(struct ring_buf *ring) +{ + return ring->size - ring->bytes; +} + +static inline void ring_consume(struct ring_buf *ring, size_t size) +{ + assert(ring->bytes >= size); + ring->bytes -= size; +} + +static inline void ring_manual_init(struct ring_buf *ring, void *buf, + size_t size, size_t head, size_t bytes) +{ + ring->buf = buf; + ring->size = size; + ring->head = head; + ring->bytes = bytes; +} + +void ring_fill(struct ring_buf *ring, const void *buf, size_t size); +void *ring_data(struct ring_buf *ring, size_t *sizep); +int ring_resize(struct ring_buf *ring, size_t new_size); + +struct sized_buf { + char *buf; + size_t size; +}; + +int ensure_sbuf_size(struct sized_buf *sbuf, size_t size); + +int read_fill(int fd, void *buf, size_t size); +int write_fill(int fd, const void *buf, size_t size); + +/* + * Bitops lifted from linux asm-generic implementation. + */ +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned + long size, unsigned long offset); +#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) +extern void __set_bit(int nr, volatile unsigned long *addr); +extern void __clear_bit(int nr, volatile unsigned long *addr); + +typedef ssize_t (*ossp_action_fn_t)(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int fd); + +int get_proc_self_info(pid_t tid, pid_t *pgrp, + char *cmd_buf, size_t cmd_buf_sz); + +/* + * Doubly linked list handling code shamelessly stolen from the Linux + * kernel 2.6.26 include/linux/list.h. + */ + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static inline void __list_splice(const struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +#endif /*_OSSP_UTIL_H*/ diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp.c new file mode 100644 index 0000000000..96f98fa37a --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp.c @@ -0,0 +1,83 @@ +/* + * ossp - OSS Proxy: emulate OSS device using CUSE + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#include "ossp.h" + +const struct ossp_arg_size ossp_arg_sizes[OSSP_NR_OPCODES] = { + [OSSP_MIXER] = { sizeof(struct ossp_mixer_arg), + sizeof(struct ossp_mixer_arg), 0 }, + + [OSSP_DSP_OPEN] = { sizeof(struct ossp_dsp_open_arg), 0, 0 }, + [OSSP_DSP_READ] = { sizeof(struct ossp_dsp_rw_arg), 0, 0 }, + [OSSP_DSP_WRITE] = { sizeof(struct ossp_dsp_rw_arg), 0, 0 }, + [OSSP_DSP_POLL] = { sizeof(int), sizeof(unsigned), 0 }, + [OSSP_DSP_MMAP] = { sizeof(struct ossp_dsp_mmap_arg), 0, 0 }, + [OSSP_DSP_MUNMAP] = { sizeof(int), 0, 0 }, + + [OSSP_DSP_RESET] = { 0, 0, 0 }, + [OSSP_DSP_SYNC] = { 0, 0, 0 }, + [OSSP_DSP_POST] = { 0, 0, 0 }, + [OSSP_DSP_GET_RATE] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_CHANNELS] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_FORMAT] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_BLKSIZE] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_FORMATS] = { 0, sizeof(int), 0 }, + [OSSP_DSP_SET_RATE] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_CHANNELS] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_FORMAT] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_SUBDIVISION] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_FRAGMENT] = { sizeof(int), 0, 0 }, + [OSSP_DSP_GET_TRIGGER] = { 0, sizeof(int), 0 }, + [OSSP_DSP_SET_TRIGGER] = { sizeof(int), 0, 0 }, + [OSSP_DSP_GET_OSPACE] = { 0, sizeof(struct audio_buf_info), 0 }, + [OSSP_DSP_GET_ISPACE] = { 0, sizeof(struct audio_buf_info), 0 }, + [OSSP_DSP_GET_OPTR] = { 0, sizeof(struct count_info), 0 }, + [OSSP_DSP_GET_IPTR] = { 0, sizeof(struct count_info), 0 }, + [OSSP_DSP_GET_ODELAY] = { 0, sizeof(int), 0 }, +}; + +const char *ossp_cmd_str[OSSP_NR_OPCODES] = { + [OSSP_MIXER] = "MIXER", + + [OSSP_DSP_OPEN] = "OPEN", + [OSSP_DSP_READ] = "READ", + [OSSP_DSP_WRITE] = "WRITE", + [OSSP_DSP_POLL] = "POLL", + [OSSP_DSP_MMAP] = "MMAP", + [OSSP_DSP_MUNMAP] = "MUNMAP", + + [OSSP_DSP_RESET] = "RESET", + [OSSP_DSP_SYNC] = "SYNC", + [OSSP_DSP_POST] = "POST", + + [OSSP_DSP_GET_RATE] = "GET_RATE", + [OSSP_DSP_GET_CHANNELS] = "GET_CHANNELS", + [OSSP_DSP_GET_FORMAT] = "GET_FORMAT", + [OSSP_DSP_GET_BLKSIZE] = "GET_BLKSIZE", + [OSSP_DSP_GET_FORMATS] = "GET_FORMATS", + [OSSP_DSP_SET_RATE] = "SET_RATE", + [OSSP_DSP_SET_CHANNELS] = "SET_CHANNELS", + [OSSP_DSP_SET_FORMAT] = "SET_FORMAT", + [OSSP_DSP_SET_SUBDIVISION] = "SET_BUSDIVISION", + + [OSSP_DSP_SET_FRAGMENT] = "SET_FRAGMENT", + [OSSP_DSP_GET_TRIGGER] = "GET_TRIGGER", + [OSSP_DSP_SET_TRIGGER] = "SET_TRIGGER", + [OSSP_DSP_GET_OSPACE] = "GET_OSPACE", + [OSSP_DSP_GET_ISPACE] = "GET_ISPACE", + [OSSP_DSP_GET_OPTR] = "GET_OPTR", + [OSSP_DSP_GET_IPTR] = "GET_IPTR", + [OSSP_DSP_GET_ODELAY] = "GET_ODELAY", +}; + +const char *ossp_notify_str[OSSP_NR_NOTIFY_OPCODES] = { + [OSSP_NOTIFY_POLL] = "POLL", + [OSSP_NOTIFY_OBITUARY] = "OBITUARY", + [OSSP_NOTIFY_VOLCHG] = "VOLCHG", +}; diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp.h b/src/mod/endpoints/mod_skypopen/osscuse/ossp.h new file mode 100644 index 0000000000..9d03e63adf --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp.h @@ -0,0 +1,117 @@ +/* + * ossp - OSS Proxy: emulate OSS device using CUSE + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#ifndef _OSSP_H +#define _OSSP_H + +#include +#include +#include + +#define OSSP_VERSION "1.3.2" +#define OSSP_CMD_MAGIC 0xdeadbeef +#define OSSP_REPLY_MAGIC 0xbeefdead +#define OSSP_NOTIFY_MAGIC 0xbebebebe + +#define PLAY 0 +#define REC 1 +#define LEFT 0 +#define RIGHT 1 + +enum ossp_opcode { + OSSP_MIXER, + + OSSP_DSP_OPEN, + OSSP_DSP_READ, + OSSP_DSP_WRITE, + OSSP_DSP_POLL, + OSSP_DSP_MMAP, + OSSP_DSP_MUNMAP, + + OSSP_DSP_RESET, + OSSP_DSP_SYNC, + OSSP_DSP_POST, + + OSSP_DSP_GET_RATE, + OSSP_DSP_GET_CHANNELS, + OSSP_DSP_GET_FORMAT, + OSSP_DSP_GET_BLKSIZE, + OSSP_DSP_GET_FORMATS, + OSSP_DSP_SET_RATE, + OSSP_DSP_SET_CHANNELS, + OSSP_DSP_SET_FORMAT, + OSSP_DSP_SET_SUBDIVISION, + + OSSP_DSP_SET_FRAGMENT, + OSSP_DSP_GET_TRIGGER, + OSSP_DSP_SET_TRIGGER, + OSSP_DSP_GET_OSPACE, + OSSP_DSP_GET_ISPACE, + OSSP_DSP_GET_OPTR, + OSSP_DSP_GET_IPTR, + OSSP_DSP_GET_ODELAY, + + OSSP_NR_OPCODES, +}; + +enum ossp_notify_opcode { + OSSP_NOTIFY_POLL, + OSSP_NOTIFY_OBITUARY, + OSSP_NOTIFY_VOLCHG, + + OSSP_NR_NOTIFY_OPCODES, +}; + +struct ossp_mixer_arg { + int vol[2][2]; +}; + +struct ossp_dsp_open_arg { + int flags; + pid_t opener_pid; +}; + +struct ossp_dsp_rw_arg { + unsigned nonblock:1; +}; + +struct ossp_dsp_mmap_arg { + int dir; + size_t size; +}; + +struct ossp_cmd { + unsigned magic; + enum ossp_opcode opcode; + size_t din_size; + size_t dout_size; +}; + +struct ossp_reply { + unsigned magic; + int result; + size_t dout_size; /* <= cmd.data_in_size */ +}; + +struct ossp_notify { + unsigned magic; + enum ossp_notify_opcode opcode; +}; + +struct ossp_arg_size { + ssize_t carg_size; + ssize_t rarg_size; + unsigned has_fd:1; +}; + +extern const struct ossp_arg_size ossp_arg_sizes[OSSP_NR_OPCODES]; +extern const char *ossp_cmd_str[OSSP_NR_OPCODES]; +extern const char *ossp_notify_str[OSSP_NR_NOTIFY_OPCODES]; + +#endif /* _OSSP_H */ diff --git a/src/mod/endpoints/mod_skypopen/osscuse/osspd.c b/src/mod/endpoints/mod_skypopen/osscuse/osspd.c new file mode 100644 index 0000000000..dc9f36a09b --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/osspd.c @@ -0,0 +1,2374 @@ +/* + * osspd - OSS Proxy Daemon: emulate OSS device using CUSE + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ +#undef GIOVANNI + +#define FUSE_USE_VERSION 28 +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ossp.h" +#include "ossp-util.h" + +/* + * MMAP support needs to be updated to the new fuse MMAP API. Disable + * it for the time being. + */ +#warning mmap support disabled for now +/* #define OSSP_MMAP */ + +#define DFL_MIXER_NAME "mixer" +#define DFL_DSP_NAME "dsp" +#define DFL_ADSP_NAME "adsp" +#define STRFMT "S[%u/%d]" +#define STRID(os) os->id, os->pid + +#define dbg1_os(os, fmt, args...) dbg1(STRFMT" "fmt, STRID(os) , ##args) +#define dbg0_os(os, fmt, args...) dbg0(STRFMT" "fmt, STRID(os) , ##args) +#define warn_os(os, fmt, args...) warn(STRFMT" "fmt, STRID(os) , ##args) +#define err_os(os, fmt, args...) err(STRFMT" "fmt, STRID(os) , ##args) +#define warn_ose(os, err, fmt, args...) \ + warn_e(err, STRFMT" "fmt, STRID(os) , ##args) +#define err_ose(os, err, fmt, args...) \ + err_e(err, STRFMT" "fmt, STRID(os) , ##args) + +enum { + SNDRV_OSS_VERSION = ((3<<16)|(8<<8)|(1<<4)|(0)), /* 3.8.1a */ + DFL_MIXER_MAJOR = 14, + DFL_MIXER_MINOR = 0, + DFL_DSP_MAJOR = 14, + DFL_DSP_MINOR = 3, + DFL_ADSP_MAJOR = 14, + DFL_ADSP_MINOR = 12, + DFL_MAX_STREAMS = 128, + MIXER_PUT_DELAY = 600, /* 10 mins */ + /* DSPS_MMAP_SIZE / 2 must be multiple of SHMLBA */ + DSPS_MMAP_SIZE = 2 * (512 << 10), /* 512k for each dir */ +}; + +struct ossp_uid_cnt { + struct list_head link; + uid_t uid; + unsigned nr_os; +}; + +struct ossp_mixer { + pid_t pgrp; + struct list_head link; + struct list_head delayed_put_link; + unsigned refcnt; + /* the following two fields are protected by mixer_mutex */ + int vol[2][2]; + int modify_counter; + time_t put_expires; +}; + +struct ossp_mixer_cmd { + struct ossp_mixer *mixer; + struct ossp_mixer_arg set; + int out_dir; + int rvol; +}; + +#define for_each_vol(i, j) \ + for (i = 0, j = 0; i < 2; j += i << 1, j++, i = j >> 1, j &= 1) + +struct ossp_stream { + unsigned id; /* stream ID */ + struct list_head link; + struct list_head pgrp_link; + struct list_head notify_link; + unsigned refcnt; + pthread_mutex_t cmd_mutex; + pthread_mutex_t mmap_mutex; + struct fuse_pollhandle *ph; + + /* stream owner info */ + pid_t pid; + pid_t pgrp; + uid_t uid; + gid_t gid; + + /* slave info */ + pid_t slave_pid; + int cmd_fd; + int notify_tx; + int notify_rx; + + /* the following dead flag is set asynchronously, keep it separate. */ + int dead; + + /* stream mixer state, protected by mixer_mutex */ + int mixer_pending; + int vol[2][2]; + int vol_set[2][2]; + + off_t mmap_off; + size_t mmap_size; + + struct ossp_uid_cnt *ucnt; + struct fuse_session *se; /* associated fuse session */ + struct ossp_mixer *mixer; +}; + +struct ossp_dsp_stream { + struct ossp_stream os; + unsigned rw; + unsigned mmapped; + int nonblock; +}; + +#define os_to_dsps(_os) container_of(_os, struct ossp_dsp_stream, os) + +static unsigned max_streams; +static unsigned umax_streams; +static unsigned hashtbl_size; +static char dsp_slave_path[PATH_MAX]; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mixer_mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned long *os_id_bitmap; +static unsigned nr_mixers; +static struct list_head *mixer_tbl; /* indexed by PGRP */ +static struct list_head *os_tbl; /* indexed by ID */ +static struct list_head *os_pgrp_tbl; /* indexed by PGRP */ +static struct list_head *os_notify_tbl; /* indexed by notify fd */ +static LIST_HEAD(uid_cnt_list); +static int notify_epfd; /* epoll used to monitor notify fds */ +static pthread_t notify_poller_thread; +static pthread_t slave_reaper_thread; +static pthread_t mixer_delayed_put_thread; +static pthread_t cuse_mixer_thread; +static pthread_t cuse_adsp_thread; +static pthread_cond_t notify_poller_kill_wait = PTHREAD_COND_INITIALIZER; +static pthread_cond_t slave_reaper_wait = PTHREAD_COND_INITIALIZER; +static LIST_HEAD(slave_corpse_list); +static LIST_HEAD(mixer_delayed_put_head); /* delayed reference */ +static pthread_cond_t mixer_delayed_put_cond = PTHREAD_COND_INITIALIZER; + +static int init_wait_fd = -1; +static int exit_on_idle; +static struct fuse_session *mixer_se; +static struct fuse_session *dsp_se; +static struct fuse_session *adsp_se; + +static void put_os(struct ossp_stream *os); + + +/*************************************************************************** + * Accessors + */ + +static struct list_head *mixer_tbl_head(pid_t pid) +{ + return &mixer_tbl[pid % hashtbl_size]; +} + +static struct list_head *os_tbl_head(uint64_t id) +{ + return &os_tbl[id % hashtbl_size]; +} + +static struct list_head *os_pgrp_tbl_head(pid_t pgrp) +{ + return &os_pgrp_tbl[pgrp % hashtbl_size]; +} + +static struct list_head *os_notify_tbl_head(int notify_rx) +{ + return &os_notify_tbl[notify_rx % hashtbl_size]; +} + +static struct ossp_mixer *find_mixer_locked(pid_t pgrp) +{ + struct ossp_mixer *mixer; + + list_for_each_entry(mixer, mixer_tbl_head(pgrp), link) + if (mixer->pgrp == pgrp) + return mixer; + return NULL; +} + +static struct ossp_mixer *find_mixer(pid_t pgrp) +{ + struct ossp_mixer *mixer; + + pthread_mutex_lock(&mutex); + mixer = find_mixer_locked(pgrp); + pthread_mutex_unlock(&mutex); + return mixer; +} + +static struct ossp_stream *find_os(unsigned id) +{ + struct ossp_stream *os, *found = NULL; + + pthread_mutex_lock(&mutex); + list_for_each_entry(os, os_tbl_head(id), link) + if (os->id == id) { + found = os; + break; + } + pthread_mutex_unlock(&mutex); + return found; +} + +static struct ossp_stream *find_os_by_notify_rx(int notify_rx) +{ + struct ossp_stream *os, *found = NULL; + + pthread_mutex_lock(&mutex); + list_for_each_entry(os, os_notify_tbl_head(notify_rx), notify_link) + if (os->notify_rx == notify_rx) { + found = os; + break; + } + pthread_mutex_unlock(&mutex); + return found; +} + + +/*************************************************************************** + * Command and ioctl helpers + */ + +static ssize_t exec_cmd_intern(struct ossp_stream *os, enum ossp_opcode opcode, + const void *carg, size_t carg_size, const void *din, size_t din_size, + void *rarg, size_t rarg_size, void *dout, size_t *dout_sizep, int fd) +{ + size_t dout_size = dout_sizep ? *dout_sizep : 0; + struct ossp_cmd cmd = { .magic = OSSP_CMD_MAGIC, .opcode = opcode, + .din_size = din_size, + .dout_size = dout_size }; + struct iovec iov = { &cmd, sizeof(cmd) }; + struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 }; + struct ossp_reply reply = { }; + char cmsg_buf[CMSG_SPACE(sizeof(fd))]; + char reason[512]; + int rc; + + if (os->dead) + return -EIO; + + //dbg1_os(os, "opcode %s=%d carg=%zu din=%zu rarg=%zu dout=%zu", + //ossp_cmd_str[opcode], opcode, carg_size, din_size, rarg_size, + //dout_size); +#ifndef GIOVANNI +memset(dout, 255, dout_size); +memset(din, 255, din_size); + +#define GIOVA_BLK 3840 +#define GIOVA_SLEEP 40000 +switch(opcode){ + + case 1: //OPEN + reply.result = 0; + break; + case 2: //READ + usleep((GIOVA_SLEEP/GIOVA_BLK)* *dout_sizep); + reply.result = *dout_sizep; + break; + case 3: //WRITE + usleep((GIOVA_SLEEP/GIOVA_BLK)* din_size); + reply.result = din_size; + break; + case 9: //POST + reply.result = -32; + break; + case 13: //GET_BLKSIZE + reply.result = 0; + *(int *)rarg = GIOVA_BLK; + break; + case 14: //GET_FORMATS + reply.result = 0; + *(int *)rarg = 28731; + break; + case 15: //SET_RATE + reply.result = 0; + *(int *)rarg = *(int *) carg; + break; + case 16: //SET_CHANNELS + reply.result = 0; + *(int *)rarg = *(int *) carg; + break; + case 17: //SET_FORMAT + reply.result = 0; + *(int *)rarg = *(int *) carg; + break; + case 19: //SET_FRAGMENT + reply.result = 0; + break; + default: + reply.result = 0; + break; +} +#endif // GIOVANNI + +#ifdef GIOVANNI + if (fd >= 0) { + struct cmsghdr *cmsg; + + msg.msg_control = cmsg_buf; + msg.msg_controllen = sizeof(cmsg_buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + *(int *)CMSG_DATA(cmsg) = fd; + msg.msg_controllen = cmsg->cmsg_len; + } + + if (sendmsg(os->cmd_fd, &msg, 0) <= 0) { + rc = -errno; + snprintf(reason, sizeof(reason), "command sendmsg failed: %s", + strerror(-rc)); + goto fail; + } + + if ((rc = write_fill(os->cmd_fd, carg, carg_size)) < 0 || + (rc = write_fill(os->cmd_fd, din, din_size)) < 0) { + snprintf(reason, sizeof(reason), + "can't tranfer command argument and/or data: %s", + strerror(-rc)); + goto fail; + } + if ((rc = read_fill(os->cmd_fd, &reply, sizeof(reply))) < 0) { + snprintf(reason, sizeof(reason), "can't read reply: %s", + strerror(-rc)); + goto fail; + } + + if (reply.magic != OSSP_REPLY_MAGIC) { + snprintf(reason, sizeof(reason), + "reply magic mismatch %x != %x", + reply.magic, OSSP_REPLY_MAGIC); + rc = -EINVAL; + goto fail; + } + + if (reply.result < 0) + goto out_unlock; + + if (reply.dout_size > dout_size) { + snprintf(reason, sizeof(reason), + "data out size overflow %zu > %zu", + reply.dout_size, dout_size); + rc = -EINVAL; + goto fail; + } + + dout_size = reply.dout_size; + if (dout_sizep) + *dout_sizep = dout_size; + + if ((rc = read_fill(os->cmd_fd, rarg, rarg_size)) < 0 || + (rc = read_fill(os->cmd_fd, dout, dout_size)) < 0) { + snprintf(reason, sizeof(reason), "can't read data out: %s", + strerror(-rc)); + goto fail; + } + +#endif // GIOVANNI + +out_unlock: + //dbg1_os(os, " completed, result=%d dout=%zu", + //reply.result, dout_size); + +//if(rarg) + //dbg1_os(os, " 2 %s=%d completed, result=%d dout=%zu carg=%d rarg=%d", ossp_cmd_str[opcode], opcode, + //reply.result, dout_size, carg ? *(int *) carg : 666, *(int *)rarg); + return reply.result; + +fail: + warn_os(os, "communication with slave failed (%s)", reason); + os->dead = 1; + return rc; +} + +static ssize_t exec_cmd(struct ossp_stream *os, enum ossp_opcode opcode, + const void *carg, size_t carg_size, const void *din, size_t din_size, + void *rarg, size_t rarg_size, void *dout, size_t *dout_sizep, int fd) +{ + int is_mixer; + int i, j; + ssize_t ret, mret; + + /* mixer command is handled exlicitly below */ + is_mixer = opcode == OSSP_MIXER; + if (is_mixer) { + ret = -pthread_mutex_trylock(&os->cmd_mutex); + if (ret) + return ret; + } else { + pthread_mutex_lock(&os->cmd_mutex); + + ret = exec_cmd_intern(os, opcode, carg, carg_size, + din, din_size, rarg, rarg_size, + dout, dout_sizep, fd); + } + + /* lazy mixer handling */ + pthread_mutex_lock(&mixer_mutex); + + if (os->mixer_pending) { + struct ossp_mixer_arg marg; + repeat_mixer: + /* we have mixer command pending */ + memcpy(marg.vol, os->vol_set, sizeof(os->vol_set)); + memset(os->vol_set, -1, sizeof(os->vol_set)); + + pthread_mutex_unlock(&mixer_mutex); + mret = exec_cmd_intern(os, OSSP_MIXER, &marg, sizeof(marg), + NULL, 0, &marg, sizeof(marg), NULL, NULL, + -1); + pthread_mutex_lock(&mixer_mutex); + + /* was there mixer set request while executing mixer command? */ + for_each_vol(i, j) + if (os->vol_set[i][j] >= 0) + goto repeat_mixer; + + /* update internal mixer state */ + if (mret == 0) { + for_each_vol(i, j) { + if (marg.vol[i][j] >= 0) { + if (os->vol[i][j] != marg.vol[i][j]) + os->mixer->modify_counter++; + os->vol[i][j] = marg.vol[i][j]; + } + } + } + os->mixer_pending = 0; + } + + pthread_mutex_unlock(&os->cmd_mutex); + + /* + * mixer mutex must be released after cmd_mutex so that + * exec_mixer_cmd() can guarantee that mixer_pending flags + * will be handled immediately or when the currently + * in-progress command completes. + */ + pthread_mutex_unlock(&mixer_mutex); + + return is_mixer ? mret : ret; +} + +static ssize_t exec_simple_cmd(struct ossp_stream *os, + enum ossp_opcode opcode, void *carg, void *rarg) +{ + return exec_cmd(os, opcode, + carg, ossp_arg_sizes[opcode].carg_size, NULL, 0, + rarg, ossp_arg_sizes[opcode].rarg_size, NULL, NULL, -1); +} + +static int ioctl_prep_uarg(fuse_req_t req, void *in, size_t in_sz, void *out, + size_t out_sz, void *uarg, const void *in_buf, + size_t in_bufsz, size_t out_bufsz) +{ + struct iovec in_iov = { }, out_iov = { }; + int retry = 0; + + if (in) { + if (!in_bufsz) { + in_iov.iov_base = uarg; + in_iov.iov_len = in_sz; + retry = 1; + } else { + assert(in_bufsz == in_sz); + memcpy(in, in_buf, in_sz); + } + } + + if (out) { + if (!out_bufsz) { + out_iov.iov_base = uarg; + out_iov.iov_len = out_sz; + retry = 1; + } else + assert(out_bufsz == out_sz); + } + + if (retry) + fuse_reply_ioctl_retry(req, &in_iov, 1, &out_iov, 1); + + return retry; +} + +#define PREP_UARG(inp, outp) do { \ + if (ioctl_prep_uarg(req, (inp), sizeof(*(inp)), \ + (outp), sizeof(*(outp)), uarg, \ + in_buf, in_bufsz, out_bufsz)) \ + return; \ +} while (0) + +#define IOCTL_RETURN(result, outp) do { \ + if ((outp) != NULL) \ + fuse_reply_ioctl(req, result, (outp), sizeof(*(outp))); \ + else \ + fuse_reply_ioctl(req, result, NULL, 0); \ + return; \ +} while (0) + + +/*************************************************************************** + * Mixer implementation + */ + +static void put_mixer_real(struct ossp_mixer *mixer) +{ + if (!--mixer->refcnt) { + dbg0("DESTROY mixer(%d)", mixer->pgrp); + list_del_init(&mixer->link); + list_del_init(&mixer->delayed_put_link); + free(mixer); + nr_mixers--; + + /* + * If exit_on_idle, mixer for pgrp0 is touched during + * init and each stream has mixer attached. As mixers + * are destroyed after they have been idle for + * MIXER_PUT_DELAY seconds, we can use it for idle + * detection. Note that this might race with + * concurrent open. The race is inherent. + */ + if (exit_on_idle && !nr_mixers) { + info("idle, exiting"); + exit(0); + } + } +} + +static struct ossp_mixer *get_mixer(pid_t pgrp) +{ + struct ossp_mixer *mixer; + + pthread_mutex_lock(&mutex); + + /* is there a matching one? */ + mixer = find_mixer_locked(pgrp); + if (mixer) { + if (list_empty(&mixer->delayed_put_link)) + mixer->refcnt++; + else + list_del_init(&mixer->delayed_put_link); + goto out_unlock; + } + + /* reap delayed put list if there are too many mixers */ + while (nr_mixers > 2 * max_streams && + !list_empty(&mixer_delayed_put_head)) { + struct ossp_mixer *mixer = + list_first_entry(&mixer_delayed_put_head, + struct ossp_mixer, delayed_put_link); + + assert(mixer->refcnt == 1); + put_mixer_real(mixer); + } + + /* create a new one */ + mixer = calloc(1, sizeof(*mixer)); + if (!mixer) { + warn("failed to allocate mixer for %d", pgrp); + mixer = NULL; + goto out_unlock; + } + + mixer->pgrp = pgrp; + INIT_LIST_HEAD(&mixer->link); + INIT_LIST_HEAD(&mixer->delayed_put_link); + mixer->refcnt = 1; + memset(mixer->vol, -1, sizeof(mixer->vol)); + + list_add(&mixer->link, mixer_tbl_head(pgrp)); + nr_mixers++; + dbg0("CREATE mixer(%d)", pgrp); + +out_unlock: + pthread_mutex_unlock(&mutex); + return mixer; +} + +static void put_mixer(struct ossp_mixer *mixer) +{ + pthread_mutex_lock(&mutex); + + if (mixer) { + if (mixer->refcnt == 1) { + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &ts); + mixer->put_expires = ts.tv_sec + MIXER_PUT_DELAY; + list_add_tail(&mixer->delayed_put_link, + &mixer_delayed_put_head); + pthread_cond_signal(&mixer_delayed_put_cond); + } else + put_mixer_real(mixer); + } + + pthread_mutex_unlock(&mutex); +} + +static void *mixer_delayed_put_worker(void *arg) +{ + struct ossp_mixer *mixer; + struct timespec ts; + time_t now; + + pthread_mutex_lock(&mutex); +again: + clock_gettime(CLOCK_REALTIME, &ts); + now = ts.tv_sec; + + mixer = NULL; + while (!list_empty(&mixer_delayed_put_head)) { + mixer = list_first_entry(&mixer_delayed_put_head, + struct ossp_mixer, delayed_put_link); + + if (now <= mixer->put_expires) + break; + + assert(mixer->refcnt == 1); + put_mixer_real(mixer); + mixer = NULL; + } + + if (mixer) { + ts.tv_sec = mixer->put_expires + 1; + pthread_cond_timedwait(&mixer_delayed_put_cond, &mutex, &ts); + } else + pthread_cond_wait(&mixer_delayed_put_cond, &mutex); + + goto again; +} + +static void init_mixer_cmd(struct ossp_mixer_cmd *mxcmd, + struct ossp_mixer *mixer) +{ + memset(mxcmd, 0, sizeof(*mxcmd)); + memset(&mxcmd->set.vol, -1, sizeof(mxcmd->set.vol)); + mxcmd->mixer = mixer; + mxcmd->out_dir = -1; +} + +static int exec_mixer_cmd(struct ossp_mixer_cmd *mxcmd, struct ossp_stream *os) +{ + int i, j, rc; + + /* + * Set pending flags before trying to execute mixer command. + * Combined with lock release order in exec_cmd(), this + * guarantees that the mixer command will be executed + * immediately or when the current command completes. + */ + pthread_mutex_lock(&mixer_mutex); + os->mixer_pending = 1; + for_each_vol(i, j) + if (mxcmd->set.vol[i][j] >= 0) + os->vol_set[i][j] = mxcmd->set.vol[i][j]; + pthread_mutex_unlock(&mixer_mutex); + + rc = exec_simple_cmd(os, OSSP_MIXER, NULL, NULL); + if (rc >= 0) { + dbg0_os(os, "volume set=%d/%d:%d/%d get=%d/%d:%d/%d", + mxcmd->set.vol[PLAY][LEFT], mxcmd->set.vol[PLAY][RIGHT], + mxcmd->set.vol[REC][LEFT], mxcmd->set.vol[REC][RIGHT], + os->vol[PLAY][LEFT], os->vol[PLAY][RIGHT], + os->vol[REC][LEFT], os->vol[REC][RIGHT]); + } else if (rc != -EBUSY) + warn_ose(os, rc, "mixer command failed"); + + return rc; +} + +static void finish_mixer_cmd(struct ossp_mixer_cmd *mxcmd) +{ + struct ossp_mixer *mixer = mxcmd->mixer; + struct ossp_stream *os; + int dir = mxcmd->out_dir; + int vol[2][2] = { }; + int cnt[2][2] = { }; + int i, j; + + pthread_mutex_lock(&mixer_mutex); + + /* get volume of all streams attached to this mixer */ + pthread_mutex_lock(&mutex); + list_for_each_entry(os, os_pgrp_tbl_head(mixer->pgrp), pgrp_link) { + if (os->pgrp != mixer->pgrp) + continue; + for_each_vol(i, j) { + if (os->vol[i][j] < 0) + continue; + vol[i][j] += os->vol[i][j]; + cnt[i][j]++; + } + } + pthread_mutex_unlock(&mutex); + + /* calculate the summary volume values */ + for_each_vol(i, j) { + if (mxcmd->set.vol[i][j] >= 0) + vol[i][j] = mxcmd->set.vol[i][j]; + else if (cnt[i][j]) + vol[i][j] = vol[i][j] / cnt[i][j]; + else if (mixer->vol[i][j] >= 0) + vol[i][j] = mixer->vol[i][j]; + else + vol[i][j] = 100; + + vol[i][j] = min(max(0, vol[i][j]), 100); + } + + if (dir >= 0) + mxcmd->rvol = vol[dir][LEFT] | (vol[dir][RIGHT] << 8); + + pthread_mutex_unlock(&mixer_mutex); +} + +static void mixer_simple_ioctl(fuse_req_t req, struct ossp_mixer *mixer, + unsigned cmd, void *uarg, const void *in_buf, + size_t in_bufsz, size_t out_bufsz, + int *not_minep) +{ + const char *id = "OSS Proxy", *name = "Mixer"; + int i; + + switch (cmd) { + case SOUND_MIXER_INFO: { + struct mixer_info info = { }; + + PREP_UARG(NULL, &info); + strncpy(info.id, id, sizeof(info.id) - 1); + strncpy(info.name, name, sizeof(info.name) - 1); + info.modify_counter = mixer->modify_counter; + IOCTL_RETURN(0, &info); + } + + case SOUND_OLD_MIXER_INFO: { + struct _old_mixer_info info = { }; + + PREP_UARG(NULL, &info); + strncpy(info.id, id, sizeof(info.id) - 1); + strncpy(info.name, name, sizeof(info.name) - 1); + IOCTL_RETURN(0, &info); + } + + case OSS_GETVERSION: + i = SNDRV_OSS_VERSION; + goto puti; + case SOUND_MIXER_READ_DEVMASK: + case SOUND_MIXER_READ_STEREODEVS: + i = SOUND_MASK_PCM | SOUND_MASK_IGAIN; + goto puti; + case SOUND_MIXER_READ_CAPS: + i = SOUND_CAP_EXCL_INPUT; + goto puti; + case SOUND_MIXER_READ_RECMASK: + case SOUND_MIXER_READ_RECSRC: + i = SOUND_MASK_IGAIN; + goto puti; + puti: + PREP_UARG(NULL, &i); + IOCTL_RETURN(0, &i); + + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_RETURN(0, NULL); + + default: + *not_minep = 1; + return; + } + assert(0); +} + +static void mixer_do_ioctl(fuse_req_t req, struct ossp_mixer *mixer, + unsigned cmd, void *uarg, const void *in_buf, + size_t in_bufsz, size_t out_bufsz) +{ + struct ossp_mixer_cmd mxcmd; + struct ossp_stream *os, **osa; + int not_mine = 0; + int slot = cmd & 0xff, dir; + int nr_os; + int i, rc; + + mixer_simple_ioctl(req, mixer, cmd, uarg, in_buf, in_bufsz, out_bufsz, + ¬_mine); + if (!not_mine) + return; + + rc = -ENXIO; + if (!(cmd & (SIOC_IN | SIOC_OUT))) + goto err; + + /* + * Okay, it's not one of the easy ones. Build mxcmd for + * actual volume control. + */ + if (cmd & SIOC_IN) + PREP_UARG(&i, &i); + else + PREP_UARG(NULL, &i); + + switch (slot) { + case SOUND_MIXER_PCM: + dir = PLAY; + break; + case SOUND_MIXER_IGAIN: + dir = REC; + break; + default: + i = 0; + IOCTL_RETURN(0, &i); + } + + init_mixer_cmd(&mxcmd, mixer); + + if (cmd & SIOC_IN) { + unsigned l, r; + + rc = -EINVAL; + l = i & 0xff; + r = (i >> 8) & 0xff; + if (l > 100 || r > 100) + goto err; + + mixer->vol[dir][LEFT] = mxcmd.set.vol[dir][LEFT] = l; + mixer->vol[dir][RIGHT] = mxcmd.set.vol[dir][RIGHT] = r; + } + mxcmd.out_dir = dir; + + /* + * Apply volume conrol + */ + /* acquire target streams */ + pthread_mutex_lock(&mutex); + osa = calloc(max_streams, sizeof(osa[0])); + if (!osa) { + pthread_mutex_unlock(&mutex); + rc = -ENOMEM; + goto err; + } + + nr_os = 0; + list_for_each_entry(os, os_pgrp_tbl_head(mixer->pgrp), pgrp_link) { + if (os->pgrp == mixer->pgrp) { + osa[nr_os++] = os; + os->refcnt++; + } + } + + pthread_mutex_unlock(&mutex); + + /* execute mxcmd for each stream and put it */ + for (i = 0; i < nr_os; i++) { + exec_mixer_cmd(&mxcmd, osa[i]); + put_os(osa[i]); + } + + finish_mixer_cmd(&mxcmd); + free(osa); + + IOCTL_RETURN(0, out_bufsz ? &mxcmd.rvol : NULL); + +err: + fuse_reply_err(req, -rc); +} + +static void mixer_open(fuse_req_t req, struct fuse_file_info *fi) +{ + pid_t pid = fuse_req_ctx(req)->pid, pgrp; + struct ossp_mixer *mixer; + int rc; + + rc = get_proc_self_info(pid, &pgrp, NULL, 0); + if (rc) { + err_e(rc, "get_proc_self_info(%d) failed", pid); + fuse_reply_err(req, -rc); + return; + } + + mixer = get_mixer(pgrp); + fi->fh = pgrp; + + if (mixer) + fuse_reply_open(req, fi); + else + fuse_reply_err(req, ENOMEM); +} + +static void mixer_ioctl(fuse_req_t req, int signed_cmd, void *uarg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz) +{ + struct ossp_mixer *mixer; + + mixer = find_mixer(fi->fh); + if (!mixer) { + fuse_reply_err(req, EBADF); + return; + } + + mixer_do_ioctl(req, mixer, signed_cmd, uarg, in_buf, in_bufsz, + out_bufsz); +} + +static void mixer_release(fuse_req_t req, struct fuse_file_info *fi) +{ + struct ossp_mixer *mixer; + + mixer = find_mixer(fi->fh); + if (mixer) { + put_mixer(mixer); + fuse_reply_err(req, 0); + } else + fuse_reply_err(req, EBADF); +} + + +/*************************************************************************** + * Stream implementation + */ + +static int alloc_os(size_t stream_size, size_t mmap_size, pid_t pid, uid_t pgrp, + uid_t uid, gid_t gid, int cmd_sock, + const int *notify, struct fuse_session *se, + struct ossp_stream **osp) +{ + struct ossp_uid_cnt *tmp_ucnt, *ucnt = NULL; + struct ossp_stream *os; + int rc; + + assert(stream_size >= sizeof(struct ossp_stream)); + os = calloc(1, stream_size); + if (!os) + return -ENOMEM; + + INIT_LIST_HEAD(&os->link); + INIT_LIST_HEAD(&os->pgrp_link); + INIT_LIST_HEAD(&os->notify_link); + os->refcnt = 1; + + rc = -pthread_mutex_init(&os->cmd_mutex, NULL); + if (rc) + goto err_free; + + rc = -pthread_mutex_init(&os->mmap_mutex, NULL); + if (rc) + goto err_destroy_cmd_mutex; + + pthread_mutex_lock(&mutex); + + list_for_each_entry(tmp_ucnt, &uid_cnt_list, link) + if (tmp_ucnt->uid == uid) { + ucnt = tmp_ucnt; + break; + } + if (!ucnt) { + rc = -ENOMEM; + ucnt = calloc(1, sizeof(*ucnt)); + if (!ucnt) + goto err_unlock; + ucnt->uid = uid; + list_add(&ucnt->link, &uid_cnt_list); + } + + rc = -EBUSY; + if (ucnt->nr_os + 1 > umax_streams) + goto err_unlock; + + /* everything looks fine, allocate id and init stream */ + rc = -EBUSY; + os->id = find_next_zero_bit(os_id_bitmap, max_streams, 0); + if (os->id >= max_streams) + goto err_unlock; + __set_bit(os->id, os_id_bitmap); + + os->cmd_fd = cmd_sock; + os->notify_tx = notify[1]; + os->notify_rx = notify[0]; + os->pid = pid; + os->pgrp = pgrp; + os->uid = uid; + os->gid = gid; + if (mmap_size) { + os->mmap_off = os->id * mmap_size; + os->mmap_size = mmap_size; + } + os->ucnt = ucnt; + os->se = se; + + memset(os->vol, -1, sizeof(os->vol)); + memset(os->vol_set, -1, sizeof(os->vol)); + + list_add(&os->link, os_tbl_head(os->id)); + list_add(&os->pgrp_link, os_pgrp_tbl_head(os->pgrp)); + + ucnt->nr_os++; + *osp = os; + pthread_mutex_unlock(&mutex); + return 0; + +err_unlock: + pthread_mutex_unlock(&mutex); + pthread_mutex_destroy(&os->mmap_mutex); +err_destroy_cmd_mutex: + pthread_mutex_destroy(&os->cmd_mutex); +err_free: + free(os); + return rc; +} + +static void shutdown_notification(struct ossp_stream *os) +{ + struct ossp_notify obituary = { .magic = OSSP_NOTIFY_MAGIC, + .opcode = OSSP_NOTIFY_OBITUARY }; + ssize_t ret; + + /* + * Shutdown notification for this stream. We politely ask + * notify_poller to shut the receive side down to avoid racing + * with it. + */ + while (os->notify_rx >= 0) { + ret = write(os->notify_tx, &obituary, sizeof(obituary)); + if (ret <= 0) { + if (ret == 0) + warn_os(os, "unexpected EOF on notify_tx"); + else if (errno != EPIPE) + warn_ose(os, -errno, + "unexpected error on notify_tx"); + close(os->notify_rx); + os->notify_rx = -1; + break; + } + + if (ret != sizeof(obituary)) + warn_os(os, "short transfer on notify_tx"); + pthread_cond_wait(¬ify_poller_kill_wait, &mutex); + } +} + +static void put_os(struct ossp_stream *os) +{ + if (!os) + return; + + pthread_mutex_lock(&mutex); + + assert(os->refcnt); + if (--os->refcnt) { + pthread_mutex_unlock(&mutex); + return; + } + + os->dead = 1; + shutdown_notification(os); + + dbg0_os(os, "DESTROY"); + + list_del_init(&os->link); + list_del_init(&os->pgrp_link); + list_del_init(&os->notify_link); + os->ucnt->nr_os--; + + pthread_mutex_unlock(&mutex); + + close(os->cmd_fd); + close(os->notify_tx); + put_mixer(os->mixer); + pthread_mutex_destroy(&os->cmd_mutex); + pthread_mutex_destroy(&os->mmap_mutex); + + pthread_mutex_lock(&mutex); + dbg1_os(os, "stream dead, requesting reaping"); + list_add_tail(&os->link, &slave_corpse_list); + pthread_cond_signal(&slave_reaper_wait); + pthread_mutex_unlock(&mutex); +} + +static void set_extra_env(pid_t pid) +{ + char procenviron[32]; + const int step = 1024; + char *data = malloc(step + 1); + int ofs = 0; + int fd; + int ret; + + if (!data) + return; + + sprintf(procenviron, "/proc/%d/environ", pid); + fd = open(procenviron, O_RDONLY); + if (fd < 0) + return; + + /* + * There should really be a 'read whole file to a newly allocated + * buffer' function. + */ + while ((ret = read(fd, data + ofs, step)) > 0) { + char *newdata; + ofs += ret; + newdata = realloc(data, ofs + step + 1); + if (!newdata) { + ret = -1; + break; + } + data = newdata; + } + if (ret == 0) { + char *ptr = data; + /* Append the extra 0 for end condition */ + data[ofs] = 0; + + while ((ret = strlen(ptr)) > 0) { + /* + * Copy all PULSE variables and DISPLAY so that + * ssh -X remotehost 'mplayer -ao oss' will work + */ + if (!strncmp(ptr, "DISPLAY=", 8) || + !strncmp(ptr, "PULSE_", 6)) + putenv(ptr); + ptr += ret + 1; + } + } + + free(data); + close(fd); +} + +#ifndef GIOVANNI +int contapid = 13000; +#endif// GIOVANNI + +static int create_os(const char *slave_path, + size_t stream_size, size_t mmap_size, + pid_t pid, pid_t pgrp, uid_t uid, gid_t gid, + struct fuse_session *se, struct ossp_stream **osp) +{ + static pthread_mutex_t create_mutex = PTHREAD_MUTEX_INITIALIZER; + int cmd_sock[2] = { -1, -1 }; + int notify_sock[2] = { -1, -1 }; + struct ossp_stream *os = NULL; + struct epoll_event ev = { }; + int i, rc; + + /* + * Only one thread can be creating a stream. This is to avoid + * leaking unwanted fds into slaves. + */ + pthread_mutex_lock(&create_mutex); + + /* prepare communication channels */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, cmd_sock) || + socketpair(AF_UNIX, SOCK_STREAM, 0, notify_sock)) { + rc = -errno; + warn_e(rc, "failed to create slave command channel"); + goto close_all; + } + + if (fcntl(notify_sock[0], F_SETFL, O_NONBLOCK) < 0) { + rc = -errno; + warn_e(rc, "failed to set NONBLOCK on notify sock"); + goto close_all; + } + + /* + * Alloc stream which will be responsible for all server side + * resources from now on. + */ + rc = alloc_os(stream_size, mmap_size, pid, pgrp, uid, gid, cmd_sock[0], + notify_sock, se, &os); + if (rc) { + warn_e(rc, "failed to allocate stream for %d", pid); + goto close_all; + } + + rc = -ENOMEM; + os->mixer = get_mixer(pgrp); + if (!os->mixer) + goto put_os; + + /* + * Register notification. If successful, notify_poller has + * custody of notify_rx fd. + */ + pthread_mutex_lock(&mutex); + list_add(&os->notify_link, os_notify_tbl_head(os->notify_rx)); + pthread_mutex_unlock(&mutex); + +#ifndef GIOVANNI + os->slave_pid = contapid; + contapid++; + if(contapid > 30000) + contapid=13000; +#endif //GIOVANNI + +//#ifdef GIOVANNI + ev.events = EPOLLIN; + ev.data.fd = notify_sock[0]; + if (epoll_ctl(notify_epfd, EPOLL_CTL_ADD, notify_sock[0], &ev)) { + /* + * Without poller watching this notify sock, poller + * shutdown sequence in shutdown_notification() can't + * be used. Kill notification rx manually. + */ + rc = -errno; + warn_ose(os, rc, "failed to add notify epoll"); + close(os->notify_rx); + os->notify_rx = -1; + goto put_os; + } + + /* start slave */ + os->slave_pid = fork(); + if (os->slave_pid < 0) { + rc = -errno; + warn_ose(os, rc, "failed to fork slave"); + goto put_os; + } + + if (os->slave_pid == 0) { + /* child */ + char id_str[2][16], fd_str[3][16]; + char mmap_off_str[32], mmap_size_str[32]; + char log_str[16], slave_path_copy[PATH_MAX]; + char *argv[] = { slave_path_copy, "-u", id_str[0], + "-g", id_str[1], "-c", fd_str[0], + "-n", fd_str[1], "-m", fd_str[2], + "-o", mmap_off_str, "-s", mmap_size_str, + "-l", log_str, NULL, NULL }; + struct passwd *pwd; + + /* drop stuff we don't need */ + if (close(cmd_sock[0]) || close(notify_sock[0])) + fatal_e(-errno, "failed to close server pipe fds"); + +#ifdef OSSP_MMAP + if (!mmap_size) + close(fuse_mmap_fd(se)); +#endif + + clearenv(); + pwd = getpwuid(os->uid); + if (pwd) { + setenv("LOGNAME", pwd->pw_name, 1); + setenv("USER", pwd->pw_name, 1); + setenv("HOME", pwd->pw_dir, 1); + } + /* Set extra environment variables from the caller */ + set_extra_env(pid); + + /* prep and exec */ + slave_path_copy[sizeof(slave_path_copy) - 1] = '\0'; + strncpy(slave_path_copy, slave_path, sizeof(slave_path_copy) - 1); + if (slave_path_copy[sizeof(slave_path_copy) - 1] != '\0') { + rc = -errno; + err_ose(os, rc, "slave path too long"); + goto child_fail; + } + + snprintf(id_str[0], sizeof(id_str[0]), "%d", os->uid); + snprintf(id_str[1], sizeof(id_str[0]), "%d", os->gid); + snprintf(fd_str[0], sizeof(fd_str[0]), "%d", cmd_sock[1]); + snprintf(fd_str[1], sizeof(fd_str[1]), "%d", notify_sock[1]); + snprintf(fd_str[2], sizeof(fd_str[2]), "%d", +#ifdef OSSP_MMAP + mmap_size ? fuse_mmap_fd(se) : +#endif + -1); + snprintf(mmap_off_str, sizeof(mmap_off_str), "0x%llx", + (unsigned long long)os->mmap_off); + snprintf(mmap_size_str, sizeof(mmap_size_str), "0x%zx", + mmap_size); + snprintf(log_str, sizeof(log_str), "%d", ossp_log_level); + if (ossp_log_timestamp) + argv[ARRAY_SIZE(argv) - 2] = "-t"; + + execv(slave_path, argv); + rc = -errno; + err_ose(os, rc, "execv failed for <%d>", pid); + child_fail: + _exit(1); + } +//#endif //GIOVANNI + + /* turn on CLOEXEC on all server side fds */ + if (fcntl(os->cmd_fd, F_SETFD, FD_CLOEXEC) < 0 || + fcntl(os->notify_tx, F_SETFD, FD_CLOEXEC) < 0 || + fcntl(os->notify_rx, F_SETFD, FD_CLOEXEC) < 0) { + rc = -errno; + err_ose(os, rc, "failed to set CLOEXEC on server side fds"); + goto put_os; + } + + dbg0_os(os, "CREATE slave=%d %s", os->slave_pid, slave_path); + dbg0_os(os, " client=%d cmd=%d:%d notify=%d:%d mmap=%d:0x%llx:%zu", + pid, cmd_sock[0], cmd_sock[1], notify_sock[0], notify_sock[1], +#ifdef OSSP_MMAP + os->mmap_size ? fuse_mmap_fd(se) : +#endif + -1, + (unsigned long long)os->mmap_off, os->mmap_size); + + *osp = os; + rc = 0; + goto close_client_fds; + +put_os: + put_os(os); +close_client_fds: + close(cmd_sock[1]); + pthread_mutex_unlock(&create_mutex); + return rc; + +close_all: + for (i = 0; i < 2; i++) { + close(cmd_sock[i]); + close(notify_sock[i]); + } + pthread_mutex_unlock(&create_mutex); + return rc; +} + +static void dsp_open_common(fuse_req_t req, struct fuse_file_info *fi, + struct fuse_session *se) +{ + const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req); + struct ossp_dsp_open_arg arg = { }; + struct ossp_stream *os = NULL; + struct ossp_mixer *mixer; + struct ossp_dsp_stream *dsps; + struct ossp_mixer_cmd mxcmd; + pid_t pgrp; + ssize_t ret; + + ret = get_proc_self_info(fuse_ctx->pid, &pgrp, NULL, 0); + if (ret) { + err_e(ret, "get_proc_self_info(%d) failed", fuse_ctx->pid); + goto err; + } + + ret = create_os(dsp_slave_path, sizeof(*dsps), DSPS_MMAP_SIZE, + fuse_ctx->pid, pgrp, fuse_ctx->uid, fuse_ctx->gid, + se, &os); + if (ret) + goto err; + dsps = os_to_dsps(os); + mixer = os->mixer; + + switch (fi->flags & O_ACCMODE) { + case O_WRONLY: + dsps->rw |= 1 << PLAY; + break; + case O_RDONLY: + dsps->rw |= 1 << REC; + break; + case O_RDWR: + dsps->rw |= (1 << PLAY) | (1 << REC); + break; + default: + assert(0); + } + + arg.flags = fi->flags; + arg.opener_pid = os->pid; + ret = exec_simple_cmd(&dsps->os, OSSP_DSP_OPEN, &arg, NULL); + if (ret < 0) { + put_os(os); + goto err; + } + + memcpy(os->vol, mixer->vol, sizeof(os->vol)); + if (os->vol[PLAY][0] >= 0 || os->vol[REC][0] >= 0) { + init_mixer_cmd(&mxcmd, mixer); + memcpy(mxcmd.set.vol, os->vol, sizeof(os->vol)); + exec_mixer_cmd(&mxcmd, os); + finish_mixer_cmd(&mxcmd); + } + + fi->direct_io = 1; + fi->nonseekable = 1; + fi->fh = os->id; + + fuse_reply_open(req, fi); + return; + +err: + fuse_reply_err(req, -ret); +} + +static void dsp_open(fuse_req_t req, struct fuse_file_info *fi) +{ + dsp_open_common(req, fi, dsp_se); +} + +static void adsp_open(fuse_req_t req, struct fuse_file_info *fi) +{ + dsp_open_common(req, fi, adsp_se); +} + +static void dsp_release(fuse_req_t req, struct fuse_file_info *fi) +{ + struct ossp_stream *os; + + os = find_os(fi->fh); + if (os) { + put_os(os); + fuse_reply_err(req, 0); + } else + fuse_reply_err(req, EBADF); +} + +static void dsp_read(fuse_req_t req, size_t size, off_t off, + struct fuse_file_info *fi) +{ + struct ossp_dsp_rw_arg arg = { }; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + void *buf = NULL; + ssize_t ret; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto out; + dsps = os_to_dsps(os); + + ret = -EINVAL; + if (!(dsps->rw & (1 << REC))) + goto out; + + ret = -ENXIO; + if (dsps->mmapped) + goto out; + + ret = -ENOMEM; + buf = malloc(size); + if (!buf) + goto out; + + arg.nonblock = (fi->flags & O_NONBLOCK) || dsps->nonblock; + + ret = exec_cmd(os, OSSP_DSP_READ, &arg, sizeof(arg), + NULL, 0, NULL, 0, buf, &size, -1); +out: + if (ret >= 0) + fuse_reply_buf(req, buf, size); + else + fuse_reply_err(req, -ret); + + free(buf); +} + +static void dsp_write(fuse_req_t req, const char *buf, size_t size, off_t off, + struct fuse_file_info *fi) +{ + struct ossp_dsp_rw_arg arg = { }; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + ssize_t ret; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto out; + dsps = os_to_dsps(os); + + ret = -EINVAL; + if (!(dsps->rw & (1 << PLAY))) + goto out; + + ret = -ENXIO; + if (dsps->mmapped) + goto out; + + arg.nonblock = (fi->flags & O_NONBLOCK) || dsps->nonblock; + + ret = exec_cmd(os, OSSP_DSP_WRITE, &arg, sizeof(arg), + buf, size, NULL, 0, NULL, NULL, -1); +out: + if (ret >= 0) + fuse_reply_write(req, ret); + else + fuse_reply_err(req, -ret); +} + +static void dsp_poll(fuse_req_t req, struct fuse_file_info *fi, + struct fuse_pollhandle *ph) +{ + int notify = ph != NULL; + unsigned revents = 0; + struct ossp_stream *os; + ssize_t ret; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto out; + + if (ph) { + pthread_mutex_lock(&mutex); + if (os->ph) + fuse_pollhandle_destroy(os->ph); + os->ph = ph; + pthread_mutex_unlock(&mutex); + } + + ret = exec_simple_cmd(os, OSSP_DSP_POLL, ¬ify, &revents); +out: + if (ret >= 0) + fuse_reply_poll(req, revents); + else + fuse_reply_err(req, -ret); +} + +static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz) +{ + /* some ioctl constants are long and has the highest bit set */ + unsigned cmd = signed_cmd; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + enum ossp_opcode op; + ssize_t ret; + int i; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto err; + dsps = os_to_dsps(os); + + /* mixer commands are allowed on DSP devices */ + if (((cmd >> 8) & 0xff) == 'M') { + mixer_do_ioctl(req, os->mixer, cmd, uarg, in_buf, in_bufsz, + out_bufsz); + return; + } + + /* and the rest */ + switch (cmd) { + case OSS_GETVERSION: + i = SNDRV_OSS_VERSION; + PREP_UARG(NULL, &i); + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_GETCAPS: + i = DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | +#ifdef OSSP_MMAP + DSP_CAP_MMAP | +#endif + DSP_CAP_MULTI; + PREP_UARG(NULL, &i); + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_NONBLOCK: + dsps->nonblock = 1; + ret = 0; + IOCTL_RETURN(0, NULL); + + case SNDCTL_DSP_RESET: op = OSSP_DSP_RESET; goto nd; + case SNDCTL_DSP_SYNC: op = OSSP_DSP_SYNC; goto nd; + case SNDCTL_DSP_POST: op = OSSP_DSP_POST; goto nd; + nd: + ret = exec_simple_cmd(&dsps->os, op, NULL, NULL); + if (ret) + goto err; + IOCTL_RETURN(0, NULL); + + case SOUND_PCM_READ_RATE: op = OSSP_DSP_GET_RATE; goto ri; + case SOUND_PCM_READ_BITS: op = OSSP_DSP_GET_FORMAT; goto ri; + case SOUND_PCM_READ_CHANNELS: op = OSSP_DSP_GET_CHANNELS; goto ri; + case SNDCTL_DSP_GETBLKSIZE: op = OSSP_DSP_GET_BLKSIZE; goto ri; + case SNDCTL_DSP_GETFMTS: op = OSSP_DSP_GET_FORMATS; goto ri; + case SNDCTL_DSP_GETTRIGGER: op = OSSP_DSP_GET_TRIGGER; goto ri; + ri: + PREP_UARG(NULL, &i); + ret = exec_simple_cmd(&dsps->os, op, NULL, &i); + if (ret) + goto err; + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_SPEED: op = OSSP_DSP_SET_RATE; goto wi; + case SNDCTL_DSP_SETFMT: op = OSSP_DSP_SET_FORMAT; goto wi; + case SNDCTL_DSP_CHANNELS: op = OSSP_DSP_SET_CHANNELS; goto wi; + case SNDCTL_DSP_SUBDIVIDE: op = OSSP_DSP_SET_SUBDIVISION; goto wi; + wi: + PREP_UARG(&i, &i); + ret = exec_simple_cmd(&dsps->os, op, &i, &i); + if (ret) + goto err; + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_STEREO: + PREP_UARG(NULL, &i); + i = 2; + ret = exec_simple_cmd(&dsps->os, OSSP_DSP_SET_CHANNELS, &i, &i); + i--; + if (ret) + goto err; + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_SETFRAGMENT: + PREP_UARG(&i, NULL); + ret = exec_simple_cmd(&dsps->os, + OSSP_DSP_SET_FRAGMENT, &i, NULL); + if (ret) + goto err; + IOCTL_RETURN(0, NULL); + + case SNDCTL_DSP_SETTRIGGER: + PREP_UARG(&i, NULL); + ret = exec_simple_cmd(&dsps->os, + OSSP_DSP_SET_TRIGGER, &i, NULL); + if (ret) + goto err; + IOCTL_RETURN(0, NULL); + + case SNDCTL_DSP_GETOSPACE: + case SNDCTL_DSP_GETISPACE: { + struct audio_buf_info info; + + ret = -EINVAL; + if (cmd == SNDCTL_DSP_GETOSPACE) { + if (!(dsps->rw & (1 << PLAY))) + goto err; + op = OSSP_DSP_GET_OSPACE; + } else { + if (!(dsps->rw & (1 << REC))) + goto err; + op = OSSP_DSP_GET_ISPACE; + } + + PREP_UARG(NULL, &info); + ret = exec_simple_cmd(&dsps->os, op, NULL, &info); + if (ret) + goto err; + IOCTL_RETURN(0, &info); + } + + case SNDCTL_DSP_GETOPTR: + case SNDCTL_DSP_GETIPTR: { + struct count_info info; + + op = cmd == SNDCTL_DSP_GETOPTR ? OSSP_DSP_GET_OPTR + : OSSP_DSP_GET_IPTR; + PREP_UARG(NULL, &info); + ret = exec_simple_cmd(&dsps->os, op, NULL, &info); + if (ret) + goto err; + IOCTL_RETURN(0, &info); + } + + case SNDCTL_DSP_GETODELAY: + PREP_UARG(NULL, &i); + i = 0; + ret = exec_simple_cmd(&dsps->os, OSSP_DSP_GET_ODELAY, NULL, &i); + IOCTL_RETURN(ret, &i); /* always copy out result, 0 on err */ + + case SOUND_PCM_WRITE_FILTER: + case SOUND_PCM_READ_FILTER: + ret = -EIO; + goto err; + + case SNDCTL_DSP_MAPINBUF: + case SNDCTL_DSP_MAPOUTBUF: + ret = -EINVAL; + goto err; + + case SNDCTL_DSP_SETSYNCRO: + case SNDCTL_DSP_SETDUPLEX: + case SNDCTL_DSP_PROFILE: + IOCTL_RETURN(0, NULL); + + default: + warn_os(os, "unknown ioctl 0x%x", cmd); + ret = -EINVAL; + goto err; + } + assert(0); /* control shouldn't reach here */ +err: + fuse_reply_err(req, -ret); +} + +#ifdef OSSP_MMAP +static int dsp_mmap_dir(int prot) +{ + if (!(prot & PROT_WRITE)) + return REC; + return PLAY; +} + +static void dsp_mmap(fuse_req_t req, void *addr, size_t len, int prot, + int flags, off_t offset, struct fuse_file_info *fi, + uint64_t mh) +{ + int dir = dsp_mmap_dir(prot); + struct ossp_dsp_mmap_arg arg = { }; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + ssize_t ret; + + os = find_os(fi->fh); + if (!os) { + fuse_reply_err(req, EBADF); + return; + } + dsps = os_to_dsps(os); + + if (!os->mmap_off || len > os->mmap_size / 2) { + fuse_reply_err(req, EINVAL); + return; + } + + pthread_mutex_lock(&os->mmap_mutex); + + ret = -EBUSY; + if (dsps->mmapped & (1 << dir)) + goto out_unlock; + + arg.dir = dir; + arg.size = len; + + ret = exec_simple_cmd(os, OSSP_DSP_MMAP, &arg, NULL); + if (ret == 0) + dsps->mmapped |= 1 << dir; + +out_unlock: + pthread_mutex_unlock(&os->mmap_mutex); + + if (ret == 0) + fuse_reply_mmap(req, os->mmap_off + dir * os->mmap_size / 2, 0); + else + fuse_reply_err(req, -ret); +} + +static void dsp_munmap(fuse_req_t req, size_t len, struct fuse_file_info *fi, + off_t offset, uint64_t mh) +{ + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + int dir, rc; + + os = find_os(fi->fh); + if (!os) + goto out; + dsps = os_to_dsps(os); + + pthread_mutex_lock(&os->mmap_mutex); + + for (dir = 0; dir < 2; dir++) + if (offset == os->mmap_off + dir * os->mmap_size / 2) + break; + if (dir == 2 || len > os->mmap_size / 2) { + warn_os(os, "invalid munmap request " + "offset=%llu len=%zu mmapped=0x%x", + (unsigned long long)offset, len, dsps->mmapped); + goto out_unlock; + } + + rc = exec_simple_cmd(os, OSSP_DSP_MUNMAP, &dir, NULL); + if (rc) + warn_ose(os, rc, "MUNMAP failed for dir=%d", dir); + + dsps->mmapped &= ~(1 << dir); + +out_unlock: + pthread_mutex_unlock(&os->mmap_mutex); +out: + fuse_reply_none(req); +} +#endif + + +/*************************************************************************** + * Notify poller + */ + +static void *notify_poller(void *arg) +{ + struct epoll_event events[1024]; + int i, nfds; + +repeat: + nfds = epoll_wait(notify_epfd, events, ARRAY_SIZE(events), -1); + for (i = 0; i < nfds; i++) { + int do_notify = 0; + struct ossp_stream *os; + struct ossp_notify notify; + ssize_t ret; + + os = find_os_by_notify_rx(events[i].data.fd); + if (!os) { + err("can't find stream for notify_rx fd %d", + events[i].data.fd); + epoll_ctl(notify_epfd, EPOLL_CTL_DEL, events[i].data.fd, + NULL); + /* we don't know what's going on, don't close the fd */ + continue; + } + + while ((ret = read(os->notify_rx, + ¬ify, sizeof(notify))) > 0) { + if (os->dead) + continue; + if (ret != sizeof(notify)) { + warn_os(os, "short read on notify_rx (%zu, " + "expected %zu), killing the stream", + ret, sizeof(notify)); + os->dead = 1; + break; + } + if (notify.magic != OSSP_NOTIFY_MAGIC) { + warn_os(os, "invalid magic on notification, " + "killing the stream"); + os->dead = 1; + break; + } + + if (notify.opcode >= OSSP_NR_NOTIFY_OPCODES) + goto unknown; + + dbg1_os(os, "NOTIFY %s", ossp_notify_str[notify.opcode]); + + switch (notify.opcode) { + case OSSP_NOTIFY_POLL: + do_notify = 1; + break; + case OSSP_NOTIFY_OBITUARY: + os->dead = 1; + break; + case OSSP_NOTIFY_VOLCHG: + pthread_mutex_lock(&mixer_mutex); + os->mixer->modify_counter++; + pthread_mutex_unlock(&mixer_mutex); + break; + default: + unknown: + warn_os(os, "unknown notification %d", + notify.opcode); + } + } + if (ret == 0) + os->dead = 1; + else if (ret < 0 && errno != EAGAIN) { + warn_ose(os, -errno, "read fail on notify fd"); + os->dead = 1; + } + + if (!do_notify && !os->dead) + continue; + + pthread_mutex_lock(&mutex); + + if (os->ph) { + fuse_lowlevel_notify_poll(os->ph); + fuse_pollhandle_destroy(os->ph); + os->ph = NULL; + } + + if (os->dead) { + dbg0_os(os, "removing %d from notify poll list", + os->notify_rx); + epoll_ctl(notify_epfd, EPOLL_CTL_DEL, os->notify_rx, + NULL); + close(os->notify_rx); + os->notify_rx = -1; + pthread_cond_broadcast(¬ify_poller_kill_wait); + } + + pthread_mutex_unlock(&mutex); + } + goto repeat; +} + + +/*************************************************************************** + * Slave corpse reaper + */ + +static void *slave_reaper(void *arg) +{ + struct ossp_stream *os; + int status; + pid_t pid; + + pthread_mutex_lock(&mutex); +repeat: + while (list_empty(&slave_corpse_list)) + pthread_cond_wait(&slave_reaper_wait, &mutex); + + os = list_first_entry(&slave_corpse_list, struct ossp_stream, link); + list_del_init(&os->link); + + pthread_mutex_unlock(&mutex); + + do { + pid = waitpid(os->slave_pid, &status, 0); + } while (pid < 0 && errno == EINTR); + + if (pid < 0) { + if (errno == ECHILD) + warn_ose(os, -errno, "slave %d already gone?", + os->slave_pid); + else + fatal_e(-errno, "waitpid(%d) failed", os->slave_pid); + } + + pthread_mutex_lock(&mutex); + + dbg1_os(os, "slave %d reaped", os->slave_pid); + __clear_bit(os->id, os_id_bitmap); + free(os); + + goto repeat; +} + + +/*************************************************************************** + * Stuff to bind and start everything + */ + +static void ossp_daemonize(void) +{ + int fd, pfd[2]; + pid_t pid; + ssize_t ret; + int err; + + fd = open("/dev/null", O_RDWR); + if (fd >= 0) { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + if (fd > 2) + close(fd); + } + + if (pipe(pfd)) + fatal_e(-errno, "failed to create pipe for init wait"); + + if (fcntl(pfd[0], F_SETFD, FD_CLOEXEC) < 0 || + fcntl(pfd[1], F_SETFD, FD_CLOEXEC) < 0) + fatal_e(-errno, "failed to set CLOEXEC on init wait pipe"); + + pid = fork(); + if (pid < 0) + fatal_e(-errno, "failed to fork for daemon"); + + if (pid == 0) { + close(pfd[0]); + init_wait_fd = pfd[1]; + + /* be evil, my child */ + chdir("/"); + setsid(); + return; + } + + /* wait for init completion and pass over success indication */ + close(pfd[1]); + + do { + ret = read(pfd[0], &err, sizeof(err)); + } while (ret < 0 && errno == EINTR); + + if (ret == sizeof(err) && err == 0) + exit(0); + + fatal("daemon init failed ret=%zd err=%d", ret, err); + exit(1); +} + +static void ossp_init_done(void *userdata) +{ + /* init complete, notify parent if it's waiting */ + if (init_wait_fd >= 0) { + ssize_t ret; + int err = 0; + + ret = write(init_wait_fd, &err, sizeof(err)); + if (ret != sizeof(err)) + fatal_e(-errno, "failed to notify init completion, " + "ret=%zd", ret); + close(init_wait_fd); + init_wait_fd = -1; + } +} + +static const struct cuse_lowlevel_ops mixer_ops = { + .open = mixer_open, + .release = mixer_release, + .ioctl = mixer_ioctl, +}; + +static const struct cuse_lowlevel_ops dsp_ops = { + .init_done = ossp_init_done, + .open = dsp_open, + .release = dsp_release, + .read = dsp_read, + .write = dsp_write, + .poll = dsp_poll, + .ioctl = dsp_ioctl, +#ifdef OSSP_MMAP + .mmap = dsp_mmap, + .munmap = dsp_munmap, +#endif +}; + +static const struct cuse_lowlevel_ops adsp_ops = { + .open = adsp_open, + .release = dsp_release, + .read = dsp_read, + .write = dsp_write, + .poll = dsp_poll, + .ioctl = dsp_ioctl, +#ifdef OSSP_MMAP + .mmap = dsp_mmap, + .munmap = dsp_munmap, +#endif +}; + +static const char *usage = +"usage: osspd [options]\n" +"\n" +"options:\n" +" --help print this help message\n" +" --dsp=NAME DSP device name (default dsp)\n" +" --dsp-maj=MAJ DSP device major number (default 14)\n" +" --dsp-min=MIN DSP device minor number (default 3)\n" +" --adsp=NAME Aux DSP device name (default adsp, blank to disable)\n" +" --adsp-maj=MAJ Aux DSP device major number (default 14)\n" +" --adsp-min=MIN Aux DSP device minor number (default 12)\n" +" --mixer=NAME mixer device name (default mixer, blank to disable)\n" +" --mixer-maj=MAJ mixer device major number (default 14)\n" +" --mixer-min=MIN mixer device minor number (default 0)\n" +" --max=MAX maximum number of open streams (default 256)\n" +" --umax=MAX maximum number of open streams per UID (default --max)\n" +" --exit-on-idle exit if idle\n" +" --dsp-slave=PATH DSP slave (default ossp-padsp in the same dir)\n" +" --log=LEVEL log level (0..6)\n" +" --timestamp timestamp log messages\n" +" -v increase verbosity, can be specified multiple times\n" +" -f Run in foreground (don't daemonize)\n" +"\n"; + +struct ossp_param { + char *dsp_name; + unsigned dsp_major; + unsigned dsp_minor; + char *adsp_name; + unsigned adsp_major; + unsigned adsp_minor; + char *mixer_name; + unsigned mixer_major; + unsigned mixer_minor; + unsigned max_streams; + unsigned umax_streams; + char *dsp_slave_path; + unsigned log_level; + int exit_on_idle; + int timestamp; + int fg; + int help; +}; + +#define OSSP_OPT(t, p) { t, offsetof(struct ossp_param, p), 1 } + +static const struct fuse_opt ossp_opts[] = { + OSSP_OPT("--dsp=%s", dsp_name), + OSSP_OPT("--dsp-maj=%u", dsp_major), + OSSP_OPT("--dsp-min=%u", dsp_minor), + OSSP_OPT("--adsp=%s", adsp_name), + OSSP_OPT("--adsp-maj=%u", adsp_major), + OSSP_OPT("--adsp-min=%u", adsp_minor), + OSSP_OPT("--mixer=%s", mixer_name), + OSSP_OPT("--mixer-maj=%u", mixer_major), + OSSP_OPT("--mixer-min=%u", mixer_minor), + OSSP_OPT("--max=%u", max_streams), + OSSP_OPT("--umax=%u", umax_streams), + OSSP_OPT("--exit-on-idle", exit_on_idle), + OSSP_OPT("--dsp-slave=%s", dsp_slave_path), + OSSP_OPT("--timestamp", timestamp), + OSSP_OPT("--log=%u", log_level), + OSSP_OPT("-f", fg), + FUSE_OPT_KEY("-h", 0), + FUSE_OPT_KEY("--help", 0), + FUSE_OPT_KEY("-v", 1), + FUSE_OPT_END +}; + +static struct fuse_session *setup_ossp_cuse(const struct cuse_lowlevel_ops *ops, + const char *name, int major, + int minor, int argc, char **argv) +{ + char name_buf[128]; + const char *bufp = name_buf; + struct cuse_info ci = { .dev_major = major, .dev_minor = minor, + .dev_info_argc = 1, .dev_info_argv = &bufp, + .flags = CUSE_UNRESTRICTED_IOCTL }; + struct fuse_session *se; + int fd; + + snprintf(name_buf, sizeof(name_buf), "DEVNAME=%s", name); + + se = cuse_lowlevel_setup(argc, argv, &ci, ops, NULL, NULL); + if (!se) { + err("failed to setup %s CUSE", name); + return NULL; + } + + fd = fuse_chan_fd(fuse_session_next_chan(se, NULL)); + if ( +#ifdef OSSP_MMAP + fd != fuse_mmap_fd(se) && +#endif + fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { + err_e(-errno, "failed to set CLOEXEC on %s CUSE fd", name); + cuse_lowlevel_teardown(se); + return NULL; + } + + return se; +} + +static void *cuse_worker(void *arg) +{ + struct fuse_session *se = arg; + int rc; + + rc = fuse_session_loop_mt(se); + cuse_lowlevel_teardown(se); + + return (void *)(unsigned long)rc; +} + +static int process_arg(void *data, const char *arg, int key, + struct fuse_args *outargs) +{ + struct ossp_param *param = data; + + switch (key) { + case 0: + fprintf(stderr, usage); + param->help = 1; + return 0; + case 1: + param->log_level++; + return 0; + } + return 1; +} + +int main(int argc, char **argv) +{ + static struct ossp_param param = { + .dsp_name = DFL_DSP_NAME, + .dsp_major = DFL_DSP_MAJOR, .dsp_minor = DFL_DSP_MINOR, + .adsp_name = DFL_ADSP_NAME, + .adsp_major = DFL_ADSP_MAJOR, .adsp_minor = DFL_ADSP_MINOR, + .mixer_name = DFL_MIXER_NAME, + .mixer_major = DFL_MIXER_MAJOR, .mixer_minor = DFL_MIXER_MINOR, + .max_streams = DFL_MAX_STREAMS, + }; + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + char path_buf[PATH_MAX], *dir; + char adsp_buf[64] = "", mixer_buf[64] = ""; + struct sigaction sa; + struct stat stat_buf; + ssize_t ret; + unsigned u; + + snprintf(ossp_log_name, sizeof(ossp_log_name), "osspd"); + param.log_level = ossp_log_level; + + if (fuse_opt_parse(&args, ¶m, ossp_opts, process_arg)) + fatal("failed to parse arguments"); + + if (param.help) + return 0; + + max_streams = param.max_streams; + hashtbl_size = max_streams / 2 + 13; + + umax_streams = max_streams; + if (param.umax_streams) + umax_streams = param.umax_streams; + if (param.log_level > OSSP_LOG_MAX) + param.log_level = OSSP_LOG_MAX; + if (!param.fg) + param.log_level = -param.log_level; + ossp_log_level = param.log_level; + ossp_log_timestamp = param.timestamp; + + if (!param.fg) + ossp_daemonize(); + + /* daemonization already handled, prevent forking inside FUSE */ + fuse_opt_add_arg(&args, "-f"); + + info("OSS Proxy v%s (C) 2008-2010 by Tejun Heo ", + OSSP_VERSION); + + /* ignore stupid SIGPIPEs */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + if (sigaction(SIGPIPE, &sa, NULL)) + fatal_e(-errno, "failed to ignore SIGPIPE"); + +//#ifdef GIOVANNI + /* determine slave path and check for availability */ + ret = readlink("/proc/self/exe", path_buf, PATH_MAX - 1); + if (ret < 0) + fatal_e(-errno, "failed to determine executable path"); + path_buf[ret] = '\0'; + dir = dirname(path_buf); + + if (param.dsp_slave_path) { + strncpy(dsp_slave_path, param.dsp_slave_path, PATH_MAX - 1); + dsp_slave_path[PATH_MAX - 1] = '\0'; + } else { + ret = snprintf(dsp_slave_path, PATH_MAX, "%s/%s", + dir, "ossp-padsp"); + if (ret >= PATH_MAX) + fatal("dsp slave pathname too long"); + } + + if (stat(dsp_slave_path, &stat_buf)) + fatal_e(-errno, "failed to stat %s", dsp_slave_path); + if (!S_ISREG(stat_buf.st_mode) || !(stat_buf.st_mode & 0444)) + fatal("%s is not executable", dsp_slave_path); + +//#endif// GIOVANNI + /* allocate tables */ + os_id_bitmap = calloc(BITS_TO_LONGS(max_streams), sizeof(long)); + mixer_tbl = calloc(hashtbl_size, sizeof(mixer_tbl[0])); + os_tbl = calloc(hashtbl_size, sizeof(os_tbl[0])); + os_pgrp_tbl = calloc(hashtbl_size, sizeof(os_pgrp_tbl[0])); + os_notify_tbl = calloc(hashtbl_size, sizeof(os_notify_tbl[0])); + if (!os_id_bitmap || !mixer_tbl || !os_tbl || !os_pgrp_tbl || + !os_notify_tbl) + fatal("failed to allocate stream hash tables"); + for (u = 0; u < hashtbl_size; u++) { + INIT_LIST_HEAD(&mixer_tbl[u]); + INIT_LIST_HEAD(&os_tbl[u]); + INIT_LIST_HEAD(&os_pgrp_tbl[u]); + INIT_LIST_HEAD(&os_notify_tbl[u]); + } + __set_bit(0, os_id_bitmap); /* don't use id 0 */ + + /* create mixer delayed reference worker */ + ret = -pthread_create(&mixer_delayed_put_thread, NULL, + mixer_delayed_put_worker, NULL); + if (ret) + fatal_e(ret, "failed to create mixer delayed put worker"); + + /* if exit_on_idle, touch mixer for pgrp0 */ + exit_on_idle = param.exit_on_idle; + if (exit_on_idle) { + struct ossp_mixer *mixer; + + mixer = get_mixer(0); + if (!mixer) + fatal("failed to touch idle mixer"); + put_mixer(mixer); + } + + /* create notify epoll and kick off watcher thread */ + notify_epfd = epoll_create(max_streams); + if (notify_epfd < 0) + fatal_e(-errno, "failed to create notify epoll"); + if (fcntl(notify_epfd, F_SETFD, FD_CLOEXEC) < 0) + fatal_e(-errno, "failed to set CLOEXEC on notify epfd"); + + ret = -pthread_create(¬ify_poller_thread, NULL, notify_poller, NULL); + if (ret) + fatal_e(ret, "failed to create notify poller thread"); + + /* create reaper for slave corpses */ + ret = -pthread_create(&slave_reaper_thread, NULL, slave_reaper, NULL); + if (ret) + fatal_e(ret, "failed to create slave reaper thread"); + +#ifdef GIOVANNI + /* we're set, let's setup fuse structures */ + if (strlen(param.mixer_name)) + mixer_se = setup_ossp_cuse(&mixer_ops, param.mixer_name, + param.mixer_major, param.mixer_minor, + args.argc, args.argv); + if (strlen(param.adsp_name)) + adsp_se = setup_ossp_cuse(&dsp_ops, param.adsp_name, + param.adsp_major, param.adsp_minor, + args.argc, args.argv); + +#endif// GIOVANNI + dsp_se = setup_ossp_cuse(&dsp_ops, param.dsp_name, + param.dsp_major, param.dsp_minor, + args.argc, args.argv); + if (!dsp_se) + fatal("can't create dsp, giving up"); + +#ifdef GIOVANNI + if (mixer_se) + snprintf(mixer_buf, sizeof(mixer_buf), ", %s (%d:%d)", + param.mixer_name, param.mixer_major, param.mixer_minor); + if (adsp_se) + snprintf(adsp_buf, sizeof(adsp_buf), ", %s (%d:%d)", + param.adsp_name, param.adsp_major, param.adsp_minor); + +#endif// GIOVANNI + info("Creating %s (%d:%d)%s%s", param.dsp_name, param.dsp_major, + param.dsp_minor, adsp_buf, mixer_buf); + +#ifdef GIOVANNI + /* start threads for mixer and adsp */ + if (mixer_se) { + ret = -pthread_create(&cuse_mixer_thread, NULL, + cuse_worker, mixer_se); + if (ret) + err_e(ret, "failed to create mixer worker"); + } + if (adsp_se) { + ret = -pthread_create(&cuse_adsp_thread, NULL, + cuse_worker, adsp_se); + if (ret) + err_e(ret, "failed to create adsp worker"); + } +#endif// GIOVANNI + + /* run CUSE for /dev/dsp in the main thread */ + ret = (ssize_t)cuse_worker(dsp_se); + if (ret < 0) + fatal("dsp worker failed"); + return 0; +} From 86657a6c0aefb1cb52f47c77aae38415bc584dfe Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 10:42:37 -0500 Subject: [PATCH 49/97] freetdm: ftmod_r2 - process all state changes before moving to openr2 events or going back to sleep --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 06d1abdc04..84ddea586c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -152,6 +152,7 @@ static ftdm_hash_t *g_mod_data_hash; static ftdm_io_interface_t g_ftdm_r2_interface; static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); +static int ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); /* functions not available on windows */ @@ -529,7 +530,7 @@ static void ftdm_r2_on_call_end(openr2_chan_t *r2chan) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); /* in some circumstances openr2 can call on_call_init right after this, so let's advance the state right here */ - ftdm_r2_state_advance(ftdmchan); + ftdm_r2_state_advance_all(ftdmchan); } static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen) @@ -1347,6 +1348,20 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) return ret; } +/* the channel must be locked when calling this function */ +static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan) +{ + /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept + * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this + * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting + * to complete (the processing is media-bound) + * */ + while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) + && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) { + ftdm_r2_state_advance(ftdmchan); + } +} + static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) { openr2_chan_t *r2chan; @@ -1431,9 +1446,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) r2call = R2CALL(ftdmchan); ftdm_mutex_lock(ftdmchan->mutex); - ftdm_r2_state_advance(ftdmchan); + ftdm_r2_state_advance_all(ftdmchan); openr2_chan_process_signaling(r2chan); - ftdm_r2_state_advance(ftdmchan); + ftdm_r2_state_advance_all(ftdmchan); ftdm_mutex_unlock(ftdmchan->mutex); } ftdm_span_trigger_signals(span); From ef8682507650792e6a3c38b9a5612526ab0b1ecb Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 13:49:34 -0200 Subject: [PATCH 50/97] freetdm: ftmod_r2 - fixed ftdm_r2_state_advance_all() definition --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 84ddea586c..8514569509 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -152,7 +152,7 @@ static ftdm_hash_t *g_mod_data_hash; static ftdm_io_interface_t g_ftdm_r2_interface; static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); -static int ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); +static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); /* functions not available on windows */ From 80031c3e17d78c50d533644bd4bbbbbc181d6252 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 14:51:09 -0200 Subject: [PATCH 51/97] freetdm: ftmod_r2 - added percentage to loop timing stats --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 8514569509..513adfd975 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1642,6 +1642,7 @@ static FIO_API_FUNCTION(ftdm_r2_api) if (!strcasecmp(argv[0], "loopstats")) { int range; + float pct; span_id = atoi(argv[1]); if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { @@ -1655,10 +1656,11 @@ static FIO_API_FUNCTION(ftdm_r2_api) } range = 0; for (i = 0; i < ftdm_array_len(r2data->loops); i++) { + pct = 100*r2data->loops[i]/r2data->total_loops; if ((i + 1) == ftdm_array_len(r2data->loops)) { - stream->write_function(stream, ">= %dms: %llu\n", range, r2data->loops[i]); + stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->loops[i], pct); } else { - stream->write_function(stream, "%d-%dms: %llu\n", range, range + 9, r2data->loops[i]); + stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 9, r2data->loops[i], pct); } range += 10; } From 2b126a1510abae4364341d29d49cb31711f2119b Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 15:03:31 -0200 Subject: [PATCH 52/97] freetdm: ftmod_r2 - cast added --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 513adfd975..c8d669ca5c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1656,7 +1656,7 @@ static FIO_API_FUNCTION(ftdm_r2_api) } range = 0; for (i = 0; i < ftdm_array_len(r2data->loops); i++) { - pct = 100*r2data->loops[i]/r2data->total_loops; + pct = 100*(float)r2data->loops[i]/r2data->total_loops; if ((i + 1) == ftdm_array_len(r2data->loops)) { stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->loops[i], pct); } else { From 894dea2803a66ad933899b4377a9154ee3f16394 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 12:39:30 -0500 Subject: [PATCH 53/97] freetdm: ftmod_wanpipe - flush stats when opening a channel --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c55d42e8b0..98da73ec92 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -516,6 +516,7 @@ static FIO_OPEN_FUNCTION(wanpipe_open) memset(&tdm_api,0,sizeof(tdm_api)); sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); + sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; From 546a2961cb5fa1cf056b682c1a4553381d9ec75a Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 26 Nov 2010 12:59:36 -0500 Subject: [PATCH 54/97] Added channel-restart-on-link-up option --- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 1 + .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c | 10 ++++++++++ .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c | 11 ++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 2a65a82985..36b5662faf 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -183,6 +183,7 @@ typedef struct sngisdn_span_data { int8_t facility_timeout; uint8_t num_local_numbers; uint8_t timer_t3; + uint8_t restart_opt; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; ftdm_sched_t *sched; ftdm_queue_t *event_queue; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 18ca9c38dd..a869bda48d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -182,6 +182,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; signal_data->timer_t3 = 8; + signal_data->restart_opt = SNGISDN_OPT_DEFAULT; signal_data->link_id = span->span_id; span->default_caller_data.bearer_capability = IN_ITC_SPEECH; @@ -271,6 +272,15 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); } else if (!strcasecmp(var, "outbound-bearer_layer1")) { ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); + } else if (!strcasecmp(var, "channel-restart-on-link-up")) { + if (!strcasecmp(val, "yes")) { + signal_data->restart_opt = SNGISDN_OPT_TRUE; + } else if (!strcasecmp(val, "no")) { + signal_data->restart_opt = SNGISDN_OPT_FALSE; + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); + } + } else if (!strcasecmp(var, "local-number")) { if (add_local_number(val, span) != FTDM_SUCCESS) { return FTDM_FAIL; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index bb46fb7fba..94683d8a4b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -701,7 +701,16 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span) cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE; cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; } - + + /* Override the restart options if user selected that option */ + if (signal_data->restart_opt != SNGISDN_OPT_DEFAULT) { + if (signal_data->restart_opt == SNGISDN_OPT_TRUE) { + cfg.t.cfg.s.inDLSAP.rstOpt = TRUE; + } else { + cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; + } + } + for (i = 0; i < IN_MAXBCHNL; i++) { cfg.t.cfg.s.inDLSAP.bProf[i].profNmb = 0; From 17fc3bd62b640196825f3002732affaa9b22da85 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 14:03:16 -0500 Subject: [PATCH 55/97] freetdm: ftmod_wanpipe, ftmod_sangoma_isdn and and core - Updated stats code --- .../ftmod_sangoma_isdn_stack_out.c | 14 +-- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 86 ++++++++++++------- libs/freetdm/src/include/private/ftdm_core.h | 38 ++++---- 3 files changed, 81 insertions(+), 57 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 2853335efc..b58bef23e5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -600,32 +600,32 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) memcpy(&l1_frame.data, data, len); - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) { l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) { l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) { l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 98da73ec92..b97b75cdfc 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -515,8 +515,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open) wanpipe_tdm_api_t tdm_api; memset(&tdm_api,0,sizeof(tdm_api)); + sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; @@ -753,6 +755,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) case FTDM_COMMAND_FLUSH_IOSTATS: { err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); } break; case FTDM_COMMAND_SET_RX_QUEUE_SIZE: @@ -782,42 +785,67 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) { - ftdmchan->iostats.stats.rx.flags = 0; - - ftdmchan->iostats.stats.rx.errors = rx_stats->wp_api_rx_hdr_errors; - ftdmchan->iostats.stats.rx.rx_queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; - ftdmchan->iostats.stats.rx.rx_queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; + ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors; + ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; + ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= (0.8*ftdmchan->iostats.stats.rx.rx_queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } + + if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + /* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= ftdmchan->iostats.stats.rx.rx_queue_size) { + if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } - return; + + if (!ftdmchan->iostats.rx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + } + + ftdmchan->iostats.rx.packets++; } /** diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 06f899c8c9..5c235ad4ea 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -368,30 +368,26 @@ typedef struct { } ftdm_channel_history_entry_t; typedef enum { - FTDM_IOSTATS_ERROR_CRC = (1<<0), - FTDM_IOSTATS_ERROR_FRAME = (1<<1), - FTDM_IOSTATS_ERROR_ABORT = (1<<2), - FTDM_IOSTATS_ERROR_FIFO = (1<<3), - FTDM_IOSTATS_ERROR_DMA = (1<<4), - FTDM_IOSTATS_ERROR_QUEUE_THRES = (1<<5), /* Queue reached high threshold */ - FTDM_IOSTATS_ERROR_QUEUE_FULL = (1<<6), /* Queue is full */ + FTDM_IOSTATS_ERROR_CRC = (1 << 0), + FTDM_IOSTATS_ERROR_FRAME = (1 << 1), + FTDM_IOSTATS_ERROR_ABORT = (1 << 2), + FTDM_IOSTATS_ERROR_FIFO = (1 << 3), + FTDM_IOSTATS_ERROR_DMA = (1 << 4), + FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */ + FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */ } ftdm_iostats_error_type_t; +typedef struct iostats_element { + uint32_t errors; + uint16_t flags; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; +} iostats_element_t; + typedef struct { - union { - struct { - uint32_t errors; - uint16_t flags; - uint8_t rx_queue_size; /* max queue size configured */ - uint8_t rx_queue_len; /* Current number of elements in queue */ - } rx; - struct { - uint32_t errors; - uint16_t flags; - uint8_t tx_queue_size; /* max queue size configured */ - uint8_t tx_queue_len; /* Current number of elements in queue */ - } tx; - } stats; + iostats_element_t rx; + iostats_element_t tx; } ftdm_channel_iostats_t; /* 2^8 table size, one for each byte (sample) value */ From 8fd62850e4ba65a249900c044bdbf057e1117477 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 26 Nov 2010 13:07:57 -0600 Subject: [PATCH 56/97] vs2010 add mod_cepstral to setup build --- Freeswitch.2010.sln | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index 186969891a..4f48314f5b 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -964,7 +964,9 @@ Global {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|Win32.ActiveCfg = Release|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64 Setup.ActiveCfg = Release|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64 Setup.Build.0 = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x86 Setup.ActiveCfg = Release|Win32 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x86 Setup.Build.0 = Release|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|Win32.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64.Build.0 = Release|x64 From d53db202435868cfac98ed0ce6fe537d84a4947d Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 15:06:36 -0500 Subject: [PATCH 57/97] freetdm: ftmod_wanpipe - add tx stats --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 44 +++++++++++++++++++ libs/freetdm/src/include/private/ftdm_core.h | 26 ++++++----- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index b97b75cdfc..804c6cfe8f 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -783,6 +783,47 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) return FTDM_SUCCESS; } +static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats) +{ + ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors; + ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; + ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; + + if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } + + if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.rx.queue_size) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } + + if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) { + ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets; + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets); + } + + if (!ftdmchan->iostats.tx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n", + ftdmchan->iostats.tx.queue_len, + ftdmchan->iostats.tx.queue_size, + ftdmchan->iostats.tx.idle_packets); + } + + ftdmchan->iostats.tx.packets++; +} + static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) { ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors; @@ -906,6 +947,9 @@ static FIO_WRITE_FUNCTION(wanpipe_write) /* should we be checking if bsent == *datalen here? */ if (bsent > 0) { *datalen = bsent; + if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { + wanpipe_write_stats(ftdmchan, &hdrframe); + } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 5c235ad4ea..7683ec7145 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -377,17 +377,23 @@ typedef enum { FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */ } ftdm_iostats_error_type_t; -typedef struct iostats_element { - uint32_t errors; - uint16_t flags; - uint8_t queue_size; /* max queue size configured */ - uint8_t queue_len; /* Current number of elements in queue */ - uint64_t packets; -} iostats_element_t; - typedef struct { - iostats_element_t rx; - iostats_element_t tx; + struct { + uint32_t errors; + uint16_t flags; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } rx; + + struct { + uint32_t errors; + uint16_t flags; + uint8_t idle_packets; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } tx; } ftdm_channel_iostats_t; /* 2^8 table size, one for each byte (sample) value */ From 0b7a2d4c92501980983bd71365f339a674a86a3c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 15:10:18 -0500 Subject: [PATCH 58/97] freetdm: remove openzap projects --- libs/freetdm/openzap.2005.sln | 82 ---- .../ftmod_analog/ozmod_analog.2005.vcproj | 202 ---------- .../ozmod_analog_em.2005.vcproj | 202 ---------- .../ftmod_wanpipe/ozmod_wanpipe.2005.vcproj | 196 ---------- .../ftmod_wanpipe/wanpipe_tdm_api_iface.h | 351 ------------------ 5 files changed, 1033 deletions(-) delete mode 100644 libs/freetdm/openzap.2005.sln delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h diff --git a/libs/freetdm/openzap.2005.sln b/libs/freetdm/openzap.2005.sln deleted file mode 100644 index c9f666b381..0000000000 --- a/libs/freetdm/openzap.2005.sln +++ /dev/null @@ -1,82 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openzap", "msvc\openzap.2005.vcproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2005.vcproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2005.vcproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_openzap", "mod_openzap\mod_openzap.2005.vcproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog", "src\ozmod\ozmod_analog\ozmod_analog.2005.vcproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog_em", "src\ozmod\ozmod_analog_em\ozmod_analog_em.2005.vcproj", "{C539D7C8-26A8-4A94-B938-77672165C130}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_isdn", "src\ozmod\ozmod_isdn\ozmod_isdn.2005.vcproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_wanpipe", "src\ozmod\ozmod_wanpipe\ozmod_wanpipe.2005.vcproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_pika", "src\ozmod\ozmod_pika\ozmod_pika.2005.vcproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.Build.0 = Debug|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.Build.0 = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.ActiveCfg = Debug|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.Build.0 = Debug|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.ActiveCfg = Release|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.Build.0 = Release|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.Build.0 = Debug|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.Build.0 = Release|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj deleted file mode 100644 index 7a1cf53b20..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj deleted file mode 100644 index 9ecbadc232..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj deleted file mode 100644 index abebf30427..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h b/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h deleted file mode 100644 index 3801ff9c8c..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h +++ /dev/null @@ -1,351 +0,0 @@ -/***************************************************************************** -* wanpipe_tdm_api_iface.h -* -* WANPIPE(tm) AFT TE1 Hardware Support -* -* Authors: Nenad Corbic -* -* Copyright (c) 2007 - 08, Sangoma Technologies -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -* ============================================================================ -* Oct 04, 2005 Nenad Corbic Initial version. -* -* Jul 25, 2006 David Rokhvarg Ported to Windows. -*****************************************************************************/ - -#ifndef __WANPIPE_TDM_API_IFACE_H_ -#define __WANPIPE_TDM_API_IFACE_H_ - - -#if defined(__WINDOWS__) -typedef HANDLE sng_fd_t; -#else -typedef int sng_fd_t; -#endif - -/* Indicate to library that new features exist */ -#define WP_TDM_FEATURE_DTMF_EVENTS 1 -#define WP_TDM_FEATURE_FE_ALARM 1 -#define WP_TDM_FEATURE_EVENTS 1 -#define WP_TDM_FEATURE_LINK_STATUS 1 - -enum wanpipe_tdm_api_cmds { - - SIOC_WP_TDM_GET_USR_MTU_MRU, /* 0x00 */ - - SIOC_WP_TDM_SET_USR_PERIOD, /* 0x01 */ - SIOC_WP_TDM_GET_USR_PERIOD, /* 0x02 */ - - SIOC_WP_TDM_SET_HW_MTU_MRU, /* 0x03 */ - SIOC_WP_TDM_GET_HW_MTU_MRU, /* 0x04 */ - - SIOC_WP_TDM_SET_CODEC, /* 0x05 */ - SIOC_WP_TDM_GET_CODEC, /* 0x06 */ - - SIOC_WP_TDM_SET_POWER_LEVEL, /* 0x07 */ - SIOC_WP_TDM_GET_POWER_LEVEL, /* 0x08 */ - - SIOC_WP_TDM_TOGGLE_RX, /* 0x09 */ - SIOC_WP_TDM_TOGGLE_TX, /* 0x0A */ - - SIOC_WP_TDM_GET_HW_CODING, /* 0x0B */ - SIOC_WP_TDM_SET_HW_CODING, /* 0x0C */ - - SIOC_WP_TDM_GET_FULL_CFG, /* 0x0D */ - - SIOC_WP_TDM_SET_EC_TAP, /* 0x0E */ - SIOC_WP_TDM_GET_EC_TAP, /* 0x0F */ - - SIOC_WP_TDM_ENABLE_RBS_EVENTS, /* 0x10 */ - SIOC_WP_TDM_DISABLE_RBS_EVENTS, /* 0x11 */ - SIOC_WP_TDM_WRITE_RBS_BITS, /* 0x12 */ - - SIOC_WP_TDM_GET_STATS, /* 0x13 */ - SIOC_WP_TDM_FLUSH_BUFFERS, /* 0x14 */ - - SIOC_WP_TDM_READ_EVENT, /* 0x15 */ - - SIOC_WP_TDM_SET_EVENT, /* 0x16 */ - - SIOC_WP_TDM_SET_RX_GAINS, /* 0x17 */ - SIOC_WP_TDM_SET_TX_GAINS, /* 0x18 */ - SIOC_WP_TDM_CLEAR_RX_GAINS, /* 0x19 */ - SIOC_WP_TDM_CLEAR_TX_GAINS, /* 0x1A */ - - SIOC_WP_TDM_GET_FE_ALARMS, /* 0x1B */ - - SIOC_WP_TDM_ENABLE_HWEC, /* 0x1C */ - SIOC_WP_TDM_DISABLE_HWEC, /* 0x1D */ - - SIOC_WP_TDM_SET_FE_STATUS, /* 0x1E */ - SIOC_WP_TDM_GET_FE_STATUS, /* 0x1F */ - - SIOC_WP_TDM_GET_HW_DTMF, /* 0x20 */ - - SIOC_WP_TDM_NOTSUPP /* */ - -}; - -#define SIOC_WP_TDM_GET_LINK_STATUS SIOC_WP_TDM_GET_FE_STATUS - -enum wanpipe_tdm_api_events { - WP_TDMAPI_EVENT_NONE, - WP_TDMAPI_EVENT_RBS, - WP_TDMAPI_EVENT_ALARM, - WP_TDMAPI_EVENT_DTMF, - WP_TDMAPI_EVENT_RM_DTMF, - WP_TDMAPI_EVENT_RXHOOK, - WP_TDMAPI_EVENT_RING, - WP_TDMAPI_EVENT_RING_DETECT, - WP_TDMAPI_EVENT_RING_TRIP_DETECT, - WP_TDMAPI_EVENT_TONE, - WP_TDMAPI_EVENT_TXSIG_KEWL, - WP_TDMAPI_EVENT_TXSIG_START, - WP_TDMAPI_EVENT_TXSIG_OFFHOOK, - WP_TDMAPI_EVENT_TXSIG_ONHOOK, - WP_TDMAPI_EVENT_ONHOOKTRANSFER, - WP_TDMAPI_EVENT_SETPOLARITY, - WP_TDMAPI_EVENT_BRI_CHAN_LOOPBACK, - WP_TDMAPI_EVENT_LINK_STATUS -}; - -#define WP_TDMAPI_EVENT_FE_ALARM WP_TDMAPI_EVENT_ALARM - - -#define WP_TDMAPI_EVENT_ENABLE 0x01 -#define WP_TDMAPI_EVENT_DISABLE 0x02 -#define WP_TDMAPI_EVENT_MODE_DECODE(mode) \ - ((mode) == WP_TDMAPI_EVENT_ENABLE) ? "Enable" : \ - ((mode) == WP_TDMAPI_EVENT_DISABLE) ? "Disable" : \ - "(Unknown mode)" - -#define WPTDM_A_BIT WAN_RBS_SIG_A -#define WPTDM_B_BIT WAN_RBS_SIG_B -#define WPTDM_C_BIT WAN_RBS_SIG_C -#define WPTDM_D_BIT WAN_RBS_SIG_D - -#define WP_TDMAPI_EVENT_RXHOOK_OFF 0x01 -#define WP_TDMAPI_EVENT_RXHOOK_ON 0x02 -#define WP_TDMAPI_EVENT_RXHOOK_DECODE(state) \ - ((state) == WP_TDMAPI_EVENT_RXHOOK_OFF) ? "Off-hook" : \ - ((state) == WP_TDMAPI_EVENT_RXHOOK_ON) ? "On-hook" : \ - "(Unknown state)" - -#define WP_TDMAPI_EVENT_RING_PRESENT 0x01 -#define WP_TDMAPI_EVENT_RING_STOP 0x02 -#define WP_TDMAPI_EVENT_RING_DECODE(state) \ - ((state) == WP_TDMAPI_EVENT_RING_PRESENT) ? "Ring Present" : \ - ((state) == WP_TDMAPI_EVENT_RING_STOP) ? "Ring Stop" : \ - "(Unknown state)" - -#define WP_TDMAPI_EVENT_RING_TRIP_PRESENT 0x01 -#define WP_TDMAPI_EVENT_RING_TRIP_STOP 0x02 -#define WP_TDMAPI_EVENT_RING_TRIP_DECODE(state) \ - ((state) == WP_TDMAPI_EVENT_RING_TRIP_PRESENT) ? "Ring Present" : \ - ((state) == WP_TDMAPI_EVENT_RING_TRIP_STOP) ? "Ring Stop" : \ - "(Unknown state)" -/*Link Status */ -#define WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED 0x01 -#define WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED 0x02 -#define WP_TDMAPI_EVENT_LINK_STATUS_DECODE(status) \ - ((status) == WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED) ? "Connected" : \ - ((status) == WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED) ? "Disconnected" : \ - "Unknown" -#define WP_TDMAPI_EVENT_TONE_DIAL 0x01 -#define WP_TDMAPI_EVENT_TONE_BUSY 0x02 -#define WP_TDMAPI_EVENT_TONE_RING 0x03 -#define WP_TDMAPI_EVENT_TONE_CONGESTION 0x04 - -/* BRI channels list */ -#define WAN_BRI_BCHAN1 0x01 -#define WAN_BRI_BCHAN2 0x02 -#define WAN_BRI_DCHAN 0x03 - - -typedef struct { - - u_int8_t type; - u_int8_t mode; - u_int32_t time_stamp; - u_int8_t channel; - u_int32_t chan_map; - u_int8_t span; - union { - struct { - u_int8_t alarm; - } te1_alarm; - struct { - u_int8_t rbs_bits; - } te1_rbs; - struct { - u_int8_t state; - u_int8_t sig; - } rm_hook; - struct { - u_int8_t state; - } rm_ring; - struct { - u_int8_t type; - } rm_tone; - struct { - u_int8_t digit; /* DTMF: digit */ - u_int8_t port; /* DTMF: SOUT/ROUT */ - u_int8_t type; /* DTMF: PRESET/STOP */ - } dtmf; - struct { - u_int16_t polarity; - u_int16_t ohttimer; - } rm_common; - struct{ - u_int16_t status; - } linkstatus; - } wp_tdm_api_event_u; -#define wp_tdm_api_event_type type -#define wp_tdm_api_event_mode mode -#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm -#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm -#define wp_tdm_api_event_rbs_bits wp_tdm_api_event_u.te1_rbs.rbs_bits -#define wp_tdm_api_event_hook_state wp_tdm_api_event_u.rm_hook.state -#define wp_tdm_api_event_hook_sig wp_tdm_api_event_u.rm_hook.sig -#define wp_tdm_api_event_ring_state wp_tdm_api_event_u.rm_ring.state -#define wp_tdm_api_event_tone_type wp_tdm_api_event_u.rm_tone.type -#define wp_tdm_api_event_dtmf_digit wp_tdm_api_event_u.dtmf.digit -#define wp_tdm_api_event_dtmf_type wp_tdm_api_event_u.dtmf.type -#define wp_tdm_api_event_dtmf_port wp_tdm_api_event_u.dtmf.port -#define wp_tdm_api_event_ohttimer wp_tdm_api_event_u.rm_common.ohttimer -#define wp_tdm_api_event_polarity wp_tdm_api_event_u.rm_common.polarity -#define wp_tdm_api_event_link_status wp_tdm_api_event_u.linkstatus.status -} wp_tdm_api_event_t; - -typedef struct { - union { - unsigned char reserved[16]; - }wp_rx_hdr_u; -} wp_tdm_api_rx_hdr_t; - -typedef struct { - wp_tdm_api_rx_hdr_t hdr; - unsigned char data[1]; -} wp_tdm_api_rx_element_t; - -typedef struct { - union { - struct { - unsigned char _rbs_rx_bits; - unsigned int _time_stamp; - }wp_tx; - unsigned char reserved[16]; - }wp_tx_hdr_u; -#define wp_api_time_stamp wp_tx_hdr_u.wp_tx._time_stamp -} wp_tdm_api_tx_hdr_t; - -typedef struct { - wp_tdm_api_tx_hdr_t hdr; - unsigned char data[1]; -} wp_tdm_api_tx_element_t; - - - -typedef struct wp_tdm_chan_stats -{ - unsigned int rx_packets; /* total packets received */ - unsigned int tx_packets; /* total packets transmitted */ - unsigned int rx_bytes; /* total bytes received */ - unsigned int tx_bytes; /* total bytes transmitted */ - unsigned int rx_errors; /* bad packets received */ - unsigned int tx_errors; /* packet transmit problems */ - unsigned int rx_dropped; /* no space in linux buffers */ - unsigned int tx_dropped; /* no space available in linux */ - unsigned int multicast; /* multicast packets received */ -#if !defined(__WINDOWS__) - unsigned int collisions; -#endif - /* detailed rx_errors: */ - unsigned int rx_length_errors; - unsigned int rx_over_errors; /* receiver ring buff overflow */ - unsigned int rx_crc_errors; /* recved pkt with crc error */ - unsigned int rx_frame_errors; /* recv'd frame alignment error */ -#if !defined(__WINDOWS__) - unsigned int rx_fifo_errors; /* recv'r fifo overrun */ -#endif - unsigned int rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ -#if !defined(__WINDOWS__) - unsigned int tx_aborted_errors; - unsigned int tx_carrier_errors; -#endif - unsigned int tx_fifo_errors; - unsigned int tx_heartbeat_errors; - unsigned int tx_window_errors; - -}wp_tdm_chan_stats_t; - - - -typedef struct wanpipe_tdm_api_cmd{ - unsigned int cmd; - unsigned int hw_tdm_coding; /* Set/Get HW TDM coding: uLaw muLaw */ - unsigned int hw_mtu_mru; /* Set/Get HW TDM MTU/MRU */ - unsigned int usr_period; /* Set/Get User Period in ms */ - unsigned int tdm_codec; /* Set/Get TDM Codec: SLinear */ - unsigned int power_level; /* Set/Get Power level treshold */ - unsigned int rx_disable; /* Enable/Disable Rx */ - unsigned int tx_disable; /* Enable/Disable Tx */ - unsigned int usr_mtu_mru; /* Set/Get User TDM MTU/MRU */ - unsigned int ec_tap; /* Echo Cancellation Tap */ - unsigned int rbs_poll; /* Enable/Disable RBS Polling */ - unsigned int rbs_rx_bits; /* Rx RBS Bits */ - unsigned int rbs_tx_bits; /* Tx RBS Bits */ - unsigned int hdlc; /* HDLC based device */ - unsigned int idle_flag; /* IDLE flag to Tx */ - unsigned int fe_alarms; /* FE Alarms detected */ - wp_tdm_chan_stats_t stats; /* TDM Statistics */ - /* Do NOT add anything above this! Important for binary backward compatibility. */ - wp_tdm_api_event_t event; /* TDM Event */ - unsigned int data_len; - void *data; - unsigned char fe_status; /* FE status - Connected or Disconnected */ - unsigned int hw_dtmf; /* HW DTMF enabled */ -}wanpipe_tdm_api_cmd_t; - -typedef struct wanpipe_tdm_api_event{ - int (*wp_rbs_event)(sng_fd_t fd, unsigned char rbs_bits); - int (*wp_dtmf_event)(sng_fd_t fd, unsigned char dtmf, unsigned char type, unsigned char port); - int (*wp_rxhook_event)(sng_fd_t fd, unsigned char hook_state); - int (*wp_ring_detect_event)(sng_fd_t fd, unsigned char ring_state); - int (*wp_ring_trip_detect_event)(sng_fd_t fd, unsigned char ring_state); - int (*wp_fe_alarm_event)(sng_fd_t fd, unsigned char fe_alarm_event); - int (*wp_link_status_event)(sng_fd_t fd, unsigned char link_status_event); -}wanpipe_tdm_api_event_t; - -typedef struct wanpipe_tdm_api{ - wanpipe_tdm_api_cmd_t wp_tdm_cmd; - wanpipe_tdm_api_event_t wp_tdm_event; -}wanpipe_tdm_api_t; - - -#endif From 7a7a387f551a8b2a52a64dd3590f73e29ee5112e Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 15:49:18 -0500 Subject: [PATCH 59/97] freetdm: improve IO stats (cherry picked from R2 branch) --- .../ftmod_sangoma_isdn_stack_out.c | 14 +- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 131 ++++++++++++++---- libs/freetdm/src/include/private/ftdm_core.h | 44 +++--- 3 files changed, 132 insertions(+), 57 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 1b906a2004..62d6d023b8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -655,32 +655,32 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) memcpy(&l1_frame.data, data, len); - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) { l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) { l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) { l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c13455dd21..c20ad82a3b 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -513,7 +513,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open) wanpipe_tdm_api_t tdm_api; memset(&tdm_api,0,sizeof(tdm_api)); + sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); + sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; @@ -750,6 +753,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) case FTDM_COMMAND_FLUSH_IOSTATS: { err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); } break; case FTDM_COMMAND_SET_RX_QUEUE_SIZE: @@ -777,44 +781,110 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) return FTDM_SUCCESS; } +static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats) +{ + ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors; + ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; + ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; + + if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } + + if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.rx.queue_size) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } + + if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) { + ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets; + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets); + } + + if (!ftdmchan->iostats.tx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n", + ftdmchan->iostats.tx.queue_len, + ftdmchan->iostats.tx.queue_size, + ftdmchan->iostats.tx.idle_packets); + } + + ftdmchan->iostats.tx.packets++; +} + static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) { - ftdmchan->iostats.stats.rx.flags = 0; - - ftdmchan->iostats.stats.rx.errors = rx_stats->wp_api_rx_hdr_errors; - ftdmchan->iostats.stats.rx.rx_queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; - ftdmchan->iostats.stats.rx.rx_queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; + ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors; + ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; + ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= (0.8*ftdmchan->iostats.stats.rx.rx_queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } + + if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + /* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= ftdmchan->iostats.stats.rx.rx_queue_size) { + if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } - return; + + if (!ftdmchan->iostats.rx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + } + + ftdmchan->iostats.rx.packets++; } /** @@ -875,6 +945,9 @@ static FIO_WRITE_FUNCTION(wanpipe_write) /* should we be checking if bsent == *datalen here? */ if (bsent > 0) { *datalen = bsent; + if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { + wanpipe_write_stats(ftdmchan, &hdrframe); + } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 06f899c8c9..7683ec7145 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -368,30 +368,32 @@ typedef struct { } ftdm_channel_history_entry_t; typedef enum { - FTDM_IOSTATS_ERROR_CRC = (1<<0), - FTDM_IOSTATS_ERROR_FRAME = (1<<1), - FTDM_IOSTATS_ERROR_ABORT = (1<<2), - FTDM_IOSTATS_ERROR_FIFO = (1<<3), - FTDM_IOSTATS_ERROR_DMA = (1<<4), - FTDM_IOSTATS_ERROR_QUEUE_THRES = (1<<5), /* Queue reached high threshold */ - FTDM_IOSTATS_ERROR_QUEUE_FULL = (1<<6), /* Queue is full */ + FTDM_IOSTATS_ERROR_CRC = (1 << 0), + FTDM_IOSTATS_ERROR_FRAME = (1 << 1), + FTDM_IOSTATS_ERROR_ABORT = (1 << 2), + FTDM_IOSTATS_ERROR_FIFO = (1 << 3), + FTDM_IOSTATS_ERROR_DMA = (1 << 4), + FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */ + FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */ } ftdm_iostats_error_type_t; typedef struct { - union { - struct { - uint32_t errors; - uint16_t flags; - uint8_t rx_queue_size; /* max queue size configured */ - uint8_t rx_queue_len; /* Current number of elements in queue */ - } rx; - struct { - uint32_t errors; - uint16_t flags; - uint8_t tx_queue_size; /* max queue size configured */ - uint8_t tx_queue_len; /* Current number of elements in queue */ - } tx; - } stats; + struct { + uint32_t errors; + uint16_t flags; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } rx; + + struct { + uint32_t errors; + uint16_t flags; + uint8_t idle_packets; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } tx; } ftdm_channel_iostats_t; /* 2^8 table size, one for each byte (sample) value */ From f7279386e423d7f525211f9f929242ca1e4baf1b Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 22:10:33 -0200 Subject: [PATCH 60/97] freetdm: ftmod_r2 - replaced deprecated ftdm_r2_configure_span() by ftdm_r2_configure_span_signaling(), all r2 default params now stays on ftmod_r2 --- libs/freetdm/mod_freetdm/mod_freetdm.c | 94 ++-------------- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 122 ++++++++++++--------- 2 files changed, 80 insertions(+), 136 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 8d961123cb..18c1d4aebe 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3212,29 +3212,6 @@ static switch_status_t load_config(void) char *name = (char *) switch_xml_attr(myspan, "name"); ftdm_status_t zstatus = FTDM_FAIL; - /* strings */ - const char *variant = "itu"; - const char *category = "national_subscriber"; - const char *logdir = "/usr/local/freeswitch/log/"; /* FIXME: get PREFIX variable */ - const char *logging = "notice,warning,error"; - const char *advanced_protocol_file = ""; - - /* booleans */ - int call_files = 0; - int get_ani_first = -1; - int immediate_accept = -1; - int double_answer = -1; - int skip_category = -1; - int forced_release = -1; - int charge_calls = -1; - - /* integers */ - int mfback_timeout = -1; - int metering_pulse_timeout = -1; - int allow_collect_calls = -1; - int max_ani = 10; - int max_dnis = 4; - /* common non r2 stuff */ const char *context = "default"; const char *dialplan = "XML"; @@ -3243,53 +3220,16 @@ static switch_status_t load_config(void) uint32_t span_id = 0; ftdm_span_t *span = NULL; + ftdm_conf_parameter_t spanparameters[30]; + unsigned paramindex = 0; + memset(spanparameters, 0, sizeof(spanparameters)); for (param = switch_xml_child(myspan, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); /* string parameters */ - if (!strcasecmp(var, "variant")) { - variant = val; - } else if (!strcasecmp(var, "category")) { - category = val; - } else if (!strcasecmp(var, "logdir")) { - logdir = val; - } else if (!strcasecmp(var, "logging")) { - logging = val; - } else if (!strcasecmp(var, "advanced_protocol_file")) { - advanced_protocol_file = val; - - /* booleans */ - } else if (!strcasecmp(var, "allow_collect_calls")) { - allow_collect_calls = switch_true(val); - } else if (!strcasecmp(var, "immediate_accept")) { - immediate_accept = switch_true(val); - } else if (!strcasecmp(var, "double_answer")) { - double_answer = switch_true(val); - } else if (!strcasecmp(var, "skip_category")) { - skip_category = switch_true(var); - } else if (!strcasecmp(var, "forced_release")) { - forced_release = switch_true(val); - } else if (!strcasecmp(var, "charge_calls")) { - charge_calls = switch_true(val); - } else if (!strcasecmp(var, "get_ani_first")) { - get_ani_first = switch_true(val); - } else if (!strcasecmp(var, "call_files")) { - call_files = switch_true(val); - - /* integers */ - } else if (!strcasecmp(var, "mfback_timeout")) { - mfback_timeout = atoi(val); - } else if (!strcasecmp(var, "metering_pulse_timeout")) { - metering_pulse_timeout = atoi(val); - } else if (!strcasecmp(var, "max_ani")) { - max_ani = atoi(val); - } else if (!strcasecmp(var, "max_dnis")) { - max_dnis = atoi(val); - - /* common non r2 stuff */ - } else if (!strcasecmp(var, "context")) { + if (!strcasecmp(var, "context")) { context = val; } else if (!strcasecmp(var, "dialplan")) { dialplan = val; @@ -3297,11 +3237,15 @@ static switch_status_t load_config(void) dial_regex = val; } else if (!strcasecmp(var, "fail-dial-regex")) { fail_dial_regex = val; + } else { + spanparameters[paramindex].var = var; + spanparameters[paramindex].val = val; + paramindex++; } } if (!id && !name) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "either 'id' or 'name' required params are missing\n"); continue; } @@ -3327,25 +3271,7 @@ static switch_status_t load_config(void) span_id = ftdm_span_get_id(span); } - if (ftdm_configure_span(span, "r2", on_r2_signal, - "variant", variant, - "max_ani", max_ani, - "max_dnis", max_dnis, - "category", category, - "logdir", logdir, - "logging", logging, - "advanced_protocol_file", advanced_protocol_file, - "allow_collect_calls", allow_collect_calls, - "immediate_accept", immediate_accept, - "double_answer", double_answer, - "skip_category", skip_category, - "forced_release", forced_release, - "charge_calls", charge_calls, - "get_ani_first", get_ani_first, - "call_files", call_files, - "mfback_timeout", mfback_timeout, - "metering_pulse_timeout", metering_pulse_timeout, - FTDM_TAG_END) != FTDM_SUCCESS) { + if (ftdm_configure_span_signaling(span, "r2", on_r2_signal, spanparameters) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "Error configuring R2 FreeTDM span %d, error: %s\n", span_id, ftdm_span_get_last_error(span)); continue; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index c8d669ca5c..ffc39e8884 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -892,27 +892,50 @@ static openr2_io_interface_t ftdm_r2_io_iface = { /* .get_oob_event */ ftdm_r2_io_get_oob_event /* never called */ }; -static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) - //ftdm_status_t (ftdm_span_t *span, fio_signal_cb_t sig_cb, va_list ap) +/* resolve a loglevel string, such as "debug,notice,warning", to an openr2 log level integer */ +static openr2_log_level_t ftdm_r2_loglevel_from_string(const char *level) +{ + openr2_log_level_t tmplevel; + openr2_log_level_t newlevel = 0; + char *clevel = NULL; + char *logval = NULL; + + logval = ftdm_malloc(strlen(level)+1); /* alloca man page scared me, so better to use good ol' malloc */ + if (!logval) { + ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", level); + return newlevel; + } + strcpy(logval, level); + while (logval) { + clevel = strsep(&logval, ","); + if (-1 == (tmplevel = openr2_log_get_level(clevel))) { + ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel); + continue; + } + newlevel |= tmplevel; + } + ftdm_safe_free(logval); + return newlevel; +} + +static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) { unsigned int i = 0; int conf_failure = 0; - char *var = NULL; - char *val = NULL; + const char *var = NULL, *val = NULL; + const char *log_level = "notice,warning,error"; /* default loglevel, if none is read from conf */ ftdm_r2_data_t *r2data = NULL; ftdm_r2_span_pvt_t *spanpvt = NULL; ftdm_r2_call_t *r2call = NULL; openr2_chan_t *r2chan = NULL; - openr2_log_level_t tmplevel; - char *clevel = NULL; - char *logval = NULL; + unsigned paramindex = 0; ft_r2_conf_t r2conf = { /* .variant */ OR2_VAR_ITU, /* .category */ OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER, /* .loglevel */ OR2_LOG_ERROR | OR2_LOG_WARNING, - /* .logdir */ NULL, + /* .logdir */ (char *)"/usr/local/freeswitch/log/", /* FIXME: get PREFIX variable */ /* .advanced_protocol_file */ NULL, /* .max_ani */ 10, /* .max_dnis */ 4, @@ -923,7 +946,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) /* .get_ani_first */ -1, /* .call_files */ 0, /* .mf_files */ 0, - /* .double_answer */ 0, + /* .double_answer */ -1, /* .charge_calls */ -1, /* .forced_release */ -1, /* .allow_collect_calls */ -1 @@ -936,10 +959,12 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) return FTDM_FAIL; } - while ((var = va_arg(ap, char *))) { + for (; ftdm_parameters[paramindex].var; paramindex++) { + var = ftdm_parameters[paramindex].var; + val = ftdm_parameters[paramindex].val; ftdm_log(FTDM_LOG_DEBUG, "Reading R2 parameter %s for span %d\n", var, span->span_id); if (!strcasecmp(var, "variant")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { @@ -954,7 +979,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) } ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d for variant %s\n", span->span_id, val); } else if (!strcasecmp(var, "category")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { @@ -969,87 +994,72 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) } ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with default category %s\n", span->span_id, val); } else if (!strcasecmp(var, "logdir")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logdir parameter\n"); continue; } - r2conf.logdir = val; + r2conf.logdir = (char *)val; ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with logdir %s\n", span->span_id, val); } else if (!strcasecmp(var, "logging")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logging parameter\n"); continue; } - logval = ftdm_malloc(strlen(val)+1); /* alloca man page scared me, so better to use good ol' malloc */ - if (!logval) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", val); - continue; - } - strcpy(logval, val); - while (logval) { - clevel = strsep(&logval, ","); - if (-1 == (tmplevel = openr2_log_get_level(clevel))) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel); - continue; - } - r2conf.loglevel |= tmplevel; - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, clevel); - } - ftdm_safe_free(logval); + log_level = val; } else if (!strcasecmp(var, "advanced_protocol_file")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 advanced_protocol_file parameter\n"); continue; } - r2conf.advanced_protocol_file = val; + r2conf.advanced_protocol_file = (char *)val; ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with advanced protocol file %s\n", span->span_id, val); } else if (!strcasecmp(var, "allow_collect_calls")) { - r2conf.allow_collect_calls = va_arg(ap, int); + r2conf.allow_collect_calls = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with allow collect calls max ani = %d\n", span->span_id, r2conf.allow_collect_calls); } else if (!strcasecmp(var, "double_answer")) { - r2conf.double_answer = va_arg(ap, int); + r2conf.double_answer = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with double answer = %d\n", span->span_id, r2conf.double_answer); } else if (!strcasecmp(var, "immediate_accept")) { - r2conf.immediate_accept = va_arg(ap, int); + r2conf.immediate_accept = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with immediate accept = %d\n", span->span_id, r2conf.immediate_accept); } else if (!strcasecmp(var, "skip_category")) { - r2conf.skip_category = va_arg(ap, int); + r2conf.skip_category = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with skip category = %d\n", span->span_id, r2conf.skip_category); } else if (!strcasecmp(var, "forced_release")) { - r2conf.forced_release = va_arg(ap, int); + r2conf.forced_release = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with forced release = %d\n", span->span_id, r2conf.forced_release); } else if (!strcasecmp(var, "charge_calls")) { - r2conf.charge_calls = va_arg(ap, int); + r2conf.charge_calls = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with charge calls = %d\n", span->span_id, r2conf.charge_calls); } else if (!strcasecmp(var, "get_ani_first")) { - r2conf.get_ani_first = va_arg(ap, int); + r2conf.get_ani_first = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with get ani first = %d\n", span->span_id, r2conf.get_ani_first); } else if (!strcasecmp(var, "call_files")) { - r2conf.call_files = va_arg(ap, int); + r2conf.call_files = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with call files = %d\n", span->span_id, r2conf.call_files); } else if (!strcasecmp(var, "mf_files")) { - r2conf.mf_files = va_arg(ap, int); + r2conf.mf_files = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with mf files = %d\n", span->span_id, r2conf.mf_files); } else if (!strcasecmp(var, "mfback_timeout")) { - r2conf.mfback_timeout = va_arg(ap, int); + r2conf.mfback_timeout = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with MF backward timeout = %dms\n", span->span_id, r2conf.mfback_timeout); } else if (!strcasecmp(var, "metering_pulse_timeout")) { - r2conf.metering_pulse_timeout = va_arg(ap, int); + r2conf.metering_pulse_timeout = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with metering pulse timeout = %dms\n", span->span_id, r2conf.metering_pulse_timeout); } else if (!strcasecmp(var, "max_ani")) { - r2conf.max_ani = va_arg(ap, int); + r2conf.max_ani = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with max ani = %d\n", span->span_id, r2conf.max_ani); } else if (!strcasecmp(var, "max_dnis")) { - r2conf.max_dnis = va_arg(ap, int); + r2conf.max_dnis = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with max dnis = %d\n", span->span_id, r2conf.max_dnis); } else { snprintf(span->last_error, sizeof(span->last_error), "Unknown R2 parameter [%s]", var); @@ -1062,6 +1072,10 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) return FTDM_FAIL; } + /* set span log level */ + r2conf.loglevel = ftdm_r2_loglevel_from_string(log_level); + ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, log_level); + r2data = ftdm_malloc(sizeof(*r2data)); if (!r2data) { snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate R2 data."); @@ -1387,6 +1401,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) r2chan = R2CALL(span->channels[i])->r2chan; openr2_chan_set_idle(r2chan); openr2_chan_process_cas_signaling(r2chan); + + ftdmchan = openr2_chan_get_client_data(r2chan); + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); } memset(&start, 0, sizeof(start)); @@ -1762,12 +1779,13 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy) } EX_DECLARE_DATA ftdm_module_t ftdm_module = { - "r2", - ftdm_r2_io_init, - NULL, - ftdm_r2_init, - ftdm_r2_configure_span, - ftdm_r2_destroy + /* .name */ "r2", + /* .io_load */ ftdm_r2_io_init, + /* .io_unload */ NULL, + /* .sig_load */ ftdm_r2_init, + /* .sig_configure */ NULL, + /* .sig_unload */ ftdm_r2_destroy, + /* .configure_span_signaling */ ftdm_r2_configure_span_signaling }; From 80174cf39fa6b29c45232b231f7f169224f975a7 Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Fri, 26 Nov 2010 20:38:46 -0500 Subject: [PATCH 61/97] mod_callcenter: Add new eventsocket agent-offering. Plus some documentation and better handeling of bad agent type -- FS-2869 --- .../mod_callcenter/mod_callcenter.c | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 1b0ba1331a..ca92b17fa4 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1346,6 +1346,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_time_t t_agent_called = 0; switch_time_t t_agent_answered = 0; switch_time_t t_member_called = atoi(h->member_joined_epoch); + switch_event_t *event = NULL; switch_mutex_lock(globals.mutex); globals.threads++; @@ -1360,6 +1361,21 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_safe_free(sql); goto done; } + + /* Proceed contact the agent to offer the member */ + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-offering"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Type", h->agent_type); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number); + switch_event_fire(&event); + } + + /* CallBack Mode */ if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) { switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name); @@ -1375,6 +1391,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_safe_free(dialstr); switch_event_destroy(&ovars); + /* UUID Standby Mode */ } else if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)) { agent_session = switch_core_session_locate(h->agent_uuid); if (agent_session) { @@ -1400,14 +1417,17 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa cc_agent_update("status", cc_agent_status2str(CC_AGENT_STATUS_LOGGED_OUT), h->agent_name); cc_agent_update("uuid", "", h->agent_name); } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invalid agent type '%s' for agent '%s', aborting member offering", h->agent_type, h->agent_name); + status = SWITCH_CAUSE_USER_NOT_REGISTERED; } + /* Originate/Bridge is not finished, processing the return value */ if (status == SWITCH_STATUS_SUCCESS) { /* Agent Answered */ const char *agent_uuid = switch_core_session_get_uuid(agent_session); switch_channel_t *member_channel = switch_core_session_get_channel(member_session); switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session); - switch_event_t *event; switch_channel_set_variable(agent_channel, "cc_member_pre_answer_uuid", NULL); From 9a9373c0bb42cf0e57c1b08e661a14b2a7760369 Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Sun, 28 Nov 2010 17:07:54 -0500 Subject: [PATCH 62/97] mod_sofia: Fix malformed Presense SQL Query --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 95ea913a61..9d0b23a06d 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1927,7 +1927,7 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where hostname='%q' " "and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')' ", + "where hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')", mod_sofia_globals.hostname, to_user, to_host, to_user, to_host); From 8825b6eac893b8280e7323133469eb24b79ed8db Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Sun, 28 Nov 2010 17:15:39 -0500 Subject: [PATCH 63/97] mod_sofia: Fix in previous commit incompleted, this one should do it (sofia presence related) --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 9d0b23a06d..5c2517db61 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1927,7 +1927,7 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')", + "where hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", mod_sofia_globals.hostname, to_user, to_host, to_user, to_host); From ac2998b61f74e06100ca988eefdb608d312d1098 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Mon, 29 Nov 2010 16:48:01 -0200 Subject: [PATCH 64/97] freetdm: ftmod_r2 - set feature FTDM_CHANNEL_FEATURE_IO_STATS just when the channel is in FTDM_CHANNEL_STATE_UP state --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index ffc39e8884..b9e0e1378f 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1403,7 +1403,6 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) openr2_chan_process_cas_signaling(r2chan); ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); } memset(&start, 0, sizeof(start)); @@ -1462,6 +1461,12 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdmchan = openr2_chan_get_client_data(r2chan); r2call = R2CALL(ftdmchan); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_UP)) { + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); + } else { + ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); + } + ftdm_mutex_lock(ftdmchan->mutex); ftdm_r2_state_advance_all(ftdmchan); openr2_chan_process_signaling(r2chan); From 2572621bc914e30cc22e79749264d67882d0aaf8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 29 Nov 2010 13:00:19 -0600 Subject: [PATCH 65/97] FS-2368 --- src/switch_core_session.c | 14 ++++-- src/switch_ivr_bridge.c | 92 ++++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 45 deletions(-) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index b3bb638c76..eca2f8daf2 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1831,10 +1831,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n", app, switch_channel_get_name(session->channel)); } else if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && !switch_channel_media_ready(session->channel)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media! pre_answering channel %s\n", - app, switch_channel_get_name(session->channel)); - if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Well, that didn't work very well did it? ...\n"); + if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media! pre_answering channel %s\n", + app, switch_channel_get_name(session->channel)); + if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Well, that didn't work very well did it? ...\n"); + switch_goto_status(SWITCH_STATUS_FALSE, done); + } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + "Cannot execute app '%s' media required on an outbound channel that does not have media established\n", app); switch_goto_status(SWITCH_STATUS_FALSE, done); } } diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index b6363ffa53..64a5f8d7c9 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -155,7 +155,6 @@ struct switch_ivr_bridge_data { switch_input_callback_function_t input_callback; void *session_data; int clean_exit; - uint32_t skip_frames; }; typedef struct switch_ivr_bridge_data switch_ivr_bridge_data_t; @@ -169,7 +168,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) switch_channel_t *chan_a, *chan_b; switch_frame_t *read_frame; switch_core_session_t *session_a, *session_b; - uint32_t loop_count = 0; + uint32_t read_frame_count = 0; const char *app_name = NULL, *app_arg = NULL; const char *hook_var = NULL; int inner_bridge = 0; @@ -181,6 +180,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) const char *bridge_answer_timeout = NULL; int answer_timeout, sent_update = 0; time_t answer_limit = 0; + const char *exec_app = NULL; + const char *exec_data = NULL; #ifdef SWITCH_VIDEO_IN_THREADS switch_thread_t *vid_thread = NULL; @@ -201,6 +202,10 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) chan_a = switch_core_session_get_channel(session_a); chan_b = switch_core_session_get_channel(session_b); + if ((exec_app = switch_channel_get_variable(chan_a, "bridge_pre_execute_app"))) { + exec_data = switch_channel_get_variable(chan_a, "bridge_pre_execute_data"); + } + bypass_media_after_bridge = switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); @@ -212,7 +217,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) } inner_bridge = switch_channel_test_flag(chan_a, CF_INNER_BRIDGE); - + if (!switch_channel_test_flag(chan_a, CF_ANSWERED) && (bridge_answer_timeout = switch_channel_get_variable(chan_a, "bridge_answer_timeout"))) { if ((answer_timeout = atoi(bridge_answer_timeout)) < 0) { answer_timeout = 0; @@ -285,7 +290,6 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) switch_channel_state_t b_state; switch_status_t status; switch_event_t *event; - loop_count++; if (switch_channel_test_flag(chan_a, CF_TRANSFER)) { data->clean_exit = 1; @@ -309,7 +313,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) goto end_of_bridge_loop; } - if (loop_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && switch_core_session_private_event_count(session_a)) { + if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && switch_core_session_private_event_count(session_a)) { switch_channel_set_flag(chan_b, CF_SUSPEND); msg.string_arg = data->b_uuid; msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE; @@ -341,13 +345,34 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) } #endif - if (loop_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && - (bypass_media_after_bridge || switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED) - && switch_channel_test_flag(chan_b, CF_ANSWERED)) { - switch_ivr_nomedia(switch_core_session_get_uuid(session_a), SMF_REBRIDGE); - bypass_media_after_bridge = 0; - switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); - goto end_of_bridge_loop; + if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a)) { + + if (exec_app) { + switch_event_t *execute_event; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_CRIT, "%s Bridge execute app %s(%s)\n", + switch_channel_get_name(chan_a), exec_app, exec_data); + + if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", exec_app); + if (exec_data) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", exec_data); + } + //switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + switch_core_session_queue_private_event(session_a, &execute_event, SWITCH_FALSE); + } + exec_app = exec_data = NULL; + } + + + if ((bypass_media_after_bridge || switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED) + && switch_channel_test_flag(chan_b, CF_ANSWERED)) { + switch_ivr_nomedia(switch_core_session_get_uuid(session_a), SMF_REBRIDGE); + bypass_media_after_bridge = 0; + switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); + goto end_of_bridge_loop; + } } /* if 1 channel has DTMF pass it to the other */ @@ -454,6 +479,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) status = switch_core_session_read_frame(session_a, &read_frame, SWITCH_IO_FLAG_NONE, stream_id); if (SWITCH_READ_ACCEPTABLE(status)) { + read_frame_count++; if (switch_test_flag(read_frame, SFF_CNG)) { if (silence_val) { switch_generate_sln_silence((int16_t *) silence_frame.data, silence_frame.samples, silence_val); @@ -463,11 +489,6 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) } } - if (data->skip_frames) { - data->skip_frames--; - continue; - } - if (switch_channel_test_flag(chan_a, CF_BRIDGE_NOWRITE)) { continue; } @@ -1193,35 +1214,24 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_channel_set_variable(peer_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session)); if ((app = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_app"))) { - switch_event_t *execute_event; - - data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_data"); - if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", app); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", data); - switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE); - a_leg->skip_frames = DEFAULT_LEAD_FRAMES; + switch_channel_set_variable(caller_channel, "bridge_pre_execute_app", app); + + if ((data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_data"))) { + switch_channel_set_variable(caller_channel, "bridge_pre_execute_data", data); } - } if ((app = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_app"))) { - switch_event_t *execute_event; - data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_data"); - if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", app); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", data); - switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(peer_session, &execute_event, SWITCH_FALSE); - b_leg->skip_frames = DEFAULT_LEAD_FRAMES; - } - } + switch_channel_set_variable(peer_channel, "bridge_pre_execute_app", app); + if ((data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_data"))) { + switch_channel_set_variable(peer_channel, "bridge_pre_execute_data", data); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "APP [%s][%s]\n", app, switch_str_nil(data)); + + } + switch_channel_set_private(peer_channel, "_bridge_", b_leg); switch_channel_set_state(peer_channel, CS_EXCHANGE_MEDIA); audio_bridge_thread(NULL, (void *) a_leg); From 9a25519496cf5299b0d4d59ea1ca9da56b008432 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 29 Nov 2010 13:02:48 -0600 Subject: [PATCH 66/97] FS-2368 forgot one debug line --- src/switch_ivr_bridge.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 64a5f8d7c9..4cae1a67e2 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -349,7 +349,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) if (exec_app) { switch_event_t *execute_event; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_CRIT, "%s Bridge execute app %s(%s)\n", + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Bridge execute app %s(%s)\n", switch_channel_get_name(chan_a), exec_app, exec_data); if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { @@ -1228,8 +1228,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_channel_set_variable(peer_channel, "bridge_pre_execute_data", data); } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "APP [%s][%s]\n", app, switch_str_nil(data)); - } switch_channel_set_private(peer_channel, "_bridge_", b_leg); From 74f04959b4e27f4af677c960c82637e874920395 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Mon, 29 Nov 2010 19:27:49 -0200 Subject: [PATCH 67/97] freetdm: ftmod_r2 - reverted last commit --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index b9e0e1378f..ffc39e8884 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1403,6 +1403,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) openr2_chan_process_cas_signaling(r2chan); ftdmchan = openr2_chan_get_client_data(r2chan); + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); } memset(&start, 0, sizeof(start)); @@ -1461,12 +1462,6 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdmchan = openr2_chan_get_client_data(r2chan); r2call = R2CALL(ftdmchan); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_UP)) { - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - } else { - ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - } - ftdm_mutex_lock(ftdmchan->mutex); ftdm_r2_state_advance_all(ftdmchan); openr2_chan_process_signaling(r2chan); From ed5266d3ca944036165a26d06eac3a3fcd0b88a5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 29 Nov 2010 15:34:27 -0600 Subject: [PATCH 68/97] don't parse events for b legs from a leg thread in case they are using a monolothic python script as a group_confirm exec over socket to send it messages while the call is ringing --- src/switch_ivr_originate.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index da76cf6cbc..f99ac69188 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -635,8 +635,15 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat } } } - - switch_ivr_parse_all_events(originate_status[i].peer_session); + + if (!switch_channel_test_flag(originate_status[i].peer_channel, CF_PARK) && + !switch_channel_test_flag(originate_status[i].peer_channel, CF_CONSUME_ON_ORIGINATE)) { + if (switch_channel_test_flag(originate_status[i].peer_channel, CF_THREAD_SLEEPING)) { + switch_core_session_wake_session_thread(originate_status[i].peer_session); + } else { + switch_ivr_parse_all_events(originate_status[i].peer_session); + } + } state = switch_channel_get_state(originate_status[i].peer_channel); if (state >= CS_HANGUP || state == CS_RESET || switch_channel_test_flag(originate_status[i].peer_channel, CF_TRANSFER) || From 7630d47e0e9efb0cea1f2a2ae7f908fee43d80a3 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 29 Nov 2010 21:55:34 -0600 Subject: [PATCH 69/97] VS2010 Initial version for freetdm --- libs/freetdm/freetdm.2010.sln | 137 +++++++++++ libs/freetdm/msvc/freetdm.2010.vcxproj | 223 ++++++++++++++++++ .../freetdm/msvc/freetdm.2010.vcxproj.filters | 128 ++++++++++ .../msvc/testanalog/testanalog.2010.vcxproj | 213 +++++++++++++++++ .../testanalog.2010.vcxproj.filters | 14 ++ .../msvc/testboost/testboost.2010.vcxproj | 218 +++++++++++++++++ .../testboost/testboost.2010.vcxproj.filters | 14 ++ .../testboost/testsangomaboost.2010.vcxproj | 218 +++++++++++++++++ .../testsangomaboost.2010.vcxproj.filters | 14 ++ .../msvc/testisdn/testisdn.2010.vcxproj | 213 +++++++++++++++++ .../testisdn/testisdn.2010.vcxproj.filters | 14 ++ .../ftmod_analog/ftmod_analog.2010.vcxproj | 198 ++++++++++++++++ .../ftmod_analog.2010.vcxproj.filters | 23 ++ .../ftmod_analog_em.2010.vcxproj | 198 ++++++++++++++++ .../ftmod_analog_em.2010.vcxproj.filters | 23 ++ .../ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj | 223 ++++++++++++++++++ .../ftmod_isdn.2010.vcxproj.filters | 110 +++++++++ .../ftmod/ftmod_pika/ftmod_pika.2010.vcxproj | 198 ++++++++++++++++ .../ftmod_pika.2010.vcxproj.filters | 23 ++ .../src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj | 95 ++++++++ .../ftmod_r2/ftmod_r2.2010.vcxproj.filters | 22 ++ .../ftmod_sangoma_boost.2010.vcxproj | 206 ++++++++++++++++ .../ftmod_sangoma_boost.2010.vcxproj.filters | 35 +++ .../ftmod_sangoma_isdn.2010.vcxproj | 121 ++++++++++ .../ftmod_sangoma_isdn.2010.vcxproj.filters | 57 +++++ .../ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj | 201 ++++++++++++++++ .../ftmod_wanpipe.2010.vcxproj.filters | 18 ++ 27 files changed, 3157 insertions(+) create mode 100644 libs/freetdm/freetdm.2010.sln create mode 100644 libs/freetdm/msvc/freetdm.2010.vcxproj create mode 100644 libs/freetdm/msvc/freetdm.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj create mode 100644 libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testboost/testboost.2010.vcxproj create mode 100644 libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj create mode 100644 libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj create mode 100644 libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters diff --git a/libs/freetdm/freetdm.2010.sln b/libs/freetdm/freetdm.2010.sln new file mode 100644 index 0000000000..1806e9ea23 --- /dev/null +++ b/libs/freetdm/freetdm.2010.sln @@ -0,0 +1,137 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetdm", "msvc\freetdm.2010.vcxproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2010.vcxproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2010.vcxproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_freetdm", "mod_freetdm\mod_freetdm.2010.vcxproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog", "src\ftmod\ftmod_analog\ftmod_analog.2010.vcxproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog_em", "src\ftmod\ftmod_analog_em\ftmod_analog_em.2010.vcxproj", "{B3F49375-2834-4937-9D8C-4AC2EC911010}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_isdn", "src\ftmod\ftmod_isdn\ftmod_isdn.2010.vcxproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_pika", "src\ftmod\ftmod_pika\ftmod_pika.2010.vcxproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ftmod_wanpipe\ftmod_wanpipe.2010.vcxproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_boost", "src\ftmod\ftmod_sangoma_boost\ftmod_sangoma_boost.2010.vcxproj", "{D021EF2A-460D-4827-A0F7-41FDECF46F1B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testboost", "msvc\testboost\testboost.2010.vcxproj", "{2B1BAF36-0241-43E7-B865-A8338AD48E2E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsangomaboost", "msvc\testboost\testsangomaboost.2010.vcxproj", "{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2010.vcxproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2010.vcxproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.ActiveCfg = Debug|x64 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.Build.0 = Debug|x64 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.ActiveCfg = Release|x64 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.Build.0 = Release|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.ActiveCfg = Debug|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.Build.0 = Debug|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.ActiveCfg = Release|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.Build.0 = Release|x64 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|x64.ActiveCfg = Debug|x64 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|x64.ActiveCfg = Release|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.ActiveCfg = Debug|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.Build.0 = Debug|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.ActiveCfg = Release|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.Build.0 = Release|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.ActiveCfg = Debug|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.Build.0 = Debug|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.ActiveCfg = Release|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.Build.0 = Release|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.ActiveCfg = Debug|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.Build.0 = Debug|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.ActiveCfg = Debug|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.Build.0 = Debug|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.ActiveCfg = Release|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.Build.0 = Release|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.ActiveCfg = Release|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.Build.0 = Release|x64 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|x64.ActiveCfg = Debug|x64 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|x64.ActiveCfg = Release|x64 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|x64.ActiveCfg = Debug|x64 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|x64.ActiveCfg = Release|x64 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.Build.0 = Debug|Win32 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|x64.ActiveCfg = Debug|x64 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.Build.0 = Release|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.Build.0 = Release|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.Build.0 = Release|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj b/libs/freetdm/msvc/freetdm.2010.vcxproj new file mode 100644 index 0000000000..71eb6dbf22 --- /dev/null +++ b/libs/freetdm/msvc/freetdm.2010.vcxproj @@ -0,0 +1,223 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + freetdm + {93B8812C-3EC4-4F78-8970-FFBFC99E167D} + freetdm + Win32Proj + + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-freetdm.htm + + + Disabled + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + true + + + + + $(IntDir)BuildLog-freetdm.htm + + + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + + + $(IntDir)BuildLog-freetdm.htm + + + X64 + + + Disabled + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + true + MachineX64 + + + + + $(IntDir)BuildLog-freetdm.htm + + + X64 + + + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj.filters b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters new file mode 100644 index 0000000000..ed642baf3d --- /dev/null +++ b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters @@ -0,0 +1,128 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj new file mode 100644 index 0000000000..719dc618a9 --- /dev/null +++ b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testanalog + {BB833648-BAFF-4BE2-94DB-F8BB043C588C} + testanalog + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testanalog.htm + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testanalog.htm + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testanalog.htm + + + X64 + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX64 + + + + + $(IntDir)BuildLog-testanalog.htm + + + X64 + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters new file mode 100644 index 0000000000..7ac3635cc5 --- /dev/null +++ b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testboost.2010.vcxproj b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj new file mode 100644 index 0000000000..62061485c2 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testboost + {2B1BAF36-0241-43E7-B865-A8338AD48E2E} + testboost + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testboost.htm + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + ..\..\debug\freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testboost.htm + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testboost.htm + + + X64 + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX64 + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + $(IntDir)BuildLog-testboost.htm + + + X64 + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + freetdm.lib;%(AdditionalDependencies) + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters new file mode 100644 index 0000000000..74181d60a8 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj new file mode 100644 index 0000000000..b6c0518883 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testsangomaboost + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE} + testsangomaboost + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + ..\..\debug\freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + X64 + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + false + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX64 + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + X64 + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + freetdm.lib;%(AdditionalDependencies) + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters new file mode 100644 index 0000000000..e72f14e161 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj new file mode 100644 index 0000000000..2dfdeb042f --- /dev/null +++ b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testisdn + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B} + testisdn + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testisdn.htm + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testisdn.htm + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testisdn.htm + + + X64 + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX64 + + + + + $(IntDir)BuildLog-testisdn.htm + + + X64 + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters new file mode 100644 index 0000000000..9d48828d4a --- /dev/null +++ b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj new file mode 100644 index 0000000000..81cb93fa44 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj @@ -0,0 +1,198 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_analog + {37C94798-6E33-4B4F-8EE0-C72A7DC91157} + ftmod_analog + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + false + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters new file mode 100644 index 0000000000..b6fed5927a --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj new file mode 100644 index 0000000000..44792df89f --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj @@ -0,0 +1,198 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_analog_em + {B3F49375-2834-4937-9D8C-4AC2EC911010} + ftmod_analog_em + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + false + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters new file mode 100644 index 0000000000..3326f9fd16 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj new file mode 100644 index 0000000000..bd2e2fe4f0 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj @@ -0,0 +1,223 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_isdn + {729344A5-D5E9-434D-8EE8-AF8C6C795D15} + ftmod_isdn + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters new file mode 100644 index 0000000000..30824888fc --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters @@ -0,0 +1,110 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj new file mode 100644 index 0000000000..c4004bda21 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj @@ -0,0 +1,198 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_pika + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF} + ftmod_pika + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + true + true + MachineX64 + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters new file mode 100644 index 0000000000..4d4cec4668 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj new file mode 100644 index 0000000000..f66f5afc0d --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj @@ -0,0 +1,95 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + ftmod_r2 + {08C3EA27-A51D-47F8-B47D-B189C649CF30} + Win32Proj + + + + DynamicLibrary + + + DynamicLibrary + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;c:\Program Files\openr2\include\openr2;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + freetdm.lib;openr2.lib;%(AdditionalDependencies) + C:\Program Files\openr2\lib;$(OutDir);%(AdditionalLibraryDirectories) + true + Windows + MachineX86 + + + + + ..\..\include;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters new file mode 100644 index 0000000000..9c91228e09 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj new file mode 100644 index 0000000000..1dd09211e2 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj @@ -0,0 +1,206 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_sangoma_boost + {D021EF2A-460D-4827-A0F7-41FDECF46F1B} + ftmod_sangoma_boost + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters new file mode 100644 index 0000000000..2aeed155cd --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj new file mode 100644 index 0000000000..b4d234cc7d --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj @@ -0,0 +1,121 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + ftmod_sangoma_isdn + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395} + ftmod_sangoma_isdn + Win32Proj + + + + DynamicLibrary + true + + + DynamicLibrary + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + EnableFastChecks + + + Level3 + EditAndContinue + + + freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\libsng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) + true + Console + false + + + MachineX86 + + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + + + + + + + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters new file mode 100644 index 0000000000..5f592fa9ef --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj new file mode 100644 index 0000000000..b165ac82d3 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj @@ -0,0 +1,201 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_wanpipe + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD} + ftmod_wanpipe + Win32Proj + + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) + true + Console + false + + + MachineX86 + + + + + X64 + + + Disabled + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories) + true + Console + false + + + MachineX64 + + + + + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories) + true + Console + true + true + false + + + MachineX64 + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters new file mode 100644 index 0000000000..15a8bc3d35 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters @@ -0,0 +1,18 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + \ No newline at end of file From 8b0421ff6815457ac9b21223db2bbe338cd782f0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 09:49:12 -0600 Subject: [PATCH 70/97] add new function to check when messages need parsing to improve performance on parsing messages during originate --- src/include/switch_core.h | 5 +++++ src/switch_core_session.c | 15 +++++++++++++++ src/switch_ivr_originate.c | 10 ++++++---- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3f636d00c4..231b26f269 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1024,6 +1024,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(_In_ switch_core */ SWITCH_DECLARE(uint32_t) switch_core_session_event_count(_In_ switch_core_session_t *session); +/* + Number of parsable messages waiting on the session. + */ +SWITCH_DECLARE(uint32_t) switch_core_session_messages_waiting(switch_core_session_t *session); + /*! \brief DE-Queue an event on a given session \param session the session to de-queue the message on diff --git a/src/switch_core_session.c b/src/switch_core_session.c index eca2f8daf2..aaa47cc696 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -861,6 +861,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_sess return status; } +SWITCH_DECLARE(uint32_t) switch_core_session_messages_waiting(switch_core_session_t *session) +{ + int x = 0; + + if (session->private_event_queue) { + x += switch_queue_size(session->private_event_queue); + } + + if (session->message_queue) { + x += switch_queue_size(session->message_queue); + } + + return x; +} + SWITCH_DECLARE(uint32_t) switch_core_session_event_count(switch_core_session_t *session) { if (session->event_queue) { diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index f99ac69188..e61534798b 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -638,10 +638,12 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat if (!switch_channel_test_flag(originate_status[i].peer_channel, CF_PARK) && !switch_channel_test_flag(originate_status[i].peer_channel, CF_CONSUME_ON_ORIGINATE)) { - if (switch_channel_test_flag(originate_status[i].peer_channel, CF_THREAD_SLEEPING)) { - switch_core_session_wake_session_thread(originate_status[i].peer_session); - } else { - switch_ivr_parse_all_events(originate_status[i].peer_session); + if (switch_core_session_messages_waiting(originate_status[i].peer_session)) { + if (switch_channel_test_flag(originate_status[i].peer_channel, CF_THREAD_SLEEPING)) { + switch_core_session_wake_session_thread(originate_status[i].peer_session); + } else { + switch_ivr_parse_all_events(originate_status[i].peer_session); + } } } From bce61e7f926ca424c04340d217ac5ee3246fe454 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 10:49:23 -0500 Subject: [PATCH 71/97] freetdm: ftmod_wanpipe - use SANGOMA_WAIT_INFINITE instead of -1 --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c20ad82a3b..65c587c350 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -121,6 +121,10 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout uint32_t outflags = 0; sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data; + if (timeout == -1) { + timeout = SANGOMA_WAIT_INFINITE; + } + err = sangoma_waitfor(sangoma_wait_obj, inflags, &outflags, timeout); *flags = 0; if (err == SANG_STATUS_SUCCESS) { From 136fc8aa954cf7154b75a72297e76b94cb92e3c3 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Tue, 30 Nov 2010 13:56:29 -0200 Subject: [PATCH 72/97] freetdm: ftmod_wanpipe - removed 80% tx/rx queue warnings --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 804c6cfe8f..17f0219b1f 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -789,16 +789,6 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; - if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } - if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); @@ -860,17 +850,6 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); } - if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - /* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } - if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); From a523e7755c111023ec767e298206fd7657693b94 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 11:07:40 -0500 Subject: [PATCH 73/97] freetdm: get rid of Linux warnings in testsangomaboost.c --- libs/freetdm/src/testsangomaboost.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/testsangomaboost.c b/libs/freetdm/src/testsangomaboost.c index 38eac3c190..85b5332635 100644 --- a/libs/freetdm/src/testsangomaboost.c +++ b/libs/freetdm/src/testsangomaboost.c @@ -45,10 +45,14 @@ #include -#include "freetdm.h" #include #include #include +#ifdef __linux__ +#define __USE_BSD +#include +#endif +#include "freetdm.h" /* arbitrary limit for max calls in this sample program */ @@ -338,9 +342,9 @@ int main(int argc, char *argv[]) exit(-1); } - if (!strcasecmp(argv[2], "cpe")) { + if (!strcmp(argv[2], "cpe")) { sigtype = "pri_cpe"; - } else if (!strcasecmp(argv[2], "net")) { + } else if (!strcmp(argv[2], "net")) { sigtype = "pri_net"; } else { fprintf(stderr, "Valid signaling types are cpe and net only\n"); From 469728a8656431e334e77d92d398cca05fa6c4a0 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 11:38:38 -0500 Subject: [PATCH 74/97] freetdm: clear out wait flags in the core on timeout --- libs/freetdm/src/ftdm_io.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 6f543304a2..4df4d81fe1 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2828,21 +2828,17 @@ done: FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t to) { - assert(ftdmchan != NULL); - assert(ftdmchan->fio != NULL); + ftdm_status_t status = FTDM_FAIL; + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n"); + ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "Null io interface\n"); + ftdm_assert_return(ftdmchan->fio->wait != NULL, FTDM_NOTIMPL, "wait method not implemented\n"); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open"); - return FTDM_FAIL; - } - - if (!ftdmchan->fio->wait) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented"); - return FTDM_FAIL; + status = ftdmchan->fio->wait(ftdmchan, flags, to); + if (status == FTDM_TIMEOUT) { + /* make sure the flags are cleared on timeout */ + *flags = 0; } - - return ftdmchan->fio->wait(ftdmchan, flags, to); - + return status; } /*******************************/ From ef4a4ed03498769c34bfbb22fce1e100a3e3b5e8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 11:01:54 -0600 Subject: [PATCH 75/97] run execute_on_answer on_media _on_ring apps async --- src/include/switch_core.h | 2 ++ src/switch_channel.c | 21 ++++++++++++++++++--- src/switch_core_session.c | 26 ++++++++++++++++++++++++++ src/switch_ivr_bridge.c | 12 +----------- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 231b26f269..33df7e31dd 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -882,6 +882,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(_In_ switch_core_sessio SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(_In_ switch_core_session_t *session, _In_ const char *app, _In_opt_z_ const char *arg, _Out_opt_ int32_t *flags); +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg); + SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *app, int32_t *flags); /*! diff --git a/src/switch_channel.c b/src/switch_channel.c index c63a1aadb9..a9c87c5954 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2518,7 +2518,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi if ((arg = strchr(app, ' '))) { *arg++ = '\0'; } - switch_core_session_execute_application(channel->session, app, arg); + + if (switch_core_session_in_thread(channel->session)) { + switch_core_session_execute_application(channel->session, app, arg); + } else { + switch_core_session_execute_application_async(channel->session, app, arg); + } } return SWITCH_STATUS_SUCCESS; @@ -2571,7 +2576,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_ if ((arg = strchr(app, ' '))) { *arg++ = '\0'; } - switch_core_session_execute_application(channel->session, app, arg); + + if (switch_core_session_in_thread(channel->session)) { + switch_core_session_execute_application(channel->session, app, arg); + } else { + switch_core_session_execute_application_async(channel->session, app, arg); + } } if ((var = switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE))) { @@ -2750,7 +2760,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan } switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s execute on answer: %s(%s)\n", channel->name, app, switch_str_nil(arg)); - switch_core_session_execute_application(channel->session, app, arg); + + if (switch_core_session_in_thread(channel->session)) { + switch_core_session_execute_application(channel->session, app, arg); + } else { + switch_core_session_execute_application_async(channel->session, app, arg); + } } } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index aaa47cc696..a84bfabaf0 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -855,6 +855,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_sess if (switch_queue_trypush(session->event_queue, *event) == SWITCH_STATUS_SUCCESS) { *event = NULL; status = SWITCH_STATUS_SUCCESS; + + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_test_flag(session->channel, CF_THREAD_SLEEPING)) { + switch_core_session_wake_session_thread(session); + } } } @@ -1814,6 +1818,28 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *ap } +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg) +{ + switch_event_t *execute_event; + + if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", app); + + if (arg) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", arg); + } + + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE); + + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + + SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(switch_core_session_t *session, const char *app, const char *arg, int32_t *flags) { diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 4cae1a67e2..4d320d0e5c 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -348,20 +348,10 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a)) { if (exec_app) { - switch_event_t *execute_event; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Bridge execute app %s(%s)\n", switch_channel_get_name(chan_a), exec_app, exec_data); - if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", exec_app); - if (exec_data) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", exec_data); - } - //switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(session_a, &execute_event, SWITCH_FALSE); - } + switch_core_session_execute_application_async(session_a, exec_app, exec_data); exec_app = exec_data = NULL; } From 5b15e03f30eabcba91b0c1bec09a489221bbaaaa Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 30 Nov 2010 11:24:59 -0600 Subject: [PATCH 76/97] swigall --- .../languages/mod_managed/freeswitch_wrap.cxx | 28 +++++++++++++++++++ src/mod/languages/mod_managed/managed/swig.cs | 16 +++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index ca001f64b1..d2f63b1006 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -7626,6 +7626,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_execute_application_get_fl } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_execute_application_async(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_core_session_execute_application_async(arg1,(char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_get_app_flags(char * jarg1, void * jarg2) { int jresult ; char *arg1 = (char *) 0 ; @@ -7856,6 +7872,18 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_event_count(void } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_messages_waiting(void * jarg1) { + unsigned long jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + uint32_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (uint32_t)switch_core_session_messages_waiting(arg1); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_dequeue_event(void * jarg1, void * jarg2, int jarg3) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index bd901911ed..fd4915f013 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -1439,6 +1439,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_execute_application_async(SWIGTYPE_p_switch_core_session session, string app, string arg) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_execute_application_async(SWIGTYPE_p_switch_core_session.getCPtr(session), app, arg); + return ret; + } + public static switch_status_t switch_core_session_get_app_flags(string app, SWIGTYPE_p_int flags) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_get_app_flags(app, SWIGTYPE_p_int.getCPtr(flags)); return ret; @@ -1518,6 +1523,11 @@ public class freeswitch { return ret; } + public static uint switch_core_session_messages_waiting(SWIGTYPE_p_switch_core_session session) { + uint ret = freeswitchPINVOKE.switch_core_session_messages_waiting(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + public static switch_status_t switch_core_session_dequeue_event(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_event arg1, switch_bool_t force) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_dequeue_event(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_event.getCPtr(arg1), (int)force); return ret; @@ -7449,6 +7459,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_execute_application_get_flags")] public static extern int switch_core_session_execute_application_get_flags(HandleRef jarg1, string jarg2, string jarg3, HandleRef jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_execute_application_async")] + public static extern int switch_core_session_execute_application_async(HandleRef jarg1, string jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_app_flags")] public static extern int switch_core_session_get_app_flags(string jarg1, HandleRef jarg2); @@ -7497,6 +7510,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_event_count")] public static extern uint switch_core_session_event_count(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_messages_waiting")] + public static extern uint switch_core_session_messages_waiting(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_dequeue_event")] public static extern int switch_core_session_dequeue_event(HandleRef jarg1, HandleRef jarg2, int jarg3); From 302d5bb18f5604c180d1eb3c48b80929e1b306ae Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 19:19:32 -0500 Subject: [PATCH 77/97] Changes for ftdm variables --- libs/freetdm/mod_freetdm/mod_freetdm.c | 73 +++-- libs/freetdm/src/ftdm_call_utils.c | 135 +++++---- libs/freetdm/src/ftdm_io.c | 20 +- .../ftmod_sangoma_boost/ftdm_sangoma_boost.h | 2 +- .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 14 +- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 11 +- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 72 +++-- .../ftmod_sangoma_isdn_cfg.c | 97 +++--- .../ftmod_sangoma_isdn_stack_hndl.c | 99 +++--- .../ftmod_sangoma_isdn_stack_out.c | 90 ++---- .../ftmod_sangoma_isdn_support.c | 285 ++++++++++++++++-- .../ftmod_sangoma_isdn_trace.c | 15 + .../ftmod_sangoma_isdn_trace.h | 6 + libs/freetdm/src/include/freetdm.h | 82 +++-- libs/freetdm/src/include/ftdm_call_utils.h | 118 ++++++++ libs/freetdm/src/include/ftdm_declare.h | 17 ++ .../src/include/private/ftdm_call_utils.h | 47 --- 17 files changed, 792 insertions(+), 391 deletions(-) create mode 100644 libs/freetdm/src/include/ftdm_call_utils.h delete mode 100644 libs/freetdm/src/include/private/ftdm_call_utils.h diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 27dc8d8c92..07d4e88f33 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -149,6 +149,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); +static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name); ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp); void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream); void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream); @@ -1049,6 +1050,27 @@ switch_io_routines_t freetdm_io_routines = { /*.receive_message*/ channel_receive_message }; +static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name) +{ + const char *variable = NULL; + + if (var_event) { + if ((variable = switch_event_get_header(var_event, variable_name))) { + return variable; + } + } + if (session) { + switch_channel_t *channel = switch_core_session_get_channel(session); + if ((variable = switch_channel_get_variable(channel, variable_name))) { + return variable; + } + } + if ((variable = switch_core_get_variable(variable_name))) { + return variable; + } + return NULL; +} + /* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines that allocate memory or you will have 1 channel with memory allocated from another channel's pool! */ @@ -1226,20 +1248,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } } - if (session) { - /* take out some other values from the session if they're present */ - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *freetdmvar; - freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_capability"); - if (freetdmvar) { - caller_data.bearer_capability = (uint8_t)atoi(freetdmvar); - } - freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_layer1"); - if (freetdmvar) { - caller_data.bearer_layer1 = (uint8_t)atoi(freetdmvar); - } - } - if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) { caller_data.screen = 1; } @@ -1248,29 +1256,37 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi caller_data.pres = 1; } - if (!zstr(dest)) { - ftdm_set_string(caller_data.dnis.digits, dest); + if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) { + caller_data.bearer_capability = (uint8_t)atoi(var); } - if ((var = switch_event_get_header(var_event, "freetdm_outbound_ton")) || (var = switch_core_get_variable("freetdm_outbound_ton"))) { - if (!strcasecmp(var, "national")) { - caller_data.dnis.type = FTDM_TON_NATIONAL; - } else if (!strcasecmp(var, "international")) { - caller_data.dnis.type = FTDM_TON_INTERNATIONAL; - } else if (!strcasecmp(var, "local")) { - caller_data.dnis.type = FTDM_TON_SUBSCRIBER_NUMBER; - } else if (!strcasecmp(var, "unknown")) { - caller_data.dnis.type = FTDM_TON_UNKNOWN; - } + if ((var = channel_get_variable(session, var_event, "freetdm_bearer_layer1"))) { + caller_data.bearer_layer1 = (uint8_t)atoi(var); + } + + if ((var = channel_get_variable(session, var_event, "freetdm_screening_ind"))) { + ftdm_set_screening_ind(var, &caller_data.screen); + } + + if ((var = channel_get_variable(session, var_event, "freetdm_presentation_ind"))) { + ftdm_set_presentation_ind(var, &caller_data.pres); + } + + if ((var = channel_get_variable(session, var_event, "freetdm_outbound_ton"))) { + ftdm_set_ton(var, &caller_data.dnis.type); } else { caller_data.dnis.type = outbound_profile->destination_number_ton; } - if ((var = switch_event_get_header(var_event, "freetdm_custom_call_data")) || (var = switch_core_get_variable("freetdm_custom_call_data"))) { + if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) { ftdm_set_string(caller_data.raw_data, var); caller_data.raw_data_len = (uint32_t)strlen(var); } + if (!zstr(dest)) { + ftdm_set_string(caller_data.dnis.digits, dest); + } + caller_data.dnis.plan = outbound_profile->destination_number_numplan; /* blindly copy data from outbound_profile. They will be overwritten @@ -2074,6 +2090,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) switch(sigmsg->event_id) { case FTDM_SIGEVENT_START: { + ftdm_channel_add_var(sigmsg->channel, "screening_ind", ftdm_screening2str(caller_data->screen)); + ftdm_channel_add_var(sigmsg->channel, "presentation_ind", ftdm_presentation2str(caller_data->pres)); + ftdm_enable_channel_dtmf(sigmsg->channel, NULL); return ftdm_channel_from_event(sigmsg, &session); } diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index d91b3bc9e2..52d2557a01 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -36,80 +36,101 @@ #include -FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) { - if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) { - *target = FTDM_NPI_ISDN; - } else if (!strcasecmp(npi_string, "data")) { - *target = FTDM_NPI_DATA; - } else if (!strcasecmp(npi_string, "telex")) { - *target = FTDM_NPI_TELEX; - } else if (!strcasecmp(npi_string, "national")) { - *target = FTDM_NPI_NATIONAL; - } else if (!strcasecmp(npi_string, "private")) { - *target = FTDM_NPI_PRIVATE; - } else if (!strcasecmp(npi_string, "reserved")) { - *target = FTDM_NPI_RESERVED; - } else if (!strcasecmp(npi_string, "unknown")) { - *target = FTDM_NPI_UNKNOWN; - } else { - ftdm_log(FTDM_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string); - *target = FTDM_NPI_UNKNOWN; - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_npi(string); + if (val == FTDM_NPI_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid NPI string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_NPI_UNKNOWN; } - return FTDM_SUCCESS; + *target = val; + return status; } -FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) { - if (!strcasecmp(ton_string, "national")) { - *target = FTDM_TON_NATIONAL; - } else if (!strcasecmp(ton_string, "international")) { - *target = FTDM_TON_INTERNATIONAL; - } else if (!strcasecmp(ton_string, "local")) { - *target = FTDM_TON_SUBSCRIBER_NUMBER; - } else if (!strcasecmp(ton_string, "unknown")) { - *target = FTDM_TON_UNKNOWN; - } else { - ftdm_log(FTDM_LOG_WARNING, "Invalid TON value (%s)\n", ton_string); - *target = FTDM_TON_UNKNOWN; - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_ton(string); + if (val == FTDM_TON_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid TON string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_TON_UNKNOWN; } - return FTDM_SUCCESS; + *target = val; + return status; } -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target) { - if (!strcasecmp(bc_string, "speech")) { - *target = FTDM_BEARER_CAP_SPEECH; - } else if (!strcasecmp(bc_string, "unrestricted-digital")) { - *target = FTDM_BEARER_CAP_64K_UNRESTRICTED; - } else if (!strcasecmp(bc_string, "3.1Khz")) { - *target = FTDM_BEARER_CAP_3_1KHZ_AUDIO; - } else { - ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Capability value (%s)\n", bc_string); - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_bearer_cap(string); + if (val == FTDM_NPI_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer-Capability string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_BEARER_CAP_SPEECH; } - return FTDM_SUCCESS; + + *target = val; + return status; } -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target) { - if (!strcasecmp(bc_string, "v110")) { - *target = FTDM_USER_LAYER1_PROT_V110; - } else if (!strcasecmp(bc_string, "ulaw")) { - *target = FTDM_USER_LAYER1_PROT_ULAW; - } else if (!strcasecmp(bc_string, "alaw")) { - *target =FTDM_USER_LAYER1_PROT_ALAW ; - } else { - ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Layer1 Prot value (%s)\n", bc_string); - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_usr_layer1_prot(string); + if (val == FTDM_USER_LAYER1_PROT_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer Layer 1 Protocol string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_USER_LAYER1_PROT_ULAW; } - return FTDM_SUCCESS; + + *target = val; + return status; } +FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target) +{ + int val; + ftdm_status_t status = FTDM_SUCCESS; -FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number) + val = ftdm_str2ftdm_screening(string); + if (val == FTDM_SCREENING_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid screening indicator string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_SCREENING_NOT_SCREENED; + } + + *target = val; + return status; +} + +FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target) +{ + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_presentation(string); + if (val == FTDM_PRES_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid presentation string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_PRES_ALLOWED; + } + + *target = val; + return status; +} + +FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number) { if (!number) { return FTDM_FAIL; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index ede3ff8fc8..3e48586a4e 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -150,6 +150,24 @@ FTDM_STR2ENUM(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t, CHA FTDM_ENUM_NAMES(SIGNALING_STATUS_NAMES, SIGSTATUS_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t, SIGNALING_STATUS_NAMES, FTDM_SIG_STATE_INVALID) +FTDM_ENUM_NAMES(TON_NAMES, TON_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t, TON_NAMES, FTDM_TON_INVALID) + +FTDM_ENUM_NAMES(NPI_NAMES, NPI_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t, NPI_NAMES, FTDM_NPI_INVALID) + +FTDM_ENUM_NAMES(PRESENTATION_NAMES, PRESENTATION_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t, PRESENTATION_NAMES, FTDM_PRES_INVALID) + +FTDM_ENUM_NAMES(SCREENING_NAMES, SCREENING_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t, SCREENING_NAMES, FTDM_SCREENING_INVALID) + +FTDM_ENUM_NAMES(BEARER_CAP_NAMES, BEARER_CAP_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t, BEARER_CAP_NAMES, FTDM_BEARER_CAP_INVALID) + +FTDM_ENUM_NAMES(USER_LAYER1_PROT_NAMES, USER_LAYER1_PROT_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t, USER_LAYER1_PROT_NAMES, FTDM_USER_LAYER1_PROT_INVALID) + static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name); static const char *cut_path(const char *in) @@ -4822,7 +4840,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t if (sigmsg->channel) { ftdm_mutex_lock(sigmsg->channel->mutex); } - + /* some core things to do on special events */ switch (sigmsg->event_id) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h index 5a3ca76c56..6fbf272d07 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h @@ -58,7 +58,7 @@ typedef struct ftdm_sangoma_boost_trunkgroup { ftdm_size_t size; /* Number of b-channels in group */ unsigned int last_used_index; /* index of last b-channel used */ ftdm_channel_t* ftdmchans[MAX_CHANS_PER_TRUNKGROUP]; - //DAVIDY need to merge congestion timeouts to this struct + //TODO need to merge congestion timeouts to this struct } ftdm_sangoma_boost_trunkgroup_t; #endif diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index c9691e232b..50a01cc0ec 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -55,7 +55,7 @@ ftdm_mutex_t *g_boost_modules_mutex = NULL; ftdm_hash_t *g_boost_modules_hash = NULL; #define MAX_TRUNK_GROUPS 64 -//DAVIDY need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups +//TODO need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups static time_t congestion_timeouts[MAX_TRUNK_GROUPS]; static ftdm_sangoma_boost_trunkgroup_t *g_trunkgroups[MAX_TRUNK_GROUPS]; @@ -2582,17 +2582,17 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span) } else if (!strcasecmp(var, "remote_port")) { remote_port = atoi(val); } else if (!strcasecmp(var, "outbound-called-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.dnis.type); + ftdm_set_ton(val, &span->default_caller_data.dnis.type); } else if (!strcasecmp(var, "outbound-called-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan); + ftdm_set_npi(val, &span->default_caller_data.dnis.plan); } else if (!strcasecmp(var, "outbound-calling-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type); + ftdm_set_ton(val, &span->default_caller_data.cid_num.type); } else if (!strcasecmp(var, "outbound-calling-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan); + ftdm_set_npi(val, &span->default_caller_data.cid_num.plan); } else if (!strcasecmp(var, "outbound-rdnis-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type); + ftdm_set_ton(val, &span->default_caller_data.rdnis.type); } else if (!strcasecmp(var, "outbound-rdnis-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan); + ftdm_set_npi(val, &span->default_caller_data.rdnis.plan); } else if (!sigmod) { snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); FAIL_CONFIG_RETURN(FTDM_FAIL); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 6f5f838590..8831ac4185 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -40,8 +40,8 @@ #include #endif -static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj); +static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj); static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span); static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span); @@ -673,7 +673,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_RINGING: { - sngisdn_snd_alert(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; + sngisdn_snd_alert(ftdmchan, prog_ind); } break; case FTDM_CHANNEL_STATE_PROGRESS: @@ -687,7 +688,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) /* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */ if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) { /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */ - sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; + sngisdn_snd_progress(ftdmchan, prog_ind); } } } @@ -699,7 +701,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) ftdm_span_send_signal(ftdmchan->span, &sigev); } else { /* Send a progress message, indicating: In-band information/pattern available */ - sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_IB_AVAIL); + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_IB_AVAIL}; + sngisdn_snd_progress(ftdmchan, prog_ind); } } break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index a82ed283e1..6957f9925e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -138,17 +138,47 @@ typedef enum { typedef enum { /* Call is not end-to-end ISDN */ - SNGISDN_PROGIND_NETE_ISDN = 1, + SNGISDN_PROGIND_DESCR_NETE_ISDN, /* Destination address is non-ISDN */ - SNGISDN_PROGIND_DEST_NISDN, + SNGISDN_PROGIND_DESCR_DEST_NISDN, /* Origination address is non-ISDN */ - SNGISDN_PROGIND_ORIG_NISDN, + SNGISDN_PROGIND_DESCR_ORIG_NISDN, /* Call has returned to the ISDN */ - SNGISDN_PROGIND_RET_ISDN, + SNGISDN_PROGIND_DESCR_RET_ISDN, /* Interworking as occured and has resulted in a telecommunication service change */ - SNGISDN_PROGIND_SERV_CHANGE, - /* In-band information or an appropriate pattern is now available */ - SNGISDN_PROGIND_IB_AVAIL, + SNGISDN_PROGIND_DESCR_SERV_CHANGE, + /* In-band information or an appropriate pattern is now available */ + SNGISDN_PROGIND_DESCR_IB_AVAIL, + /* Invalid */ + SNGISDN_PROGIND_DESCR_INVALID, +} ftdm_sngisdn_progind_descr_t; +#define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t); + +typedef enum { + /* User */ + SNGISDN_PROGIND_LOC_USER, + /* Private network serving the local user */ + SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR, + /* Public network serving the local user */ + SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR, + /* Transit network */ + SNGISDN_PROGIND_LOC_TRANSIT_NET, + /* Public network serving remote user */ + SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR, + /* Private network serving remote user */ + SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR, + /* Network beyond the interworking point */ + SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW, + /* Invalid */ + SNGISDN_PROGIND_LOC_INVALID, +} ftdm_sngisdn_progind_loc_t; +#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t); + +typedef struct ftdm_sngisdn_prog_ind { + ftdm_sngisdn_progind_loc_t loc; /* location */ + ftdm_sngisdn_progind_descr_t descr; /* description */ } ftdm_sngisdn_progind_t; /* Only timers that can be cancelled are listed here */ @@ -201,6 +231,7 @@ typedef struct sngisdn_span_data { uint8_t facility; int8_t facility_timeout; uint8_t num_local_numbers; + uint8_t ignore_cause_value; uint8_t timer_t3; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; ftdm_sched_t *sched; @@ -376,18 +407,25 @@ void sngisdn_rcv_cc_ind(CcMngmt *status); void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); void sngisdn_rcv_sng_assert(char *message); -ftdm_status_t get_calling_num(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); -ftdm_status_t get_called_num(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); -ftdm_status_t get_redir_num(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); -ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *ftdm, Display *display); -ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *ftdm, UsrUsr *usrUsr); -ftdm_status_t get_facility_ie(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); +ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); +ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb); +ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb); +ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display); +ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr); +ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad); +ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd); +ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); +ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len); -ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); +ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb); +ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb); +ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt); +ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad); +ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind); ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); +ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len); + uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability); uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 657aa5e206..6b4e73ab25 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -34,13 +34,24 @@ #include "ftmod_sangoma_isdn.h" -ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span); -ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span); -ftdm_status_t add_local_number(const char* val, ftdm_span_t *span); +static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span); +static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span); +static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span); +static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target); extern ftdm_sngisdn_data_t g_sngisdn_data; -ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) +static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target) +{ + if (ftdm_true(val)) { + *target = SNGISDN_OPT_TRUE; + } else { + *target = SNGISDN_OPT_FALSE; + } + return FTDM_SUCCESS; +} + +static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; @@ -53,7 +64,7 @@ ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) +static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) { unsigned i; ftdm_iterator_t *chaniter = NULL; @@ -160,7 +171,7 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span) +static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; if (!strcasecmp(signalling, "net") || @@ -190,7 +201,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->min_digits = 8; signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; - signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; + signal_data->facility_ie_decode = SNGISDN_OPT_DEFAULT; + signal_data->ignore_cause_value = SNGISDN_OPT_DEFAULT; signal_data->timer_t3 = 8; signal_data->link_id = span->span_id; @@ -202,20 +214,19 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - - ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan); - ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type); - ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan); - ftdm_span_set_ton("unknown", &span->default_caller_data.cid_num.type); - ftdm_span_set_npi("unknown", &span->default_caller_data.rdnis.plan); - ftdm_span_set_ton("unknown", &span->default_caller_data.rdnis.type); + ftdm_set_npi("unknown", &span->default_caller_data.dnis.plan); + ftdm_set_ton("unknown", &span->default_caller_data.dnis.type); + ftdm_set_npi("unknown", &span->default_caller_data.cid_num.plan); + ftdm_set_ton("unknown", &span->default_caller_data.cid_num.type); + ftdm_set_npi("unknown", &span->default_caller_data.rdnis.plan); + ftdm_set_ton("unknown", &span->default_caller_data.rdnis.type); } else { - ftdm_span_set_npi("e164", &span->default_caller_data.dnis.plan); - ftdm_span_set_ton("national", &span->default_caller_data.dnis.type); - ftdm_span_set_npi("e164", &span->default_caller_data.cid_num.plan); - ftdm_span_set_ton("national", &span->default_caller_data.cid_num.type); - ftdm_span_set_npi("e164", &span->default_caller_data.rdnis.plan); - ftdm_span_set_ton("national", &span->default_caller_data.rdnis.type); + ftdm_set_npi("isdn", &span->default_caller_data.dnis.plan); + ftdm_set_ton("national", &span->default_caller_data.dnis.type); + ftdm_set_npi("isdn", &span->default_caller_data.cid_num.plan); + ftdm_set_ton("national", &span->default_caller_data.cid_num.type); + ftdm_set_npi("isdn", &span->default_caller_data.rdnis.plan); + ftdm_set_ton("national", &span->default_caller_data.rdnis.type); } for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { @@ -247,41 +258,29 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ } else { ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); } - } else if (!strcasecmp(var, "setup arbitration")) { - if (!strcasecmp(val, "yes")) { - signal_data->setup_arb = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->setup_arb = SNGISDN_OPT_FALSE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); - } + } else if (!strcasecmp(var, "setup-arbitration")) { + parse_yesno(var, val, &signal_data->setup_arb); } else if (!strcasecmp(var, "facility")) { - if (!strcasecmp(val, "yes")) { - signal_data->facility = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->facility = SNGISDN_OPT_FALSE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); - } + parse_yesno(var, val, &signal_data->facility); } else if (!strcasecmp(var, "min_digits")) { signal_data->min_digits = atoi(val); } else if (!strcasecmp(var, "outbound-called-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.dnis.type); + ftdm_set_ton(val, &span->default_caller_data.dnis.type); } else if (!strcasecmp(var, "outbound-called-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan); + ftdm_set_npi(val, &span->default_caller_data.dnis.plan); } else if (!strcasecmp(var, "outbound-calling-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type); + ftdm_set_ton(val, &span->default_caller_data.cid_num.type); } else if (!strcasecmp(var, "outbound-calling-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan); + ftdm_set_npi(val, &span->default_caller_data.cid_num.plan); } else if (!strcasecmp(var, "outbound-rdnis-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type); + ftdm_set_ton(val, &span->default_caller_data.rdnis.type); } else if (!strcasecmp(var, "outbound-rdnis-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan); + ftdm_set_npi(val, &span->default_caller_data.rdnis.plan); } else if (!strcasecmp(var, "outbound-bearer_cap")) { - ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); + ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability); } else if (!strcasecmp(var, "outbound-bearer_layer1")) { - ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); - } else if (!strcasecmp(var, "local-number")) { + ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1); + } else if (!strcasecmp(var, "local-number")) { if (add_local_number(val, span) != FTDM_SUCCESS) { return FTDM_FAIL; } @@ -291,13 +290,9 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->facility_timeout = 0; } } else if (!strcasecmp(var, "facility-ie-decode")) { - if (!strcasecmp(val, "yes")) { - signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->facility_ie_decode = SNGISDN_OPT_FALSE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); - } + parse_yesno(var, val, &signal_data->facility_ie_decode); + } else if (!strcasecmp(var, "ignore-cause-value")) { + parse_yesno(var, val, &signal_data->ignore_cause_value); } else { ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index a541a655d8..6bf0c25212 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -127,13 +127,15 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1"); #endif /* Fill in call information */ - get_calling_num(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); - get_called_num(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); - get_redir_num(&ftdmchan->caller_data, &conEvnt->redirNmb); + get_calling_num(ftdmchan, &conEvnt->cgPtyNmb); + get_called_num(ftdmchan, &conEvnt->cdPtyNmb); + get_redir_num(ftdmchan, &conEvnt->redirNmb); + get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad); - if (get_calling_name_from_display(&ftdmchan->caller_data, &conEvnt->display) != FTDM_SUCCESS) { - get_calling_name_from_usr_usr(&ftdmchan->caller_data, &conEvnt->usrUsr); + if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) { + get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr); } + get_prog_ind_ie(ftdmchan, &conEvnt->progInd); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); @@ -148,35 +150,35 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); } } + } - if (conEvnt->facilityStr.eh.pres) { - if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); - } else if (signal_data->facility == SNGISDN_OPT_TRUE) { - /* Verify whether the Caller Name will come in a subsequent FACILITY message */ - uint16_t ret_val; - char retrieved_str[255]; - - ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); - /* - return values for "sng_isdn_retrieve_facility_information_following": - If there will be no information following, or fails to decode IE, returns -1 - If there will be no information following, but current FACILITY IE contains a caller name, returns 0 - If there will be information following, returns 1 - */ + if (conEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + get_facility_ie(ftdmchan, &conEvnt->facilityStr); + } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + /* Verify whether the Caller Name will come in a subsequent FACILITY message */ + uint16_t ret_val; + char retrieved_str[255]; - if (ret_val == 1) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); - /* Launch timer in case we never get a FACILITY msg */ - if (signal_data->facility_timeout) { - ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, - sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); - } - break; - } else if (ret_val == 0) { - strcpy(ftdmchan->caller_data.cid_name, retrieved_str); + ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); + /* + return values for "sng_isdn_retrieve_facility_information_following": + If there will be no information following, or fails to decode IE, returns -1 + If there will be no information following, but current FACILITY IE contains a caller name, returns 0 + If there will be information following, returns 1 + */ + + if (ret_val == 1) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); + /* Launch timer in case we never get a FACILITY msg */ + if (signal_data->facility_timeout) { + ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, + sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); } + break; + } else if (ret_val == 0) { + strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } } } @@ -254,8 +256,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - /* Function does not require any info from conStEvnt struct for now */ - /* CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; */ + CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); @@ -281,6 +282,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_DIALING: + get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); break; case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: @@ -344,9 +346,13 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) suId, suInstId, spInstId, ces); switch(evntType) { + case MI_CALLPROC: case MI_PROGRESS: - if (signal_data->switchtype == SNGISDN_SWITCH_NI2 && - cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) { + case MI_ALERTING: + get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); + + if (signal_data->ignore_cause_value != SNGISDN_OPT_TRUE && + cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) { switch(cnStEvnt->causeDgn[0].causeVal.val) { case 17: /* User Busy */ @@ -371,24 +377,17 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) goto sngisdn_process_cnst_ind_end; } } - /* fall-through */ - case MI_ALERTING: - case MI_CALLPROC: - + switch(ftdmchan->state) { case FTDM_CHANNEL_STATE_DIALING: - if (evntType == MI_CALLPROC) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); - } else if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + case FTDM_CHANNEL_STATE_PROCEED: + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); } - break; case FTDM_CHANNEL_STATE_PROGRESS: - if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } break; @@ -417,7 +416,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits; ftdm_size_t num_digits; - get_called_num(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); + get_called_num(ftdmchan, &cnStEvnt->cdPtyNmb); num_digits = strlen(ftdmchan->caller_data.dnis.digits); if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) { @@ -476,7 +475,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_UP: if (discEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); + get_facility_ie(ftdmchan, &discEvnt->facilityStr); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -573,7 +572,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) if (relEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); + get_facility_ie(ftdmchan, &relEvnt->facilityStr); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -789,7 +788,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) ftdm_sigmsg_t sigev; if (facEvnt->facElmt.facStr.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); + get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 36c6782a97..e91f21f55e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -34,13 +34,12 @@ #include "ftmod_sangoma_isdn.h" -static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prod_ind); - void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { - ConEvnt conEvnt; + ConEvnt conEvnt; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n"); @@ -118,14 +117,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id; } - conEvnt.progInd.eh.pres = PRSNT_NODEF; - conEvnt.progInd.location.pres = PRSNT_NODEF; - conEvnt.progInd.location.val = IN_LOC_USER; - conEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - conEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - conEvnt.progInd.progDesc.pres = PRSNT_NODEF; - conEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */ - if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) { conEvnt.sndCmplt.eh.pres = PRSNT_NODEF; } @@ -135,11 +126,13 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) } ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); - set_called_num(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); - set_calling_num(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); - set_redir_num(&conEvnt.redirNmb, &ftdmchan->caller_data); - set_calling_name(&conEvnt, ftdmchan); + set_called_num(ftdmchan, &conEvnt.cdPtyNmb); + set_calling_num(ftdmchan, &conEvnt.cgPtyNmb); + set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad); + set_redir_num(ftdmchan, &conEvnt.redirNmb); + set_calling_name(ftdmchan, &conEvnt); set_facility_ie(ftdmchan, &conEvnt.facilityStr); + set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -347,15 +340,7 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ } memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - cnStEvnt.progInd.eh.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.val = IN_LOC_USER; - cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - - sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); + set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) { @@ -380,13 +365,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - cnStEvnt.progInd.eh.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.val = IN_LOC_USER; - cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); + set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -398,10 +377,10 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) { - CnStEvnt cnStEvnt; - + CnStEvnt cnStEvnt; sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); @@ -444,14 +423,8 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) cnStEvnt.chanId.chanNmbSlotMap.len = 1; cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id; } - - cnStEvnt.progInd.eh.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.val = IN_LOC_USER; - cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */ + + set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) { @@ -473,7 +446,12 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan) } memset(&facEvnt, 0, sizeof(facEvnt)); - + + set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (ftdm_size_t*)&facEvnt.facElmt.facStr.len); + + facEvnt.facElmt.facStr.val[0] = 0x1C; + facEvnt.facElmt.facStr.val[1] = facEvnt.facElmt.facStr.len; + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) { @@ -619,32 +597,6 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) return; } -static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind) -{ - switch(prog_ind) { - case SNGISDN_PROGIND_NETE_ISDN: - progInd->progDesc.val = IN_PD_NOTETEISDN; - break; - case SNGISDN_PROGIND_DEST_NISDN: - progInd->progDesc.val = IN_PD_DSTNOTISDN; - break; - case SNGISDN_PROGIND_ORIG_NISDN: - progInd->progDesc.val = IN_PD_ORGNOTISDN; - break; - case SNGISDN_PROGIND_RET_ISDN: - progInd->progDesc.val = IN_PD_CALLRET; - break; - case SNGISDN_PROGIND_SERV_CHANGE: - /* Trillium defines do not match ITU-T Q931 Progress descriptions, - indicate a delayed response for now */ - progInd->progDesc.val = IN_PD_DELRESP; - break; - case SNGISDN_PROGIND_IB_AVAIL: - progInd->progDesc.val = IN_PD_IBAVAIL; - break; - } - return; -} /* We received an incoming frame on the d-channel, send data to the stack */ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 4ddb90bbd3..964d06caaf 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -33,6 +33,15 @@ */ #include "ftmod_sangoma_isdn.h" +#define SNGISDN_Q931_FACILITY_IE_ID 0x1C + +/* ftmod_sangoma_isdn specific enum look-up functions */ + +FTDM_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID) + +FTDM_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID) ftdm_status_t sngisdn_check_free_ids(void); @@ -129,7 +138,6 @@ ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) { - if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { @@ -147,8 +155,9 @@ ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) return FTDM_SUCCESS; } -ftdm_status_t get_calling_num(ftdm_caller_data_t *caller_data, CgPtyNmb *cgPtyNmb) +ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (cgPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -176,8 +185,9 @@ ftdm_status_t get_calling_num(ftdm_caller_data_t *caller_data, CgPtyNmb *cgPtyNm return FTDM_SUCCESS; } -ftdm_status_t get_called_num(ftdm_caller_data_t *caller_data, CdPtyNmb *cdPtyNmb) +ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -199,8 +209,9 @@ ftdm_status_t get_called_num(ftdm_caller_data_t *caller_data, CdPtyNmb *cdPtyNmb return FTDM_SUCCESS; } -ftdm_status_t get_redir_num(ftdm_caller_data_t *caller_data, RedirNmb *redirNmb) +ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (redirNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -219,8 +230,9 @@ ftdm_status_t get_redir_num(ftdm_caller_data_t *caller_data, RedirNmb *redirNmb) return FTDM_SUCCESS; } -ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *caller_data, Display *display) +ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (display->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -232,8 +244,9 @@ ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *caller_data, Dis return FTDM_SUCCESS; } -ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *caller_data, UsrUsr *usrUsr) +ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (usrUsr->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -250,26 +263,124 @@ ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *caller_data, Usr return FTDM_SUCCESS; } -ftdm_status_t get_facility_ie(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) +ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) { + char subaddress[100]; + + if (cgPtySad->eh.pres != PRSNT_NODEF) { + return FTDM_FAIL; + } + memset(subaddress, 0, sizeof(subaddress)); + if(cgPtySad->sadInfo.len >= sizeof(subaddress)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%d)\n", cgPtySad->sadInfo.len, sizeof(subaddress)); + cgPtySad->sadInfo.len = sizeof(subaddress)-1; + } + + memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len); + subaddress[cgPtySad->sadInfo.len] = '\0'; + ftdm_channel_add_var(ftdmchan, "isdn.calling_subaddr", subaddress); + return FTDM_SUCCESS; +} + +ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) +{ + if (!facilityStr->eh.pres) { + return FTDM_FAIL; + } + + return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len); +} + +ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (data_len > sizeof(caller_data->raw_data)-2) { ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n"); return FTDM_FAIL; } - + memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data)); /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */ - caller_data->raw_data[0] = 0x1C; + caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID; caller_data->raw_data[1] = data_len; memcpy(&caller_data->raw_data[2], data, data_len); caller_data->raw_data_len = data_len+2; - return FTDM_SUCCESS; } -ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *caller_data) +ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd) { + uint8_t val; + if (!progInd->eh.pres) { + return FTDM_FAIL; + } + + if (progInd->progDesc.pres) { + switch (progInd->progDesc.val) { + case IN_PD_NOTETEISDN: + val = SNGISDN_PROGIND_DESCR_NETE_ISDN; + break; + case IN_PD_DSTNOTISDN: + val = SNGISDN_PROGIND_DESCR_DEST_NISDN; + break; + case IN_PD_ORGNOTISDN: + val = SNGISDN_PROGIND_DESCR_ORIG_NISDN; + break; + case IN_PD_CALLRET: + val = SNGISDN_PROGIND_DESCR_RET_ISDN; + break; + case IN_PD_DELRESP: + val = SNGISDN_PROGIND_DESCR_SERV_CHANGE; + break; + case IN_PD_IBAVAIL: + val = SNGISDN_PROGIND_DESCR_IB_AVAIL; + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Description (%d)\n", progInd->progDesc.val); + val = SNGISDN_PROGIND_DESCR_INVALID; + break; + } + ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val)); + } + + if (progInd->location.pres) { + switch (progInd->location.val) { + case IN_LOC_USER: + val = SNGISDN_PROGIND_LOC_USER; + break; + case IN_LOC_PRIVNETLU: + val = SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR; + break; + case IN_LOC_PUBNETLU: + val = SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR; + break; + case IN_LOC_TRANNET: + val = SNGISDN_PROGIND_LOC_TRANSIT_NET; + break; + case IN_LOC_PUBNETRU: + val = SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR; + break; + case IN_LOC_PRIVNETRU: + val = SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR; + break; + case IN_LOC_NETINTER: + val = SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW; + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Location (%d)", progInd->location.val); + val = SNGISDN_PROGIND_LOC_INVALID; + break; + } + ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val)); + } + return FTDM_SUCCESS; +} + + +ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; uint8_t len = strlen(caller_data->cid_num.digits); if (!len) { return FTDM_SUCCESS; @@ -296,9 +407,11 @@ ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *caller_dat return FTDM_SUCCESS; } -ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *caller_data) +ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; uint8_t len = strlen(caller_data->dnis.digits); + if (!len) { return FTDM_SUCCESS; } @@ -326,8 +439,9 @@ ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *caller_data return FTDM_SUCCESS; } -ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *caller_data) +ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; uint8_t len = strlen(caller_data->rdnis.digits); if (!len) { return FTDM_SUCCESS; @@ -358,7 +472,7 @@ ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *caller_data) } -ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt) { uint8_t len; ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; @@ -411,20 +525,139 @@ ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) return FTDM_SUCCESS; } +ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) +{ + const char* clg_subaddr = NULL; + clg_subaddr = ftdm_channel_get_var(ftdmchan, "isdn.calling_subaddr"); + if ((clg_subaddr != NULL) && (*clg_subaddr)) { + unsigned len = strlen (clg_subaddr); + cgPtySad->eh.pres = PRSNT_NODEF; + cgPtySad->typeSad.pres = 1; + cgPtySad->typeSad.val = 0; /* NSAP */ + cgPtySad->oddEvenInd.pres = 1; + cgPtySad->oddEvenInd.val = 0; + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Calling Party Subaddress:%s\n", clg_subaddr); + cgPtySad->sadInfo.pres = 1; + cgPtySad->sadInfo.len = len; + memcpy(cgPtySad->sadInfo.val, clg_subaddr, len); + } + return FTDM_SUCCESS; +} + + ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) { - const char *facility_str = NULL; - - facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); - if (facility_str) { + ftdm_status_t status; + status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (ftdm_size_t*)&facilityStr->facilityStr.len); + if (status == FTDM_SUCCESS) { facilityStr->eh.pres = PRSNT_NODEF; - facilityStr->facilityStr.len = strlen(facility_str); - memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); - return FTDM_SUCCESS; + facilityStr->facilityStr.pres = PRSNT_NODEF; } + return status; +} + +ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; + + if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) { + + *data_len = caller_data->raw_data[1]; + memcpy(data, &caller_data->raw_data[2], *data_len); + return FTDM_SUCCESS; + } return FTDM_FAIL; } +ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind) +{ + const char *str = NULL; + int descr = prog_ind.descr; + int loc = prog_ind.loc; + + str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.descr"); + if (str && *str) { + /* User wants to override progress indicator */ + descr = ftdm_str2ftdm_sngisdn_progind_descr(str); + } + + if (descr == SNGISDN_PROGIND_DESCR_INVALID) { + /* User does not want to send progress indicator */ + return FTDM_SUCCESS; + } + + str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.loc"); + if (str && *str) { + loc = ftdm_str2ftdm_sngisdn_progind_loc(str); + } + if (loc == SNGISDN_PROGIND_LOC_INVALID) { + loc = SNGISDN_PROGIND_LOC_USER; + } + + progInd->eh.pres = PRSNT_NODEF; + progInd->codeStand0.pres = PRSNT_NODEF; + progInd->codeStand0.val = IN_CSTD_CCITT; + + progInd->progDesc.pres = PRSNT_NODEF; + switch(descr) { + case SNGISDN_PROGIND_DESCR_NETE_ISDN: + progInd->progDesc.val = IN_PD_NOTETEISDN; + break; + case SNGISDN_PROGIND_DESCR_DEST_NISDN: + progInd->progDesc.val = IN_PD_DSTNOTISDN; + break; + case SNGISDN_PROGIND_DESCR_ORIG_NISDN: + progInd->progDesc.val = IN_PD_ORGNOTISDN; + break; + case SNGISDN_PROGIND_DESCR_RET_ISDN: + progInd->progDesc.val = IN_PD_CALLRET; + break; + case SNGISDN_PROGIND_DESCR_SERV_CHANGE: + /* Trillium defines do not match ITU-T Q931 Progress descriptions, + indicate a delayed response for now */ + progInd->progDesc.val = IN_PD_DELRESP; + break; + case SNGISDN_PROGIND_DESCR_IB_AVAIL: + progInd->progDesc.val = IN_PD_IBAVAIL; + break; + default: + ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind description:%d\n", descr); + progInd->progDesc.val = IN_PD_NOTETEISDN; + break; + } + + progInd->location.pres = PRSNT_NODEF; + switch (loc) { + case SNGISDN_PROGIND_LOC_USER: + progInd->location.val = IN_LOC_USER; + break; + case SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR: + progInd->location.val = IN_LOC_PRIVNETLU; + break; + case SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR: + progInd->location.val = IN_LOC_PUBNETLU; + break; + case SNGISDN_PROGIND_LOC_TRANSIT_NET: + progInd->location.val = IN_LOC_TRANNET; + break; + case SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR: + progInd->location.val = IN_LOC_PUBNETRU; + break; + case SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR: + progInd->location.val = IN_LOC_PRIVNETRU; + break; + case SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW: + progInd->location.val = IN_LOC_NETINTER; + break; + default: + ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind location:%d\n", loc); + progInd->location.val = IN_PD_NOTETEISDN; + } + return FTDM_SUCCESS; +} + + void sngisdn_t3_timeout(void* p_sngisdn_info) { sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; @@ -581,13 +814,12 @@ uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability) switch(bearer_capability) { case FTDM_BEARER_CAP_SPEECH: return IN_ITC_SPEECH; - case FTDM_BEARER_CAP_64K_UNRESTRICTED: return IN_ITC_UNRDIG; - case FTDM_BEARER_CAP_3_1KHZ_AUDIO: return IN_ITC_A31KHZ; - + case FTDM_BEARER_CAP_INVALID: + return IN_ITC_SPEECH; /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ } return FTDM_BEARER_CAP_SPEECH; @@ -598,13 +830,12 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_pr switch(layer1_prot) { case FTDM_USER_LAYER1_PROT_V110: return IN_UIL1_CCITTV110; - case FTDM_USER_LAYER1_PROT_ULAW: return IN_UIL1_G711ULAW; - case FTDM_USER_LAYER1_PROT_ALAW: return IN_UIL1_G711ALAW; - + case FTDM_USER_LAYER1_PROT_INVALID: + return IN_UIL1_G711ULAW; /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ } return IN_UIL1_G711ULAW; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c index 624d35c147..e5167164b3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c @@ -613,6 +613,21 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset return 0; break; case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS: + { + uint8_t type; + uint8_t currentOct, j=0; + char calling_subaddr_string[82]; + memset(calling_subaddr_string, 0, sizeof(calling_subaddr_string)); + type = get_bits(OCTET(3),5,7); + currentOct = 3; + while(currentOct++ <= len+1) { + calling_subaddr_string[j++]=ia5[get_bits(OCTET(currentOct),1,4)][get_bits(OCTET(currentOct),5,8)]; + } + calling_subaddr_string[j++]='\0'; + *str_len += sprintf(&str[*str_len], "%s (l:%d) type:%s(%d) \n", + calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type); + } + break; case PROT_Q931_IE_REDIRECTION_NUMBER: case PROT_Q931_IE_NOTIFICATION_IND: case PROT_Q931_IE_DATE_TIME: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h index d210c50db9..f054de9377 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h @@ -544,5 +544,11 @@ struct code2str dcodQ931GenDigitsTypeTable[] = { {-1, "Invalid"}, }; +struct code2str dcodQ931TypeOfSubaddressTable[] = { + { 0x00, "NSAP"}, + { 0x02, "User-specified"}, + { -1, "Invalid"}, +}; + #endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */ diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 014eeef852..45254e817f 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -41,6 +41,7 @@ #include "ftdm_declare.h" +#include "ftdm_call_utils.h" /*! \brief Max number of channels per physical span */ #define FTDM_MAX_CHANNELS_PHYSICAL_SPAN 32 @@ -62,23 +63,6 @@ #define FTDM_INVALID_INT_PARM 0xFF -/*! \brief FreeTDM APIs possible return codes */ -typedef enum { - FTDM_SUCCESS, /*!< Success */ - FTDM_FAIL, /*!< Failure, generic error return code, use ftdm_channel_get_last_error or ftdm_span_get_last_error for details */ - FTDM_MEMERR, /*!< Memory error, most likely allocation failure */ - FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/ - FTDM_NOTIMPL, /*!< Operation not implemented */ - FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */ - FTDM_EINVAL /*!< Invalid argument */ -} ftdm_status_t; - -/*! \brief FreeTDM bool type. */ -typedef enum { - FTDM_FALSE, - FTDM_TRUE -} ftdm_bool_t; - /*! \brief Thread/Mutex OS abstraction API. */ #include "ftdm_os.h" @@ -220,8 +204,10 @@ typedef enum { FTDM_TON_SUBSCRIBER_NUMBER, FTDM_TON_ABBREVIATED_NUMBER, FTDM_TON_RESERVED, - FTDM_TON_INVALID = 255 + FTDM_TON_INVALID } ftdm_ton_t; +#define TON_STRINGS "unknown", "international", "national", "network-specific", "subscriber-number", "abbreviated-number", "reserved", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t) /*! Numbering Plan Identification (NPI) */ typedef enum { @@ -232,8 +218,52 @@ typedef enum { FTDM_NPI_NATIONAL = 8, FTDM_NPI_PRIVATE = 9, FTDM_NPI_RESERVED = 10, - FTDM_NPI_INVALID = 255 + FTDM_NPI_INVALID } ftdm_npi_t; +#define NPI_STRINGS "unknown", "ISDN", "data", "telex", "national", "private", "reserved", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t) + +/*! Presentation Ind */ +typedef enum { + FTDM_PRES_ALLOWED, + FTDM_PRES_RESTRICTED, + FTDM_PRES_NOT_AVAILABLE, + FTDM_PRES_RESERVED, + FTDM_PRES_INVALID +} ftdm_presentation_t; +#define PRESENTATION_STRINGS "presentation-allowed", "presentation-restricted", "number-not-available", "reserved", "Invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t) + +/*! Screening Ind */ +typedef enum { + FTDM_SCREENING_NOT_SCREENED, + FTDM_SCREENING_VERIFIED_PASSED, + FTDM_SCREENING_VERIFIED_FAILED, + FTDM_SCREENING_NETWORK_PROVIDED, + FTDM_SCREENING_INVALID +} ftdm_screening_t; +#define SCREENING_STRINGS "user-provided-not-screened", "user-provided-verified-and-passed", "user-provided-verified-and-failed", "network-provided", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t) + +/*! \brief bearer capability */ +typedef enum { + FTDM_BEARER_CAP_SPEECH = 0x00, + FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, + FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03, + FTDM_BEARER_CAP_INVALID +} ftdm_bearer_cap_t; +#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "3.1-Khz-audio", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t) + +/*! \brief user information layer 1 protocol */ +typedef enum { + FTDM_USER_LAYER1_PROT_V110 = 0x01, + FTDM_USER_LAYER1_PROT_ULAW = 0x02, + FTDM_USER_LAYER1_PROT_ALAW = 0x03, + FTDM_USER_LAYER1_PROT_INVALID +} ftdm_user_layer1_prot_t; +#define USER_LAYER1_PROT_STRINGS "V.110", "u-law", "a-law", "Invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t) /*! \brief Number abstraction */ typedef struct { @@ -242,20 +272,6 @@ typedef struct { uint8_t plan; } ftdm_number_t; -/*! \brief bearer capability */ -typedef enum { - FTDM_BEARER_CAP_SPEECH = 0x00, - FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, - FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03 -} ftdm_bearer_cap_t; - -/*! \brief user information layer 1 protocol */ -typedef enum { - FTDM_USER_LAYER1_PROT_V110 = 0x01, - FTDM_USER_LAYER1_PROT_ULAW = 0x02, - FTDM_USER_LAYER1_PROT_ALAW = 0x03, -} ftdm_user_layer1_prot_t; - /*! \brief Caller information */ typedef struct ftdm_caller_data { char cid_date[8]; /*!< Caller ID date */ diff --git a/libs/freetdm/src/include/ftdm_call_utils.h b/libs/freetdm/src/include/ftdm_call_utils.h new file mode 100644 index 0000000000..835a5c6cdc --- /dev/null +++ b/libs/freetdm/src/include/ftdm_call_utils.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * David Yat Sin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FTDM_CALL_UTILS_H__ +#define __FTDM_CALL_UTILS_H__ + +/*! + * \brief Set the Numbering Plan Identification from a string + * + * \param npi_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *npi_string, uint8_t *target); + + +/*! + * \brief Set the Type of number from a string + * + * \param ton_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *ton_string, uint8_t *target); + +/*! + * \brief Set the Bearer Capability from a string + * + * \param bc_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *bc_string, uint8_t *target); + +/*! + * \brief Set the Bearer Capability - Layer 1 from a string + * + * \param bc_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *bc_string, uint8_t *target); + +/*! + * \brief Set the Screening Ind from a string + * + * \param screen_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target); + + +/*! + * \brief Set the Presentation Ind from an enum + * + * \param screen_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target); + + +/*! + * \brief Checks whether a string contains only numbers + * + * \param number string value + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number); + +#endif /* __FTDM_CALL_UTILS_H__ */ + diff --git a/libs/freetdm/src/include/ftdm_declare.h b/libs/freetdm/src/include/ftdm_declare.h index ab3b5c8966..4aba703f28 100644 --- a/libs/freetdm/src/include/ftdm_declare.h +++ b/libs/freetdm/src/include/ftdm_declare.h @@ -171,6 +171,23 @@ typedef int ftdm_socket_t; #include #endif +/*! \brief FreeTDM APIs possible return codes */ +typedef enum { + FTDM_SUCCESS, /*!< Success */ + FTDM_FAIL, /*!< Failure, generic error return code, use ftdm_channel_get_last_error or ftdm_span_get_last_error for details */ + FTDM_MEMERR, /*!< Memory error, most likely allocation failure */ + FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/ + FTDM_NOTIMPL, /*!< Operation not implemented */ + FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */ + FTDM_EINVAL /*!< Invalid argument */ +} ftdm_status_t; + +/*! \brief FreeTDM bool type. */ +typedef enum { + FTDM_FALSE, + FTDM_TRUE +} ftdm_bool_t; + /*! * \brief FreeTDM channel. * This is the basic data structure used to place calls and I/O operations diff --git a/libs/freetdm/src/include/private/ftdm_call_utils.h b/libs/freetdm/src/include/private/ftdm_call_utils.h deleted file mode 100644 index 782abde927..0000000000 --- a/libs/freetdm/src/include/private/ftdm_call_utils.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __FTDM_CALL_UTILS_H__ -#define __FTDM_CALL_UTILS_H__ - -#include "freetdm.h" - -FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target); -FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target); -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target); -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target); -FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number); - -#endif /* __FTDM_CALL_UTILS_H__ */ - From 3934682e9b616f9117d70f05965e8c5f3bbc3269 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Tue, 30 Nov 2010 16:01:08 -0200 Subject: [PATCH 78/97] freetdm: ftmod_r2 - rename ftdm_started flag to ftdm_call_started --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index ffc39e8884..b98f7db99c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -68,7 +68,7 @@ typedef struct ftdm_r2_call_t { int accepted:1; int answer_pending:1; int disconnect_rcvd:1; - int ftdm_started:1; + int ftdm_call_started:1; int protocol_error:1; ftdm_channel_state_t chanstate; ftdm_size_t dnis_index; @@ -357,7 +357,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) } ft_r2_clean_call(ftdmchan->call_data); - R2CALL(ftdmchan)->ftdm_started = 1; + R2CALL(ftdmchan)->ftdm_call_started = 1; R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); @@ -503,7 +503,7 @@ static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_discon } /* if the call has not been started yet we must go to HANGUP right here */ - if (!R2CALL(ftdmchan)->ftdm_started) { + if (!R2CALL(ftdmchan)->ftdm_call_started) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); return; } @@ -567,7 +567,7 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err R2CALL(ftdmchan)->disconnect_rcvd = 1; R2CALL(ftdmchan)->protocol_error = 1; - if (!R2CALL(ftdmchan)->ftdm_started) { + if (!R2CALL(ftdmchan)->ftdm_call_started) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); return; } @@ -1260,7 +1260,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); break; } - R2CALL(ftdmchan)->ftdm_started = 1; + R2CALL(ftdmchan)->ftdm_call_started = 1; break; From e3b070c88fa02406890b35e554f5c0ac1ad6aa36 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 13:21:47 -0500 Subject: [PATCH 79/97] freetdm: ftmod_wanpipe - do not test 80% tx queue full --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index fbb827e27f..0ac628a260 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -791,16 +791,7 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; - if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } - + /* we don't test for 80% full in tx since is typically full for voice channels, should we test tx 80% full for D-channels? */ if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.tx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.tx.queue_size); From 1f329ad521926c5af22a710a7e473daec0177f3e Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 13:28:14 -0500 Subject: [PATCH 80/97] set the right configs in sync with mainstream --- conf/autoload_configs/callcenter.conf.xml | 1 + conf/autoload_configs/erlang_event.conf.xml | 9 ++ conf/autoload_configs/modules.conf.xml | 96 +++++++++++++++++++++ conf/autoload_configs/switch.conf.xml | 6 ++ conf/autoload_configs/voicemail.conf.xml | 7 +- conf/sip_profiles/internal.xml | 20 +++++ conf/skinny_profiles/internal.xml | 2 +- conf/vars.xml | 2 +- 8 files changed, 138 insertions(+), 5 deletions(-) diff --git a/conf/autoload_configs/callcenter.conf.xml b/conf/autoload_configs/callcenter.conf.xml index 9140193b22..a069413ac6 100644 --- a/conf/autoload_configs/callcenter.conf.xml +++ b/conf/autoload_configs/callcenter.conf.xml @@ -13,6 +13,7 @@ + diff --git a/conf/autoload_configs/erlang_event.conf.xml b/conf/autoload_configs/erlang_event.conf.xml index ec14e21a25..62deb84f67 100644 --- a/conf/autoload_configs/erlang_event.conf.xml +++ b/conf/autoload_configs/erlang_event.conf.xml @@ -2,7 +2,16 @@ + + + + + diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 90d66f5798..f5627fe965 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -1,17 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index 7a68a7f2bd..896dd0e712 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -15,6 +15,11 @@ + + + + + @@ -81,6 +86,7 @@ + diff --git a/conf/autoload_configs/voicemail.conf.xml b/conf/autoload_configs/voicemail.conf.xml index 14ad98b41c..06bd6f6dca 100644 --- a/conf/autoload_configs/voicemail.conf.xml +++ b/conf/autoload_configs/voicemail.conf.xml @@ -33,9 +33,10 @@ - - - + --> + + + diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 69b0d15be4..3e756a85c0 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -42,6 +42,26 @@ + + + + + + diff --git a/conf/skinny_profiles/internal.xml b/conf/skinny_profiles/internal.xml index 5feac1ffbf..52da89741d 100644 --- a/conf/skinny_profiles/internal.xml +++ b/conf/skinny_profiles/internal.xml @@ -16,7 +16,7 @@ - + diff --git a/conf/vars.xml b/conf/vars.xml index c638a80582..fced2ef139 100644 --- a/conf/vars.xml +++ b/conf/vars.xml @@ -195,7 +195,7 @@ - + From cefedc0da9a8248cbebde655ecc73701d7cfcd1d Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 13:30:37 -0500 Subject: [PATCH 81/97] sync .sln file with mainstream, ppl stop blindly using git commit -a! --- Freeswitch.2008.sln | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 4ffd66abac..01a4cf43c1 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -36,6 +36,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Default", "Default", "{3B08FEFD-4D3D-4C16-BA94-EE83509E32A0}" ProjectSection(SolutionItems) = preProject conf\freeswitch.xml = conf\freeswitch.xml + conf\vars.xml = conf\vars.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Release", "Release", "{7BFD517E-7F8F-4A40-A78E-8D3632738227}" @@ -56,6 +57,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Build System", "_Build Sys bootstrap.sh = bootstrap.sh build\buildlib.sh = build\buildlib.sh configure.in = configure.in + Makefile.am = Makefile.am build\modmake.rules.in = build\modmake.rules.in build\modules.conf.in = build\modules.conf.in libs\win32\util.vbs = libs\win32\util.vbs @@ -90,12 +92,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa conf\autoload_configs\limit.conf.xml = conf\autoload_configs\limit.conf.xml conf\autoload_configs\local_stream.conf.xml = conf\autoload_configs\local_stream.conf.xml conf\autoload_configs\logfile.conf.xml = conf\autoload_configs\logfile.conf.xml + conf\autoload_configs\modules.conf.xml = conf\autoload_configs\modules.conf.xml conf\autoload_configs\openmrcp.conf.xml = conf\autoload_configs\openmrcp.conf.xml conf\autoload_configs\portaudio.conf.xml = conf\autoload_configs\portaudio.conf.xml conf\autoload_configs\rss.conf.xml = conf\autoload_configs\rss.conf.xml conf\autoload_configs\sofia.conf.xml = conf\autoload_configs\sofia.conf.xml conf\autoload_configs\spidermonkey.conf.xml = conf\autoload_configs\spidermonkey.conf.xml + conf\autoload_configs\switch.conf.xml = conf\autoload_configs\switch.conf.xml conf\autoload_configs\syslog.conf.xml = conf\autoload_configs\syslog.conf.xml + conf\autoload_configs\voicemail.conf.xml = conf\autoload_configs\voicemail.conf.xml conf\autoload_configs\wanpipe.conf.xml = conf\autoload_configs\wanpipe.conf.xml conf\autoload_configs\woomera.conf.xml = conf\autoload_configs\woomera.conf.xml conf\autoload_configs\xml_cdr.conf.xml = conf\autoload_configs\xml_cdr.conf.xml @@ -106,6 +111,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{C7E2382E-2C22-4D18-BF93-80C6A1FFA7AC}" ProjectSection(SolutionItems) = preProject + conf\dialplan\default.xml = conf\dialplan\default.xml conf\dialplan\public.xml = conf\dialplan\public.xml EndProjectSection EndProject @@ -117,6 +123,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sip_profiles", "sip_profiles", "{8E2E8798-8B6F-4A55-8E4F-4E6FDE40ED26}" ProjectSection(SolutionItems) = preProject conf\sip_profiles\external.xml = conf\sip_profiles\external.xml + conf\sip_profiles\internal.xml = conf\sip_profiles\internal.xml conf\sip_profiles\nat.xml = conf\sip_profiles\nat.xml EndProjectSection EndProject @@ -301,6 +308,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{23874F4B-C0AF-4587-9F7E-DB0F06DE8CB4}" + ProjectSection(SolutionItems) = preProject + conf\dialplan\default.xml = conf\dialplan\default.xml + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "directory", "directory", "{19ED97F6-30D8-4FCE-AE1D-8B7FCB170D40}" ProjectSection(SolutionItems) = preProject @@ -1261,15 +1271,15 @@ Global {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|Win32.Build.0 = Release|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.Build.0 = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.Build.0 = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.Build.0 = Release|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.Build.0 = Debug|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.Build.0 = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.Build.0 = Release|x64 From c4369fc84dc00348169f0e7adc9a0169d864ac96 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 15:34:22 -0600 Subject: [PATCH 82/97] add uuid_fileman : <-- same vals as the callbacks in js and lua to control the currently playing file of a channel from the cli or ESL (for the people who were ignoring me on the conference call so I decided to implement it instead of try to explain it ) --- src/include/private/switch_core_pvt.h | 1 + src/include/switch_core.h | 5 + src/include/switch_ivr.h | 5 + .../applications/mod_commands/mod_commands.c | 43 +++++++ src/switch_core_rwlock.c | 40 ++++++ src/switch_core_session.c | 1 + src/switch_cpp.cpp | 115 +---------------- src/switch_ivr.c | 118 ++++++++++++++++++ src/switch_ivr_play_say.c | 44 +++++++ 9 files changed, 258 insertions(+), 114 deletions(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 3df9001b0c..13410a00ae 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -135,6 +135,7 @@ struct switch_core_session { switch_mutex_t *frame_read_mutex; switch_thread_rwlock_t *rwlock; + switch_thread_rwlock_t *io_rwlock; void *streams[SWITCH_MAX_STREAMS]; int stream_count; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 33df7e31dd..840a06c204 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -354,6 +354,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void); ///\ingroup core1 ///\{ + +SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session); + #ifdef SWITCH_DEBUG_RWLOCKS SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(_In_ switch_core_session_t *session, const char *file, const char *func, int line); #endif diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 249ac63a58..d277bd030f 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -874,6 +874,11 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_set_input_timeout_ms(switch_ivr_dmachin SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear_realm(switch_ivr_dmachine_t *dmachine, const char *realm); SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachine_t *dmachine, const char *realm); + +SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh); +SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh); +SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp); + /** @} */ SWITCH_END_EXTERN_C diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index ba4b6d310d..c7edfd5420 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -3968,6 +3968,47 @@ SWITCH_STANDARD_API(uuid_getvar_function) return SWITCH_STATUS_SUCCESS; } + +#define FILEMAN_SYNTAX " :" +SWITCH_STANDARD_API(uuid_fileman_function) +{ + switch_core_session_t *psession = NULL; + char *mycmd = NULL, *argv[4] = { 0 }; + int argc = 0; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + if (argc >= 2 && !zstr(argv[0])) { + char *uuid = argv[0]; + char *cmd = argv[1]; + + if ((psession = switch_core_session_locate(uuid))) { + switch_channel_t *channel; + switch_file_handle_t *fh = NULL; + + channel = switch_core_session_get_channel(psession); + + if (switch_ivr_get_file_handle(psession, &fh) == SWITCH_STATUS_SUCCESS) { + switch_ivr_process_fh(psession, cmd, fh); + switch_ivr_release_file_handle(psession, &fh); + } + + switch_core_session_rwunlock(psession); + + } else { + stream->write_function(stream, "-ERR No Such Channel!\n"); + } + goto done; + } + } + + stream->write_function(stream, "-USAGE: %s\n", GETVAR_SYNTAX); + + done: + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + #define UUID_SEND_DTMF_SYNTAX " " SWITCH_STANDARD_API(uuid_send_dtmf_function) { @@ -4674,6 +4715,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_display", "change display", uuid_display_function, DISPLAY_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_dump", "uuid_dump", uuid_dump_function, DUMP_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_exists", "see if a uuid exists", uuid_exists_function, EXISTS_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_fileman", "uuid_fileman", uuid_fileman_function, FILEMAN_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, ""); SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX); @@ -4785,6 +4827,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_display ::console::list_uuid"); switch_console_set_complete("add uuid_dump ::console::list_uuid"); switch_console_set_complete("add uuid_exists ::console::list_uuid"); + switch_console_set_complete("add uuid_fileman ::console::list_uuid"); switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid"); switch_console_set_complete("add uuid_getvar ::console::list_uuid"); switch_console_set_complete("add uuid_hold ::console::list_uuid"); diff --git a/src/switch_core_rwlock.c b/src/switch_core_rwlock.c index 4285491dc1..57168d9a29 100644 --- a/src/switch_core_rwlock.c +++ b/src/switch_core_rwlock.c @@ -36,6 +36,46 @@ #include "private/switch_core_pvt.h" +SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (session->io_rwlock) { + if (switch_thread_rwlock_tryrdlock(session->io_rwlock) == SWITCH_STATUS_SUCCESS) { + status = SWITCH_STATUS_SUCCESS; + } + } + + return status; +} + +SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (session->io_rwlock) { + switch_thread_rwlock_wrlock(session->io_rwlock); + status = SWITCH_STATUS_SUCCESS; + } + + return status; +} + + +SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (session->io_rwlock) { + switch_thread_rwlock_unlock(session->io_rwlock); + status = SWITCH_STATUS_SUCCESS; + } + + return status; +} + + + #ifdef SWITCH_DEBUG_RWLOCKS SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(switch_core_session_t *session, const char *file, const char *func, int line) #else diff --git a/src/switch_core_session.c b/src/switch_core_session.c index a84bfabaf0..fc7648155a 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1667,6 +1667,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_ switch_thread_rwlock_create(&session->bug_rwlock, session->pool); switch_thread_cond_create(&session->cond, session->pool); switch_thread_rwlock_create(&session->rwlock, session->pool); + switch_thread_rwlock_create(&session->io_rwlock, session->pool); switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool); switch_queue_create(&session->event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool); switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool); diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index 469ae18c4b..40462db567 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -1269,120 +1269,7 @@ SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *resul this_check(SWITCH_STATUS_FALSE); sanity_check(SWITCH_STATUS_FALSE); - if (zstr(result)) { - return SWITCH_STATUS_SUCCESS; - } - - if (fhp) { - if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { - return SWITCH_STATUS_FALSE; - } - - if (!strncasecmp(result, "speed", 5)) { - char *p; - - if ((p = strchr(result, ':'))) { - p++; - if (*p == '+' || *p == '-') { - int step; - if (!(step = atoi(p))) { - step = 1; - } - fhp->speed += step; - } else { - int speed = atoi(p); - fhp->speed = speed; - } - return SWITCH_STATUS_SUCCESS; - } - - return SWITCH_STATUS_FALSE; - - } else if (!strncasecmp(result, "volume", 6)) { - char *p; - - if ((p = strchr(result, ':'))) { - p++; - if (*p == '+' || *p == '-') { - int step; - if (!(step = atoi(p))) { - step = 1; - } - fhp->vol += step; - } else { - int vol = atoi(p); - fhp->vol = vol; - } - return SWITCH_STATUS_SUCCESS; - } - - if (fhp->vol) { - switch_normalize_volume(fhp->vol); - } - - return SWITCH_STATUS_FALSE; - } else if (!strcasecmp(result, "pause")) { - if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { - switch_clear_flag(fhp, SWITCH_FILE_PAUSE); - } else { - switch_set_flag(fhp, SWITCH_FILE_PAUSE); - } - return SWITCH_STATUS_SUCCESS; - } else if (!strcasecmp(result, "stop")) { - return SWITCH_STATUS_FALSE; - } else if (!strcasecmp(result, "truncate")) { - switch_core_file_truncate(fhp, 0); - } else if (!strcasecmp(result, "restart")) { - unsigned int pos = 0; - fhp->speed = 0; - switch_core_file_seek(fhp, &pos, 0, SEEK_SET); - return SWITCH_STATUS_SUCCESS; - } else if (!strncasecmp(result, "seek", 4)) { - switch_codec_t *codec; - unsigned int samps = 0; - unsigned int pos = 0; - char *p; - codec = switch_core_session_get_read_codec(session); - - if ((p = strchr(result, ':'))) { - p++; - if (*p == '+' || *p == '-') { - int step; - int32_t target; - if (!(step = atoi(p))) { - step = 1000; - } - - samps = step * (codec->implementation->samples_per_second / 1000); - target = (int32_t)fhp->pos + samps; - - if (target < 0) { - target = 0; - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); - switch_core_file_seek(fhp, &pos, target, SEEK_SET); - - } else { - samps = atoi(p) * (codec->implementation->samples_per_second / 1000); - if (samps < 0) { - samps = 0; - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); - switch_core_file_seek(fhp, &pos, samps, SEEK_SET); - } - } - - return SWITCH_STATUS_SUCCESS; - } - } - - if (!strcmp(result, "true") || !strcmp(result, "undefined")) { - return SWITCH_STATUS_SUCCESS; - } - - - return SWITCH_STATUS_FALSE; + return switch_ivr_process_fh(session, result, fhp); } /* For Emacs: diff --git a/src/switch_ivr.c b/src/switch_ivr.c index df88451a3d..00917adc34 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2563,6 +2563,124 @@ SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid) return exists; } +SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp) +{ + if (zstr(cmd)) { + return SWITCH_STATUS_SUCCESS; + } + + if (fhp) { + if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { + return SWITCH_STATUS_FALSE; + } + + if (!strncasecmp(cmd, "speed", 5)) { + char *p; + + if ((p = strchr(cmd, ':'))) { + p++; + if (*p == '+' || *p == '-') { + int step; + if (!(step = atoi(p))) { + step = 1; + } + fhp->speed += step; + } else { + int speed = atoi(p); + fhp->speed = speed; + } + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; + + } else if (!strncasecmp(cmd, "volume", 6)) { + char *p; + + if ((p = strchr(cmd, ':'))) { + p++; + if (*p == '+' || *p == '-') { + int step; + if (!(step = atoi(p))) { + step = 1; + } + fhp->vol += step; + } else { + int vol = atoi(p); + fhp->vol = vol; + } + return SWITCH_STATUS_SUCCESS; + } + + if (fhp->vol) { + switch_normalize_volume(fhp->vol); + } + + return SWITCH_STATUS_FALSE; + } else if (!strcasecmp(cmd, "pause")) { + if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { + switch_clear_flag(fhp, SWITCH_FILE_PAUSE); + } else { + switch_set_flag(fhp, SWITCH_FILE_PAUSE); + } + return SWITCH_STATUS_SUCCESS; + } else if (!strcasecmp(cmd, "stop")) { + return SWITCH_STATUS_FALSE; + } else if (!strcasecmp(cmd, "truncate")) { + switch_core_file_truncate(fhp, 0); + } else if (!strcasecmp(cmd, "restart")) { + unsigned int pos = 0; + fhp->speed = 0; + switch_core_file_seek(fhp, &pos, 0, SEEK_SET); + return SWITCH_STATUS_SUCCESS; + } else if (!strncasecmp(cmd, "seek", 4)) { + switch_codec_t *codec; + unsigned int samps = 0; + unsigned int pos = 0; + char *p; + codec = switch_core_session_get_read_codec(session); + + if ((p = strchr(cmd, ':'))) { + p++; + if (*p == '+' || *p == '-') { + int step; + int32_t target; + if (!(step = atoi(p))) { + step = 1000; + } + + samps = step * (codec->implementation->samples_per_second / 1000); + target = (int32_t)fhp->pos + samps; + + if (target < 0) { + target = 0; + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); + switch_core_file_seek(fhp, &pos, target, SEEK_SET); + + } else { + samps = atoi(p) * (codec->implementation->samples_per_second / 1000); + if (samps < 0) { + samps = 0; + } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); + switch_core_file_seek(fhp, &pos, samps, SEEK_SET); + } + } + + return SWITCH_STATUS_SUCCESS; + } + } + + if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) { + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; + +} + /* For Emacs: * Local Variables: diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index 7285b894ea..3c8fa5e10f 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -913,6 +913,31 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi return SWITCH_STATUS_SUCCESS; } +SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh) +{ + switch_file_handle_t *fhp; + switch_channel_t *channel = switch_core_session_get_channel(session); + + *fh = NULL; + switch_core_session_io_read_lock(session); + + if ((fhp = switch_channel_get_private(channel, "__fh"))) { + *fh = fhp; + return SWITCH_STATUS_SUCCESS; + } + + switch_core_session_io_rwunlock(session); + + return SWITCH_STATUS_FALSE; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh) +{ + *fh = NULL; + switch_core_session_io_rwunlock(session); + + return SWITCH_STATUS_SUCCESS; +} #define FILE_STARTSAMPLES 1024 * 32 #define FILE_BLOCKSIZE 1024 * 8 @@ -994,6 +1019,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } + + if (play_delimiter) { file_dup = switch_core_session_strdup(session, file); argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0]))); @@ -1134,6 +1161,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess status = SWITCH_STATUS_NOTFOUND; continue; } + + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", fh); + switch_core_session_io_rwunlock(session); + if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) { asis = 1; } @@ -1208,7 +1240,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval); + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", NULL); + switch_core_session_io_rwunlock(session); + switch_core_file_close(fh); + switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE); status = SWITCH_STATUS_GENERR; continue; @@ -1228,6 +1265,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n"); switch_core_codec_destroy(&codec); + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", NULL); + switch_core_session_io_rwunlock(session); switch_core_file_close(fh); switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE); status = SWITCH_STATUS_GENERR; @@ -1538,6 +1578,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_out); + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", NULL); + switch_core_session_io_rwunlock(session); + switch_core_file_close(fh); if (fh->audio_buffer) { From 15b5170b14396e1e17b6f75a3da01695cb49eff3 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 16:42:58 -0500 Subject: [PATCH 83/97] freetdm: ftmod_libpri - add support for RINGING state --- libs/freetdm/mod_freetdm/mod_freetdm.c | 12 ++++++------ libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 07d4e88f33..b5c8b84c0c 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -841,9 +841,9 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, assert(tech_pvt != NULL); if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } + switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); + return SWITCH_STATUS_FALSE; + } if (ftdm_channel_call_check_hangup(tech_pvt->ftdmchan)) { return SWITCH_STATUS_SUCCESS; @@ -888,9 +888,9 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio assert(tech_pvt != NULL); if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } + switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); + return SWITCH_STATUS_FALSE; + } if (switch_channel_test_flag(channel, CF_OUTBOUND)) { return SWITCH_STATUS_SUCCESS; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index c8e865214c..68f0e9e5a4 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -462,7 +462,7 @@ static ftdm_state_map_t isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_RING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END} + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END} }, { ZSD_INBOUND, @@ -479,7 +479,7 @@ static ftdm_state_map_t isdn_state_map = { { ZSD_INBOUND, ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, + {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END}, }, @@ -537,6 +537,8 @@ static __inline__ void state_advance(ftdm_channel_t *chan) break; case FTDM_CHANNEL_STATE_PROGRESS: + /* RINGING is an alias for PROGRESS state in inbound calls ATM */ + case FTDM_CHANNEL_STATE_RINGING: { if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_PROGRESS; From a1d6596ea627285828e5425282c60052c4a88b27 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 15:50:15 -0600 Subject: [PATCH 84/97] swigall --- .../languages/mod_managed/freeswitch_wrap.cxx | 80 +++++++++++++++++++ src/mod/languages/mod_managed/managed/swig.cs | 78 ++++++++++++++++++ src/mod/languages/mod_perl/mod_perl_wrap.cpp | 6 +- 3 files changed, 161 insertions(+), 3 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index d2f63b1006..f4bf780086 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -6744,6 +6744,42 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_destroy() { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_read_lock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_read_lock(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_write_lock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_write_lock(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_rwunlock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_rwunlock(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_read_lock(void * jarg1) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -28317,6 +28353,50 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_dmachine_set_realm(void * jarg1, ch } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_get_file_handle(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_file_handle_t **arg2 = (switch_file_handle_t **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_file_handle_t **)jarg2; + result = (switch_status_t)switch_ivr_get_file_handle(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_release_file_handle(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_file_handle_t **arg2 = (switch_file_handle_t **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_file_handle_t **)jarg2; + result = (switch_status_t)switch_ivr_release_file_handle(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_process_fh(void * jarg1, char * jarg2, void * jarg3) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + switch_file_handle_t *arg3 = (switch_file_handle_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (switch_file_handle_t *)jarg3; + result = (switch_status_t)switch_ivr_process_fh(arg1,(char const *)arg2,arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_RTP_MAX_BUF_LEN_get() { int jresult ; int result; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index fd4915f013..10fd3c6bc6 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -1103,6 +1103,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_io_read_lock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_read_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + + public static switch_status_t switch_core_session_io_write_lock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_write_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + + public static switch_status_t switch_core_session_io_rwunlock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_rwunlock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + public static switch_status_t switch_core_session_read_lock(SWIGTYPE_p_switch_core_session session) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_read_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); return ret; @@ -4471,6 +4486,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_get_file_handle(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_file_handle fh) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_get_file_handle(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_file_handle.getCPtr(fh)); + return ret; + } + + public static switch_status_t switch_ivr_release_file_handle(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_file_handle fh) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_release_file_handle(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_file_handle.getCPtr(fh)); + return ret; + } + + public static switch_status_t switch_ivr_process_fh(SWIGTYPE_p_switch_core_session session, string cmd, switch_file_handle fhp) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_process_fh(SWIGTYPE_p_switch_core_session.getCPtr(session), cmd, switch_file_handle.getCPtr(fhp)); + return ret; + } + public static switch_status_t switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp rtp_session, switch_rtp_crypto_direction_t direction, uint index, switch_rtp_crypto_key_type_t type, SWIGTYPE_p_unsigned_char key, SWIGTYPE_p_switch_size_t keylen) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)direction, index, (int)type, SWIGTYPE_p_unsigned_char.getCPtr(key), SWIGTYPE_p_switch_size_t.getCPtr(keylen)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -7255,6 +7285,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_destroy")] public static extern int switch_core_destroy(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_read_lock")] + public static extern int switch_core_session_io_read_lock(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_write_lock")] + public static extern int switch_core_session_io_write_lock(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_rwunlock")] + public static extern int switch_core_session_io_rwunlock(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_read_lock")] public static extern int switch_core_session_read_lock(HandleRef jarg1); @@ -12244,6 +12283,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_set_realm")] public static extern int switch_ivr_dmachine_set_realm(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_get_file_handle")] + public static extern int switch_ivr_get_file_handle(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_release_file_handle")] + public static extern int switch_ivr_release_file_handle(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_process_fh")] + public static extern int switch_ivr_process_fh(HandleRef jarg1, string jarg2, HandleRef jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_RTP_MAX_BUF_LEN_get")] public static extern int SWITCH_RTP_MAX_BUF_LEN_get(); @@ -17119,6 +17167,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_p_switch_file_handle { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_p_switch_file_handle(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_p_switch_file_handle() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_file_handle obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_p_switch_frame { private HandleRef swigCPtr; diff --git a/src/mod/languages/mod_perl/mod_perl_wrap.cpp b/src/mod/languages/mod_perl/mod_perl_wrap.cpp index 370c88bc99..2efbdf1abc 100644 --- a/src/mod/languages/mod_perl/mod_perl_wrap.cpp +++ b/src/mod/languages/mod_perl/mod_perl_wrap.cpp @@ -9732,17 +9732,17 @@ XS(SWIG_init) { SWIG_TypeClientData(SWIGTYPE_p_IVRMenu, (void*) "freeswitch::IVRMenu"); SWIG_TypeClientData(SWIGTYPE_p_API, (void*) "freeswitch::API"); SWIG_TypeClientData(SWIGTYPE_p_input_callback_state, (void*) "freeswitch::input_callback_state_t"); - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_HUP", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_HUP))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_FREE", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_FREE))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_RDLOCK", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_RDLOCK))); SvREADONLY_on(sv); From 086245a70103f87fc16eb294e23738cca95b1817 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 17:21:48 -0500 Subject: [PATCH 85/97] freetdm: do not skip states if FREETDM_SKIP_SIG_STATES is not defined --- libs/freetdm/src/ftdm_io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index cffd98203b..bcaa15a77c 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2051,10 +2051,10 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char goto done; } -#if 0 - /* DAVIDY - We will fail RFC's if we do that, but some modules apart from ftmod_sangoma_isdn +#ifndef FREETDM_SKIP_SIG_STATES + /* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn * expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so - * remove this only in netborder branch for now */ + * remove this only in netborder branch for now while we update the sig modules */ if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); From 35ba58e64994efa0a2c97a08b5164a5ea9f20679 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 30 Nov 2010 16:45:05 -0500 Subject: [PATCH 86/97] freetdm - ISDN:Fix for windows compilation issues --- libs/freetdm/src/ftdm_call_utils.c | 12 +++---- libs/freetdm/src/ftdm_io.c | 2 -- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 4 +-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 31 +++++++++++++++++-- .../ftmod_sangoma_isdn_stack_hndl.c | 5 ++- .../ftmod_sangoma_isdn_support.c | 8 ++--- 6 files changed, 42 insertions(+), 20 deletions(-) diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index 52d2557a01..69f2fb4fff 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -38,7 +38,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_npi(string); @@ -53,7 +53,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_ton(string); @@ -68,7 +68,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_bearer_cap(string); @@ -84,7 +84,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_usr_layer1_prot(string); @@ -100,7 +100,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *ta FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_screening(string); @@ -116,7 +116,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *ta FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_presentation(string); diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index bcaa15a77c..5ba7e389f8 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -38,8 +38,6 @@ */ #define _GNU_SOURCE -#ifndef WIN32 -#endif #include "private/ftdm_core.h" #include #ifdef WIN32 diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 02927d7c88..03b5a5fb1d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -799,9 +799,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_DOWN: /* the call is finished and removed */ { - uint8_t glare = 0; - - glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE); + uint8_t glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE); /* clear all of the call specific data store in the channel structure */ clear_call_data(sngisdn_info); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 9cddecb04e..b9ab3395ae 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -64,6 +64,33 @@ /* TODO: rename all *_cc_* to *_an_* */ +#define SNGISDN_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL }; +#define SNGISDN_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type); +#define SNGISDN_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \ + _TYPE _FUNC1 (const char *name) \ +{ \ + int i; \ + _TYPE t = _MAX ; \ + \ + for (i = 0; i < _MAX ; i++) { \ + if (!strcasecmp(name, _STRINGS[i])) { \ + t = (_TYPE) i; \ + break; \ +} \ +} \ + \ + return t; \ +} \ + const char * _FUNC2 (_TYPE type) \ +{ \ + if (type > _MAX) { \ + type = _MAX; \ +} \ + return _STRINGS[(int)type]; \ +} \ + + + typedef enum { FLAG_RESET_RX = (1 << 0), FLAG_RESET_TX = (1 << 1), @@ -153,7 +180,7 @@ typedef enum { SNGISDN_PROGIND_DESCR_INVALID, } ftdm_sngisdn_progind_descr_t; #define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t); +SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t); typedef enum { /* User */ @@ -174,7 +201,7 @@ typedef enum { SNGISDN_PROGIND_LOC_INVALID, } ftdm_sngisdn_progind_loc_t; #define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t); +SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t); typedef struct ftdm_sngisdn_prog_ind { ftdm_sngisdn_progind_loc_t loc; /* location */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index c4e9f4a33f..d557ca3ba0 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -255,10 +255,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) uint8_t ces = sngisdn_event->ces; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; + + ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 964d06caaf..42bcd1e20a 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -37,11 +37,11 @@ /* ftmod_sangoma_isdn specific enum look-up functions */ -FTDM_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID) +SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS) +SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID) -FTDM_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID) +SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS) +SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID) ftdm_status_t sngisdn_check_free_ids(void); From 6b611662c26fbdd1ae96d71dadd243c48b725ab6 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 1 Dec 2010 13:47:17 -0200 Subject: [PATCH 87/97] freetdm: removed ftmod_sangoma_boost, testboost, testsangomaboost, ftmod_sangoma_isdn and ftmod_r2 from default msvc 2008 build --- libs/freetdm/freetdm.2008.sln | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/freetdm.2008.sln b/libs/freetdm/freetdm.2008.sln index f059d941d3..c7207a6216 100644 --- a/libs/freetdm/freetdm.2008.sln +++ b/libs/freetdm/freetdm.2008.sln @@ -64,6 +64,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\f EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2008.vcproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" + ProjectSection(ProjectDependencies) = postProject + {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -131,7 +134,6 @@ Global {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32 @@ -139,7 +141,6 @@ Global {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32 @@ -147,7 +148,6 @@ Global {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32 @@ -155,13 +155,11 @@ Global {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32 From 85d2395d26135a862b3bed07b316c0ebbf14b725 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 1 Dec 2010 16:23:21 -0200 Subject: [PATCH 88/97] freetdm: ftmod_r2 - now clearing FTDM_CHANNEL_STATE_CHANGE flag when needed --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 54 ++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index b98f7db99c..73856f000c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -56,15 +56,10 @@ typedef enum { FTDM_R2_RUNNING = (1 << 0), } ftdm_r2_flag_t; -typedef enum { - FTDM_R2_WAITING_ACK = (1 << 0), -} ftdm_r2_call_flag_t; - /* private call information stored in ftdmchan->call_data void* ptr */ #define R2CALL(ftdmchan) ((ftdm_r2_call_t*)((ftdmchan)->call_data)) typedef struct ftdm_r2_call_t { openr2_chan_t *r2chan; - ftdm_r2_call_flag_t flags; int accepted:1; int answer_pending:1; int disconnect_rcvd:1; @@ -154,6 +149,12 @@ static ftdm_io_interface_t g_ftdm_r2_interface; static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); +/* whether R2 call accept process is pending */ +#define IS_ACCEPTING_PENDING(ftdmchan) \ + ( (!ftdm_test_flag((ftdmchan), FTDM_CHANNEL_OUTBOUND)) && !R2CALL((ftdmchan))->accepted && \ + ((ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS || \ + (ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || \ + (ftdmchan)->state == FTDM_CHANNEL_STATE_UP) ) /* functions not available on windows */ #ifdef WIN32 @@ -374,7 +375,6 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) if (ftdmchan->state != FTDM_CHANNEL_STATE_DIALING) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Collision after call attempt, try another channel, new state = %s\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_clear_flag(R2CALL(ftdmchan), FTDM_R2_WAITING_ACK); return FTDM_BREAK; } @@ -451,16 +451,43 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); } +/* + * Accepting a call in R2 is a lengthy process due to MF tones, + * when the user sends PROGRESS indication (implicitly moving the + * ftdm channel to PROGRESS state) the R2 processing loop + * does not clear FTDM_CHANNEL_STATE_CHANGE immediately as it does + * for all the other states, instead has to wait for on_call_accepted + * callback from openr2, which means the MF has ended and the progress + * indication is done, in order to clear the flag. However, if + * a protocol error or call disconnection (which is indicated using CAS bits) + * occurrs while accepting, we must clear the pending flag, this function + * takes care of that + * */ +static void clear_accept_pending(ftdm_channel_t *fchan) +{ + if (IS_ACCEPTING_PENDING(fchan)) { + ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); + ftdm_channel_complete_state(fchan); + } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_log_chan(fchan, FTDM_LOG_CRIT, "State change flag set in state %s, last state = %s\n", + ftdm_channel_state2str(fchan->state), ftdm_channel_state2str(fchan->last_state)); + ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); + ftdm_channel_complete_state(fchan); + } +} + static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode) { ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n"); + + clear_accept_pending(ftdmchan); + /* at this point the MF signaling has ended and there is no point on keep reading */ openr2_chan_disable_read(r2chan); R2CALL(ftdmchan)->accepted = 1; + if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); if (R2CALL(ftdmchan)->answer_pending) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answer was pending, answering now.\n"); ft_r2_answer_call(ftdmchan); @@ -493,6 +520,8 @@ static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_discon ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got openr2 disconnection, clearing call\n"); + clear_accept_pending(ftdmchan); + R2CALL(ftdmchan)->disconnect_rcvd = 1; if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { @@ -564,6 +593,8 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n"); + clear_accept_pending(ftdmchan); + R2CALL(ftdmchan)->disconnect_rcvd = 1; R2CALL(ftdmchan)->protocol_error = 1; @@ -1204,12 +1235,9 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); R2CALL(ftdmchan)->chanstate = ftdmchan->state; - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && !R2CALL(ftdmchan)->accepted && - (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || - ftdmchan->state == FTDM_CHANNEL_STATE_UP) ) { + if (IS_ACCEPTING_PENDING(ftdmchan)) { /* - Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call, and accepting + Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting the call in R2 means sending a tone, then waiting for the acknowledge from the other end, since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100) which means during that time the user should not try to perform any operations like answer, hangup or anything From 71e8ed8180d50227cf324c218cd13039c51a51dd Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 1 Dec 2010 17:02:58 -0500 Subject: [PATCH 89/97] freetdm: ISDN - Fix for not being able to open d-channel when span is in alarm --- libs/freetdm/src/ftdm_io.c | 39 ++++++++++--------- .../ftmod_sangoma_isdn_cfg.c | 2 +- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 5ba7e389f8..3dd1aa9ece 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1764,16 +1764,26 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan) ftdm_mutex_lock(ftdmchan->mutex); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n"); - goto done; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n"); - goto done; + if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n"); + goto done; + } + + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n"); + goto done; + } + + if (globals.cpu_monitor.alarm && + globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) { + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n"); + ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION; + goto done; + } } if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) { @@ -1782,15 +1792,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan) goto done; } - if (globals.cpu_monitor.alarm && - globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n"); - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION; - goto done; - } - - status = ftdmchan->fio->open(ftdmchan); if (status == FTDM_SUCCESS) { ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OPEN | FTDM_CHANNEL_INUSE); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 6afab42a89..cce10cc1dd 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -280,7 +280,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ } else if (!strcasecmp(var, "outbound-bearer_cap")) { ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability); } else if (!strcasecmp(var, "outbound-bearer_layer1")) { - ftdm_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); + ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1); } else if (!strcasecmp(var, "channel-restart-on-link-up")) { parse_yesno(var, val, &signal_data->restart_opt); } else if (!strcasecmp(var, "local-number")) { From 87d582614250e45c7a6834ffbf58911a34d0b674 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 1 Dec 2010 20:18:35 -0200 Subject: [PATCH 90/97] freetdm: Fix segfault due to race condition in ftmod_r2 processing loop Added SIGEVENT_PROCEED for ftmod_r2 Cleaned up code in main loop to use channel iterators --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 42 ++++++++++++++-------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 73856f000c..6440c796b2 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1303,6 +1303,10 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) } } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n"); + sigev.event_id = FTDM_SIGEVENT_PROCEED; + if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + } sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); @@ -1417,6 +1421,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) int res, ms; int index = 0; struct timeval start, end; + ftdm_iterator_t *chaniter = NULL; short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); #ifdef __linux__ @@ -1436,6 +1441,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) memset(&start, 0, sizeof(start)); memset(&end, 0, sizeof(end)); + chaniter = ftdm_span_get_chan_iterator(span, NULL); while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) { res = gettimeofday(&end, NULL); if (start.tv_sec) { @@ -1457,9 +1463,10 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) /* figure out what event to poll each channel for. POLLPRI when the channel is down, * POLLPRI|POLLIN|POLLOUT otherwise */ memset(poll_events, 0, sizeof(short)*span->chan_count); - for (i = 0; i < span->chan_count; i++) { - r2chan = R2CALL(span->channels[(i+1)])->r2chan; - ftdmchan = openr2_chan_get_client_data(r2chan); + chaniter = ftdm_span_get_chan_iterator(span, chaniter); + for (i = 0; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) { + ftdmchan = ftdm_iterator_current(chaniter); + r2chan = R2CALL(ftdmchan)->r2chan; poll_events[i] = POLLPRI; if (openr2_chan_get_read_enabled(r2chan)) { poll_events[i] |= POLLIN; @@ -1481,29 +1488,36 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) continue; } - /* XXX - * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span. - * is it possible to know on which channels those events are pending, without traversing the span? - * XXX */ - for (i = 1; i <= span->chan_count; i++) { - r2chan = R2CALL(span->channels[i])->r2chan; - ftdmchan = openr2_chan_get_client_data(r2chan); - r2call = R2CALL(ftdmchan); + /* this main loop takes care of MF and CAS signaling during call setup and tear down + * for every single channel in the span, do not perform blocking operations here! */ + chaniter = ftdm_span_get_chan_iterator(span, chaniter); + for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) { + ftdmchan = ftdm_iterator_current(chaniter); ftdm_mutex_lock(ftdmchan->mutex); + + r2chan = R2CALL(span->channels[i])->r2chan; + ftdm_r2_state_advance_all(ftdmchan); + openr2_chan_process_signaling(r2chan); + ftdm_r2_state_advance_all(ftdmchan); + ftdm_mutex_unlock(ftdmchan->mutex); } + /* deliver the actual events to the user now without any channel locking */ ftdm_span_trigger_signals(span); } - - for (i = 1; i <= span->chan_count; i++) { - r2chan = R2CALL(span->channels[i])->r2chan; + + chaniter = ftdm_span_get_chan_iterator(span, chaniter); + for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) { + ftdmchan = ftdm_iterator_current(chaniter); + r2chan = R2CALL(ftdmchan)->r2chan; openr2_chan_set_blocked(r2chan); } + ftdm_iterator_free(chaniter); ftdm_safe_free(poll_events); ftdm_clear_flag(r2data, FTDM_R2_RUNNING); From 383395d12509d35b85dcd8383e53370247596544 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 1 Dec 2010 17:44:05 -0500 Subject: [PATCH 91/97] freetdm: ftmod_r2 - tabs and logging fixes --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 23 ++++++++++------------ 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 6440c796b2..bdfcda7c9f 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -316,9 +316,9 @@ static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_ch static void ft_r2_clean_call(ftdm_r2_call_t *call) { - openr2_chan_t *r2chan = call->r2chan; - memset(call, 0, sizeof(*call)); - call->r2chan = r2chan; + openr2_chan_t *r2chan = call->r2chan; + memset(call, 0, sizeof(*call)); + call->r2chan = r2chan; } static void ft_r2_accept_call(ftdm_channel_t *ftdmchan) @@ -360,27 +360,24 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) ft_r2_clean_call(ftdmchan->call_data); R2CALL(ftdmchan)->ftdm_call_started = 1; R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); callstatus = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan, ftdmchan->caller_data.cid_num.digits, ftdmchan->caller_data.dnis.digits, OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER); - if (callstatus) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n"); - return FTDM_FAIL; - } + if (callstatus) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n"); + return FTDM_FAIL; + } if (ftdmchan->state != FTDM_CHANNEL_STATE_DIALING) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Collision after call attempt, try another channel, new state = %s\n", ftdm_channel_state2str(ftdmchan->state)); return FTDM_BREAK; } - - /* non-threaded implementation, we're done here */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 call placed in non-threaded mode\n"); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } static ftdm_status_t ftdm_r2_start(ftdm_span_t *span) @@ -447,7 +444,7 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons { ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Priority = (%d)\n", ani, dnis, category); + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = (%d)\n", ani, dnis, category); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); } From 1e2ce092b30f9c8abeda9237e2c63c16dd08f577 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 2 Dec 2010 13:10:57 -0200 Subject: [PATCH 92/97] freetdm: ftmod_r2 - fixed segfault --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 6440c796b2..8222fa413f 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1496,10 +1496,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdm_mutex_lock(ftdmchan->mutex); - r2chan = R2CALL(span->channels[i])->r2chan; - ftdm_r2_state_advance_all(ftdmchan); + r2chan = R2CALL(ftdmchan)->r2chan; openr2_chan_process_signaling(r2chan); ftdm_r2_state_advance_all(ftdmchan); From 980692ba9496fc2329389d85c4347cbfae6a35bf Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 2 Dec 2010 13:38:28 -0200 Subject: [PATCH 93/97] freetdm: ftmod_r2 - fixed 'Tx Queue Full' print, it was printing rx's queue length instead of tx --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 0fd2cd66be..72a57280d6 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -796,7 +796,7 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t /* we don't test for 80% full in tx since is typically full for voice channels, should we test tx 80% full for D-channels? */ if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.tx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n", From d0f403b114d2d446cc7def0ed5acccd9b4b5280a Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 2 Dec 2010 16:38:29 -0200 Subject: [PATCH 94/97] freetdm: ftmod_r2 - Use FTDM_CHANNEL_STATE_TERMINATING state properly as well-behaved modules should --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 95 +++++++++------------- 1 file changed, 38 insertions(+), 57 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 9cc96a0ab8..485b2fa784 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -445,7 +445,7 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = (%d)\n", ani, dnis, category); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); } /* @@ -492,7 +492,7 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m return; } } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } } @@ -502,15 +502,13 @@ static void ftdm_r2_on_call_answered(openr2_chan_t *r2chan) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call answered\n"); /* notify the upper layer of progress in the outbound call */ if (OR2_DIR_FORWARD == openr2_chan_get_direction(r2chan)) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); } } /* may be called in the signaling or media thread depending on whether the hangup is product of MF or CAS signaling */ static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause) { - ftdm_sigmsg_t sigev; - ftdm_r2_data_t *r2data; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call disconnected\n"); @@ -523,28 +521,13 @@ static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_discon if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call had been disconnected already by the user\n"); - /* just ack the hangup to go down */ + /* just ack the hangup to trigger the on_call_end callback and go down */ openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING); return; } - /* if the call has not been started yet we must go to HANGUP right here */ - if (!R2CALL(ftdmchan)->ftdm_call_started) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - return; - } - ftdmchan->caller_data.hangup_cause = ftdm_r2_cause_to_ftdm_cause(ftdmchan, cause); - - /* notify the user of the call terminating */ - memset(&sigev, 0, sizeof(sigev)); - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - sigev.event_id = FTDM_SIGEVENT_STOP; - r2data = ftdmchan->span->signal_data; - - ftdm_span_send_signal(ftdmchan->span, &sigev); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); } static void ftdm_r2_on_call_end(openr2_chan_t *r2chan) @@ -580,8 +563,6 @@ static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode) static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason) { - ftdm_sigmsg_t sigev; - ftdm_r2_data_t *r2data; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { @@ -595,22 +576,14 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err R2CALL(ftdmchan)->disconnect_rcvd = 1; R2CALL(ftdmchan)->protocol_error = 1; - if (!R2CALL(ftdmchan)->ftdm_call_started) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "The user already hung up, finishing call in protocol error\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); return; } ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_PROTOCOL_ERROR; - - /* FIXME: go to terminating and notify the user from the terminating handler instead of notifying here */ - memset(&sigev, 0, sizeof(sigev)); - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - sigev.event_id = FTDM_SIGEVENT_STOP; - r2data = ftdmchan->span->signal_data; - - ftdm_span_send_signal(ftdmchan->span, &sigev); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); } static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan) @@ -669,14 +642,13 @@ static void ftdm_r2_on_chan_log(openr2_chan_t *r2chan, const char *file, const c openr2_log_level_t level, const char *fmt, va_list ap) { ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); -#define CHAN_TAG "Chan " - char logmsg[512]; - char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1]; + char logmsg[1024]; + char completemsg[sizeof(logmsg)]; vsnprintf(logmsg, sizeof(logmsg), fmt, ap); - snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d:%d [%s] %s", - ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state), logmsg); + snprintf(completemsg, sizeof(completemsg), "[s%dc%d] [%d:%d] [%s] %s", + ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->physical_span_id, ftdmchan->physical_chan_id, + ftdm_channel_state2str(ftdmchan->state), logmsg); ftdm_r2_write_log(level, file, function, line, completemsg); -#undef CHAN_TAG } static int ftdm_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit) @@ -1301,13 +1273,10 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n"); sigev.event_id = FTDM_SIGEVENT_PROCEED; - if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } + ftdm_span_send_signal(ftdmchan->span, &sigev); + sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } + ftdm_span_send_signal(ftdmchan->span, &sigev); } } break; @@ -1328,31 +1297,44 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n"); sigev.event_id = FTDM_SIGEVENT_UP; - if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } + ftdm_span_send_signal(ftdmchan->span, &sigev); } } break; /* just got hangup */ - case FTDM_CHANNEL_STATE_HANGUP: + case FTDM_CHANNEL_STATE_HANGUP: { - openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); if (!R2CALL(ftdmchan)->disconnect_rcvd) { + openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ openr2_chan_disconnect_call(r2chan, disconnect_cause); } else if (!R2CALL(ftdmchan)->protocol_error) { /* just ack the hangup, on_call_end will be called by openr2 right after */ - openr2_chan_disconnect_call(r2chan, disconnect_cause); + openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING); } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Clearing call due to protocol error\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n"); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } } break; + case FTDM_CHANNEL_STATE_TERMINATING: + { + /* if the call has not been started yet we must go to HANGUP right here */ + if (!R2CALL(ftdmchan)->ftdm_call_started) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + } else { + openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); + /* notify the user of the call terminating and we wait for the user to move us to hangup */ + sigev.event_id = FTDM_SIGEVENT_STOP; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } + } + break; + /* just got hangup from the freetdm side due to abnormal failure */ case FTDM_CHANNEL_STATE_CANCEL: { @@ -1408,7 +1390,6 @@ static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan) static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) { openr2_chan_t *r2chan; - ftdm_r2_call_t *r2call = NULL; ftdm_channel_t *ftdmchan = NULL; ftdm_status_t status; ftdm_span_t *span = (ftdm_span_t *) obj; From a440210f44d2785ca795bae069e3fe1809738170 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 2 Dec 2010 19:10:34 -0200 Subject: [PATCH 95/97] freetdm: ftmod_r2 - added state map --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 101 ++++++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 485b2fa784..c503ba2234 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -513,8 +513,6 @@ static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_discon ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call disconnected\n"); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got openr2 disconnection, clearing call\n"); - clear_accept_pending(ftdmchan); R2CALL(ftdmchan)->disconnect_rcvd = 1; @@ -918,6 +916,103 @@ static openr2_log_level_t ftdm_r2_loglevel_from_string(const char *level) return newlevel; } +static ftdm_state_map_t r2_state_map = { + { + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, + {FTDM_CHANNEL_STATE_COLLECT, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_COLLECT, FTDM_END}, + {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_RING, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, + {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}, + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}, + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_UP, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, + }, + + /* Outbound states */ + + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, + {FTDM_CHANNEL_STATE_DIALING, FTDM_END} + }, + + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END} + }, + + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, + {FTDM_CHANNEL_STATE_DOWN, FTDM_END} + }, + + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + }, + + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END} + }, + + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_UP, FTDM_END}, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END} + }, + } +}; + static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) { unsigned int i = 0; @@ -1160,6 +1255,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) span->signal_data = r2data; span->outgoing_call = r2_outgoing_call; + span->state_map = &r2_state_map; + /* use signals queue */ ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); From eab0318b7aae921520b974d2aa44081866fc04b6 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 2 Dec 2010 19:11:35 -0200 Subject: [PATCH 96/97] freetdm: ftmod_r2 - disabled IO stats on all channels --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index c503ba2234..5160005dc1 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1511,7 +1511,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) openr2_chan_process_cas_signaling(r2chan); ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); + //ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); } memset(&start, 0, sizeof(start)); From 7dbb4834e4654b7a0574b3da6337c4216edab9ea Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 2 Dec 2010 20:21:22 -0200 Subject: [PATCH 97/97] freetdm: ftmod_wanpipe - fixed param documentation for wanpipe_channel_next_event() --- libs/freetdm/src/include/freetdm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 5ae14abb31..57c590faf2 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -915,7 +915,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ft * from a different thread or even the same. It is recommended to * handle events from the same span in a single thread. * - * \param span The channel to retrieve the event from + * \param ftdmchan The channel to retrieve the event from * \param event Pointer to store the pointer to the event * * \retval FTDM_SUCCESS success (at least one event available)