]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix issue with threaded ivrd, forking is back by default but threaded can be chosen...
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 3 May 2012 18:13:48 +0000 (13:13 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 3 May 2012 18:13:48 +0000 (13:13 -0500)
libs/esl/ivrd.c
libs/esl/src/esl.c
libs/esl/src/include/esl.h
libs/esl/testserver.c

index 3032a81cd3d3fd9a5791d3601e7c1c6f67d08771..2e2e6b2fa48ca5912c651e7e26e3b2a649383ee6 100644 (file)
 #include <esl.h>
 #include <errno.h>
 
-static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr)
+static void my_forking_callback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr)
 {
        esl_handle_t handle = {{0}};
+       char path_buffer[1024] = { 0 };
        const char *path;
+       char arg[64] = { 0 };
+
+       if (fork()) {
+               close(client_sock);
+               return;
+       }
        
        if (esl_attach_handle(&handle, client_sock, addr) != ESL_SUCCESS || !handle.info_event) {
-               close(client_sock);
                esl_log(ESL_LOG_ERROR, "Socket Error\n");
-               return;
+               exit(0);
        }
 
        if (!(path = esl_event_get_header(handle.info_event, "variable_ivr_path"))) {
                esl_disconnect(&handle);
                esl_log(ESL_LOG_ERROR, "Missing ivr_path param!\n");
-               return;
+               exit(0);
        }
 
+       snprintf(arg, sizeof(arg), "%d", client_sock);
+
+       strncpy(path_buffer, path, sizeof(path_buffer) - 1);
+       
+       /* hotwire the socket to STDIN/STDOUT */
        /* hotwire the socket to STDIN/STDOUT */
        if (!(dup2(client_sock, STDIN_FILENO)) && !(dup2(client_sock, STDOUT_FILENO))){
                esl_disconnect(&handle);
@@ -60,9 +71,40 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc
                return;
        }
 
-       if(system(path)) {
+       /* close the handle but leak the socket on purpose cos the child will need it open */
+       handle.sock = -1;
+       esl_disconnect(&handle);
+       
+       execl(path_buffer, path_buffer, arg, (char *)NULL);
+       close(client_sock);
+       exit(0);
+}
+
+static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr)
+{
+       esl_handle_t handle = {{0}};
+       const char *path;
+       char path_buffer[1024] = { 0 };
+
+       if (esl_attach_handle(&handle, client_sock, addr) != ESL_SUCCESS || !handle.info_event) {
+               close(client_sock);
+               esl_log(ESL_LOG_ERROR, "Socket Error\n");
+               return;
+       }
+
+       if (!(path = esl_event_get_header(handle.info_event, "variable_ivr_path"))) {
+               esl_disconnect(&handle);
+               esl_log(ESL_LOG_ERROR, "Missing ivr_path param!\n");
+               return;
+       }
+
+       snprintf(path_buffer, sizeof(path_buffer), "%s %d", path, client_sock);
+
+
+       if (system(path_buffer)) {
                 esl_log(ESL_LOG_ERROR, "System Call Failed! [%s]\n", strerror(errno));
        }
+
        esl_disconnect(&handle);
        
 }
@@ -71,24 +113,43 @@ int main(int argc, char *argv[])
 {
        int i;
        char *ip = NULL;
-       int port = 0;
+       int port = 0, thread = 0;
        
-       for (i = 1; i + 1 < argc; ) {
-               if (!strcasecmp(argv[i], "-h")) {
-                       ip = argv[++i];
-               } else if (!strcasecmp(argv[i], "-p")) {
-                       port = atoi(argv[++i]);
-               } else {
+       for (i = 1; i < argc; ) {
+               int cont = 0;
+
+               if (i + 1 < argc) {
+                       if (!strcasecmp(argv[i], "-h")) {
+                               ip = argv[++i]; cont++;
+                       } else if (!strcasecmp(argv[i], "-p")) {
+                               port = atoi(argv[++i]); cont++;
+                       }
+               }
+
+               if (cont) {
                        i++;
+                       continue;
+               }
+
+               if (!strcasecmp(argv[i], "-t")) {
+                       thread++;
                }
+
+               i++;
        }
 
        if (!(ip && port)) {
-               fprintf(stderr, "Usage %s -h <host> -p <port>\n", argv[0]);
+               fprintf(stderr, "Usage %s [-t] -h <host> -p <port>\n", argv[0]);
                return -1;
        }
 
-       esl_listen(ip, port, mycallback, 100000);
+       if (thread) {
+               printf("Starting threaded listener.\n");
+               esl_listen_threaded(ip, port, mycallback, 100000);
+       } else {
+               printf("Starting forking listener.\n");
+               esl_listen(ip, port, my_forking_callback);
+       }
        
        return 0;
 }
index fb50c6d0da07e4163e4fafcebb1bcb22e3dc38cd..22b27836fd83e9e5d91e4ff827cadffa5ef8cade 100644 (file)
@@ -649,7 +649,64 @@ static void *client_thread(esl_thread_t *me, void *obj)
 
 }
 
-ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback, int max)
+ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback)
+{
+       esl_socket_t server_sock = ESL_SOCK_INVALID;
+       struct sockaddr_in addr;
+       esl_status_t status = ESL_SUCCESS;
+       
+       if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+               return ESL_FAIL;
+       }
+
+       esl_socket_reuseaddr(server_sock);
+                  
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    addr.sin_port = htons(port);
+       
+    if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+               status = ESL_FAIL;
+               goto end;
+       }
+
+    if (listen(server_sock, 10000) < 0) {
+               status = ESL_FAIL;
+               goto end;
+       }
+
+       for (;;) {
+               int client_sock;                    
+               struct sockaddr_in echoClntAddr;
+#ifdef WIN32
+               int clntLen;
+#else
+               unsigned int clntLen;
+#endif
+
+               clntLen = sizeof(echoClntAddr);
+    
+               if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == ESL_SOCK_INVALID) {
+                       status = ESL_FAIL;
+                       goto end;
+               }
+               
+               callback(server_sock, client_sock, &echoClntAddr);
+       }
+
+ end:
+
+       if (server_sock != ESL_SOCK_INVALID) {
+               closesocket(server_sock);
+               server_sock = ESL_SOCK_INVALID;
+       }
+
+       return status;
+
+}
+
+ESL_DECLARE(esl_status_t) esl_listen_threaded(const char *host, esl_port_t port, esl_listen_callback_t callback, int max)
 {
        esl_socket_t server_sock = ESL_SOCK_INVALID;
        struct sockaddr_in addr;
index 7ba705359e76cfb92e9a3ad13403750ba528012d..4296175f3a18861931d17039161b7c1239e58bd0 100644 (file)
@@ -391,7 +391,9 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s
     \param port Port to bind to
     \param callback Callback that will be called upon data received
 */
-ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback, int max);
+
+ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback);
+ESL_DECLARE(esl_status_t) esl_listen_threaded(const char *host, esl_port_t port, esl_listen_callback_t callback, int max);
 /*!
     \brief Executes application with sendmsg to a specific UUID. Used for outbound socket.
     \param handle Handle that the msg will be sent
index cf60313fe7ef4917b7cb13f2fe657a3c3f07ea79..1477d8d71ebc489d6b8f7a7645f643da2f6a0019 100644 (file)
@@ -48,7 +48,7 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc
 int main(void)
 {
        esl_global_set_default_logger(7);
-       esl_listen("localhost", 8084, mycallback, 100000);
+       esl_listen_threaded("localhost", 8084, mycallback, 100000);
        
        return 0;
 }