mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-13 12:40:17 +00:00
fix socket race
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@12605 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
dfda1d8f27
commit
73e738ab9d
@ -193,8 +193,7 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
|
|||||||
thread_running = 1;
|
thread_running = 1;
|
||||||
|
|
||||||
while(thread_running && handle->connected) {
|
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) {
|
if (status == ESL_FAIL) {
|
||||||
esl_log(ESL_LOG_WARNING, "Disconnected.\n");
|
esl_log(ESL_LOG_WARNING, "Disconnected.\n");
|
||||||
running = thread_running = 0;
|
running = thread_running = 0;
|
||||||
@ -240,7 +239,11 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!known) {
|
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);
|
print_banner(stdout);
|
||||||
|
|
||||||
esl_log(ESL_LOG_INFO, "FS CLI Ready.\nenter /help for a list of commands.\n");
|
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) {
|
while (running) {
|
||||||
|
|
||||||
|
@ -683,6 +683,7 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle)
|
|||||||
esl_mutex_lock(mutex);
|
esl_mutex_lock(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esl_event_safe_destroy(&handle->race_event);
|
||||||
esl_event_safe_destroy(&handle->last_event);
|
esl_event_safe_destroy(&handle->last_event);
|
||||||
esl_event_safe_destroy(&handle->last_sr_event);
|
esl_event_safe_destroy(&handle->last_sr_event);
|
||||||
esl_event_safe_destroy(&handle->last_ievent);
|
esl_event_safe_destroy(&handle->last_ievent);
|
||||||
@ -705,20 +706,29 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle)
|
|||||||
return status;
|
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;
|
fd_set rfds, efds;
|
||||||
struct timeval tv = { 0 };
|
struct timeval tv = { 0 };
|
||||||
int max, activity;
|
int max, activity;
|
||||||
esl_status_t status = ESL_SUCCESS;
|
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) {
|
if (!handle || !handle->connected || handle->sock == -1) {
|
||||||
return ESL_FAIL;
|
return ESL_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tv.tv_usec = ms * 1000;
|
tv.tv_usec = ms * 1000;
|
||||||
|
|
||||||
esl_mutex_lock(handle->mutex);
|
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_ZERO(&efds);
|
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;
|
max = handle->sock + 1;
|
||||||
|
|
||||||
if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) {
|
if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) {
|
||||||
status = ESL_FAIL;
|
return ESL_FAIL;
|
||||||
goto done;
|
}
|
||||||
|
|
||||||
|
if (esl_mutex_trylock(handle->mutex) != ESL_SUCCESS) {
|
||||||
|
return ESL_BREAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activity && FD_ISSET(handle->sock, &rfds)) {
|
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;
|
status = ESL_FAIL;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status = ESL_BREAK;
|
status = ESL_BREAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
|
|
||||||
if (handle->mutex) esl_mutex_unlock(handle->mutex);
|
if (handle->mutex) esl_mutex_unlock(handle->mutex);
|
||||||
|
|
||||||
return status;
|
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;
|
char *c;
|
||||||
esl_ssize_t rrval;
|
esl_ssize_t rrval;
|
||||||
int crc = 0;
|
int crc = 0;
|
||||||
esl_event_t *revent = NULL;
|
esl_event_t *revent = NULL, *qevent = NULL;
|
||||||
char *beg;
|
char *beg;
|
||||||
char *hname, *hval;
|
char *hname, *hval;
|
||||||
char *col;
|
char *col;
|
||||||
char *cl;
|
char *cl;
|
||||||
esl_ssize_t len;
|
esl_ssize_t len;
|
||||||
int zc = 0;
|
int zc = 0;
|
||||||
|
|
||||||
|
|
||||||
if (!handle->connected) {
|
if (!handle->connected) {
|
||||||
return ESL_FAIL;
|
return ESL_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
esl_mutex_lock(handle->mutex);
|
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);
|
esl_event_safe_destroy(&handle->last_event);
|
||||||
memset(handle->header_buf, 0, sizeof(handle->header_buf));
|
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++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!revent) {
|
if (!revent) {
|
||||||
goto fail;
|
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) {
|
if (save_event) {
|
||||||
*save_event = revent;
|
*save_event = revent;
|
||||||
|
revent = NULL;
|
||||||
} else {
|
} else {
|
||||||
handle->last_event = revent;
|
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;
|
return ESL_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
esl_mutex_lock(handle->mutex);
|
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))) {
|
if ((status = esl_send(handle, cmd))) {
|
||||||
|
esl_mutex_unlock(handle->mutex);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = esl_recv_event(handle, &handle->last_sr_event);
|
recv:
|
||||||
|
|
||||||
if (handle->last_sr_event) {
|
|
||||||
hval = esl_event_get_header(handle->last_sr_event, "reply-text");
|
|
||||||
|
|
||||||
if (!esl_strlen_zero(hval)) {
|
status = esl_recv_event(handle, 0, &handle->last_sr_event);
|
||||||
strncpy(handle->last_sr_reply, hval, sizeof(handle->last_sr_reply));
|
|
||||||
|
if (handle->last_sr_event) {
|
||||||
|
char *ct = esl_event_get_header(handle->last_sr_event,"content-type");
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_DECLARE(void) esl_event_destroy(esl_event_t **event)
|
||||||
{
|
{
|
||||||
esl_event_t *ep = *event;
|
esl_event_t *ep = *event, *this_event;
|
||||||
esl_event_header_t *hp, *this;
|
esl_event_header_t *hp, *this_header;
|
||||||
|
|
||||||
if (ep) {
|
for (ep = *event ; ep ;) {
|
||||||
for (hp = ep->headers; hp;) {
|
this_event = ep;
|
||||||
this = hp;
|
ep = ep->next;
|
||||||
|
|
||||||
|
for (hp = this_event->headers; hp;) {
|
||||||
|
this_header = hp;
|
||||||
hp = hp->next;
|
hp = hp->next;
|
||||||
FREE(this->name);
|
FREE(this_header->name);
|
||||||
FREE(this->value);
|
FREE(this_header->value);
|
||||||
memset(this, 0, sizeof(*this));
|
memset(this_header, 0, sizeof(*this_header));
|
||||||
FREE(this);
|
FREE(this_header);
|
||||||
}
|
}
|
||||||
FREE(ep->body);
|
FREE(this_event->body);
|
||||||
FREE(ep->subclass_name);
|
FREE(this_event->subclass_name);
|
||||||
memset(ep, 0, sizeof(*ep));
|
memset(this_event, 0, sizeof(*this_event));
|
||||||
FREE(ep);
|
FREE(this_event);
|
||||||
}
|
}
|
||||||
*event = NULL;
|
*event = NULL;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ ESLevent *ESLconnection::recvEvent()
|
|||||||
delete last_event_obj;
|
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;
|
esl_event_t *e = handle.last_ievent ? handle.last_ievent : handle.last_event;
|
||||||
if (e) {
|
if (e) {
|
||||||
esl_event_t *event;
|
esl_event_t *event;
|
||||||
@ -176,7 +176,7 @@ ESLevent *ESLconnection::recvEventTimed(int ms)
|
|||||||
last_event_obj = NULL;
|
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;
|
esl_event_t *e = handle.last_ievent ? handle.last_ievent : handle.last_event;
|
||||||
if (e) {
|
if (e) {
|
||||||
esl_event_t *event;
|
esl_event_t *event;
|
||||||
|
@ -266,6 +266,7 @@ typedef struct {
|
|||||||
char last_sr_reply[1024];
|
char last_sr_reply[1024];
|
||||||
esl_event_t *last_event;
|
esl_event_t *last_event;
|
||||||
esl_event_t *last_sr_event;
|
esl_event_t *last_sr_event;
|
||||||
|
esl_event_t *race_event;
|
||||||
esl_event_t *last_ievent;
|
esl_event_t *last_ievent;
|
||||||
esl_event_t *info_event;
|
esl_event_t *info_event;
|
||||||
int connected;
|
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_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_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_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(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, 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_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_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);
|
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(_h) esl_recv_event(_h, 0, NULL)
|
||||||
#define esl_recv_timed(_h, _ms) esl_recv_event_timed(_h, _ms, 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)
|
static __inline__ int esl_safe_strcasecmp(const char *s1, const char *s2)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user