[Freeswitch-svn] [commit] r10892 - in freeswitch/trunk/libs/esl: . src src/include
FreeSWITCH SVN
anthm at freeswitch.org
Fri Dec 19 21:24:55 PST 2008
Author: anthm
Date: Sat Dec 20 00:24:51 2008
New Revision: 10892
Log:
work in progress
Added:
freeswitch/trunk/libs/esl/src/esl_config.c
freeswitch/trunk/libs/esl/src/include/esl_config.h
Modified:
freeswitch/trunk/libs/esl/Makefile
freeswitch/trunk/libs/esl/fs_cli.c
freeswitch/trunk/libs/esl/src/esl.c
freeswitch/trunk/libs/esl/src/include/esl.h
Modified: freeswitch/trunk/libs/esl/Makefile
==============================================================================
--- freeswitch/trunk/libs/esl/Makefile (original)
+++ freeswitch/trunk/libs/esl/Makefile Sat Dec 20 00:24:51 2008
@@ -4,7 +4,7 @@
CFLAGS=$(INCS) -g -ggdb -I$(LIBEDIT_DIR)/src/
MYLIB=libesl.a
-OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o
+OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o
all: $(MYLIB) fs_cli
Modified: freeswitch/trunk/libs/esl/fs_cli.c
==============================================================================
--- freeswitch/trunk/libs/esl/fs_cli.c (original)
+++ freeswitch/trunk/libs/esl/fs_cli.c Sat Dec 20 00:24:51 2008
@@ -61,14 +61,18 @@
esl_mutex_unlock(global_mutex);
goto done;
}
-
-
if (activity && FD_ISSET(handle->sock, &rfds)) {
- esl_recv(handle);
+ if (esl_recv(handle)) {
+ running = thread_running = 0;
+ esl_mutex_unlock(global_mutex);
+ esl_log(ESL_LOG_WARNING, "Disconnected.\n");
+ goto done;
+ }
+
if (handle->last_event) {
const char *type = esl_event_get_header(handle->last_event, "content-type");
if (!strcasecmp(type, "log/data")) {
- int level;
+ int level = 0;
if (strstr(handle->last_event->body, "[CONSOLE]")) {
level = 0;
} else if (strstr(handle->last_event->body, "[ALERT]")) {
@@ -88,6 +92,10 @@
}
printf("%s%s%s", COLORS[level], handle->last_event->body, ESL_SEQ_DEFAULT_COLOR);
+ } else if (0 && !strcasecmp(type, "text/disconnect-notice")) {
+ running = thread_running = 0;
+ } else {
+ printf("INCOMING DATA [%s]\n%s", type, handle->last_event->body);
}
}
@@ -106,28 +114,29 @@
static int process_command(esl_handle_t *handle, const char *cmd)
{
- if (!strcasecmp(cmd, "exit")) {
+ if (
+ !strcasecmp(cmd, "exit") ||
+ !strcasecmp(cmd, "quit") ||
+ !strcasecmp(cmd, "bye")
+ ) {
return -1;
}
- if (!strncasecmp(cmd, "loglevel", 8)) {
- const char *level = cmd + 8;
-
- while(*level == ' ') level++;
- if (!esl_strlen_zero(level)) {
- char cb[128] = "";
-
- snprintf(cb, sizeof(cb), "log %s\n\n", level);
- esl_mutex_lock(global_mutex);
- esl_send_recv(handle, cb);
- printf("%s\n", handle->last_reply);
- esl_mutex_unlock(global_mutex);
- }
-
+ if (
+ !strncasecmp(cmd, "event", 5) ||
+ !strncasecmp(cmd, "noevent", 7) ||
+ !strncasecmp(cmd, "nixevent", 8) ||
+ !strncasecmp(cmd, "log", 3) ||
+ !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);
goto end;
}
-
-
+
printf("Unknown command [%s]\n", cmd);
end:
@@ -136,17 +145,35 @@
}
-int main(void)
+typedef struct {
+ char host[128];
+ char pass[128];
+ esl_port_t port;
+} cli_profile_t;
+
+static cli_profile_t profiles[128] = { 0 };
+static int pcount;
+
+int main(int argc, char *argv[])
{
esl_handle_t handle = {0};
int count;
const char *line;
char cmd_str[1024] = "";
char hfile[512] = "/tmp/fs_cli_history";
+ char cfile[512] = "/tmp/fs_cli_config";
char *home = getenv("HOME");
-
+ esl_config_t cfg;
+ cli_profile_t *profile = &profiles[0];
+
+ strncpy(profiles[0].host, "localhost", sizeof(profiles[0].host));
+ strncpy(profiles[0].pass, "ClueCon", sizeof(profiles[0].pass));
+ profiles[0].port = 8021;
+ pcount = 1;
+
if (home) {
snprintf(hfile, sizeof(hfile), "%s/.fs_cli_history", home);
+ snprintf(cfile, sizeof(cfile), "%s/.fs_cli_config", home);
}
esl_mutex_create(&global_mutex);
@@ -155,15 +182,27 @@
gethostname(hostname, sizeof(hostname));
handle.debug = 0;
-
- // um ya add some command line parsing for host port and pass
+
+ if (esl_config_open_file(&cfg, cfile)) {
+ char *var, *val;
+ while (esl_config_next_pair(&cfg, &var, &val)) {
+
+ }
+ esl_config_close_file(&cfg);
+ }
- if (esl_connect(&handle, "localhost", 8021, "ClueCon")) {
+
+ if (esl_connect(&handle, profile->host, profile->port, profile->pass)) {
printf("Error Connecting [%s]\n", handle.err);
- goto done;
+ return -1;
}
-
+
+
+ if (handle.debug) {
+ esl_global_set_default_logger(7);
+ }
+
esl_thread_create_detached(msg_thread_run, &handle);
el = el_init(__FILE__, stdout, stdout, stdout);
Modified: freeswitch/trunk/libs/esl/src/esl.c
==============================================================================
--- freeswitch/trunk/libs/esl/src/esl.c (original)
+++ freeswitch/trunk/libs/esl/src/esl.c Sat Dec 20 00:24:51 2008
@@ -32,6 +32,7 @@
*/
#include <esl.h>
+#include <sys/signal.h>
#ifndef HAVE_GETHOSTBYNAME_R
extern int gethostbyname_r (const char *__name,
@@ -43,6 +44,230 @@
+/* Written by Marc Espie, public domain */
+#define ESL_CTYPE_NUM_CHARS 256
+
+const short _esl_C_toupper_[1 + ESL_CTYPE_NUM_CHARS] = {
+ EOF,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+const short *_esl_toupper_tab_ = _esl_C_toupper_;
+
+int esl_toupper(int c)
+{
+ if ((unsigned int)c > 255)
+ return(c);
+ if (c < -1)
+ return EOF;
+ return((_esl_toupper_tab_ + 1)[c]);
+}
+
+const short _esl_C_tolower_[1 + ESL_CTYPE_NUM_CHARS] = {
+ EOF,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+const short *_esl_tolower_tab_ = _esl_C_tolower_;
+
+int esl_tolower(int c)
+{
+ if ((unsigned int)c > 255)
+ return(c);
+ if (c < -1)
+ return EOF;
+ return((_esl_tolower_tab_ + 1)[c]);
+}
+
+const char *esl_stristr(const char *instr, const char *str)
+{
+/*
+** Rev History: 16/07/97 Greg Thayer Optimized
+** 07/04/95 Bob Stout ANSI-fy
+** 02/03/94 Fred Cole Original
+** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback
+**
+** Hereby donated to public domain.
+*/
+ const char *pptr, *sptr, *start;
+
+ if (!str || !instr)
+ return NULL;
+
+ for (start = str; *start; start++) {
+ /* find start of pattern in string */
+ for (; ((*start) && (esl_toupper(*start) != esl_toupper(*instr))); start++);
+
+ if (!*start)
+ return NULL;
+
+ pptr = instr;
+ sptr = start;
+
+ while (esl_toupper(*sptr) == esl_toupper(*pptr)) {
+ sptr++;
+ pptr++;
+
+ /* if end of pattern then pattern was found */
+ if (!*pptr)
+ return (start);
+
+ if (!*sptr)
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+
+static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
+{
+ if (file && func && line && level && fmt) {
+ return;
+ }
+ return;
+}
+
+
+static const char *LEVEL_NAMES[] = {
+ "EMERG",
+ "ALERT",
+ "CRIT",
+ "ERROR",
+ "WARNING",
+ "NOTICE",
+ "INFO",
+ "DEBUG",
+ NULL
+};
+
+static int esl_log_level = 7;
+
+static const char *cut_path(const char *in)
+{
+ const char *p, *ret = in;
+ char delims[] = "/\\";
+ char *i;
+
+ for (i = delims; *i; i++) {
+ p = in;
+ while ((p = strchr(p, *i)) != 0) {
+ ret = ++p;
+ }
+ }
+ return ret;
+}
+
+
+static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
+{
+ const char *fp;
+ char data[1024];
+ va_list ap;
+
+ if (level < 0 || level > 7) {
+ level = 7;
+ }
+ if (level > esl_log_level) {
+ return;
+ }
+
+ fp = cut_path(file);
+
+ va_start(ap, fmt);
+
+ vsnprintf(data, sizeof(data), fmt, ap);
+
+
+ fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
+
+ va_end(ap);
+
+}
+
+esl_logger_t esl_log = null_logger;
+
+void esl_global_set_logger(esl_logger_t logger)
+{
+ if (logger) {
+ esl_log = logger;
+ } else {
+ esl_log = null_logger;
+ }
+}
+
+void esl_global_set_default_logger(int level)
+{
+ if (level < 0 || level > 7) {
+ level = 7;
+ }
+
+ esl_log = default_logger;
+ esl_log_level = level;
+}
+
size_t esl_url_encode(const char *url, char *buf, size_t len)
{
const char *p;
@@ -138,10 +363,12 @@
rval = connect(handle->sock, (struct sockaddr *) &handle->sockaddr, sizeof(handle->sockaddr));
if (rval) {
- strerror_r(handle->errno, handle->err, sizeof(handle->err));
+ snprintf(handle->err, sizeof(handle->err), "Socket Connection Error");
goto fail;
}
-
+
+ handle->connected = 1;
+
if (esl_recv(handle)) {
snprintf(handle->err, sizeof(handle->err), "Connection Error");
goto fail;
@@ -171,8 +398,6 @@
goto fail;
}
- handle->connected = 1;
-
return ESL_SUCCESS;
fail:
@@ -184,7 +409,9 @@
esl_status_t esl_disconnect(esl_handle_t *handle)
{
esl_event_safe_destroy(&handle->last_event);
-
+ esl_event_safe_destroy(&handle->last_ievent);
+ esl_event_safe_destroy(&handle->info_event);
+
if (handle->sock != ESL_SOCK_INVALID) {
close(handle->sock);
handle->sock = ESL_SOCK_INVALID;
@@ -207,20 +434,29 @@
char *col;
char *cl;
ssize_t len;
-
+ int zc = 0;
+
esl_event_safe_destroy(&handle->last_event);
memset(handle->header_buf, 0, sizeof(handle->header_buf));
c = handle->header_buf;
beg = c;
- for(;;) {
+ while(handle->connected) {
rrval = recv(handle->sock, c, 1, 0);
- if (rrval < 0) {
+ if (rrval == 0) {
+
+ if (++zc >= 100) {
+ esl_disconnect(handle);
+ return ESL_FAIL;
+ }
+ } else if (rrval < 0) {
strerror_r(handle->errno, handle->err, sizeof(handle->err));
goto fail;
- } else if (rrval > 0) {
+ } else {
+ zc = 0;
+
if (*c == '\n') {
if (++crc == 2) {
break;
@@ -243,7 +479,7 @@
if (hname && hval) {
if (handle->debug > 1) {
- printf("RECV HEADER [%s] = [%s]\n", hname, hval);
+ esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
}
esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
}
@@ -289,17 +525,84 @@
handle->last_event = revent;
if (handle->last_event) {
- const char *reply = esl_event_get_header(handle->last_event, "reply-text");
- if (!esl_strlen_zero(reply)) {
- strncpy(handle->last_reply, reply, sizeof(handle->last_reply));
+ const char *hval = esl_event_get_header(handle->last_event, "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");
+
+ if (!esl_strlen_zero(hval) && !strcasecmp(hval, "text/event-plain") && handle->last_event->body) {
+ const char *en;
+ esl_event_types_t et = ESL_EVENT_COMMAND;
+ char *body = strdup(handle->last_event->body);
+ char *beg;
+ char *hname, *hval;
+ char *col;
+ char *cl;
+ ssize_t len;
+ char *c;
+
+ esl_event_safe_destroy(&handle->last_ievent);
+
+ if ((en = esl_stristr("event-name:", body))) {
+ en++;
+ while(*en == ' ') en++;
+ if (en) {
+ esl_name_event(en, &et);
+ }
+ }
+
+ esl_event_create(&handle->last_ievent, et);
+
+ beg = body;
+
+ while(beg) {
+ if (!(c = strchr(beg, '\n'))) {
+ break;
+ }
+
+ 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);
+
+ if (handle->debug > 1) {
+ esl_log(ESL_LOG_DEBUG, "RECV INNER HEADER [%s] = [%s]\n", hname, hval);
+ }
+ esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
+ }
+
+ beg = c + 1;
+ }
+
+ free(body);
+
+ if (handle->debug) {
+ char *foo;
+ esl_event_serialize(handle->last_ievent, &foo, ESL_FALSE);
+ esl_log(ESL_LOG_DEBUG, "RECV EVENT\n%s\n", foo);
+ free(foo);
+ }
}
+
}
if (handle->debug) {
char *foo;
esl_event_serialize(handle->last_event, &foo, ESL_FALSE);
- printf("RECV MESSAGE\n%s\n", foo);
+ esl_log(ESL_LOG_DEBUG, "RECV MESSAGE\n%s\n", foo);
free(foo);
}
@@ -314,11 +617,17 @@
esl_status_t esl_send(esl_handle_t *handle, const char *cmd)
{
+ const char *e = cmd + strlen(cmd) -1;
+
if (handle->debug) {
- printf("SEND\n%s\n", cmd);
+ esl_log(ESL_LOG_DEBUG, "SEND\n%s\n", cmd);
}
send(handle->sock, cmd, strlen(cmd), 0);
+
+ if (!(*e == '\n' && *(e-1) == '\n')) {
+ send(handle->sock, "\n\n", 2, 0);
+ }
}
Added: freeswitch/trunk/libs/esl/src/esl_config.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/esl/src/esl_config.c Sat Dec 20 00:24:51 2008
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "esl.h"
+#include "esl_config.h"
+
+int esl_config_open_file(esl_config_t *cfg, const char *file_path)
+{
+ FILE *f;
+ const char *path = NULL;
+ char path_buf[1024];
+
+ if (file_path[0] == '/') {
+ path = file_path;
+ } else {
+ snprintf(path_buf, sizeof(path_buf), "%s%s%s", ESL_CONFIG_DIR, ESL_PATH_SEPARATOR, file_path);
+ path = path_buf;
+ }
+
+ if (!path) {
+ return 0;
+ }
+
+ memset(cfg, 0, sizeof(*cfg));
+ cfg->lockto = -1;
+ esl_log(ESL_LOG_DEBUG, "Configuration file is %s.\n", path);
+ f = fopen(path, "r");
+
+ if (!f) {
+ if (file_path[0] != '/') {
+ int last = -1;
+ char *var, *val;
+
+ snprintf(path_buf, sizeof(path_buf), "%s%sopenesl.conf", ESL_CONFIG_DIR, ESL_PATH_SEPARATOR);
+ path = path_buf;
+
+ if ((f = fopen(path, "r")) == 0) {
+ return 0;
+ }
+
+ cfg->file = f;
+ esl_set_string(cfg->path, path);
+
+ while (esl_config_next_pair(cfg, &var, &val)) {
+ if ((cfg->sectno != last) && !strcmp(cfg->section, file_path)) {
+ cfg->lockto = cfg->sectno;
+ return 1;
+ }
+ }
+
+ esl_config_close_file(cfg);
+ memset(cfg, 0, sizeof(*cfg));
+ return 0;
+ }
+
+ return 0;
+ } else {
+ cfg->file = f;
+ esl_set_string(cfg->path, path);
+ return 1;
+ }
+}
+
+void esl_config_close_file(esl_config_t *cfg)
+{
+
+ if (cfg->file) {
+ fclose(cfg->file);
+ }
+
+ memset(cfg, 0, sizeof(*cfg));
+}
+
+
+
+int esl_config_next_pair(esl_config_t *cfg, char **var, char **val)
+{
+ int ret = 0;
+ char *p, *end;
+
+ *var = *val = NULL;
+
+ if (!cfg->path) {
+ return 0;
+ }
+
+ for (;;) {
+ cfg->lineno++;
+
+ if (!fgets(cfg->buf, sizeof(cfg->buf), cfg->file)) {
+ ret = 0;
+ break;
+ }
+ *var = cfg->buf;
+
+ if (**var == '[' && (end = strchr(*var, ']')) != 0) {
+ *end = '\0';
+ (*var)++;
+ if (**var == '+') {
+ (*var)++;
+ esl_copy_string(cfg->section, *var, sizeof(cfg->section));
+ cfg->sectno++;
+
+ if (cfg->lockto > -1 && cfg->sectno != cfg->lockto) {
+ break;
+ }
+ cfg->catno = 0;
+ cfg->lineno = 0;
+ *var = (char *) "";
+ *val = (char *) "";
+ return 1;
+ } else {
+ esl_copy_string(cfg->category, *var, sizeof(cfg->category));
+ cfg->catno++;
+ }
+ continue;
+ }
+
+
+
+ if (**var == '#' || **var == ';' || **var == '\n' || **var == '\r') {
+ continue;
+ }
+
+ if (!strncmp(*var, "__END__", 7)) {
+ break;
+ }
+
+
+ if ((end = strchr(*var, ';')) && *(end+1) == *end) {
+ *end = '\0';
+ end--;
+ } else if ((end = strchr(*var, '\n')) != 0) {
+ if (*(end - 1) == '\r') {
+ end--;
+ }
+ *end = '\0';
+ }
+
+ p = *var;
+ while ((*p == ' ' || *p == '\t') && p != end) {
+ *p = '\0';
+ p++;
+ }
+ *var = p;
+
+
+ if ((*val = strchr(*var, '=')) == 0) {
+ ret = -1;
+ /* log_printf(0, server.log, "Invalid syntax on %s: line %d\n", cfg->path, cfg->lineno); */
+ continue;
+ } else {
+ p = *val - 1;
+ *(*val) = '\0';
+ (*val)++;
+ if (*(*val) == '>') {
+ *(*val) = '\0';
+ (*val)++;
+ }
+
+ while ((*p == ' ' || *p == '\t') && p != *var) {
+ *p = '\0';
+ p--;
+ }
+
+ p = *val;
+ while ((*p == ' ' || *p == '\t') && p != end) {
+ *p = '\0';
+ p++;
+ }
+ *val = p;
+ ret = 1;
+ break;
+ }
+ }
+
+
+ return ret;
+
+}
+
+int esl_config_get_cas_bits(char *strvalue, unsigned char *outbits)
+{
+ char cas_bits[5];
+ unsigned char bit = 0x8;
+ char *double_colon = strchr(strvalue, ':');
+ if (!double_colon) {
+ esl_log(ESL_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
+ return -1;
+ }
+ double_colon++;
+ *outbits = 0;
+ cas_bits[4] = 0;
+ if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) {
+ esl_log(ESL_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
+ return -1;
+ }
+ esl_log(ESL_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits);
+ int x = 0;
+ for (; cas_bits[x]; x++) {
+ if ('1' == cas_bits[x]) {
+ *outbits |= bit;
+ } else if ('0' != cas_bits[x]) {
+ esl_log(ESL_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n");
+ return -1;
+ }
+ bit >>= 1;
+ }
+ return 0;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
Modified: freeswitch/trunk/libs/esl/src/include/esl.h
==============================================================================
--- freeswitch/trunk/libs/esl/src/include/esl.h (original)
+++ freeswitch/trunk/libs/esl/src/include/esl.h Sat Dec 20 00:24:51 2008
@@ -34,6 +34,9 @@
#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))
+
typedef struct esl_event_header esl_event_header_t;
typedef struct esl_event esl_event_t;
@@ -204,6 +207,8 @@
char header_buf[4196];
char last_reply[1024];
esl_event_t *last_event;
+ esl_event_t *last_ievent;
+ esl_event_t *info_event;
int debug;
int connected;
} esl_handle_t;
@@ -213,12 +218,44 @@
ESL_FALSE = 0
} esl_bool_t;
+#ifndef __FUNCTION__
+#define __FUNCTION__ (const char *)__func__
+#endif
+
+#define ESL_PRE __FILE__, __FUNCTION__, __LINE__
+#define ESL_LOG_LEVEL_DEBUG 7
+#define ESL_LOG_LEVEL_INFO 6
+#define ESL_LOG_LEVEL_NOTICE 5
+#define ESL_LOG_LEVEL_WARNING 4
+#define ESL_LOG_LEVEL_ERROR 3
+#define ESL_LOG_LEVEL_CRIT 2
+#define ESL_LOG_LEVEL_ALERT 1
+#define ESL_LOG_LEVEL_EMERG 0
+
+#define ESL_LOG_DEBUG ESL_PRE, ESL_LOG_LEVEL_DEBUG
+#define ESL_LOG_INFO ESL_PRE, ESL_LOG_LEVEL_INFO
+#define ESL_LOG_NOTICE ESL_PRE, ESL_LOG_LEVEL_NOTICE
+#define ESL_LOG_WARNING ESL_PRE, ESL_LOG_LEVEL_WARNING
+#define ESL_LOG_ERROR ESL_PRE, ESL_LOG_LEVEL_ERROR
+#define ESL_LOG_CRIT ESL_PRE, ESL_LOG_LEVEL_CRIT
+#define ESL_LOG_ALERT ESL_PRE, ESL_LOG_LEVEL_ALERT
+#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, ...);
+
+extern esl_logger_t esl_log;
+
+void esl_global_set_logger(esl_logger_t logger);
+void esl_global_set_default_logger(int level);
#include "esl_event.h"
#include "esl_threadmutex.h"
+#include "esl_config.h"
size_t esl_url_encode(const char *url, char *buf, size_t len);
char *esl_url_decode(char *s);
+int esl_toupper(int c);
+int esl_tolower(int c);
+
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);
@@ -226,7 +263,6 @@
esl_status_t esl_recv(esl_handle_t *handle);
esl_status_t esl_send_recv(esl_handle_t *handle, const char *cmd);
-
#endif
Added: freeswitch/trunk/libs/esl/src/include/esl_config.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/esl/src/include/esl_config.h Sat Dec 20 00:24:51 2008
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2007, Anthony Minessale II
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup config Config File Parser
+ * @ingroup config
+ * This module implements a basic interface and file format parser
+ *
+ * <pre>
+ *
+ * EXAMPLE
+ *
+ * [category1]
+ * var1 => val1
+ * var2 => val2
+ * \# lines that begin with \# are comments
+ * \#var3 => val3
+ * </pre>
+ * @{
+ */
+
+#ifndef ESL_CONFIG_H
+#define ESL_CONFIG_H
+
+#include "esl.h"
+#define ESL_URL_SEPARATOR "://"
+
+
+#ifdef WIN32
+#define ESL_PATH_SEPARATOR "\\"
+#ifndef ESL_CONFIG_DIR
+#define ESL_CONFIG_DIR "c:\\openesl"
+#endif
+#define esl_is_file_path(file) (*(file +1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR))
+#else
+#define ESL_PATH_SEPARATOR "/"
+#ifndef ESL_CONFIG_DIR
+#define ESL_CONFIG_DIR "/etc/openesl"
+#endif
+#define esl_is_file_path(file) ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR))
+#endif
+
+typedef struct esl_config esl_config_t;
+
+/*! \brief A simple file handle representing an open configuration file **/
+struct esl_config {
+ /*! FILE stream buffer to the opened file */
+ FILE *file;
+ /*! path to the file */
+ char path[512];
+ /*! current category */
+ char category[256];
+ /*! current section */
+ char section[256];
+ /*! buffer of current line being read */
+ char buf[1024];
+ /*! current line number in file */
+ int lineno;
+ /*! current category number in file */
+ int catno;
+ /*! current section number in file */
+ int sectno;
+
+ int lockto;
+};
+
+/*!
+ \brief Open a configuration file
+ \param cfg (esl_config_t *) config handle to use
+ \param file_path path to the file
+ \return 1 (true) on success 0 (false) on failure
+*/
+int esl_config_open_file(esl_config_t * cfg, const char *file_path);
+
+/*!
+ \brief Close a previously opened configuration file
+ \param cfg (esl_config_t *) config handle to use
+*/
+void esl_config_close_file(esl_config_t * cfg);
+
+/*!
+ \brief Retrieve next name/value pair from configuration file
+ \param cfg (esl_config_t *) config handle to use
+ \param var pointer to aim at the new variable name
+ \param val pointer to aim at the new value
+*/
+int esl_config_next_pair(esl_config_t * cfg, char **var, char **val);
+
+/*!
+ \brief Retrieve the CAS bits from a configuration string value
+ \param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx)
+ \param outbits pointer to aim at the CAS bits
+*/
+int esl_config_get_cas_bits(char *strvalue, unsigned char *outbits);
+
+
+/** @} */
+#endif
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
More information about the Freeswitch-svn
mailing list