2008-12-20 00:35:09 +00:00
/*
* 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 .
*/
2011-03-26 10:59:48 -05:00
/* Use select on windows and poll everywhere else.
Select is the devil . Especially if you are doing a lot of small socket connections .
If your FD number is bigger than 1024 you will silently create memory corruption .
If you have build errors on your platform because you don ' t have poll find a way to detect it and # define ESL_USE_SELECT and # undef ESL_USE_POLL
All of this will be upgraded to autoheadache eventually .
*/
/* TBD for win32 figure out how to tell if you have WSAPoll (vista or higher) and use it when available by #defining ESL_USE_WSAPOLL (see below) */
# ifdef _MSC_VER
# define FD_SETSIZE 8192
# define ESL_USE_SELECT
# else
# define ESL_USE_POLL
# endif
2008-12-20 00:35:09 +00:00
# include <esl.h>
2008-12-21 22:13:20 +00:00
# ifndef WIN32
# define closesocket(x) close(x)
2010-07-20 14:42:43 -04:00
# include <fcntl.h>
2010-07-19 15:25:45 -05:00
# else
2010-09-20 09:25:14 -05:00
# pragma warning (disable:6386)
/* These warnings need to be ignored warning in sdk header */
2010-07-19 15:25:45 -05:00
# include <Ws2tcpip.h>
2010-09-20 09:25:14 -05:00
# pragma warning (default:6386)
2008-12-21 22:13:20 +00:00
# endif
2008-12-20 00:35:09 +00:00
2011-03-26 11:07:34 -05:00
# ifdef ESL_USE_POLL
# include <poll.h>
# endif
2008-12-20 00:35:09 +00:00
2008-12-20 05:24:51 +00:00
/* 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_ ;
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( int ) esl_toupper ( int c )
2008-12-20 05:24:51 +00:00
{
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_ ;
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( int ) esl_tolower ( int c )
2008-12-20 05:24:51 +00:00
{
if ( ( unsigned int ) c > 255 )
return ( c ) ;
if ( c < - 1 )
return EOF ;
return ( ( _esl_tolower_tab_ + 1 ) [ c ] ) ;
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( const char * ) esl_stristr ( const char * instr , const char * str )
2008-12-20 05:24:51 +00:00
{
/*
* * 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 ;
}
2008-12-22 18:53:09 +00:00
# ifdef WIN32
# ifndef vsnprintf
# define vsnprintf _vsnprintf
# endif
# endif
2009-01-15 22:11:27 +00:00
int vasprintf ( char * * ret , const char * format , va_list ap ) ;
ESL_DECLARE ( int ) esl_vasprintf ( char * * ret , const char * fmt , va_list ap )
{
# if !defined(WIN32) && !defined(__sun)
return vasprintf ( ret , fmt , ap ) ;
# else
char * buf ;
int len ;
size_t buflen ;
va_list ap2 ;
char * tmp = NULL ;
# ifdef _MSC_VER
# if _MSC_VER >= 1500
/* hack for incorrect assumption in msvc header files for code analysis */
__analysis_assume ( tmp ) ;
# endif
ap2 = ap ;
# else
va_copy ( ap2 , ap ) ;
# endif
len = vsnprintf ( tmp , 0 , fmt , ap2 ) ;
if ( len > 0 & & ( buf = malloc ( ( buflen = ( size_t ) ( len + 1 ) ) ) ) ! = NULL ) {
len = vsnprintf ( buf , buflen , fmt , ap ) ;
* ret = buf ;
} else {
* ret = NULL ;
len = - 1 ;
}
va_end ( ap2 ) ;
return len ;
# endif
}
2008-12-22 18:53:09 +00:00
ESL_DECLARE ( int ) esl_snprintf ( char * buffer , size_t count , const char * fmt , . . . )
{
va_list ap ;
int ret ;
va_start ( ap , fmt ) ;
ret = vsnprintf ( buffer , count - 1 , fmt , ap ) ;
if ( ret < 0 )
buffer [ count - 1 ] = ' \0 ' ;
va_end ( ap ) ;
return ret ;
2008-12-22 16:27:39 +00:00
}
2008-12-20 05:24:51 +00:00
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 ;
2009-01-15 22:11:27 +00:00
char * data ;
2008-12-20 05:24:51 +00:00
va_list ap ;
2009-01-15 22:11:27 +00:00
int ret ;
2008-12-20 05:24:51 +00:00
if ( level < 0 | | level > 7 ) {
level = 7 ;
}
if ( level > esl_log_level ) {
return ;
}
fp = cut_path ( file ) ;
va_start ( ap , fmt ) ;
2009-01-15 22:11:27 +00:00
ret = esl_vasprintf ( & data , fmt , ap ) ;
2008-12-20 05:24:51 +00:00
2009-01-15 22:11:27 +00:00
if ( ret ! = - 1 ) {
2011-04-22 16:43:29 -05:00
fprintf ( stderr , " [%s] %s:%d %s() %s " , LEVEL_NAMES [ level ] , fp , line , func , data ) ;
2009-01-15 22:11:27 +00:00
free ( data ) ;
}
2008-12-20 05:24:51 +00:00
va_end ( ap ) ;
}
esl_logger_t esl_log = null_logger ;
2008-12-22 18:53:09 +00:00
ESL_DECLARE ( void ) esl_global_set_logger ( esl_logger_t logger )
2008-12-20 05:24:51 +00:00
{
if ( logger ) {
esl_log = logger ;
} else {
esl_log = null_logger ;
}
}
2008-12-22 18:53:09 +00:00
ESL_DECLARE ( void ) esl_global_set_default_logger ( int level )
2008-12-20 05:24:51 +00:00
{
if ( level < 0 | | level > 7 ) {
level = 7 ;
}
esl_log = default_logger ;
esl_log_level = level ;
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( size_t ) esl_url_encode ( const char * url , char * buf , size_t len )
2008-12-20 00:35:09 +00:00
{
const char * p ;
size_t x = 0 ;
const char urlunsafe [ ] = " \r \n \" #%&+:;<=>?@[ \\ ]^`{|} " ;
const char hex [ ] = " 0123456789ABCDEF " ;
if ( ! buf ) {
return 0 ;
}
if ( ! url ) {
return 0 ;
}
len - - ;
for ( p = url ; * p ; p + + ) {
if ( x > = len ) {
break ;
}
if ( * p < ' ' | | * p > ' ~ ' | | strchr ( urlunsafe , * p ) ) {
if ( ( x + 3 ) > = len ) {
break ;
}
buf [ x + + ] = ' % ' ;
buf [ x + + ] = hex [ * p > > 4 ] ;
buf [ x + + ] = hex [ * p & 0x0f ] ;
} else {
buf [ x + + ] = * p ;
}
}
buf [ x ] = ' \0 ' ;
return x ;
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( char * ) esl_url_decode ( char * s )
2008-12-20 00:35:09 +00:00
{
char * o ;
unsigned int tmp ;
for ( o = s ; * s ; s + + , o + + ) {
if ( * s = = ' % ' & & strlen ( s ) > 2 & & sscanf ( s + 1 , " %2x " , & tmp ) = = 1 ) {
* o = ( char ) tmp ;
s + = 2 ;
} else {
* o = * s ;
}
}
* o = ' \0 ' ;
return s ;
}
2010-02-22 18:35:21 +00:00
static int sock_setup ( esl_handle_t * handle )
2009-01-15 22:11:27 +00:00
{
2010-02-22 18:35:21 +00:00
if ( handle - > sock = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
2009-02-22 01:42:33 +00:00
# ifdef WIN32
2010-02-22 19:18:11 +00:00
{
BOOL bOptVal = TRUE ;
int bOptLen = sizeof ( BOOL ) ;
setsockopt ( handle - > sock , IPPROTO_TCP , TCP_NODELAY , ( const char * ) & bOptVal , bOptLen ) ;
}
2009-01-15 23:05:50 +00:00
# else
2010-02-22 19:18:11 +00:00
{
int x = 1 ;
setsockopt ( handle - > sock , IPPROTO_TCP , TCP_NODELAY , & x , sizeof ( x ) ) ;
}
2009-01-15 23:05:50 +00:00
# endif
2010-02-22 18:35:21 +00:00
return ESL_SUCCESS ;
2009-01-15 22:11:27 +00:00
}
2009-02-17 00:27:28 +00:00
ESL_DECLARE ( esl_status_t ) esl_attach_handle ( esl_handle_t * handle , esl_socket_t socket , struct sockaddr_in * addr )
2008-12-20 18:34:34 +00:00
{
2010-02-22 18:35:21 +00:00
if ( ! handle | | socket = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
2008-12-20 18:34:34 +00:00
handle - > sock = socket ;
2010-02-22 18:35:21 +00:00
2009-02-17 00:27:28 +00:00
if ( addr ) {
handle - > addr = * addr ;
}
2008-12-20 18:34:34 +00:00
2010-02-22 18:35:21 +00:00
if ( sock_setup ( handle ) ! = ESL_SUCCESS ) {
2008-12-20 18:34:34 +00:00
return ESL_FAIL ;
}
2010-02-22 18:35:21 +00:00
2008-12-20 18:34:34 +00:00
if ( ! handle - > mutex ) {
esl_mutex_create ( & handle - > mutex ) ;
}
2010-12-16 11:33:38 -06:00
if ( ! handle - > packet_buf ) {
esl_buffer_create ( & handle - > packet_buf , BUF_CHUNK , BUF_START , 0 ) ;
}
2008-12-20 18:34:34 +00:00
handle - > connected = 1 ;
esl_send_recv ( handle , " connect \n \n " ) ;
2009-01-15 22:11:27 +00:00
2008-12-20 18:34:34 +00:00
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 ;
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( esl_status_t ) esl_sendevent ( esl_handle_t * handle , esl_event_t * event )
2008-12-20 18:34:34 +00:00
{
char * txt ;
2009-04-02 18:16:59 +00:00
char event_buf [ 256 ] = " " ;
2008-12-20 18:34:34 +00:00
2009-04-02 14:16:58 +00:00
if ( ! handle - > connected | | ! event ) {
2009-01-06 23:40:28 +00:00
return ESL_FAIL ;
}
2009-04-17 15:59:25 +00:00
esl_event_serialize ( event , & txt , ESL_FALSE ) ;
2008-12-20 18:34:34 +00:00
2008-12-31 16:52:11 +00:00
esl_log ( ESL_LOG_DEBUG , " SEND EVENT \n %s \n " , txt ) ;
2009-04-02 18:16:59 +00:00
snprintf ( event_buf , sizeof ( event_buf ) , " sendevent %s \n " , esl_event_name ( event - > event_id ) ) ;
2010-03-05 23:10:41 +00:00
if ( send ( handle - > sock , event_buf , strlen ( event_buf ) , 0 ) < = 0 ) goto fail ;
if ( send ( handle - > sock , txt , strlen ( txt ) , 0 ) < = 0 ) goto fail ;
2010-02-22 18:35:21 +00:00
2008-12-20 18:34:34 +00:00
free ( txt ) ;
2008-12-21 21:54:43 +00:00
2010-03-05 23:10:41 +00:00
return esl_recv ( handle ) ;
2010-02-22 18:35:21 +00:00
fail :
handle - > connected = 0 ;
free ( txt ) ;
return ESL_FAIL ;
2008-12-20 18:34:34 +00:00
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( esl_status_t ) esl_execute ( esl_handle_t * handle , const char * app , const char * arg , const char * uuid )
2008-12-20 18:34:34 +00:00
{
char cmd_buf [ 128 ] = " sendmsg " ;
char app_buf [ 512 ] = " " ;
char arg_buf [ 512 ] = " " ;
2009-02-17 14:13:32 +00:00
const char * el_buf = " event-lock: true \n " ;
2009-03-24 18:03:26 +00:00
const char * bl_buf = " async: true \n " ;
2008-12-20 18:34:34 +00:00
char send_buf [ 1292 ] = " " ;
2010-02-22 18:35:21 +00:00
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
2009-01-06 23:40:28 +00:00
2008-12-20 18:34:34 +00:00
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 ) ;
}
2009-02-17 14:13:32 +00:00
snprintf ( send_buf , sizeof ( send_buf ) , " %s \n call-command: execute \n %s%s%s%s \n " ,
2009-03-24 18:03:26 +00:00
cmd_buf , app_buf , arg_buf , handle - > event_lock ? el_buf : " " , handle - > async_execute ? bl_buf : " " ) ;
2008-12-20 18:34:34 +00:00
2008-12-21 21:54:43 +00:00
return esl_send_recv ( handle , send_buf ) ;
2008-12-20 18:34:34 +00:00
}
2008-12-20 00:35:09 +00:00
2009-01-15 22:11:27 +00:00
2011-09-06 14:53:38 -05:00
ESL_DECLARE ( esl_status_t ) esl_sendmsg ( esl_handle_t * handle , esl_event_t * event , const char * uuid )
{
2011-09-06 15:07:51 -05:00
char cmd_buf [ 128 ] = " sendmsg \n " ;
2011-09-06 14:53:38 -05:00
char * txt ;
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
if ( uuid ) {
2011-09-06 15:07:51 -05:00
snprintf ( cmd_buf , sizeof ( cmd_buf ) , " sendmsg %s \n " , uuid ) ;
2011-09-06 14:53:38 -05:00
}
esl_event_serialize ( event , & txt , ESL_FALSE ) ;
2011-09-06 15:07:51 -05:00
esl_log ( ESL_LOG_DEBUG , " %s%s \n " , cmd_buf , txt ) ;
2011-09-06 14:53:38 -05:00
2011-09-06 15:07:51 -05:00
if ( send ( handle - > sock , cmd_buf , strlen ( cmd_buf ) , 0 ) < = 0 ) goto fail ;
2011-09-06 14:53:38 -05:00
if ( send ( handle - > sock , txt , strlen ( txt ) , 0 ) < = 0 ) goto fail ;
free ( txt ) ;
return esl_recv ( handle ) ;
fail :
handle - > connected = 0 ;
free ( txt ) ;
return ESL_FAIL ;
}
2009-01-15 22:11:27 +00:00
ESL_DECLARE ( esl_status_t ) esl_filter ( esl_handle_t * handle , const char * header , const char * value )
{
char send_buf [ 1024 ] = " " ;
2010-02-22 18:35:21 +00:00
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
2009-01-15 22:11:27 +00:00
snprintf ( send_buf , sizeof ( send_buf ) , " filter %s %s \n \n " , header , value ) ;
return esl_send_recv ( handle , send_buf ) ;
}
ESL_DECLARE ( esl_status_t ) esl_events ( esl_handle_t * handle , esl_event_type_t etype , const char * value )
{
char send_buf [ 1024 ] = " " ;
const char * type = " plain " ;
2010-02-22 18:35:21 +00:00
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
2009-01-15 22:11:27 +00:00
if ( etype = = ESL_EVENT_TYPE_XML ) {
type = " xml " ;
2010-06-17 11:49:16 -05:00
} else if ( etype = = ESL_EVENT_TYPE_JSON ) {
type = " json " ;
2009-01-15 22:11:27 +00:00
}
snprintf ( send_buf , sizeof ( send_buf ) , " event %s %s \n \n " , type , value ) ;
return esl_send_recv ( handle , send_buf ) ;
}
2008-12-22 05:05:44 +00:00
static int esl_socket_reuseaddr ( esl_socket_t socket )
{
# ifdef WIN32
2008-12-22 18:53:09 +00:00
BOOL reuse_addr = TRUE ;
2008-12-22 05:05:44 +00:00
return setsockopt ( socket , SOL_SOCKET , SO_REUSEADDR , ( char * ) & reuse_addr , sizeof ( reuse_addr ) ) ;
# else
int reuse_addr = 1 ;
return setsockopt ( socket , SOL_SOCKET , SO_REUSEADDR , & reuse_addr , sizeof ( reuse_addr ) ) ;
# endif
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( esl_status_t ) esl_listen ( const char * host , esl_port_t port , esl_listen_callback_t callback )
2008-12-20 15:40:33 +00:00
{
esl_socket_t server_sock = ESL_SOCK_INVALID ;
struct sockaddr_in addr ;
esl_status_t status = ESL_SUCCESS ;
if ( ( server_sock = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP ) ) < 0 ) {
return ESL_FAIL ;
}
2008-12-22 05:05:44 +00:00
esl_socket_reuseaddr ( server_sock ) ;
2008-12-20 15:40:33 +00:00
memset ( & addr , 0 , sizeof ( addr ) ) ;
addr . sin_family = AF_INET ;
addr . sin_addr . s_addr = htonl ( INADDR_ANY ) ;
addr . sin_port = htons ( port ) ;
if ( bind ( server_sock , ( struct sockaddr * ) & addr , sizeof ( addr ) ) < 0 ) {
status = ESL_FAIL ;
goto end ;
}
if ( listen ( server_sock , 10000 ) < 0 ) {
status = ESL_FAIL ;
goto end ;
}
for ( ; ; ) {
int client_sock ;
2008-12-22 05:37:54 +00:00
struct sockaddr_in echoClntAddr ;
# ifdef WIN32
int clntLen ;
# else
unsigned int clntLen ;
# endif
2008-12-20 15:40:33 +00:00
clntLen = sizeof ( echoClntAddr ) ;
if ( ( client_sock = accept ( server_sock , ( struct sockaddr * ) & echoClntAddr , & clntLen ) ) = = ESL_SOCK_INVALID ) {
status = ESL_FAIL ;
goto end ;
}
2009-02-22 01:42:33 +00:00
2009-02-17 00:27:28 +00:00
callback ( server_sock , client_sock , & echoClntAddr ) ;
2008-12-20 15:40:33 +00:00
}
end :
if ( server_sock ! = ESL_SOCK_INVALID ) {
2008-12-21 22:13:20 +00:00
closesocket ( server_sock ) ;
2008-12-20 15:40:33 +00:00
server_sock = ESL_SOCK_INVALID ;
}
return status ;
}
2008-12-20 00:35:09 +00:00
2011-03-26 10:59:48 -05:00
/* USE WSAPoll on vista or higher */
# ifdef ESL_USE_WSAPOLL
ESL_DECLARE ( int ) esl_wait_sock ( esl_socket_t sock , uint32_t ms , esl_poll_t flags )
{
}
# endif
# ifdef ESL_USE_SELECT
2011-03-27 12:09:10 -05:00
# ifdef WIN32
# pragma warning( push )
# pragma warning( disable : 6262 ) /* warning C6262: Function uses '98348' bytes of stack: exceeds /analyze:stacksize'16384'. Consider moving some data to heap */
# endif
2011-03-26 10:59:48 -05:00
ESL_DECLARE ( int ) esl_wait_sock ( esl_socket_t sock , uint32_t ms , esl_poll_t flags )
{
int s = 0 , r = 0 ;
fd_set rfds ;
fd_set wfds ;
fd_set efds ;
struct timeval tv ;
2011-03-27 12:09:10 -05:00
FD_ZERO ( & rfds ) ;
FD_ZERO ( & wfds ) ;
FD_ZERO ( & efds ) ;
2011-03-26 10:59:48 -05:00
/* Wouldn't you rather know?? */
assert ( sock < = FD_SETSIZE ) ;
if ( ( flags & ESL_POLL_READ ) ) {
# ifdef WIN32
# pragma warning( push )
# pragma warning( disable : 4127 )
FD_SET ( sock , & rfds ) ;
# pragma warning( pop )
# else
FD_SET ( sock , & rfds ) ;
# endif
}
if ( ( flags & ESL_POLL_WRITE ) ) {
# ifdef WIN32
# pragma warning( push )
# pragma warning( disable : 4127 )
FD_SET ( sock , & wfds ) ;
# pragma warning( pop )
# else
FD_SET ( sock , & wfds ) ;
# endif
}
if ( ( flags & ESL_POLL_ERROR ) ) {
# ifdef WIN32
# pragma warning( push )
# pragma warning( disable : 4127 )
FD_SET ( sock , & efds ) ;
# pragma warning( pop )
# else
FD_SET ( sock , & efds ) ;
# endif
}
tv . tv_sec = ms / 1000 ;
tv . tv_usec = ( ms % 1000 ) * ms ;
s = select ( sock + 1 , ( flags & ESL_POLL_READ ) ? & rfds : NULL , ( flags & ESL_POLL_WRITE ) ? & wfds : NULL , ( flags & ESL_POLL_ERROR ) ? & efds : NULL , & tv ) ;
if ( s < 0 ) {
r = s ;
} else if ( s > 0 ) {
if ( ( flags & ESL_POLL_READ ) & & FD_ISSET ( sock , & rfds ) ) {
r | = ESL_POLL_READ ;
}
if ( ( flags & ESL_POLL_WRITE ) & & FD_ISSET ( sock , & wfds ) ) {
r | = ESL_POLL_WRITE ;
}
if ( ( flags & ESL_POLL_ERROR ) & & FD_ISSET ( sock , & efds ) ) {
r | = ESL_POLL_ERROR ;
}
}
return r ;
}
2011-03-27 12:09:10 -05:00
# ifdef WIN32
# pragma warning( pop )
# endif
2011-03-26 10:59:48 -05:00
# endif
# ifdef ESL_USE_POLL
ESL_DECLARE ( int ) esl_wait_sock ( esl_socket_t sock , uint32_t ms , esl_poll_t flags )
{
struct pollfd pfds [ 2 ] = { { 0 } } ;
int s = 0 , r = 0 ;
pfds [ 0 ] . fd = sock ;
if ( ( flags & ESL_POLL_READ ) ) {
pfds [ 0 ] . events | = POLLIN ;
}
if ( ( flags & ESL_POLL_WRITE ) ) {
pfds [ 0 ] . events | = POLLOUT ;
}
if ( ( flags & ESL_POLL_ERROR ) ) {
pfds [ 0 ] . events | = POLLERR ;
}
s = poll ( pfds , 1 , ms ) ;
if ( s < 0 ) {
r = s ;
} else if ( s > 0 ) {
if ( ( pfds [ 0 ] . revents & POLLIN ) ) {
r | = ESL_POLL_READ ;
}
if ( ( pfds [ 0 ] . revents & POLLOUT ) ) {
r | = ESL_POLL_WRITE ;
}
if ( ( pfds [ 0 ] . revents & POLLERR ) ) {
r | = ESL_POLL_ERROR ;
}
}
return r ;
}
# endif
2010-07-20 17:18:43 -04:00
ESL_DECLARE ( esl_status_t ) esl_connect_timeout ( esl_handle_t * handle , const char * host , esl_port_t port , const char * user , const char * password , uint32_t timeout )
2008-12-20 00:35:09 +00:00
{
char sendbuf [ 256 ] ;
2008-12-21 23:31:57 +00:00
int rval = 0 ;
2008-12-20 00:35:09 +00:00
const char * hval ;
2010-07-19 16:10:41 -04:00
struct addrinfo hints = { 0 } , * result ;
2010-07-20 17:19:30 -04:00
# ifndef WIN32
2010-08-18 18:26:57 -04:00
int fd_flags = 0 ;
2010-07-20 17:19:30 -04:00
# else
2008-12-23 23:26:37 +00:00
WORD wVersionRequested = MAKEWORD ( 2 , 0 ) ;
WSADATA wsaData ;
int err = WSAStartup ( wVersionRequested , & wsaData ) ;
if ( err ! = 0 ) {
snprintf ( handle - > err , sizeof ( handle - > err ) , " WSAStartup Error " ) ;
return ESL_FAIL ;
}
# endif
2008-12-20 00:35:09 +00:00
2008-12-20 18:34:34 +00:00
if ( ! handle - > mutex ) {
esl_mutex_create ( & handle - > mutex ) ;
}
2010-12-16 11:33:38 -06:00
if ( ! handle - > packet_buf ) {
esl_buffer_create ( & handle - > packet_buf , BUF_CHUNK , BUF_START , 0 ) ;
}
2008-12-20 18:34:34 +00:00
2008-12-20 00:35:09 +00:00
handle - > sock = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP ) ;
if ( handle - > sock = = ESL_SOCK_INVALID ) {
snprintf ( handle - > err , sizeof ( handle - > err ) , " Socket Error " ) ;
return ESL_FAIL ;
}
2010-07-19 16:10:41 -04:00
hints . ai_family = AF_INET ;
hints . ai_socktype = SOCK_STREAM ;
2008-12-20 00:35:09 +00:00
2010-07-19 16:10:41 -04:00
if ( getaddrinfo ( host , NULL , & hints , & result ) ) {
strncpy ( handle - > err , " Cannot resolve host " , sizeof ( handle - > err ) ) ;
2008-12-20 00:35:09 +00:00
goto fail ;
}
2010-08-12 11:58:40 -04:00
memcpy ( & handle - > sockaddr , result - > ai_addr , sizeof ( handle - > sockaddr ) ) ;
2010-07-19 16:10:41 -04:00
handle - > sockaddr . sin_family = AF_INET ;
handle - > sockaddr . sin_port = htons ( port ) ;
2010-08-12 11:58:40 -04:00
freeaddrinfo ( result ) ;
2010-07-19 16:10:41 -04:00
2010-07-20 17:18:43 -04:00
if ( timeout ) {
2010-07-20 14:42:43 -04:00
# ifdef WIN32
u_long arg = 1 ;
if ( ioctlsocket ( handle - > sock , FIONBIO , & arg ) = = SOCKET_ERROR ) {
snprintf ( handle - > err , sizeof ( handle - > err ) , " Socket Connection Error " ) ;
goto fail ;
}
# else
fd_flags = fcntl ( handle - > sock , F_GETFL , 0 ) ;
if ( fcntl ( handle - > sock , F_SETFL , fd_flags | O_NONBLOCK ) ) {
snprintf ( handle - > err , sizeof ( handle - > err ) , " Socket Connection Error " ) ;
goto fail ;
}
# endif
}
2010-07-19 16:10:41 -04:00
rval = connect ( handle - > sock , ( struct sockaddr * ) & handle - > sockaddr , sizeof ( handle - > sockaddr ) ) ;
2008-12-20 00:35:09 +00:00
2010-07-20 17:18:43 -04:00
if ( timeout ) {
2010-07-20 14:42:43 -04:00
int r ;
2011-03-26 10:59:48 -05:00
r = esl_wait_sock ( handle - > sock , timeout , ESL_POLL_WRITE ) ;
2010-07-20 14:42:43 -04:00
if ( r < = 0 ) {
snprintf ( handle - > err , sizeof ( handle - > err ) , " Connection timed out " ) ;
goto fail ;
}
2011-03-26 10:59:48 -05:00
if ( ! ( r & ESL_POLL_WRITE ) ) {
2010-07-20 14:42:43 -04:00
snprintf ( handle - > err , sizeof ( handle - > err ) , " Connection timed out " ) ;
goto fail ;
}
# ifdef WIN32
{
u_long arg = 0 ;
if ( ioctlsocket ( handle - > sock , FIONBIO , & arg ) = = SOCKET_ERROR ) {
snprintf ( handle - > err , sizeof ( handle - > err ) , " Socket Connection Error " ) ;
goto fail ;
}
}
# else
fcntl ( handle - > sock , F_SETFL , fd_flags ) ;
# endif
rval = 0 ;
}
2010-07-19 16:10:41 -04:00
result = NULL ;
2008-12-20 00:35:09 +00:00
if ( rval ) {
2008-12-20 05:24:51 +00:00
snprintf ( handle - > err , sizeof ( handle - > err ) , " Socket Connection Error " ) ;
2008-12-20 00:35:09 +00:00
goto fail ;
}
2008-12-20 05:24:51 +00:00
2009-01-15 22:11:27 +00:00
sock_setup ( handle ) ;
2008-12-20 05:24:51 +00:00
handle - > connected = 1 ;
2010-07-20 17:18:43 -04:00
if ( esl_recv_timed ( handle , timeout ) ) {
2008-12-20 00:35:09 +00:00
snprintf ( handle - > err , sizeof ( handle - > err ) , " Connection Error " ) ;
goto fail ;
}
hval = esl_event_get_header ( handle - > last_event , " content-type " ) ;
2009-02-20 01:10:59 +00:00
if ( esl_safe_strcasecmp ( hval , " auth/request " ) ) {
2008-12-20 00:35:09 +00:00
snprintf ( handle - > err , sizeof ( handle - > err ) , " Connection Error " ) ;
goto fail ;
}
2010-01-05 20:37:16 +00:00
if ( esl_strlen_zero ( user ) ) {
snprintf ( sendbuf , sizeof ( sendbuf ) , " auth %s \n \n " , password ) ;
} else {
snprintf ( sendbuf , sizeof ( sendbuf ) , " userauth %s:%s \n \n " , user , password ) ;
}
2008-12-20 00:35:09 +00:00
esl_send ( handle , sendbuf ) ;
2010-07-20 17:18:43 -04:00
if ( esl_recv_timed ( handle , timeout ) ) {
2009-01-26 18:10:19 +00:00
snprintf ( handle - > err , sizeof ( handle - > err ) , " Authentication Error " ) ;
2008-12-20 00:35:09 +00:00
goto fail ;
}
hval = esl_event_get_header ( handle - > last_event , " reply-text " ) ;
2009-02-20 01:10:59 +00:00
if ( esl_safe_strcasecmp ( hval , " +OK accepted " ) ) {
2009-01-26 18:10:19 +00:00
snprintf ( handle - > err , sizeof ( handle - > err ) , " Authentication Error " ) ;
2008-12-20 00:35:09 +00:00
goto fail ;
}
2008-12-20 18:34:34 +00:00
2008-12-20 00:35:09 +00:00
return ESL_SUCCESS ;
fail :
2010-02-22 18:35:21 +00:00
handle - > connected = 0 ;
2010-10-08 09:03:43 -05:00
esl_disconnect ( handle ) ;
2008-12-20 18:34:34 +00:00
2008-12-20 00:35:09 +00:00
return ESL_FAIL ;
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( esl_status_t ) esl_disconnect ( esl_handle_t * handle )
2008-12-20 00:35:09 +00:00
{
2009-01-06 00:18:57 +00:00
esl_mutex_t * mutex = handle - > mutex ;
2009-01-06 23:40:28 +00:00
esl_status_t status = ESL_FAIL ;
2009-01-06 00:18:57 +00:00
2010-02-22 18:35:21 +00:00
if ( handle - > destroyed ) {
return ESL_FAIL ;
}
2009-01-06 00:18:57 +00:00
if ( mutex ) {
esl_mutex_lock ( mutex ) ;
}
2010-02-22 18:35:21 +00:00
handle - > destroyed = 1 ;
handle - > connected = 0 ;
2009-03-14 19:23:07 +00:00
esl_event_safe_destroy ( & handle - > race_event ) ;
2008-12-20 00:35:09 +00:00
esl_event_safe_destroy ( & handle - > last_event ) ;
2008-12-20 18:34:34 +00:00
esl_event_safe_destroy ( & handle - > last_sr_event ) ;
2008-12-20 05:24:51 +00:00
esl_event_safe_destroy ( & handle - > last_ievent ) ;
esl_event_safe_destroy ( & handle - > info_event ) ;
2008-12-20 00:35:09 +00:00
if ( handle - > sock ! = ESL_SOCK_INVALID ) {
2008-12-21 22:13:20 +00:00
closesocket ( handle - > sock ) ;
2008-12-20 00:35:09 +00:00
handle - > sock = ESL_SOCK_INVALID ;
2009-01-06 23:40:28 +00:00
status = ESL_SUCCESS ;
2008-12-20 00:35:09 +00:00
}
2009-01-06 00:18:57 +00:00
if ( mutex ) {
2010-02-22 18:35:21 +00:00
esl_mutex_unlock ( mutex ) ;
esl_mutex_lock ( mutex ) ;
2009-01-06 00:18:57 +00:00
esl_mutex_unlock ( mutex ) ;
esl_mutex_destroy ( & mutex ) ;
}
2010-12-16 11:33:38 -06:00
if ( handle - > packet_buf ) {
esl_buffer_destroy ( & handle - > packet_buf ) ;
}
2009-01-06 00:18:57 +00:00
return status ;
2008-12-20 00:35:09 +00:00
}
2009-03-14 19:23:07 +00:00
ESL_DECLARE ( esl_status_t ) esl_recv_event_timed ( esl_handle_t * handle , uint32_t ms , int check_q , esl_event_t * * save_event )
2008-12-20 18:34:34 +00:00
{
2011-03-26 10:59:48 -05:00
int activity ;
2008-12-20 18:34:34 +00:00
esl_status_t status = ESL_SUCCESS ;
2010-07-20 17:18:43 -04:00
if ( ! ms ) {
return esl_recv_event ( handle , check_q , save_event ) ;
}
2008-12-20 18:34:34 +00:00
2010-02-22 18:35:21 +00:00
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
2009-03-14 19:23:07 +00:00
if ( check_q ) {
esl_mutex_lock ( handle - > mutex ) ;
2010-12-16 11:33:38 -06:00
if ( handle - > race_event | | esl_buffer_packet_count ( handle - > packet_buf ) ) {
2009-03-14 19:23:07 +00:00
esl_mutex_unlock ( handle - > mutex ) ;
return esl_recv_event ( handle , check_q , save_event ) ;
}
esl_mutex_unlock ( handle - > mutex ) ;
}
2011-03-26 10:59:48 -05:00
activity = esl_wait_sock ( handle - > sock , ms , ESL_POLL_READ | ESL_POLL_ERROR ) ;
2008-12-20 18:34:34 +00:00
2011-03-26 10:59:48 -05:00
if ( activity < 0 ) {
2010-02-22 18:35:21 +00:00
handle - > connected = 0 ;
2009-03-14 19:23:07 +00:00
return ESL_FAIL ;
}
2011-03-26 10:59:48 -05:00
if ( activity = = 0 | | ! ( activity & ESL_POLL_READ ) | | ( esl_mutex_trylock ( handle - > mutex ) ! = ESL_SUCCESS ) ) {
2009-03-14 19:23:07 +00:00
return ESL_BREAK ;
2008-12-20 18:34:34 +00:00
}
2011-03-26 10:59:48 -05:00
activity = esl_wait_sock ( handle - > sock , ms , ESL_POLL_READ | ESL_POLL_ERROR ) ;
2010-02-22 18:35:21 +00:00
if ( activity < 0 ) {
handle - > connected = 0 ;
status = ESL_FAIL ;
2011-03-26 10:59:48 -05:00
} else if ( activity > 0 & & ( activity & ESL_POLL_READ ) ) {
2009-03-14 19:23:07 +00:00
if ( esl_recv_event ( handle , check_q , save_event ) ) {
2008-12-20 18:34:34 +00:00
status = ESL_FAIL ;
}
} else {
status = ESL_BREAK ;
}
2008-12-26 20:39:03 +00:00
if ( handle - > mutex ) esl_mutex_unlock ( handle - > mutex ) ;
2008-12-20 18:34:34 +00:00
return status ;
}
2010-12-16 11:33:38 -06:00
static esl_ssize_t handle_recv ( esl_handle_t * handle , void * data , esl_size_t datalen )
{
return recv ( handle - > sock , data , datalen , 0 ) ;
}
2008-12-20 18:34:34 +00:00
2009-03-14 19:23:07 +00:00
ESL_DECLARE ( esl_status_t ) esl_recv_event ( esl_handle_t * handle , int check_q , esl_event_t * * save_event )
2008-12-20 00:35:09 +00:00
{
char * c ;
esl_ssize_t rrval ;
2010-04-13 13:35:38 -05:00
esl_event_t * revent = NULL ;
2008-12-20 00:35:09 +00:00
char * beg ;
char * hname , * hval ;
char * col ;
char * cl ;
2008-12-21 22:13:20 +00:00
esl_ssize_t len ;
2008-12-20 05:24:51 +00:00
int zc = 0 ;
2010-02-22 18:35:21 +00:00
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
2009-01-06 23:40:28 +00:00
return ESL_FAIL ;
}
2010-02-22 18:35:21 +00:00
2008-12-20 18:34:34 +00:00
esl_mutex_lock ( handle - > mutex ) ;
2010-02-22 18:35:21 +00:00
if ( ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
2010-12-16 11:33:38 -06:00
goto fail ;
2010-02-22 18:35:21 +00:00
}
2009-05-01 15:00:31 +00:00
esl_event_safe_destroy ( & handle - > last_ievent ) ;
2009-03-14 19:23:07 +00:00
if ( check_q & & handle - > race_event ) {
2010-04-13 13:35:38 -05:00
revent = handle - > race_event ;
2009-03-14 19:23:07 +00:00
handle - > race_event = handle - > race_event - > next ;
2010-04-13 13:35:38 -05:00
revent - > next = NULL ;
2009-03-14 19:23:07 +00:00
2010-04-13 13:35:38 -05:00
goto parse_event ;
2009-03-14 19:23:07 +00:00
}
2010-12-16 11:33:38 -06:00
while ( ! revent & & handle - > connected ) {
2010-12-16 14:24:54 -06:00
esl_size_t len1 ;
2010-12-16 11:33:38 -06:00
2011-02-22 17:07:18 -06:00
if ( ( len1 = esl_buffer_read_packet ( handle - > packet_buf , handle - > socket_buf , sizeof ( handle - > socket_buf ) - 1 ) ) ) {
2010-12-16 11:33:38 -06:00
char * data = ( char * ) handle - > socket_buf ;
char * p , * e ;
2011-02-22 17:07:18 -06:00
* ( data + len1 ) = ' \0 ' ;
2010-12-16 11:33:38 -06:00
esl_event_create ( & revent , ESL_EVENT_CLONE ) ;
revent - > event_id = ESL_EVENT_SOCKET_DATA ;
esl_event_add_header_string ( revent , ESL_STACK_BOTTOM , " Event-Name " , " SOCKET_DATA " ) ;
hname = p = data ;
2011-02-22 17:07:18 -06:00
2010-12-16 11:33:38 -06:00
while ( p ) {
hname = p ;
p = NULL ;
if ( ( hval = strchr ( hname , ' : ' ) ) ) {
* hval + + = ' \0 ' ;
while ( * hval = = ' ' | | * hval = = ' \t ' ) hval + + ;
if ( ( e = strchr ( hval , ' \n ' ) ) ) {
* e + + = ' \0 ' ;
while ( * e = = ' \n ' | | * e = = ' \r ' ) e + + ;
if ( hname & & hval ) {
esl_url_decode ( hval ) ;
esl_log ( ESL_LOG_DEBUG , " RECV HEADER [%s] = [%s] \n " , hname , hval ) ;
2011-05-25 15:42:36 -05:00
if ( ! strncmp ( hval , " ARRAY:: " , 7 ) ) {
2011-05-26 09:55:41 -05:00
esl_event_add_array ( revent , hname , hval ) ;
2011-05-25 15:42:36 -05:00
} else {
esl_event_add_header_string ( revent , ESL_STACK_BOTTOM , hname , hval ) ;
}
2010-12-16 11:33:38 -06:00
}
p = e ;
}
}
}
2008-12-20 00:35:09 +00:00
2010-12-16 11:33:38 -06:00
break ;
2010-05-28 14:20:20 -05:00
}
2011-02-22 17:07:18 -06:00
rrval = handle_recv ( handle , handle - > socket_buf , sizeof ( handle - > socket_buf ) - 1 ) ;
* ( ( char * ) handle - > socket_buf + rrval ) = ' \0 ' ;
2010-12-16 11:33:38 -06:00
2008-12-20 05:24:51 +00:00
if ( rrval = = 0 ) {
if ( + + zc > = 100 ) {
2010-12-16 11:33:38 -06:00
goto fail ;
2008-12-20 05:24:51 +00:00
}
2010-12-16 11:33:38 -06:00
continue ;
2008-12-20 05:24:51 +00:00
} else if ( rrval < 0 ) {
2008-12-21 22:13:20 +00:00
strerror_r ( handle - > errnum , handle - > err , sizeof ( handle - > err ) ) ;
2008-12-20 00:35:09 +00:00
goto fail ;
2010-12-16 11:33:38 -06:00
}
2008-12-20 00:35:09 +00:00
2010-12-16 11:33:38 -06:00
zc = 0 ;
2008-12-20 00:35:09 +00:00
2010-12-16 11:33:38 -06:00
esl_buffer_write ( handle - > packet_buf , handle - > socket_buf , rrval ) ;
2008-12-20 00:35:09 +00:00
}
2010-12-16 11:33:38 -06:00
2008-12-20 00:35:09 +00:00
if ( ! revent ) {
goto fail ;
}
if ( ( cl = esl_event_get_header ( revent , " content-length " ) ) ) {
char * body ;
esl_ssize_t sofar = 0 ;
len = atol ( cl ) ;
body = malloc ( len + 1 ) ;
esl_assert ( body ) ;
* ( body + len ) = ' \0 ' ;
do {
2010-12-16 11:33:38 -06:00
esl_ssize_t r , s = esl_buffer_inuse ( handle - > packet_buf ) ;
if ( s > = len ) {
sofar = esl_buffer_read ( handle - > packet_buf , body , len ) ;
} else {
2011-02-22 17:07:18 -06:00
r = handle_recv ( handle , handle - > socket_buf , sizeof ( handle - > socket_buf ) - 1 ) ;
* ( ( char * ) handle - > socket_buf + r ) = ' \0 ' ;
2010-12-16 11:33:38 -06:00
if ( r < 0 ) {
strerror_r ( handle - > errnum , handle - > err , sizeof ( handle - > err ) ) ;
goto fail ;
} else if ( r = = 0 ) {
if ( + + zc > = 100 ) {
goto fail ;
}
continue ;
}
zc = 0 ;
esl_buffer_write ( handle - > packet_buf , handle - > socket_buf , r ) ;
2008-12-20 00:35:09 +00:00
}
2010-12-16 11:33:38 -06:00
2008-12-20 00:35:09 +00:00
} while ( sofar < len ) ;
revent - > body = body ;
}
2010-04-13 13:35:38 -05:00
parse_event :
2008-12-20 18:34:34 +00:00
if ( save_event ) {
* save_event = revent ;
2009-03-14 19:23:07 +00:00
revent = NULL ;
2008-12-20 18:34:34 +00:00
} else {
2011-03-10 00:33:43 -06:00
esl_event_safe_destroy ( & handle - > last_event ) ;
2008-12-20 18:34:34 +00:00
handle - > last_event = revent ;
}
2008-12-20 00:35:09 +00:00
2008-12-20 18:34:34 +00:00
if ( revent ) {
2008-12-22 16:44:43 +00:00
hval = esl_event_get_header ( revent , " reply-text " ) ;
2008-12-20 05:24:51 +00:00
if ( ! esl_strlen_zero ( hval ) ) {
strncpy ( handle - > last_reply , hval , sizeof ( handle - > last_reply ) ) ;
2008-12-20 00:35:09 +00:00
}
2008-12-20 05:24:51 +00:00
2008-12-20 18:34:34 +00:00
hval = esl_event_get_header ( revent , " content-type " ) ;
2008-12-20 05:24:51 +00:00
2009-02-21 23:19:58 +00:00
if ( ! esl_safe_strcasecmp ( hval , " text/disconnect-notice " ) & & revent - > body ) {
2011-02-25 16:13:16 -06:00
const char * dval = esl_event_get_header ( revent , " content-disposition " ) ;
if ( esl_strlen_zero ( dval ) | | strcasecmp ( dval , " linger " ) ) {
goto fail ;
}
2009-02-21 23:19:58 +00:00
}
2010-06-17 11:49:16 -05:00
if ( revent - > body ) {
if ( ! esl_safe_strcasecmp ( hval , " text/event-plain " ) ) {
esl_event_types_t et = ESL_EVENT_CLONE ;
char * body = strdup ( revent - > body ) ;
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
esl_event_create ( & handle - > last_ievent , et ) ;
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
beg = body ;
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
while ( beg ) {
if ( ! ( c = strchr ( beg , ' \n ' ) ) ) {
break ;
}
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
hname = beg ;
hval = col = NULL ;
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
if ( hname & & ( col = strchr ( hname , ' : ' ) ) ) {
hval = col + 1 ;
* col = ' \0 ' ;
while ( * hval = = ' ' ) hval + + ;
}
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
* c = ' \0 ' ;
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
if ( hname & & hval ) {
esl_url_decode ( hval ) ;
esl_log ( ESL_LOG_DEBUG , " RECV INNER HEADER [%s] = [%s] \n " , hname , hval ) ;
if ( ! strcasecmp ( hname , " event-name " ) ) {
esl_event_del_header ( handle - > last_ievent , " event-name " ) ;
2011-01-12 16:24:04 -03:00
esl_name_event ( hval , & handle - > last_ievent - > event_id ) ;
2010-06-17 11:49:16 -05:00
}
2011-05-25 15:42:36 -05:00
if ( ! strncmp ( hval , " ARRAY:: " , 7 ) ) {
2011-05-26 09:55:41 -05:00
esl_event_add_array ( handle - > last_ievent , hname , hval ) ;
2011-05-25 15:42:36 -05:00
} else {
esl_event_add_header_string ( handle - > last_ievent , ESL_STACK_BOTTOM , hname , hval ) ;
}
2009-02-21 23:19:58 +00:00
}
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
beg = c + 1 ;
2008-12-20 05:24:51 +00:00
2010-06-17 11:49:16 -05:00
if ( * beg = = ' \n ' ) {
beg + + ;
break ;
}
2009-02-22 01:42:33 +00:00
}
2009-02-21 23:19:58 +00:00
2010-06-17 11:49:16 -05:00
if ( ( cl = esl_event_get_header ( handle - > last_ievent , " content-length " ) ) ) {
handle - > last_ievent - > body = strdup ( beg ) ;
}
2008-12-31 16:52:11 +00:00
2010-06-17 11:49:16 -05:00
free ( body ) ;
2009-02-22 01:42:33 +00:00
2010-06-17 11:49:16 -05:00
if ( esl_log_level > = 7 ) {
char * foo ;
esl_event_serialize ( handle - > last_ievent , & foo , ESL_FALSE ) ;
esl_log ( ESL_LOG_DEBUG , " RECV EVENT \n %s \n " , foo ) ;
free ( foo ) ;
}
} else if ( ! esl_safe_strcasecmp ( hval , " text/event-json " ) ) {
esl_event_create_json ( & handle - > last_ievent , revent - > body ) ;
2008-12-20 05:24:51 +00:00
}
}
2010-06-17 11:49:16 -05:00
2008-12-31 16:52:11 +00:00
if ( esl_log_level > = 7 ) {
2008-12-20 18:34:34 +00:00
char * foo ;
esl_event_serialize ( revent , & foo , ESL_FALSE ) ;
esl_log ( ESL_LOG_DEBUG , " RECV MESSAGE \n %s \n " , foo ) ;
free ( foo ) ;
}
2008-12-20 00:35:09 +00:00
}
2008-12-20 18:34:34 +00:00
esl_mutex_unlock ( handle - > mutex ) ;
2008-12-20 00:35:09 +00:00
return ESL_SUCCESS ;
fail :
2010-12-16 11:33:38 -06:00
esl_mutex_unlock ( handle - > mutex ) ;
2010-02-22 18:35:21 +00:00
handle - > connected = 0 ;
2008-12-20 00:35:09 +00:00
return ESL_FAIL ;
}
2008-12-22 17:59:14 +00:00
ESL_DECLARE ( esl_status_t ) esl_send ( esl_handle_t * handle , const char * cmd )
2008-12-20 00:35:09 +00:00
{
2008-12-20 05:24:51 +00:00
const char * e = cmd + strlen ( cmd ) - 1 ;
2010-02-22 18:35:21 +00:00
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
2009-01-06 23:40:28 +00:00
return ESL_FAIL ;
}
2008-12-31 16:52:11 +00:00
esl_log ( ESL_LOG_DEBUG , " SEND \n %s \n " , cmd ) ;
2008-12-20 00:35:09 +00:00
2008-12-26 17:07:05 +00:00
if ( send ( handle - > sock , cmd , strlen ( cmd ) , 0 ) ! = ( int ) strlen ( cmd ) ) {
2010-02-22 18:35:21 +00:00
handle - > connected = 0 ;
2008-12-21 22:14:10 +00:00
strerror_r ( handle - > errnum , handle - > err , sizeof ( handle - > err ) ) ;
2008-12-21 21:54:43 +00:00
return ESL_FAIL ;
}
2008-12-26 16:43:03 +00:00
2008-12-20 05:24:51 +00:00
if ( ! ( * e = = ' \n ' & & * ( e - 1 ) = = ' \n ' ) ) {
2008-12-26 18:11:31 +00:00
if ( send ( handle - > sock , " \n \n " , 2 , 0 ) ! = 2 ) {
2010-02-22 18:35:21 +00:00
handle - > connected = 0 ;
2008-12-21 22:14:10 +00:00
strerror_r ( handle - > errnum , handle - > err , sizeof ( handle - > err ) ) ;
2008-12-21 21:54:43 +00:00
return ESL_FAIL ;
}
2008-12-20 05:24:51 +00:00
}
2008-12-21 21:54:43 +00:00
return ESL_SUCCESS ;
2008-12-20 00:35:09 +00:00
}
2010-07-20 17:18:43 -04:00
ESL_DECLARE ( esl_status_t ) esl_send_recv_timed ( esl_handle_t * handle , const char * cmd , uint32_t ms )
2008-12-20 00:35:09 +00:00
{
2008-12-20 18:34:34 +00:00
const char * hval ;
2008-12-21 21:54:43 +00:00
esl_status_t status ;
2010-02-22 18:35:21 +00:00
if ( ! handle | | ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
return ESL_FAIL ;
}
2009-03-14 19:23:07 +00:00
2008-12-20 18:34:34 +00:00
esl_mutex_lock ( handle - > mutex ) ;
2008-12-26 16:43:03 +00:00
2010-02-22 18:35:21 +00:00
if ( ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
handle - > connected = 0 ;
esl_mutex_unlock ( handle - > mutex ) ;
return ESL_FAIL ;
}
2009-03-14 19:23:07 +00:00
esl_event_safe_destroy ( & handle - > last_sr_event ) ;
* handle - > last_sr_reply = ' \0 ' ;
2008-12-26 16:43:03 +00:00
if ( ( status = esl_send ( handle , cmd ) ) ) {
2009-03-14 19:23:07 +00:00
esl_mutex_unlock ( handle - > mutex ) ;
2008-12-26 16:43:03 +00:00
return status ;
}
2009-03-14 19:23:07 +00:00
recv :
2010-07-20 17:18:43 -04:00
status = esl_recv_event_timed ( handle , ms , 0 , & handle - > last_sr_event ) ;
2009-03-14 19:23:07 +00:00
2008-12-20 18:34:34 +00:00
if ( handle - > last_sr_event ) {
2009-03-14 19:23:07 +00:00
char * ct = esl_event_get_header ( handle - > last_sr_event , " content-type " ) ;
2008-12-20 18:34:34 +00:00
2009-03-14 19:23:07 +00:00
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 ) ;
2010-02-22 18:35:21 +00:00
if ( ! handle - > connected | | handle - > sock = = ESL_SOCK_INVALID ) {
handle - > connected = 0 ;
esl_mutex_unlock ( handle - > mutex ) ;
return ESL_FAIL ;
}
2009-03-14 19:23:07 +00:00
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 ) ) ;
}
2008-12-20 18:34:34 +00:00
}
}
esl_mutex_unlock ( handle - > mutex ) ;
2008-12-21 21:54:43 +00:00
return status ;
2008-12-20 00:35:09 +00:00
}
2011-05-25 15:42:36 -05:00
ESL_DECLARE ( unsigned int ) esl_separate_string_string ( char * buf , const char * delim , char * * array , unsigned int arraylen )
{
unsigned int count = 0 ;
char * d ;
size_t dlen = strlen ( delim ) ;
array [ count + + ] = buf ;
while ( count < arraylen & & array [ count - 1 ] ) {
if ( ( d = strstr ( array [ count - 1 ] , delim ) ) ) {
* d = ' \0 ' ;
d + = dlen ;
array [ count + + ] = d ;
} else
break ;
}
2008-12-20 00:35:09 +00:00
2011-05-25 15:42:36 -05:00
return count ;
}
2008-12-20 00:35:09 +00:00