1 /*
2 * API - service related calls
3 *
4 * Copyright (C) 2013 Adam Sutton
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef __TVH_API_SERVICE_H__
21 #define __TVH_API_SERVICE_H__
22
23 #include "tvheadend.h"
24 #include "subscriptions.h"
25 #include "access.h"
26 #include "api.h"
27 #include "tcp.h"
28 #include "input.h"
29
30 static int
api_status_inputs(access_t * perm,void * opaque,const char * op,htsmsg_t * args,htsmsg_t ** resp)31 api_status_inputs
32 ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
33 {
34 int c = 0;
35 htsmsg_t *l, *e;
36 tvh_input_t *ti;
37 tvh_input_stream_t *st;
38 tvh_input_stream_list_t stl = { 0 };
39
40 pthread_mutex_lock(&global_lock);
41 TVH_INPUT_FOREACH(ti)
42 ti->ti_get_streams(ti, &stl);
43 pthread_mutex_unlock(&global_lock);
44
45 l = htsmsg_create_list();
46 while ((st = LIST_FIRST(&stl))) {
47 e = tvh_input_stream_create_msg(st);
48 htsmsg_add_msg(l, NULL, e);
49 tvh_input_stream_destroy(st);
50 LIST_REMOVE(st, link);
51 free(st);
52 c++;
53 }
54
55 *resp = htsmsg_create_map();
56 htsmsg_add_msg(*resp, "entries", l);
57 htsmsg_add_u32(*resp, "totalCount", c);
58
59 return 0;
60 }
61
62 static int
api_status_subscriptions(access_t * perm,void * opaque,const char * op,htsmsg_t * args,htsmsg_t ** resp)63 api_status_subscriptions
64 ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
65 {
66 int c;
67 htsmsg_t *l, *e;
68 th_subscription_t *ths;
69
70 l = htsmsg_create_list();
71 c = 0;
72 pthread_mutex_lock(&global_lock);
73 LIST_FOREACH(ths, &subscriptions, ths_global_link) {
74 e = subscription_create_msg(ths, perm->aa_lang_ui);
75 htsmsg_add_msg(l, NULL, e);
76 c++;
77 }
78 pthread_mutex_unlock(&global_lock);
79
80 *resp = htsmsg_create_map();
81 htsmsg_add_msg(*resp, "entries", l);
82 htsmsg_add_u32(*resp, "totalCount", c);
83
84 return 0;
85 }
86
87 static int
api_status_connections(access_t * perm,void * opaque,const char * op,htsmsg_t * args,htsmsg_t ** resp)88 api_status_connections
89 ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
90 {
91 pthread_mutex_lock(&global_lock);
92 *resp = tcp_server_connections();
93 pthread_mutex_unlock(&global_lock);
94 return 0;
95 }
96
97 static int
api_connections_cancel(access_t * perm,void * opaque,const char * op,htsmsg_t * args,htsmsg_t ** resp)98 api_connections_cancel
99 ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
100 {
101 htsmsg_field_t *f;
102 htsmsg_t *ids;
103 uint32_t id;
104
105 if (!(f = htsmsg_field_find(args, "id")))
106 return EINVAL;
107 if (!(ids = htsmsg_field_get_list(f)))
108 if (htsmsg_field_get_u32(f, &id))
109 return EINVAL;
110
111 if (ids) {
112 HTSMSG_FOREACH(f, ids) {
113 if (htsmsg_field_get_u32(f, &id)) continue;
114 if (!id) continue;
115 pthread_mutex_lock(&global_lock);
116 tcp_connection_cancel(id);
117 pthread_mutex_unlock(&global_lock);
118 }
119 } else {
120 pthread_mutex_lock(&global_lock);
121 tcp_connection_cancel(id);
122 pthread_mutex_unlock(&global_lock);
123 }
124 return 0;
125 }
126
127 static void
input_clear_stats(const char * uuid)128 input_clear_stats(const char *uuid)
129 {
130 tvh_input_instance_t *tii;
131 tvh_input_t *ti;
132
133 pthread_mutex_lock(&global_lock);
134 if ((tii = tvh_input_instance_find_by_uuid(uuid)) != NULL)
135 if (tii->tii_clear_stats)
136 tii->tii_clear_stats(tii);
137 if ((ti = tvh_input_find_by_uuid(uuid)) != NULL)
138 if (ti->ti_clear_stats)
139 ti->ti_clear_stats(ti);
140 pthread_mutex_unlock(&global_lock);
141 }
142
143 static int
api_status_input_clear_stats(access_t * perm,void * opaque,const char * op,htsmsg_t * args,htsmsg_t ** resp)144 api_status_input_clear_stats
145 ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
146 {
147 htsmsg_field_t *f;
148 htsmsg_t *ids;
149 const char *uuid;
150
151 if (!(f = htsmsg_field_find(args, "uuid")))
152 return EINVAL;
153 if (!(ids = htsmsg_field_get_list(f))) {
154 if ((uuid = htsmsg_field_get_str(f)) == NULL)
155 return EINVAL;
156 input_clear_stats(uuid);
157 } else {
158 HTSMSG_FOREACH(f, ids) {
159 if ((uuid = htsmsg_field_get_str(f)) == NULL) continue;
160 input_clear_stats(uuid);
161 }
162 }
163 return 0;
164 }
165
api_status_init(void)166 void api_status_init ( void )
167 {
168 static api_hook_t ah[] = {
169 { "status/connections", ACCESS_ADMIN, api_status_connections, NULL },
170 { "status/subscriptions", ACCESS_ADMIN, api_status_subscriptions, NULL },
171 { "status/inputs", ACCESS_ADMIN, api_status_inputs, NULL },
172 { "status/inputclrstats", ACCESS_ADMIN, api_status_input_clear_stats, NULL },
173 { "connections/cancel", ACCESS_ADMIN, api_connections_cancel, NULL },
174 { NULL },
175 };
176
177 api_register_all(ah);
178 }
179
180
181 #endif /* __TVH_API_IDNODE_H__ */
182