]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix disconnect issue in event socket and fix a few small bugs
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 15 Jan 2009 22:11:27 +0000 (22:11 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 15 Jan 2009 22:11:27 +0000 (22:11 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11234 d0543943-73ff-0310-b7d9-9358b9ac24b2

libs/esl/src/esl.c
libs/esl/src/esl_event.c
libs/esl/src/include/esl.h
libs/esl/testserver.c
src/include/switch_apr.h
src/mod/event_handlers/mod_event_socket/mod_event_socket.c
src/switch_ivr.c

index 403aafada550364dfb8a9154b9e3afe9db46fc2b..02451dfdb0748a71ef0fd255f5ce67315173af8f 100644 (file)
@@ -37,7 +37,6 @@
 #endif
 
 
-
 /* Written by Marc Espie, public domain */
 #define ESL_CTYPE_NUM_CHARS       256
 
@@ -181,6 +180,48 @@ ESL_DECLARE(const char *)esl_stristr(const char *instr, const char *str)
 #endif
 #endif
 
+
+int vasprintf(char **ret, const char *format, va_list ap);
+
+ESL_DECLARE(int) esl_vasprintf(char **ret, const char *fmt, va_list ap)
+{
+#if !defined(WIN32) && !defined(__sun)
+       return vasprintf(ret, fmt, ap);
+#else
+       char *buf;
+       int len;
+       size_t buflen;
+       va_list ap2;
+       char *tmp = NULL;
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1500
+       /* hack for incorrect assumption in msvc header files for code analysis */
+       __analysis_assume(tmp);
+#endif
+       ap2 = ap;
+#else
+       va_copy(ap2, ap);
+#endif
+
+       len = vsnprintf(tmp, 0, fmt, ap2);
+
+       if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
+               len = vsnprintf(buf, buflen, fmt, ap);
+               *ret = buf;
+       } else {
+               *ret = NULL;
+               len = -1;
+       }
+
+       va_end(ap2);
+       return len;
+#endif
+}
+
+
+
+
 ESL_DECLARE(int) esl_snprintf(char *buffer, size_t count, const char *fmt, ...)
 {
        va_list ap;
@@ -236,9 +277,10 @@ static const char *cut_path(const char *in)
 static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
 {
        const char *fp;
-       char data[1024];
+       char *data;
        va_list ap;
-
+       int ret;
+       
        if (level < 0 || level > 7) {
                level = 7;
        }
@@ -250,10 +292,12 @@ static void default_logger(const char *file, const char *func, int line, int lev
 
        va_start(ap, fmt);
 
-       vsnprintf(data, sizeof(data), fmt, ap);
+       ret = esl_vasprintf(&data, fmt, ap);
 
-
-       fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
+       if (ret != -1) {
+               fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
+               free(data);
+       }
 
        va_end(ap);
 
@@ -334,6 +378,14 @@ ESL_DECLARE(char *)esl_url_decode(char *s)
        return s;
 }
 
+static void sock_setup(esl_handle_t *handle)
+{
+       int x = 1;
+
+       setsockopt(handle->sock, IPPROTO_TCP, TCP_NODELAY, &x, sizeof(x));
+
+}
+
 ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t socket, struct sockaddr_in addr)
 {
        handle->sock = socket;
@@ -350,9 +402,11 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s
 
        handle->connected = 1;
 
+       sock_setup(handle);
+
        esl_send_recv(handle, "connect\n\n");
        
-
+       
        if (handle->last_sr_event) {
                handle->info_event = handle->last_sr_event;
                handle->last_sr_event = NULL;
@@ -413,6 +467,39 @@ ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, con
        return esl_send_recv(handle, send_buf);
 }
 
+
+ESL_DECLARE(esl_status_t) esl_filter(esl_handle_t *handle, const char *header, const char *value)
+{
+       char send_buf[1024] = "";
+       
+       if (!handle->connected) {
+               return ESL_FAIL;
+       }
+
+       snprintf(send_buf, sizeof(send_buf), "filter %s %s\n\n", header, value);
+
+       return esl_send_recv(handle, send_buf);
+}
+
+
+ESL_DECLARE(esl_status_t) esl_events(esl_handle_t *handle, esl_event_type_t etype, const char *value)
+{
+       char send_buf[1024] = "";
+       const char *type = "plain";
+
+       if (!handle->connected) {
+               return ESL_FAIL;
+       }
+
+       if (etype == ESL_EVENT_TYPE_XML) {
+               type = "xml";
+       }
+
+       snprintf(send_buf, sizeof(send_buf), "event %s %s\n\n", type, value);
+       
+       return esl_send_recv(handle, send_buf);
+}
+
 static int esl_socket_reuseaddr(esl_socket_t socket) 
 {
 #ifdef WIN32
@@ -536,6 +623,8 @@ ESL_DECLARE(esl_status_t) esl_connect(esl_handle_t *handle, const char *host, es
                goto fail;
        }
 
+       sock_setup(handle);
+
        handle->connected = 1;
 
        if (esl_recv(handle)) {
index cb3af9c97b5c13acef422ccb65d01ca889f10c50..92b1ff69ca0b8fe69b9f46f9a98c2520e36ab1ad 100644 (file)
@@ -311,45 +311,6 @@ static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t st
        return ESL_SUCCESS;
 }
 
-int vasprintf(char **ret, const char *format, va_list ap);
-
-static int esl_vasprintf(char **ret, const char *fmt, va_list ap)
-{
-#if !defined(WIN32) && !defined(__sun)
-       return vasprintf(ret, fmt, ap);
-#else
-       char *buf;
-       int len;
-       size_t buflen;
-       va_list ap2;
-       char *tmp = NULL;
-
-#ifdef _MSC_VER
-#if _MSC_VER >= 1500
-       /* hack for incorrect assumption in msvc header files for code analysis */
-       __analysis_assume(tmp);
-#endif
-       ap2 = ap;
-#else
-       va_copy(ap2, ap);
-#endif
-
-       len = vsnprintf(tmp, 0, fmt, ap2);
-
-       if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
-               len = vsnprintf(buf, buflen, fmt, ap);
-               *ret = buf;
-       } else {
-               *ret = NULL;
-               len = -1;
-       }
-
-       va_end(ap2);
-       return len;
-#endif
-}
-
-
 ESL_DECLARE(esl_status_t) esl_event_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, const char *fmt, ...)
 {
        int ret = 0;
@@ -496,6 +457,8 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
                 * the memory, allocate and only reallocate if we need more.  This avoids an alloc, free CPU
                 * destroying loop.
                 */
+
+               
                new_len = (strlen(hp->value) * 3) + 1;
 
                if (encode_len < new_len) {
@@ -575,6 +538,7 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
                snprintf(buf + len, dlen - len, "\n");
        }
 
+
        *str = buf;
 
        return ESL_SUCCESS;
index 2905fc2f175d6eca503b9e4402c5627f2d7c0ead..2abe03329b59ddc2d0e6f110b6f01a49d111fea4 100644 (file)
 typedef struct esl_event_header esl_event_header_t;
 typedef struct esl_event esl_event_t;
 
+
+typedef enum {
+       ESL_EVENT_TYPE_PLAIN,
+       ESL_EVENT_TYPE_XML
+} esl_event_type_t;
+
 #ifdef WIN32
 #define ESL_SEQ_FWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
 #define ESL_SEQ_FRED FOREGROUND_RED | FOREGROUND_INTENSITY
@@ -164,6 +170,7 @@ typedef struct esl_event esl_event_t;
 #include <stdlib.h>
 #include <string.h>
 #ifndef WIN32
+#include <netinet/tcp.h>
 #include <sys/signal.h>
 #include <unistd.h>
 #include <ctype.h>
@@ -290,6 +297,9 @@ typedef enum {
 #define ESL_LOG_EMERG ESL_PRE, ESL_LOG_LEVEL_EMERG
 typedef void (*esl_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
 
+
+ESL_DECLARE(int) esl_vasprintf(char **ret, const char *fmt, va_list ap);
+
 ESL_DECLARE_DATA extern esl_logger_t esl_log;
 
 ESL_DECLARE(void) esl_global_set_logger(esl_logger_t logger);
@@ -320,6 +330,9 @@ ESL_DECLARE(esl_status_t) esl_send(esl_handle_t *handle, const char *cmd);
 ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, esl_event_t **save_event);
 ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms, esl_event_t **save_event);
 ESL_DECLARE(esl_status_t) esl_send_recv(esl_handle_t *handle, const char *cmd);
+ESL_DECLARE(esl_status_t) esl_filter(esl_handle_t *handle, const char *header, const char *value);
+ESL_DECLARE(esl_status_t) esl_events(esl_handle_t *handle, esl_event_type_t etype, const char *value);
+
 #define esl_recv(_h) esl_recv_event(_h, NULL)
 #define esl_recv_timed(_h, _ms) esl_recv_event_timed(_h, _ms, NULL)
 
index 5f3a413665ec54de013b7bcc625cb17d45bd39b8..c3e24f4ce0c4f4bcd26339aaa7641caf2e03922a 100644 (file)
@@ -5,23 +5,24 @@
 static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in addr)
 {
        esl_handle_t handle = {{0}};
-
+       
        if (fork()) {
                close(client_sock);
                return;
        }
 
-
        esl_attach_handle(&handle, client_sock, addr);
 
        printf("Connected! %d\n", handle.sock);
-       
 
+       esl_filter(&handle, "unique-id", esl_event_get_header(handle.info_event, "caller-unique-id"));
+       esl_events(&handle, ESL_EVENT_TYPE_PLAIN, "SESSION_HEARTBEAT CHANNEL_ANSWER CHANNEL_ORIGINATE CHANNEL_PROGRESS CHANNEL_HANGUP "
+                          "CHANNEL_BRIDGE CHANNEL_UNBRIDGE CHANNEL_OUTGOING CHANNEL_EXECUTE CHANNEL_EXECUTE_COMPLETE DTMF CUSTOM conference::maintenance");
 
        esl_execute(&handle, "answer", NULL, NULL);
-       esl_execute(&handle, "playback", "/ram/swimp.raw", NULL);
+       esl_execute(&handle, "conference", "3000@default", NULL);
        
-       sleep(30);
+       while(esl_recv(&handle) == ESL_SUCCESS);
 
        esl_disconnect(&handle);
 }
index a0a2dffc316a7336c8bd98e5b041a03d86945c27..7a1d8b84629cf049c8898470d777e5165780e724 100644 (file)
@@ -946,6 +946,8 @@ SWITCH_DECLARE(switch_status_t) switch_thread_create(switch_thread_t **new_threa
 #define SWITCH_SO_SNDBUF 64
 #define SWITCH_SO_RCVBUF 128
 #define SWITCH_SO_DISCONNECTED 256
+#define SWITCH_SO_TCP_NODELAY 512
+
 
  /**
  * @def SWITCH_INET
index cb9da8ba68e3f4130d8d34f7c6753f669286062c..c586161ba26dbec730252baaddaa9e140e160504 100644 (file)
@@ -74,7 +74,6 @@ struct listener {
        switch_core_session_t *session;
        int lost_events;
        int lost_logs;
-       int hup;
        time_t last_flush;
        uint32_t timeout;
        uint32_t id;
@@ -385,6 +384,7 @@ SWITCH_STANDARD_APP(socket_function)
        }
 
        switch_socket_opt_set(new_sock, SWITCH_SO_KEEPALIVE, 1);
+       switch_socket_opt_set(new_sock, SWITCH_SO_TCP_NODELAY, 1);
 
        if (switch_socket_connect(new_sock, sa) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error!\n");
@@ -978,17 +978,6 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
                        return SWITCH_STATUS_FALSE;
                }
 
-               if (switch_test_flag(listener, LFLAG_MYEVENTS) && !listener->hup && channel && !switch_channel_ready(channel)) {
-                       listener->hup = 1;
-               }
-
-               if (listener->hup == 2 || 
-                       ((!switch_test_flag(listener, LFLAG_MYEVENTS) && !switch_test_flag(listener, LFLAG_EVENTS)) && 
-                        channel && !switch_channel_ready(channel)) ) {
-                       status = SWITCH_STATUS_FALSE;
-            break;
-               }
-
                if (mlen) {
                        bytes += mlen;
                        do_sleep = 0;
@@ -1124,9 +1113,9 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
                                        do_sleep = 0;
                                }
                        }
-
+                       
                        if (switch_test_flag(listener, LFLAG_EVENTS)) {
-                               if (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
+                               while (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
                                        char hbuf[512];
                                        switch_event_t *pevent = (switch_event_t *) pop;
                                        char *etype;
@@ -1148,11 +1137,8 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
                                                }
                                        }
 
-                                       if (!listener->ebuf) {
-                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No event data (allocation error?)\n");
-                                               goto endloop;
-                                       }
-
+                                       switch_assert(listener->ebuf);
+                                       
                                        len = strlen(listener->ebuf);
 
                                        switch_snprintf(hbuf, sizeof(hbuf), "Content-Length: %" SWITCH_SSIZE_T_FMT "\n" "Content-Type: text/event-%s\n" "\n", len, etype);
@@ -1162,22 +1148,21 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
 
                                        len = strlen(listener->ebuf);
                                        switch_socket_send(listener->sock, listener->ebuf, &len);
-
+                                       
                                        switch_safe_free(listener->ebuf);
 
-                                 endloop:
+                               endloop:
 
-                                       if (listener->hup == 1 && pevent->event_id == SWITCH_EVENT_CHANNEL_HANGUP) {
-                                               char *uuid = switch_event_get_header(pevent, "unique-id");
-                                               if (!strcmp(uuid, switch_core_session_get_uuid(listener->session))) {
-                                                       listener->hup = 2;
-                                               }
-                                       }
-                                       
                                        switch_event_destroy(&pevent);
                                }
                        }
                }
+
+               if (channel && !switch_channel_ready(channel)) {
+                       status = SWITCH_STATUS_FALSE;
+            break;
+               }
+               
                if (do_sleep) {
                        switch_cond_next();
                }
@@ -1775,6 +1760,9 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
                }
        }
 
+       switch_socket_opt_set(listener->sock, SWITCH_SO_TCP_NODELAY, TRUE);
+       switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK, TRUE);
+
        if (prefs.acl_count && listener->sa && !switch_strlen_zero(listener->remote_ip)) {
                uint32_t x = 0;
 
@@ -1932,10 +1920,18 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
        switch_mutex_unlock(listener->filter_mutex);
        if (listener->sock) {
                char disco_buf[512] = "";
-               const char message[] = "Disconnected, goodbye!\nSee you at ClueCon http://www.cluecon.com/ !!!\n";
+               const char message[] = "Disconnected, goodbye.\nSee you at ClueCon! http://www.cluecon.com/\n";
                int mlen = strlen(message);
                
-               switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\nContent-Length: %d\n\n", mlen);
+               if (listener->session) {
+                       switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\n"
+                                                       "Controlled-Session-UUID: %s\n"
+                                                       "Content-Length: %d\n\n", 
+                                                       switch_core_session_get_uuid(listener->session), mlen);
+               } else {
+                       switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\nContent-Length: %d\n\n", mlen);
+               }
+
                len = strlen(disco_buf);
                switch_socket_send(listener->sock, disco_buf, &len);
                len = mlen;
index dfc7c8d1cc301a047ba27db8e0e68b9044b579fb..34bd416ff44fd2bc39822cec047a65ebe71e19d2 100644 (file)
@@ -453,7 +453,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
                                                switch_time_t b4, aftr;
 
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Command Execute %s(%s)\n",
-                                                                                 switch_channel_get_name(channel), app_name, app_arg);
+                                                                                 switch_channel_get_name(channel), app_name, switch_str_nil(app_arg));
                                                b4 = switch_timestamp_now();
                                                switch_core_session_exec(session, application_interface, app_arg);
                                                aftr = switch_timestamp_now();