[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