frwu: lowercase the FRWU codec name
[libav.git] / avserver.c
1 /*
2 * Multiple format streaming server
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4 *
5 * This file is part of Libav.
6 *
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "config.h"
23 #if !HAVE_CLOSESOCKET
24 #define closesocket close
25 #endif
26 #include <string.h>
27 #include <stdlib.h>
28 #include "libavformat/avformat.h"
29 // FIXME those are internal headers, avserver _really_ shouldn't use them
30 #include "libavformat/ffm.h"
31 #include "libavformat/network.h"
32 #include "libavformat/os_support.h"
33 #include "libavformat/rtpdec.h"
34 #include "libavformat/rtsp.h"
35 #include "libavformat/avio_internal.h"
36 #include "libavformat/internal.h"
37 #include "libavformat/url.h"
38
39 #include "libavutil/avstring.h"
40 #include "libavutil/lfg.h"
41 #include "libavutil/dict.h"
42 #include "libavutil/mathematics.h"
43 #include "libavutil/random_seed.h"
44 #include "libavutil/parseutils.h"
45 #include "libavutil/opt.h"
46 #include <stdarg.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <sys/ioctl.h>
50 #if HAVE_POLL_H
51 #include <poll.h>
52 #endif
53 #include <errno.h>
54 #include <sys/time.h>
55 #include <time.h>
56 #include <sys/wait.h>
57 #include <signal.h>
58 #if HAVE_DLFCN_H
59 #include <dlfcn.h>
60 #endif
61
62 #include "cmdutils.h"
63
64 const char program_name[] = "avserver";
65 const int program_birth_year = 2000;
66
67 static const OptionDef options[];
68
69 enum HTTPState {
70 HTTPSTATE_WAIT_REQUEST,
71 HTTPSTATE_SEND_HEADER,
72 HTTPSTATE_SEND_DATA_HEADER,
73 HTTPSTATE_SEND_DATA, /* sending TCP or UDP data */
74 HTTPSTATE_SEND_DATA_TRAILER,
75 HTTPSTATE_RECEIVE_DATA,
76 HTTPSTATE_WAIT_FEED, /* wait for data from the feed */
77 HTTPSTATE_READY,
78
79 RTSPSTATE_WAIT_REQUEST,
80 RTSPSTATE_SEND_REPLY,
81 RTSPSTATE_SEND_PACKET,
82 };
83
84 static const char *http_state[] = {
85 "HTTP_WAIT_REQUEST",
86 "HTTP_SEND_HEADER",
87
88 "SEND_DATA_HEADER",
89 "SEND_DATA",
90 "SEND_DATA_TRAILER",
91 "RECEIVE_DATA",
92 "WAIT_FEED",
93 "READY",
94
95 "RTSP_WAIT_REQUEST",
96 "RTSP_SEND_REPLY",
97 "RTSP_SEND_PACKET",
98 };
99
100 #define MAX_STREAMS 20
101
102 #define IOBUFFER_INIT_SIZE 8192
103
104 /* timeouts are in ms */
105 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
106 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
107
108 #define SYNC_TIMEOUT (10 * 1000)
109
110 typedef struct RTSPActionServerSetup {
111 uint32_t ipaddr;
112 char transport_option[512];
113 } RTSPActionServerSetup;
114
115 typedef struct {
116 int64_t count1, count2;
117 int64_t time1, time2;
118 } DataRateData;
119
120 /* context associated with one connection */
121 typedef struct HTTPContext {
122 enum HTTPState state;
123 int fd; /* socket file descriptor */
124 struct sockaddr_in from_addr; /* origin */
125 struct pollfd *poll_entry; /* used when polling */
126 int64_t timeout;
127 uint8_t *buffer_ptr, *buffer_end;
128 int http_error;
129 int post;
130 int chunked_encoding;
131 int chunk_size; /* 0 if it needs to be read */
132 struct HTTPContext *next;
133 int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
134 int64_t data_count;
135 /* feed input */
136 int feed_fd;
137 /* input format handling */
138 AVFormatContext *fmt_in;
139 int64_t start_time; /* In milliseconds - this wraps fairly often */
140 int64_t first_pts; /* initial pts value */
141 int64_t cur_pts; /* current pts value from the stream in us */
142 int64_t cur_frame_duration; /* duration of the current frame in us */
143 int cur_frame_bytes; /* output frame size, needed to compute
144 the time at which we send each
145 packet */
146 int pts_stream_index; /* stream we choose as clock reference */
147 int64_t cur_clock; /* current clock reference value in us */
148 /* output format handling */
149 struct FFStream *stream;
150 /* -1 is invalid stream */
151 int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
152 int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
153 int switch_pending;
154 AVFormatContext fmt_ctx; /* instance of FFStream for one user */
155 int last_packet_sent; /* true if last data packet was sent */
156 int suppress_log;
157 DataRateData datarate;
158 int wmp_client_id;
159 char protocol[16];
160 char method[16];
161 char url[128];
162 int buffer_size;
163 uint8_t *buffer;
164 int is_packetized; /* if true, the stream is packetized */
165 int packet_stream_index; /* current stream for output in state machine */
166
167 /* RTSP state specific */
168 uint8_t *pb_buffer; /* XXX: use that in all the code */
169 AVIOContext *pb;
170 int seq; /* RTSP sequence number */
171
172 /* RTP state specific */
173 enum RTSPLowerTransport rtp_protocol;
174 char session_id[32]; /* session id */
175 AVFormatContext *rtp_ctx[MAX_STREAMS];
176
177 /* RTP/UDP specific */
178 URLContext *rtp_handles[MAX_STREAMS];
179
180 /* RTP/TCP specific */
181 struct HTTPContext *rtsp_c;
182 uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
183 } HTTPContext;
184
185 /* each generated stream is described here */
186 enum StreamType {
187 STREAM_TYPE_LIVE,
188 STREAM_TYPE_STATUS,
189 STREAM_TYPE_REDIRECT,
190 };
191
192 enum IPAddressAction {
193 IP_ALLOW = 1,
194 IP_DENY,
195 };
196
197 typedef struct IPAddressACL {
198 struct IPAddressACL *next;
199 enum IPAddressAction action;
200 /* These are in host order */
201 struct in_addr first;
202 struct in_addr last;
203 } IPAddressACL;
204
205 /* description of each stream of the avserver.conf file */
206 typedef struct FFStream {
207 enum StreamType stream_type;
208 char filename[1024]; /* stream filename */
209 struct FFStream *feed; /* feed we are using (can be null if
210 coming from file) */
211 AVDictionary *in_opts; /* input parameters */
212 AVInputFormat *ifmt; /* if non NULL, force input format */
213 AVOutputFormat *fmt;
214 IPAddressACL *acl;
215 char dynamic_acl[1024];
216 int nb_streams;
217 int prebuffer; /* Number of millseconds early to start */
218 int64_t max_time; /* Number of milliseconds to run */
219 int send_on_key;
220 AVStream *streams[MAX_STREAMS];
221 int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
222 char feed_filename[1024]; /* file name of the feed storage, or
223 input file name for a stream */
224 char author[512];
225 char title[512];
226 char copyright[512];
227 char comment[512];
228 pid_t pid; /* of avconv process */
229 time_t pid_start; /* of avconv process */
230 char **child_argv;
231 struct FFStream *next;
232 unsigned bandwidth; /* bandwidth, in kbits/s */
233 /* RTSP options */
234 char *rtsp_option;
235 /* multicast specific */
236 int is_multicast;
237 struct in_addr multicast_ip;
238 int multicast_port; /* first port used for multicast */
239 int multicast_ttl;
240 int loop; /* if true, send the stream in loops (only meaningful if file) */
241
242 /* feed specific */
243 int feed_opened; /* true if someone is writing to the feed */
244 int is_feed; /* true if it is a feed */
245 int readonly; /* True if writing is prohibited to the file */
246 int truncate; /* True if feeder connection truncate the feed file */
247 int conns_served;
248 int64_t bytes_served;
249 int64_t feed_max_size; /* maximum storage size, zero means unlimited */
250 int64_t feed_write_index; /* current write position in feed (it wraps around) */
251 int64_t feed_size; /* current size of feed */
252 struct FFStream *next_feed;
253 } FFStream;
254
255 typedef struct FeedData {
256 long long data_count;
257 float avg_frame_size; /* frame size averaged over last frames with exponential mean */
258 } FeedData;
259
260 static struct sockaddr_in my_http_addr;
261 static struct sockaddr_in my_rtsp_addr;
262
263 static char logfilename[1024];
264 static HTTPContext *first_http_ctx;
265 static FFStream *first_feed; /* contains only feeds */
266 static FFStream *first_stream; /* contains all streams, including feeds */
267
268 static void new_connection(int server_fd, int is_rtsp);
269 static void close_connection(HTTPContext *c);
270
271 /* HTTP handling */
272 static int handle_connection(HTTPContext *c);
273 static int http_parse_request(HTTPContext *c);
274 static int http_send_data(HTTPContext *c);
275 static void compute_status(HTTPContext *c);
276 static int open_input_stream(HTTPContext *c, const char *info);
277 static int http_start_receive_data(HTTPContext *c);
278 static int http_receive_data(HTTPContext *c);
279
280 /* RTSP handling */
281 static int rtsp_parse_request(HTTPContext *c);
282 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
283 static void rtsp_cmd_options(HTTPContext *c, const char *url);
284 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
285 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
286 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
287 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
288
289 /* SDP handling */
290 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
291 struct in_addr my_ip);
292
293 /* RTP handling */
294 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
295 FFStream *stream, const char *session_id,
296 enum RTSPLowerTransport rtp_protocol);
297 static int rtp_new_av_stream(HTTPContext *c,
298 int stream_index, struct sockaddr_in *dest_addr,
299 HTTPContext *rtsp_c);
300
301 static const char *my_program_name;
302 static const char *my_program_dir;
303
304 static const char *config_filename = "/etc/avserver.conf";
305
306 static int avserver_debug;
307 static int avserver_daemon;
308 static int no_launch;
309 static int need_to_start_children;
310
311 /* maximum number of simultaneous HTTP connections */
312 static unsigned int nb_max_http_connections = 2000;
313 static unsigned int nb_max_connections = 5;
314 static unsigned int nb_connections;
315
316 static uint64_t max_bandwidth = 1000;
317 static uint64_t current_bandwidth;
318
319 static int64_t cur_time; // Making this global saves on passing it around everywhere
320
321 static AVLFG random_state;
322
323 static FILE *logfile = NULL;
324
325 void exit_program(int ret)
326 {
327 exit(ret);
328 }
329
330 /* FIXME: make avserver work with IPv6 */
331 /* resolve host with also IP address parsing */
332 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
333 {
334
335 if (!ff_inet_aton(hostname, sin_addr)) {
336 #if HAVE_GETADDRINFO
337 struct addrinfo *ai, *cur;
338 struct addrinfo hints;
339 memset(&hints, 0, sizeof(hints));
340 hints.ai_family = AF_INET;
341 if (getaddrinfo(hostname, NULL, &hints, &ai))
342 return -1;
343 /* getaddrinfo returns a linked list of addrinfo structs.
344 * Even if we set ai_family = AF_INET above, make sure
345 * that the returned one actually is of the correct type. */
346 for (cur = ai; cur; cur = cur->ai_next) {
347 if (cur->ai_family == AF_INET) {
348 *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
349 freeaddrinfo(ai);
350 return 0;
351 }
352 }
353 freeaddrinfo(ai);
354 return -1;
355 #else
356 struct hostent *hp;
357 hp = gethostbyname(hostname);
358 if (!hp)
359 return -1;
360 memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
361 #endif
362 }
363 return 0;
364 }
365
366 static char *ctime1(char *buf2)
367 {
368 time_t ti;
369 char *p;
370
371 ti = time(NULL);
372 p = ctime(&ti);
373 strcpy(buf2, p);
374 p = buf2 + strlen(p) - 1;
375 if (*p == '\n')
376 *p = '\0';
377 return buf2;
378 }
379
380 static void http_vlog(const char *fmt, va_list vargs)
381 {
382 static int print_prefix = 1;
383 if (logfile) {
384 if (print_prefix) {
385 char buf[32];
386 ctime1(buf);
387 fprintf(logfile, "%s ", buf);
388 }
389 print_prefix = strstr(fmt, "\n") != NULL;
390 vfprintf(logfile, fmt, vargs);
391 fflush(logfile);
392 }
393 }
394
395 #ifdef __GNUC__
396 __attribute__ ((format (printf, 1, 2)))
397 #endif
398 static void http_log(const char *fmt, ...)
399 {
400 va_list vargs;
401 va_start(vargs, fmt);
402 http_vlog(fmt, vargs);
403 va_end(vargs);
404 }
405
406 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
407 {
408 static int print_prefix = 1;
409 AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
410 if (level > av_log_get_level())
411 return;
412 if (print_prefix && avc)
413 http_log("[%s @ %p]", avc->item_name(ptr), ptr);
414 print_prefix = strstr(fmt, "\n") != NULL;
415 http_vlog(fmt, vargs);
416 }
417
418 static void log_connection(HTTPContext *c)
419 {
420 if (c->suppress_log)
421 return;
422
423 http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
424 inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
425 c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
426 }
427
428 static void update_datarate(DataRateData *drd, int64_t count)
429 {
430 if (!drd->time1 && !drd->count1) {
431 drd->time1 = drd->time2 = cur_time;
432 drd->count1 = drd->count2 = count;
433 } else if (cur_time - drd->time2 > 5000) {
434 drd->time1 = drd->time2;
435 drd->count1 = drd->count2;
436 drd->time2 = cur_time;
437 drd->count2 = count;
438 }
439 }
440
441 /* In bytes per second */
442 static int compute_datarate(DataRateData *drd, int64_t count)
443 {
444 if (cur_time == drd->time1)
445 return 0;
446
447 return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
448 }
449
450
451 static void start_children(FFStream *feed)
452 {
453 if (no_launch)
454 return;
455
456 for (; feed; feed = feed->next) {
457 if (feed->child_argv && !feed->pid) {
458 feed->pid_start = time(0);
459
460 feed->pid = fork();
461
462 if (feed->pid < 0) {
463 http_log("Unable to create children\n");
464 exit(1);
465 }
466 if (!feed->pid) {
467 /* In child */
468 char pathname[1024];
469 char *slash;
470 int i;
471
472 av_strlcpy(pathname, my_program_name, sizeof(pathname));
473
474 slash = strrchr(pathname, '/');
475 if (!slash)
476 slash = pathname;
477 else
478 slash++;
479 strcpy(slash, "avconv");
480
481 http_log("Launch command line: ");
482 http_log("%s ", pathname);
483 for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
484 http_log("%s ", feed->child_argv[i]);
485 http_log("\n");
486
487 for (i = 3; i < 256; i++)
488 close(i);
489
490 if (!avserver_debug) {
491 i = open("/dev/null", O_RDWR);
492 if (i != -1) {
493 dup2(i, 0);
494 dup2(i, 1);
495 dup2(i, 2);
496 close(i);
497 }
498 }
499
500 /* This is needed to make relative pathnames work */
501 chdir(my_program_dir);
502
503 signal(SIGPIPE, SIG_DFL);
504
505 execvp(pathname, feed->child_argv);
506
507 _exit(1);
508 }
509 }
510 }
511 }
512
513 /* open a listening socket */
514 static int socket_open_listen(struct sockaddr_in *my_addr)
515 {
516 int server_fd, tmp;
517
518 server_fd = socket(AF_INET,SOCK_STREAM,0);
519 if (server_fd < 0) {
520 perror ("socket");
521 return -1;
522 }
523
524 tmp = 1;
525 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
526
527 my_addr->sin_family = AF_INET;
528 if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
529 char bindmsg[32];
530 snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
531 perror (bindmsg);
532 closesocket(server_fd);
533 return -1;
534 }
535
536 if (listen (server_fd, 5) < 0) {
537 perror ("listen");
538 closesocket(server_fd);
539 return -1;
540 }
541 ff_socket_nonblock(server_fd, 1);
542
543 return server_fd;
544 }
545
546 /* start all multicast streams */
547 static void start_multicast(void)
548 {
549 FFStream *stream;
550 char session_id[32];
551 HTTPContext *rtp_c;
552 struct sockaddr_in dest_addr;
553 int default_port, stream_index;
554
555 default_port = 6000;
556 for(stream = first_stream; stream != NULL; stream = stream->next) {
557 if (stream->is_multicast) {
558 /* open the RTP connection */
559 snprintf(session_id, sizeof(session_id), "%08x%08x",
560 av_lfg_get(&random_state), av_lfg_get(&random_state));
561
562 /* choose a port if none given */
563 if (stream->multicast_port == 0) {
564 stream->multicast_port = default_port;
565 default_port += 100;
566 }
567
568 dest_addr.sin_family = AF_INET;
569 dest_addr.sin_addr = stream->multicast_ip;
570 dest_addr.sin_port = htons(stream->multicast_port);
571
572 rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
573 RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
574 if (!rtp_c)
575 continue;
576
577 if (open_input_stream(rtp_c, "") < 0) {
578 http_log("Could not open input stream for stream '%s'\n",
579 stream->filename);
580 continue;
581 }
582
583 /* open each RTP stream */
584 for(stream_index = 0; stream_index < stream->nb_streams;
585 stream_index++) {
586 dest_addr.sin_port = htons(stream->multicast_port +
587 2 * stream_index);
588 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
589 http_log("Could not open output stream '%s/streamid=%d'\n",
590 stream->filename, stream_index);
591 exit(1);
592 }
593 }
594
595 /* change state to send data */
596 rtp_c->state = HTTPSTATE_SEND_DATA;
597 }
598 }
599 }
600
601 /* main loop of the http server */
602 static int http_server(void)
603 {
604 int server_fd = 0, rtsp_server_fd = 0;
605 int ret, delay, delay1;
606 struct pollfd *poll_table, *poll_entry;
607 HTTPContext *c, *c_next;
608
609 if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
610 http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
611 return -1;
612 }
613
614 if (my_http_addr.sin_port) {
615 server_fd = socket_open_listen(&my_http_addr);
616 if (server_fd < 0)
617 return -1;
618 }
619
620 if (my_rtsp_addr.sin_port) {
621 rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
622 if (rtsp_server_fd < 0)
623 return -1;
624 }
625
626 if (!rtsp_server_fd && !server_fd) {
627 http_log("HTTP and RTSP disabled.\n");
628 return -1;
629 }
630
631 http_log("AVserver started.\n");
632
633 start_children(first_feed);
634
635 start_multicast();
636
637 for(;;) {
638 poll_entry = poll_table;
639 if (server_fd) {
640 poll_entry->fd = server_fd;
641 poll_entry->events = POLLIN;
642 poll_entry++;
643 }
644 if (rtsp_server_fd) {
645 poll_entry->fd = rtsp_server_fd;
646 poll_entry->events = POLLIN;
647 poll_entry++;
648 }
649
650 /* wait for events on each HTTP handle */
651 c = first_http_ctx;
652 delay = 1000;
653 while (c != NULL) {
654 int fd;
655 fd = c->fd;
656 switch(c->state) {
657 case HTTPSTATE_SEND_HEADER:
658 case RTSPSTATE_SEND_REPLY:
659 case RTSPSTATE_SEND_PACKET:
660 c->poll_entry = poll_entry;
661 poll_entry->fd = fd;
662 poll_entry->events = POLLOUT;
663 poll_entry++;
664 break;
665 case HTTPSTATE_SEND_DATA_HEADER:
666 case HTTPSTATE_SEND_DATA:
667 case HTTPSTATE_SEND_DATA_TRAILER:
668 if (!c->is_packetized) {
669 /* for TCP, we output as much as we can (may need to put a limit) */
670 c->poll_entry = poll_entry;
671 poll_entry->fd = fd;
672 poll_entry->events = POLLOUT;
673 poll_entry++;
674 } else {
675 /* when avserver is doing the timing, we work by
676 looking at which packet need to be sent every
677 10 ms */
678 delay1 = 10; /* one tick wait XXX: 10 ms assumed */
679 if (delay1 < delay)
680 delay = delay1;
681 }
682 break;
683 case HTTPSTATE_WAIT_REQUEST:
684 case HTTPSTATE_RECEIVE_DATA:
685 case HTTPSTATE_WAIT_FEED:
686 case RTSPSTATE_WAIT_REQUEST:
687 /* need to catch errors */
688 c->poll_entry = poll_entry;
689 poll_entry->fd = fd;
690 poll_entry->events = POLLIN;/* Maybe this will work */
691 poll_entry++;
692 break;
693 default:
694 c->poll_entry = NULL;
695 break;
696 }
697 c = c->next;
698 }
699
700 /* wait for an event on one connection. We poll at least every
701 second to handle timeouts */
702 do {
703 ret = poll(poll_table, poll_entry - poll_table, delay);
704 if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
705 ff_neterrno() != AVERROR(EINTR))
706 return -1;
707 } while (ret < 0);
708
709 cur_time = av_gettime() / 1000;
710
711 if (need_to_start_children) {
712 need_to_start_children = 0;
713 start_children(first_feed);
714 }
715
716 /* now handle the events */
717 for(c = first_http_ctx; c != NULL; c = c_next) {
718 c_next = c->next;
719 if (handle_connection(c) < 0) {
720 /* close and free the connection */
721 log_connection(c);
722 close_connection(c);
723 }
724 }
725
726 poll_entry = poll_table;
727 if (server_fd) {
728 /* new HTTP connection request ? */
729 if (poll_entry->revents & POLLIN)
730 new_connection(server_fd, 0);
731 poll_entry++;
732 }
733 if (rtsp_server_fd) {
734 /* new RTSP connection request ? */
735 if (poll_entry->revents & POLLIN)
736 new_connection(rtsp_server_fd, 1);
737 }
738 }
739 }
740
741 /* start waiting for a new HTTP/RTSP request */
742 static void start_wait_request(HTTPContext *c, int is_rtsp)
743 {
744 c->buffer_ptr = c->buffer;
745 c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
746
747 if (is_rtsp) {
748 c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
749 c->state = RTSPSTATE_WAIT_REQUEST;
750 } else {
751 c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
752 c->state = HTTPSTATE_WAIT_REQUEST;
753 }
754 }
755
756 static void http_send_too_busy_reply(int fd)
757 {
758 char buffer[300];
759 int len = snprintf(buffer, sizeof(buffer),
760 "HTTP/1.0 503 Server too busy\r\n"
761 "Content-type: text/html\r\n"
762 "\r\n"
763 "<html><head><title>Too busy</title></head><body>\r\n"
764 "<p>The server is too busy to serve your request at this time.</p>\r\n"
765 "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
766 "</body></html>\r\n",
767 nb_connections, nb_max_connections);
768 send(fd, buffer, len, 0);
769 }
770
771
772 static void new_connection(int server_fd, int is_rtsp)
773 {
774 struct sockaddr_in from_addr;
775 int fd, len;
776 HTTPContext *c = NULL;
777
778 len = sizeof(from_addr);
779 fd = accept(server_fd, (struct sockaddr *)&from_addr,
780 &len);
781 if (fd < 0) {
782 http_log("error during accept %s\n", strerror(errno));
783 return;
784 }
785 ff_socket_nonblock(fd, 1);
786
787 if (nb_connections >= nb_max_connections) {
788 http_send_too_busy_reply(fd);
789 goto fail;
790 }
791
792 /* add a new connection */
793 c = av_mallocz(sizeof(HTTPContext));
794 if (!c)
795 goto fail;
796
797 c->fd = fd;
798 c->poll_entry = NULL;
799 c->from_addr = from_addr;
800 c->buffer_size = IOBUFFER_INIT_SIZE;
801 c->buffer = av_malloc(c->buffer_size);
802 if (!c->buffer)
803 goto fail;
804
805 c->next = first_http_ctx;
806 first_http_ctx = c;
807 nb_connections++;
808
809 start_wait_request(c, is_rtsp);
810
811 return;
812
813 fail:
814 if (c) {
815 av_free(c->buffer);
816 av_free(c);
817 }
818 closesocket(fd);
819 }
820
821 static void close_connection(HTTPContext *c)
822 {
823 HTTPContext **cp, *c1;
824 int i, nb_streams;
825 AVFormatContext *ctx;
826 URLContext *h;
827 AVStream *st;
828
829 /* remove connection from list */
830 cp = &first_http_ctx;
831 while ((*cp) != NULL) {
832 c1 = *cp;
833 if (c1 == c)
834 *cp = c->next;
835 else
836 cp = &c1->next;
837 }
838
839 /* remove references, if any (XXX: do it faster) */
840 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
841 if (c1->rtsp_c == c)
842 c1->rtsp_c = NULL;
843 }
844
845 /* remove connection associated resources */
846 if (c->fd >= 0)
847 closesocket(c->fd);
848 if (c->fmt_in) {
849 /* close each frame parser */
850 for(i=0;i<c->fmt_in->nb_streams;i++) {
851 st = c->fmt_in->streams[i];
852 if (st->codec->codec)
853 avcodec_close(st->codec);
854 }
855 avformat_close_input(&c->fmt_in);
856 }
857
858 /* free RTP output streams if any */
859 nb_streams = 0;
860 if (c->stream)
861 nb_streams = c->stream->nb_streams;
862
863 for(i=0;i<nb_streams;i++) {
864 ctx = c->rtp_ctx[i];
865 if (ctx) {
866 av_write_trailer(ctx);
867 av_dict_free(&ctx->metadata);
868 av_free(ctx->streams[0]);
869 av_free(ctx);
870 }
871 h = c->rtp_handles[i];
872 if (h)
873 ffurl_close(h);
874 }
875
876 ctx = &c->fmt_ctx;
877
878 if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
879 if (ctx->oformat) {
880 /* prepare header */
881 if (avio_open_dyn_buf(&ctx->pb) >= 0) {
882 av_write_trailer(ctx);
883 av_freep(&c->pb_buffer);
884 avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
885 }
886 }
887 }
888
889 for(i=0; i<ctx->nb_streams; i++)
890 av_free(ctx->streams[i]);
891
892 if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
893 current_bandwidth -= c->stream->bandwidth;
894
895 /* signal that there is no feed if we are the feeder socket */
896 if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
897 c->stream->feed_opened = 0;
898 close(c->feed_fd);
899 }
900
901 av_freep(&c->pb_buffer);
902 av_freep(&c->packet_buffer);
903 av_free(c->buffer);
904 av_free(c);
905 nb_connections--;
906 }
907
908 static int handle_connection(HTTPContext *c)
909 {
910 int len, ret;
911
912 switch(c->state) {
913 case HTTPSTATE_WAIT_REQUEST:
914 case RTSPSTATE_WAIT_REQUEST:
915 /* timeout ? */
916 if ((c->timeout - cur_time) < 0)
917 return -1;
918 if (c->poll_entry->revents & (POLLERR | POLLHUP))
919 return -1;
920
921 /* no need to read if no events */
922 if (!(c->poll_entry->revents & POLLIN))
923 return 0;
924 /* read the data */
925 read_loop:
926 len = recv(c->fd, c->buffer_ptr, 1, 0);
927 if (len < 0) {
928 if (ff_neterrno() != AVERROR(EAGAIN) &&
929 ff_neterrno() != AVERROR(EINTR))
930 return -1;
931 } else if (len == 0) {
932 return -1;
933 } else {
934 /* search for end of request. */
935 uint8_t *ptr;
936 c->buffer_ptr += len;
937 ptr = c->buffer_ptr;
938 if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
939 (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
940 /* request found : parse it and reply */
941 if (c->state == HTTPSTATE_WAIT_REQUEST) {
942 ret = http_parse_request(c);
943 } else {
944 ret = rtsp_parse_request(c);
945 }
946 if (ret < 0)
947 return -1;
948 } else if (ptr >= c->buffer_end) {
949 /* request too long: cannot do anything */
950 return -1;
951 } else goto read_loop;
952 }
953 break;
954
955 case HTTPSTATE_SEND_HEADER:
956 if (c->poll_entry->revents & (POLLERR | POLLHUP))
957 return -1;
958
959 /* no need to write if no events */
960 if (!(c->poll_entry->revents & POLLOUT))
961 return 0;
962 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
963 if (len < 0) {
964 if (ff_neterrno() != AVERROR(EAGAIN) &&
965 ff_neterrno() != AVERROR(EINTR)) {
966 /* error : close connection */
967 av_freep(&c->pb_buffer);
968 return -1;
969 }
970 } else {
971 c->buffer_ptr += len;
972 if (c->stream)
973 c->stream->bytes_served += len;
974 c->data_count += len;
975 if (c->buffer_ptr >= c->buffer_end) {
976 av_freep(&c->pb_buffer);
977 /* if error, exit */
978 if (c->http_error)
979 return -1;
980 /* all the buffer was sent : synchronize to the incoming stream */
981 c->state = HTTPSTATE_SEND_DATA_HEADER;
982 c->buffer_ptr = c->buffer_end = c->buffer;
983 }
984 }
985 break;
986
987 case HTTPSTATE_SEND_DATA:
988 case HTTPSTATE_SEND_DATA_HEADER:
989 case HTTPSTATE_SEND_DATA_TRAILER:
990 /* for packetized output, we consider we can always write (the
991 input streams sets the speed). It may be better to verify
992 that we do not rely too much on the kernel queues */
993 if (!c->is_packetized) {
994 if (c->poll_entry->revents & (POLLERR | POLLHUP))
995 return -1;
996
997 /* no need to read if no events */
998 if (!(c->poll_entry->revents & POLLOUT))
999 return 0;
1000 }
1001 if (http_send_data(c) < 0)
1002 return -1;
1003 /* close connection if trailer sent */
1004 if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
1005 return -1;
1006 break;
1007 case HTTPSTATE_RECEIVE_DATA:
1008 /* no need to read if no events */
1009 if (c->poll_entry->revents & (POLLERR | POLLHUP))
1010 return -1;
1011 if (!(c->poll_entry->revents & POLLIN))
1012 return 0;
1013 if (http_receive_data(c) < 0)
1014 return -1;
1015 break;
1016 case HTTPSTATE_WAIT_FEED:
1017 /* no need to read if no events */
1018 if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1019 return -1;
1020
1021 /* nothing to do, we'll be waken up by incoming feed packets */
1022 break;
1023
1024 case RTSPSTATE_SEND_REPLY:
1025 if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1026 av_freep(&c->pb_buffer);
1027 return -1;
1028 }
1029 /* no need to write if no events */
1030 if (!(c->poll_entry->revents & POLLOUT))
1031 return 0;
1032 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1033 if (len < 0) {
1034 if (ff_neterrno() != AVERROR(EAGAIN) &&
1035 ff_neterrno() != AVERROR(EINTR)) {
1036 /* error : close connection */
1037 av_freep(&c->pb_buffer);
1038 return -1;
1039 }
1040 } else {
1041 c->buffer_ptr += len;
1042 c->data_count += len;
1043 if (c->buffer_ptr >= c->buffer_end) {
1044 /* all the buffer was sent : wait for a new request */
1045 av_freep(&c->pb_buffer);
1046 start_wait_request(c, 1);
1047 }
1048 }
1049 break;
1050 case RTSPSTATE_SEND_PACKET:
1051 if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1052 av_freep(&c->packet_buffer);
1053 return -1;
1054 }
1055 /* no need to write if no events */
1056 if (!(c->poll_entry->revents & POLLOUT))
1057 return 0;
1058 len = send(c->fd, c->packet_buffer_ptr,
1059 c->packet_buffer_end - c->packet_buffer_ptr, 0);
1060 if (len < 0) {
1061 if (ff_neterrno() != AVERROR(EAGAIN) &&
1062 ff_neterrno() != AVERROR(EINTR)) {
1063 /* error : close connection */
1064 av_freep(&c->packet_buffer);
1065 return -1;
1066 }
1067 } else {
1068 c->packet_buffer_ptr += len;
1069 if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1070 /* all the buffer was sent : wait for a new request */
1071 av_freep(&c->packet_buffer);
1072 c->state = RTSPSTATE_WAIT_REQUEST;
1073 }
1074 }
1075 break;
1076 case HTTPSTATE_READY:
1077 /* nothing to do */
1078 break;
1079 default:
1080 return -1;
1081 }
1082 return 0;
1083 }
1084
1085 static int extract_rates(char *rates, int ratelen, const char *request)
1086 {
1087 const char *p;
1088
1089 for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1090 if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1091 const char *q = p + 7;
1092
1093 while (*q && *q != '\n' && isspace(*q))
1094 q++;
1095
1096 if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1097 int stream_no;
1098 int rate_no;
1099
1100 q += 20;
1101
1102 memset(rates, 0xff, ratelen);
1103
1104 while (1) {
1105 while (*q && *q != '\n' && *q != ':')
1106 q++;
1107
1108 if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1109 break;
1110
1111 stream_no--;
1112 if (stream_no < ratelen && stream_no >= 0)
1113 rates[stream_no] = rate_no;
1114
1115 while (*q && *q != '\n' && !isspace(*q))
1116 q++;
1117 }
1118
1119 return 1;
1120 }
1121 }
1122 p = strchr(p, '\n');
1123 if (!p)
1124 break;
1125
1126 p++;
1127 }
1128
1129 return 0;
1130 }
1131
1132 static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1133 {
1134 int i;
1135 int best_bitrate = 100000000;
1136 int best = -1;
1137
1138 for (i = 0; i < feed->nb_streams; i++) {
1139 AVCodecContext *feed_codec = feed->streams[i]->codec;
1140
1141 if (feed_codec->codec_id != codec->codec_id ||
1142 feed_codec->sample_rate != codec->sample_rate ||
1143 feed_codec->width != codec->width ||
1144 feed_codec->height != codec->height)
1145 continue;
1146
1147 /* Potential stream */
1148
1149 /* We want the fastest stream less than bit_rate, or the slowest
1150 * faster than bit_rate
1151 */
1152
1153 if (feed_codec->bit_rate <= bit_rate) {
1154 if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1155 best_bitrate = feed_codec->bit_rate;
1156 best = i;
1157 }
1158 } else {
1159 if (feed_codec->bit_rate < best_bitrate) {
1160 best_bitrate = feed_codec->bit_rate;
1161 best = i;
1162 }
1163 }
1164 }
1165
1166 return best;
1167 }
1168
1169 static int modify_current_stream(HTTPContext *c, char *rates)
1170 {
1171 int i;
1172 FFStream *req = c->stream;
1173 int action_required = 0;
1174
1175 /* Not much we can do for a feed */
1176 if (!req->feed)
1177 return 0;
1178
1179 for (i = 0; i < req->nb_streams; i++) {
1180 AVCodecContext *codec = req->streams[i]->codec;
1181
1182 switch(rates[i]) {
1183 case 0:
1184 c->switch_feed_streams[i] = req->feed_streams[i];
1185 break;
1186 case 1:
1187 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1188 break;
1189 case 2:
1190 /* Wants off or slow */
1191 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1192 #ifdef WANTS_OFF
1193 /* This doesn't work well when it turns off the only stream! */
1194 c->switch_feed_streams[i] = -2;
1195 c->feed_streams[i] = -2;
1196 #endif
1197 break;
1198 }
1199
1200 if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1201 action_required = 1;
1202 }
1203
1204 return action_required;
1205 }
1206
1207 /* XXX: factorize in utils.c ? */
1208 /* XXX: take care with different space meaning */
1209 static void skip_spaces(const char **pp)
1210 {
1211 const char *p;
1212 p = *pp;
1213 while (*p == ' ' || *p == '\t')
1214 p++;
1215 *pp = p;
1216 }
1217
1218 static void get_word(char *buf, int buf_size, const char **pp)
1219 {
1220 const char *p;
1221 char *q;
1222
1223 p = *pp;
1224 skip_spaces(&p);
1225 q = buf;
1226 while (!isspace(*p) && *p != '\0') {
1227 if ((q - buf) < buf_size - 1)
1228 *q++ = *p;
1229 p++;
1230 }
1231 if (buf_size > 0)
1232 *q = '\0';
1233 *pp = p;
1234 }
1235
1236 static void get_arg(char *buf, int buf_size, const char **pp)
1237 {
1238 const char *p;
1239 char *q;
1240 int quote;
1241
1242 p = *pp;
1243 while (isspace(*p)) p++;
1244 q = buf;
1245 quote = 0;
1246 if (*p == '\"' || *p == '\'')
1247 quote = *p++;
1248 for(;;) {
1249 if (quote) {
1250 if (*p == quote)
1251 break;
1252 } else {
1253 if (isspace(*p))
1254 break;
1255 }
1256 if (*p == '\0')
1257 break;
1258 if ((q - buf) < buf_size - 1)
1259 *q++ = *p;
1260 p++;
1261 }
1262 *q = '\0';
1263 if (quote && *p == quote)
1264 p++;
1265 *pp = p;
1266 }
1267
1268 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1269 const char *p, const char *filename, int line_num)
1270 {
1271 char arg[1024];
1272 IPAddressACL acl;
1273 int errors = 0;
1274
1275 get_arg(arg, sizeof(arg), &p);
1276 if (av_strcasecmp(arg, "allow") == 0)
1277 acl.action = IP_ALLOW;
1278 else if (av_strcasecmp(arg, "deny") == 0)
1279 acl.action = IP_DENY;
1280 else {
1281 fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1282 filename, line_num, arg);
1283 errors++;
1284 }
1285
1286 get_arg(arg, sizeof(arg), &p);
1287
1288 if (resolve_host(&acl.first, arg) != 0) {
1289 fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1290 filename, line_num, arg);
1291 errors++;
1292 } else
1293 acl.last = acl.first;
1294
1295 get_arg(arg, sizeof(arg), &p);
1296
1297 if (arg[0]) {
1298 if (resolve_host(&acl.last, arg) != 0) {
1299 fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1300 filename, line_num, arg);
1301 errors++;
1302 }
1303 }
1304
1305 if (!errors) {
1306 IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1307 IPAddressACL **naclp = 0;
1308
1309 acl.next = 0;
1310 *nacl = acl;
1311
1312 if (stream)
1313 naclp = &stream->acl;
1314 else if (feed)
1315 naclp = &feed->acl;
1316 else if (ext_acl)
1317 naclp = &ext_acl;
1318 else {
1319 fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1320 filename, line_num);
1321 errors++;
1322 }
1323
1324 if (naclp) {
1325 while (*naclp)
1326 naclp = &(*naclp)->next;
1327
1328 *naclp = nacl;
1329 }
1330 }
1331 }
1332
1333
1334 static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
1335 {
1336 FILE* f;
1337 char line[1024];
1338 char cmd[1024];
1339 IPAddressACL *acl = NULL;
1340 int line_num = 0;
1341 const char *p;
1342
1343 f = fopen(stream->dynamic_acl, "r");
1344 if (!f) {
1345 perror(stream->dynamic_acl);
1346 return NULL;
1347 }
1348
1349 acl = av_mallocz(sizeof(IPAddressACL));
1350
1351 /* Build ACL */
1352 for(;;) {
1353 if (fgets(line, sizeof(line), f) == NULL)
1354 break;
1355 line_num++;
1356 p = line;
1357 while (isspace(*p))
1358 p++;
1359 if (*p == '\0' || *p == '#')
1360 continue;
1361 get_arg(cmd, sizeof(cmd), &p);
1362
1363 if (!av_strcasecmp(cmd, "ACL"))
1364 parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1365 }
1366 fclose(f);
1367 return acl;
1368 }
1369
1370
1371 static void free_acl_list(IPAddressACL *in_acl)
1372 {
1373 IPAddressACL *pacl,*pacl2;
1374
1375 pacl = in_acl;
1376 while(pacl) {
1377 pacl2 = pacl;
1378 pacl = pacl->next;
1379 av_freep(pacl2);
1380 }
1381 }
1382
1383 static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
1384 {
1385 enum IPAddressAction last_action = IP_DENY;
1386 IPAddressACL *acl;
1387 struct in_addr *src = &c->from_addr.sin_addr;
1388 unsigned long src_addr = src->s_addr;
1389
1390 for (acl = in_acl; acl; acl = acl->next) {
1391 if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1392 return (acl->action == IP_ALLOW) ? 1 : 0;
1393 last_action = acl->action;
1394 }
1395
1396 /* Nothing matched, so return not the last action */
1397 return (last_action == IP_DENY) ? 1 : 0;
1398 }
1399
1400 static int validate_acl(FFStream *stream, HTTPContext *c)
1401 {
1402 int ret = 0;
1403 IPAddressACL *acl;
1404
1405
1406 /* if stream->acl is null validate_acl_list will return 1 */
1407 ret = validate_acl_list(stream->acl, c);
1408
1409 if (stream->dynamic_acl[0]) {
1410 acl = parse_dynamic_acl(stream, c);
1411
1412 ret = validate_acl_list(acl, c);
1413
1414 free_acl_list(acl);
1415 }
1416
1417 return ret;
1418 }
1419
1420 /* compute the real filename of a file by matching it without its
1421 extensions to all the stream filenames */
1422 static void compute_real_filename(char *filename, int max_size)
1423 {
1424 char file1[1024];
1425 char file2[1024];
1426 char *p;
1427 FFStream *stream;
1428
1429 /* compute filename by matching without the file extensions */
1430 av_strlcpy(file1, filename, sizeof(file1));
1431 p = strrchr(file1, '.');
1432 if (p)
1433 *p = '\0';
1434 for(stream = first_stream; stream != NULL; stream = stream->next) {
1435 av_strlcpy(file2, stream->filename, sizeof(file2));
1436 p = strrchr(file2, '.');
1437 if (p)
1438 *p = '\0';
1439 if (!strcmp(file1, file2)) {
1440 av_strlcpy(filename, stream->filename, max_size);
1441 break;
1442 }
1443 }
1444 }
1445
1446 enum RedirType {
1447 REDIR_NONE,
1448 REDIR_ASX,
1449 REDIR_RAM,
1450 REDIR_ASF,
1451 REDIR_RTSP,
1452 REDIR_SDP,
1453 };
1454
1455 /* parse http request and prepare header */
1456 static int http_parse_request(HTTPContext *c)
1457 {
1458 char *p;
1459 enum RedirType redir_type;
1460 char cmd[32];
1461 char info[1024], filename[1024];
1462 char url[1024], *q;
1463 char protocol[32];
1464 char msg[1024];
1465 const char *mime_type;
1466 FFStream *stream;
1467 int i;
1468 char ratebuf[32];
1469 char *useragent = 0;
1470
1471 p = c->buffer;
1472 get_word(cmd, sizeof(cmd), (const char **)&p);
1473 av_strlcpy(c->method, cmd, sizeof(c->method));
1474
1475 if (!strcmp(cmd, "GET"))
1476 c->post = 0;
1477 else if (!strcmp(cmd, "POST"))
1478 c->post = 1;
1479 else
1480 return -1;
1481
1482 get_word(url, sizeof(url), (const char **)&p);
1483 av_strlcpy(c->url, url, sizeof(c->url));
1484
1485 get_word(protocol, sizeof(protocol), (const char **)&p);
1486 if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1487 return -1;
1488
1489 av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1490
1491 if (avserver_debug)
1492 http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1493
1494 /* find the filename and the optional info string in the request */
1495 p = strchr(url, '?');
1496 if (p) {
1497 av_strlcpy(info, p, sizeof(info));
1498 *p = '\0';
1499 } else
1500 info[0] = '\0';
1501
1502 av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1503
1504 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1505 if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1506 useragent = p + 11;
1507 if (*useragent && *useragent != '\n' && isspace(*useragent))
1508 useragent++;
1509 break;
1510 }
1511 p = strchr(p, '\n');
1512 if (!p)
1513 break;
1514
1515 p++;
1516 }
1517
1518 redir_type = REDIR_NONE;
1519 if (av_match_ext(filename, "asx")) {
1520 redir_type = REDIR_ASX;
1521 filename[strlen(filename)-1] = 'f';
1522 } else if (av_match_ext(filename, "asf") &&
1523 (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1524 /* if this isn't WMP or lookalike, return the redirector file */
1525 redir_type = REDIR_ASF;
1526 } else if (av_match_ext(filename, "rpm,ram")) {
1527 redir_type = REDIR_RAM;
1528 strcpy(filename + strlen(filename)-2, "m");
1529 } else if (av_match_ext(filename, "rtsp")) {
1530 redir_type = REDIR_RTSP;
1531 compute_real_filename(filename, sizeof(filename) - 1);
1532 } else if (av_match_ext(filename, "sdp")) {
1533 redir_type = REDIR_SDP;
1534 compute_real_filename(filename, sizeof(filename) - 1);
1535 }
1536
1537 // "redirect" / request to index.html
1538 if (!strlen(filename))
1539 av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1540
1541 stream = first_stream;
1542 while (stream != NULL) {
1543 if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1544 break;
1545 stream = stream->next;
1546 }
1547 if (stream == NULL) {
1548 snprintf(msg, sizeof(msg), "File '%s' not found", url);
1549 http_log("File '%s' not found\n", url);
1550 goto send_error;
1551 }
1552
1553 c->stream = stream;
1554 memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1555 memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1556
1557 if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1558 c->http_error = 301;
1559 q = c->buffer;
1560 q += snprintf(q, c->buffer_size,
1561 "HTTP/1.0 301 Moved\r\n"
1562 "Location: %s\r\n"
1563 "Content-type: text/html\r\n"
1564 "\r\n"
1565 "<html><head><title>Moved</title></head><body>\r\n"
1566 "You should be <a href=\"%s\">redirected</a>.\r\n"
1567 "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1568 /* prepare output buffer */
1569 c->buffer_ptr = c->buffer;
1570 c->buffer_end = q;
1571 c->state = HTTPSTATE_SEND_HEADER;
1572 return 0;
1573 }
1574
1575 /* If this is WMP, get the rate information */
1576 if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1577 if (modify_current_stream(c, ratebuf)) {
1578 for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1579 if (c->switch_feed_streams[i] >= 0)
1580 c->switch_feed_streams[i] = -1;
1581 }
1582 }
1583 }
1584
1585 if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1586 current_bandwidth += stream->bandwidth;
1587
1588 /* If already streaming this feed, do not let start another feeder. */
1589 if (stream->feed_opened) {
1590 snprintf(msg, sizeof(msg), "This feed is already being received.");
1591 http_log("Feed '%s' already being received\n", stream->feed_filename);
1592 goto send_error;
1593 }
1594
1595 if (c->post == 0 && max_bandwidth < current_bandwidth) {
1596 c->http_error = 503;
1597 q = c->buffer;
1598 q += snprintf(q, c->buffer_size,
1599 "HTTP/1.0 503 Server too busy\r\n"
1600 "Content-type: text/html\r\n"
1601 "\r\n"
1602 "<html><head><title>Too busy</title></head><body>\r\n"
1603 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1604 "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1605 "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1606 "</body></html>\r\n", current_bandwidth, max_bandwidth);
1607 /* prepare output buffer */
1608 c->buffer_ptr = c->buffer;
1609 c->buffer_end = q;
1610 c->state = HTTPSTATE_SEND_HEADER;
1611 return 0;
1612 }
1613
1614 if (redir_type != REDIR_NONE) {
1615 char *hostinfo = 0;
1616
1617 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1618 if (av_strncasecmp(p, "Host:", 5) == 0) {
1619 hostinfo = p + 5;
1620 break;
1621 }
1622 p = strchr(p, '\n');
1623 if (!p)
1624 break;
1625
1626 p++;
1627 }
1628
1629 if (hostinfo) {
1630 char *eoh;
1631 char hostbuf[260];
1632
1633 while (isspace(*hostinfo))
1634 hostinfo++;
1635
1636 eoh = strchr(hostinfo, '\n');
1637 if (eoh) {
1638 if (eoh[-1] == '\r')
1639 eoh--;
1640
1641 if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1642 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1643 hostbuf[eoh - hostinfo] = 0;
1644
1645 c->http_error = 200;
1646 q = c->buffer;
1647 switch(redir_type) {
1648 case REDIR_ASX:
1649 q += snprintf(q, c->buffer_size,
1650 "HTTP/1.0 200 ASX Follows\r\n"
1651 "Content-type: video/x-ms-asf\r\n"
1652 "\r\n"
1653 "<ASX Version=\"3\">\r\n"
1654 //"<!-- Autogenerated by avserver -->\r\n"
1655 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1656 "</ASX>\r\n", hostbuf, filename, info);
1657 break;
1658 case REDIR_RAM:
1659 q += snprintf(q, c->buffer_size,
1660 "HTTP/1.0 200 RAM Follows\r\n"
1661 "Content-type: audio/x-pn-realaudio\r\n"
1662 "\r\n"
1663 "# Autogenerated by avserver\r\n"
1664 "http://%s/%s%s\r\n", hostbuf, filename, info);
1665 break;
1666 case REDIR_ASF:
1667 q += snprintf(q, c->buffer_size,
1668 "HTTP/1.0 200 ASF Redirect follows\r\n"
1669 "Content-type: video/x-ms-asf\r\n"
1670 "\r\n"
1671 "[Reference]\r\n"
1672 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1673 break;
1674 case REDIR_RTSP:
1675 {
1676 char hostname[256], *p;
1677 /* extract only hostname */
1678 av_strlcpy(hostname, hostbuf, sizeof(hostname));
1679 p = strrchr(hostname, ':');
1680 if (p)
1681 *p = '\0';
1682 q += snprintf(q, c->buffer_size,
1683 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1684 /* XXX: incorrect mime type ? */
1685 "Content-type: application/x-rtsp\r\n"
1686 "\r\n"
1687 "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1688 }
1689 break;
1690 case REDIR_SDP:
1691 {
1692 uint8_t *sdp_data;
1693 int sdp_data_size, len;
1694 struct sockaddr_in my_addr;
1695
1696 q += snprintf(q, c->buffer_size,
1697 "HTTP/1.0 200 OK\r\n"
1698 "Content-type: application/sdp\r\n"
1699 "\r\n");
1700
1701 len = sizeof(my_addr);
1702 getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1703
1704 /* XXX: should use a dynamic buffer */
1705 sdp_data_size = prepare_sdp_description(stream,
1706 &sdp_data,
1707 my_addr.sin_addr);
1708 if (sdp_data_size > 0) {
1709 memcpy(q, sdp_data, sdp_data_size);
1710 q += sdp_data_size;
1711 *q = '\0';
1712 av_free(sdp_data);
1713 }
1714 }
1715 break;
1716 default:
1717 abort();
1718 break;
1719 }
1720
1721 /* prepare output buffer */
1722 c->buffer_ptr = c->buffer;
1723 c->buffer_end = q;
1724 c->state = HTTPSTATE_SEND_HEADER;
1725 return 0;
1726 }
1727 }
1728 }
1729
1730 snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1731 goto send_error;
1732 }
1733
1734 stream->conns_served++;
1735
1736 /* XXX: add there authenticate and IP match */
1737
1738 if (c->post) {
1739 /* if post, it means a feed is being sent */
1740 if (!stream->is_feed) {
1741 /* However it might be a status report from WMP! Let us log the
1742 * data as it might come in handy one day. */
1743 char *logline = 0;
1744 int client_id = 0;
1745
1746 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1747 if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1748 logline = p;
1749 break;
1750 }
1751 if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1752 client_id = strtol(p + 18, 0, 10);
1753 p = strchr(p, '\n');
1754 if (!p)
1755 break;
1756
1757 p++;
1758 }
1759
1760 if (logline) {
1761 char *eol = strchr(logline, '\n');
1762
1763 logline += 17;
1764
1765 if (eol) {
1766 if (eol[-1] == '\r')
1767 eol--;
1768 http_log("%.*s\n", (int) (eol - logline), logline);
1769 c->suppress_log = 1;
1770 }
1771 }
1772
1773 #ifdef DEBUG
1774 http_log("\nGot request:\n%s\n", c->buffer);
1775 #endif
1776
1777 if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1778 HTTPContext *wmpc;
1779
1780 /* Now we have to find the client_id */
1781 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1782 if (wmpc->wmp_client_id == client_id)
1783 break;
1784 }
1785
1786 if (wmpc && modify_current_stream(wmpc, ratebuf))
1787 wmpc->switch_pending = 1;
1788 }
1789
1790 snprintf(msg, sizeof(msg), "POST command not handled");
1791 c->stream = 0;
1792 goto send_error;
1793 }
1794 if (http_start_receive_data(c) < 0) {
1795 snprintf(msg, sizeof(msg), "could not open feed");
1796 goto send_error;
1797 }
1798 c->http_error = 0;
1799 c->state = HTTPSTATE_RECEIVE_DATA;
1800 return 0;
1801 }
1802
1803 #ifdef DEBUG
1804 if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1805 http_log("\nGot request:\n%s\n", c->buffer);
1806 #endif
1807
1808 if (c->stream->stream_type == STREAM_TYPE_STATUS)
1809 goto send_status;
1810
1811 /* open input stream */
1812 if (open_input_stream(c, info) < 0) {
1813 snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1814 goto send_error;
1815 }
1816
1817 /* prepare http header */
1818 q = c->buffer;
1819 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1820 mime_type = c->stream->fmt->mime_type;
1821 if (!mime_type)
1822 mime_type = "application/x-octet-stream";
1823 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
1824
1825 /* for asf, we need extra headers */
1826 if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1827 /* Need to allocate a client id */
1828
1829 c->wmp_client_id = av_lfg_get(&random_state);
1830
1831 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);
1832 }
1833 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1834 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1835
1836 /* prepare output buffer */
1837 c->http_error = 0;
1838 c->buffer_ptr = c->buffer;
1839 c->buffer_end = q;
1840 c->state = HTTPSTATE_SEND_HEADER;
1841 return 0;
1842 send_error:
1843 c->http_error = 404;
1844 q = c->buffer;
1845 q += snprintf(q, c->buffer_size,
1846 "HTTP/1.0 404 Not Found\r\n"
1847 "Content-type: text/html\r\n"
1848 "\r\n"
1849 "<html>\n"
1850 "<head><title>404 Not Found</title></head>\n"
1851 "<body>%s</body>\n"
1852 "</html>\n", msg);
1853 /* prepare output buffer */
1854 c->buffer_ptr = c->buffer;
1855 c->buffer_end = q;
1856 c->state = HTTPSTATE_SEND_HEADER;
1857 return 0;
1858 send_status:
1859 compute_status(c);
1860 c->http_error = 200; /* horrible : we use this value to avoid
1861 going to the send data state */
1862 c->state = HTTPSTATE_SEND_HEADER;
1863 return 0;
1864 }
1865
1866 static void fmt_bytecount(AVIOContext *pb, int64_t count)
1867 {
1868 static const char *suffix = " kMGTP";
1869 const char *s;
1870
1871 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1872
1873 avio_printf(pb, "%"PRId64"%c", count, *s);
1874 }
1875
1876 static void compute_status(HTTPContext *c)
1877 {
1878 HTTPContext *c1;
1879 FFStream *stream;
1880 char *p;
1881 time_t ti;
1882 int i, len;
1883 AVIOContext *pb;
1884
1885 if (avio_open_dyn_buf(&pb) < 0) {
1886 /* XXX: return an error ? */
1887 c->buffer_ptr = c->buffer;
1888 c->buffer_end = c->buffer;
1889 return;
1890 }
1891
1892 avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1893 avio_printf(pb, "Content-type: %s\r\n", "text/html");
1894 avio_printf(pb, "Pragma: no-cache\r\n");
1895 avio_printf(pb, "\r\n");
1896
1897 avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1898 if (c->stream->feed_filename[0])
1899 avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1900 avio_printf(pb, "</head>\n<body>");
1901 avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1902 /* format status */
1903 avio_printf(pb, "<h2>Available Streams</h2>\n");
1904 avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1905 avio_printf(pb, "<tr><th valign=top>Path<th align=left>Served<br>Conns<th><br>bytes<th valign=top>Format<th>Bit rate<br>kbits/s<th align=left>Video<br>kbits/s<th><br>Codec<th align=left>Audio<br>kbits/s<th><br>Codec<th align=left valign=top>Feed\n");
1906 stream = first_stream;
1907 while (stream != NULL) {
1908 char sfilename[1024];
1909 char *eosf;
1910
1911 if (stream->feed != stream) {
1912 av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1913 eosf = sfilename + strlen(sfilename);
1914 if (eosf - sfilename >= 4) {
1915 if (strcmp(eosf - 4, ".asf") == 0)
1916 strcpy(eosf - 4, ".asx");
1917 else if (strcmp(eosf - 3, ".rm") == 0)
1918 strcpy(eosf - 3, ".ram");
1919 else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1920 /* generate a sample RTSP director if
1921 unicast. Generate an SDP redirector if
1922 multicast */
1923 eosf = strrchr(sfilename, '.');
1924 if (!eosf)
1925 eosf = sfilename + strlen(sfilename);
1926 if (stream->is_multicast)
1927 strcpy(eosf, ".sdp");
1928 else
1929 strcpy(eosf, ".rtsp");
1930 }
1931 }
1932
1933 avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1934 sfilename, stream->filename);
1935 avio_printf(pb, "<td align=right> %d <td align=right> ",
1936 stream->conns_served);
1937 fmt_bytecount(pb, stream->bytes_served);
1938 switch(stream->stream_type) {
1939 case STREAM_TYPE_LIVE: {
1940 int audio_bit_rate = 0;
1941 int video_bit_rate = 0;
1942 const char *audio_codec_name = "";
1943 const char *video_codec_name = "";
1944 const char *audio_codec_name_extra = "";
1945 const char *video_codec_name_extra = "";
1946
1947 for(i=0;i<stream->nb_streams;i++) {
1948 AVStream *st = stream->streams[i];
1949 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1950 switch(st->codec->codec_type) {
1951 case AVMEDIA_TYPE_AUDIO:
1952 audio_bit_rate += st->codec->bit_rate;
1953 if (codec) {
1954 if (*audio_codec_name)
1955 audio_codec_name_extra = "...";
1956 audio_codec_name = codec->name;
1957 }
1958 break;
1959 case AVMEDIA_TYPE_VIDEO:
1960 video_bit_rate += st->codec->bit_rate;
1961 if (codec) {
1962 if (*video_codec_name)
1963 video_codec_name_extra = "...";
1964 video_codec_name = codec->name;
1965 }
1966 break;
1967 case AVMEDIA_TYPE_DATA:
1968 video_bit_rate += st->codec->bit_rate;
1969 break;
1970 default:
1971 abort();
1972 }
1973 }
1974 avio_printf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
1975 stream->fmt->name,
1976 stream->bandwidth,
1977 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1978 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
1979 if (stream->feed)
1980 avio_printf(pb, "<td>%s", stream->feed->filename);
1981 else
1982 avio_printf(pb, "<td>%s", stream->feed_filename);
1983 avio_printf(pb, "\n");
1984 }
1985 break;
1986 default:
1987 avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
1988 break;
1989 }
1990 }
1991 stream = stream->next;
1992 }
1993 avio_printf(pb, "</table>\n");
1994
1995 stream = first_stream;
1996 while (stream != NULL) {
1997 if (stream->feed == stream) {
1998 avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
1999 if (stream->pid) {
2000 avio_printf(pb, "Running as pid %d.\n", stream->pid);
2001
2002 #if defined(linux) && !defined(CONFIG_NOCUTILS)
2003 {
2004 FILE *pid_stat;
2005 char ps_cmd[64];
2006
2007 /* This is somewhat linux specific I guess */
2008 snprintf(ps_cmd, sizeof(ps_cmd),
2009 "ps -o \"%%cpu,cputime\" --no-headers %d",
2010 stream->pid);
2011
2012 pid_stat = popen(ps_cmd, "r");
2013 if (pid_stat) {
2014 char cpuperc[10];
2015 char cpuused[64];
2016
2017 if (fscanf(pid_stat, "%10s %64s", cpuperc,
2018 cpuused) == 2) {
2019 avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2020 cpuperc, cpuused);
2021 }
2022 fclose(pid_stat);
2023 }
2024 }
2025 #endif
2026
2027 avio_printf(pb, "<p>");
2028 }
2029 avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
2030
2031 for (i = 0; i < stream->nb_streams; i++) {
2032 AVStream *st = stream->streams[i];
2033 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2034 const char *type = "unknown";
2035 char parameters[64];
2036
2037 parameters[0] = 0;
2038
2039 switch(st->codec->codec_type) {
2040 case AVMEDIA_TYPE_AUDIO:
2041 type = "audio";
2042 snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2043 break;
2044 case AVMEDIA_TYPE_VIDEO:
2045 type = "video";
2046 snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2047 st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2048 break;
2049 default:
2050 abort();
2051 }
2052 avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2053 i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2054 }
2055 avio_printf(pb, "</table>\n");
2056
2057 }
2058 stream = stream->next;
2059 }
2060
2061 /* connection status */
2062 avio_printf(pb, "<h2>Connection Status</h2>\n");
2063
2064 avio_printf(pb, "Number of connections: %d / %d<br>\n",
2065 nb_connections, nb_max_connections);
2066
2067 avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2068 current_bandwidth, max_bandwidth);
2069
2070 avio_printf(pb, "<table>\n");
2071 avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2072 c1 = first_http_ctx;
2073 i = 0;
2074 while (c1 != NULL) {
2075 int bitrate;
2076 int j;
2077
2078 bitrate = 0;
2079 if (c1->stream) {
2080 for (j = 0; j < c1->stream->nb_streams; j++) {
2081 if (!c1->stream->feed)
2082 bitrate += c1->stream->streams[j]->codec->bit_rate;
2083 else if (c1->feed_streams[j] >= 0)
2084 bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2085 }
2086 }
2087
2088 i++;
2089 p = inet_ntoa(c1->from_addr.sin_addr);
2090 avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2091 i,
2092 c1->stream ? c1->stream->filename : "",
2093 c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2094 p,
2095 c1->protocol,
2096 http_state[c1->state]);
2097 fmt_bytecount(pb, bitrate);
2098 avio_printf(pb, "<td align=right>");
2099 fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2100 avio_printf(pb, "<td align=right>");
2101 fmt_bytecount(pb, c1->data_count);
2102 avio_printf(pb, "\n");
2103 c1 = c1->next;
2104 }
2105 avio_printf(pb, "</table>\n");
2106
2107 /* date */
2108 ti = time(NULL);
2109 p = ctime(&ti);
2110 avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2111 avio_printf(pb, "</body>\n</html>\n");
2112
2113 len = avio_close_dyn_buf(pb, &c->pb_buffer);
2114 c->buffer_ptr = c->pb_buffer;
2115 c->buffer_end = c->pb_buffer + len;
2116 }
2117
2118 static int open_input_stream(HTTPContext *c, const char *info)
2119 {
2120 char buf[128];
2121 char input_filename[1024];
2122 AVFormatContext *s = NULL;
2123 int i, ret;
2124 int64_t stream_pos;
2125
2126 /* find file name */
2127 if (c->stream->feed) {
2128 strcpy(input_filename, c->stream->feed->feed_filename);
2129 /* compute position (absolute time) */
2130 if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2131 if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2132 return ret;
2133 } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2134 int prebuffer = strtol(buf, 0, 10);
2135 stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2136 } else
2137 stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2138 } else {
2139 strcpy(input_filename, c->stream->feed_filename);
2140 /* compute position (relative time) */
2141 if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2142 if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2143 return ret;
2144 } else
2145 stream_pos = 0;
2146 }
2147 if (input_filename[0] == '\0')
2148 return -1;
2149
2150 /* open stream */
2151 if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2152 http_log("could not open %s: %d\n", input_filename, ret);
2153 return -1;
2154 }
2155 s->flags |= AVFMT_FLAG_GENPTS;
2156 c->fmt_in = s;
2157 if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2158 http_log("Could not find stream info '%s'\n", input_filename);
2159 avformat_close_input(&s);
2160 return -1;
2161 }
2162
2163 /* choose stream as clock source (we favorize video stream if
2164 present) for packet sending */
2165 c->pts_stream_index = 0;
2166 for(i=0;i<c->stream->nb_streams;i++) {
2167 if (c->pts_stream_index == 0 &&
2168 c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2169 c->pts_stream_index = i;
2170 }
2171 }
2172
2173 if (c->fmt_in->iformat->read_seek)
2174 av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2175 /* set the start time (needed for maxtime and RTP packet timing) */
2176 c->start_time = cur_time;
2177 c->first_pts = AV_NOPTS_VALUE;
2178 return 0;
2179 }
2180
2181 /* return the server clock (in us) */
2182 static int64_t get_server_clock(HTTPContext *c)
2183 {
2184 /* compute current pts value from system time */
2185 return (cur_time - c->start_time) * 1000;
2186 }
2187
2188 /* return the estimated time at which the current packet must be sent
2189 (in us) */
2190 static int64_t get_packet_send_clock(HTTPContext *c)
2191 {
2192 int bytes_left, bytes_sent, frame_bytes;
2193
2194 frame_bytes = c->cur_frame_bytes;
2195 if (frame_bytes <= 0)
2196 return c->cur_pts;
2197 else {
2198 bytes_left = c->buffer_end - c->buffer_ptr;
2199 bytes_sent = frame_bytes - bytes_left;
2200 return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2201 }
2202 }
2203
2204
2205 static int http_prepare_data(HTTPContext *c)
2206 {
2207 int i, len, ret;
2208 AVFormatContext *ctx;
2209
2210 av_freep(&c->pb_buffer);
2211 switch(c->state) {
2212 case HTTPSTATE_SEND_DATA_HEADER:
2213 memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2214 av_dict_set(&c->fmt_ctx.metadata, "author" , c->stream->author , 0);
2215 av_dict_set(&c->fmt_ctx.metadata, "comment" , c->stream->comment , 0);
2216 av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2217 av_dict_set(&c->fmt_ctx.metadata, "title" , c->stream->title , 0);
2218
2219 c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2220
2221 for(i=0;i<c->stream->nb_streams;i++) {
2222 AVStream *src;
2223 c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2224 /* if file or feed, then just take streams from FFStream struct */
2225 if (!c->stream->feed ||
2226 c->stream->feed == c->stream)
2227 src = c->stream->streams[i];
2228 else
2229 src = c->stream->feed->streams[c->stream->feed_streams[i]];
2230
2231 *(c->fmt_ctx.streams[i]) = *src;
2232 c->fmt_ctx.streams[i]->priv_data = 0;
2233 c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2234 AVStream, not in codec */
2235 }
2236 /* set output format parameters */
2237 c->fmt_ctx.oformat = c->stream->fmt;
2238 c->fmt_ctx.nb_streams = c->stream->nb_streams;
2239
2240 c->got_key_frame = 0;
2241
2242 /* prepare header and save header data in a stream */
2243 if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2244 /* XXX: potential leak */
2245 return -1;
2246 }
2247 c->fmt_ctx.pb->seekable = 0;
2248
2249 /*
2250 * HACK to avoid mpeg ps muxer to spit many underflow errors
2251 * Default value from Libav
2252 * Try to set it use configuration option
2253 */
2254 c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2255
2256 if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2257 http_log("Error writing output header\n");
2258 return -1;
2259 }
2260 av_dict_free(&c->fmt_ctx.metadata);
2261
2262 len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2263 c->buffer_ptr = c->pb_buffer;
2264 c->buffer_end = c->pb_buffer + len;
2265
2266 c->state = HTTPSTATE_SEND_DATA;
2267 c->last_packet_sent = 0;
2268 break;
2269 case HTTPSTATE_SEND_DATA:
2270 /* find a new packet */
2271 /* read a packet from the input stream */
2272 if (c->stream->feed)
2273 ffm_set_write_index(c->fmt_in,
2274 c->stream->feed->feed_write_index,
2275 c->stream->feed->feed_size);
2276
2277 if (c->stream->max_time &&
2278 c->stream->max_time + c->start_time - cur_time < 0)
2279 /* We have timed out */
2280 c->state = HTTPSTATE_SEND_DATA_TRAILER;
2281 else {
2282 AVPacket pkt;
2283 redo:
2284 ret = av_read_frame(c->fmt_in, &pkt);
2285 if (ret < 0) {
2286 if (c->stream->feed) {
2287 /* if coming from feed, it means we reached the end of the
2288 ffm file, so must wait for more data */
2289 c->state = HTTPSTATE_WAIT_FEED;
2290 return 1; /* state changed */
2291 } else if (ret == AVERROR(EAGAIN)) {
2292 /* input not ready, come back later */
2293 return 0;
2294 } else {
2295 if (c->stream->loop) {
2296 avformat_close_input(&c->fmt_in);
2297 if (open_input_stream(c, "") < 0)
2298 goto no_loop;
2299 goto redo;
2300 } else {
2301 no_loop:
2302 /* must send trailer now because eof or error */
2303 c->state = HTTPSTATE_SEND_DATA_TRAILER;
2304 }
2305 }
2306 } else {
2307 int source_index = pkt.stream_index;
2308 /* update first pts if needed */
2309 if (c->first_pts == AV_NOPTS_VALUE) {
2310 c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2311 c->start_time = cur_time;
2312 }
2313 /* send it to the appropriate stream */
2314 if (c->stream->feed) {
2315 /* if coming from a feed, select the right stream */
2316 if (c->switch_pending) {
2317 c->switch_pending = 0;
2318 for(i=0;i<c->stream->nb_streams;i++) {
2319 if (c->switch_feed_streams[i] == pkt.stream_index)
2320 if (pkt.flags & AV_PKT_FLAG_KEY)
2321 c->switch_feed_streams[i] = -1;
2322 if (c->switch_feed_streams[i] >= 0)
2323 c->switch_pending = 1;
2324 }
2325 }
2326 for(i=0;i<c->stream->nb_streams;i++) {
2327 if (c->stream->feed_streams[i] == pkt.stream_index) {
2328 AVStream *st = c->fmt_in->streams[source_index];
2329 pkt.stream_index = i;
2330 if (pkt.flags & AV_PKT_FLAG_KEY &&
2331 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2332 c->stream->nb_streams == 1))
2333 c->got_key_frame = 1;
2334 if (!c->stream->send_on_key || c->got_key_frame)
2335 goto send_it;
2336 }
2337 }
2338 } else {
2339 AVCodecContext *codec;
2340 AVStream *ist, *ost;
2341 send_it:
2342 ist = c->fmt_in->streams[source_index];
2343 /* specific handling for RTP: we use several
2344 output stream (one for each RTP
2345 connection). XXX: need more abstract handling */
2346 if (c->is_packetized) {
2347 /* compute send time and duration */
2348 c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2349 c->cur_pts -= c->first_pts;
2350 c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2351 /* find RTP context */
2352 c->packet_stream_index = pkt.stream_index;
2353 ctx = c->rtp_ctx[c->packet_stream_index];
2354 if(!ctx) {
2355 av_free_packet(&pkt);
2356 break;
2357 }
2358 codec = ctx->streams[0]->codec;
2359 /* only one stream per RTP connection */
2360 pkt.stream_index = 0;
2361 } else {
2362 ctx = &c->fmt_ctx;
2363 /* Fudge here */
2364 codec = ctx->streams[pkt.stream_index]->codec;
2365 }
2366
2367 if (c->is_packetized) {
2368 int max_packet_size;
2369 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2370 max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2371 else
2372 max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2373 ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2374 } else {
2375 ret = avio_open_dyn_buf(&ctx->pb);
2376 }
2377 if (ret < 0) {
2378 /* XXX: potential leak */
2379 return -1;
2380 }
2381 ost = ctx->streams[pkt.stream_index];
2382
2383 ctx->pb->seekable = 0;
2384 if (pkt.dts != AV_NOPTS_VALUE)
2385 pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2386 if (pkt.pts != AV_NOPTS_VALUE)
2387 pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2388 pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2389 if (av_write_frame(ctx, &pkt) < 0) {
2390 http_log("Error writing frame to output\n");
2391 c->state = HTTPSTATE_SEND_DATA_TRAILER;
2392 }
2393
2394 len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2395 c->cur_frame_bytes = len;
2396 c->buffer_ptr = c->pb_buffer;
2397 c->buffer_end = c->pb_buffer + len;
2398
2399 codec->frame_number++;
2400 if (len == 0) {
2401 av_free_packet(&pkt);
2402 goto redo;
2403 }
2404 }
2405 av_free_packet(&pkt);
2406 }
2407 }
2408 break;
2409 default:
2410 case HTTPSTATE_SEND_DATA_TRAILER:
2411 /* last packet test ? */
2412 if (c->last_packet_sent || c->is_packetized)
2413 return -1;
2414 ctx = &c->fmt_ctx;
2415 /* prepare header */
2416 if (avio_open_dyn_buf(&ctx->pb) < 0) {
2417 /* XXX: potential leak */
2418 return -1;
2419 }
2420 c->fmt_ctx.pb->seekable = 0;
2421 av_write_trailer(ctx);
2422 len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2423 c->buffer_ptr = c->pb_buffer;
2424 c->buffer_end = c->pb_buffer + len;
2425
2426 c->last_packet_sent = 1;
2427 break;
2428 }
2429 return 0;
2430 }
2431
2432 /* should convert the format at the same time */
2433 /* send data starting at c->buffer_ptr to the output connection
2434 (either UDP or TCP connection) */
2435 static int http_send_data(HTTPContext *c)
2436 {
2437 int len, ret;
2438
2439 for(;;) {
2440 if (c->buffer_ptr >= c->buffer_end) {
2441 ret = http_prepare_data(c);
2442 if (ret < 0)
2443 return -1;
2444 else if (ret != 0)
2445 /* state change requested */
2446 break;
2447 } else {
2448 if (c->is_packetized) {
2449 /* RTP data output */
2450 len = c->buffer_end - c->buffer_ptr;
2451 if (len < 4) {
2452 /* fail safe - should never happen */
2453 fail1:
2454 c->buffer_ptr = c->buffer_end;
2455 return 0;
2456 }
2457 len = (c->buffer_ptr[0] << 24) |
2458 (c->buffer_ptr[1] << 16) |
2459 (c->buffer_ptr[2] << 8) |
2460 (c->buffer_ptr[3]);
2461 if (len > (c->buffer_end - c->buffer_ptr))
2462 goto fail1;
2463 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2464 /* nothing to send yet: we can wait */
2465 return 0;
2466 }
2467
2468 c->data_count += len;
2469 update_datarate(&c->datarate, c->data_count);
2470 if (c->stream)
2471 c->stream->bytes_served += len;
2472
2473 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2474 /* RTP packets are sent inside the RTSP TCP connection */
2475 AVIOContext *pb;
2476 int interleaved_index, size;
2477 uint8_t header[4];
2478 HTTPContext *rtsp_c;
2479
2480 rtsp_c = c->rtsp_c;
2481 /* if no RTSP connection left, error */
2482 if (!rtsp_c)
2483 return -1;
2484 /* if already sending something, then wait. */
2485 if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2486 break;
2487 if (avio_open_dyn_buf(&pb) < 0)
2488 goto fail1;
2489 interleaved_index = c->packet_stream_index * 2;
2490 /* RTCP packets are sent at odd indexes */
2491 if (c->buffer_ptr[1] == 200)
2492 interleaved_index++;
2493 /* write RTSP TCP header */
2494 header[0] = '$';
2495 header[1] = interleaved_index;
2496 header[2] = len >> 8;
2497 header[3] = len;
2498 avio_write(pb, header, 4);
2499 /* write RTP packet data */
2500 c->buffer_ptr += 4;
2501 avio_write(pb, c->buffer_ptr, len);
2502 size = avio_close_dyn_buf(pb, &c->packet_buffer);
2503 /* prepare asynchronous TCP sending */
2504 rtsp_c->packet_buffer_ptr = c->packet_buffer;
2505 rtsp_c->packet_buffer_end = c->packet_buffer + size;
2506 c->buffer_ptr += len;
2507
2508 /* send everything we can NOW */
2509 len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2510 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2511 if (len > 0)
2512 rtsp_c->packet_buffer_ptr += len;
2513 if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2514 /* if we could not send all the data, we will
2515 send it later, so a new state is needed to
2516 "lock" the RTSP TCP connection */
2517 rtsp_c->state = RTSPSTATE_SEND_PACKET;
2518 break;
2519 } else
2520 /* all data has been sent */
2521 av_freep(&c->packet_buffer);
2522 } else {
2523 /* send RTP packet directly in UDP */
2524 c->buffer_ptr += 4;
2525 ffurl_write(c->rtp_handles[c->packet_stream_index],
2526 c->buffer_ptr, len);
2527 c->buffer_ptr += len;
2528 /* here we continue as we can send several packets per 10 ms slot */
2529 }
2530 } else {
2531 /* TCP data output */
2532 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2533 if (len < 0) {
2534 if (ff_neterrno() != AVERROR(EAGAIN) &&
2535 ff_neterrno() != AVERROR(EINTR))
2536 /* error : close connection */
2537 return -1;
2538 else
2539 return 0;
2540 } else
2541 c->buffer_ptr += len;
2542
2543 c->data_count += len;
2544 update_datarate(&c->datarate, c->data_count);
2545 if (c->stream)
2546 c->stream->bytes_served += len;
2547 break;
2548 }
2549 }
2550 } /* for(;;) */
2551 return 0;
2552 }
2553
2554 static int http_start_receive_data(HTTPContext *c)
2555 {
2556 int fd;
2557
2558 if (c->stream->feed_opened)
2559 return -1;
2560
2561 /* Don't permit writing to this one */
2562 if (c->stream->readonly)
2563 return -1;
2564
2565 /* open feed */
2566 fd = open(c->stream->feed_filename, O_RDWR);
2567 if (fd < 0) {
2568 http_log("Error opening feeder file: %s\n", strerror(errno));
2569 return -1;
2570 }
2571 c->feed_fd = fd;
2572
2573 if (c->stream->truncate) {
2574 /* truncate feed file */
2575 ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2576 ftruncate(c->feed_fd, FFM_PACKET_SIZE);
2577 http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2578 } else {
2579 if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2580 http_log("Error reading write index from feed file: %s\n", strerror(errno));
2581 return -1;
2582 }
2583 }
2584
2585 c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2586 c->stream->feed_size = lseek(fd, 0, SEEK_END);
2587 lseek(fd, 0, SEEK_SET);
2588
2589 /* init buffer input */
2590 c->buffer_ptr = c->buffer;
2591 c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2592 c->stream->feed_opened = 1;
2593 c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2594 return 0;
2595 }
2596
2597 static int http_receive_data(HTTPContext *c)
2598 {
2599 HTTPContext *c1;
2600 int len, loop_run = 0;
2601
2602 while (c->chunked_encoding && !c->chunk_size &&
2603 c->buffer_end > c->buffer_ptr) {
2604 /* read chunk header, if present */
2605 len = recv(c->fd, c->buffer_ptr, 1, 0);
2606
2607 if (len < 0) {
2608 if (ff_neterrno() != AVERROR(EAGAIN) &&
2609 ff_neterrno() != AVERROR(EINTR))
2610 /* error : close connection */
2611 goto fail;
2612 return 0;
2613 } else if (len == 0) {
2614 /* end of connection : close it */
2615 goto fail;
2616 } else if (c->buffer_ptr - c->buffer >= 2 &&
2617 !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2618 c->chunk_size = strtol(c->buffer, 0, 16);
2619 if (c->chunk_size == 0) // end of stream
2620 goto fail;
2621 c->buffer_ptr = c->buffer;
2622 break;
2623 } else if (++loop_run > 10) {
2624 /* no chunk header, abort */
2625 goto fail;
2626 } else {
2627 c->buffer_ptr++;
2628 }
2629 }
2630
2631 if (c->buffer_end > c->buffer_ptr) {
2632 len = recv(c->fd, c->buffer_ptr,
2633 FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2634 if (len < 0) {
2635 if (ff_neterrno() != AVERROR(EAGAIN) &&
2636 ff_neterrno() != AVERROR(EINTR))
2637 /* error : close connection */
2638 goto fail;
2639 } else if (len == 0)
2640 /* end of connection : close it */
2641 goto fail;
2642 else {
2643 c->chunk_size -= len;
2644 c->buffer_ptr += len;
2645 c->data_count += len;
2646 update_datarate(&c->datarate, c->data_count);
2647 }
2648 }
2649
2650 if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2651 if (c->buffer[0] != 'f' ||
2652 c->buffer[1] != 'm') {
2653 http_log("Feed stream has become desynchronized -- disconnecting\n");
2654 goto fail;
2655 }
2656 }
2657
2658 if (c->buffer_ptr >= c->buffer_end) {
2659 FFStream *feed = c->stream;
2660 /* a packet has been received : write it in the store, except
2661 if header */
2662 if (c->data_count > FFM_PACKET_SIZE) {
2663
2664 // printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2665 /* XXX: use llseek or url_seek */
2666 lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2667 if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2668 http_log("Error writing to feed file: %s\n", strerror(errno));
2669 goto fail;
2670 }
2671
2672 feed->feed_write_index += FFM_PACKET_SIZE;
2673 /* update file size */
2674 if (feed->feed_write_index > c->stream->feed_size)
2675 feed->feed_size = feed->feed_write_index;
2676
2677 /* handle wrap around if max file size reached */
2678 if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2679 feed->feed_write_index = FFM_PACKET_SIZE;
2680
2681 /* write index */
2682 if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2683 http_log("Error writing index to feed file: %s\n", strerror(errno));
2684 goto fail;
2685 }
2686
2687 /* wake up any waiting connections */
2688 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2689 if (c1->state == HTTPSTATE_WAIT_FEED &&
2690 c1->stream->feed == c->stream->feed)
2691 c1->state = HTTPSTATE_SEND_DATA;
2692 }
2693 } else {
2694 /* We have a header in our hands that contains useful data */
2695 AVFormatContext *s = avformat_alloc_context();
2696 AVIOContext *pb;
2697 AVInputFormat *fmt_in;
2698 int i;
2699
2700 if (!s)
2701 goto fail;
2702
2703 /* use feed output format name to find corresponding input format */
2704 fmt_in = av_find_input_format(feed->fmt->name);
2705 if (!fmt_in)
2706 goto fail;
2707
2708 pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2709 0, NULL, NULL, NULL, NULL);
2710 pb->seekable = 0;
2711
2712 s->pb = pb;
2713 if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2714 av_free(pb);
2715 goto fail;
2716 }
2717
2718 /* Now we have the actual streams */
2719 if (s->nb_streams != feed->nb_streams) {
2720 avformat_close_input(&s);
2721 av_free(pb);
2722 http_log("Feed '%s' stream number does not match registered feed\n",
2723 c->stream->feed_filename);
2724 goto fail;
2725 }
2726
2727 for (i = 0; i < s->nb_streams; i++) {
2728 AVStream *fst = feed->streams[i];
2729 AVStream *st = s->streams[i];
2730 avcodec_copy_context(fst->codec, st->codec);
2731 }
2732
2733 avformat_close_input(&s);
2734 av_free(pb);
2735 }
2736 c->buffer_ptr = c->buffer;
2737 }
2738
2739 return 0;
2740 fail:
2741 c->stream->feed_opened = 0;
2742 close(c->feed_fd);
2743 /* wake up any waiting connections to stop waiting for feed */
2744 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2745 if (c1->state == HTTPSTATE_WAIT_FEED &&
2746 c1->stream->feed == c->stream->feed)
2747 c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2748 }
2749 return -1;
2750 }
2751
2752 /********************************************************************/
2753 /* RTSP handling */
2754
2755 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2756 {
2757 const char *str;
2758 time_t ti;
2759 struct tm *tm;
2760 char buf2[32];
2761
2762 switch(error_number) {
2763 case RTSP_STATUS_OK:
2764 str = "OK";
2765 break;
2766 case RTSP_STATUS_METHOD:
2767 str = "Method Not Allowed";
2768 break;
2769 case RTSP_STATUS_BANDWIDTH:
2770 str = "Not Enough Bandwidth";
2771 break;
2772 case RTSP_STATUS_SESSION:
2773 str = "Session Not Found";
2774 break;
2775 case RTSP_STATUS_STATE:
2776 str = "Method Not Valid in This State";
2777 break;
2778 case RTSP_STATUS_AGGREGATE:
2779 str = "Aggregate operation not allowed";
2780 break;
2781 case RTSP_STATUS_ONLY_AGGREGATE:
2782 str = "Only aggregate operation allowed";
2783 break;
2784 case RTSP_STATUS_TRANSPORT:
2785 str = "Unsupported transport";
2786 break;
2787 case RTSP_STATUS_INTERNAL:
2788 str = "Internal Server Error";
2789 break;
2790 case RTSP_STATUS_SERVICE:
2791 str = "Service Unavailable";
2792 break;
2793 case RTSP_STATUS_VERSION:
2794 str = "RTSP Version not supported";
2795 break;
2796 default:
2797 str = "Unknown Error";
2798 break;
2799 }
2800
2801 avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2802 avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2803
2804 /* output GMT time */
2805 ti = time(NULL);
2806 tm = gmtime(&ti);
2807 strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2808 avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2809 }
2810
2811 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2812 {
2813 rtsp_reply_header(c, error_number);
2814 avio_printf(c->pb, "\r\n");
2815 }
2816
2817 static int rtsp_parse_request(HTTPContext *c)
2818 {
2819 const char *p, *p1, *p2;
2820 char cmd[32];
2821 char url[1024];
2822 char protocol[32];
2823 char line[1024];
2824 int len;
2825 RTSPMessageHeader header1, *header = &header1;
2826
2827 c->buffer_ptr[0] = '\0';
2828 p = c->buffer;
2829
2830 get_word(cmd, sizeof(cmd), &p);
2831 get_word(url, sizeof(url), &p);
2832 get_word(protocol, sizeof(protocol), &p);
2833
2834 av_strlcpy(c->method, cmd, sizeof(c->method));
2835 av_strlcpy(c->url, url, sizeof(c->url));
2836 av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2837
2838 if (avio_open_dyn_buf(&c->pb) < 0) {
2839 /* XXX: cannot do more */
2840 c->pb = NULL; /* safety */
2841 return -1;
2842 }
2843
2844 /* check version name */
2845 if (strcmp(protocol, "RTSP/1.0") != 0) {
2846 rtsp_reply_error(c, RTSP_STATUS_VERSION);
2847 goto the_end;
2848 }
2849
2850 /* parse each header line */
2851 memset(header, 0, sizeof(*header));
2852 /* skip to next line */
2853 while (*p != '\n' && *p != '\0')
2854 p++;
2855 if (*p == '\n')
2856 p++;
2857 while (*p != '\0') {
2858 p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2859 if (!p1)
2860 break;
2861 p2 = p1;
2862 if (p2 > p && p2[-1] == '\r')
2863 p2--;
2864 /* skip empty line */
2865 if (p2 == p)
2866 break;
2867 len = p2 - p;
2868 if (len > sizeof(line) - 1)
2869 len = sizeof(line) - 1;
2870 memcpy(line, p, len);
2871 line[len] = '\0';
2872 ff_rtsp_parse_line(header, line, NULL, NULL);
2873 p = p1 + 1;
2874 }
2875
2876 /* handle sequence number */
2877 c->seq = header->seq;
2878
2879 if (!strcmp(cmd, "DESCRIBE"))
2880 rtsp_cmd_describe(c, url);
2881 else if (!strcmp(cmd, "OPTIONS"))
2882 rtsp_cmd_options(c, url);
2883 else if (!strcmp(cmd, "SETUP"))
2884 rtsp_cmd_setup(c, url, header);
2885 else if (!strcmp(cmd, "PLAY"))
2886 rtsp_cmd_play(c, url, header);
2887 else if (!strcmp(cmd, "PAUSE"))
2888 rtsp_cmd_pause(c, url, header);
2889 else if (!strcmp(cmd, "TEARDOWN"))
2890 rtsp_cmd_teardown(c, url, header);
2891 else
2892 rtsp_reply_error(c, RTSP_STATUS_METHOD);
2893
2894 the_end:
2895 len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2896 c->pb = NULL; /* safety */
2897 if (len < 0) {
2898 /* XXX: cannot do more */
2899 return -1;
2900 }
2901 c->buffer_ptr = c->pb_buffer;
2902 c->buffer_end = c->pb_buffer + len;
2903 c->state = RTSPSTATE_SEND_REPLY;
2904 return 0;
2905 }
2906
2907 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2908 struct in_addr my_ip)
2909 {
2910 AVFormatContext *avc;
2911 AVStream *avs = NULL;
2912 int i;
2913
2914 avc = avformat_alloc_context();
2915 if (avc == NULL) {
2916 return -1;
2917 }
2918 av_dict_set(&avc->metadata, "title",
2919 stream->title[0] ? stream->title : "No Title", 0);
2920 avc->nb_streams = stream->nb_streams;
2921 if (stream->is_multicast) {
2922 snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2923 inet_ntoa(stream->multicast_ip),
2924 stream->multicast_port, stream->multicast_ttl);
2925 } else {
2926 snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2927 }
2928
2929 if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2930 !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2931 goto sdp_done;
2932 if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2933 !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2934 goto sdp_done;
2935
2936 for(i = 0; i < stream->nb_streams; i++) {
2937 avc->streams[i] = &avs[i];
2938 avc->streams[i]->codec = stream->streams[i]->codec;
2939 }
2940 *pbuffer = av_mallocz(2048);
2941 av_sdp_create(&avc, 1, *pbuffer, 2048);
2942
2943 sdp_done:
2944 av_free(avc->streams);
2945 av_dict_free(&avc->metadata);
2946 av_free(avc);
2947 av_free(avs);
2948
2949 return strlen(*pbuffer);
2950 }
2951
2952 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2953 {
2954 // rtsp_reply_header(c, RTSP_STATUS_OK);
2955 avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2956 avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2957 avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2958 avio_printf(c->pb, "\r\n");
2959 }
2960
2961 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2962 {
2963 FFStream *stream;
2964 char path1[1024];
2965 const char *path;
2966 uint8_t *content;
2967 int content_length, len;
2968 struct sockaddr_in my_addr;
2969
2970 /* find which url is asked */
2971 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2972 path = path1;
2973 if (*path == '/')
2974 path++;
2975
2976 for(stream = first_stream; stream != NULL; stream = stream->next) {
2977 if (!stream->is_feed &&
2978 stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2979 !strcmp(path, stream->filename)) {
2980 goto found;
2981 }
2982 }
2983 /* no stream found */
2984 rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2985 return;
2986
2987 found:
2988 /* prepare the media description in sdp format */
2989
2990 /* get the host IP */
2991 len = sizeof(my_addr);
2992 getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
2993 content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
2994 if (content_length < 0) {
2995 rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
2996 return;
2997 }
2998 rtsp_reply_header(c, RTSP_STATUS_OK);
2999 avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3000 avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3001 avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3002 avio_printf(c->pb, "\r\n");
3003 avio_write(c->pb, content, content_length);
3004 av_free(content);
3005 }
3006
3007 static HTTPContext *find_rtp_session(const char *session_id)
3008 {
3009 HTTPContext *c;
3010
3011 if (session_id[0] == '\0')
3012 return NULL;
3013
3014 for(c = first_http_ctx; c != NULL; c = c->next) {
3015 if (!strcmp(c->session_id, session_id))
3016 return c;
3017 }
3018 return NULL;
3019 }
3020
3021 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3022 {
3023 RTSPTransportField *th;
3024 int i;
3025
3026 for(i=0;i<h->nb_transports;i++) {
3027 th = &h->transports[i];
3028 if (th->lower_transport == lower_transport)
3029 return th;
3030 }
3031 return NULL;
3032 }
3033
3034 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3035 RTSPMessageHeader *h)
3036 {
3037 FFStream *stream;
3038 int stream_index, rtp_port, rtcp_port;
3039 char buf[1024];
3040 char path1[1024];
3041 const char *path;
3042 HTTPContext *rtp_c;
3043 RTSPTransportField *th;
3044 struct sockaddr_in dest_addr;
3045 RTSPActionServerSetup setup;
3046
3047 /* find which url is asked */
3048 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3049 path = path1;
3050 if (*path == '/')
3051 path++;
3052
3053 /* now check each stream */
3054 for(stream = first_stream; stream != NULL; stream = stream->next) {
3055 if (!stream->is_feed &&
3056 stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3057 /* accept aggregate filenames only if single stream */
3058 if (!strcmp(path, stream->filename)) {
3059 if (stream->nb_streams != 1) {
3060 rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3061 return;
3062 }
3063 stream_index = 0;
3064 goto found;
3065 }
3066
3067 for(stream_index = 0; stream_index < stream->nb_streams;
3068 stream_index++) {
3069 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3070 stream->filename, stream_index);
3071 if (!strcmp(path, buf))
3072 goto found;
3073 }
3074 }
3075 }
3076 /* no stream found */
3077 rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3078 return;
3079 found:
3080
3081 /* generate session id if needed */
3082 if (h->session_id[0] == '\0')
3083 snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3084 av_lfg_get(&random_state), av_lfg_get(&random_state));
3085
3086 /* find rtp session, and create it if none found */
3087 rtp_c = find_rtp_session(h->session_id);
3088 if (!rtp_c) {
3089 /* always prefer UDP */
3090 th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3091 if (!th) {
3092 th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3093 if (!th) {
3094 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3095 return;
3096 }
3097 }
3098
3099 rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3100 th->lower_transport);
3101 if (!rtp_c) {
3102 rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3103 return;
3104 }
3105
3106 /* open input stream */
3107 if (open_input_stream(rtp_c, "") < 0) {
3108 rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3109 return;
3110 }
3111 }
3112
3113 /* test if stream is OK (test needed because several SETUP needs
3114 to be done for a given file) */
3115 if (rtp_c->stream != stream) {
3116 rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3117 return;
3118 }
3119
3120 /* test if stream is already set up */
3121 if (rtp_c->rtp_ctx[stream_index]) {
3122 rtsp_reply_error(c, RTSP_STATUS_STATE);
3123 return;
3124 }
3125
3126 /* check transport */
3127 th = find_transport(h, rtp_c->rtp_protocol);
3128 if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3129 th->client_port_min <= 0)) {
3130 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3131 return;
3132 }
3133
3134 /* setup default options */
3135 setup.transport_option[0] = '\0';
3136 dest_addr = rtp_c->from_addr;
3137 dest_addr.sin_port = htons(th->client_port_min);
3138
3139 /* setup stream */
3140 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3141 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3142 return;
3143 }
3144
3145 /* now everything is OK, so we can send the connection parameters */
3146 rtsp_reply_header(c, RTSP_STATUS_OK);
3147 /* session ID */
3148 avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3149
3150 switch(rtp_c->rtp_protocol) {
3151 case RTSP_LOWER_TRANSPORT_UDP:
3152 rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3153 rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3154 avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3155 "client_port=%d-%d;server_port=%d-%d",
3156 th->client_port_min, th->client_port_max,
3157 rtp_port, rtcp_port);
3158 break;
3159 case RTSP_LOWER_TRANSPORT_TCP:
3160 avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3161 stream_index * 2, stream_index * 2 + 1);
3162 break;
3163 default:
3164 break;
3165 }
3166 if (setup.transport_option[0] != '\0')
3167 avio_printf(c->pb, ";%s", setup.transport_option);
3168 avio_printf(c->pb, "\r\n");
3169
3170
3171 avio_printf(c->pb, "\r\n");
3172 }
3173
3174
3175 /* find an rtp connection by using the session ID. Check consistency
3176 with filename */
3177 static HTTPContext *find_rtp_session_with_url(const char *url,
3178 const char *session_id)
3179 {
3180 HTTPContext *rtp_c;
3181 char path1[1024];
3182 const char *path;
3183 char buf[1024];
3184 int s, len;
3185
3186 rtp_c = find_rtp_session(session_id);
3187 if (!rtp_c)
3188 return NULL;
3189
3190 /* find which url is asked */
3191 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3192 path = path1;
3193 if (*path == '/')
3194 path++;
3195 if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3196 for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3197 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3198 rtp_c->stream->filename, s);
3199 if(!strncmp(path, buf, sizeof(buf))) {
3200 // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3201 return rtp_c;
3202 }
3203 }
3204 len = strlen(path);
3205 if (len > 0 && path[len - 1] == '/' &&
3206 !strncmp(path, rtp_c->stream->filename, len - 1))
3207 return rtp_c;
3208 return NULL;
3209 }
3210
3211 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3212 {
3213 HTTPContext *rtp_c;
3214
3215 rtp_c = find_rtp_session_with_url(url, h->session_id);
3216 if (!rtp_c) {
3217 rtsp_reply_error(c, RTSP_STATUS_SESSION);
3218 return;
3219 }
3220
3221 if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3222 rtp_c->state != HTTPSTATE_WAIT_FEED &&
3223 rtp_c->state != HTTPSTATE_READY) {
3224 rtsp_reply_error(c, RTSP_STATUS_STATE);
3225 return;
3226 }
3227
3228 rtp_c->state = HTTPSTATE_SEND_DATA;
3229
3230 /* now everything is OK, so we can send the connection parameters */
3231 rtsp_reply_header(c, RTSP_STATUS_OK);
3232 /* session ID */
3233 avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3234 avio_printf(c->pb, "\r\n");
3235 }
3236
3237 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3238 {
3239 HTTPContext *rtp_c;
3240
3241 rtp_c = find_rtp_session_with_url(url, h->session_id);
3242 if (!rtp_c) {
3243 rtsp_reply_error(c