]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
use a packet buffer for ESL
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 16 Dec 2010 17:33:38 +0000 (11:33 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 16 Dec 2010 17:33:38 +0000 (11:33 -0600)
Makefile.am
libs/esl/Makefile
libs/esl/src/esl.c
libs/esl/src/include/esl.h
libs/esl/testclient.c

index da89572c6f14fee8f066ee88e8c30c81e743fc3c..df1ee2e0d05235513f991221cc9a308c05cf04c9 100644 (file)
@@ -276,7 +276,8 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode
 ##
 ## fs_cli ()
 ##
-fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c
+fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
+       libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
 fs_cli_CFLAGS  = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include 
 fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
 
@@ -304,7 +305,8 @@ tone2wav_LDADD   = libfreeswitch.la
 ##
 ## fs_ivrd ()
 ##
-fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c
+fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
+       libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
 fs_ivrd_CFLAGS  = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include 
 fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
 
index a180406bdaf530fe7e535d6a312b7bd6ef74efae..ab50bac4d90868057f780b4b1bce51a91019cda6 100644 (file)
@@ -9,9 +9,9 @@ CXXFLAGS=$(BASE_FLAGS) -Wall -Werror -Wno-unused-variable
 MYLIB=libesl.a
 LIBS=-lncurses -lpthread -lesl -lm
 LDFLAGS=-L.
-OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o
-SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c
-HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h
+OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o src/esl_buffer.o
+SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c src/esl_buffer.c
+HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h src/include/esl_buffer.h
 SOLINK=-shared -Xlinker -x
 # comment the next line to disable c++ (no swig mods for you then)
 OBJS += src/esl_oop.o
index ce582d3837911df4dd8e74da2b68077897e77a81..3397dbfb557f4d230aefb5c535e0e435913d6345 100644 (file)
@@ -428,6 +428,10 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s
                esl_mutex_create(&handle->mutex);
        }
 
+       if (!handle->packet_buf) {
+               esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0);
+       }
+
        handle->connected = 1;
 
        esl_send_recv(handle, "connect\n\n");
@@ -632,6 +636,10 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char *
        if (!handle->mutex) {
                esl_mutex_create(&handle->mutex);
        }
+
+       if (!handle->packet_buf) {
+               esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0);
+       }
        
        handle->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        
@@ -805,6 +813,11 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle)
                esl_mutex_destroy(&mutex);
        }
 
+       if (handle->packet_buf) {
+               esl_buffer_destroy(&handle->packet_buf);
+       }
+       
+
        return status;
 }
 
@@ -825,7 +838,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
 
        if (check_q) {
                esl_mutex_lock(handle->mutex);
-               if (handle->race_event) {
+               if (handle->race_event || esl_buffer_packet_count(handle->packet_buf)) {
                        esl_mutex_unlock(handle->mutex);
                        return esl_recv_event(handle, check_q, save_event);
                }
@@ -894,12 +907,15 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
 
 }
 
+static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t datalen)
+{
+       return recv(handle->sock, data, datalen, 0);
+}
 
 ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event)
 {
        char *c;
        esl_ssize_t rrval;
-       int crc = 0;
        esl_event_t *revent = NULL;
        char *beg;
        char *hname, *hval;
@@ -907,7 +923,6 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
        char *cl;
        esl_ssize_t len;
        int zc = 0;
-       int bread = 0;
 
        if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) {
                return ESL_FAIL;
@@ -916,9 +931,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
        esl_mutex_lock(handle->mutex);
 
        if (!handle->connected || handle->sock == ESL_SOCK_INVALID) {
-               handle->connected = 0;
-               esl_mutex_unlock(handle->mutex);
-               return ESL_FAIL;
+               goto fail;
        }
 
        esl_event_safe_destroy(&handle->last_event);
@@ -932,76 +945,62 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
                goto parse_event;
        }
 
-       memset(handle->header_buf, 0, sizeof(handle->header_buf));
-
-       c = handle->header_buf;
-       beg = c;
+       
+       while(!revent && handle->connected) {
+               esl_size_t len;
+               
+               if ((len = esl_buffer_read_packet(handle->packet_buf, handle->socket_buf, sizeof(handle->socket_buf)))) {
+                       char *data = (char *) handle->socket_buf;
+                       char *p, *e;
+                       
+                       esl_event_create(&revent, ESL_EVENT_CLONE);
+                       revent->event_id = ESL_EVENT_SOCKET_DATA;
+                       esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA");
+                       
+                       hname = p = data;
+                       while(p) {
+                               hname = p;
+                               p = NULL;
+
+                               if ((hval = strchr(hname, ':'))) {
+                                       *hval++ = '\0';
+                                       while(*hval == ' ' || *hval == '\t') hval++;
+
+                                       if ((e = strchr(hval, '\n'))) {
+                                               *e++ = '\0';
+                                               while(*e == '\n' || *e == '\r') e++;
+                                               
+                                               if (hname && hval) {
+                                                       esl_url_decode(hval);
+                                                       esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
+                                                       esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
+                                               }
+                                               
+                                               p = e;
+                                       }
+                               }
+                       }
 
-       while(handle->connected) {
-               if (bread + 2 >= sizeof(handle->header_buf)) {
-                       esl_log(ESL_LOG_CRIT, "OUT OF BUFFER SPACE!\n");
-                       handle->connected = 0;
-                       esl_mutex_unlock(handle->mutex);
-                       return ESL_DISCONNECTED;
+                       break;
                }
 
-               rrval = recv(handle->sock, c, 1, 0);
+               rrval = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf));
+               
                if (rrval == 0) {
                        if (++zc >= 100) {
-                               handle->connected = 0;
-                               esl_mutex_unlock(handle->mutex);
-                               return ESL_DISCONNECTED;
+                               goto fail;
                        }
+                       continue;
                } else if (rrval < 0) {
                        strerror_r(handle->errnum, handle->err, sizeof(handle->err));
                        goto fail;
-               } else {
-                       zc = 0;
-                       
-                       if (*c == '\n') {
-
-                               *(c+1) = '\0';
-
-                               if (++crc == 2) {
-                                       break;
-                               }
-                               
-                               if (!revent) {
-                                       esl_event_create(&revent, ESL_EVENT_CLONE);
-                                       revent->event_id = ESL_EVENT_SOCKET_DATA;
-                                       esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA");
-
-                               }
-                               
-                               hname = beg;
-                               hval = col = NULL;
-                               
-                               if (hname && (col = strchr(hname, ':'))) {
-                                       hval = col + 1;
-                                       *col = '\0';
-                                       while(*hval == ' ') hval++;
-                               }
-                       
-                               *c = '\0';
-                               
-                               if (hname && hval) {
-                                       esl_url_decode(hval);
-                                       esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
-                                       esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
-                               }
+               }
 
-                               c = beg;
-                               bread = 0;
-                               continue;
-                               
-                       } else {
-                               crc = 0;
-                       }
+               zc = 0;
 
-                       c++;
-               }
+               esl_buffer_write(handle->packet_buf, handle->socket_buf, rrval);
        }
-
+       
        if (!revent) {
                goto fail;
        }
@@ -1016,12 +1015,28 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
                *(body + len) = '\0';
                
                do {
-                       esl_ssize_t r;
-                       if ((r = recv(handle->sock, body + sofar, len - sofar, 0)) < 0) {
-                               strerror_r(handle->errnum, handle->err, sizeof(handle->err));   
-                               goto fail;
+                       esl_ssize_t r,s = esl_buffer_inuse(handle->packet_buf);
+
+                       if (s >= len) {
+                               sofar = esl_buffer_read(handle->packet_buf, body, len);
+                       } else {
+                               r = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf));
+
+                               if (r < 0) {
+                                       strerror_r(handle->errnum, handle->err, sizeof(handle->err));
+                                       goto fail;
+                               } else if (r == 0) {
+                                       if (++zc >= 100) {
+                                               goto fail;
+                                       }
+                                       continue;
+                               }
+
+                               zc = 0;
+                               
+                               esl_buffer_write(handle->packet_buf, handle->socket_buf, r);
                        }
-                       sofar += r;
+                       
                } while (sofar < len);
                
                revent->body = body;
@@ -1123,6 +1138,8 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
 
  fail:
 
+       esl_mutex_unlock(handle->mutex);
+
        handle->connected = 0;
 
        return ESL_FAIL;
index 9f28c3d9258ec96514c7b342eae151fd38f4a3fc..99ab53ae955e1ae01d44089e05c7e0c2994a4b23 100644 (file)
@@ -251,6 +251,7 @@ typedef int esl_filehandle_t;
 #include "esl_json.h"
 
 typedef int16_t esl_port_t;
+typedef size_t esl_size_t;
 
 typedef enum {
        ESL_SUCCESS,
@@ -259,7 +260,11 @@ typedef enum {
        ESL_DISCONNECTED
 } esl_status_t;
 
+#define BUF_CHUNK 65536 * 50
+#define BUF_START 65536 * 100
+
 #include <esl_threadmutex.h>
+#include <esl_buffer.h>
 
 /*! \brief A handle that will hold the socket information and
            different events received. */
@@ -273,7 +278,8 @@ typedef struct {
        /*! The error number reported by the OS */
        int errnum;
        /*! The inner contents received by the socket. Used only internally. */
-       char header_buf[4196];
+       esl_buffer_t *packet_buf;
+       char socket_buf[65536];
        /*! Last command reply */
        char last_reply[1024];
        /*! Las command reply when called with esl_send_recv */
index 9fa271fd0bc432e601d219e1fe9e517f1b683de2..a031836d5095696335acf33bc2a685e52e5ef390 100644 (file)
@@ -6,6 +6,47 @@
 int main(void)
 {
        esl_handle_t handle = {{0}};
+       esl_buffer_t *buffer;
+       char doh[65536];
+
+       esl_buffer_create(&buffer, 32 * 1024, 32 * 1024, 0);
+
+       snprintf(doh, sizeof(doh), "TEST 1 FOO BAR 1234\n");
+       esl_buffer_write(buffer, doh, strlen(doh));
+       esl_buffer_write(buffer, doh, strlen(doh));
+       esl_buffer_write(buffer, doh, strlen(doh));
+       snprintf(doh, sizeof(doh), "TEST 1 END\n\n");
+       esl_buffer_write(buffer, doh, strlen(doh));
+
+
+
+       snprintf(doh, sizeof(doh), "TEST 2 BAR FOO 4321\n");
+       esl_buffer_write(buffer, doh, strlen(doh));
+       esl_buffer_write(buffer, doh, strlen(doh));
+       esl_buffer_write(buffer, doh, strlen(doh));
+       snprintf(doh, sizeof(doh), "TEST 2 END\n\n");
+       esl_buffer_write(buffer, doh, strlen(doh));
+
+       snprintf(doh, sizeof(doh), "TEST 2 BAR FOO 4321\n");
+       esl_buffer_write(buffer, doh, strlen(doh));
+       esl_buffer_write(buffer, doh, strlen(doh));
+       esl_buffer_write(buffer, doh, strlen(doh));
+       snprintf(doh, sizeof(doh), "TEST 2 END\n\n");
+       esl_buffer_write(buffer, doh, strlen(doh));
+
+       printf("COUNT %ld\n", esl_buffer_packet_count(buffer));
+
+       memset(doh, 0, sizeof(doh));
+       esl_buffer_read_packet(buffer, doh, sizeof(doh));
+       printf("TEST: [%s]\n", doh);
+
+       memset(doh, 0, sizeof(doh));
+
+
+       esl_buffer_read_packet(buffer, doh, sizeof(doh));
+       printf("TEST2: [%s]\n", doh);
+
+       return 0;
 
        esl_connect(&handle, "localhost", 8021, NULL, "ClueCon");