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