]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix socket race
authorAnthony Minessale <anthony.minessale@gmail.com>
Sat, 14 Mar 2009 19:23:07 +0000 (19:23 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Sat, 14 Mar 2009 19:23:07 +0000 (19:23 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@12605 d0543943-73ff-0310-b7d9-9358b9ac24b2

libs/esl/fs_cli.c
libs/esl/src/esl.c
libs/esl/src/esl_event.c
libs/esl/src/esl_oop.cpp
libs/esl/src/include/esl.h

index 55b43fa8207867ee8a50faf7ce75558b39c43943..a721e33762e0cf5ffb621efd0e10a0c9ae490065 100644 (file)
@@ -193,8 +193,7 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
        thread_running = 1;
 
        while(thread_running && handle->connected) {
-               esl_status_t status = esl_recv_timed(handle, 10);
-               
+               esl_status_t status = esl_recv_event_timed(handle, 10, 1, NULL);
                if (status == ESL_FAIL) {
                        esl_log(ESL_LOG_WARNING, "Disconnected.\n");
                        running = thread_running = 0;
@@ -240,7 +239,11 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
                                }
                                
                                if (!known) {
-                                       printf("INCOMING DATA [%s]\n%s", type, handle->last_event->body);
+                                       printf("INCOMING DATA [%s]\n%s\n", type, handle->last_event->body ? handle->last_event->body : "");
+                                               char *foo;
+                                               esl_event_serialize(handle->last_event, &foo, ESL_FALSE);
+                                               printf("RECV EVENT\n%s\n", foo);
+                                               free(foo);
                                }
                        }
                }
@@ -724,6 +727,7 @@ int main(int argc, char *argv[])
        print_banner(stdout);
 
        esl_log(ESL_LOG_INFO, "FS CLI Ready.\nenter /help for a list of commands.\n");
+       printf("%s\n", handle.last_sr_reply);
 
        while (running) {
 
index 3a3df319569bfe16a24f00674cd118d32195d0a4..a0f360e32067df29bd681c048a5ea828b090a9d5 100644 (file)
@@ -683,6 +683,7 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle)
                esl_mutex_lock(mutex);
        }
 
+       esl_event_safe_destroy(&handle->race_event);
        esl_event_safe_destroy(&handle->last_event);
        esl_event_safe_destroy(&handle->last_sr_event);
        esl_event_safe_destroy(&handle->last_ievent);
@@ -705,20 +706,29 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle)
        return status;
 }
 
-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_recv_event_timed(esl_handle_t *handle, uint32_t ms, int check_q, esl_event_t **save_event)
 {
        fd_set rfds, efds;
        struct timeval tv = { 0 };
        int max, activity;
        esl_status_t status = ESL_SUCCESS;
 
+       if (check_q) {
+               esl_mutex_lock(handle->mutex);
+               if (handle->race_event) {
+                       esl_mutex_unlock(handle->mutex);
+                       return esl_recv_event(handle, check_q, save_event);
+               }
+               esl_mutex_unlock(handle->mutex);
+       }
+
        if (!handle || !handle->connected || handle->sock == -1) {
                return ESL_FAIL;
        }
 
        tv.tv_usec = ms * 1000;
 
-       esl_mutex_lock(handle->mutex);
+
        FD_ZERO(&rfds);
        FD_ZERO(&efds);
 
@@ -736,21 +746,21 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
        max = handle->sock + 1;
        
        if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) {
-               status = ESL_FAIL;
-               goto done;
+               return ESL_FAIL;
+       }
+
+       if (esl_mutex_trylock(handle->mutex) != ESL_SUCCESS) {
+               return ESL_BREAK;
        }
 
        if (activity && FD_ISSET(handle->sock, &rfds)) {
-               if (esl_recv_event(handle, save_event)) {
+               if (esl_recv_event(handle, check_q, save_event)) {
                        status = ESL_FAIL;
-                       goto done;
                }
        } else {
                status = ESL_BREAK;
        }
 
- done:
-
        if (handle->mutex) esl_mutex_unlock(handle->mutex);
 
        return status;
@@ -758,26 +768,41 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
 }
 
 
-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(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;
+       esl_event_t *revent = NULL, *qevent = NULL;
        char *beg;
        char *hname, *hval;
        char *col;
        char *cl;
        esl_ssize_t len;
        int zc = 0;
-       
 
        if (!handle->connected) {
                return ESL_FAIL;
        }
-
+       
        esl_mutex_lock(handle->mutex);
 
+       if (check_q && handle->race_event) {
+               qevent = handle->race_event;
+               handle->race_event = handle->race_event->next;
+               qevent->next = NULL;
+
+               if (save_event) {
+                       *save_event = qevent;
+                       qevent = NULL;
+               } else {
+                       handle->last_event = qevent;
+               }
+               
+               esl_mutex_unlock(handle->mutex);
+               return ESL_SUCCESS;
+       }
+
        esl_event_safe_destroy(&handle->last_event);
        memset(handle->header_buf, 0, sizeof(handle->header_buf));
 
@@ -834,7 +859,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, esl_event_t **sav
                        c++;
                }
        }
-
+       
        if (!revent) {
                goto fail;
        }
@@ -862,6 +887,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, esl_event_t **sav
 
        if (save_event) {
                *save_event = revent;
+               revent = NULL;
        } else {
                handle->last_event = revent;
        }
@@ -992,19 +1018,50 @@ ESL_DECLARE(esl_status_t) esl_send_recv(esl_handle_t *handle, const char *cmd)
                return ESL_FAIL;
        }
 
+
        esl_mutex_lock(handle->mutex);
 
+       esl_event_safe_destroy(&handle->last_event);
+       esl_event_safe_destroy(&handle->last_sr_event);
+
+       *handle->last_sr_reply = '\0';
+
        if ((status = esl_send(handle, cmd))) {
+               esl_mutex_unlock(handle->mutex);
                return status;
        }
 
-       status = esl_recv_event(handle, &handle->last_sr_event);
-       
+ recv: 
+
+       status = esl_recv_event(handle, 0, &handle->last_sr_event);
+
        if (handle->last_sr_event) {
-               hval = esl_event_get_header(handle->last_sr_event, "reply-text");
+               char *ct = esl_event_get_header(handle->last_sr_event,"content-type");
 
-               if (!esl_strlen_zero(hval)) {
-                       strncpy(handle->last_sr_reply, hval, sizeof(handle->last_sr_reply));
+               if (strcasecmp(ct, "api/response") && strcasecmp(ct, "command/reply")) {
+                       esl_event_t *ep;
+
+                       for(ep = handle->race_event; ep && ep->next; ep = ep->next);
+                       
+                       if (ep) {
+                               ep->next = handle->last_sr_event;
+                       } else {
+                               handle->race_event = handle->last_sr_event;
+                       }
+
+                       handle->last_sr_event = NULL;
+                       
+                       esl_mutex_unlock(handle->mutex);
+                       esl_mutex_lock(handle->mutex);
+                       goto recv;
+               }
+
+               if (handle->last_sr_event) {
+                       hval = esl_event_get_header(handle->last_sr_event, "reply-text");
+
+                       if (!esl_strlen_zero(hval)) {
+                               strncpy(handle->last_sr_reply, hval, sizeof(handle->last_sr_reply));
+                       }               
                }
        }
        
index 2c4cfec5b21a5f9608cdf7fa0942fda88c571c65..b683488ba083b50a22d565f39df25bf9f21f80a3 100644 (file)
@@ -367,22 +367,25 @@ ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt
 
 ESL_DECLARE(void) esl_event_destroy(esl_event_t **event)
 {
-       esl_event_t *ep = *event;
-       esl_event_header_t *hp, *this;
+       esl_event_t *ep = *event, *this_event;
+       esl_event_header_t *hp, *this_header;
 
-       if (ep) {
-               for (hp = ep->headers; hp;) {
-                       this = hp;
+       for (ep = *event ; ep ;) {
+               this_event = ep;
+               ep = ep->next;
+               
+               for (hp = this_event->headers; hp;) {
+                       this_header = hp;
                        hp = hp->next;
-                       FREE(this->name);
-                       FREE(this->value);
-                       memset(this, 0, sizeof(*this));
-                       FREE(this);
+                       FREE(this_header->name);
+                       FREE(this_header->value);
+                       memset(this_header, 0, sizeof(*this_header));
+                       FREE(this_header);
                }
-               FREE(ep->body);
-               FREE(ep->subclass_name);
-               memset(ep, 0, sizeof(*ep));
-               FREE(ep);
+               FREE(this_event->body);
+               FREE(this_event->subclass_name);
+               memset(this_event, 0, sizeof(*this_event));
+               FREE(this_event);
        }
        *event = NULL;
 }
index 8328c2e416f30d3fcee10d2663456812fa739fb2..164fec14ee1a5284a2b8709188f71df611407322 100644 (file)
@@ -154,7 +154,7 @@ ESLevent *ESLconnection::recvEvent()
                delete last_event_obj;
        }
        
-       if (esl_recv_event(&handle, NULL) == ESL_SUCCESS) {
+       if (esl_recv_event(&handle, 1, NULL) == ESL_SUCCESS) {
                esl_event_t *e = handle.last_ievent ? handle.last_ievent : handle.last_event;
                if (e) {
                        esl_event_t *event;
@@ -176,7 +176,7 @@ ESLevent *ESLconnection::recvEventTimed(int ms)
                last_event_obj = NULL;
        }
 
-       if (esl_recv_event_timed(&handle, ms, NULL) == ESL_SUCCESS) {
+       if (esl_recv_event_timed(&handle, ms, 1, NULL) == ESL_SUCCESS) {
                esl_event_t *e = handle.last_ievent ? handle.last_ievent : handle.last_event;
                if (e) {
                        esl_event_t *event;
index e7b1c4528eb3fff588912e16d91700dd8f936887..a43ff6db22a858bb4cc428e1b1b592fbf411fd41 100644 (file)
@@ -266,6 +266,7 @@ typedef struct {
        char last_sr_reply[1024];
        esl_event_t *last_event;
        esl_event_t *last_sr_event;
+       esl_event_t *race_event;
        esl_event_t *last_ievent;
        esl_event_t *info_event;
        int connected;
@@ -334,14 +335,14 @@ ESL_DECLARE(esl_status_t) esl_sendevent(esl_handle_t *handle, esl_event_t *event
 ESL_DECLARE(esl_status_t) esl_connect(esl_handle_t *handle, const char *host, esl_port_t port, const char *password);
 ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle);
 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_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event);
+ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms, int check_q, 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)
+#define esl_recv(_h) esl_recv_event(_h, 0, NULL)
+#define esl_recv_timed(_h, _ms) esl_recv_event_timed(_h, _ms, 0, NULL)
 
 static __inline__ int esl_safe_strcasecmp(const char *s1, const char *s2)
 {