api: started to add idnode to the new API structure

This commit is contained in:
Adam Sutton 2013-08-12 20:39:40 +01:00
parent 0efeda1727
commit f067952fd5
6 changed files with 248 additions and 15 deletions

View file

@ -111,6 +111,7 @@ SRCS = src/version.c \
SRCS += \
src/api.c \
src/api/api_idnode.c \
SRCS += \
src/parsers/parsers.c \
@ -139,7 +140,7 @@ SRCS += src/webui/webui.c \
src/webui/simpleui.c \
src/webui/statedump.c \
src/webui/html.c\
src/webui/api.c\
src/webui/webui_api.c\
SRCS += src/muxer.c \
src/muxer/muxer_pass.c \

View file

@ -37,18 +37,24 @@ static int ah_cmp
}
void
api_register ( const api_hook_t *hooks )
api_register ( const api_hook_t *hook )
{
static api_link_t *t, *skel = NULL;
if (!skel)
skel = calloc(1, sizeof(api_link_t));
skel->hook = hook;
t = RB_INSERT_SORTED(&api_hook_tree, skel, link, ah_cmp);
if (t)
tvherror("api", "trying to re-register subsystem");
else
skel = NULL;
}
void
api_register_all ( const api_hook_t *hooks )
{
while (hooks->ah_subsystem) {
if (!skel)
skel = calloc(1, sizeof(api_link_t));
skel->hook = hooks;
t = RB_INSERT_SORTED(&api_hook_tree, skel, link, ah_cmp);
if (t)
tvherror("api", "trying to re-register subsystem");
else
skel = NULL;
api_register(hooks);
hooks++;
}
}
@ -106,5 +112,8 @@ void api_init ( void )
{ "serverinfo", ACCESS_ANONYMOUS, api_serverinfo, NULL },
{ NULL, 0, NULL, NULL }
};
api_register(h);
api_register_all(h);
/* Subsystems */
api_idnode_init();
}

View file

@ -21,6 +21,7 @@
#define __TVH_API_H__
#include "htsmsg.h"
#include "idnode.h"
#include "redblack.h"
#define TVH_API_VERSION 12
@ -43,7 +44,8 @@ typedef struct api_hook
/*
* Regsiter handler
*/
void api_register ( const api_hook_t *hooks );
void api_register ( const api_hook_t *hook );
void api_register_all ( const api_hook_t *hooks );
/*
* Execute
@ -54,5 +56,13 @@ int api_exec ( const char *subsystem, htsmsg_t *args, htsmsg_t **resp );
* Initialise
*/
void api_init ( void );
void api_idnode_init ( void );
/*
* Re-usable functions
*/
int api_idnode_tree0
( const char *uuid, const char *root, idnode_set_t *(*rootfn)(void),
htsmsg_t **resp );
#endif /* __TVH_API_H__ */

204
src/api/api_idnode.c Normal file
View file

@ -0,0 +1,204 @@
/*
* API - idnode related API calls
*
* Copyright (C) 2013 Adam Sutton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TVH_API_IDNODE_H__
#define __TVH_API_IDNODE_H__
#include "tvheadend.h"
#include "access.h"
#include "idnode.h"
#include "htsmsg.h"
#include "api.h"
int
api_idnode_tree0
( const char *uuid, const char *root,
idnode_set_t *(*rootfn)(void), htsmsg_t **resp )
{
int isroot;
idnode_t *node = NULL;
/* Validate */
if (!uuid)
return EINVAL;
isroot = !strcmp("root", uuid);
if (isroot && !(root || rootfn))
return EINVAL;
pthread_mutex_lock(&global_lock);
if (!isroot || root) {
if (!(node = idnode_find(isroot ? root : uuid, NULL))) {
pthread_mutex_unlock(&global_lock);
return EINVAL;
}
}
*resp = htsmsg_create_list();
/* Root node */
if (isroot && node) {
htsmsg_t *m = idnode_serialize(node);
htsmsg_add_u32(m, "leaf", idnode_is_leaf(node));
htsmsg_add_msg(*resp, NULL, m);
/* Children */
} else {
idnode_set_t *v = node ? idnode_get_childs(node) : rootfn();
if (v) {
int i;
for(i = 0; i < v->is_count; i++) {
htsmsg_t *m = idnode_serialize(v->is_array[i]);
htsmsg_add_u32(m, "leaf", idnode_is_leaf(v->is_array[i]));
htsmsg_add_msg(*resp, NULL, m);
}
idnode_set_free(v);
}
}
pthread_mutex_unlock(&global_lock);
return 0;
}
static int
api_idnode_class
( const char *class, htsmsg_t *args, htsmsg_t **resp )
{
int i, brief;
const idclass_t *idc;
idnode_set_t *is;
idnode_t *in;
htsmsg_t *e;
// TODO: this only works if pass as integer
brief = htsmsg_get_bool_or_default(args, "brief", 0);
pthread_mutex_lock(&global_lock);
/* Find class */
if (!(idc = idclass_find(class))) {
pthread_mutex_unlock(&global_lock);
return EINVAL;
}
*resp = htsmsg_create_list();
if ((is = idnode_find_all(idc))) {
for (i = 0; i < is->is_count; i++) {
in = is->is_array[i];
/* Name/UUID only */
if (brief) {
e = htsmsg_create_map();
htsmsg_add_str(e, "key", idnode_uuid_as_str(in));
htsmsg_add_str(e, "val", idnode_get_title(in));
/* Full record */
} else
e = idnode_serialize(in);
if (e)
htsmsg_add_msg(*resp, NULL, e);
}
}
pthread_mutex_unlock(&global_lock);
return 0;
}
static int
api_idnode_load
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
int err = 0;
idnode_t *in;
htsmsg_t *l;
htsmsg_field_t *f;
const char *uuid, *class;
/* Class based */
if ((class = htsmsg_get_str(args, "class")))
return api_idnode_class(class, args, resp);
/* ID based */
if (!(f = htsmsg_field_find(args, "uuid")))
return EINVAL;
pthread_mutex_lock(&global_lock);
/* Single */
if (f->hmf_type == HMF_STR) {
uuid = htsmsg_field_get_string(f);
in = idnode_find(uuid, NULL);
if (in)
*resp = idnode_serialize(in);
else
err = ENOENT;
/* Multiple */
} else if (f->hmf_type == HMF_LIST) {
l = htsmsg_get_list_by_field(f);
*resp = htsmsg_create_list();
HTSMSG_FOREACH(f, l) {
if (!(uuid = htsmsg_field_get_string(f))) continue;
if (!(in = idnode_find(uuid, NULL))) continue;
htsmsg_add_msg(*resp, NULL, idnode_serialize(in));
}
/* Invalid */
} else {
err = EINVAL;
}
pthread_mutex_unlock(&global_lock);
return err;
}
static int
api_idnode_save
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
return 0;
}
static int
api_idnode_tree
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
const char *uuid = htsmsg_get_str(args, "uuid");
const char *root = htsmsg_get_str(args, "root");
return api_idnode_tree0(uuid, root, NULL, resp);
}
void api_idnode_init ( void )
{
static api_hook_t ah[] = {
{ "idnode/load", ACCESS_ANONYMOUS, api_idnode_load, NULL },
{ "idnode/save", ACCESS_ADMIN, api_idnode_save, NULL },
{ "idnode/tree", ACCESS_ANONYMOUS, api_idnode_tree, NULL },
{ NULL },
};
api_register_all(ah);
}
#endif /* __TVH_API_IDNODE_H__ */

View file

@ -2223,7 +2223,7 @@ extjs_start(void)
http_path_add("/tvadapters",
NULL, extjs_tvadapters, ACCESS_ADMIN);
http_path_add("/api/idnode", NULL, extjs_idnode, ACCESS_ADMIN); // TODO: might want diff access for read/write`
http_path_add("/api/idnode2", NULL, extjs_idnode, ACCESS_ADMIN); // TODO: might want diff access for read/write`
http_path_add("/api/service_mapping", NULL, extjs_service_mapping, ACCESS_ADMIN);
extjs_start_dvb();

View file

@ -30,15 +30,15 @@ webui_api_handler
( http_connection_t *hc, const char *remain, void *opaque )
{
int r;
http_arg_t *ha;
htsmsg_t *args, *resp;
const char *a = http_arg_get(&hc->hc_req_args, "args");
const char *op = http_arg_get(&hc->hc_req_args, "method");
// Compat
if (!op)
op = http_arg_get(&hc->hc_req_args, "op");
/* Parse arguments */
if (a)
args = htsmsg_json_deserialize(a);
@ -47,6 +47,15 @@ webui_api_handler
if (!args)
return HTTP_STATUS_BAD_REQUEST;
/* Add HTTP arguments?? */
TAILQ_FOREACH(ha, &hc->hc_req_args, link) {
// Ignore obvious keys
if (strcmp("op", ha->key) &&
strcmp("method", ha->key) &&
strcmp("args", ha->key))
htsmsg_add_str(args, ha->key, ha->val);
}
/* Add operation */
if (!htsmsg_get_str(args, "method") && op)
htsmsg_add_str(args, "method", op);