don't call us we'll call you
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3917 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
aa2d884df7
commit
9d1e2e9167
|
@ -13,8 +13,11 @@ sub init($;$) {
|
|||
$self->{_host} = $args->{-host} || "localhost";
|
||||
$self->{_port} = $args->{-port} || 8021;
|
||||
$self->{_password} = $args->{-password} || undef;
|
||||
|
||||
$self->{events} = [];
|
||||
my $me = bless $self,$class;
|
||||
if (!$self->{_password}) {
|
||||
return $me;
|
||||
}
|
||||
if ($me->connect()) {
|
||||
return $me;
|
||||
} else {
|
||||
|
@ -22,61 +25,62 @@ sub init($;$) {
|
|||
}
|
||||
}
|
||||
|
||||
sub input($;$) {
|
||||
sub readhash($;$) {
|
||||
my ($self,$to) = @_;
|
||||
my $i;
|
||||
my @r;
|
||||
my $s = $self->{_sock};
|
||||
my $x = 0;
|
||||
my $done = 0;
|
||||
my $start = time;
|
||||
my ($can_read) = IO::Select::select($self->{_sel}, undef, undef, $to ? to : undef);
|
||||
my $s = shift @{$can_read};
|
||||
my @r = ();
|
||||
my $crc = 0;
|
||||
my $h;
|
||||
|
||||
while(!$done) {
|
||||
if ($to and time - $start > $to) {
|
||||
last;
|
||||
}
|
||||
@ready = $self->{_sel}->can_read($to);
|
||||
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 ($s) {
|
||||
for (;;) {
|
||||
my $line;
|
||||
for (;;) {
|
||||
my $i = 0;
|
||||
recv $s, $i, 1, 0;
|
||||
if ($i eq "") {
|
||||
$h->{socketerror} = "yes";
|
||||
return $h;
|
||||
last;
|
||||
} elsif ($i eq "\n") {
|
||||
$crc++;
|
||||
last;
|
||||
} else {
|
||||
$crc = 0;
|
||||
}
|
||||
$line .= $i;
|
||||
}
|
||||
if (!$line) {
|
||||
last;
|
||||
}
|
||||
push @r, $line;
|
||||
}
|
||||
|
||||
if (!@r) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
foreach(@r) {
|
||||
my ($var, $val) = /^([^:]+):[\s\t]*(.*)$/;
|
||||
$h->{lc $var} = $val;
|
||||
}
|
||||
|
||||
if ($h->{'content-length'}) {
|
||||
recv $s, $h->{body}, $h->{'content-length'}, 0;
|
||||
}
|
||||
|
||||
if ($h->{'content-type'} eq "text/event-plain") {
|
||||
my $e = $self->extract_event($h);
|
||||
$h->{has_event} = 1;
|
||||
$h->{event} = $e;
|
||||
}
|
||||
}
|
||||
return @r;
|
||||
|
||||
|
||||
}
|
||||
|
||||
sub readhash($$) {
|
||||
my $self = shift;
|
||||
my $arg = shift;
|
||||
return $h;
|
||||
|
||||
my @r = $self->input($arg);
|
||||
|
||||
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'}) {
|
||||
my $s = $self->{_sock};
|
||||
read $s, $h{body}, $h{'content-length'};
|
||||
}
|
||||
|
||||
return \%h;
|
||||
}
|
||||
|
||||
sub error($$) {
|
||||
|
@ -92,31 +96,147 @@ sub output($$) {
|
|||
print $s $data ;
|
||||
}
|
||||
|
||||
sub cmd($$$) {
|
||||
sub get_events($) {
|
||||
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 $e;
|
||||
|
||||
$self->output($cmd->{command});
|
||||
foreach(keys %{$cmd}) {
|
||||
next if ($_ eq "command");
|
||||
$self->output($cmd->{$_});
|
||||
for(;;) {
|
||||
$e = $self->readhash(.1);
|
||||
if ($e && !$e->{socketerror}) {
|
||||
#print Dumper $e;
|
||||
push @{$self->{events}}, $e;
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
$self->output("\n\n");
|
||||
|
||||
my $h = $self->readhash($to);
|
||||
$self->output($sendmsg->{command} . "\n");
|
||||
foreach(keys %{$sendmsg}) {
|
||||
next if ($_ eq "command");
|
||||
$self->output("$_" . ": " . $sendmsg->{$_} . "\n");
|
||||
}
|
||||
$self->output("\n");
|
||||
|
||||
$h;
|
||||
return $self->readhash($to);
|
||||
}
|
||||
|
||||
sub command($$) {
|
||||
my $self = shift;
|
||||
my $reply;
|
||||
|
||||
my $r = $self->sendmsg({ 'command' => "api " . shift });
|
||||
|
||||
if ($r->{body}) {
|
||||
$reply = $r->{body};
|
||||
} else {
|
||||
$reply = "socketerror";
|
||||
}
|
||||
|
||||
return $reply;
|
||||
}
|
||||
|
||||
sub disconnect($) {
|
||||
my $self = shift;
|
||||
$self->{_sock}->shutdown(2);
|
||||
$self->{_sock}->close();
|
||||
if ($self->{_sock}) {
|
||||
$self->{_sock}->shutdown(2);
|
||||
$self->{_sock}->close();
|
||||
}
|
||||
undef $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($) {
|
||||
my $self = shift;
|
||||
|
||||
|
@ -134,7 +254,7 @@ sub connect($) {
|
|||
|
||||
if ($h->{"content-type"} eq "auth/request") {
|
||||
my $pass = $self->{"_password"};
|
||||
$h = $self->cmd({command => "auth $pass"});
|
||||
$h = $self->sendmsg({command => "auth $pass"});
|
||||
}
|
||||
|
||||
if ($h->{'reply-text'} =~ "OK") {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#!/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
|
|||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\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
|
||||
\param session the session to wait for.
|
||||
|
|
|
@ -39,7 +39,11 @@ typedef enum {
|
|||
LFLAG_AUTHED = (1 << 0),
|
||||
LFLAG_RUNNING = (1 << 1),
|
||||
LFLAG_EVENTS = (1 << 2),
|
||||
LFLAG_LOG = (1 << 3)
|
||||
LFLAG_LOG = (1 << 3),
|
||||
LFLAG_FULL = (1 << 4),
|
||||
LFLAG_MYEVENTS = (1 << 5),
|
||||
LFLAG_SESSION = (1 << 6),
|
||||
LFLAG_ASYNC = (1 << 7)
|
||||
} event_flag_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -60,6 +64,7 @@ struct listener {
|
|||
uint8_t event_list[SWITCH_EVENT_ALL+1];
|
||||
switch_hash_t *event_hash;
|
||||
switch_thread_rwlock_t *rwlock;
|
||||
switch_core_session_t *session;
|
||||
struct listener *next;
|
||||
};
|
||||
|
||||
|
@ -83,6 +88,9 @@ static struct {
|
|||
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, prefs.ip)
|
||||
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_pass, prefs.password)
|
||||
|
||||
static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj);
|
||||
static void launch_listener_thread(listener_t *listener);
|
||||
|
||||
static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_level_t level)
|
||||
{
|
||||
listener_t *l;
|
||||
|
@ -122,7 +130,7 @@ static void event_handler(switch_event_t *event)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (l->event_list[(uint8_t)SWITCH_EVENT_ALL]) {
|
||||
if (l->event_list[(uint8_t)SWITCH_EVENT_ALL]) {
|
||||
send = 1;
|
||||
} else if ((l->event_list[(uint8_t)event->event_id])) {
|
||||
if (event->event_id != SWITCH_EVENT_CUSTOM || (event->subclass && switch_core_hash_find(l->event_hash, event->subclass->name))) {
|
||||
|
@ -130,6 +138,13 @@ static void event_handler(switch_event_t *event)
|
|||
}
|
||||
}
|
||||
|
||||
if (send && switch_test_flag(l, LFLAG_MYEVENTS)) {
|
||||
char *uuid = switch_event_get_header(event, "unique-id");
|
||||
if (!uuid || strcmp(uuid, switch_core_session_get_uuid(l->session))) {
|
||||
send = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (send) {
|
||||
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_queue_push(l->event_queue, clone);
|
||||
|
@ -142,6 +157,105 @@ static void event_handler(switch_event_t *event)
|
|||
switch_mutex_unlock(listen_list.mutex);
|
||||
}
|
||||
|
||||
static void socket_function(switch_core_session_t *session, char *data)
|
||||
{
|
||||
char *host, *port_name;
|
||||
switch_socket_t *new_sock;
|
||||
switch_sockaddr_t *sa;
|
||||
int port = 8084;
|
||||
listener_t *listener;
|
||||
int argc = 0, x = 0;
|
||||
char *argv[80] = {0};
|
||||
char *mydata;
|
||||
|
||||
if (data && (mydata = switch_core_session_strdup(session, data))) {
|
||||
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
}
|
||||
|
||||
if (argc < 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
host = argv[0];
|
||||
|
||||
if (switch_strlen_zero(host)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Host!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((port_name = strchr(host, ':'))) {
|
||||
*port_name++ = '\0';
|
||||
port = atoi(port_name);
|
||||
}
|
||||
|
||||
if (switch_sockaddr_info_get(&sa, host, AF_INET, port, 0, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (switch_socket_create(&new_sock, AF_INET, SOCK_STREAM, APR_PROTO_TCP, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch_socket_opt_set(new_sock, SWITCH_SO_KEEPALIVE, 1);
|
||||
|
||||
if (switch_socket_connect(new_sock, sa) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!(listener = switch_core_session_alloc(session, sizeof(*listener)))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch_thread_rwlock_create(&listener->rwlock, switch_core_session_get_pool(session));
|
||||
switch_queue_create(&listener->event_queue, SWITCH_CORE_QUEUE_LEN, switch_core_session_get_pool(session));
|
||||
switch_queue_create(&listener->log_queue, SWITCH_CORE_QUEUE_LEN, switch_core_session_get_pool(session));
|
||||
|
||||
listener->sock = new_sock;
|
||||
listener->pool = switch_core_session_get_pool(session);
|
||||
listener->format = EVENT_FORMAT_PLAIN;
|
||||
listener->session = session;
|
||||
|
||||
switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED, listener->pool);
|
||||
switch_core_hash_init(&listener->event_hash, listener->pool);
|
||||
switch_set_flag(listener, LFLAG_AUTHED);
|
||||
for(x = 1; x < argc; x++) {
|
||||
if (argv[x] && !strcasecmp(argv[x], "full")) {
|
||||
switch_set_flag(listener, LFLAG_FULL);
|
||||
} else if (argv[x] && !strcasecmp(argv[x], "async")) {
|
||||
switch_set_flag(listener, LFLAG_ASYNC);
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_test_flag(listener, LFLAG_ASYNC)) {
|
||||
launch_listener_thread(listener);
|
||||
switch_ivr_park(session);
|
||||
} else {
|
||||
listener_run(NULL, (void*) listener);
|
||||
}
|
||||
|
||||
while(switch_test_flag(listener, LFLAG_SESSION)) {
|
||||
switch_yield(100000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static const switch_application_interface_t socket_application_interface = {
|
||||
/*.interface_name */ "socket",
|
||||
/*.application_function */ socket_function,
|
||||
/* long_desc */ "Connect to a socket",
|
||||
/* short_desc */ "Connect to a socket",
|
||||
/* syntax */ "<ip>[:<port>]",
|
||||
/*.next */ NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
static switch_loadable_module_interface_t event_socket_module_interface = {
|
||||
/*.module_name */ modname,
|
||||
|
@ -149,7 +263,7 @@ static switch_loadable_module_interface_t event_socket_module_interface = {
|
|||
/*.timer_interface */ NULL,
|
||||
/*.dialplan_interface */ NULL,
|
||||
/*.codec_interface */ NULL,
|
||||
/*.application_interface */ NULL
|
||||
/*.application_interface */ &socket_application_interface
|
||||
};
|
||||
|
||||
|
||||
|
@ -255,6 +369,11 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (listener->session && !switch_channel_ready(switch_core_session_get_channel(listener->session))) {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mlen) {
|
||||
bytes += mlen;
|
||||
do_sleep = 0;
|
||||
|
@ -313,7 +432,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (timeout) {
|
||||
elapsed = (uint32_t)(time(NULL) - start);
|
||||
if (elapsed >= timeout) {
|
||||
|
@ -493,6 +612,53 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t *event
|
|||
}
|
||||
|
||||
|
||||
if (listener->session) {
|
||||
if (!strncasecmp(cmd, "connect", 7)) {
|
||||
snprintf(reply, reply_len, "+OK");
|
||||
goto done;
|
||||
} else if (!strncasecmp(cmd, "sendmsg", 4)) {
|
||||
if (switch_test_flag(listener, LFLAG_ASYNC)) {
|
||||
if ((status = switch_core_session_queue_private_event(listener->session, &event)) == SWITCH_STATUS_SUCCESS) {
|
||||
snprintf(reply, reply_len, "+OK");
|
||||
} else {
|
||||
snprintf(reply, reply_len, "-ERR memory error");
|
||||
}
|
||||
} else {
|
||||
switch_ivr_parse_event(listener->session, event);
|
||||
snprintf(reply, reply_len, "+OK");
|
||||
}
|
||||
goto done;
|
||||
} else if (!strncasecmp(cmd, "myevents", 8)) {
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_CREATE] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_DESTROY] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_STATE] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_ANSWER] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_HANGUP] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_EXECUTE] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_BRIDGE] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_UNBRIDGE] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_PROGRESS] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_OUTGOING] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_PARK] = 1;
|
||||
listener->event_list[SWITCH_EVENT_CHANNEL_UNPARK] = 1;
|
||||
listener->event_list[SWITCH_EVENT_TALK] = 1;
|
||||
listener->event_list[SWITCH_EVENT_DTMF] = 1;
|
||||
listener->event_list[SWITCH_EVENT_NOTALK] = 1;
|
||||
listener->event_list[SWITCH_EVENT_DETECTED_SPEECH] = 1;
|
||||
switch_set_flag_locked(listener, LFLAG_MYEVENTS);
|
||||
switch_set_flag_locked(listener, LFLAG_EVENTS);
|
||||
if (strstr(cmd, "xml") || strstr(cmd, "XML")) {
|
||||
listener->format = EVENT_FORMAT_XML;
|
||||
}
|
||||
snprintf(reply, reply_len, "+OK Events Enabled");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!switch_test_flag(listener, LFLAG_FULL)) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strncasecmp(cmd, "sendevent", 9)) {
|
||||
char *ename;
|
||||
strip_cr(cmd);
|
||||
|
@ -798,42 +964,92 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
|
|||
switch_status_t status;
|
||||
switch_event_t *event;
|
||||
char reply[512] = "";
|
||||
switch_core_session_t *session = NULL;
|
||||
switch_channel_t *channel = NULL;
|
||||
|
||||
|
||||
assert(listener != NULL);
|
||||
|
||||
if ((session = listener->session)) {
|
||||
channel = switch_core_session_get_channel(session);
|
||||
switch_core_session_read_lock(session);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Open\n");
|
||||
|
||||
switch_socket_opt_set(listener->sock, APR_SO_NONBLOCK, TRUE);
|
||||
switch_set_flag_locked(listener, LFLAG_RUNNING);
|
||||
add_listener(listener);
|
||||
|
||||
snprintf(buf, sizeof(buf), "Content-Type: auth/request\n\n");
|
||||
|
||||
len = strlen(buf);
|
||||
switch_socket_send(listener->sock, buf, &len);
|
||||
|
||||
if (session && switch_test_flag(listener, LFLAG_AUTHED)) {
|
||||
switch_event_t *event = NULL, *call_event;
|
||||
char *event_str;
|
||||
|
||||
|
||||
while (!switch_test_flag(listener, LFLAG_AUTHED)) {
|
||||
switch_set_flag_locked(listener, LFLAG_SESSION);
|
||||
status = read_packet(listener, &event, 25);
|
||||
|
||||
if (status != SWITCH_STATUS_SUCCESS || !event) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Socket Error!\n");
|
||||
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_event_create(&call_event, SWITCH_EVENT_MESSAGE) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
|
||||
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (parse_command(listener, event, reply, sizeof(reply)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch_caller_profile_event_set_data(switch_channel_get_caller_profile(channel), "Channel", call_event);
|
||||
switch_channel_event_set_data(channel, call_event);
|
||||
switch_event_add_header(call_event, SWITCH_STACK_BOTTOM, "Content-Type", "command/reply");
|
||||
|
||||
switch_event_add_header(call_event, SWITCH_STACK_BOTTOM, "Socket-Mode", switch_test_flag(listener, LFLAG_ASYNC) ? "async" : "static");
|
||||
switch_event_add_header(call_event, SWITCH_STACK_BOTTOM, "Control", switch_test_flag(listener, LFLAG_FULL) ? "full" : "single-channel");
|
||||
|
||||
switch_event_serialize(call_event, &event_str);
|
||||
if (!event_str) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
|
||||
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
||||
goto done;
|
||||
}
|
||||
len = strlen(event_str);
|
||||
switch_socket_send(listener->sock, event_str, &len);
|
||||
|
||||
switch_safe_free(event_str);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "Content-Type: auth/request\n\n");
|
||||
|
||||
status = read_packet(listener, &event, 25);
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
if (!event) {
|
||||
continue;
|
||||
}
|
||||
if (parse_command(listener, event, reply, sizeof(reply)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
||||
goto done;
|
||||
}
|
||||
if (!switch_strlen_zero(reply)) {
|
||||
snprintf(buf, sizeof(buf), "Content-Type: command/reply\nReply-Text: %s\n\n", reply);
|
||||
len = strlen(buf);
|
||||
switch_socket_send(listener->sock, buf, &len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
len = strlen(buf);
|
||||
switch_socket_send(listener->sock, buf, &len);
|
||||
|
||||
while (!switch_test_flag(listener, LFLAG_AUTHED)) {
|
||||
status = read_packet(listener, &event, 25);
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
if (!event) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parse_command(listener, event, reply, sizeof(reply)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
||||
goto done;
|
||||
}
|
||||
if (!switch_strlen_zero(reply)) {
|
||||
snprintf(buf, sizeof(buf), "Content-Type: command/reply\nReply-Text: %s\n\n", reply);
|
||||
len = strlen(buf);
|
||||
switch_socket_send(listener->sock, buf, &len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while(switch_test_flag(listener, LFLAG_RUNNING) && listen_list.ready) {
|
||||
switch_event_t *event;
|
||||
|
@ -855,7 +1071,6 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!switch_strlen_zero(reply)) {
|
||||
snprintf(buf, sizeof(buf), "Content-Type: command/reply\nReply-Text: %s\n\n", reply);
|
||||
len = strlen(buf);
|
||||
|
@ -869,25 +1084,23 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
|
|||
remove_listener(listener);
|
||||
close_socket(&listener->sock);
|
||||
|
||||
if (switch_test_flag(listener, LFLAG_EVENTS)) {
|
||||
remove_listener(listener);
|
||||
}
|
||||
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Thread done, waiting for children\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session complete, waiting for children\n");
|
||||
|
||||
switch_thread_rwlock_wrlock(listener->rwlock);
|
||||
switch_thread_rwlock_unlock(listener->rwlock);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Closed\n");
|
||||
|
||||
|
||||
|
||||
if (listener->pool) {
|
||||
if (session) {
|
||||
switch_channel_clear_flag(switch_core_session_get_channel(session), CF_CONTROLLED);
|
||||
switch_clear_flag_locked(listener, LFLAG_SESSION);
|
||||
switch_core_session_rwunlock(session);
|
||||
} else if (listener->pool) {
|
||||
switch_memory_pool_t *pool = listener->pool;
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
char *cmd = switch_event_get_header(event, "call-command");
|
||||
|
@ -97,40 +97,47 @@ static void switch_ivr_parse_event(switch_core_session_t *session, switch_event_
|
|||
unsigned long CMD_NOMEDIA = apr_hashfunc_default("nomedia", &hlen);
|
||||
|
||||
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);
|
||||
cmd_hash = apr_hashfunc_default(cmd, &hlen);
|
||||
|
||||
switch_channel_set_flag(channel, CF_EVENT_PARSE);
|
||||
|
||||
if (!switch_strlen_zero(cmd)) {
|
||||
if (cmd_hash == CMD_EXECUTE) {
|
||||
const switch_application_interface_t *application_interface;
|
||||
char *app_name = switch_event_get_header(event, "execute-app-name");
|
||||
char *app_arg = switch_event_get_header(event, "execute-app-arg");
|
||||
|
||||
if (cmd_hash == CMD_EXECUTE) {
|
||||
const switch_application_interface_t *application_interface;
|
||||
char *app_name = switch_event_get_header(event, "execute-app-name");
|
||||
char *app_arg = switch_event_get_header(event, "execute-app-arg");
|
||||
|
||||
if (app_name && app_arg) {
|
||||
if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
|
||||
if (application_interface->application_function) {
|
||||
application_interface->application_function(session, app_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cmd_hash == CMD_HANGUP) {
|
||||
char *cause_name = switch_event_get_header(event, "hangup-cause");
|
||||
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
||||
if (app_name && app_arg) {
|
||||
if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
|
||||
if (application_interface->application_function) {
|
||||
application_interface->application_function(session, app_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cmd_hash == CMD_HANGUP) {
|
||||
char *cause_name = switch_event_get_header(event, "hangup-cause");
|
||||
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
||||
|
||||
if (cause_name) {
|
||||
cause = switch_channel_str2cause(cause_name);
|
||||
}
|
||||
if (cause_name) {
|
||||
cause = switch_channel_str2cause(cause_name);
|
||||
}
|
||||
|
||||
switch_channel_hangup(channel, cause);
|
||||
} else if (cmd_hash == CMD_NOMEDIA) {
|
||||
char *uuid = switch_event_get_header(event, "nomedia-uuid");
|
||||
switch_ivr_nomedia(uuid, SMF_REBRIDGE);
|
||||
}
|
||||
}
|
||||
switch_channel_hangup(channel, cause);
|
||||
} else if (cmd_hash == CMD_NOMEDIA) {
|
||||
char *uuid = switch_event_get_header(event, "nomedia-uuid");
|
||||
switch_ivr_nomedia(uuid, SMF_REBRIDGE);
|
||||
}
|
||||
|
||||
|
||||
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)
|
|||
}
|
||||
|
||||
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 (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
|
@ -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) {
|
||||
switch_ivr_parse_event(session, 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
|
|||
done = 1;
|
||||
break;
|
||||
} 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")) {
|
||||
switch_say_interface_t *si;
|
||||
if ((si = switch_loadable_module_get_say_interface(lang))) {
|
||||
|
|
Loading…
Reference in New Issue