[Freeswitch-svn] [commit] r3917 - in freeswitch/trunk: scripts/socket scripts/socket/FreeSWITCH src src/include src/mod/event_handlers/mod_event_socket

Freeswitch SVN anthm at freeswitch.org
Sat Jan 6 12:06:18 EST 2007


Author: anthm
Date: Sat Jan  6 12:06:18 2007
New Revision: 3917

Added:
   freeswitch/trunk/scripts/socket/sock.pl   (contents, props changed)
Modified:
   freeswitch/trunk/scripts/socket/FreeSWITCH/Client.pm
   freeswitch/trunk/src/include/switch_ivr.h
   freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
   freeswitch/trunk/src/switch_ivr.c

Log:
don't call us we'll call you

Modified: freeswitch/trunk/scripts/socket/FreeSWITCH/Client.pm
==============================================================================
--- freeswitch/trunk/scripts/socket/FreeSWITCH/Client.pm	(original)
+++ freeswitch/trunk/scripts/socket/FreeSWITCH/Client.pm	Sat Jan  6 12:06:18 2007
@@ -13,8 +13,11 @@
   $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 input($;$) {
+sub readhash($;$) {
   my ($self,$to) = @_;
-  my $i;
-  my @r;
-  my $s = $self->{_sock};
-  my $x = 0;
-  my $done = 0;
-  my $start = time;
-
-  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");
+  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;
+
+  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;
     }
-  }
-  return @r;
-
-}
-
-sub readhash($$) {
-  my $self = shift;
-  my $arg = shift;
-
-  my @r = $self->input($arg);
 
-  my $data = join "\n", @r;
-  my %h = $data =~ /^([^:]+)\s*:\s*([^\n]*)/mg;
+    foreach(@r) {
+      my ($var, $val) = /^([^:]+):[\s\t]*(.*)$/;
+      $h->{lc $var} = $val;
+    }
+    
+    if ($h->{'content-length'}) {
+      recv $s, $h->{body}, $h->{'content-length'}, 0;
+    }
 
-  foreach (keys %h) {
-    my $new = lc $_;
-    $h{$new} = $h{$_};
-    delete $h{$_};
+    if ($h->{'content-type'} eq "text/event-plain") {
+      my $e = $self->extract_event($h);
+      $h->{has_event} = 1;
+      $h->{event} = $e;
+    }    
   }
+    
 
-  if ($h{'content-length'}) {
-    my $s = $self->{_sock};
-    read $s, $h{body}, $h{'content-length'};
-  }
 
-  return \%h;
+  return $h;
+
 }
 
 sub error($$) {
@@ -92,31 +96,147 @@
   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}) {
+  for(;;) {
+    $e = $self->readhash(.1);
+    if ($e && !$e->{socketerror}) {
+      #print Dumper $e;
+      push @{$self->{events}}, $e;
+    } else  {
+      last;
+    }
+  }
+
+  $self->output($sendmsg->{command} . "\n");
+  foreach(keys %{$sendmsg}) {
     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($) {
   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 @@
 
   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") {

Added: freeswitch/trunk/scripts/socket/sock.pl
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/socket/sock.pl	Sat Jan  6 12:06:18 2007
@@ -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";
+
+

Modified: freeswitch/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_ivr.h	(original)
+++ freeswitch/trunk/src/include/switch_ivr.h	Sat Jan  6 12:06:18 2007
@@ -53,6 +53,14 @@
 
 
 /*!
+  \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.
   \param ms the number of milliseconds

Modified: freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
==============================================================================
--- freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c	(original)
+++ freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c	Sat Jan  6 12:06:18 2007
@@ -39,7 +39,11 @@
 	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 @@
 	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 @@
 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 @@
 			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 @@
 			}
 		}
 
+        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 @@
 	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 @@
 	/*.timer_interface */ NULL,
 	/*.dialplan_interface */ NULL,
 	/*.codec_interface */ NULL,
-	/*.application_interface */ NULL
+	/*.application_interface */ &socket_application_interface
 };
 
 
@@ -255,6 +369,11 @@
 			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 @@
 				break;
 			}
 		}
-
+        
 		if (timeout) {
 			elapsed = (uint32_t)(time(NULL) - start);
 			if (elapsed >= timeout) {
@@ -493,6 +612,53 @@
 	}
 
 
+    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 @@
 	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");
+    if (session && switch_test_flag(listener, LFLAG_AUTHED)) {
+        switch_event_t *event = NULL, *call_event;
+        char *event_str;
+        
+
+        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");
 		
-	len = strlen(buf);
-	switch_socket_send(listener->sock, buf, &len);
+        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;
+            }
 
-	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;
-	}
-		
+            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 @@
 			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 @@
 	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;
 }
 

Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c	(original)
+++ freeswitch/trunk/src/switch_ivr.c	Sat Jan  6 12:06:18 2007
@@ -86,7 +86,7 @@
 }
 
 
-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 @@
 	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 (cause_name) {
-				cause = switch_channel_str2cause(cause_name);
-			}
+        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;
 
-			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);
-		} 
-	}
+        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_clear_flag(channel, CF_EVENT_PARSE);
+    return SWITCH_STATUS_SUCCESS;
 
 }
 
@@ -153,7 +160,7 @@
 	}
 
 	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)) {
@@ -164,6 +171,16 @@
                 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 @@
                         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))) {



More information about the Freeswitch-svn mailing list