1 /*
2 * tvheadend, HTTP interface
3 * Copyright (C) 2007 Andreas Öman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #ifndef HTTP_H_
20 #define HTTP_H_
21
22 #include "htsbuf.h"
23 #include "url.h"
24 #include "tvhpoll.h"
25 #include "access.h"
26 #include "atomic.h"
27
28 struct channel;
29 struct http_path;
30
31 typedef LIST_HEAD(, http_path) http_path_list_t;
32
33 typedef TAILQ_HEAD(http_arg_list, http_arg) http_arg_list_t;
34
35 typedef RB_HEAD(,http_arg) http_arg_tree_t;
36
37 typedef struct http_arg {
38 RB_ENTRY(http_arg) rb_link;
39 TAILQ_ENTRY(http_arg) link;
40 char *key;
41 char *val;
42 } http_arg_t;
43
44 #define HTTP_STATUS_CONTINUE 100
45 #define HTTP_STATUS_PSWITCH 101
46 #define HTTP_STATUS_OK 200
47 #define HTTP_STATUS_CREATED 201
48 #define HTTP_STATUS_ACCEPTED 202
49 #define HTTP_STATUS_NON_AUTH_INFO 203
50 #define HTTP_STATUS_NO_CONTENT 204
51 #define HTTP_STATUS_RESET_CONTENT 205
52 #define HTTP_STATUS_PARTIAL_CONTENT 206
53 #define HTTP_STATUS_MULTIPLE 300
54 #define HTTP_STATUS_MOVED 301
55 #define HTTP_STATUS_FOUND 302
56 #define HTTP_STATUS_SEE_OTHER 303
57 #define HTTP_STATUS_NOT_MODIFIED 304
58 #define HTTP_STATUS_USE_PROXY 305
59 #define HTTP_STATUS_TMP_REDIR 307
60 #define HTTP_STATUS_BAD_REQUEST 400
61 #define HTTP_STATUS_UNAUTHORIZED 401
62 #define HTTP_STATUS_PAYMENT 402
63 #define HTTP_STATUS_FORBIDDEN 403
64 #define HTTP_STATUS_NOT_FOUND 404
65 #define HTTP_STATUS_NOT_ALLOWED 405
66 #define HTTP_STATUS_NOT_ACCEPTABLE 406
67 #define HTTP_STATUS_PROXY_AUTH 407
68 #define HTTP_STATUS_TIMEOUT 408
69 #define HTTP_STATUS_CONFLICT 409
70 #define HTTP_STATUS_GONE 410
71 #define HTTP_STATUS_LENGTH 411
72 #define HTTP_STATUS_PRECONDITION 412
73 #define HTTP_STATUS_ENTITY_OVER 413
74 #define HTTP_STATUS_URI_TOO_LONG 414
75 #define HTTP_STATUS_UNSUPPORTED 415
76 #define HTTP_STATUS_BAD_RANGE 417
77 #define HTTP_STATUS_EXPECTATION 418
78 #define HTTP_STATUS_BANDWIDTH 453
79 #define HTTP_STATUS_BAD_SESSION 454
80 #define HTTP_STATUS_METHOD_INVALID 455
81 #define HTTP_STATUS_BAD_TRANSFER 456
82 #define HTTP_STATUS_INTERNAL 500
83 #define HTTP_STATUS_NOT_IMPLEMENTED 501
84 #define HTTP_STATUS_BAD_GATEWAY 502
85 #define HTTP_STATUS_SERVICE 503
86 #define HTTP_STATUS_GATEWAY_TIMEOUT 504
87 #define HTTP_STATUS_HTTP_VERSION 505
88 #define HTTP_STATUS_OP_NOT_SUPPRT 551
89
90 typedef enum http_state {
91 HTTP_CON_WAIT_REQUEST,
92 HTTP_CON_READ_HEADER,
93 HTTP_CON_END,
94 HTTP_CON_POST_DATA,
95 HTTP_CON_SENDING,
96 HTTP_CON_SENT,
97 HTTP_CON_RECEIVING,
98 HTTP_CON_DONE,
99 HTTP_CON_IDLE,
100 HTTP_CON_OK
101 } http_state_t;
102
103 typedef enum http_cmd {
104 HTTP_CMD_NONE,
105 HTTP_CMD_GET,
106 HTTP_CMD_HEAD,
107 HTTP_CMD_POST,
108 RTSP_CMD_DESCRIBE,
109 RTSP_CMD_OPTIONS,
110 RTSP_CMD_SETUP,
111 RTSP_CMD_TEARDOWN,
112 RTSP_CMD_PLAY,
113 RTSP_CMD_PAUSE,
114 RTSP_CMD_GET_PARAMETER,
115 } http_cmd_t;
116
117 #define HTTP_CMD_OPTIONS RTSP_CMD_OPTIONS
118
119 typedef enum http_ver {
120 HTTP_VERSION_1_0,
121 HTTP_VERSION_1_1,
122 RTSP_VERSION_1_0,
123 } http_ver_t;
124
125 typedef struct http_connection {
126 int hc_fd;
127 struct sockaddr_storage *hc_peer;
128 char *hc_peer_ipstr;
129 struct sockaddr_storage *hc_self;
130 char *hc_representative;
131
132 pthread_mutex_t *hc_paths_mutex;
133 http_path_list_t *hc_paths;
134 int (*hc_process)(struct http_connection *hc, htsbuf_queue_t *spill);
135
136 char *hc_url;
137 char *hc_url_orig;
138 int hc_keep_alive;
139
140 htsbuf_queue_t hc_reply;
141
142 int hc_extra_insend;
143 pthread_mutex_t hc_extra_lock;
144 int hc_extra_chunks;
145 htsbuf_queue_t hc_extra;
146
147 http_arg_list_t hc_args;
148
149 http_arg_list_t hc_req_args; /* Argumets from GET or POST request */
150
151 http_state_t hc_state;
152 http_cmd_t hc_cmd;
153 http_ver_t hc_version;
154
155 char *hc_username;
156 char *hc_password;
157 char *hc_authhdr;
158 char *hc_nonce;
159 access_t *hc_access;
160
161 struct config_head *hc_user_config;
162
163 int hc_no_output;
164 int hc_shutdown;
165 uint64_t hc_cseq;
166 char *hc_session;
167
168 /* Support for HTTP POST */
169
170 char *hc_post_data;
171 unsigned int hc_post_len;
172
173 } http_connection_t;
174
175 extern void *http_server;
176
177 const char *http_cmd2str(int val);
178 int http_str2cmd(const char *str);
179 const char *http_ver2str(int val);
180 int http_str2ver(const char *str);
181
http_arg_init(struct http_arg_list * list)182 static inline void http_arg_init(struct http_arg_list *list)
183 {
184 TAILQ_INIT(list);
185 }
186
187 void http_arg_remove(struct http_arg_list *list, struct http_arg *arg);
188 void http_arg_flush(struct http_arg_list *list);
189
190 char *http_arg_get(struct http_arg_list *list, const char *name);
191 char *http_arg_get_remove(struct http_arg_list *list, const char *name);
192
193 void http_arg_set(struct http_arg_list *list, const char *key, const char *val);
194
http_args_empty(const struct http_arg_list * list)195 static inline int http_args_empty(const struct http_arg_list *list) { return TAILQ_EMPTY(list); }
196
197 int http_tokenize(char *buf, char **vec, int vecsize, int delimiter);
198
199 void http_error(http_connection_t *hc, int error);
200
201 int http_encoding_valid(http_connection_t *hc, const char *encoding);
202
203 void http_output_html(http_connection_t *hc);
204
205 void http_output_content(http_connection_t *hc, const char *content);
206
207 void http_redirect(http_connection_t *hc, const char *location,
208 struct http_arg_list *req_args, int external);
209
210 void http_css_import(http_connection_t *hc, const char *location);
211
212 void http_extra_destroy(http_connection_t *hc);
213
214 int http_extra_flush(http_connection_t *hc);
215
216 int http_extra_flush_partial(http_connection_t *hc);
217
218 int http_extra_send(http_connection_t *hc, const void *data,
219 size_t data_len, int may_discard);
220
221 int http_extra_send_prealloc(http_connection_t *hc, const void *data,
222 size_t data_len, int may_discard);
223
http_send_begin(http_connection_t * hc)224 static inline void http_send_begin(http_connection_t *hc)
225 {
226 atomic_add(&hc->hc_extra_insend, 1);
227 if (atomic_get(&hc->hc_extra_chunks) > 0)
228 http_extra_flush_partial(hc);
229 }
230
http_send_end(http_connection_t * hc)231 static inline void http_send_end(http_connection_t *hc)
232 {
233 atomic_dec(&hc->hc_extra_insend, 1);
234 if (atomic_get(&hc->hc_extra_chunks) > 0)
235 http_extra_flush(hc);
236 }
237
238 void http_send_header(http_connection_t *hc, int rc, const char *content,
239 int64_t contentlen, const char *encoding,
240 const char *location, int maxage, const char *range,
241 const char *disposition, http_arg_list_t *args);
242
243 void http_serve_requests(http_connection_t *hc);
244
245 void http_cancel(void *opaque);
246
247 typedef int (http_callback_t)(http_connection_t *hc,
248 const char *remain, void *opaque);
249
250 typedef char * (http_path_modify_t)(http_connection_t *hc,
251 const char * path, int *cut);
252
253
254 typedef struct http_path {
255 LIST_ENTRY(http_path) hp_link;
256 const char *hp_path;
257 void *hp_opaque;
258 http_callback_t *hp_callback;
259 int hp_len;
260 int hp_no_verification;
261 uint32_t hp_accessmask;
262 http_path_modify_t *hp_path_modify;
263 } http_path_t;
264
265 http_path_t *http_path_add_modify(const char *path, void *opaque,
266 http_callback_t *callback,
267 uint32_t accessmask,
268 http_path_modify_t path_modify);
269 http_path_t *http_path_add(const char *path, void *opaque,
270 http_callback_t *callback, uint32_t accessmask);
271
272 void http_server_init(const char *bindaddr);
273 void http_server_register(void);
274 void http_server_done(void);
275
276 int http_access_verify(http_connection_t *hc, int mask);
277 int http_access_verify_channel(http_connection_t *hc, int mask,
278 struct channel *ch);
279
280 void http_parse_args(http_arg_list_t *list, char *args);
281
282 char *http_get_hostpath(http_connection_t *hc);
283
284 /*
285 * HTTP/RTSP Client
286 */
287
288 typedef struct http_client http_client_t;
289
290 typedef struct http_client_wcmd {
291
292 TAILQ_ENTRY(http_client_wcmd) link;
293
294 enum http_cmd wcmd;
295 int wcseq;
296
297 void *wbuf;
298 size_t wpos;
299 size_t wsize;
300 } http_client_wcmd_t;
301
302 struct http_client {
303
304 TAILQ_ENTRY(http_client) hc_link;
305
306 pthread_mutex_t hc_mutex;
307
308 int hc_id;
309 int hc_fd;
310 char *hc_scheme;
311 char *hc_host;
312 int hc_port;
313 char *hc_bindaddr;
314 tvhpoll_t *hc_efd;
315 int hc_pevents;
316 int hc_pevents_pause;
317
318 int hc_code;
319 http_ver_t hc_version;
320 http_ver_t hc_redirv;
321 http_cmd_t hc_cmd;
322
323 struct http_arg_list hc_args; /* header */
324
325 char *hc_url;
326
327 void *hc_aux;
328 size_t hc_data_limit;
329 size_t hc_io_size;
330 char *hc_data; /* data body */
331 size_t hc_data_size; /* data body size - result for caller */
332
333 int64_t hc_ping_time; /* last issued command */
334
335 char *hc_rbuf; /* read buffer */
336 size_t hc_rsize; /* read buffer size */
337 size_t hc_rpos; /* read buffer position */
338 size_t hc_hsize; /* header size in bytes */
339 size_t hc_csize; /* contents size in bytes */
340 char *hc_chunk;
341 size_t hc_chunk_size;
342 size_t hc_chunk_csize;
343 size_t hc_chunk_alloc;
344 size_t hc_chunk_pos;
345 char *hc_location;
346 uint8_t hc_running; /* outside hc_mutex */
347 uint8_t hc_shutdown_wait;/* outside hc_mutex */
348 int hc_refcnt; /* callback protection - outside hc_mutex */
349 int hc_redirects;
350 int hc_result;
351 int hc_shutdown:1;
352 int hc_sending:1;
353 int hc_einprogress:1;
354 int hc_reconnected:1;
355 int hc_keepalive:1;
356 int hc_in_data:1;
357 int hc_in_rtp_data:1;
358 int hc_chunked:1;
359 int hc_chunk_trails:1;
360 int hc_handle_location:1; /* handle the redirection (location) requests */
361 int hc_pause:1;
362
363 http_client_wcmd_t *hc_wcmd;
364 TAILQ_HEAD(,http_client_wcmd) hc_wqueue;
365
366 int hc_verify_peer; /* SSL - verify peer */
367
368 int hc_cseq; /* RTSP */
369 int hc_rcseq; /* RTSP - expected cseq */
370 char *hc_rtsp_session;
371 char *hc_rtp_dest;
372 int hc_rtp_port;
373 int hc_rtcp_port;
374 int hc_rtp_tcp;
375 int hc_rtcp_tcp;
376 int hc_rtcp_server_port;
377 int hc_rtp_multicast:1;
378 long hc_rtsp_stream_id;
379 int hc_rtp_timeout;
380 char *hc_rtsp_user;
381 char *hc_rtsp_pass;
382 char hc_rtsp_keep_alive_cmd;
383
384 struct http_client_ssl *hc_ssl; /* ssl internals */
385
386 mtimer_t hc_close_timer;
387
388 /* callbacks */
389 void (*hc_hdr_create) (http_client_t *hc, http_arg_list_t *h,
390 const url_t *url, int keepalive);
391 int (*hc_hdr_received) (http_client_t *hc);
392 int (*hc_data_received)(http_client_t *hc, void *buf, size_t len);
393 int (*hc_data_complete)(http_client_t *hc);
394 int (*hc_rtp_data_received)(http_client_t *hc, void *buf, size_t len);
395 int (*hc_rtp_data_complete)(http_client_t *hc);
396 void (*hc_conn_closed) (http_client_t *hc, int err);
397 };
398
399 void http_client_init ( const char *user_agent );
400 void http_client_done ( void );
401
402 http_client_t*
403 http_client_connect ( void *aux, http_ver_t ver, const char *scheme,
404 const char *host, int port, const char *bindaddr );
405 void http_client_register ( http_client_t *hc );
406 void http_client_close ( http_client_t *hc );
407
408 int http_client_send( http_client_t *hc, http_cmd_t cmd,
409 const char *path, const char *query,
410 http_arg_list_t *header, void *body, size_t body_size );
411 void http_client_basic_auth( http_client_t *hc, http_arg_list_t *h,
412 const char *user, const char *pass );
413 void http_client_basic_args ( http_client_t *hc, http_arg_list_t *h,
414 const url_t *url, int keepalive );
415 void http_client_add_args ( http_client_t *hc, http_arg_list_t *h,
416 const char *args );
417 int http_client_simple_reconnect ( http_client_t *hc, const url_t *u, http_ver_t ver );
418 int http_client_simple( http_client_t *hc, const url_t *url);
419 int http_client_clear_state( http_client_t *hc );
420 int http_client_run( http_client_t *hc );
421 void http_client_ssl_peer_verify( http_client_t *hc, int verify );
422 void http_client_unpause( http_client_t *hc );
423
424 /*
425 * RTSP helpers
426 */
427
428 int rtsp_send_ext( http_client_t *hc, http_cmd_t cmd, const char *path,
429 const char *query, http_arg_list_t *hdr, const char *body, size_t size );
430
431 static inline int
rtsp_send(http_client_t * hc,http_cmd_t cmd,const char * path,const char * query,http_arg_list_t * hdr)432 rtsp_send( http_client_t *hc, http_cmd_t cmd, const char *path,
433 const char *query, http_arg_list_t *hdr ) {
434 return rtsp_send_ext( hc, cmd, path, query, hdr, NULL, 0 );
435 }
436
437 void rtsp_clear_session( http_client_t *hc );
438
439 int rtsp_options_decode( http_client_t *hc );
rtsp_options(http_client_t * hc)440 static inline int rtsp_options( http_client_t *hc ) {
441 return rtsp_send(hc, RTSP_CMD_OPTIONS, NULL, NULL, NULL);
442 }
443
444 int rtsp_setup_decode( http_client_t *hc, int satip );
445 int rtsp_setup( http_client_t *hc, const char *path, const char *query,
446 const char *multicast_addr, int rtp_port, int rtcp_port );
447
448 static inline int
rtsp_play(http_client_t * hc,const char * path,const char * query)449 rtsp_play( http_client_t *hc, const char *path, const char *query ) {
450 return rtsp_send(hc, RTSP_CMD_PLAY, path, query, NULL);
451 }
452
453 static inline int
rtsp_pause(http_client_t * hc,const char * path,const char * query)454 rtsp_pause( http_client_t *hc, const char *path, const char *query ) {
455 return rtsp_send(hc, RTSP_CMD_PAUSE, path, query, NULL);
456 }
457
458 static inline int
rtsp_teardown(http_client_t * hc,const char * path,const char * query)459 rtsp_teardown( http_client_t *hc, const char *path, const char *query ) {
460 return rtsp_send(hc, RTSP_CMD_TEARDOWN, path, query, NULL);
461 }
462
463 int rtsp_get_parameter( http_client_t *hc, const char *parameter );
464
465 int rtsp_describe_decode( http_client_t *hc );
466 static inline int
rtsp_describe(http_client_t * hc,const char * path,const char * query)467 rtsp_describe( http_client_t *hc, const char *path, const char *query ) {
468 return rtsp_send(hc, RTSP_CMD_DESCRIBE, path, query, NULL);
469 }
470
471 #endif /* HTTP_H_ */
472