From 74c4b1dc92ffc4ba5d2d7eab685733bbb98248c4 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 20 Dec 2008 18:34:34 +0000 Subject: [PATCH] update git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10896 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/esl/fs_cli.c | 50 +++-------- libs/esl/src/esl.c | 173 +++++++++++++++++++++++++++++++++---- libs/esl/src/include/esl.h | 18 +++- 3 files changed, 183 insertions(+), 58 deletions(-) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 4fe7908236..b6206b5037 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -25,7 +25,7 @@ static HistEvent ev; static char *hfile = NULL; static int running = 1; static int thread_running = 0; -static esl_mutex_t *global_mutex; + static void handle_SIGINT(int sig) { @@ -45,30 +45,12 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) thread_running = 1; while(thread_running && handle->connected) { - fd_set rfds, efds; - struct timeval tv = { 0, 10 * 1000 }; - int max, activity, i = 0; + esl_status_t status = esl_recv_timed(handle, 10); - esl_mutex_lock(global_mutex); - FD_ZERO(&rfds); - FD_ZERO(&efds); - FD_SET(handle->sock, &rfds); - FD_SET(handle->sock, &efds); - - max = handle->sock + 1; - - if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) { - esl_mutex_unlock(global_mutex); - goto done; - } - if (activity && FD_ISSET(handle->sock, &rfds)) { - if (esl_recv(handle)) { - running = thread_running = 0; - esl_mutex_unlock(global_mutex); - esl_log(ESL_LOG_WARNING, "Disconnected.\n"); - goto done; - } - + if (status == ESL_FAIL) { + esl_log(ESL_LOG_WARNING, "Disconnected.\n"); + running = thread_running = 0; + } else if (status == ESL_SUCCESS) { if (handle->last_event) { const char *type = esl_event_get_header(handle->last_event, "content-type"); int known = 0; @@ -102,10 +84,8 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) printf("INCOMING DATA [%s]\n%s", type, handle->last_event->body); } } - } - esl_mutex_unlock(global_mutex); usleep(1000); } @@ -135,10 +115,10 @@ static int process_command(esl_handle_t *handle, const char *cmd) !strncasecmp(cmd, "nolog", 5) || !strncasecmp(cmd, "filter", 6) ) { - esl_mutex_lock(global_mutex); + esl_send_recv(handle, cmd); - printf("%s\n", handle->last_reply); - esl_mutex_unlock(global_mutex); + printf("%s\n", handle->last_sr_reply); + goto end; } @@ -181,8 +161,6 @@ int main(int argc, char *argv[]) snprintf(cfile, sizeof(cfile), "%s/.fs_cli_config", home); } - esl_mutex_create(&global_mutex); - signal(SIGINT, handle_SIGINT); gethostname(hostname, sizeof(hostname)); @@ -226,9 +204,7 @@ int main(int argc, char *argv[]) snprintf(cmd_str, sizeof(cmd_str), "log info\n\n"); - esl_mutex_lock(global_mutex); esl_send_recv(&handle, cmd_str); - esl_mutex_unlock(global_mutex); while (running) { @@ -254,10 +230,10 @@ int main(int argc, char *argv[]) } } else { snprintf(cmd_str, sizeof(cmd_str), "api %s\n\n", cmd); - esl_mutex_lock(global_mutex); esl_send_recv(&handle, cmd_str); - printf("%s\n", handle.last_event->body); - esl_mutex_unlock(global_mutex); + if (handle.last_sr_event) { + printf("%s\n", handle.last_sr_event->body); + } } el_deletestr(el, strlen(foo) + 1); @@ -283,7 +259,5 @@ int main(int argc, char *argv[]) thread_running = 0; - esl_mutex_destroy(&global_mutex); - return 0; } diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index b5b8f04e11..8e7f73f38e 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -322,6 +322,76 @@ char *esl_url_decode(char *s) return s; } +esl_status_t esl_attach_handle(esl_handle_t *handle, esl_socket_t socket, struct sockaddr_in addr) +{ + handle->sock = socket; + handle->addr = addr; + + if (handle->sock == ESL_SOCK_INVALID) { + return ESL_FAIL; + } + + + if (!handle->mutex) { + esl_mutex_create(&handle->mutex); + } + + handle->connected = 1; + + esl_send_recv(handle, "connect\n\n"); + + + if (handle->last_sr_event) { + handle->info_event = handle->last_sr_event; + handle->last_sr_event = NULL; + return ESL_SUCCESS; + } + + handle->connected = 0; + + return ESL_FAIL; +} + +esl_status_t esl_sendevent(esl_handle_t *handle, esl_event_t *event) +{ + char *txt; + + esl_event_serialize(handle->last_ievent, &txt, ESL_TRUE); + + if (handle->debug) { + esl_log(ESL_LOG_DEBUG, "SEND EVENT\n%s\n", txt); + } + + send(handle->sock, "sendevent\n", 10, 0); + send(handle->sock, txt, strlen(txt), 0); + send(handle->sock, "\n\n", 2, 0); + + free(txt); +} + +esl_status_t esl_execute(esl_handle_t *handle, const char *app, const char *arg, const char *uuid) +{ + char cmd_buf[128] = "sendmsg"; + char app_buf[512] = ""; + char arg_buf[512] = ""; + char send_buf[1292] = ""; + + if (uuid) { + snprintf(cmd_buf, sizeof(cmd_buf), "sendmsg %s", uuid); + } + + if (app) { + snprintf(app_buf, sizeof(app_buf), "execute-app-name: %s\n", app); + } + + if (arg) { + snprintf(arg_buf, sizeof(arg_buf), "execute-app-arg: %s\n", arg); + } + + snprintf(send_buf, sizeof(send_buf), "%s\ncall-command: execute\n%s%s\n", cmd_buf, app_buf, arg_buf); + + esl_send_recv(handle, send_buf); +} esl_status_t esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback) { @@ -386,6 +456,10 @@ esl_status_t esl_connect(esl_handle_t *handle, const char *host, esl_port_t port int rval; const char *hval; + if (!handle->mutex) { + esl_mutex_create(&handle->mutex); + } + handle->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (handle->sock == ESL_SOCK_INVALID) { @@ -450,21 +524,27 @@ esl_status_t esl_connect(esl_handle_t *handle, const char *host, esl_port_t port snprintf(handle->err, sizeof(handle->err), "Connection Error"); goto fail; } - + return ESL_SUCCESS; fail: esl_disconnect(handle); + return ESL_FAIL; } esl_status_t esl_disconnect(esl_handle_t *handle) { esl_event_safe_destroy(&handle->last_event); + esl_event_safe_destroy(&handle->last_sr_event); esl_event_safe_destroy(&handle->last_ievent); esl_event_safe_destroy(&handle->info_event); + if (handle->mutex) { + esl_mutex_destroy(&handle->mutex); + } + if (handle->sock != ESL_SOCK_INVALID) { close(handle->sock); handle->sock = ESL_SOCK_INVALID; @@ -476,7 +556,45 @@ esl_status_t esl_disconnect(esl_handle_t *handle) return ESL_FAIL; } -esl_status_t esl_recv(esl_handle_t *handle) +esl_status_t esl_recv_event_timed(esl_handle_t *handle, uint32_t ms, esl_event_t **save_event) +{ + fd_set rfds, efds; + struct timeval tv = { 0, ms * 1000 }; + int max, activity, i = 0; + esl_status_t status = ESL_SUCCESS; + + esl_mutex_lock(handle->mutex); + FD_ZERO(&rfds); + FD_ZERO(&efds); + FD_SET(handle->sock, &rfds); + FD_SET(handle->sock, &efds); + + max = handle->sock + 1; + + if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) { + status = ESL_FAIL; + goto done; + } + + if (activity && FD_ISSET(handle->sock, &rfds)) { + if (esl_recv_event(handle, save_event)) { + status = ESL_FAIL; + goto done; + } + } else { + status = ESL_BREAK; + } + + done: + + esl_mutex_unlock(handle->mutex); + + return status; + +} + + +esl_status_t esl_recv_event(esl_handle_t *handle, esl_event_t **save_event) { char *c; esl_ssize_t rrval; @@ -489,6 +607,8 @@ esl_status_t esl_recv(esl_handle_t *handle) ssize_t len; int zc = 0; + esl_mutex_lock(handle->mutex); + esl_event_safe_destroy(&handle->last_event); memset(handle->header_buf, 0, sizeof(handle->header_buf)); @@ -501,6 +621,7 @@ esl_status_t esl_recv(esl_handle_t *handle) if (rrval == 0) { if (++zc >= 100) { esl_disconnect(handle); + esl_mutex_unlock(handle->mutex); return ESL_FAIL; } } else if (rrval < 0) { @@ -530,6 +651,7 @@ esl_status_t esl_recv(esl_handle_t *handle) *c = '\0'; if (hname && hval) { + esl_url_decode(hval); if (handle->debug > 1) { esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval); } @@ -572,23 +694,25 @@ esl_status_t esl_recv(esl_handle_t *handle) revent->body = body; } - - - handle->last_event = revent; + if (save_event) { + *save_event = revent; + } else { + handle->last_event = revent; + } - if (handle->last_event) { - const char *hval = esl_event_get_header(handle->last_event, "reply-text"); + if (revent) { + const char *hval = esl_event_get_header(revent, "reply-text"); if (!esl_strlen_zero(hval)) { strncpy(handle->last_reply, hval, sizeof(handle->last_reply)); } - hval = esl_event_get_header(handle->last_event, "content-type"); + hval = esl_event_get_header(revent, "content-type"); - if (!esl_strlen_zero(hval) && !strcasecmp(hval, "text/event-plain") && handle->last_event->body) { + if (!esl_strlen_zero(hval) && !strcasecmp(hval, "text/event-plain") && revent->body) { const char *en; esl_event_types_t et = ESL_EVENT_COMMAND; - char *body = strdup(handle->last_event->body); + char *body = strdup(revent->body); char *beg; char *hname, *hval; char *col; @@ -669,15 +793,15 @@ esl_status_t esl_recv(esl_handle_t *handle) } } + if (handle->debug) { + char *foo; + esl_event_serialize(revent, &foo, ESL_FALSE); + esl_log(ESL_LOG_DEBUG, "RECV MESSAGE\n%s\n", foo); + free(foo); + } } - - if (handle->debug) { - char *foo; - esl_event_serialize(handle->last_event, &foo, ESL_FALSE); - esl_log(ESL_LOG_DEBUG, "RECV MESSAGE\n%s\n", foo); - free(foo); - } + esl_mutex_unlock(handle->mutex); return ESL_SUCCESS; @@ -706,8 +830,21 @@ esl_status_t esl_send(esl_handle_t *handle, const char *cmd) esl_status_t esl_send_recv(esl_handle_t *handle, const char *cmd) { + const char *hval; + + esl_mutex_lock(handle->mutex); esl_send(handle, cmd); - esl_recv(handle); + esl_recv_event(handle, &handle->last_sr_event); + + 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)); + } + } + + esl_mutex_unlock(handle->mutex); } diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h index 4aec7e0d40..d555def0dc 100644 --- a/libs/esl/src/include/esl.h +++ b/libs/esl/src/include/esl.h @@ -34,6 +34,7 @@ #ifndef _ESL_H_ #define _ESL_H_ + #define esl_copy_string(_x, _y, _z) strncpy(_x, _y, _z - 1) #define esl_set_string(_x, _y) esl_copy_string(_x, _y, sizeof(_x)) @@ -193,10 +194,13 @@ typedef int16_t esl_port_t; typedef enum { ESL_SUCCESS, - ESL_FAIL + ESL_FAIL, + ESL_BREAK } esl_status_t; +#include + typedef struct { struct sockaddr_in sockaddr; struct hostent hostent; @@ -206,11 +210,15 @@ typedef struct { int errno; char header_buf[4196]; char last_reply[1024]; + char last_sr_reply[1024]; esl_event_t *last_event; + esl_event_t *last_sr_event; esl_event_t *last_ievent; esl_event_t *info_event; int debug; int connected; + struct sockaddr_in addr; + esl_mutex_t *mutex; } esl_handle_t; typedef enum { @@ -258,13 +266,19 @@ int esl_tolower(int c); typedef void (*esl_listen_callback_t)(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in addr); +esl_status_t esl_attach_handle(esl_handle_t *handle, esl_socket_t socket, struct sockaddr_in addr); esl_status_t esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback); +esl_status_t esl_execute(esl_handle_t *handle, const char *app, const char *arg, const char *uuid); +esl_status_t esl_sendevent(esl_handle_t *handle, esl_event_t *event); esl_status_t esl_connect(esl_handle_t *handle, const char *host, esl_port_t port, const char *password); esl_status_t esl_disconnect(esl_handle_t *handle); esl_status_t esl_send(esl_handle_t *handle, const char *cmd); -esl_status_t esl_recv(esl_handle_t *handle); +esl_status_t esl_recv_event(esl_handle_t *handle, esl_event_t **save_event); +esl_status_t esl_recv_event_timed(esl_handle_t *handle, uint32_t ms, esl_event_t **save_event); esl_status_t esl_send_recv(esl_handle_t *handle, const char *cmd); +#define esl_recv(_h) esl_recv_event(_h, NULL) +#define esl_recv_timed(_h, _ms) esl_recv_event_timed(_h, _ms, NULL) #endif