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