add io_ functions for plugins

This commit is contained in:
Ron Pedde 2007-08-18 01:15:51 +00:00
parent 40956ee0f9
commit f2be31595f
7 changed files with 380 additions and 118 deletions

26
src/ff-plugin-events.h Normal file
View File

@ -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_ */

View File

@ -7,6 +7,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "bsd-snprintf.h"
#include "conf.h" #include "conf.h"
#include "configfile.h" #include "configfile.h"
#include "daapd.h" #include "daapd.h"
@ -14,6 +15,7 @@
#include "err.h" #include "err.h"
#include "ff-dbstruct.h" #include "ff-dbstruct.h"
#include "ff-plugins.h" #include "ff-plugins.h"
#include "io.h"
#include "mp3-scanner.h" #include "mp3-scanner.h"
#include "plugin.h" #include "plugin.h"
#include "util.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, ...) { 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);
} }

View File

@ -23,6 +23,7 @@
#define _FF_PLUGINS_H_ #define _FF_PLUGINS_H_
#include "ff-dbstruct.h" #include "ff-dbstruct.h"
#include "ff-plugin-events.h"
#ifdef WIN32 #ifdef WIN32
# ifdef _WINDLL # ifdef _WINDLL
@ -40,25 +41,6 @@
#define FALSE 0 #define FALSE 0
#endif #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 #ifndef E_FATAL
# define E_FATAL 0 # define E_FATAL 0
# define E_LOG 1 # define E_LOG 1
@ -72,6 +54,7 @@
#define COUNT_PLAYLISTS 1 #define COUNT_PLAYLISTS 1
struct tag_ws_conninfo; struct tag_ws_conninfo;
typedef void* HANDLE;
/* Functions that must be exported by different plugin types */ /* Functions that must be exported by different plugin types */
typedef struct tag_plugin_output_fn { 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 char *pi_conf_alloc_string(char *section, char *key, char *dflt);
extern EXPORT void pi_conf_dispose_string(char *str); extern EXPORT void pi_conf_dispose_string(char *str);
extern EXPORT int pi_conf_get_int(char *section, char *key, int dflt); 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, ...); 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 #ifdef __cplusplus
} }
#endif #endif
#endif /* _FF_PLUGINS_ */ #endif /* _FF_PLUGINS_ */

View File

@ -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_getpos(IO_PRIVHANDLE *phandle, uint64_t *pos);
int io_buffer(IO_PRIVHANDLE *phandle); int io_buffer(IO_PRIVHANDLE *phandle);
int io_readline(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len); 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); uint32_t *len, uint32_t *ms);
char *io_errstr(IO_PRIVHANDLE *phandle); char *io_errstr(IO_PRIVHANDLE *phandle);
void io_dispose(IO_PRIVHANDLE *phandle); void io_dispose(IO_PRIVHANDLE *phandle);
@ -404,7 +404,7 @@ int io_urldecode(char *str) {
char *current,*dst; char *current,*dst;
int digit1, digit2; int digit1, digit2;
char *hexdigits = "0123456789abcdef"; char *hexdigits = "0123456789abcdef";
current = dst = str; current = dst = str;
while(*current) { while(*current) {
switch(*current) { switch(*current) {
@ -419,7 +419,7 @@ int io_urldecode(char *str) {
return FALSE; return FALSE;
} }
current++; current++;
if(!strchr(hexdigits,tolower(*current))) { if(!strchr(hexdigits,tolower(*current))) {
io_err_printf(IO_LOG_DEBUG,"urldecode: bad hex digit\n"); io_err_printf(IO_LOG_DEBUG,"urldecode: bad hex digit\n");
return FALSE; return FALSE;
@ -441,7 +441,7 @@ int io_urldecode(char *str) {
break; break;
} }
} }
*dst = '\0'; *dst = '\0';
return TRUE; return TRUE;
} }
@ -664,7 +664,7 @@ int io_open(IO_PRIVHANDLE *phandle, char *fmt, ...) {
if(path_part) if(path_part)
io_urldecode(path_part); io_urldecode(path_part);
/* find the start of the options */ /* find the start of the options */
options_part = strchr(path_part,'?'); options_part = strchr(path_part,'?');
if(options_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); ASSERT(phandle->fnptr->fn_read);
io_err_printf(IO_LOG_SPAM,"entering io_read_timeout\n"); io_err_printf(IO_LOG_SPAM,"entering io_read_timeout\n");
if((!phandle) || (!phandle->open) || (!phandle->fnptr)) { if((!phandle) || (!phandle->open) || (!phandle->fnptr)) {
io_err(phandle,IO_E_NOTINIT); io_err(phandle,IO_E_NOTINIT);
*len = 0; *len = 0;
@ -826,7 +826,7 @@ int io_read(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) {
ASSERT(phandle->fnptr->fn_read); ASSERT(phandle->fnptr->fn_read);
io_err_printf(IO_LOG_SPAM,"entering io_read\n"); io_err_printf(IO_LOG_SPAM,"entering io_read\n");
if((!phandle) || (!phandle->open) || (!phandle->fnptr)) { if((!phandle) || (!phandle->open) || (!phandle->fnptr)) {
io_err(phandle,IO_E_NOTINIT); io_err(phandle,IO_E_NOTINIT);
*len = 0; *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 */ /* fill as much as possible from buffer */
if(phandle->buffer_offset < phandle->buffer_len) { if(phandle->buffer_offset < phandle->buffer_len) {
io_err_printf(IO_LOG_SPAM,"Fulfilling from buffer\n"); 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)) if(read_size > (phandle->buffer_len - phandle->buffer_offset))
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); 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; return FALSE;
} }
phandle->buffer_offset = 0; phandle->buffer_offset = 0;
if(phandle->buffer_len == 0) if(phandle->buffer_len == 0)
return TRUE; /* can't read any more */ 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 * @returns TRUE on success, FALSE with ms=0 on timeout, or FALSE
* on other kind of error * 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 *len, uint32_t *ms) {
uint32_t numread = 0; uint32_t numread = 0;
uint32_t to_read; uint32_t to_read;
int ascii = 0; int ascii = 0;
if(io_option_get(phandle,"ascii",NULL)) if(io_option_get(phandle,"ascii",NULL))
ascii = 1; 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)) { while(numread < (*len - 1)) {
to_read = 1; to_read = 1;
if(io_read_timeout(phandle, buf + numread, &to_read, ms)) { 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) { uint32_t *len) {
io_err_printf(IO_LOG_SPAM,"entering io_readline\n"); 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 ascii_len;
uint32_t index; uint32_t index;
uint32_t real_len; uint32_t real_len;
ASSERT(io_initialized); /* call io_init first */ ASSERT(io_initialized); /* call io_init first */
ASSERT(phandle); ASSERT(phandle);
ASSERT(phandle->open); ASSERT(phandle->open);
ASSERT(phandle->fnptr); ASSERT(phandle->fnptr);
ASSERT(phandle->fnptr->fn_write); ASSERT(phandle->fnptr->fn_write);
if((!phandle) || (!phandle->open) || (!phandle->fnptr)) { if((!phandle) || (!phandle->open) || (!phandle->fnptr)) {
io_err(phandle,IO_E_NOTINIT); io_err(phandle,IO_E_NOTINIT);
*len = 0; *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"); io_err_printf(IO_LOG_FATAL,"Could not alloc buffer in io_printf\n");
exit(-1); exit(-1);
} }
must_free = TRUE; must_free = TRUE;
dst = real_buffer; dst = real_buffer;
for(index = 0; index < *len; index++) { 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_buffer = buf; /* just write what was passed */
real_len = *len; real_len = *len;
} }
result = phandle->fnptr->fn_write(phandle,real_buffer,&real_len); result = phandle->fnptr->fn_write(phandle,real_buffer,&real_len);
if(!result) if(!result)
@ -1030,7 +1030,7 @@ int io_write(IO_PRIVHANDLE *phandle, unsigned char *buf, uint32_t *len) {
real_len = *len; real_len = *len;
free(real_buffer); free(real_buffer);
} }
*len = real_len; *len = real_len;
return result; 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)) { if(!io_write(phandle,(unsigned char *)outbuf,&len) || (len != new_size)) {
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -1194,10 +1194,10 @@ int io_getpos(IO_PRIVHANDLE *phandle, uint64_t *pos) {
*/ */
int io_buffer(IO_PRIVHANDLE *phandle) { int io_buffer(IO_PRIVHANDLE *phandle) {
ASSERT(phandle); ASSERT(phandle);
if(!phandle) if(!phandle)
return FALSE; return FALSE;
if(phandle->buffer) if(phandle->buffer)
return TRUE; return TRUE;
@ -1206,9 +1206,9 @@ int io_buffer(IO_PRIVHANDLE *phandle) {
io_err_printf(IO_LOG_FATAL,"Malloc error in io_buffer\n"); io_err_printf(IO_LOG_FATAL,"Malloc error in io_buffer\n");
exit(-1); exit(-1);
} }
phandle->buffering=1; phandle->buffering=1;
return TRUE; return TRUE;
} }
@ -1285,7 +1285,7 @@ void io_err(IO_PRIVHANDLE *phandle, uint32_t errorcode) {
free(phandle->err_str); free(phandle->err_str);
phandle->err = errorcode; phandle->err = errorcode;
if(errorcode) { if(errorcode) {
phandle->err_str = strdup(io_err_strings[errorcode & 0x00FFFFFF]); phandle->err_str = strdup(io_err_strings[errorcode & 0x00FFFFFF]);
phandle->err = errorcode; phandle->err = errorcode;
@ -1778,10 +1778,10 @@ char *io_file_geterrmsg(IO_PRIVHANDLE *phandle, ERR_T *code, int *is_local) {
if(!priv) { if(!priv) {
return "file not initialized"; return "file not initialized";
} }
if(code) if(code)
*code = priv->err; *code = priv->err;
if(priv->local_err) { if(priv->local_err) {
if(is_local) if(is_local)
*is_local = TRUE; *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) { char *io_socket_geterrmsg(IO_PRIVHANDLE *phandle, ERR_T *code, int *is_local) {
IO_SOCKET_PRIV *priv; IO_SOCKET_PRIV *priv;
#ifdef WIN32 #ifdef WIN32
char lpErrorBuf[256]; char lpErrorBuf[256];
#endif #endif
@ -2410,7 +2410,7 @@ char *io_socket_geterrmsg(IO_PRIVHANDLE *phandle, ERR_T *code, int *is_local) {
priv = (IO_SOCKET_PRIV*)(phandle->private); priv = (IO_SOCKET_PRIV*)(phandle->private);
if(*code) if(*code)
*code = priv->err; *code = priv->err;
if(priv->local_err) { if(priv->local_err) {
*is_local = TRUE; *is_local = TRUE;
return strdup(io_socket_err_strings[priv->err & 0x00FFFFFF]); return strdup(io_socket_err_strings[priv->err & 0x00FFFFFF]);

View File

@ -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(IOHANDLE io, unsigned char *buf, uint32_t *len);
extern int io_read_timeout(IOHANDLE io, unsigned char *buf, uint32_t *len, extern int io_read_timeout(IOHANDLE io, unsigned char *buf, uint32_t *len,
uint32_t *ms); 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_write(IOHANDLE io, unsigned char *buf, uint32_t *len);
extern int io_printf(IOHANDLE io, char *fmt, ...); extern int io_printf(IOHANDLE io, char *fmt, ...);
extern int io_size(IOHANDLE io, uint64_t *size); extern int io_size(IOHANDLE io, uint64_t *size);

View File

@ -25,6 +25,7 @@
#include "webserver.h" #include "webserver.h"
#include "xml-rpc.h" #include "xml-rpc.h"
#include "db-generic.h" #include "db-generic.h"
#include "ff-plugin-events.h"
extern int plugin_init(void); extern int plugin_init(void);
extern int plugin_load(char **pe, char *path); 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_NOLOAD 1
#define PLUGIN_E_BADFUNCS 2 #define PLUGIN_E_BADFUNCS 2
#include "ff-plugins.h"
#endif /* _PLUGIN_H_ */ #endif /* _PLUGIN_H_ */

View File

@ -99,7 +99,7 @@ typedef struct tag_ws_private {
WSCONFIG wsconfig; WSCONFIG wsconfig;
WS_HANDLER handlers; WS_HANDLER handlers;
WS_CONNLIST connlist; WS_CONNLIST connlist;
IOHANDLE hserver; IOHANDLE hserver;
int stop; int stop;
int running; 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) { void ws_default_errhandler(int level, char *msg) {
fprintf(stderr,"%d: %s", level, msg); fprintf(stderr,"%d: %s", level, msg);
@ -218,7 +218,7 @@ int ws_lock_unsafe(void) {
int retval=TRUE; int retval=TRUE;
WS_ENTER(); WS_ENTER();
if((err=pthread_mutex_lock(&ws_unsafe))) { if((err=pthread_mutex_lock(&ws_unsafe))) {
ws_dprintf(L_WS_FATAL,"Cannot lock mutex: %s\n",strerror(err)); ws_dprintf(L_WS_FATAL,"Cannot lock mutex: %s\n",strerror(err));
retval=FALSE; retval=FALSE;
@ -240,7 +240,7 @@ int ws_unlock_unsafe(void) {
int retval=TRUE; int retval=TRUE;
WS_ENTER(); WS_ENTER();
if((err=pthread_mutex_unlock(&ws_unsafe))) { if((err=pthread_mutex_unlock(&ws_unsafe))) {
ws_dprintf(L_WS_FATAL,"Cannot unlock mutex: %s\n",strerror(err)); ws_dprintf(L_WS_FATAL,"Cannot unlock mutex: %s\n",strerror(err));
retval=FALSE; retval=FALSE;
@ -281,7 +281,7 @@ WSHANDLE ws_init(WSCONFIG *config) {
ws_dprintf(L_WS_SPAM,"Malloc error: %s\n",strerror(errno)); ws_dprintf(L_WS_SPAM,"Malloc error: %s\n",strerror(errno));
return NULL; return NULL;
} }
memcpy(&pwsp->wsconfig,config,sizeof(WS_PRIVATE)); memcpy(&pwsp->wsconfig,config,sizeof(WS_PRIVATE));
pwsp->connlist.next=NULL; pwsp->connlist.next=NULL;
pwsp->running=0; 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)); ws_dprintf(L_WS_LOG,"Error in pthread_mutex_init: %s\n",strerror(err));
return NULL; return NULL;
} }
WS_EXIT(); WS_EXIT();
return (WSHANDLE)pwsp; return (WSHANDLE)pwsp;
} }
@ -324,7 +324,7 @@ int ws_start(WSHANDLE ws) {
WS_PRIVATE *pwsp = (WS_PRIVATE*)ws; WS_PRIVATE *pwsp = (WS_PRIVATE*)ws;
WS_ENTER(); WS_ENTER();
/* this is kind of stupid, but is easier to fix once here /* this is kind of stupid, but is easier to fix once here
* rather than mucking with differences in sockets on windows/unix * 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_CONNLIST *pHead, *pTail;
WS_ENTER(); WS_ENTER();
ws_lock_connlist(pwsp); ws_lock_connlist(pwsp);
pTail=&(pwsp->connlist); pTail=&(pwsp->connlist);
@ -424,7 +424,7 @@ void ws_add_dispatch_thread(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) {
WS_CONNLIST *pNew; WS_CONNLIST *pNew;
WS_ENTER(); WS_ENTER();
pNew=(WS_CONNLIST*)malloc(sizeof(WS_CONNLIST)); pNew=(WS_CONNLIST*)malloc(sizeof(WS_CONNLIST));
pNew->next=NULL; pNew->next=NULL;
pNew->pwsc=pwsc; pNew->pwsc=pwsc;
@ -461,7 +461,7 @@ int ws_stop(WSHANDLE ws) {
void *result; void *result;
WS_ENTER(); WS_ENTER();
/* free the ws_handlers */ /* free the ws_handlers */
while(pwsp->handlers.next) { while(pwsp->handlers.next) {
current=pwsp->handlers.next; current=pwsp->handlers.next;
@ -534,7 +534,7 @@ void *ws_mainthread(void *arg) {
struct in_addr hostaddr; struct in_addr hostaddr;
WS_ENTER(); WS_ENTER();
while(1) { while(1) {
pwsc=(WS_CONNINFO*)malloc(sizeof(WS_CONNINFO)); pwsc=(WS_CONNINFO*)malloc(sizeof(WS_CONNINFO));
if(!pwsc) { if(!pwsc) {
@ -551,8 +551,8 @@ void *ws_mainthread(void *arg) {
hnew = io_new(); hnew = io_new();
if(!hnew) if(!hnew)
ws_dprintf(L_WS_FATAL,"Malloc error in io_new()"); 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", ws_dprintf(L_WS_LOG,"Dispatcher: accept failed: %s\n",
io_errstr(pwsp->hserver)); io_errstr(pwsp->hserver));
io_close(pwsp->hserver); io_close(pwsp->hserver);
@ -606,7 +606,7 @@ void *ws_mainthread(void *arg) {
* *
* Mainly, we just want to make sure that any * Mainly, we just want to make sure that any
* allocated memory has been freed * allocated memory has been freed
* *
* @param pwsc connection to close * @param pwsc connection to close
* @returns TRUE on success * @returns TRUE on success
*/ */
@ -614,7 +614,7 @@ void ws_close(WS_CONNINFO *pwsc) {
WS_PRIVATE *pwsp = (WS_PRIVATE *)(pwsc->pwsp); WS_PRIVATE *pwsp = (WS_PRIVATE *)(pwsc->pwsp);
WS_ENTER(); WS_ENTER();
ws_dprintf(L_WS_DBG,"Thread %d: Terminating\n",pwsc->threadno); 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_dprintf(L_WS_DBG,"Thread %d: Freeing request headers\n",pwsc->threadno);
ws_freearglist(&pwsc->request_headers); ws_freearglist(&pwsc->request_headers);
@ -696,7 +696,7 @@ void ws_emitheaders(WS_CONNINFO *pwsc) {
* get headers. This should really only be called if * get headers. This should really only be called if
* the method if post. This will fill in the request_headers * the method if post. This will fill in the request_headers
* linked list. * linked list.
* *
* @param pwsc session to parse post vars for * @param pwsc session to parse post vars for
* @returns TRUE on success * @returns TRUE on success
*/ */
@ -705,9 +705,9 @@ int ws_getpostvars(WS_CONNINFO *pwsc) {
unsigned char *buffer; unsigned char *buffer;
uint32_t length; uint32_t length;
uint32_t ms; uint32_t ms;
WS_ENTER(); WS_ENTER();
content_length = ws_getarg(&pwsc->request_headers,"Content-Length"); content_length = ws_getarg(&pwsc->request_headers,"Content-Length");
if(!content_length) { if(!content_length) {
ws_set_err(pwsc,E_WS_CONTENTLEN); 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); ws_dprintf(L_WS_DBG,"Thread %d: Read post vars: %s\n",pwsc->threadno,buffer);
if(!ws_getgetvars(pwsc,(char*)buffer)) { if(!ws_getgetvars(pwsc,(char*)buffer)) {
/* assume error was set already */ /* assume error was set already */
free(buffer); free(buffer);
ws_dprintf(L_WS_LOG,"Could not parse get vars\n"); ws_dprintf(L_WS_LOG,"Could not parse get vars\n");
return FALSE; return FALSE;
@ -855,8 +855,8 @@ int ws_getheaders(WS_CONNINFO *pwsc) {
* Olive/HiFidelio issue with not honoring "Connection: close", as is * Olive/HiFidelio issue with not honoring "Connection: close", as is
* *REQUIRED* by RFC for HTTP 1.1 browsers, and ignored by HiFidelio. * *REQUIRED* by RFC for HTTP 1.1 browsers, and ignored by HiFidelio.
* *
* HiFidelio programmers, take note -- if you fixed your HTTP * HiFidelio programmers, take note -- if you fixed your HTTP
* implementation to be RFC compliant, I could provide transcoding * implementation to be RFC compliant, I could provide transcoding
* for your clients. (And they want it, judging by my forums) * for your clients. (And they want it, judging by my forums)
* *
* @param pwsc session to check for encoding style * @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 pwsc the session to parse vars for
* @params string the argument part of the URI as requested by the client * @params string the argument part of the URI as requested by the client
* @returns * @returns
*/ */
int ws_getgetvars(WS_CONNINFO *pwsc, char *string) { int ws_getgetvars(WS_CONNINFO *pwsc, char *string) {
char *first, *last, *middle; 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 * Main dispatch thread. This gets the request, reads the
* headers, decodes the GET'd or POST'd variables, * headers, decodes the GET'd or POST'd variables,
* then decides what function should service the request * then decides what function should service the request
* *
* @param arg a pointer to the WS_CONNINFO struct we are servicing * @param arg a pointer to the WS_CONNINFO struct we are servicing
*/ */
void *ws_dispatcher(void *arg) { void *ws_dispatcher(void *arg) {
@ -969,7 +969,7 @@ void *ws_dispatcher(void *arg) {
// and decide where to dispatch it // and decide where to dispatch it
ms = 1800 * 1000; ms = 1800 * 1000;
len = sizeof(buffer); 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); ws_set_err(pwsc,E_WS_TIMEOUT);
pwsc->error=errno; pwsc->error=errno;
pwsc->close=1; pwsc->close=1;
@ -1161,7 +1161,7 @@ void *ws_dispatcher(void *arg) {
} }
ws_close(pwsc); ws_close(pwsc);
} }
WS_EXIT(); WS_EXIT();
return NULL; return NULL;
} }
@ -1169,7 +1169,7 @@ void *ws_dispatcher(void *arg) {
/** /**
* Write a printf-style output to a connection. * Write a printf-style output to a connection.
* *
* FIXME: This has a max buffer length of 1024, and shold * FIXME: This has a max buffer length of 1024, and shold
* be fixed to use a variable-length buffer. Note to self: * be fixed to use a variable-length buffer. Note to self:
* use io_printf to write a platform-indepentent aprintf, or * 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", ws_dprintf(L_WS_LOG,"Error writing to client socket: %s",
io_errstr(pwsc->hclient)); io_errstr(pwsc->hclient));
} }
WS_EXIT(); WS_EXIT();
return len; return len;
} }
@ -1212,14 +1212,14 @@ int ws_writefd(WS_CONNINFO *pwsc, char *fmt, ...) {
*/ */
int ws_writebinary(WS_CONNINFO *pwsc, char *data, int len) { int ws_writebinary(WS_CONNINFO *pwsc, char *data, int len) {
uint32_t bytes_written; uint32_t bytes_written;
WS_ENTER(); WS_ENTER();
bytes_written = (uint32_t) len; bytes_written = (uint32_t) len;
if(!io_write(pwsc->hclient, (unsigned char *)data, &bytes_written)) { 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)); io_errstr(pwsc->hclient));
} }
WS_EXIT(); WS_EXIT();
return (int)bytes_written; return (int)bytes_written;
} }
@ -1242,7 +1242,7 @@ int ws_returnerror(WS_CONNINFO *pwsc,int error, char *description) {
char *err_str; char *err_str;
WS_ENTER(); WS_ENTER();
ws_dprintf(L_WS_WARN,"Thread %d: Entering ws_returnerror (%d: %s)\n", ws_dprintf(L_WS_WARN,"Thread %d: Entering ws_returnerror (%d: %s)\n",
pwsc->threadno,error,description); pwsc->threadno,error,description);
ws_writefd(pwsc,"HTTP/1.1 %d %s\r\n",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<H1>%s</H1>\r\n",description); ws_writefd(pwsc,"\r\n<H1>%s</H1>\r\n",description);
ws_writefd(pwsc,"Error %d\r\n<hr>\r\n",error); ws_writefd(pwsc,"Error %d\r\n<hr>\r\n",error);
ws_writefd(pwsc,"<i>" PACKAGE ": %s\r\n<br>",VERSION); ws_writefd(pwsc,"<i>" PACKAGE ": %s\r\n<br>",VERSION);
ws_get_err(pwsc,&err_code, &err_str); ws_get_err(pwsc,&err_code, &err_str);
if(E_WS_SUCCESS != err_code) if(E_WS_SUCCESS != err_code)
ws_writefd(pwsc,"Error: %s\r\n",strerror(errno)); 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)); pwsc->threadno,resolved_path,strerror(errno));
ws_returnerror(pwsc,404,"Not found"); ws_returnerror(pwsc,404,"Not found");
ws_close(pwsc); ws_close(pwsc);
io_dispose(hfile); io_dispose(hfile);
WS_EXIT(); WS_EXIT();
return; return;
@ -1361,7 +1361,7 @@ void ws_defaulthandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) {
io_close(hfile); io_close(hfile);
io_dispose(hfile); io_dispose(hfile);
WS_EXIT(); WS_EXIT();
return; return;
} }
@ -1469,7 +1469,7 @@ int ws_addarg(ARGLIST *root, char *key, char *fmt, ...) {
char value[MAX_LINEBUFFER]; char value[MAX_LINEBUFFER];
WS_ENTER(); WS_ENTER();
va_start(ap,fmt); va_start(ap,fmt);
vsnprintf(value,sizeof(value),fmt,ap); vsnprintf(value,sizeof(value),fmt,ap);
va_end(ap); va_end(ap);
@ -1531,7 +1531,7 @@ char *ws_urldecode(char *string, int space_as_plus) {
int val=0; int val=0;
WS_ENTER(); WS_ENTER();
pnew=(char*)malloc(strlen(string)+1); pnew=(char*)malloc(strlen(string)+1);
if(!pnew) { if(!pnew) {
WS_EXIT(); 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 ws pointer to private webserver struct
* @param stem the prefix of the handled web namespace ("/upnp", etc) * @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; phandler->next=pwsp->handlers.next;
pwsp->handlers.next=phandler; pwsp->handlers.next=phandler;
ws_unlock_unsafe(); ws_unlock_unsafe();
WS_EXIT(); WS_EXIT();
return TRUE; return TRUE;
} }
@ -1698,9 +1698,9 @@ int ws_decodepassword(char *header, char **username, char **password) {
*password=NULL; *password=NULL;
WS_ENTER(); WS_ENTER();
ws_lock_unsafe(); ws_lock_unsafe();
if(!ws_xlat_init) { if(!ws_xlat_init) {
ws_xlat_init=1; ws_xlat_init=1;
@ -1717,7 +1717,7 @@ int ws_decodepassword(char *header, char **username, char **password) {
ws_xlat['+'] = 62; ws_xlat['+'] = 62;
ws_xlat['/'] = 63; ws_xlat['/'] = 63;
} }
ws_unlock_unsafe(); ws_unlock_unsafe();
/* xlat table is initialized */ /* xlat table is initialized */
@ -1812,7 +1812,7 @@ int ws_addresponseheader(WS_CONNINFO *pwsc, char *header, char *fmt, ...) {
char value[MAX_LINEBUFFER]; char value[MAX_LINEBUFFER];
WS_ENTER(); WS_ENTER();
va_start(ap,fmt); va_start(ap,fmt);
vsnprintf(value,sizeof(value),fmt,ap); vsnprintf(value,sizeof(value),fmt,ap);
va_end(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; uint64_t total_bytes = 0;
uint32_t bytes_read = 0; uint32_t bytes_read = 0;
uint32_t bytes_written = 0; uint32_t bytes_written = 0;
ASSERT(pwsc); ASSERT(pwsc);
if(!pwsc) if(!pwsc)
return -1; /* error handling! */ return -1; /* error handling! */
@ -2018,12 +2018,12 @@ int ws_copyfile(WS_CONNINFO *pwsc, IOHANDLE hfile, uint64_t *bytes_copied) {
*bytes_copied = total_bytes; *bytes_copied = total_bytes;
return FALSE; return FALSE;
} }
if(bytes_written != bytes_read) { if(bytes_written != bytes_read) {
ws_dprintf(L_WS_LOG,"Internal error in ws_copyfile\n"); ws_dprintf(L_WS_LOG,"Internal error in ws_copyfile\n");
break; break;
} }
total_bytes += bytes_read; total_bytes += bytes_read;
} }
@ -2032,10 +2032,10 @@ int ws_copyfile(WS_CONNINFO *pwsc, IOHANDLE hfile, uint64_t *bytes_copied) {
} else { } else {
ws_dprintf(L_WS_LOG,"Read error %s\n",io_errstr(hfile)); ws_dprintf(L_WS_LOG,"Read error %s\n",io_errstr(hfile));
} }
if(bytes_copied) if(bytes_copied)
*bytes_copied = total_bytes; *bytes_copied = total_bytes;
return retval; return retval;
} }
@ -2057,7 +2057,7 @@ char *ws_uri(WS_CONNINFO *pwsc) {
*/ */
void ws_should_close(WS_CONNINFO *pwsc, int should_close) { void ws_should_close(WS_CONNINFO *pwsc, int should_close) {
ASSERT(pwsc); ASSERT(pwsc);
pwsc->close = should_close; 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) { extern int ws_threadno(WS_CONNINFO *pwsc) {
ASSERT(pwsc); ASSERT(pwsc);
if(pwsc) if(pwsc)
return pwsc->threadno; return pwsc->threadno;
return 0; return 0;
@ -2077,17 +2077,17 @@ extern int ws_threadno(WS_CONNINFO *pwsc) {
/** /**
* return the hostname of the connected endpoint * return the hostname of the connected endpoint
* *
* @param pwsc connection to get endpoint for * @param pwsc connection to get endpoint for
*/ */
extern char *ws_hostname(WS_CONNINFO *pwsc) { extern char *ws_hostname(WS_CONNINFO *pwsc) {
ASSERT(pwsc); ASSERT(pwsc);
ASSERT(pwsc->hostname); ASSERT(pwsc->hostname);
if((pwsc) && (pwsc->hostname)) { if((pwsc) && (pwsc->hostname)) {
return pwsc->hostname; return pwsc->hostname;
} }
return NULL; return NULL;
} }
@ -2107,19 +2107,19 @@ int ws_set_err(WS_CONNINFO *pwsc, int ws_error) {
#endif #endif
ASSERT(pwsc); ASSERT(pwsc);
if(!pwsc) if(!pwsc)
return FALSE; return FALSE;
if(pwsc->err_msg) if(pwsc->err_msg)
free(pwsc->err_msg); free(pwsc->err_msg);
pwsc->err_code = ws_error; pwsc->err_code = ws_error;
ws_should_close(pwsc,TRUE); /* close the session on error */ ws_should_close(pwsc,TRUE); /* close the session on error */
if(E_WS_SUCCESS == ws_error) if(E_WS_SUCCESS == ws_error)
return TRUE; return TRUE;
if(E_WS_NATIVE == ws_error) { if(E_WS_NATIVE == ws_error) {
#ifdef WIN32 #ifdef WIN32
pwsc->err_native = GetLastError(); pwsc->err_native = GetLastError();
@ -2131,9 +2131,9 @@ int ws_set_err(WS_CONNINFO *pwsc, int ws_error) {
#else #else
pwsc->err_native = errno; pwsc->err_native = errno;
pwsc->err_msg = strdup(strerror(pwsc->err_native)); pwsc->err_msg = strdup(strerror(pwsc->err_native));
#endif #endif
} }
return TRUE; 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. * Note that the error message is a pointer to an internal string.
* The error isn't valid of other socket operations take place. The * The error isn't valid of other socket operations take place. The
* error should be dup'ed or used immediately. * error should be dup'ed or used immediately.
* *
* Sample: * Sample:
* *
* char *errstr; * char *errstr;
@ -2161,11 +2161,11 @@ int ws_get_err(WS_CONNINFO *pwsc, int *errcode, char **err_msg) {
if(!pwsc) if(!pwsc)
return FALSE; return FALSE;
if(errcode) { if(errcode) {
*errcode = pwsc->err_code; *errcode = pwsc->err_code;
} }
if(err_msg) { if(err_msg) {
if(E_WS_NATIVE != pwsc->err_code) { if(E_WS_NATIVE != pwsc->err_code) {
*err_msg = ws_errors[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; *err_msg = pwsc->err_msg;
} }
} }
return TRUE; return TRUE;
} }