more plugin work

This commit is contained in:
Ron Pedde 2006-04-20 06:52:21 +00:00
parent ff0491f798
commit 1af9e8c08e
7 changed files with 190 additions and 28 deletions

View File

@ -109,7 +109,7 @@ CONFIG config; /**< Main configuration structure, as read from configfile */
*/
static void usage(char *program);
static void txt_add(char *txtrecord, char *fmt, ...);
static void main_handler(WS_CONNINFO *pwsc);
/**
* build a dns text string
@ -133,6 +133,18 @@ void txt_add(char *txtrecord, char *fmt, ...) {
strcpy(end+1,buff);
}
void main_handler(WS_CONNINFO *pwsc) {
if(plugin_url_candispatch(pwsc)) {
DPRINTF(E_DBG,L_MAIN,"Dispatching %s to plugin\n",pwsc->uri);
plugin_url_handle(pwsc);
return;
}
DPRINTF(E_DBG,L_MAIN,"Dispatching %s to config handler\n",pwsc->uri);
config_handler(pwsc);
}
/**
* Print usage information to stdout
@ -391,7 +403,7 @@ int main(int argc, char *argv[]) {
DPRINTF(E_FATAL,L_MAIN|L_WS,"Error staring web server: %s\n",strerror(errno));
}
ws_registerhandler(config.server, "^.*$",config_handler,config_auth,1);
ws_registerhandler(config.server, "^.*$",main_handler,config_auth,1);
ws_registerhandler(config.server, "^/server-info$",daap_handler,NULL,0);
ws_registerhandler(config.server, "^/content-codes$",daap_handler,daap_auth,0); /* iTunes 6.0.4+? */
ws_registerhandler(config.server,"^/login$",daap_handler,daap_auth,0);

View File

@ -428,12 +428,22 @@ int _os_start_signal_handler(pthread_t *handler_tid) {
*
* @param
*/
void *os_loadlib(char *path) {
return dlopen(path,RTLD_LAZY);
void *os_loadlib(char **pe, char *path) {
void *retval;
if(!(retval = dlopen(path,RTLD_NOW)))
*pe = strdup(dlerror());
return retval;
}
void *os_libfunc(void *handle, char *function) {
return dlsym(handle,function);
void *os_libfunc(char **pe, void *handle, char *function) {
void *retval;
if(!(retval = dlsym(handle,function)))
*pe = strdup(dlerror());
return retval;
}
int *os_unload(void *handle) {

View File

@ -34,8 +34,8 @@ extern int os_syslog(int level, char *msg);
extern int os_chown(char *path, char *user);
/* library loading functions */
extern void *os_loadlib(char *path);
extern void *os_libfunc(void *handle, char *function);
extern void *os_loadlib(char **pe, char *path);
extern void *os_libfunc(char **pe, void *handle, char *function);
extern void *os_unload(void *handle);
#ifdef WIN32

View File

@ -25,6 +25,7 @@
#include <errno.h>
#include <pthread.h>
#include <regex.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@ -33,16 +34,21 @@
#include "err.h"
#include "os.h"
#include "plugin.h"
#include "xml-rpc.h"
#include "webserver.h"
typedef struct tag_pluginentry {
void *phandle;
int type;
char *versionstring;
regex_t regex;
void *functions;
struct tag_pluginentry *next;
} PLUGIN_ENTRY;
/* Globals */
static PLUGIN_ENTRY _plugin_list = { NULL, 0, NULL, NULL };
static PLUGIN_ENTRY _plugin_list;
static int _plugin_initialized = 0;
static pthread_mutex_t _plugin_mutex = PTHREAD_MUTEX_INITIALIZER;
static char* _plugin_error_list[] = {
@ -51,7 +57,6 @@ static char* _plugin_error_list[] = {
"Plugin missing required export: plugin_type/plugin_ver"
};
/* Forwards */
void _plugin_lock(void);
void _plugin_unlock(void);
@ -114,14 +119,15 @@ int _plugin_error(char **pe, int error, ...) {
int plugin_load(char **pe, char *path) {
PLUGIN_ENTRY *ppi;
void *phandle;
int (*type_func)(void);
char* (*ver_func)(void);
PLUGIN_INFO *(*info_func)(void);
PLUGIN_INFO *pinfo;
DPRINTF(E_DBG,L_PLUG,"Attempting to load plugin %s\n",path);
phandle = os_loadlib(path);
phandle = os_loadlib(pe, path);
if(!phandle) {
return _plugin_error(pe,PLUGIN_E_NOLOAD,strerror(errno));
DPRINTF(E_INF,L_PLUG,"Couldn't get lib handle for %s\n",path);
return PLUGIN_E_NOLOAD;
}
ppi = (PLUGIN_ENTRY*)malloc(sizeof(PLUGIN_ENTRY));
@ -129,19 +135,32 @@ int plugin_load(char **pe, char *path) {
ppi->phandle = phandle;
type_func = (int(*)(void)) os_libfunc(phandle,"plugin_type");
ver_func = (char*(*)(void)) os_libfunc(phandle,"plugin_ver");
if((type_func == NULL) || (ver_func == NULL))
return _plugin_error(pe,PLUGIN_E_BADFUNCS);
ppi->type = type_func();
ppi->versionstring = ver_func();
info_func = (PLUGIN_INFO*(*)(void)) os_libfunc(pe, phandle,"plugin_info");
if(info_func == NULL) {
DPRINTF(E_INF,L_PLUG,"Couldn't get info_func for %s\n",path);
return PLUGIN_E_BADFUNCS;
}
pinfo = info_func();
ppi->type = pinfo->type;
ppi->versionstring = pinfo->server;
if(ppi->type == PLUGIN_OUTPUT) {
/* build the regex */
if(regcomp(&ppi->regex,pinfo->url,REG_EXTENDED | REG_NOSUB)) {
DPRINTF(E_LOG,L_PLUG,"Bad regex in %s: %s\n",path,pinfo->url);
}
}
ppi->functions = pinfo->handler_functions;
DPRINTF(E_INF,L_PLUG,"Loaded plugin %s (%s)\n",path,ppi->versionstring);
_plugin_lock();
if(!_plugin_initialized) {
_plugin_initialized = 1;
memset((void*)&_plugin_list,0,sizeof(_plugin_list));
}
ppi->next = _plugin_list.next;
_plugin_list.next = ppi;
@ -149,4 +168,100 @@ int plugin_load(char **pe, char *path) {
return PLUGIN_E_SUCCESS;
}
/**
* check to see if we want to dispatch a particular url
*
* @param pwsc the connection info (including uri) to check
* @returns TRUE if we want to handle it
*/
int plugin_url_candispatch(WS_CONNINFO *pwsc) {
PLUGIN_ENTRY *ppi;
_plugin_lock();
ppi = _plugin_list.next;
while(ppi) {
if(ppi->type == PLUGIN_OUTPUT) {
if(!regexec(&ppi->regex,pwsc->uri,0,NULL,0)) {
/* we have a winner */
_plugin_unlock();
return TRUE;
}
ppi = ppi->next;
}
}
_plugin_unlock();
return FALSE;
}
/**
* actually DISPATCH the hander we said we wanted
*
* @param pwsc the connection info (including uri) to check
* @returns TRUE if we want to handle it
*/
void plugin_url_handle(WS_CONNINFO *pwsc) {
PLUGIN_ENTRY *ppi;
void (*disp_fn)(WS_CONNINFO *pwsc);
_plugin_lock();
ppi = _plugin_list.next;
while(ppi) {
if(ppi->type == PLUGIN_OUTPUT) {
if(!regexec(&ppi->regex,pwsc->uri,0,NULL,0)) {
/* we have a winner */
DPRINTF(E_DBG,L_PLUG,"Dispatching %s to %s\n", pwsc->uri,
ppi->versionstring);
/* so functions must be a tag_plugin_output_fn */
disp_fn=(((PLUGIN_OUTPUT_FN*)ppi->functions)->handler);
disp_fn(pwsc);
ws_returnerror(pwsc,404,"Wtf!");
_plugin_unlock();
return;
}
ppi = ppi->next;
}
}
/* should 500 here or something */
ws_returnerror(pwsc, 500, "Can't find plugin handler");
_plugin_unlock();
return;
}
/* plugin wrappers for utility functions & stuff
*
* these functions need to be wrapped so we can maintain a stable
* interface to older plugins even if we get newer functions or apis
* upstream... it's a binary compatibility layer.
*/
XMLSTRUCT *pi_xml_init(WS_CONNINFO *pwsc, int emit_header) {
return xml_init(pwsc, emit_header);
}
void pi_xml_push(XMLSTRUCT *pxml, char *term) {
return xml_push(pxml, term);
}
void pi_xml_pop(XMLSTRUCT *pxml) {
return xml_pop(pxml);
}
/* FIXME: 256? */
void pi_xml_output(XMLSTRUCT *pxml, char *section, char *fmt, ...) {
char buf[256];
va_list ap;
va_start(ap,fmt);
vsnprintf(buf,sizeof(buf),fmt,ap);
va_end(ap);
xml_output(pxml,section,"%s",buf);
}
void pi_xml_deinit(XMLSTRUCT *pxml) {
return xml_deinit(pxml);
}

View File

@ -22,11 +22,38 @@
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
#include "webserver.h"
extern int plugin_load(char **pe, char *path);
/* Interfaces for web */
extern int plugin_url_candispatch(WS_CONNINFO *pwsc);
extern void plugin_url_handle(WS_CONNINFO *pwsc);
#define PLUGIN_E_SUCCESS 0
#define PLUGIN_E_NOLOAD 1
#define PLUGIN_E_BADFUNCS 2
#define PLUGIN_OUTPUT 0
#define PLUGIN_SCANNER 1
#define PLUGIN_DATABASE 2
#define PLUGIN_OTHER 3
#define PLUGIN_VERSION 1
typedef struct tag_plugin_output_fn {
void(*handler)(WS_CONNINFO *pwsc);
} PLUGIN_OUTPUT_FN;
/* version 1 plugin info */
typedef struct tag_plugin_info {
int version;
int type;
char *server;
char *url; /* for output plugins */
void *handler_functions;
} PLUGIN_INFO;
#endif /* _PLUGIN_H_ */

View File

@ -1268,10 +1268,6 @@ char *ws_urldecode(char *string, int space_as_plus) {
while(*src) {
switch(*src) {
/* DWB - space gets converted to %20, not +, this definitely breaks compatibility with iTunes */
/* But the browsers encode space as plus, so when using the web interface,
* anything with a plus is broken. This will end up having to be sniffed
* by remote agent */
case '+':
if(space_as_plus) {
*dst++=' ';

View File

@ -165,6 +165,8 @@ void xml_pop(XMLSTRUCT *pxml) {
pxml->stack_level--;
}
/* FIXME: Fixed at 256? And can't I get an expandable sprintf/cat? */
/**
* output a string
*/