[asterisk-commits] jpeeler: trunk r108404 - /trunk/apps/app_externalivr.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Mar 13 13:59:04 CDT 2008


Author: jpeeler
Date: Thu Mar 13 13:59:04 2008
New Revision: 108404

URL: http://svn.digium.com/view/asterisk?view=rev&rev=108404
Log:
(closes issue #11827)
Reported by: ctooley
Patches:
      eivr_tcp_generic.patch uploaded by jpeeler (license 325)
This change adds the ability to communicate over a TCP socket instead of forking a child process.

Modified:
    trunk/apps/app_externalivr.c

Modified: trunk/apps/app_externalivr.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_externalivr.c?view=diff&rev=108404&r1=108403&r2=108404
==============================================================================
--- trunk/apps/app_externalivr.c (original)
+++ trunk/apps/app_externalivr.c Thu Mar 13 13:59:04 2008
@@ -45,6 +45,7 @@
 #include "asterisk/linkedlists.h"
 #include "asterisk/app.h"
 #include "asterisk/utils.h"
+#include "asterisk/tcptls.h"
 
 static const char *app = "ExternalIVR";
 
@@ -88,6 +89,8 @@
 static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u, 
               int eivr_events_fd, int eivr_commands_fd, int eivr_errors_fd, 
               const char *args);
+
+int eivr_connect_socket(struct ast_channel *chan, const char *host, int port);
 
 static void send_eivr_event(FILE *handle, const char event, const char *data,
 	const struct ast_channel *chan)
@@ -305,6 +308,12 @@
 	int gen_active = 0;
 	int pid;
 	char *buf, *pipe_delim_argbuf, *pdargbuf_ptr;
+
+	char hostname[1024];
+	char *port_str = NULL;
+	int port = 0;
+	struct ast_tcptls_session_instance *ser;
+
 	struct ivr_localuser foo = {
 		.playlist = AST_LIST_HEAD_INIT_VALUE,
 		.finishlist = AST_LIST_HEAD_INIT_VALUE,
@@ -333,90 +342,137 @@
 	pipe_delim_argbuf = ast_strdupa(data);
 	while((pdargbuf_ptr = strchr(pipe_delim_argbuf, ',')) != NULL)
 		pdargbuf_ptr[0] = '|';
+
+	if(!strncmp(args.cmd[0], "ivr://", 6)) {
+		struct server_args ivr_desc = {
+			.accept_fd = -1,
+			.name = "IVR",
+		};
+		struct ast_hostent hp;
+
+		/*communicate through socket to server*/
+		if (chan->_state != AST_STATE_UP) {
+			ast_answer(chan);
+		}
+		if (ast_activate_generator(chan, &gen, u) < 0) {
+			ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
+			goto exit;
+		} else {
+			gen_active = 1;
+		}
+
+		ast_chan_log(LOG_DEBUG, chan, "Parsing hostname:port for socket connect from \"%s\"\n", args.cmd[0]);           
+		strncpy(hostname, args.cmd[0] + 6, sizeof(hostname));
+		if((port_str = strchr(hostname, ':')) != NULL) {
+			port_str[0] = 0;
+			port_str += 1;
+			port = atoi(port_str);
+		}
+		if(!port)
+			port = 2949;  /*default port, if one is not provided*/
+
+		ast_gethostbyname(hostname, &hp);
+		ivr_desc.sin.sin_family = AF_INET;
+		ivr_desc.sin.sin_port = htons(port);
+		memmove(&ivr_desc.sin.sin_addr.s_addr, hp.hp.h_addr, hp.hp.h_length);
+		ser = ast_tcptls_client_start(&ivr_desc);
+
+		if (!ser) {
+			goto exit;
+		} 
+		res = eivr_comm(chan, u, ser->fd, ser->fd, 0, pipe_delim_argbuf);
+	} else {
 	
-	if (pipe(child_stdin)) {
-		ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
-		goto exit;
-	}
-	if (pipe(child_stdout)) {
-		ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno));
-		goto exit;
-	}
-	if (pipe(child_stderr)) {
-		ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
-		goto exit;
-	}
-	if (chan->_state != AST_STATE_UP) {
-		ast_answer(chan);
-	}
-	if (ast_activate_generator(chan, &gen, u) < 0) {
-		ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
-		goto exit;
-	} else
-		gen_active = 1;
-
-	pid = fork();
-	if (pid < 0) {
-		ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
-		goto exit;
-	}
-
-	if (!pid) {
-		/* child process */
-		int i;
-
-		signal(SIGPIPE, SIG_DFL);
-		pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
-
-		if (ast_opt_high_priority)
-			ast_set_priority(0);
-
-		dup2(child_stdin[0], STDIN_FILENO);
-		dup2(child_stdout[1], STDOUT_FILENO);
-		dup2(child_stderr[1], STDERR_FILENO);
-		for (i = STDERR_FILENO + 1; i < 1024; i++)
-			close(i);
-		execv(args.cmd[0], args.cmd);
-		fprintf(stderr, "Failed to execute '%s': %s\n", args.cmd[0], strerror(errno));
-		_exit(1);
-	} else {
-		/* parent process */
-
+		if (pipe(child_stdin)) {
+			ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
+			goto exit;
+		}
+		if (pipe(child_stdout)) {
+			ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno));
+			goto exit;
+		}
+		if (pipe(child_stderr)) {
+			ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
+			goto exit;
+		}
+		if (chan->_state != AST_STATE_UP) {
+			ast_answer(chan);
+		}
+		if (ast_activate_generator(chan, &gen, u) < 0) {
+			ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
+			goto exit;
+		} else {
+			gen_active = 1;
+		}
+	
+		pid = fork();
+		if (pid < 0) {
+			ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
+			goto exit;
+		}
+	
+		if (!pid) {
+			/* child process */
+			int i;
+	
+			signal(SIGPIPE, SIG_DFL);
+			pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+	
+			if (ast_opt_high_priority)
+				ast_set_priority(0);
+	
+			dup2(child_stdin[0], STDIN_FILENO);
+			dup2(child_stdout[1], STDOUT_FILENO);
+			dup2(child_stderr[1], STDERR_FILENO);
+			for (i = STDERR_FILENO + 1; i < 1024; i++)
+				close(i);
+			execv(args.cmd[0], args.cmd);
+			fprintf(stderr, "Failed to execute '%s': %s\n", args.cmd[0], strerror(errno));
+			_exit(1);
+		} else {
+			/* parent process */
+	
+			close(child_stdin[0]);
+			child_stdin[0] = 0;
+			close(child_stdout[1]);
+			child_stdout[1] = 0;
+			close(child_stderr[1]);
+			child_stderr[1] = 0;
+			res = eivr_comm(chan, u, child_stdin[1], child_stdout[0], child_stderr[0], pipe_delim_argbuf);
+		}
+	}
+
+	exit:
+	if (gen_active)
+		ast_deactivate_generator(chan);
+
+	if (child_stdin[0])
 		close(child_stdin[0]);
-		child_stdin[0] = 0;
+
+	if (child_stdin[1])
+		close(child_stdin[1]);
+
+	if (child_stdout[0])
+		close(child_stdout[0]);
+
+	if (child_stdout[1])
 		close(child_stdout[1]);
-		child_stdout[1] = 0;
+
+	if (child_stderr[0])
+		close(child_stderr[0]);
+
+	if (child_stderr[1])
 		close(child_stderr[1]);
-		child_stderr[1] = 0;
-		res = eivr_comm(chan, u, child_stdin[1], child_stdout[0], child_stderr[0], pipe_delim_argbuf);
-
-		exit:
-		if (gen_active)
-			ast_deactivate_generator(chan);
-
-		if (child_stdin[0])
-			close(child_stdin[0]);
-
-		if (child_stdin[1])
-			close(child_stdin[1]);
-
-		if (child_stdout[0])
-			close(child_stdout[0]);
-
-		if (child_stdout[1])
-			close(child_stdout[1]);
-
-		if (child_stderr[0])
-			close(child_stderr[0]);
-
-		if (child_stderr[1])
-			close(child_stderr[1]);
-
-		while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
-			ast_free(entry);
-
-		return res;
-	}
+
+	if (ser) {
+		fclose(ser->f);
+		ast_tcptls_session_instance_destroy(ser);
+	}
+
+	while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
+		ast_free(entry);
+
+	return res;
 }
 
 static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u, 
@@ -436,21 +492,21 @@
  	FILE *eivr_commands = NULL;
  	FILE *eivr_errors = NULL;
  	FILE *eivr_events = NULL;
- 
- 	if (!(eivr_events = fdopen(eivr_events_fd, "w"))) {
- 		ast_chan_log(LOG_WARNING, chan, "Could not open stream to send events\n");
- 		goto exit;
- 	}
- 	if (!(eivr_commands = fdopen(eivr_commands_fd, "r"))) {
- 		ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive commands\n");
- 		goto exit;
- 	}
- 	if(eivr_errors_fd) {  /*if opening a socket connection, error stream will not be used*/
+
+	if (!(eivr_events = fdopen(eivr_events_fd, "w"))) {
+		ast_chan_log(LOG_WARNING, chan, "Could not open stream to send events\n");
+		goto exit;
+	}
+	if (!(eivr_commands = fdopen(eivr_commands_fd, "r"))) {
+		ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive commands\n");
+		goto exit;
+	}
+	if(eivr_errors_fd) {  /* if opening a socket connection, error stream will not be used */
  		if (!(eivr_errors = fdopen(eivr_errors_fd, "r"))) {
  			ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive errors\n");
  			goto exit;
  		}
- 	}
+	}
  
  	setvbuf(eivr_events, NULL, _IONBF, 0);
  	setvbuf(eivr_commands, NULL, _IONBF, 0);
@@ -633,18 +689,18 @@
  
 exit:
  
- 	if (eivr_events)
+	if (eivr_events)
  		fclose(eivr_events);
  
- 	if (eivr_commands)
+	if (eivr_commands)
 		fclose(eivr_commands);
 
- 	if (eivr_errors)
- 		fclose(eivr_errors);
+	if (eivr_errors)
+		fclose(eivr_errors);
   
   	return res;
  
-  }
+}
 
 static int unload_module(void)
 {




More information about the asterisk-commits mailing list