提交 9d1e2e91 authored 作者: Anthony Minessale's avatar Anthony Minessale

don't call us we'll call you

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3917 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 aa2d884d
...@@ -13,8 +13,11 @@ sub init($;$) { ...@@ -13,8 +13,11 @@ sub init($;$) {
$self->{_host} = $args->{-host} || "localhost"; $self->{_host} = $args->{-host} || "localhost";
$self->{_port} = $args->{-port} || 8021; $self->{_port} = $args->{-port} || 8021;
$self->{_password} = $args->{-password} || undef; $self->{_password} = $args->{-password} || undef;
$self->{events} = [];
my $me = bless $self,$class; my $me = bless $self,$class;
if (!$self->{_password}) {
return $me;
}
if ($me->connect()) { if ($me->connect()) {
return $me; return $me;
} else { } else {
...@@ -22,61 +25,62 @@ sub init($;$) { ...@@ -22,61 +25,62 @@ sub init($;$) {
} }
} }
sub input($;$) { sub readhash($;$) {
my ($self,$to) = @_; my ($self,$to) = @_;
my $i; my ($can_read) = IO::Select::select($self->{_sel}, undef, undef, $to ? to : undef);
my @r; my $s = shift @{$can_read};
my $s = $self->{_sock}; my @r = ();
my $x = 0; my $crc = 0;
my $done = 0; my $h;
my $start = time;
if ($s) {
while(!$done) { for (;;) {
if ($to and time - $start > $to) { my $line;
for (;;) {
my $i = 0;
recv $s, $i, 1, 0;
if ($i eq "") {
$h->{socketerror} = "yes";
return $h;
last; last;
} elsif ($i eq "\n") {
$crc++;
last;
} else {
$crc = 0;
} }
@ready = $self->{_sel}->can_read($to); $line .= $i;
if (@ready) {
$x=0;
foreach my $s (@ready) {
while ($i = <$s>) {
$x++;
return @r if($i eq "\n");
$i =~ s/[\n]+$//g;
push @r,$i;
}
unless($x) {
return ("SocketError: yes");
} }
if (!$line) {
last;
} }
push @r, $line;
} }
if (!@r) {
return undef;
} }
return @r;
} foreach(@r) {
my ($var, $val) = /^([^:]+):[\s\t]*(.*)$/;
$h->{lc $var} = $val;
}
sub readhash($$) { if ($h->{'content-length'}) {
my $self = shift; recv $s, $h->{body}, $h->{'content-length'}, 0;
my $arg = shift; }
my @r = $self->input($arg); if ($h->{'content-type'} eq "text/event-plain") {
my $e = $self->extract_event($h);
$h->{has_event} = 1;
$h->{event} = $e;
}
}
my $data = join "\n", @r;
my %h = $data =~ /^([^:]+)\s*:\s*([^\n]*)/mg;
foreach (keys %h) {
my $new = lc $_;
$h{$new} = $h{$_};
delete $h{$_};
}
if ($h{'content-length'}) { return $h;
my $s = $self->{_sock};
read $s, $h{body}, $h{'content-length'};
}
return \%h;
} }
sub error($$) { sub error($$) {
...@@ -92,31 +96,147 @@ sub output($$) { ...@@ -92,31 +96,147 @@ sub output($$) {
print $s $data ; print $s $data ;
} }
sub cmd($$$) { sub get_events($) {
my $self = shift; my $self = shift;
my $cmd = shift; my $e = $self->{events};
$self->{events} = [];
return $e;
}
sub sendmsg($$$) {
my $self = shift;
my $sendmsg = shift;
my $to = shift; my $to = shift;
my $e;
for(;;) {
$e = $self->readhash(.1);
if ($e && !$e->{socketerror}) {
#print Dumper $e;
push @{$self->{events}}, $e;
} else {
last;
}
}
$self->output($cmd->{command}); $self->output($sendmsg->{command} . "\n");
foreach(keys %{$cmd}) { foreach(keys %{$sendmsg}) {
next if ($_ eq "command"); next if ($_ eq "command");
$self->output($cmd->{$_}); $self->output("$_" . ": " . $sendmsg->{$_} . "\n");
} }
$self->output("\n\n"); $self->output("\n");
return $self->readhash($to);
}
sub command($$) {
my $self = shift;
my $reply;
my $h = $self->readhash($to); my $r = $self->sendmsg({ 'command' => "api " . shift });
$h; if ($r->{body}) {
$reply = $r->{body};
} else {
$reply = "socketerror";
}
return $reply;
} }
sub disconnect($) { sub disconnect($) {
my $self = shift; my $self = shift;
if ($self->{_sock}) {
$self->{_sock}->shutdown(2); $self->{_sock}->shutdown(2);
$self->{_sock}->close(); $self->{_sock}->close();
}
undef $self->{_sock}; undef $self->{_sock};
delete $self->{_sock}; delete $self->{_sock};
} }
sub raw_command($) {
my $self = shift;
return $self->sendmsg({ 'command' => shift });
}
sub htdecode($;$) {
my $urlin = shift;
my $url = (ref $urlin) ? \$$urlin : \$urlin;
$$url =~ s/%([0-9A-Z]{2})/chr hex $1/ieg;
$$url;
}
sub extract_event($$) {
my $self = shift;
my $r = shift;
my %h = $r->{body} =~ /^([^:]+)\s*:\s*([^\n]*)/mg;
foreach (keys %h) {
my $new = lc $_;
$h{$new} = $h{$_};
delete $h{$_};
}
foreach(keys %h) {
htdecode(\$h{$_});
}
return \%h;
}
sub call_command($$$) {
my $self = shift;
my $app = shift;
my $arg = shift;
my $hash = {
'command' => "sendmsg",
'call-command' => "execute",
'execute-app-name' => $app,
'execute-app-arg' => $arg
};
return $self->sendmsg($hash);
}
sub call_data($) {
my $self = shift;
return $self->{call_data};
}
sub accept($;$$) {
my $self = shift;
my $ip = shift;
my $port = shift || 8084;
if (!$self->{_lsock}) {
$self->{_lsock} = IO::Socket::INET->new(Listen => 10000,
LocalAddr => $ip,
LocalPort => $port,
Reuse => 1,
Proto => "tcp") or return $self->error("Cannot listen");
}
$self->{_sock} = $self->{_lsock}->accept();
$self->{_sock}->autoflush(1);
$self->{_sel} = new IO::Select( $self->{_sock} );
$self->{call_data} = $self->sendmsg({ 'command' => "connect"});
foreach(keys %{$self->{call_data}}) {
htdecode(\$self->{call_data}->{$_});
}
if ($self->{call_data} =~ /socketerror/) {
return 0;
}
return 1;
};
sub connect($) { sub connect($) {
my $self = shift; my $self = shift;
...@@ -134,7 +254,7 @@ sub connect($) { ...@@ -134,7 +254,7 @@ sub connect($) {
if ($h->{"content-type"} eq "auth/request") { if ($h->{"content-type"} eq "auth/request") {
my $pass = $self->{"_password"}; my $pass = $self->{"_password"};
$h = $self->cmd({command => "auth $pass"}); $h = $self->sendmsg({command => "auth $pass"});
} }
if ($h->{'reply-text'} =~ "OK") { if ($h->{'reply-text'} =~ "OK") {
......
#!/usr/bin/perl
use FreeSWITCH::Client;
use Data::Dumper;
my $fs = init FreeSWITCH::Client {} or die "Error $@";
my $pid;
for (;;) {
$fs->accept();
if (!($pid = fork)) {
last;
}
}
my $data = $fs->call_data();
#print Dumper $data
print "Call: $data->{'caller-channel-name'} $data->{'unique-id'}\n";
$o = $fs->call_command("answer");
#to turn on events when in async mode
#$o = $fs->raw_command("myevents");
$o = $fs->call_command("playback", "/ram/swimp.raw");
$o = $fs->call_command("hangup");
#comment exit in async mode
exit;
while(my $r = $fs->readhash(undef)) {
if ($r->{socketerror}) {
last;
}
if ($r->{has_event}) {
print Dumper $r->{event};
}
}
$fs->disconnect();
print "done\n";
...@@ -52,6 +52,14 @@ SWITCH_BEGIN_EXTERN_C ...@@ -52,6 +52,14 @@ SWITCH_BEGIN_EXTERN_C
*/ */
/*!
\brief Parse command from an event
\param session the session to send the message to
\param event the event to send
\return SWITCH_STATUS_SUCCESS if successful
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *session, switch_event_t *event);
/*! /*!
\brief Wait for time to pass for a specified number of milliseconds \brief Wait for time to pass for a specified number of milliseconds
\param session the session to wait for. \param session the session to wait for.
......
...@@ -86,7 +86,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, ...@@ -86,7 +86,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
} }
static void switch_ivr_parse_event(switch_core_session_t *session, switch_event_t *event) SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *session, switch_event_t *event)
{ {
switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_t *channel = switch_core_session_get_channel(session);
char *cmd = switch_event_get_header(event, "call-command"); char *cmd = switch_event_get_header(event, "call-command");
...@@ -97,12 +97,18 @@ static void switch_ivr_parse_event(switch_core_session_t *session, switch_event_ ...@@ -97,12 +97,18 @@ static void switch_ivr_parse_event(switch_core_session_t *session, switch_event_
unsigned long CMD_NOMEDIA = apr_hashfunc_default("nomedia", &hlen); unsigned long CMD_NOMEDIA = apr_hashfunc_default("nomedia", &hlen);
assert(channel != NULL); assert(channel != NULL);
if (switch_strlen_zero(cmd)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Command!\n");
return SWITCH_STATUS_FALSE;
}
hlen = (switch_size_t) strlen(cmd); hlen = (switch_size_t) strlen(cmd);
cmd_hash = apr_hashfunc_default(cmd, &hlen); cmd_hash = apr_hashfunc_default(cmd, &hlen);
switch_channel_set_flag(channel, CF_EVENT_PARSE); switch_channel_set_flag(channel, CF_EVENT_PARSE);
if (!switch_strlen_zero(cmd)) {
if (cmd_hash == CMD_EXECUTE) { if (cmd_hash == CMD_EXECUTE) {
const switch_application_interface_t *application_interface; const switch_application_interface_t *application_interface;
char *app_name = switch_event_get_header(event, "execute-app-name"); char *app_name = switch_event_get_header(event, "execute-app-name");
...@@ -128,9 +134,10 @@ static void switch_ivr_parse_event(switch_core_session_t *session, switch_event_ ...@@ -128,9 +134,10 @@ static void switch_ivr_parse_event(switch_core_session_t *session, switch_event_
char *uuid = switch_event_get_header(event, "nomedia-uuid"); char *uuid = switch_event_get_header(event, "nomedia-uuid");
switch_ivr_nomedia(uuid, SMF_REBRIDGE); switch_ivr_nomedia(uuid, SMF_REBRIDGE);
} }
}
switch_channel_clear_flag(channel, CF_EVENT_PARSE); switch_channel_clear_flag(channel, CF_EVENT_PARSE);
return SWITCH_STATUS_SUCCESS;
} }
...@@ -153,7 +160,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session) ...@@ -153,7 +160,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session)
} }
switch_channel_set_flag(channel, CF_CONTROLLED); switch_channel_set_flag(channel, CF_CONTROLLED);
while (switch_channel_ready(channel)) { while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_CONTROLLED)) {
if ((status = switch_core_session_read_frame(session, &frame, -1, stream_id)) == SWITCH_STATUS_SUCCESS) { if ((status = switch_core_session_read_frame(session, &frame, -1, stream_id)) == SWITCH_STATUS_SUCCESS) {
if (!SWITCH_READ_ACCEPTABLE(status)) { if (!SWITCH_READ_ACCEPTABLE(status)) {
...@@ -163,6 +170,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session) ...@@ -163,6 +170,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session)
if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) { if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
switch_ivr_parse_event(session, event); switch_ivr_parse_event(session, event);
switch_event_destroy(&event); switch_event_destroy(&event);
}
if (switch_channel_has_dtmf(channel)) {
char dtmf[128];
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
}
if (switch_core_session_dequeue_event(session, &event) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
} }
} }
...@@ -4597,27 +4614,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro(switch_core_session_t *s ...@@ -4597,27 +4614,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro(switch_core_session_t *s
done = 1; done = 1;
break; break;
} else if (!strcasecmp(func, "execute")) { } else if (!strcasecmp(func, "execute")) {
const switch_application_interface_t *application_interface;
char *app_name = NULL;
char *app_arg = NULL;
if ((app_name = strdup(odata))) {
char *e = NULL;
if ((app_arg = strchr(app_name, '('))) {
*app_arg++ = '\0';
if ((e = strchr(app_arg, ')'))) {
*e = '\0';
}
if (app_name && app_arg && e && (application_interface = switch_loadable_module_get_application_interface(app_name))) {
if (application_interface->application_function) {
application_interface->application_function(session, app_arg);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application!\n");
}
}
switch_safe_free(app_name);
}
} else if (!strcasecmp(func, "say")) { } else if (!strcasecmp(func, "say")) {
switch_say_interface_t *si; switch_say_interface_t *si;
if ((si = switch_loadable_module_get_say_interface(lang))) { if ((si = switch_loadable_module_get_say_interface(lang))) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论