mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-20 04:24:20 -04:00
add io_ functions for plugins
This commit is contained in:
parent
40956ee0f9
commit
f2be31595f
26
src/ff-plugin-events.h
Normal file
26
src/ff-plugin-events.h
Normal 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_ */
|
239
src/ff-plugins.c
239
src/ff-plugins.c
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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_ */
|
||||||
|
62
src/io.c
62
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_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]);
|
||||||
|
3
src/io.h
3
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(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);
|
||||||
|
@ -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_ */
|
||||||
|
124
src/webserver.c
124
src/webserver.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user