From f2be31595f950b48705c0c349a4730f8977edadf Mon Sep 17 00:00:00 2001 From: Ron Pedde Date: Sat, 18 Aug 2007 01:15:51 +0000 Subject: [PATCH] add io_ functions for plugins --- src/ff-plugin-events.h | 26 +++++ src/ff-plugins.c | 239 +++++++++++++++++++++++++++++++++++++++++ src/ff-plugins.h | 41 +++---- src/io.c | 62 +++++------ src/io.h | 3 - src/plugin.h | 3 +- src/webserver.c | 124 ++++++++++----------- 7 files changed, 380 insertions(+), 118 deletions(-) create mode 100644 src/ff-plugin-events.h diff --git a/src/ff-plugin-events.h b/src/ff-plugin-events.h new file mode 100644 index 00000000..cd4a2d5d --- /dev/null +++ b/src/ff-plugin-events.h @@ -0,0 +1,26 @@ + + +#ifndef _FF_PLUGIN_EVENTS_H_ +#define _FF_PLUGIN_EVENTS_H_ + +/* Plugin types */ +#define PLUGIN_OUTPUT 1 +#define PLUGIN_SCANNER 2 +#define PLUGIN_DATABASE 4 +#define PLUGIN_EVENT 8 +#define PLUGIN_TRANSCODE 16 + +/* plugin event types */ +#define PLUGIN_EVENT_LOG 0 +#define PLUGIN_EVENT_FULLSCAN_START 1 +#define PLUGIN_EVENT_FULLSCAN_END 2 +#define PLUGIN_EVENT_STARTING 3 +#define PLUGIN_EVENT_SHUTDOWN 4 +#define PLUGIN_EVENT_STARTSTREAM 5 +#define PLUGIN_EVENT_ABORTSTREAM 6 +#define PLUGIN_EVENT_ENDSTREAM 7 + +#define PLUGIN_VERSION 1 + + +#endif /* _FF_PLUGIN_EVENTS_ */ diff --git a/src/ff-plugins.c b/src/ff-plugins.c index 2828ec2f..6b050604 100644 --- a/src/ff-plugins.c +++ b/src/ff-plugins.c @@ -7,6 +7,7 @@ #include #include +#include "bsd-snprintf.h" #include "conf.h" #include "configfile.h" #include "daapd.h" @@ -14,6 +15,7 @@ #include "err.h" #include "ff-dbstruct.h" #include "ff-plugins.h" +#include "io.h" #include "mp3-scanner.h" #include "plugin.h" #include "util.h" @@ -526,4 +528,241 @@ EXPORT int pi_conf_get_int(char *section, char *key, int dflt) { } EXPORT void pi_config_set_status(WS_CONNINFO *pwsc, int session, char *fmt, ...) { + char *out; + va_list ap; + + ASSERT(fmt); + if(!fmt) + return; + + va_start(ap,fmt); + out = util_vasprintf(fmt,ap); + va_end(ap); + + config_set_status(pwsc, session, "%s", out); + free(out); +} + +/** + * allocte an io object + * + * @returns NULL on malloc error, IOHANDLE otherwise + */ +EXPORT IOHANDLE pi_io_new(void) { + return io_new(); +} + +/** + * open an io object given a printf-style URI + * + * @param io io handle allocated with pi_io_new + * @param fmt printf-style format string for URI (%U URI-encodes strings) + * @returns TRUE on success, FALSE otherwise. use io_err* to get error info + */ +EXPORT int pi_io_open(IOHANDLE io, char *fmt, ...) { + char uri_copy[4096]; + va_list ap; + + va_start(ap, fmt); + io_util_vsnprintf(uri_copy, sizeof(uri_copy), fmt, ap); + va_end(ap); + + return io_open(io, "%s", uri_copy); +} + +/** + * close an open io_object + * + * @param io handle to close + * @returns TRUE on success, FALSE otherwise + */ +EXPORT int pi_io_close(IOHANDLE io) { + return io_close(io); +} + +/** + * read from an open io handle + * + * @param io open handle to read from + * @param buf buffer to read into + * @param len length to read, on return: length read + * @returns TRUE on success, FALSE otherwise, len set with bytes read + */ +EXPORT int pi_io_read(IOHANDLE io, unsigned char *buf, uint32_t *len){ + return io_read(io, buf, len); +} + +/** + * read from an io handle with timeout + * + * Returns FALSE on read error or timeout. Timeout versus + * read error condition can be determined by ms. If ms is 0, + * then a timeout condition occurred + * + * @param io open handle to read from + * @param buf buffer to read into + * @param len length to read, on return: length read + * @param ms time to wait (in ms), on return: time left + * @returns TRUE on success, FALSE on failure (or timeout) + */ +EXPORT int pi_io_read_timeout(IOHANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms) { + return io_read_timeout(io, buf, len, ms); +} + +/** + * write a block of data to an open io handle + * + * @param io io handle to write to + * @param buf buffer to write from + * @param len bytes to write to io handle, on return: bytes written + * @returns TRUE on success, FALSE otherwise + */ +EXPORT int pi_io_write(IOHANDLE io, unsigned char *buf, uint32_t *len) { + return io_write(io, buf, len); +} + +/** + * write a printf formatted string to io handle + * + * @param io io handle to write to + * @param fmt printf style format specifier + * @returns TRUE on success, FALSE otherwise + */ +EXPORT int pi_io_printf(IOHANDLE io, char *fmt, ...) { + char *out; + va_list ap; + int result; + + ASSERT(fmt); + if(!fmt) + return FALSE; + + va_start(ap,fmt); + out = util_vasprintf(fmt,ap); + va_end(ap); + + result = io_printf(io,"%s",out); + free(out); + + return result; +} + +/** + * get the (64-bit) size of a file. Built in URI's use seekability + * to determine extent of file, so non-seekable io objects (sockets, etc) + * will return IO_E_BADFN. + * + * @param io io handle to get size of + * @param size returns the 64-bit size of file + * @returns TRUE on success, FALSE on error (check io_errstr) + */ +EXPORT int pi_io_size(IOHANDLE io, uint64_t *size) { + return io_size(io, size); +} + +/** + * set the position of file read handle. There are several limitations + * to this. Non seekable handles (sockets, etc) won't seek, NOT + * EVEN FORWARD! + * + * FIXME: seeking on buffered file handle makes explode + * + * @param io handle to set position of + * @param offset how far to move + * @param whence from where (in lseek style -- SEEK_SET, SEEK_CUR, SEEK_END) + * @returns TRUE on success, FALSE otherwise (check io_errstr) + */ +EXPORT int pi_io_setpos(IOHANDLE io, uint64_t offset, int whence) { + return io_setpos(io, offset, whence); +} + +/** + * get current file position in a stream. Like setpos, this won't work on non- + * streamable io handles, and it won't (currently) work on buffered file handles. + * in addition, it might behave strangely various filter drivers (ssl, etc) + * + * @param io io handle to get position for + * @param pos on return, the current file position + * @returns TRUE on success, FALSE otherwise (see io_errstr) + */ +EXPORT int pi_io_getpos(IOHANDLE io, uint64_t *pos) { + return io_getpos(io, pos); +} + + +/** + * turn on buffering for a file handle. This really only makes sense + * when doing readlines. Note that you can't currently turn of buffered + * mode, so if doing a mix of buffered and unbuffered io, don't buffer the + * handle. Also, once the handle is buffered, setpos and getpos won't work + * right, and will very likely make Bad Things Happen. You have been + * warned. + * + * @param io handle to buffer + * @returns TRUE + */ +EXPORT int pi_io_buffer(IOHANDLE io) { + return io_buffer(io); +} + +/** + * read a line from the file handle. If the file is opened with + * ascii=1, then line ending conversions to/from windows/unix will + * take place. + * + * @param io handle to read line from + * @param buf buffer to read line into + * @param len size of buffer, on return: bytes read + * @returns TRUE on success, FALSE on error (see io_errstr) + */ +EXPORT int pi_io_readline(IOHANDLE io, unsigned char *buf, uint32_t *len) { + return io_readline(io, buf, len); +} + +/** + * read a line from a file handle with timeout. + * + * Errors (including timeout) return FALSE. Timeout errors + * can be detected because ms=0 + * + * @param io handle to read from + * @param buf buffer to read into + * @param len size of buffer, on return: bytes read + * @param ms timeout, in ms, on return: time remaining + * @returns TRUE on success, FALSE otherwise + */ +EXPORT int pi_io_readline_timeout(IOHANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms) { + return io_readline_timeout(io, buf, len, ms); +} + +/** + * get error string of last error + * + * @param io handle to get error of + * @returns error string, does not need to be free'd + */ +EXPORT char* pi_io_errstr(IOHANDLE io) { + return io_errstr(io); +} + +/** + * get native error code + * + * @param io handle to get error code for + * @returns error code (see io-errors.h) + */ +EXPORT int pi_io_errcode(IOHANDLE io) { + return io_errcode(io); +} + +/** + * dispose of an io handle, freeing up any internally allocated + * memory and structs. This implicitly calls io_close, so + * you don't *need* to do io_close(hio); io_dispoase(hio);, but I + * do anyway. :) + * + * @param io handle to dispose of + */ +EXPORT void pi_io_dispose(IOHANDLE io) { + return io_dispose(io); } diff --git a/src/ff-plugins.h b/src/ff-plugins.h index a153fc20..1c6a80e8 100644 --- a/src/ff-plugins.h +++ b/src/ff-plugins.h @@ -23,6 +23,7 @@ #define _FF_PLUGINS_H_ #include "ff-dbstruct.h" +#include "ff-plugin-events.h" #ifdef WIN32 # ifdef _WINDLL @@ -40,25 +41,6 @@ #define FALSE 0 #endif -/* Plugin types */ -#define PLUGIN_OUTPUT 1 -#define PLUGIN_SCANNER 2 -#define PLUGIN_DATABASE 4 -#define PLUGIN_EVENT 8 -#define PLUGIN_TRANSCODE 16 - -/* plugin event types */ -#define PLUGIN_EVENT_LOG 0 -#define PLUGIN_EVENT_FULLSCAN_START 1 -#define PLUGIN_EVENT_FULLSCAN_END 2 -#define PLUGIN_EVENT_STARTING 3 -#define PLUGIN_EVENT_SHUTDOWN 4 -#define PLUGIN_EVENT_STARTSTREAM 5 -#define PLUGIN_EVENT_ABORTSTREAM 6 -#define PLUGIN_EVENT_ENDSTREAM 7 - -#define PLUGIN_VERSION 1 - #ifndef E_FATAL # define E_FATAL 0 # define E_LOG 1 @@ -72,6 +54,7 @@ #define COUNT_PLAYLISTS 1 struct tag_ws_conninfo; +typedef void* HANDLE; /* Functions that must be exported by different plugin types */ typedef struct tag_plugin_output_fn { @@ -178,11 +161,29 @@ extern EXPORT int pi_db_wait_update(struct tag_ws_conninfo *); extern EXPORT char *pi_conf_alloc_string(char *section, char *key, char *dflt); extern EXPORT void pi_conf_dispose_string(char *str); extern EXPORT int pi_conf_get_int(char *section, char *key, int dflt); - extern EXPORT void pi_config_set_status(struct tag_ws_conninfo *pwsc, int session, char *fmt, ...); +/* io functions */ +extern EXPORT HANDLE pi_io_new(void); +extern EXPORT int pi_io_open(HANDLE io, char *fmt, ...); +extern EXPORT int pi_io_close(HANDLE io); +extern EXPORT int pi_io_read(HANDLE io, unsigned char *buf, uint32_t *len); +extern EXPORT int pi_io_read_timeout(HANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms); +extern EXPORT int pi_io_write(HANDLE io, unsigned char *buf, uint32_t *len); +extern EXPORT int pi_io_printf(HANDLE io, char *fmt, ...); +extern EXPORT int pi_io_size(HANDLE io, uint64_t *size); +extern EXPORT int pi_io_setpos(HANDLE io, uint64_t offset, int whence); +extern EXPORT int pi_io_getpos(HANDLE io, uint64_t *pos); +extern EXPORT int pi_io_buffer(HANDLE io); /* unimplemented */ +extern EXPORT int pi_io_readline(HANDLE io, unsigned char *buf, uint32_t *len); +extern EXPORT int pi_io_readline_timeout(HANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms); +extern EXPORT char* pi_io_errstr(HANDLE io); +extern EXPORT int pi_io_errcode(HANDLE io); +extern EXPORT void pi_io_dispose(HANDLE io); + #ifdef __cplusplus } #endif + #endif /* _FF_PLUGINS_ */ diff --git a/src/io.c b/src/io.c index e6bdc8ff..d6d3c2b6 100644 --- a/src/io.c +++ b/src/io.c @@ -113,7 +113,7 @@ int io_setpos(IO_PRIVHANDLE *phandle, uint64_t offset, int whence); int io_getpos(IO_PRIVHANDLE *phandle, uint64_t *pos); int io_buffer(IO_PRIVHANDLE *phandle); int io_readline(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len); -int io_readline_timed(IO_PRIVHANDLE *phandle, unsigned char *buf, +int io_readline_timeout(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len, uint32_t *ms); char *io_errstr(IO_PRIVHANDLE *phandle); void io_dispose(IO_PRIVHANDLE *phandle); @@ -404,7 +404,7 @@ int io_urldecode(char *str) { char *current,*dst; int digit1, digit2; char *hexdigits = "0123456789abcdef"; - + current = dst = str; while(*current) { switch(*current) { @@ -419,7 +419,7 @@ int io_urldecode(char *str) { return FALSE; } current++; - + if(!strchr(hexdigits,tolower(*current))) { io_err_printf(IO_LOG_DEBUG,"urldecode: bad hex digit\n"); return FALSE; @@ -441,7 +441,7 @@ int io_urldecode(char *str) { break; } } - + *dst = '\0'; return TRUE; } @@ -664,7 +664,7 @@ int io_open(IO_PRIVHANDLE *phandle, char *fmt, ...) { if(path_part) io_urldecode(path_part); - + /* find the start of the options */ options_part = strchr(path_part,'?'); if(options_part) { @@ -771,7 +771,7 @@ int io_read_timeout(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len, ASSERT(phandle->fnptr->fn_read); io_err_printf(IO_LOG_SPAM,"entering io_read_timeout\n"); - + if((!phandle) || (!phandle->open) || (!phandle->fnptr)) { io_err(phandle,IO_E_NOTINIT); *len = 0; @@ -826,7 +826,7 @@ int io_read(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { ASSERT(phandle->fnptr->fn_read); io_err_printf(IO_LOG_SPAM,"entering io_read\n"); - + if((!phandle) || (!phandle->open) || (!phandle->fnptr)) { io_err(phandle,IO_E_NOTINIT); *len = 0; @@ -846,7 +846,7 @@ int io_read(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { /* fill as much as possible from buffer */ if(phandle->buffer_offset < phandle->buffer_len) { io_err_printf(IO_LOG_SPAM,"Fulfilling from buffer\n"); - read_size = max_len; + read_size = max_len; if(read_size > (phandle->buffer_len - phandle->buffer_offset)) read_size = phandle->buffer_len - phandle->buffer_offset; memcpy((void*)buf_ptr,(void*)&phandle->buffer[phandle->buffer_offset], read_size); @@ -863,7 +863,7 @@ int io_read(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { return FALSE; } phandle->buffer_offset = 0; - if(phandle->buffer_len == 0) + if(phandle->buffer_len == 0) return TRUE; /* can't read any more */ } } @@ -894,17 +894,17 @@ int io_read(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { * @returns TRUE on success, FALSE with ms=0 on timeout, or FALSE * on other kind of error */ -int io_readline_timed(IO_PRIVHANDLE *phandle, unsigned char *buf, +int io_readline_timeout(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len, uint32_t *ms) { uint32_t numread = 0; uint32_t to_read; int ascii = 0; - + if(io_option_get(phandle,"ascii",NULL)) ascii = 1; - - io_err_printf(IO_LOG_SPAM,"entering readline_timed\n"); - + + io_err_printf(IO_LOG_SPAM,"entering readline_timeout\n"); + while(numread < (*len - 1)) { to_read = 1; if(io_read_timeout(phandle, buf + numread, &to_read, ms)) { @@ -946,7 +946,7 @@ int io_readline(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { io_err_printf(IO_LOG_SPAM,"entering io_readline\n"); - return io_readline_timed(phandle, buf, len, NULL); + return io_readline_timeout(phandle, buf, len, NULL); } @@ -969,13 +969,13 @@ int io_write(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { uint32_t ascii_len; uint32_t index; uint32_t real_len; - + ASSERT(io_initialized); /* call io_init first */ ASSERT(phandle); ASSERT(phandle->open); ASSERT(phandle->fnptr); ASSERT(phandle->fnptr->fn_write); - + if((!phandle) || (!phandle->open) || (!phandle->fnptr)) { io_err(phandle,IO_E_NOTINIT); *len = 0; @@ -1006,7 +1006,7 @@ int io_write(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { io_err_printf(IO_LOG_FATAL,"Could not alloc buffer in io_printf\n"); exit(-1); } - + must_free = TRUE; dst = real_buffer; for(index = 0; index < *len; index++) { @@ -1019,7 +1019,7 @@ int io_write(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { real_buffer = buf; /* just write what was passed */ real_len = *len; } - + result = phandle->fnptr->fn_write(phandle,real_buffer,&real_len); if(!result) @@ -1030,7 +1030,7 @@ int io_write(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) { real_len = *len; free(real_buffer); } - + *len = real_len; return result; } @@ -1083,7 +1083,7 @@ int io_printf(IO_PRIVHANDLE *phandle, char *fmt, ...) { if(!io_write(phandle,(unsigned char *)outbuf,&len) || (len != new_size)) { return FALSE; } - + return TRUE; } @@ -1194,10 +1194,10 @@ int io_getpos(IO_PRIVHANDLE *phandle, uint64_t *pos) { */ int io_buffer(IO_PRIVHANDLE *phandle) { ASSERT(phandle); - - if(!phandle) + + if(!phandle) return FALSE; - + if(phandle->buffer) return TRUE; @@ -1206,9 +1206,9 @@ int io_buffer(IO_PRIVHANDLE *phandle) { io_err_printf(IO_LOG_FATAL,"Malloc error in io_buffer\n"); exit(-1); } - + phandle->buffering=1; - + return TRUE; } @@ -1285,7 +1285,7 @@ void io_err(IO_PRIVHANDLE *phandle, uint32_t errorcode) { free(phandle->err_str); phandle->err = errorcode; - + if(errorcode) { phandle->err_str = strdup(io_err_strings[errorcode & 0x00FFFFFF]); phandle->err = errorcode; @@ -1778,10 +1778,10 @@ char *io_file_geterrmsg(IO_PRIVHANDLE *phandle, ERR_T *code, int *is_local) { if(!priv) { return "file not initialized"; } - + if(code) *code = priv->err; - + if(priv->local_err) { if(is_local) *is_local = TRUE; @@ -2400,7 +2400,7 @@ void io_socket_seterr(IO_PRIVHANDLE *phandle, ERR_T errcode) { */ char *io_socket_geterrmsg(IO_PRIVHANDLE *phandle, ERR_T *code, int *is_local) { IO_SOCKET_PRIV *priv; - + #ifdef WIN32 char lpErrorBuf[256]; #endif @@ -2410,7 +2410,7 @@ char *io_socket_geterrmsg(IO_PRIVHANDLE *phandle, ERR_T *code, int *is_local) { priv = (IO_SOCKET_PRIV*)(phandle->private); if(*code) *code = priv->err; - + if(priv->local_err) { *is_local = TRUE; return strdup(io_socket_err_strings[priv->err & 0x00FFFFFF]); diff --git a/src/io.h b/src/io.h index 0eca2e34..d380f34a 100644 --- a/src/io.h +++ b/src/io.h @@ -67,9 +67,6 @@ extern int io_close(IOHANDLE io); extern int io_read(IOHANDLE io, unsigned char *buf, uint32_t *len); extern int io_read_timeout(IOHANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms); -extern int io_readline(IOHANDLE io, unsigned char *buf, uint32_t *len); -extern int io_readline_timed(IOHANDLE io, unsigned char *buf, uint32_t *len, - uint32_t *ms); extern int io_write(IOHANDLE io, unsigned char *buf, uint32_t *len); extern int io_printf(IOHANDLE io, char *fmt, ...); extern int io_size(IOHANDLE io, uint64_t *size); diff --git a/src/plugin.h b/src/plugin.h index bb721929..45c82b8c 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -25,6 +25,7 @@ #include "webserver.h" #include "xml-rpc.h" #include "db-generic.h" +#include "ff-plugin-events.h" extern int plugin_init(void); extern int plugin_load(char **pe, char *path); @@ -49,6 +50,4 @@ extern int plugin_ssc_transcode(WS_CONNINFO *pwsc, MP3FILE *pmp3, int offset, in #define PLUGIN_E_NOLOAD 1 #define PLUGIN_E_BADFUNCS 2 -#include "ff-plugins.h" - #endif /* _PLUGIN_H_ */ diff --git a/src/webserver.c b/src/webserver.c index 6e25607d..87fd350d 100644 --- a/src/webserver.c +++ b/src/webserver.c @@ -99,7 +99,7 @@ typedef struct tag_ws_private { WSCONFIG wsconfig; WS_HANDLER handlers; WS_CONNLIST connlist; - + IOHANDLE hserver; int stop; int running; @@ -197,7 +197,7 @@ void ws_set_errhandler(void(*err_handler)(int, char*)) { /** - * by default, just dump to stdout + * by default, just dump to stdout */ void ws_default_errhandler(int level, char *msg) { fprintf(stderr,"%d: %s", level, msg); @@ -218,7 +218,7 @@ int ws_lock_unsafe(void) { int retval=TRUE; WS_ENTER(); - + if((err=pthread_mutex_lock(&ws_unsafe))) { ws_dprintf(L_WS_FATAL,"Cannot lock mutex: %s\n",strerror(err)); retval=FALSE; @@ -240,7 +240,7 @@ int ws_unlock_unsafe(void) { int retval=TRUE; WS_ENTER(); - + if((err=pthread_mutex_unlock(&ws_unsafe))) { ws_dprintf(L_WS_FATAL,"Cannot unlock mutex: %s\n",strerror(err)); retval=FALSE; @@ -281,7 +281,7 @@ WSHANDLE ws_init(WSCONFIG *config) { ws_dprintf(L_WS_SPAM,"Malloc error: %s\n",strerror(errno)); return NULL; } - + memcpy(&pwsp->wsconfig,config,sizeof(WS_PRIVATE)); pwsp->connlist.next=NULL; pwsp->running=0; @@ -299,7 +299,7 @@ WSHANDLE ws_init(WSCONFIG *config) { ws_dprintf(L_WS_LOG,"Error in pthread_mutex_init: %s\n",strerror(err)); return NULL; } - + WS_EXIT(); return (WSHANDLE)pwsp; } @@ -324,7 +324,7 @@ int ws_start(WSHANDLE ws) { WS_PRIVATE *pwsp = (WS_PRIVATE*)ws; WS_ENTER(); - + /* this is kind of stupid, but is easier to fix once here * rather than mucking with differences in sockets on windows/unix */ @@ -386,7 +386,7 @@ void ws_remove_dispatch_thread(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { WS_CONNLIST *pHead, *pTail; WS_ENTER(); - + ws_lock_connlist(pwsp); pTail=&(pwsp->connlist); @@ -424,7 +424,7 @@ void ws_add_dispatch_thread(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { WS_CONNLIST *pNew; WS_ENTER(); - + pNew=(WS_CONNLIST*)malloc(sizeof(WS_CONNLIST)); pNew->next=NULL; pNew->pwsc=pwsc; @@ -461,7 +461,7 @@ int ws_stop(WSHANDLE ws) { void *result; WS_ENTER(); - + /* free the ws_handlers */ while(pwsp->handlers.next) { current=pwsp->handlers.next; @@ -534,7 +534,7 @@ void *ws_mainthread(void *arg) { struct in_addr hostaddr; WS_ENTER(); - + while(1) { pwsc=(WS_CONNINFO*)malloc(sizeof(WS_CONNINFO)); if(!pwsc) { @@ -551,8 +551,8 @@ void *ws_mainthread(void *arg) { hnew = io_new(); if(!hnew) ws_dprintf(L_WS_FATAL,"Malloc error in io_new()"); - - if(!io_listen_accept(pwsp->hserver,hnew,&hostaddr)) { + + if(!io_listen_accept(pwsp->hserver,hnew,&hostaddr)) { ws_dprintf(L_WS_LOG,"Dispatcher: accept failed: %s\n", io_errstr(pwsp->hserver)); io_close(pwsp->hserver); @@ -606,7 +606,7 @@ void *ws_mainthread(void *arg) { * * Mainly, we just want to make sure that any * allocated memory has been freed - * + * * @param pwsc connection to close * @returns TRUE on success */ @@ -614,7 +614,7 @@ void ws_close(WS_CONNINFO *pwsc) { WS_PRIVATE *pwsp = (WS_PRIVATE *)(pwsc->pwsp); WS_ENTER(); - + ws_dprintf(L_WS_DBG,"Thread %d: Terminating\n",pwsc->threadno); ws_dprintf(L_WS_DBG,"Thread %d: Freeing request headers\n",pwsc->threadno); ws_freearglist(&pwsc->request_headers); @@ -696,7 +696,7 @@ void ws_emitheaders(WS_CONNINFO *pwsc) { * get headers. This should really only be called if * the method if post. This will fill in the request_headers * linked list. - * + * * @param pwsc session to parse post vars for * @returns TRUE on success */ @@ -705,9 +705,9 @@ int ws_getpostvars(WS_CONNINFO *pwsc) { unsigned char *buffer; uint32_t length; uint32_t ms; - + WS_ENTER(); - + content_length = ws_getarg(&pwsc->request_headers,"Content-Length"); if(!content_length) { ws_set_err(pwsc,E_WS_CONTENTLEN); @@ -752,7 +752,7 @@ int ws_getpostvars(WS_CONNINFO *pwsc) { ws_dprintf(L_WS_DBG,"Thread %d: Read post vars: %s\n",pwsc->threadno,buffer); if(!ws_getgetvars(pwsc,(char*)buffer)) { - /* assume error was set already */ + /* assume error was set already */ free(buffer); ws_dprintf(L_WS_LOG,"Could not parse get vars\n"); return FALSE; @@ -855,8 +855,8 @@ int ws_getheaders(WS_CONNINFO *pwsc) { * Olive/HiFidelio issue with not honoring "Connection: close", as is * *REQUIRED* by RFC for HTTP 1.1 browsers, and ignored by HiFidelio. * - * HiFidelio programmers, take note -- if you fixed your HTTP - * implementation to be RFC compliant, I could provide transcoding + * HiFidelio programmers, take note -- if you fixed your HTTP + * implementation to be RFC compliant, I could provide transcoding * for your clients. (And they want it, judging by my forums) * * @param pwsc session to check for encoding style @@ -885,7 +885,7 @@ int ws_encoding_hack(WS_CONNINFO *pwsc) { * * @params pwsc the session to parse vars for * @params string the argument part of the URI as requested by the client - * @returns + * @returns */ int ws_getgetvars(WS_CONNINFO *pwsc, char *string) { char *first, *last, *middle; @@ -940,7 +940,7 @@ int ws_getgetvars(WS_CONNINFO *pwsc, char *string) { * Main dispatch thread. This gets the request, reads the * headers, decodes the GET'd or POST'd variables, * then decides what function should service the request - * + * * @param arg a pointer to the WS_CONNINFO struct we are servicing */ void *ws_dispatcher(void *arg) { @@ -969,7 +969,7 @@ void *ws_dispatcher(void *arg) { // and decide where to dispatch it ms = 1800 * 1000; len = sizeof(buffer); - if(!io_readline_timed(pwsc->hclient,(unsigned char *)buffer,&len,&ms) || (!len)) { + if(!io_readline_timeout(pwsc->hclient,(unsigned char *)buffer,&len,&ms) || (!len)) { ws_set_err(pwsc,E_WS_TIMEOUT); pwsc->error=errno; pwsc->close=1; @@ -1161,7 +1161,7 @@ void *ws_dispatcher(void *arg) { } ws_close(pwsc); } - + WS_EXIT(); return NULL; } @@ -1169,7 +1169,7 @@ void *ws_dispatcher(void *arg) { /** * Write a printf-style output to a connection. - * + * * FIXME: This has a max buffer length of 1024, and shold * be fixed to use a variable-length buffer. Note to self: * use io_printf to write a platform-indepentent aprintf, or @@ -1197,7 +1197,7 @@ int ws_writefd(WS_CONNINFO *pwsc, char *fmt, ...) { ws_dprintf(L_WS_LOG,"Error writing to client socket: %s", io_errstr(pwsc->hclient)); } - + WS_EXIT(); return len; } @@ -1212,14 +1212,14 @@ int ws_writefd(WS_CONNINFO *pwsc, char *fmt, ...) { */ int ws_writebinary(WS_CONNINFO *pwsc, char *data, int len) { uint32_t bytes_written; - + WS_ENTER(); bytes_written = (uint32_t) len; if(!io_write(pwsc->hclient, (unsigned char *)data, &bytes_written)) { - ws_dprintf(L_WS_LOG,"Error writing to client socket: %s", + ws_dprintf(L_WS_LOG,"Error writing to client socket: %s", io_errstr(pwsc->hclient)); } - + WS_EXIT(); return (int)bytes_written; } @@ -1242,7 +1242,7 @@ int ws_returnerror(WS_CONNINFO *pwsc,int error, char *description) { char *err_str; WS_ENTER(); - + ws_dprintf(L_WS_WARN,"Thread %d: Entering ws_returnerror (%d: %s)\n", pwsc->threadno,error,description); ws_writefd(pwsc,"HTTP/1.1 %d %s\r\n",error,description); @@ -1271,7 +1271,7 @@ int ws_returnerror(WS_CONNINFO *pwsc,int error, char *description) { ws_writefd(pwsc,"\r\n

%s

\r\n",description); ws_writefd(pwsc,"Error %d\r\n
\r\n",error); ws_writefd(pwsc,"" PACKAGE ": %s\r\n
",VERSION); - + ws_get_err(pwsc,&err_code, &err_str); if(E_WS_SUCCESS != err_code) ws_writefd(pwsc,"Error: %s\r\n",strerror(errno)); @@ -1341,7 +1341,7 @@ void ws_defaulthandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { pwsc->threadno,resolved_path,strerror(errno)); ws_returnerror(pwsc,404,"Not found"); ws_close(pwsc); - + io_dispose(hfile); WS_EXIT(); return; @@ -1361,7 +1361,7 @@ void ws_defaulthandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { io_close(hfile); io_dispose(hfile); - + WS_EXIT(); return; } @@ -1469,7 +1469,7 @@ int ws_addarg(ARGLIST *root, char *key, char *fmt, ...) { char value[MAX_LINEBUFFER]; WS_ENTER(); - + va_start(ap,fmt); vsnprintf(value,sizeof(value),fmt,ap); va_end(ap); @@ -1531,7 +1531,7 @@ char *ws_urldecode(char *string, int space_as_plus) { int val=0; WS_ENTER(); - + pnew=(char*)malloc(strlen(string)+1); if(!pnew) { WS_EXIT(); @@ -1584,7 +1584,7 @@ char *ws_urldecode(char *string, int space_as_plus) { /** - * Register a page and auth handler. + * Register a page and auth handler. * * @param ws pointer to private webserver struct * @param stem the prefix of the handled web namespace ("/upnp", etc) @@ -1616,7 +1616,7 @@ int ws_registerhandler(WSHANDLE ws, char *stem, phandler->next=pwsp->handlers.next; pwsp->handlers.next=phandler; ws_unlock_unsafe(); - + WS_EXIT(); return TRUE; } @@ -1698,9 +1698,9 @@ int ws_decodepassword(char *header, char **username, char **password) { *password=NULL; WS_ENTER(); - + ws_lock_unsafe(); - + if(!ws_xlat_init) { ws_xlat_init=1; @@ -1717,7 +1717,7 @@ int ws_decodepassword(char *header, char **username, char **password) { ws_xlat['+'] = 62; ws_xlat['/'] = 63; } - + ws_unlock_unsafe(); /* xlat table is initialized */ @@ -1812,7 +1812,7 @@ int ws_addresponseheader(WS_CONNINFO *pwsc, char *header, char *fmt, ...) { char value[MAX_LINEBUFFER]; WS_ENTER(); - + va_start(ap,fmt); vsnprintf(value,sizeof(value),fmt,ap); va_end(ap); @@ -2005,7 +2005,7 @@ int ws_copyfile(WS_CONNINFO *pwsc, IOHANDLE hfile, uint64_t *bytes_copied) { uint64_t total_bytes = 0; uint32_t bytes_read = 0; uint32_t bytes_written = 0; - + ASSERT(pwsc); if(!pwsc) return -1; /* error handling! */ @@ -2018,12 +2018,12 @@ int ws_copyfile(WS_CONNINFO *pwsc, IOHANDLE hfile, uint64_t *bytes_copied) { *bytes_copied = total_bytes; return FALSE; } - + if(bytes_written != bytes_read) { ws_dprintf(L_WS_LOG,"Internal error in ws_copyfile\n"); break; } - + total_bytes += bytes_read; } @@ -2032,10 +2032,10 @@ int ws_copyfile(WS_CONNINFO *pwsc, IOHANDLE hfile, uint64_t *bytes_copied) { } else { ws_dprintf(L_WS_LOG,"Read error %s\n",io_errstr(hfile)); } - + if(bytes_copied) *bytes_copied = total_bytes; - + return retval; } @@ -2057,7 +2057,7 @@ char *ws_uri(WS_CONNINFO *pwsc) { */ void ws_should_close(WS_CONNINFO *pwsc, int should_close) { ASSERT(pwsc); - + pwsc->close = should_close; } @@ -2069,7 +2069,7 @@ void ws_should_close(WS_CONNINFO *pwsc, int should_close) { */ extern int ws_threadno(WS_CONNINFO *pwsc) { ASSERT(pwsc); - + if(pwsc) return pwsc->threadno; return 0; @@ -2077,17 +2077,17 @@ extern int ws_threadno(WS_CONNINFO *pwsc) { /** * return the hostname of the connected endpoint - * + * * @param pwsc connection to get endpoint for */ extern char *ws_hostname(WS_CONNINFO *pwsc) { ASSERT(pwsc); ASSERT(pwsc->hostname); - + if((pwsc) && (pwsc->hostname)) { return pwsc->hostname; } - + return NULL; } @@ -2107,19 +2107,19 @@ int ws_set_err(WS_CONNINFO *pwsc, int ws_error) { #endif ASSERT(pwsc); - + if(!pwsc) return FALSE; - + if(pwsc->err_msg) free(pwsc->err_msg); - + pwsc->err_code = ws_error; ws_should_close(pwsc,TRUE); /* close the session on error */ if(E_WS_SUCCESS == ws_error) return TRUE; - + if(E_WS_NATIVE == ws_error) { #ifdef WIN32 pwsc->err_native = GetLastError(); @@ -2131,9 +2131,9 @@ int ws_set_err(WS_CONNINFO *pwsc, int ws_error) { #else pwsc->err_native = errno; pwsc->err_msg = strdup(strerror(pwsc->err_native)); -#endif +#endif } - + return TRUE; } @@ -2142,7 +2142,7 @@ int ws_set_err(WS_CONNINFO *pwsc, int ws_error) { * Note that the error message is a pointer to an internal string. * The error isn't valid of other socket operations take place. The * error should be dup'ed or used immediately. - * + * * Sample: * * char *errstr; @@ -2161,11 +2161,11 @@ int ws_get_err(WS_CONNINFO *pwsc, int *errcode, char **err_msg) { if(!pwsc) return FALSE; - + if(errcode) { *errcode = pwsc->err_code; } - + if(err_msg) { if(E_WS_NATIVE != pwsc->err_code) { *err_msg = ws_errors[pwsc->err_code]; @@ -2173,7 +2173,7 @@ int ws_get_err(WS_CONNINFO *pwsc, int *errcode, char **err_msg) { *err_msg = pwsc->err_msg; } } - + return TRUE; }