]> git.sesse.net Git - ffmpeg/blob - ffserver.c
ffserver: Make sure a destination URL is set when creating the SDP
[ffmpeg] / 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 "libavcodec/opt.h"
40 #include <stdarg.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <sys/ioctl.h>
44 #if HAVE_POLL_H
45 #include <poll.h>
46 #endif
47 #include <errno.h>
48 #include <sys/time.h>
49 #include <time.h>
50 #include <sys/wait.h>
51 #include <signal.h>
52 #if HAVE_DLFCN_H
53 #include <dlfcn.h>
54 #endif
55
56 #include "cmdutils.h"
57
58 const char program_name[] = "FFserver";
59 const int program_birth_year = 2000;
60
61 static const OptionDef options[];
62
63 enum HTTPState {
64     HTTPSTATE_WAIT_REQUEST,
65     HTTPSTATE_SEND_HEADER,
66     HTTPSTATE_SEND_DATA_HEADER,
67     HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
68     HTTPSTATE_SEND_DATA_TRAILER,
69     HTTPSTATE_RECEIVE_DATA,
70     HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
71     HTTPSTATE_READY,
72
73     RTSPSTATE_WAIT_REQUEST,
74     RTSPSTATE_SEND_REPLY,
75     RTSPSTATE_SEND_PACKET,
76 };
77
78 static const char *http_state[] = {
79     "HTTP_WAIT_REQUEST",
80     "HTTP_SEND_HEADER",
81
82     "SEND_DATA_HEADER",
83     "SEND_DATA",
84     "SEND_DATA_TRAILER",
85     "RECEIVE_DATA",
86     "WAIT_FEED",
87     "READY",
88
89     "RTSP_WAIT_REQUEST",
90     "RTSP_SEND_REPLY",
91     "RTSP_SEND_PACKET",
92 };
93
94 #define IOBUFFER_INIT_SIZE 8192
95
96 /* timeouts are in ms */
97 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
98 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
99
100 #define SYNC_TIMEOUT (10 * 1000)
101
102 typedef struct RTSPActionServerSetup {
103     uint32_t ipaddr;
104     char transport_option[512];
105 } RTSPActionServerSetup;
106
107 typedef struct {
108     int64_t count1, count2;
109     int64_t time1, time2;
110 } DataRateData;
111
112 /* context associated with one connection */
113 typedef struct HTTPContext {
114     enum HTTPState state;
115     int fd; /* socket file descriptor */
116     struct sockaddr_in from_addr; /* origin */
117     struct pollfd *poll_entry; /* used when polling */
118     int64_t timeout;
119     uint8_t *buffer_ptr, *buffer_end;
120     int http_error;
121     int post;
122     int chunked_encoding;
123     int chunk_size;               /* 0 if it needs to be read */
124     struct HTTPContext *next;
125     int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
126     int64_t data_count;
127     /* feed input */
128     int feed_fd;
129     /* input format handling */
130     AVFormatContext *fmt_in;
131     int64_t start_time;            /* In milliseconds - this wraps fairly often */
132     int64_t first_pts;            /* initial pts value */
133     int64_t cur_pts;             /* current pts value from the stream in us */
134     int64_t cur_frame_duration;  /* duration of the current frame in us */
135     int cur_frame_bytes;       /* output frame size, needed to compute
136                                   the time at which we send each
137                                   packet */
138     int pts_stream_index;        /* stream we choose as clock reference */
139     int64_t cur_clock;           /* current clock reference value in us */
140     /* output format handling */
141     struct FFStream *stream;
142     /* -1 is invalid stream */
143     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
144     int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
145     int switch_pending;
146     AVFormatContext fmt_ctx; /* instance of FFStream for one user */
147     int last_packet_sent; /* true if last data packet was sent */
148     int suppress_log;
149     DataRateData datarate;
150     int wmp_client_id;
151     char protocol[16];
152     char method[16];
153     char url[128];
154     int buffer_size;
155     uint8_t *buffer;
156     int is_packetized; /* if true, the stream is packetized */
157     int packet_stream_index; /* current stream for output in state machine */
158
159     /* RTSP state specific */
160     uint8_t *pb_buffer; /* XXX: use that in all the code */
161     ByteIOContext *pb;
162     int seq; /* RTSP sequence number */
163
164     /* RTP state specific */
165     enum RTSPLowerTransport rtp_protocol;
166     char session_id[32]; /* session id */
167     AVFormatContext *rtp_ctx[MAX_STREAMS];
168
169     /* RTP/UDP specific */
170     URLContext *rtp_handles[MAX_STREAMS];
171
172     /* RTP/TCP specific */
173     struct HTTPContext *rtsp_c;
174     uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
175 } HTTPContext;
176
177 /* each generated stream is described here */
178 enum StreamType {
179     STREAM_TYPE_LIVE,
180     STREAM_TYPE_STATUS,
181     STREAM_TYPE_REDIRECT,
182 };
183
184 enum IPAddressAction {
185     IP_ALLOW = 1,
186     IP_DENY,
187 };
188
189 typedef struct IPAddressACL {
190     struct IPAddressACL *next;
191     enum IPAddressAction action;
192     /* These are in host order */
193     struct in_addr first;
194     struct in_addr last;
195 } IPAddressACL;
196
197 /* description of each stream of the ffserver.conf file */
198 typedef struct FFStream {
199     enum StreamType stream_type;
200     char filename[1024];     /* stream filename */
201     struct FFStream *feed;   /* feed we are using (can be null if
202                                 coming from file) */
203     AVFormatParameters *ap_in; /* input parameters */
204     AVInputFormat *ifmt;       /* if non NULL, force input format */
205     AVOutputFormat *fmt;
206     IPAddressACL *acl;
207     char dynamic_acl[1024];
208     int nb_streams;
209     int prebuffer;      /* Number of millseconds early to start */
210     int64_t max_time;      /* Number of milliseconds to run */
211     int send_on_key;
212     AVStream *streams[MAX_STREAMS];
213     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
214     char feed_filename[1024]; /* file name of the feed storage, or
215                                  input file name for a stream */
216     char author[512];
217     char title[512];
218     char copyright[512];
219     char comment[512];
220     pid_t pid;  /* Of ffmpeg process */
221     time_t pid_start;  /* Of ffmpeg process */
222     char **child_argv;
223     struct FFStream *next;
224     unsigned bandwidth; /* bandwidth, in kbits/s */
225     /* RTSP options */
226     char *rtsp_option;
227     /* multicast specific */
228     int is_multicast;
229     struct in_addr multicast_ip;
230     int multicast_port; /* first port used for multicast */
231     int multicast_ttl;
232     int loop; /* if true, send the stream in loops (only meaningful if file) */
233
234     /* feed specific */
235     int feed_opened;     /* true if someone is writing to the feed */
236     int is_feed;         /* true if it is a feed */
237     int readonly;        /* True if writing is prohibited to the file */
238     int truncate;        /* True if feeder connection truncate the feed file */
239     int conns_served;
240     int64_t bytes_served;
241     int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
242     int64_t feed_write_index;   /* current write position in feed (it wraps around) */
243     int64_t feed_size;          /* current size of feed */
244     struct FFStream *next_feed;
245 } FFStream;
246
247 typedef struct FeedData {
248     long long data_count;
249     float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
250 } FeedData;
251
252 static struct sockaddr_in my_http_addr;
253 static struct sockaddr_in my_rtsp_addr;
254
255 static char logfilename[1024];
256 static HTTPContext *first_http_ctx;
257 static FFStream *first_feed;   /* contains only feeds */
258 static FFStream *first_stream; /* contains all streams, including feeds */
259
260 static void new_connection(int server_fd, int is_rtsp);
261 static void close_connection(HTTPContext *c);
262
263 /* HTTP handling */
264 static int handle_connection(HTTPContext *c);
265 static int http_parse_request(HTTPContext *c);
266 static int http_send_data(HTTPContext *c);
267 static void compute_status(HTTPContext *c);
268 static int open_input_stream(HTTPContext *c, const char *info);
269 static int http_start_receive_data(HTTPContext *c);
270 static int http_receive_data(HTTPContext *c);
271
272 /* RTSP handling */
273 static int rtsp_parse_request(HTTPContext *c);
274 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
275 static void rtsp_cmd_options(HTTPContext *c, const char *url);
276 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
277 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
278 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
279 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
280
281 /* SDP handling */
282 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
283                                    struct in_addr my_ip);
284
285 /* RTP handling */
286 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
287                                        FFStream *stream, const char *session_id,
288                                        enum RTSPLowerTransport rtp_protocol);
289 static int rtp_new_av_stream(HTTPContext *c,
290                              int stream_index, struct sockaddr_in *dest_addr,
291                              HTTPContext *rtsp_c);
292
293 static const char *my_program_name;
294 static const char *my_program_dir;
295
296 static const char *config_filename = "/etc/ffserver.conf";
297
298 static int ffserver_debug;
299 static int ffserver_daemon;
300 static int no_launch;
301 static int need_to_start_children;
302
303 /* maximum number of simultaneous HTTP connections */
304 static unsigned int nb_max_http_connections = 2000;
305 static unsigned int nb_max_connections = 5;
306 static unsigned int nb_connections;
307
308 static uint64_t max_bandwidth = 1000;
309 static uint64_t current_bandwidth;
310
311 static int64_t cur_time;           // Making this global saves on passing it around everywhere
312
313 static AVLFG random_state;
314
315 static FILE *logfile = NULL;
316
317 /* FIXME: make ffserver work with IPv6 */
318 /* resolve host with also IP address parsing */
319 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
320 {
321
322     if (!ff_inet_aton(hostname, sin_addr)) {
323 #if HAVE_GETADDRINFO
324         struct addrinfo *ai, *cur;
325         struct addrinfo hints;
326         memset(&hints, 0, sizeof(hints));
327         hints.ai_family = AF_INET;
328         if (getaddrinfo(hostname, NULL, &hints, &ai))
329             return -1;
330         /* getaddrinfo returns a linked list of addrinfo structs.
331          * Even if we set ai_family = AF_INET above, make sure
332          * that the returned one actually is of the correct type. */
333         for (cur = ai; cur; cur = cur->ai_next) {
334             if (cur->ai_family == AF_INET) {
335                 *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
336                 freeaddrinfo(ai);
337                 return 0;
338             }
339         }
340         freeaddrinfo(ai);
341         return -1;
342 #else
343         struct hostent *hp;
344         hp = gethostbyname(hostname);
345         if (!hp)
346             return -1;
347         memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
348 #endif
349     }
350     return 0;
351 }
352
353 static char *ctime1(char *buf2)
354 {
355     time_t ti;
356     char *p;
357
358     ti = time(NULL);
359     p = ctime(&ti);
360     strcpy(buf2, p);
361     p = buf2 + strlen(p) - 1;
362     if (*p == '\n')
363         *p = '\0';
364     return buf2;
365 }
366
367 static void http_vlog(const char *fmt, va_list vargs)
368 {
369     static int print_prefix = 1;
370     if (logfile) {
371         if (print_prefix) {
372             char buf[32];
373             ctime1(buf);
374             fprintf(logfile, "%s ", buf);
375         }
376         print_prefix = strstr(fmt, "\n") != NULL;
377         vfprintf(logfile, fmt, vargs);
378         fflush(logfile);
379     }
380 }
381
382 static void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...)
383 {
384     va_list vargs;
385     va_start(vargs, fmt);
386     http_vlog(fmt, vargs);
387     va_end(vargs);
388 }
389
390 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
391 {
392     static int print_prefix = 1;
393     AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
394     if (level > av_log_get_level())
395         return;
396     if (print_prefix && avc)
397         http_log("[%s @ %p]", avc->item_name(ptr), ptr);
398     print_prefix = strstr(fmt, "\n") != NULL;
399     http_vlog(fmt, vargs);
400 }
401
402 static void log_connection(HTTPContext *c)
403 {
404     if (c->suppress_log)
405         return;
406
407     http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
408              inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
409              c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
410 }
411
412 static void update_datarate(DataRateData *drd, int64_t count)
413 {
414     if (!drd->time1 && !drd->count1) {
415         drd->time1 = drd->time2 = cur_time;
416         drd->count1 = drd->count2 = count;
417     } else if (cur_time - drd->time2 > 5000) {
418         drd->time1 = drd->time2;
419         drd->count1 = drd->count2;
420         drd->time2 = cur_time;
421         drd->count2 = count;
422     }
423 }
424
425 /* In bytes per second */
426 static int compute_datarate(DataRateData *drd, int64_t count)
427 {
428     if (cur_time == drd->time1)
429         return 0;
430
431     return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
432 }
433
434
435 static void start_children(FFStream *feed)
436 {
437     if (no_launch)
438         return;
439
440     for (; feed; feed = feed->next) {
441         if (feed->child_argv && !feed->pid) {
442             feed->pid_start = time(0);
443
444             feed->pid = fork();
445
446             if (feed->pid < 0) {
447                 http_log("Unable to create children\n");
448                 exit(1);
449             }
450             if (!feed->pid) {
451                 /* In child */
452                 char pathname[1024];
453                 char *slash;
454                 int i;
455
456                 av_strlcpy(pathname, my_program_name, sizeof(pathname));
457
458                 slash = strrchr(pathname, '/');
459                 if (!slash)
460                     slash = pathname;
461                 else
462                     slash++;
463                 strcpy(slash, "ffmpeg");
464
465                 http_log("Launch commandline: ");
466                 http_log("%s ", pathname);
467                 for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
468                     http_log("%s ", feed->child_argv[i]);
469                 http_log("\n");
470
471                 for (i = 3; i < 256; i++)
472                     close(i);
473
474                 if (!ffserver_debug) {
475                     i = open("/dev/null", O_RDWR);
476                     if (i != -1) {
477                         dup2(i, 0);
478                         dup2(i, 1);
479                         dup2(i, 2);
480                         close(i);
481                     }
482                 }
483
484                 /* This is needed to make relative pathnames work */
485                 chdir(my_program_dir);
486
487                 signal(SIGPIPE, SIG_DFL);
488
489                 execvp(pathname, feed->child_argv);
490
491                 _exit(1);
492             }
493         }
494     }
495 }
496
497 /* open a listening socket */
498 static int socket_open_listen(struct sockaddr_in *my_addr)
499 {
500     int server_fd, tmp;
501
502     server_fd = socket(AF_INET,SOCK_STREAM,0);
503     if (server_fd < 0) {
504         perror ("socket");
505         return -1;
506     }
507
508     tmp = 1;
509     setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
510
511     if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
512         char bindmsg[32];
513         snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
514         perror (bindmsg);
515         closesocket(server_fd);
516         return -1;
517     }
518
519     if (listen (server_fd, 5) < 0) {
520         perror ("listen");
521         closesocket(server_fd);
522         return -1;
523     }
524     ff_socket_nonblock(server_fd, 1);
525
526     return server_fd;
527 }
528
529 /* start all multicast streams */
530 static void start_multicast(void)
531 {
532     FFStream *stream;
533     char session_id[32];
534     HTTPContext *rtp_c;
535     struct sockaddr_in dest_addr;
536     int default_port, stream_index;
537
538     default_port = 6000;
539     for(stream = first_stream; stream != NULL; stream = stream->next) {
540         if (stream->is_multicast) {
541             /* open the RTP connection */
542             snprintf(session_id, sizeof(session_id), "%08x%08x",
543                      av_lfg_get(&random_state), av_lfg_get(&random_state));
544
545             /* choose a port if none given */
546             if (stream->multicast_port == 0) {
547                 stream->multicast_port = default_port;
548                 default_port += 100;
549             }
550
551             dest_addr.sin_family = AF_INET;
552             dest_addr.sin_addr = stream->multicast_ip;
553             dest_addr.sin_port = htons(stream->multicast_port);
554
555             rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
556                                        RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
557             if (!rtp_c)
558                 continue;
559
560             if (open_input_stream(rtp_c, "") < 0) {
561                 http_log("Could not open input stream for stream '%s'\n",
562                          stream->filename);
563                 continue;
564             }
565
566             /* open each RTP stream */
567             for(stream_index = 0; stream_index < stream->nb_streams;
568                 stream_index++) {
569                 dest_addr.sin_port = htons(stream->multicast_port +
570                                            2 * stream_index);
571                 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
572                     http_log("Could not open output stream '%s/streamid=%d'\n",
573                              stream->filename, stream_index);
574                     exit(1);
575                 }
576             }
577
578             /* change state to send data */
579             rtp_c->state = HTTPSTATE_SEND_DATA;
580         }
581     }
582 }
583
584 /* main loop of the http server */
585 static int http_server(void)
586 {
587     int server_fd = 0, rtsp_server_fd = 0;
588     int ret, delay, delay1;
589     struct pollfd *poll_table, *poll_entry;
590     HTTPContext *c, *c_next;
591
592     if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
593         http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
594         return -1;
595     }
596
597     if (my_http_addr.sin_port) {
598         server_fd = socket_open_listen(&my_http_addr);
599         if (server_fd < 0)
600             return -1;
601     }
602
603     if (my_rtsp_addr.sin_port) {
604         rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
605         if (rtsp_server_fd < 0)
606             return -1;
607     }
608
609     if (!rtsp_server_fd && !server_fd) {
610         http_log("HTTP and RTSP disabled.\n");
611         return -1;
612     }
613
614     http_log("FFserver started.\n");
615
616     start_children(first_feed);
617
618     start_multicast();
619
620     for(;;) {
621         poll_entry = poll_table;
622         if (server_fd) {
623             poll_entry->fd = server_fd;
624             poll_entry->events = POLLIN;
625             poll_entry++;
626         }
627         if (rtsp_server_fd) {
628             poll_entry->fd = rtsp_server_fd;
629             poll_entry->events = POLLIN;
630             poll_entry++;
631         }
632
633         /* wait for events on each HTTP handle */
634         c = first_http_ctx;
635         delay = 1000;
636         while (c != NULL) {
637             int fd;
638             fd = c->fd;
639             switch(c->state) {
640             case HTTPSTATE_SEND_HEADER:
641             case RTSPSTATE_SEND_REPLY:
642             case RTSPSTATE_SEND_PACKET:
643                 c->poll_entry = poll_entry;
644                 poll_entry->fd = fd;
645                 poll_entry->events = POLLOUT;
646                 poll_entry++;
647                 break;
648             case HTTPSTATE_SEND_DATA_HEADER:
649             case HTTPSTATE_SEND_DATA:
650             case HTTPSTATE_SEND_DATA_TRAILER:
651                 if (!c->is_packetized) {
652                     /* for TCP, we output as much as we can (may need to put a limit) */
653                     c->poll_entry = poll_entry;
654                     poll_entry->fd = fd;
655                     poll_entry->events = POLLOUT;
656                     poll_entry++;
657                 } else {
658                     /* when ffserver is doing the timing, we work by
659                        looking at which packet need to be sent every
660                        10 ms */
661                     delay1 = 10; /* one tick wait XXX: 10 ms assumed */
662                     if (delay1 < delay)
663                         delay = delay1;
664                 }
665                 break;
666             case HTTPSTATE_WAIT_REQUEST:
667             case HTTPSTATE_RECEIVE_DATA:
668             case HTTPSTATE_WAIT_FEED:
669             case RTSPSTATE_WAIT_REQUEST:
670                 /* need to catch errors */
671                 c->poll_entry = poll_entry;
672                 poll_entry->fd = fd;
673                 poll_entry->events = POLLIN;/* Maybe this will work */
674                 poll_entry++;
675                 break;
676             default:
677                 c->poll_entry = NULL;
678                 break;
679             }
680             c = c->next;
681         }
682
683         /* wait for an event on one connection. We poll at least every
684            second to handle timeouts */
685         do {
686             ret = poll(poll_table, poll_entry - poll_table, delay);
687             if (ret < 0 && ff_neterrno() != FF_NETERROR(EAGAIN) &&
688                 ff_neterrno() != FF_NETERROR(EINTR))
689                 return -1;
690         } while (ret < 0);
691
692         cur_time = av_gettime() / 1000;
693
694         if (need_to_start_children) {
695             need_to_start_children = 0;
696             start_children(first_feed);
697         }
698
699         /* now handle the events */
700         for(c = first_http_ctx; c != NULL; c = c_next) {
701             c_next = c->next;
702             if (handle_connection(c) < 0) {
703                 /* close and free the connection */
704                 log_connection(c);
705                 close_connection(c);
706             }
707         }
708
709         poll_entry = poll_table;
710         if (server_fd) {
711             /* new HTTP connection request ? */
712             if (poll_entry->revents & POLLIN)
713                 new_connection(server_fd, 0);
714             poll_entry++;
715         }
716         if (rtsp_server_fd) {
717             /* new RTSP connection request ? */
718             if (poll_entry->revents & POLLIN)
719                 new_connection(rtsp_server_fd, 1);
720         }
721     }
722 }
723
724 /* start waiting for a new HTTP/RTSP request */
725 static void start_wait_request(HTTPContext *c, int is_rtsp)
726 {
727     c->buffer_ptr = c->buffer;
728     c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
729
730     if (is_rtsp) {
731         c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
732         c->state = RTSPSTATE_WAIT_REQUEST;
733     } else {
734         c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
735         c->state = HTTPSTATE_WAIT_REQUEST;
736     }
737 }
738
739 static void http_send_too_busy_reply(int fd)
740 {
741     char buffer[300];
742     int len = snprintf(buffer, sizeof(buffer),
743                        "HTTP/1.0 200 Server too busy\r\n"
744                        "Content-type: text/html\r\n"
745                        "\r\n"
746                        "<html><head><title>Too busy</title></head><body>\r\n"
747                        "<p>The server is too busy to serve your request at this time.</p>\r\n"
748                        "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
749                        "</body></html>\r\n",
750                        nb_connections, nb_max_connections);
751     send(fd, buffer, len, 0);
752 }
753
754
755 static void new_connection(int server_fd, int is_rtsp)
756 {
757     struct sockaddr_in from_addr;
758     int fd, len;
759     HTTPContext *c = NULL;
760
761     len = sizeof(from_addr);
762     fd = accept(server_fd, (struct sockaddr *)&from_addr,
763                 &len);
764     if (fd < 0) {
765         http_log("error during accept %s\n", strerror(errno));
766         return;
767     }
768     ff_socket_nonblock(fd, 1);
769
770     if (nb_connections >= nb_max_connections) {
771         http_send_too_busy_reply(fd);
772         goto fail;
773     }
774
775     /* add a new connection */
776     c = av_mallocz(sizeof(HTTPContext));
777     if (!c)
778         goto fail;
779
780     c->fd = fd;
781     c->poll_entry = NULL;
782     c->from_addr = from_addr;
783     c->buffer_size = IOBUFFER_INIT_SIZE;
784     c->buffer = av_malloc(c->buffer_size);
785     if (!c->buffer)
786         goto fail;
787
788     c->next = first_http_ctx;
789     first_http_ctx = c;
790     nb_connections++;
791
792     start_wait_request(c, is_rtsp);
793
794     return;
795
796  fail:
797     if (c) {
798         av_free(c->buffer);
799         av_free(c);
800     }
801     closesocket(fd);
802 }
803
804 static void close_connection(HTTPContext *c)
805 {
806     HTTPContext **cp, *c1;
807     int i, nb_streams;
808     AVFormatContext *ctx;
809     URLContext *h;
810     AVStream *st;
811
812     /* remove connection from list */
813     cp = &first_http_ctx;
814     while ((*cp) != NULL) {
815         c1 = *cp;
816         if (c1 == c)
817             *cp = c->next;
818         else
819             cp = &c1->next;
820     }
821
822     /* remove references, if any (XXX: do it faster) */
823     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
824         if (c1->rtsp_c == c)
825             c1->rtsp_c = NULL;
826     }
827
828     /* remove connection associated resources */
829     if (c->fd >= 0)
830         closesocket(c->fd);
831     if (c->fmt_in) {
832         /* close each frame parser */
833         for(i=0;i<c->fmt_in->nb_streams;i++) {
834             st = c->fmt_in->streams[i];
835             if (st->codec->codec)
836                 avcodec_close(st->codec);
837         }
838         av_close_input_file(c->fmt_in);
839     }
840
841     /* free RTP output streams if any */
842     nb_streams = 0;
843     if (c->stream)
844         nb_streams = c->stream->nb_streams;
845
846     for(i=0;i<nb_streams;i++) {
847         ctx = c->rtp_ctx[i];
848         if (ctx) {
849             av_write_trailer(ctx);
850             av_free(ctx);
851         }
852         h = c->rtp_handles[i];
853         if (h)
854             url_close(h);
855     }
856
857     ctx = &c->fmt_ctx;
858
859     if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
860         if (ctx->oformat) {
861             /* prepare header */
862             if (url_open_dyn_buf(&ctx->pb) >= 0) {
863                 av_write_trailer(ctx);
864                 av_freep(&c->pb_buffer);
865                 url_close_dyn_buf(ctx->pb, &c->pb_buffer);
866             }
867         }
868     }
869
870     for(i=0; i<ctx->nb_streams; i++)
871         av_free(ctx->streams[i]);
872
873     if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
874         current_bandwidth -= c->stream->bandwidth;
875
876     /* signal that there is no feed if we are the feeder socket */
877     if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
878         c->stream->feed_opened = 0;
879         close(c->feed_fd);
880     }
881
882     av_freep(&c->pb_buffer);
883     av_freep(&c->packet_buffer);
884     av_free(c->buffer);
885     av_free(c);
886     nb_connections--;
887 }
888
889 static int handle_connection(HTTPContext *c)
890 {
891     int len, ret;
892
893     switch(c->state) {
894     case HTTPSTATE_WAIT_REQUEST:
895     case RTSPSTATE_WAIT_REQUEST:
896         /* timeout ? */
897         if ((c->timeout - cur_time) < 0)
898             return -1;
899         if (c->poll_entry->revents & (POLLERR | POLLHUP))
900             return -1;
901
902         /* no need to read if no events */
903         if (!(c->poll_entry->revents & POLLIN))
904             return 0;
905         /* read the data */
906     read_loop:
907         len = recv(c->fd, c->buffer_ptr, 1, 0);
908         if (len < 0) {
909             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
910                 ff_neterrno() != FF_NETERROR(EINTR))
911                 return -1;
912         } else if (len == 0) {
913             return -1;
914         } else {
915             /* search for end of request. */
916             uint8_t *ptr;
917             c->buffer_ptr += len;
918             ptr = c->buffer_ptr;
919             if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
920                 (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
921                 /* request found : parse it and reply */
922                 if (c->state == HTTPSTATE_WAIT_REQUEST) {
923                     ret = http_parse_request(c);
924                 } else {
925                     ret = rtsp_parse_request(c);
926                 }
927                 if (ret < 0)
928                     return -1;
929             } else if (ptr >= c->buffer_end) {
930                 /* request too long: cannot do anything */
931                 return -1;
932             } else goto read_loop;
933         }
934         break;
935
936     case HTTPSTATE_SEND_HEADER:
937         if (c->poll_entry->revents & (POLLERR | POLLHUP))
938             return -1;
939
940         /* no need to write if no events */
941         if (!(c->poll_entry->revents & POLLOUT))
942             return 0;
943         len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
944         if (len < 0) {
945             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
946                 ff_neterrno() != FF_NETERROR(EINTR)) {
947                 /* error : close connection */
948                 av_freep(&c->pb_buffer);
949                 return -1;
950             }
951         } else {
952             c->buffer_ptr += len;
953             if (c->stream)
954                 c->stream->bytes_served += len;
955             c->data_count += len;
956             if (c->buffer_ptr >= c->buffer_end) {
957                 av_freep(&c->pb_buffer);
958                 /* if error, exit */
959                 if (c->http_error)
960                     return -1;
961                 /* all the buffer was sent : synchronize to the incoming stream */
962                 c->state = HTTPSTATE_SEND_DATA_HEADER;
963                 c->buffer_ptr = c->buffer_end = c->buffer;
964             }
965         }
966         break;
967
968     case HTTPSTATE_SEND_DATA:
969     case HTTPSTATE_SEND_DATA_HEADER:
970     case HTTPSTATE_SEND_DATA_TRAILER:
971         /* for packetized output, we consider we can always write (the
972            input streams sets the speed). It may be better to verify
973            that we do not rely too much on the kernel queues */
974         if (!c->is_packetized) {
975             if (c->poll_entry->revents & (POLLERR | POLLHUP))
976                 return -1;
977
978             /* no need to read if no events */
979             if (!(c->poll_entry->revents & POLLOUT))
980                 return 0;
981         }
982         if (http_send_data(c) < 0)
983             return -1;
984         /* close connection if trailer sent */
985         if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
986             return -1;
987         break;
988     case HTTPSTATE_RECEIVE_DATA:
989         /* no need to read if no events */
990         if (c->poll_entry->revents & (POLLERR | POLLHUP))
991             return -1;
992         if (!(c->poll_entry->revents & POLLIN))
993             return 0;
994         if (http_receive_data(c) < 0)
995             return -1;
996         break;
997     case HTTPSTATE_WAIT_FEED:
998         /* no need to read if no events */
999         if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1000             return -1;
1001
1002         /* nothing to do, we'll be waken up by incoming feed packets */
1003         break;
1004
1005     case RTSPSTATE_SEND_REPLY:
1006         if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1007             av_freep(&c->pb_buffer);
1008             return -1;
1009         }
1010         /* no need to write if no events */
1011         if (!(c->poll_entry->revents & POLLOUT))
1012             return 0;
1013         len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1014         if (len < 0) {
1015             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
1016                 ff_neterrno() != FF_NETERROR(EINTR)) {
1017                 /* error : close connection */
1018                 av_freep(&c->pb_buffer);
1019                 return -1;
1020             }
1021         } else {
1022             c->buffer_ptr += len;
1023             c->data_count += len;
1024             if (c->buffer_ptr >= c->buffer_end) {
1025                 /* all the buffer was sent : wait for a new request */
1026                 av_freep(&c->pb_buffer);
1027                 start_wait_request(c, 1);
1028             }
1029         }
1030         break;
1031     case RTSPSTATE_SEND_PACKET:
1032         if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1033             av_freep(&c->packet_buffer);
1034             return -1;
1035         }
1036         /* no need to write if no events */
1037         if (!(c->poll_entry->revents & POLLOUT))
1038             return 0;
1039         len = send(c->fd, c->packet_buffer_ptr,
1040                     c->packet_buffer_end - c->packet_buffer_ptr, 0);
1041         if (len < 0) {
1042             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
1043                 ff_neterrno() != FF_NETERROR(EINTR)) {
1044                 /* error : close connection */
1045                 av_freep(&c->packet_buffer);
1046                 return -1;
1047             }
1048         } else {
1049             c->packet_buffer_ptr += len;
1050             if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1051                 /* all the buffer was sent : wait for a new request */
1052                 av_freep(&c->packet_buffer);
1053                 c->state = RTSPSTATE_WAIT_REQUEST;
1054             }
1055         }
1056         break;
1057     case HTTPSTATE_READY:
1058         /* nothing to do */
1059         break;
1060     default:
1061         return -1;
1062     }
1063     return 0;
1064 }
1065
1066 static int extract_rates(char *rates, int ratelen, const char *request)
1067 {
1068     const char *p;
1069
1070     for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1071         if (strncasecmp(p, "Pragma:", 7) == 0) {
1072             const char *q = p + 7;
1073
1074             while (*q && *q != '\n' && isspace(*q))
1075                 q++;
1076
1077             if (strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1078                 int stream_no;
1079                 int rate_no;
1080
1081                 q += 20;
1082
1083                 memset(rates, 0xff, ratelen);
1084
1085                 while (1) {
1086                     while (*q && *q != '\n' && *q != ':')
1087                         q++;
1088
1089                     if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1090                         break;
1091
1092                     stream_no--;
1093                     if (stream_no < ratelen && stream_no >= 0)
1094                         rates[stream_no] = rate_no;
1095
1096                     while (*q && *q != '\n' && !isspace(*q))
1097                         q++;
1098                 }
1099
1100                 return 1;
1101             }
1102         }
1103         p = strchr(p, '\n');
1104         if (!p)
1105             break;
1106
1107         p++;
1108     }
1109
1110     return 0;
1111 }
1112
1113 static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1114 {
1115     int i;
1116     int best_bitrate = 100000000;
1117     int best = -1;
1118
1119     for (i = 0; i < feed->nb_streams; i++) {
1120         AVCodecContext *feed_codec = feed->streams[i]->codec;
1121
1122         if (feed_codec->codec_id != codec->codec_id ||
1123             feed_codec->sample_rate != codec->sample_rate ||
1124             feed_codec->width != codec->width ||
1125             feed_codec->height != codec->height)
1126             continue;
1127
1128         /* Potential stream */
1129
1130         /* We want the fastest stream less than bit_rate, or the slowest
1131          * faster than bit_rate
1132          */
1133
1134         if (feed_codec->bit_rate <= bit_rate) {
1135             if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1136                 best_bitrate = feed_codec->bit_rate;
1137                 best = i;
1138             }
1139         } else {
1140             if (feed_codec->bit_rate < best_bitrate) {
1141                 best_bitrate = feed_codec->bit_rate;
1142                 best = i;
1143             }
1144         }
1145     }
1146
1147     return best;
1148 }
1149
1150 static int modify_current_stream(HTTPContext *c, char *rates)
1151 {
1152     int i;
1153     FFStream *req = c->stream;
1154     int action_required = 0;
1155
1156     /* Not much we can do for a feed */
1157     if (!req->feed)
1158         return 0;
1159
1160     for (i = 0; i < req->nb_streams; i++) {
1161         AVCodecContext *codec = req->streams[i]->codec;
1162
1163         switch(rates[i]) {
1164             case 0:
1165                 c->switch_feed_streams[i] = req->feed_streams[i];
1166                 break;
1167             case 1:
1168                 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1169                 break;
1170             case 2:
1171                 /* Wants off or slow */
1172                 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1173 #ifdef WANTS_OFF
1174                 /* This doesn't work well when it turns off the only stream! */
1175                 c->switch_feed_streams[i] = -2;
1176                 c->feed_streams[i] = -2;
1177 #endif
1178                 break;
1179         }
1180
1181         if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1182             action_required = 1;
1183     }
1184
1185     return action_required;
1186 }
1187
1188
1189 static void do_switch_stream(HTTPContext *c, int i)
1190 {
1191     if (c->switch_feed_streams[i] >= 0) {
1192 #ifdef PHILIP
1193         c->feed_streams[i] = c->switch_feed_streams[i];
1194 #endif
1195
1196         /* Now update the stream */
1197     }
1198     c->switch_feed_streams[i] = -1;
1199 }
1200
1201 /* XXX: factorize in utils.c ? */
1202 /* XXX: take care with different space meaning */
1203 static void skip_spaces(const char **pp)
1204 {
1205     const char *p;
1206     p = *pp;
1207     while (*p == ' ' || *p == '\t')
1208         p++;
1209     *pp = p;
1210 }
1211
1212 static void get_word(char *buf, int buf_size, const char **pp)
1213 {
1214     const char *p;
1215     char *q;
1216
1217     p = *pp;
1218     skip_spaces(&p);
1219     q = buf;
1220     while (!isspace(*p) && *p != '\0') {
1221         if ((q - buf) < buf_size - 1)
1222             *q++ = *p;
1223         p++;
1224     }
1225     if (buf_size > 0)
1226         *q = '\0';
1227     *pp = p;
1228 }
1229
1230 static void get_arg(char *buf, int buf_size, const char **pp)
1231 {
1232     const char *p;
1233     char *q;
1234     int quote;
1235
1236     p = *pp;
1237     while (isspace(*p)) p++;
1238     q = buf;
1239     quote = 0;
1240     if (*p == '\"' || *p == '\'')
1241         quote = *p++;
1242     for(;;) {
1243         if (quote) {
1244             if (*p == quote)
1245                 break;
1246         } else {
1247             if (isspace(*p))
1248                 break;
1249         }
1250         if (*p == '\0')
1251             break;
1252         if ((q - buf) < buf_size - 1)
1253             *q++ = *p;
1254         p++;
1255     }
1256     *q = '\0';
1257     if (quote && *p == quote)
1258         p++;
1259     *pp = p;
1260 }
1261
1262 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1263                          const char *p, const char *filename, int line_num)
1264 {
1265     char arg[1024];
1266     IPAddressACL acl;
1267     int errors = 0;
1268
1269     get_arg(arg, sizeof(arg), &p);
1270     if (strcasecmp(arg, "allow") == 0)
1271         acl.action = IP_ALLOW;
1272     else if (strcasecmp(arg, "deny") == 0)
1273         acl.action = IP_DENY;
1274     else {
1275         fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1276                 filename, line_num, arg);
1277         errors++;
1278     }
1279
1280     get_arg(arg, sizeof(arg), &p);
1281
1282     if (resolve_host(&acl.first, arg) != 0) {
1283         fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1284                 filename, line_num, arg);
1285         errors++;
1286     } else
1287         acl.last = acl.first;
1288
1289     get_arg(arg, sizeof(arg), &p);
1290
1291     if (arg[0]) {
1292         if (resolve_host(&acl.last, arg) != 0) {
1293             fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1294                     filename, line_num, arg);
1295             errors++;
1296         }
1297     }
1298
1299     if (!errors) {
1300         IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1301         IPAddressACL **naclp = 0;
1302
1303         acl.next = 0;
1304         *nacl = acl;
1305
1306         if (stream)
1307             naclp = &stream->acl;
1308         else if (feed)
1309             naclp = &feed->acl;
1310         else if (ext_acl)
1311             naclp = &ext_acl;
1312         else {
1313             fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1314                     filename, line_num);
1315             errors++;
1316         }
1317
1318         if (naclp) {
1319             while (*naclp)
1320                 naclp = &(*naclp)->next;
1321
1322             *naclp = nacl;
1323         }
1324     }
1325 }
1326
1327
1328 static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
1329 {
1330     FILE* f;
1331     char line[1024];
1332     char  cmd[1024];
1333     IPAddressACL *acl = NULL;
1334     int line_num = 0;
1335     const char *p;
1336
1337     f = fopen(stream->dynamic_acl, "r");
1338     if (!f) {
1339         perror(stream->dynamic_acl);
1340         return NULL;
1341     }
1342
1343     acl = av_mallocz(sizeof(IPAddressACL));
1344
1345     /* Build ACL */
1346     for(;;) {
1347         if (fgets(line, sizeof(line), f) == NULL)
1348             break;
1349         line_num++;
1350         p = line;
1351         while (isspace(*p))
1352             p++;
1353         if (*p == '\0' || *p == '#')
1354             continue;
1355         get_arg(cmd, sizeof(cmd), &p);
1356
1357         if (!strcasecmp(cmd, "ACL"))
1358             parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1359     }
1360     fclose(f);
1361     return acl;
1362 }
1363
1364
1365 static void free_acl_list(IPAddressACL *in_acl)
1366 {
1367     IPAddressACL *pacl,*pacl2;
1368
1369     pacl = in_acl;
1370     while(pacl) {
1371         pacl2 = pacl;
1372         pacl = pacl->next;
1373         av_freep(pacl2);
1374     }
1375 }
1376
1377 static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
1378 {
1379     enum IPAddressAction last_action = IP_DENY;
1380     IPAddressACL *acl;
1381     struct in_addr *src = &c->from_addr.sin_addr;
1382     unsigned long src_addr = src->s_addr;
1383
1384     for (acl = in_acl; acl; acl = acl->next) {
1385         if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1386             return (acl->action == IP_ALLOW) ? 1 : 0;
1387         last_action = acl->action;
1388     }
1389
1390     /* Nothing matched, so return not the last action */
1391     return (last_action == IP_DENY) ? 1 : 0;
1392 }
1393
1394 static int validate_acl(FFStream *stream, HTTPContext *c)
1395 {
1396     int ret = 0;
1397     IPAddressACL *acl;
1398
1399
1400     /* if stream->acl is null validate_acl_list will return 1 */
1401     ret = validate_acl_list(stream->acl, c);
1402
1403     if (stream->dynamic_acl[0]) {
1404         acl = parse_dynamic_acl(stream, c);
1405
1406         ret = validate_acl_list(acl, c);
1407
1408         free_acl_list(acl);
1409     }
1410
1411     return ret;
1412 }
1413
1414 /* compute the real filename of a file by matching it without its
1415    extensions to all the stream filenames */
1416 static void compute_real_filename(char *filename, int max_size)
1417 {
1418     char file1[1024];
1419     char file2[1024];
1420     char *p;
1421     FFStream *stream;
1422
1423     /* compute filename by matching without the file extensions */
1424     av_strlcpy(file1, filename, sizeof(file1));
1425     p = strrchr(file1, '.');
1426     if (p)
1427         *p = '\0';
1428     for(stream = first_stream; stream != NULL; stream = stream->next) {
1429         av_strlcpy(file2, stream->filename, sizeof(file2));
1430         p = strrchr(file2, '.');
1431         if (p)
1432             *p = '\0';
1433         if (!strcmp(file1, file2)) {
1434             av_strlcpy(filename, stream->filename, max_size);
1435             break;
1436         }
1437     }
1438 }
1439
1440 enum RedirType {
1441     REDIR_NONE,
1442     REDIR_ASX,
1443     REDIR_RAM,
1444     REDIR_ASF,
1445     REDIR_RTSP,
1446     REDIR_SDP,
1447 };
1448
1449 /* parse http request and prepare header */
1450 static int http_parse_request(HTTPContext *c)
1451 {
1452     char *p;
1453     enum RedirType redir_type;
1454     char cmd[32];
1455     char info[1024], filename[1024];
1456     char url[1024], *q;
1457     char protocol[32];
1458     char msg[1024];
1459     const char *mime_type;
1460     FFStream *stream;
1461     int i;
1462     char ratebuf[32];
1463     char *useragent = 0;
1464
1465     p = c->buffer;
1466     get_word(cmd, sizeof(cmd), (const char **)&p);
1467     av_strlcpy(c->method, cmd, sizeof(c->method));
1468
1469     if (!strcmp(cmd, "GET"))
1470         c->post = 0;
1471     else if (!strcmp(cmd, "POST"))
1472         c->post = 1;
1473     else
1474         return -1;
1475
1476     get_word(url, sizeof(url), (const char **)&p);
1477     av_strlcpy(c->url, url, sizeof(c->url));
1478
1479     get_word(protocol, sizeof(protocol), (const char **)&p);
1480     if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1481         return -1;
1482
1483     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1484
1485     if (ffserver_debug)
1486         http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1487
1488     /* find the filename and the optional info string in the request */
1489     p = strchr(url, '?');
1490     if (p) {
1491         av_strlcpy(info, p, sizeof(info));
1492         *p = '\0';
1493     } else
1494         info[0] = '\0';
1495
1496     av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1497
1498     for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1499         if (strncasecmp(p, "User-Agent:", 11) == 0) {
1500             useragent = p + 11;
1501             if (*useragent && *useragent != '\n' && isspace(*useragent))
1502                 useragent++;
1503             break;
1504         }
1505         p = strchr(p, '\n');
1506         if (!p)
1507             break;
1508
1509         p++;
1510     }
1511
1512     redir_type = REDIR_NONE;
1513     if (av_match_ext(filename, "asx")) {
1514         redir_type = REDIR_ASX;
1515         filename[strlen(filename)-1] = 'f';
1516     } else if (av_match_ext(filename, "asf") &&
1517         (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1518         /* if this isn't WMP or lookalike, return the redirector file */
1519         redir_type = REDIR_ASF;
1520     } else if (av_match_ext(filename, "rpm,ram")) {
1521         redir_type = REDIR_RAM;
1522         strcpy(filename + strlen(filename)-2, "m");
1523     } else if (av_match_ext(filename, "rtsp")) {
1524         redir_type = REDIR_RTSP;
1525         compute_real_filename(filename, sizeof(filename) - 1);
1526     } else if (av_match_ext(filename, "sdp")) {
1527         redir_type = REDIR_SDP;
1528         compute_real_filename(filename, sizeof(filename) - 1);
1529     }
1530
1531     // "redirect" / request to index.html
1532     if (!strlen(filename))
1533         av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1534
1535     stream = first_stream;
1536     while (stream != NULL) {
1537         if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1538             break;
1539         stream = stream->next;
1540     }
1541     if (stream == NULL) {
1542         snprintf(msg, sizeof(msg), "File '%s' not found", url);
1543         http_log("File '%s' not found\n", url);
1544         goto send_error;
1545     }
1546
1547     c->stream = stream;
1548     memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1549     memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1550
1551     if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1552         c->http_error = 301;
1553         q = c->buffer;
1554         q += snprintf(q, c->buffer_size,
1555                       "HTTP/1.0 301 Moved\r\n"
1556                       "Location: %s\r\n"
1557                       "Content-type: text/html\r\n"
1558                       "\r\n"
1559                       "<html><head><title>Moved</title></head><body>\r\n"
1560                       "You should be <a href=\"%s\">redirected</a>.\r\n"
1561                       "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1562         /* prepare output buffer */
1563         c->buffer_ptr = c->buffer;
1564         c->buffer_end = q;
1565         c->state = HTTPSTATE_SEND_HEADER;
1566         return 0;
1567     }
1568
1569     /* If this is WMP, get the rate information */
1570     if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1571         if (modify_current_stream(c, ratebuf)) {
1572             for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1573                 if (c->switch_feed_streams[i] >= 0)
1574                     do_switch_stream(c, i);
1575             }
1576         }
1577     }
1578
1579     if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1580         current_bandwidth += stream->bandwidth;
1581
1582     /* If already streaming this feed, do not let start another feeder. */
1583     if (stream->feed_opened) {
1584         snprintf(msg, sizeof(msg), "This feed is already being received.");
1585         http_log("Feed '%s' already being received\n", stream->feed_filename);
1586         goto send_error;
1587     }
1588
1589     if (c->post == 0 && max_bandwidth < current_bandwidth) {
1590         c->http_error = 200;
1591         q = c->buffer;
1592         q += snprintf(q, c->buffer_size,
1593                       "HTTP/1.0 200 Server too busy\r\n"
1594                       "Content-type: text/html\r\n"
1595                       "\r\n"
1596                       "<html><head><title>Too busy</title></head><body>\r\n"
1597                       "<p>The server is too busy to serve your request at this time.</p>\r\n"
1598                       "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1599                       "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1600                       "</body></html>\r\n", current_bandwidth, max_bandwidth);
1601         /* prepare output buffer */
1602         c->buffer_ptr = c->buffer;
1603         c->buffer_end = q;
1604         c->state = HTTPSTATE_SEND_HEADER;
1605         return 0;
1606     }
1607
1608     if (redir_type != REDIR_NONE) {
1609         char *hostinfo = 0;
1610
1611         for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1612             if (strncasecmp(p, "Host:", 5) == 0) {
1613                 hostinfo = p + 5;
1614                 break;
1615             }
1616             p = strchr(p, '\n');
1617             if (!p)
1618                 break;
1619
1620             p++;
1621         }
1622
1623         if (hostinfo) {
1624             char *eoh;
1625             char hostbuf[260];
1626
1627             while (isspace(*hostinfo))
1628                 hostinfo++;
1629
1630             eoh = strchr(hostinfo, '\n');
1631             if (eoh) {
1632                 if (eoh[-1] == '\r')
1633                     eoh--;
1634
1635                 if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1636                     memcpy(hostbuf, hostinfo, eoh - hostinfo);
1637                     hostbuf[eoh - hostinfo] = 0;
1638
1639                     c->http_error = 200;
1640                     q = c->buffer;
1641                     switch(redir_type) {
1642                     case REDIR_ASX:
1643                         q += snprintf(q, c->buffer_size,
1644                                       "HTTP/1.0 200 ASX Follows\r\n"
1645                                       "Content-type: video/x-ms-asf\r\n"
1646                                       "\r\n"
1647                                       "<ASX Version=\"3\">\r\n"
1648                                       //"<!-- Autogenerated by ffserver -->\r\n"
1649                                       "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1650                                       "</ASX>\r\n", hostbuf, filename, info);
1651                         break;
1652                     case REDIR_RAM:
1653                         q += snprintf(q, c->buffer_size,
1654                                       "HTTP/1.0 200 RAM Follows\r\n"
1655                                       "Content-type: audio/x-pn-realaudio\r\n"
1656                                       "\r\n"
1657                                       "# Autogenerated by ffserver\r\n"
1658                                       "http://%s/%s%s\r\n", hostbuf, filename, info);
1659                         break;
1660                     case REDIR_ASF:
1661                         q += snprintf(q, c->buffer_size,
1662                                       "HTTP/1.0 200 ASF Redirect follows\r\n"
1663                                       "Content-type: video/x-ms-asf\r\n"
1664                                       "\r\n"
1665                                       "[Reference]\r\n"
1666                                       "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1667                         break;
1668                     case REDIR_RTSP:
1669                         {
1670                             char hostname[256], *p;
1671                             /* extract only hostname */
1672                             av_strlcpy(hostname, hostbuf, sizeof(hostname));
1673                             p = strrchr(hostname, ':');
1674                             if (p)
1675                                 *p = '\0';
1676                             q += snprintf(q, c->buffer_size,
1677                                           "HTTP/1.0 200 RTSP Redirect follows\r\n"
1678                                           /* XXX: incorrect mime type ? */
1679                                           "Content-type: application/x-rtsp\r\n"
1680                                           "\r\n"
1681                                           "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1682                         }
1683                         break;
1684                     case REDIR_SDP:
1685                         {
1686                             uint8_t *sdp_data;
1687                             int sdp_data_size, len;
1688                             struct sockaddr_in my_addr;
1689
1690                             q += snprintf(q, c->buffer_size,
1691                                           "HTTP/1.0 200 OK\r\n"
1692                                           "Content-type: application/sdp\r\n"
1693                                           "\r\n");
1694
1695                             len = sizeof(my_addr);
1696                             getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1697
1698                             /* XXX: should use a dynamic buffer */
1699                             sdp_data_size = prepare_sdp_description(stream,
1700                                                                     &sdp_data,
1701                                                                     my_addr.sin_addr);
1702                             if (sdp_data_size > 0) {
1703                                 memcpy(q, sdp_data, sdp_data_size);
1704                                 q += sdp_data_size;
1705                                 *q = '\0';
1706                                 av_free(sdp_data);
1707                             }
1708                         }
1709                         break;
1710                     default:
1711                         abort();
1712                         break;
1713                     }
1714
1715                     /* prepare output buffer */
1716                     c->buffer_ptr = c->buffer;
1717                     c->buffer_end = q;
1718                     c->state = HTTPSTATE_SEND_HEADER;
1719                     return 0;
1720                 }
1721             }
1722         }
1723
1724         snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1725         goto send_error;
1726     }
1727
1728     stream->conns_served++;
1729
1730     /* XXX: add there authenticate and IP match */
1731
1732     if (c->post) {
1733         /* if post, it means a feed is being sent */
1734         if (!stream->is_feed) {
1735             /* However it might be a status report from WMP! Let us log the
1736              * data as it might come in handy one day. */
1737             char *logline = 0;
1738             int client_id = 0;
1739
1740             for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1741                 if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1742                     logline = p;
1743                     break;
1744                 }
1745                 if (strncasecmp(p, "Pragma: client-id=", 18) == 0)
1746                     client_id = strtol(p + 18, 0, 10);
1747                 p = strchr(p, '\n');
1748                 if (!p)
1749                     break;
1750
1751                 p++;
1752             }
1753
1754             if (logline) {
1755                 char *eol = strchr(logline, '\n');
1756
1757                 logline += 17;
1758
1759                 if (eol) {
1760                     if (eol[-1] == '\r')
1761                         eol--;
1762                     http_log("%.*s\n", (int) (eol - logline), logline);
1763                     c->suppress_log = 1;
1764                 }
1765             }
1766
1767 #ifdef DEBUG_WMP
1768             http_log("\nGot request:\n%s\n", c->buffer);
1769 #endif
1770
1771             if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1772                 HTTPContext *wmpc;
1773
1774                 /* Now we have to find the client_id */
1775                 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1776                     if (wmpc->wmp_client_id == client_id)
1777                         break;
1778                 }
1779
1780                 if (wmpc && modify_current_stream(wmpc, ratebuf))
1781                     wmpc->switch_pending = 1;
1782             }
1783
1784             snprintf(msg, sizeof(msg), "POST command not handled");
1785             c->stream = 0;
1786             goto send_error;
1787         }
1788         if (http_start_receive_data(c) < 0) {
1789             snprintf(msg, sizeof(msg), "could not open feed");
1790             goto send_error;
1791         }
1792         c->http_error = 0;
1793         c->state = HTTPSTATE_RECEIVE_DATA;
1794         return 0;
1795     }
1796
1797 #ifdef DEBUG_WMP
1798     if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1799         http_log("\nGot request:\n%s\n", c->buffer);
1800 #endif
1801
1802     if (c->stream->stream_type == STREAM_TYPE_STATUS)
1803         goto send_status;
1804
1805     /* open input stream */
1806     if (open_input_stream(c, info) < 0) {
1807         snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1808         goto send_error;
1809     }
1810
1811     /* prepare http header */
1812     q = c->buffer;
1813     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1814     mime_type = c->stream->fmt->mime_type;
1815     if (!mime_type)
1816         mime_type = "application/x-octet-stream";
1817     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
1818
1819     /* for asf, we need extra headers */
1820     if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1821         /* Need to allocate a client id */
1822
1823         c->wmp_client_id = av_lfg_get(&random_state);
1824
1825         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);
1826     }
1827     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1828     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1829
1830     /* prepare output buffer */
1831     c->http_error = 0;
1832     c->buffer_ptr = c->buffer;
1833     c->buffer_end = q;
1834     c->state = HTTPSTATE_SEND_HEADER;
1835     return 0;
1836  send_error:
1837     c->http_error = 404;
1838     q = c->buffer;
1839     q += snprintf(q, c->buffer_size,
1840                   "HTTP/1.0 404 Not Found\r\n"
1841                   "Content-type: text/html\r\n"
1842                   "\r\n"
1843                   "<html>\n"
1844                   "<head><title>404 Not Found</title></head>\n"
1845                   "<body>%s</body>\n"
1846                   "</html>\n", msg);
1847     /* prepare output buffer */
1848     c->buffer_ptr = c->buffer;
1849     c->buffer_end = q;
1850     c->state = HTTPSTATE_SEND_HEADER;
1851     return 0;
1852  send_status:
1853     compute_status(c);
1854     c->http_error = 200; /* horrible : we use this value to avoid
1855                             going to the send data state */
1856     c->state = HTTPSTATE_SEND_HEADER;
1857     return 0;
1858 }
1859
1860 static void fmt_bytecount(ByteIOContext *pb, int64_t count)
1861 {
1862     static const char *suffix = " kMGTP";
1863     const char *s;
1864
1865     for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1866
1867     url_fprintf(pb, "%"PRId64"%c", count, *s);
1868 }
1869
1870 static void compute_status(HTTPContext *c)
1871 {
1872     HTTPContext *c1;
1873     FFStream *stream;
1874     char *p;
1875     time_t ti;
1876     int i, len;
1877     ByteIOContext *pb;
1878
1879     if (url_open_dyn_buf(&pb) < 0) {
1880         /* XXX: return an error ? */
1881         c->buffer_ptr = c->buffer;
1882         c->buffer_end = c->buffer;
1883         return;
1884     }
1885
1886     url_fprintf(pb, "HTTP/1.0 200 OK\r\n");
1887     url_fprintf(pb, "Content-type: %s\r\n", "text/html");
1888     url_fprintf(pb, "Pragma: no-cache\r\n");
1889     url_fprintf(pb, "\r\n");
1890
1891     url_fprintf(pb, "<html><head><title>%s Status</title>\n", program_name);
1892     if (c->stream->feed_filename[0])
1893         url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1894     url_fprintf(pb, "</head>\n<body>");
1895     url_fprintf(pb, "<h1>%s Status</h1>\n", program_name);
1896     /* format status */
1897     url_fprintf(pb, "<h2>Available Streams</h2>\n");
1898     url_fprintf(pb, "<table cellspacing=0 cellpadding=4>\n");
1899     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");
1900     stream = first_stream;
1901     while (stream != NULL) {
1902         char sfilename[1024];
1903         char *eosf;
1904
1905         if (stream->feed != stream) {
1906             av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1907             eosf = sfilename + strlen(sfilename);
1908             if (eosf - sfilename >= 4) {
1909                 if (strcmp(eosf - 4, ".asf") == 0)
1910                     strcpy(eosf - 4, ".asx");
1911                 else if (strcmp(eosf - 3, ".rm") == 0)
1912                     strcpy(eosf - 3, ".ram");
1913                 else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1914                     /* generate a sample RTSP director if
1915                        unicast. Generate an SDP redirector if
1916                        multicast */
1917                     eosf = strrchr(sfilename, '.');
1918                     if (!eosf)
1919                         eosf = sfilename + strlen(sfilename);
1920                     if (stream->is_multicast)
1921                         strcpy(eosf, ".sdp");
1922                     else
1923                         strcpy(eosf, ".rtsp");
1924                 }
1925             }
1926
1927             url_fprintf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1928                          sfilename, stream->filename);
1929             url_fprintf(pb, "<td align=right> %d <td align=right> ",
1930                         stream->conns_served);
1931             fmt_bytecount(pb, stream->bytes_served);
1932             switch(stream->stream_type) {
1933             case STREAM_TYPE_LIVE: {
1934                     int audio_bit_rate = 0;
1935                     int video_bit_rate = 0;
1936                     const char *audio_codec_name = "";
1937                     const char *video_codec_name = "";
1938                     const char *audio_codec_name_extra = "";
1939                     const char *video_codec_name_extra = "";
1940
1941                     for(i=0;i<stream->nb_streams;i++) {
1942                         AVStream *st = stream->streams[i];
1943                         AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1944                         switch(st->codec->codec_type) {
1945                         case AVMEDIA_TYPE_AUDIO:
1946                             audio_bit_rate += st->codec->bit_rate;
1947                             if (codec) {
1948                                 if (*audio_codec_name)
1949                                     audio_codec_name_extra = "...";
1950                                 audio_codec_name = codec->name;
1951                             }
1952                             break;
1953                         case AVMEDIA_TYPE_VIDEO:
1954                             video_bit_rate += st->codec->bit_rate;
1955                             if (codec) {
1956                                 if (*video_codec_name)
1957                                     video_codec_name_extra = "...";
1958                                 video_codec_name = codec->name;
1959                             }
1960                             break;
1961                         case AVMEDIA_TYPE_DATA:
1962                             video_bit_rate += st->codec->bit_rate;
1963                             break;
1964                         default:
1965                             abort();
1966                         }
1967                     }
1968                     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",
1969                                  stream->fmt->name,
1970                                  stream->bandwidth,
1971                                  video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1972                                  audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
1973                     if (stream->feed)
1974                         url_fprintf(pb, "<td>%s", stream->feed->filename);
1975                     else
1976                         url_fprintf(pb, "<td>%s", stream->feed_filename);
1977                     url_fprintf(pb, "\n");
1978                 }
1979                 break;
1980             default:
1981                 url_fprintf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
1982                 break;
1983             }
1984         }
1985         stream = stream->next;
1986     }
1987     url_fprintf(pb, "</table>\n");
1988
1989     stream = first_stream;
1990     while (stream != NULL) {
1991         if (stream->feed == stream) {
1992             url_fprintf(pb, "<h2>Feed %s</h2>", stream->filename);
1993             if (stream->pid) {
1994                 url_fprintf(pb, "Running as pid %d.\n", stream->pid);
1995
1996 #if defined(linux) && !defined(CONFIG_NOCUTILS)
1997                 {
1998                     FILE *pid_stat;
1999                     char ps_cmd[64];
2000
2001                     /* This is somewhat linux specific I guess */
2002                     snprintf(ps_cmd, sizeof(ps_cmd),
2003                              "ps -o \"%%cpu,cputime\" --no-headers %d",
2004                              stream->pid);
2005
2006                     pid_stat = popen(ps_cmd, "r");
2007                     if (pid_stat) {
2008                         char cpuperc[10];
2009                         char cpuused[64];
2010
2011                         if (fscanf(pid_stat, "%10s %64s", cpuperc,
2012                                    cpuused) == 2) {
2013                             url_fprintf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2014                                          cpuperc, cpuused);
2015                         }
2016                         fclose(pid_stat);
2017                     }
2018                 }
2019 #endif
2020
2021                 url_fprintf(pb, "<p>");
2022             }
2023             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");
2024
2025             for (i = 0; i < stream->nb_streams; i++) {
2026                 AVStream *st = stream->streams[i];
2027                 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2028                 const char *type = "unknown";
2029                 char parameters[64];
2030
2031                 parameters[0] = 0;
2032
2033                 switch(st->codec->codec_type) {
2034                 case AVMEDIA_TYPE_AUDIO:
2035                     type = "audio";
2036                     snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2037                     break;
2038                 case AVMEDIA_TYPE_VIDEO:
2039                     type = "video";
2040                     snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2041                                 st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2042                     break;
2043                 default:
2044                     abort();
2045                 }
2046                 url_fprintf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2047                         i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2048             }
2049             url_fprintf(pb, "</table>\n");
2050
2051         }
2052         stream = stream->next;
2053     }
2054
2055     /* connection status */
2056     url_fprintf(pb, "<h2>Connection Status</h2>\n");
2057
2058     url_fprintf(pb, "Number of connections: %d / %d<br>\n",
2059                  nb_connections, nb_max_connections);
2060
2061     url_fprintf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2062                  current_bandwidth, max_bandwidth);
2063
2064     url_fprintf(pb, "<table>\n");
2065     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");
2066     c1 = first_http_ctx;
2067     i = 0;
2068     while (c1 != NULL) {
2069         int bitrate;
2070         int j;
2071
2072         bitrate = 0;
2073         if (c1->stream) {
2074             for (j = 0; j < c1->stream->nb_streams; j++) {
2075                 if (!c1->stream->feed)
2076                     bitrate += c1->stream->streams[j]->codec->bit_rate;
2077                 else if (c1->feed_streams[j] >= 0)
2078                     bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2079             }
2080         }
2081
2082         i++;
2083         p = inet_ntoa(c1->from_addr.sin_addr);
2084         url_fprintf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2085                     i,
2086                     c1->stream ? c1->stream->filename : "",
2087                     c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2088                     p,
2089                     c1->protocol,
2090                     http_state[c1->state]);
2091         fmt_bytecount(pb, bitrate);
2092         url_fprintf(pb, "<td align=right>");
2093         fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2094         url_fprintf(pb, "<td align=right>");
2095         fmt_bytecount(pb, c1->data_count);
2096         url_fprintf(pb, "\n");
2097         c1 = c1->next;
2098     }
2099     url_fprintf(pb, "</table>\n");
2100
2101     /* date */
2102     ti = time(NULL);
2103     p = ctime(&ti);
2104     url_fprintf(pb, "<hr size=1 noshade>Generated at %s", p);
2105     url_fprintf(pb, "</body>\n</html>\n");
2106
2107     len = url_close_dyn_buf(pb, &c->pb_buffer);
2108     c->buffer_ptr = c->pb_buffer;
2109     c->buffer_end = c->pb_buffer + len;
2110 }
2111
2112 /* check if the parser needs to be opened for stream i */
2113 static void open_parser(AVFormatContext *s, int i)
2114 {
2115     AVStream *st = s->streams[i];
2116     AVCodec *codec;
2117
2118     if (!st->codec->codec) {
2119         codec = avcodec_find_decoder(st->codec->codec_id);
2120         if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
2121             st->codec->parse_only = 1;
2122             if (avcodec_open(st->codec, codec) < 0)
2123                 st->codec->parse_only = 0;
2124         }
2125     }
2126 }
2127
2128 static int open_input_stream(HTTPContext *c, const char *info)
2129 {
2130     char buf[128];
2131     char input_filename[1024];
2132     AVFormatContext *s;
2133     int buf_size, i, ret;
2134     int64_t stream_pos;
2135
2136     /* find file name */
2137     if (c->stream->feed) {
2138         strcpy(input_filename, c->stream->feed->feed_filename);
2139         buf_size = FFM_PACKET_SIZE;
2140         /* compute position (absolute time) */
2141         if (find_info_tag(buf, sizeof(buf), "date", info)) {
2142             stream_pos = parse_date(buf, 0);
2143             if (stream_pos == INT64_MIN)
2144                 return -1;
2145         } else if (find_info_tag(buf, sizeof(buf), "buffer", info)) {
2146             int prebuffer = strtol(buf, 0, 10);
2147             stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2148         } else
2149             stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2150     } else {
2151         strcpy(input_filename, c->stream->feed_filename);
2152         buf_size = 0;
2153         /* compute position (relative time) */
2154         if (find_info_tag(buf, sizeof(buf), "date", info)) {
2155             stream_pos = parse_date(buf, 1);
2156             if (stream_pos == INT64_MIN)
2157                 return -1;
2158         } else
2159             stream_pos = 0;
2160     }
2161     if (input_filename[0] == '\0')
2162         return -1;
2163
2164     /* open stream */
2165     if ((ret = av_open_input_file(&s, input_filename, c->stream->ifmt,
2166                                   buf_size, c->stream->ap_in)) < 0) {
2167         http_log("could not open %s: %d\n", input_filename, ret);
2168         return -1;
2169     }
2170     s->flags |= AVFMT_FLAG_GENPTS;
2171     c->fmt_in = s;
2172     if (strcmp(s->iformat->name, "ffm") && av_find_stream_info(c->fmt_in) < 0) {
2173         http_log("Could not find stream info '%s'\n", input_filename);
2174         av_close_input_file(s);
2175         return -1;
2176     }
2177
2178     /* open each parser */
2179     for(i=0;i<s->nb_streams;i++)
2180         open_parser(s, i);
2181
2182     /* choose stream as clock source (we favorize video stream if
2183        present) for packet sending */
2184     c->pts_stream_index = 0;
2185     for(i=0;i<c->stream->nb_streams;i++) {
2186         if (c->pts_stream_index == 0 &&
2187             c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2188             c->pts_stream_index = i;
2189         }
2190     }
2191
2192 #if 1
2193     if (c->fmt_in->iformat->read_seek)
2194         av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2195 #endif
2196     /* set the start time (needed for maxtime and RTP packet timing) */
2197     c->start_time = cur_time;
2198     c->first_pts = AV_NOPTS_VALUE;
2199     return 0;
2200 }
2201
2202 /* return the server clock (in us) */
2203 static int64_t get_server_clock(HTTPContext *c)
2204 {
2205     /* compute current pts value from system time */
2206     return (cur_time - c->start_time) * 1000;
2207 }
2208
2209 /* return the estimated time at which the current packet must be sent
2210    (in us) */
2211 static int64_t get_packet_send_clock(HTTPContext *c)
2212 {
2213     int bytes_left, bytes_sent, frame_bytes;
2214
2215     frame_bytes = c->cur_frame_bytes;
2216     if (frame_bytes <= 0)
2217         return c->cur_pts;
2218     else {
2219         bytes_left = c->buffer_end - c->buffer_ptr;
2220         bytes_sent = frame_bytes - bytes_left;
2221         return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2222     }
2223 }
2224
2225
2226 static int http_prepare_data(HTTPContext *c)
2227 {
2228     int i, len, ret;
2229     AVFormatContext *ctx;
2230
2231     av_freep(&c->pb_buffer);
2232     switch(c->state) {
2233     case HTTPSTATE_SEND_DATA_HEADER:
2234         memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2235         av_metadata_set2(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2236         av_metadata_set2(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2237         av_metadata_set2(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2238         av_metadata_set2(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2239
2240         for(i=0;i<c->stream->nb_streams;i++) {
2241             AVStream *st;
2242             AVStream *src;
2243             st = av_mallocz(sizeof(AVStream));
2244             c->fmt_ctx.streams[i] = st;
2245             /* if file or feed, then just take streams from FFStream struct */
2246             if (!c->stream->feed ||
2247                 c->stream->feed == c->stream)
2248                 src = c->stream->streams[i];
2249             else
2250                 src = c->stream->feed->streams[c->stream->feed_streams[i]];
2251
2252             *st = *src;
2253             st->priv_data = 0;
2254             st->codec->frame_number = 0; /* XXX: should be done in
2255                                            AVStream, not in codec */
2256         }
2257         /* set output format parameters */
2258         c->fmt_ctx.oformat = c->stream->fmt;
2259         c->fmt_ctx.nb_streams = c->stream->nb_streams;
2260
2261         c->got_key_frame = 0;
2262
2263         /* prepare header and save header data in a stream */
2264         if (url_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2265             /* XXX: potential leak */
2266             return -1;
2267         }
2268         c->fmt_ctx.pb->is_streamed = 1;
2269
2270         /*
2271          * HACK to avoid mpeg ps muxer to spit many underflow errors
2272          * Default value from FFmpeg
2273          * Try to set it use configuration option
2274          */
2275         c->fmt_ctx.preload   = (int)(0.5*AV_TIME_BASE);
2276         c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2277
2278         av_set_parameters(&c->fmt_ctx, NULL);
2279         if (av_write_header(&c->fmt_ctx) < 0) {
2280             http_log("Error writing output header\n");
2281             return -1;
2282         }
2283
2284         len = url_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2285         c->buffer_ptr = c->pb_buffer;
2286         c->buffer_end = c->pb_buffer + len;
2287
2288         c->state = HTTPSTATE_SEND_DATA;
2289         c->last_packet_sent = 0;
2290         break;
2291     case HTTPSTATE_SEND_DATA:
2292         /* find a new packet */
2293         /* read a packet from the input stream */
2294         if (c->stream->feed)
2295             ffm_set_write_index(c->fmt_in,
2296                                 c->stream->feed->feed_write_index,
2297                                 c->stream->feed->feed_size);
2298
2299         if (c->stream->max_time &&
2300             c->stream->max_time + c->start_time - cur_time < 0)
2301             /* We have timed out */
2302             c->state = HTTPSTATE_SEND_DATA_TRAILER;
2303         else {
2304             AVPacket pkt;
2305         redo:
2306             if (av_read_frame(c->fmt_in, &pkt) < 0) {
2307                 if (c->stream->feed && c->stream->feed->feed_opened) {
2308                     /* if coming from feed, it means we reached the end of the
2309                        ffm file, so must wait for more data */
2310                     c->state = HTTPSTATE_WAIT_FEED;
2311                     return 1; /* state changed */
2312                 } else {
2313                     if (c->stream->loop) {
2314                         av_close_input_file(c->fmt_in);
2315                         c->fmt_in = NULL;
2316                         if (open_input_stream(c, "") < 0)
2317                             goto no_loop;
2318                         goto redo;
2319                     } else {
2320                     no_loop:
2321                         /* must send trailer now because eof or error */
2322                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2323                     }
2324                 }
2325             } else {
2326                 int source_index = pkt.stream_index;
2327                 /* update first pts if needed */
2328                 if (c->first_pts == AV_NOPTS_VALUE) {
2329                     c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2330                     c->start_time = cur_time;
2331                 }
2332                 /* send it to the appropriate stream */
2333                 if (c->stream->feed) {
2334                     /* if coming from a feed, select the right stream */
2335                     if (c->switch_pending) {
2336                         c->switch_pending = 0;
2337                         for(i=0;i<c->stream->nb_streams;i++) {
2338                             if (c->switch_feed_streams[i] == pkt.stream_index)
2339                                 if (pkt.flags & AV_PKT_FLAG_KEY)
2340                                     do_switch_stream(c, i);
2341                             if (c->switch_feed_streams[i] >= 0)
2342                                 c->switch_pending = 1;
2343                         }
2344                     }
2345                     for(i=0;i<c->stream->nb_streams;i++) {
2346                         if (c->feed_streams[i] == pkt.stream_index) {
2347                             AVStream *st = c->fmt_in->streams[source_index];
2348                             pkt.stream_index = i;
2349                             if (pkt.flags & AV_PKT_FLAG_KEY &&
2350                                 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2351                                  c->stream->nb_streams == 1))
2352                                 c->got_key_frame = 1;
2353                             if (!c->stream->send_on_key || c->got_key_frame)
2354                                 goto send_it;
2355                         }
2356                     }
2357                 } else {
2358                     AVCodecContext *codec;
2359                     AVStream *ist, *ost;
2360                 send_it:
2361                     ist = c->fmt_in->streams[source_index];
2362                     /* specific handling for RTP: we use several
2363                        output stream (one for each RTP
2364                        connection). XXX: need more abstract handling */
2365                     if (c->is_packetized) {
2366                         /* compute send time and duration */
2367                         c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2368                         if (ist->start_time != AV_NOPTS_VALUE)
2369                             c->cur_pts -= av_rescale_q(ist->start_time, ist->time_base, AV_TIME_BASE_Q);
2370                         c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2371                         /* find RTP context */
2372                         c->packet_stream_index = pkt.stream_index;
2373                         ctx = c->rtp_ctx[c->packet_stream_index];
2374                         if(!ctx) {
2375                             av_free_packet(&pkt);
2376                             break;
2377                         }
2378                         codec = ctx->streams[0]->codec;
2379                         /* only one stream per RTP connection */
2380                         pkt.stream_index = 0;
2381                     } else {
2382                         ctx = &c->fmt_ctx;
2383                         /* Fudge here */
2384                         codec = ctx->streams[pkt.stream_index]->codec;
2385                     }
2386
2387                     if (c->is_packetized) {
2388                         int max_packet_size;
2389                         if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2390                             max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2391                         else
2392                             max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
2393                         ret = url_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2394                     } else {
2395                         ret = url_open_dyn_buf(&ctx->pb);
2396                     }
2397                     if (ret < 0) {
2398                         /* XXX: potential leak */
2399                         return -1;
2400                     }
2401                     ost = ctx->streams[pkt.stream_index];
2402
2403                     ctx->pb->is_streamed = 1;
2404                     if (pkt.dts != AV_NOPTS_VALUE)
2405                         pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2406                     if (pkt.pts != AV_NOPTS_VALUE)
2407                         pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2408                     pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2409                     if (av_write_frame(ctx, &pkt) < 0) {
2410                         http_log("Error writing frame to output\n");
2411                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2412                     }
2413
2414                     len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
2415                     c->cur_frame_bytes = len;
2416                     c->buffer_ptr = c->pb_buffer;
2417                     c->buffer_end = c->pb_buffer + len;
2418
2419                     codec->frame_number++;
2420                     if (len == 0) {
2421                         av_free_packet(&pkt);
2422                         goto redo;
2423                     }
2424                 }
2425                 av_free_packet(&pkt);
2426             }
2427         }
2428         break;
2429     default:
2430     case HTTPSTATE_SEND_DATA_TRAILER:
2431         /* last packet test ? */
2432         if (c->last_packet_sent || c->is_packetized)
2433             return -1;
2434         ctx = &c->fmt_ctx;
2435         /* prepare header */
2436         if (url_open_dyn_buf(&ctx->pb) < 0) {
2437             /* XXX: potential leak */
2438             return -1;
2439         }
2440         c->fmt_ctx.pb->is_streamed = 1;
2441         av_write_trailer(ctx);
2442         len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
2443         c->buffer_ptr = c->pb_buffer;
2444         c->buffer_end = c->pb_buffer + len;
2445
2446         c->last_packet_sent = 1;
2447         break;
2448     }
2449     return 0;
2450 }
2451
2452 /* should convert the format at the same time */
2453 /* send data starting at c->buffer_ptr to the output connection
2454    (either UDP or TCP connection) */
2455 static int http_send_data(HTTPContext *c)
2456 {
2457     int len, ret;
2458
2459     for(;;) {
2460         if (c->buffer_ptr >= c->buffer_end) {
2461             ret = http_prepare_data(c);
2462             if (ret < 0)
2463                 return -1;
2464             else if (ret != 0)
2465                 /* state change requested */
2466                 break;
2467         } else {
2468             if (c->is_packetized) {
2469                 /* RTP data output */
2470                 len = c->buffer_end - c->buffer_ptr;
2471                 if (len < 4) {
2472                     /* fail safe - should never happen */
2473                 fail1:
2474                     c->buffer_ptr = c->buffer_end;
2475                     return 0;
2476                 }
2477                 len = (c->buffer_ptr[0] << 24) |
2478                     (c->buffer_ptr[1] << 16) |
2479                     (c->buffer_ptr[2] << 8) |
2480                     (c->buffer_ptr[3]);
2481                 if (len > (c->buffer_end - c->buffer_ptr))
2482                     goto fail1;
2483                 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2484                     /* nothing to send yet: we can wait */
2485                     return 0;
2486                 }
2487
2488                 c->data_count += len;
2489                 update_datarate(&c->datarate, c->data_count);
2490                 if (c->stream)
2491                     c->stream->bytes_served += len;
2492
2493                 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2494                     /* RTP packets are sent inside the RTSP TCP connection */
2495                     ByteIOContext *pb;
2496                     int interleaved_index, size;
2497                     uint8_t header[4];
2498                     HTTPContext *rtsp_c;
2499
2500                     rtsp_c = c->rtsp_c;
2501                     /* if no RTSP connection left, error */
2502                     if (!rtsp_c)
2503                         return -1;
2504                     /* if already sending something, then wait. */
2505                     if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2506                         break;
2507                     if (url_open_dyn_buf(&pb) < 0)
2508                         goto fail1;
2509                     interleaved_index = c->packet_stream_index * 2;
2510                     /* RTCP packets are sent at odd indexes */
2511                     if (c->buffer_ptr[1] == 200)
2512                         interleaved_index++;
2513                     /* write RTSP TCP header */
2514                     header[0] = '$';
2515                     header[1] = interleaved_index;
2516                     header[2] = len >> 8;
2517                     header[3] = len;
2518                     put_buffer(pb, header, 4);
2519                     /* write RTP packet data */
2520                     c->buffer_ptr += 4;
2521                     put_buffer(pb, c->buffer_ptr, len);
2522                     size = url_close_dyn_buf(pb, &c->packet_buffer);
2523                     /* prepare asynchronous TCP sending */
2524                     rtsp_c->packet_buffer_ptr = c->packet_buffer;
2525                     rtsp_c->packet_buffer_end = c->packet_buffer + size;
2526                     c->buffer_ptr += len;
2527
2528                     /* send everything we can NOW */
2529                     len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2530                                 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2531                     if (len > 0)
2532                         rtsp_c->packet_buffer_ptr += len;
2533                     if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2534                         /* if we could not send all the data, we will
2535                            send it later, so a new state is needed to
2536                            "lock" the RTSP TCP connection */
2537                         rtsp_c->state = RTSPSTATE_SEND_PACKET;
2538                         break;
2539                     } else
2540                         /* all data has been sent */
2541                         av_freep(&c->packet_buffer);
2542                 } else {
2543                     /* send RTP packet directly in UDP */
2544                     c->buffer_ptr += 4;
2545                     url_write(c->rtp_handles[c->packet_stream_index],
2546                               c->buffer_ptr, len);
2547                     c->buffer_ptr += len;
2548                     /* here we continue as we can send several packets per 10 ms slot */
2549                 }
2550             } else {
2551                 /* TCP data output */
2552                 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2553                 if (len < 0) {
2554                     if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2555                         ff_neterrno() != FF_NETERROR(EINTR))
2556                         /* error : close connection */
2557                         return -1;
2558                     else
2559                         return 0;
2560                 } else
2561                     c->buffer_ptr += len;
2562
2563                 c->data_count += len;
2564                 update_datarate(&c->datarate, c->data_count);
2565                 if (c->stream)
2566                     c->stream->bytes_served += len;
2567                 break;
2568             }
2569         }
2570     } /* for(;;) */
2571     return 0;
2572 }
2573
2574 static int http_start_receive_data(HTTPContext *c)
2575 {
2576     int fd;
2577
2578     if (c->stream->feed_opened)
2579         return -1;
2580
2581     /* Don't permit writing to this one */
2582     if (c->stream->readonly)
2583         return -1;
2584
2585     /* open feed */
2586     fd = open(c->stream->feed_filename, O_RDWR);
2587     if (fd < 0) {
2588         http_log("Error opening feeder file: %s\n", strerror(errno));
2589         return -1;
2590     }
2591     c->feed_fd = fd;
2592
2593     if (c->stream->truncate) {
2594         /* truncate feed file */
2595         ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2596         ftruncate(c->feed_fd, FFM_PACKET_SIZE);
2597         http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2598     } else {
2599         if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2600             http_log("Error reading write index from feed file: %s\n", strerror(errno));
2601             return -1;
2602         }
2603     }
2604
2605     c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2606     c->stream->feed_size = lseek(fd, 0, SEEK_END);
2607     lseek(fd, 0, SEEK_SET);
2608
2609     /* init buffer input */
2610     c->buffer_ptr = c->buffer;
2611     c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2612     c->stream->feed_opened = 1;
2613     c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2614     return 0;
2615 }
2616
2617 static int http_receive_data(HTTPContext *c)
2618 {
2619     HTTPContext *c1;
2620     int len, loop_run = 0;
2621
2622     while (c->chunked_encoding && !c->chunk_size &&
2623            c->buffer_end > c->buffer_ptr) {
2624         /* read chunk header, if present */
2625         len = recv(c->fd, c->buffer_ptr, 1, 0);
2626
2627         if (len < 0) {
2628             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2629                 ff_neterrno() != FF_NETERROR(EINTR))
2630                 /* error : close connection */
2631                 goto fail;
2632         } else if (len == 0) {
2633             /* end of connection : close it */
2634             goto fail;
2635         } else if (c->buffer_ptr - c->buffer >= 2 &&
2636                    !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2637             c->chunk_size = strtol(c->buffer, 0, 16);
2638             if (c->chunk_size == 0) // end of stream
2639                 goto fail;
2640             c->buffer_ptr = c->buffer;
2641             break;
2642         } else if (++loop_run > 10) {
2643             /* no chunk header, abort */
2644             goto fail;
2645         } else {
2646             c->buffer_ptr++;
2647         }
2648     }
2649
2650     if (c->buffer_end > c->buffer_ptr) {
2651         len = recv(c->fd, c->buffer_ptr,
2652                    FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2653         if (len < 0) {
2654             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2655                 ff_neterrno() != FF_NETERROR(EINTR))
2656                 /* error : close connection */
2657                 goto fail;
2658         } else if (len == 0)
2659             /* end of connection : close it */
2660             goto fail;
2661         else {
2662             c->chunk_size -= len;
2663             c->buffer_ptr += len;
2664             c->data_count += len;
2665             update_datarate(&c->datarate, c->data_count);
2666         }
2667     }
2668
2669     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2670         if (c->buffer[0] != 'f' ||
2671             c->buffer[1] != 'm') {
2672             http_log("Feed stream has become desynchronized -- disconnecting\n");
2673             goto fail;
2674         }
2675     }
2676
2677     if (c->buffer_ptr >= c->buffer_end) {
2678         FFStream *feed = c->stream;
2679         /* a packet has been received : write it in the store, except
2680            if header */
2681         if (c->data_count > FFM_PACKET_SIZE) {
2682
2683             //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2684             /* XXX: use llseek or url_seek */
2685             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2686             if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2687                 http_log("Error writing to feed file: %s\n", strerror(errno));
2688                 goto fail;
2689             }
2690
2691             feed->feed_write_index += FFM_PACKET_SIZE;
2692             /* update file size */
2693             if (feed->feed_write_index > c->stream->feed_size)
2694                 feed->feed_size = feed->feed_write_index;
2695
2696             /* handle wrap around if max file size reached */
2697             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2698                 feed->feed_write_index = FFM_PACKET_SIZE;
2699
2700             /* write index */
2701             if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2702                 http_log("Error writing index to feed file: %s\n", strerror(errno));
2703                 goto fail;
2704             }
2705
2706             /* wake up any waiting connections */
2707             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2708                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2709                     c1->stream->feed == c->stream->feed)
2710                     c1->state = HTTPSTATE_SEND_DATA;
2711             }
2712         } else {
2713             /* We have a header in our hands that contains useful data */
2714             AVFormatContext *s = NULL;
2715             ByteIOContext *pb;
2716             AVInputFormat *fmt_in;
2717             int i;
2718
2719             /* use feed output format name to find corresponding input format */
2720             fmt_in = av_find_input_format(feed->fmt->name);
2721             if (!fmt_in)
2722                 goto fail;
2723
2724             url_open_buf(&pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
2725             pb->is_streamed = 1;
2726
2727             if (av_open_input_stream(&s, pb, c->stream->feed_filename, fmt_in, NULL) < 0) {
2728                 av_free(pb);
2729                 goto fail;
2730             }
2731
2732             /* Now we have the actual streams */
2733             if (s->nb_streams != feed->nb_streams) {
2734                 av_close_input_stream(s);
2735                 av_free(pb);
2736                 http_log("Feed '%s' stream number does not match registered feed\n",
2737                          c->stream->feed_filename);
2738                 goto fail;
2739             }
2740
2741             for (i = 0; i < s->nb_streams; i++) {
2742                 AVStream *fst = feed->streams[i];
2743                 AVStream *st = s->streams[i];
2744                 memcpy(fst->codec, st->codec, sizeof(AVCodecContext));
2745                 if (fst->codec->extradata_size) {
2746                     fst->codec->extradata = av_malloc(fst->codec->extradata_size);
2747                     if (!fst->codec->extradata)
2748                         goto fail;
2749                     memcpy(fst->codec->extradata, st->codec->extradata,
2750                            fst->codec->extradata_size);
2751                 }
2752             }
2753
2754             av_close_input_stream(s);
2755             av_free(pb);
2756         }
2757         c->buffer_ptr = c->buffer;
2758     }
2759
2760     return 0;
2761  fail:
2762     c->stream->feed_opened = 0;
2763     close(c->feed_fd);
2764     /* wake up any waiting connections to stop waiting for feed */
2765     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2766         if (c1->state == HTTPSTATE_WAIT_FEED &&
2767             c1->stream->feed == c->stream->feed)
2768             c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2769     }
2770     return -1;
2771 }
2772
2773 /********************************************************************/
2774 /* RTSP handling */
2775
2776 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2777 {
2778     const char *str;
2779     time_t ti;
2780     char *p;
2781     char buf2[32];
2782
2783     switch(error_number) {
2784     case RTSP_STATUS_OK:
2785         str = "OK";
2786         break;
2787     case RTSP_STATUS_METHOD:
2788         str = "Method Not Allowed";
2789         break;
2790     case RTSP_STATUS_BANDWIDTH:
2791         str = "Not Enough Bandwidth";
2792         break;
2793     case RTSP_STATUS_SESSION:
2794         str = "Session Not Found";
2795         break;
2796     case RTSP_STATUS_STATE:
2797         str = "Method Not Valid in This State";
2798         break;
2799     case RTSP_STATUS_AGGREGATE:
2800         str = "Aggregate operation not allowed";
2801         break;
2802     case RTSP_STATUS_ONLY_AGGREGATE:
2803         str = "Only aggregate operation allowed";
2804         break;
2805     case RTSP_STATUS_TRANSPORT:
2806         str = "Unsupported transport";
2807         break;
2808     case RTSP_STATUS_INTERNAL:
2809         str = "Internal Server Error";
2810         break;
2811     case RTSP_STATUS_SERVICE:
2812         str = "Service Unavailable";
2813         break;
2814     case RTSP_STATUS_VERSION:
2815         str = "RTSP Version not supported";
2816         break;
2817     default:
2818         str = "Unknown Error";
2819         break;
2820     }
2821
2822     url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2823     url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2824
2825     /* output GMT time */
2826     ti = time(NULL);
2827     p = ctime(&ti);
2828     strcpy(buf2, p);
2829     p = buf2 + strlen(p) - 1;
2830     if (*p == '\n')
2831         *p = '\0';
2832     url_fprintf(c->pb, "Date: %s GMT\r\n", buf2);
2833 }
2834
2835 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2836 {
2837     rtsp_reply_header(c, error_number);
2838     url_fprintf(c->pb, "\r\n");
2839 }
2840
2841 static int rtsp_parse_request(HTTPContext *c)
2842 {
2843     const char *p, *p1, *p2;
2844     char cmd[32];
2845     char url[1024];
2846     char protocol[32];
2847     char line[1024];
2848     int len;
2849     RTSPMessageHeader header1, *header = &header1;
2850
2851     c->buffer_ptr[0] = '\0';
2852     p = c->buffer;
2853
2854     get_word(cmd, sizeof(cmd), &p);
2855     get_word(url, sizeof(url), &p);
2856     get_word(protocol, sizeof(protocol), &p);
2857
2858     av_strlcpy(c->method, cmd, sizeof(c->method));
2859     av_strlcpy(c->url, url, sizeof(c->url));
2860     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2861
2862     if (url_open_dyn_buf(&c->pb) < 0) {
2863         /* XXX: cannot do more */
2864         c->pb = NULL; /* safety */
2865         return -1;
2866     }
2867
2868     /* check version name */
2869     if (strcmp(protocol, "RTSP/1.0") != 0) {
2870         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2871         goto the_end;
2872     }
2873
2874     /* parse each header line */
2875     memset(header, 0, sizeof(*header));
2876     /* skip to next line */
2877     while (*p != '\n' && *p != '\0')
2878         p++;
2879     if (*p == '\n')
2880         p++;
2881     while (*p != '\0') {
2882         p1 = strchr(p, '\n');
2883         if (!p1)
2884             break;
2885         p2 = p1;
2886         if (p2 > p && p2[-1] == '\r')
2887             p2--;
2888         /* skip empty line */
2889         if (p2 == p)
2890             break;
2891         len = p2 - p;
2892         if (len > sizeof(line) - 1)
2893             len = sizeof(line) - 1;
2894         memcpy(line, p, len);
2895         line[len] = '\0';
2896         ff_rtsp_parse_line(header, line, NULL);
2897         p = p1 + 1;
2898     }
2899
2900     /* handle sequence number */
2901     c->seq = header->seq;
2902
2903     if (!strcmp(cmd, "DESCRIBE"))
2904         rtsp_cmd_describe(c, url);
2905     else if (!strcmp(cmd, "OPTIONS"))
2906         rtsp_cmd_options(c, url);
2907     else if (!strcmp(cmd, "SETUP"))
2908         rtsp_cmd_setup(c, url, header);
2909     else if (!strcmp(cmd, "PLAY"))
2910         rtsp_cmd_play(c, url, header);
2911     else if (!strcmp(cmd, "PAUSE"))
2912         rtsp_cmd_pause(c, url, header);
2913     else if (!strcmp(cmd, "TEARDOWN"))
2914         rtsp_cmd_teardown(c, url, header);
2915     else
2916         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2917
2918  the_end:
2919     len = url_close_dyn_buf(c->pb, &c->pb_buffer);
2920     c->pb = NULL; /* safety */
2921     if (len < 0) {
2922         /* XXX: cannot do more */
2923         return -1;
2924     }
2925     c->buffer_ptr = c->pb_buffer;
2926     c->buffer_end = c->pb_buffer + len;
2927     c->state = RTSPSTATE_SEND_REPLY;
2928     return 0;
2929 }
2930
2931 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2932                                    struct in_addr my_ip)
2933 {
2934     AVFormatContext *avc;
2935     AVStream avs[MAX_STREAMS];
2936     int i;
2937
2938     avc =  avformat_alloc_context();
2939     if (avc == NULL) {
2940         return -1;
2941     }
2942     av_metadata_set2(&avc->metadata, "title",
2943                      stream->title[0] ? stream->title : "No Title", 0);
2944     avc->nb_streams = stream->nb_streams;
2945     if (stream->is_multicast) {
2946         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2947                  inet_ntoa(stream->multicast_ip),
2948                  stream->multicast_port, stream->multicast_ttl);
2949     } else {
2950         snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2951     }
2952
2953     for(i = 0; i < stream->nb_streams; i++) {
2954         avc->streams[i] = &avs[i];
2955         avc->streams[i]->codec = stream->streams[i]->codec;
2956     }
2957     *pbuffer = av_mallocz(2048);
2958     avf_sdp_create(&avc, 1, *pbuffer, 2048);
2959     av_free(avc);
2960
2961     return strlen(*pbuffer);
2962 }
2963
2964 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2965 {
2966 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2967     url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2968     url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2969     url_fprintf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2970     url_fprintf(c->pb, "\r\n");
2971 }
2972
2973 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2974 {
2975     FFStream *stream;
2976     char path1[1024];
2977     const char *path;
2978     uint8_t *content;
2979     int content_length, len;
2980     struct sockaddr_in my_addr;
2981
2982     /* find which url is asked */
2983     ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2984     path = path1;
2985     if (*path == '/')
2986         path++;
2987
2988     for(stream = first_stream; stream != NULL; stream = stream->next) {
2989         if (!stream->is_feed &&
2990             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2991             !strcmp(path, stream->filename)) {
2992             goto found;
2993         }
2994     }
2995     /* no stream found */
2996     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2997     return;
2998
2999  found:
3000     /* prepare the media description in sdp format */
3001
3002     /* get the host IP */
3003     len = sizeof(my_addr);
3004     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3005     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3006     if (content_length < 0) {
3007         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3008         return;
3009     }
3010     rtsp_reply_header(c, RTSP_STATUS_OK);
3011     url_fprintf(c->pb, "Content-Type: application/sdp\r\n");
3012     url_fprintf(c->pb, "Content-Length: %d\r\n", content_length);
3013     url_fprintf(c->pb, "\r\n");
3014     put_buffer(c->pb, content, content_length);
3015 }
3016
3017 static HTTPContext *find_rtp_session(const char *session_id)
3018 {
3019     HTTPContext *c;
3020
3021     if (session_id[0] == '\0')
3022         return NULL;
3023
3024     for(c = first_http_ctx; c != NULL; c = c->next) {
3025         if (!strcmp(c->session_id, session_id))
3026             return c;
3027     }
3028     return NULL;
3029 }
3030
3031 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3032 {
3033     RTSPTransportField *th;
3034     int i;
3035
3036     for(i=0;i<h->nb_transports;i++) {
3037         th = &h->transports[i];
3038         if (th->lower_transport == lower_transport)
3039             return th;
3040     }
3041     return NULL;
3042 }
3043
3044 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3045                            RTSPMessageHeader *h)
3046 {
3047     FFStream *stream;
3048     int stream_index, rtp_port, rtcp_port;
3049     char buf[1024];
3050     char path1[1024];
3051     const char *path;
3052     HTTPContext *rtp_c;
3053     RTSPTransportField *th;
3054     struct sockaddr_in dest_addr;
3055     RTSPActionServerSetup setup;
3056
3057     /* find which url is asked */
3058     ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3059     path = path1;
3060     if (*path == '/')
3061         path++;
3062
3063     /* now check each stream */
3064     for(stream = first_stream; stream != NULL; stream = stream->next) {
3065         if (!stream->is_feed &&
3066             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3067             /* accept aggregate filenames only if single stream */
3068             if (!strcmp(path, stream->filename)) {
3069                 if (stream->nb_streams != 1) {
3070                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3071                     return;
3072                 }
3073                 stream_index = 0;
3074                 goto found;
3075             }
3076
3077             for(stream_index = 0; stream_index < stream->nb_streams;
3078                 stream_index++) {
3079                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3080                          stream->filename, stream_index);
3081                 if (!strcmp(path, buf))
3082                     goto found;
3083             }
3084         }
3085     }
3086     /* no stream found */
3087     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3088     return;
3089  found:
3090
3091     /* generate session id if needed */
3092     if (h->session_id[0] == '\0')
3093         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3094                  av_lfg_get(&random_state), av_lfg_get(&random_state));
3095
3096     /* find rtp session, and create it if none found */
3097     rtp_c = find_rtp_session(h->session_id);
3098     if (!rtp_c) {
3099         /* always prefer UDP */
3100         th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3101         if (!th) {
3102             th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3103             if (!th) {
3104                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3105                 return;
3106             }
3107         }
3108
3109         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3110                                    th->lower_transport);
3111         if (!rtp_c) {
3112             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3113             return;
3114         }
3115
3116         /* open input stream */
3117         if (open_input_stream(rtp_c, "") < 0) {
3118             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3119             return;
3120         }
3121     }
3122
3123     /* test if stream is OK (test needed because several SETUP needs
3124        to be done for a given file) */
3125     if (rtp_c->stream != stream) {
3126         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3127         return;
3128     }
3129
3130     /* test if stream is already set up */
3131     if (rtp_c->rtp_ctx[stream_index]) {
3132         rtsp_reply_error(c, RTSP_STATUS_STATE);
3133         return;
3134     }
3135
3136     /* check transport */
3137     th = find_transport(h, rtp_c->rtp_protocol);
3138     if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3139                 th->client_port_min <= 0)) {
3140         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3141         return;
3142     }
3143
3144     /* setup default options */
3145     setup.transport_option[0] = '\0';
3146     dest_addr = rtp_c->from_addr;
3147     dest_addr.sin_port = htons(th->client_port_min);
3148
3149     /* setup stream */
3150     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3151         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3152         return;
3153     }
3154
3155     /* now everything is OK, so we can send the connection parameters */
3156     rtsp_reply_header(c, RTSP_STATUS_OK);
3157     /* session ID */
3158     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3159
3160     switch(rtp_c->rtp_protocol) {
3161     case RTSP_LOWER_TRANSPORT_UDP:
3162         rtp_port = rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3163         rtcp_port = rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3164         url_fprintf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3165                     "client_port=%d-%d;server_port=%d-%d",
3166                     th->client_port_min, th->client_port_max,
3167                     rtp_port, rtcp_port);
3168         break;
3169     case RTSP_LOWER_TRANSPORT_TCP:
3170         url_fprintf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3171                     stream_index * 2, stream_index * 2 + 1);
3172         break;
3173     default:
3174         break;
3175     }
3176     if (setup.transport_option[0] != '\0')
3177         url_fprintf(c->pb, ";%s", setup.transport_option);
3178     url_fprintf(c->pb, "\r\n");
3179
3180
3181     url_fprintf(c->pb, "\r\n");
3182 }
3183
3184
3185 /* find an rtp connection by using the session ID. Check consistency
3186    with filename */
3187 static HTTPContext *find_rtp_session_with_url(const char *url,
3188                                               const char *session_id)
3189 {
3190     HTTPContext *rtp_c;
3191     char path1[1024];
3192     const char *path;
3193     char buf[1024];
3194     int s;
3195
3196     rtp_c = find_rtp_session(session_id);
3197     if (!rtp_c)
3198         return NULL;
3199
3200     /* find which url is asked */
3201     ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3202     path = path1;
3203     if (*path == '/')
3204         path++;
3205     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3206     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3207       snprintf(buf, sizeof(buf), "%s/streamid=%d",
3208         rtp_c->stream->filename, s);
3209       if(!strncmp(path, buf, sizeof(buf))) {
3210     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3211         return rtp_c;
3212       }
3213     }
3214     return NULL;
3215 }
3216
3217 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3218 {
3219     HTTPContext *rtp_c;
3220
3221     rtp_c = find_rtp_session_with_url(url, h->session_id);
3222     if (!rtp_c) {
3223         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3224         return;
3225     }
3226
3227     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3228         rtp_c->state != HTTPSTATE_WAIT_FEED &&
3229         rtp_c->state != HTTPSTATE_READY) {
3230         rtsp_reply_error(c, RTSP_STATUS_STATE);
3231         return;
3232     }
3233
3234     rtp_c->state = HTTPSTATE_SEND_DATA;
3235
3236     /* now everything is OK, so we can send the connection parameters */
3237     rtsp_reply_header(c, RTSP_STATUS_OK);
3238     /* session ID */
3239     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3240     url_fprintf(c->pb, "\r\n");
3241 }
3242
3243 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3244 {
3245     HTTPContext *rtp_c;
3246
3247     rtp_c = find_rtp_session_with_url(url, h->session_id);
3248     if (!rtp_c) {
3249         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3250         return;
3251     }
3252
3253     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3254         rtp_c->state != HTTPSTATE_WAIT_FEED) {
3255         rtsp_reply_error(c, RTSP_STATUS_STATE);
3256         return;
3257     }
3258
3259     rtp_c->state = HTTPSTATE_READY;
3260     rtp_c->first_pts = AV_NOPTS_VALUE;
3261     /* now everything is OK, so we can send the connection parameters */
3262     rtsp_reply_header(c, RTSP_STATUS_OK);
3263     /* session ID */
3264     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3265     url_fprintf(c->pb, "\r\n");
3266 }
3267
3268 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3269 {
3270     HTTPContext *rtp_c;
3271     char session_id[32];
3272
3273     rtp_c = find_rtp_session_with_url(url, h->session_id);
3274     if (!rtp_c) {
3275         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3276         return;
3277     }
3278
3279     av_strlcpy(session_id, rtp_c->session_id, sizeof(session_id));
3280
3281     /* abort the session */
3282     close_connection(rtp_c);
3283
3284     /* now everything is OK, so we can send the connection parameters */
3285     rtsp_reply_header(c, RTSP_STATUS_OK);
3286     /* session ID */
3287     url_fprintf(c->pb, "Session: %s\r\n", session_id);
3288     url_fprintf(c->pb, "\r\n");
3289 }
3290
3291
3292 /********************************************************************/
3293 /* RTP handling */
3294
3295 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3296                                        FFStream *stream, const char *session_id,
3297                                        enum RTSPLowerTransport rtp_protocol)
3298 {
3299     HTTPContext *c = NULL;
3300     const char *proto_str;
3301
3302     /* XXX: should output a warning page when coming
3303        close to the connection limit */
3304     if (nb_connections >= nb_max_connections)
3305         goto fail;
3306
3307     /* add a new connection */
3308     c = av_mallocz(sizeof(HTTPContext));
3309     if (!c)
3310         goto fail;
3311
3312     c->fd = -1;
3313     c->poll_entry = NULL;
3314     c->from_addr = *from_addr;
3315     c->buffer_size = IOBUFFER_INIT_SIZE;
3316     c->buffer = av_malloc(c->buffer_size);
3317     if (!c->buffer)
3318         goto fail;
3319     nb_connections++;
3320     c->stream = stream;
3321     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3322     c->state = HTTPSTATE_READY;
3323     c->is_packetized = 1;
3324     c->rtp_protocol = rtp_protocol;
3325
3326     /* protocol is shown in statistics */
3327     switch(c->rtp_protocol) {
3328     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3329         proto_str = "MCAST";
3330         break;
3331     case RTSP_LOWER_TRANSPORT_UDP:
3332         proto_str = "UDP";
3333         break;
3334     case RTSP_LOWER_TRANSPORT_TCP:
3335         proto_str = "TCP";
3336         break;
3337     default:
3338         proto_str = "???";
3339         break;
3340     }
3341     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3342     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3343
3344     current_bandwidth += stream->bandwidth;
3345
3346     c->next = first_http_ctx;
3347     first_http_ctx = c;
3348     return c;
3349
3350  fail:
3351     if (c) {
3352         av_free(c->buffer);
3353         av_free(c);
3354     }
3355     return NULL;
3356 }
3357
3358 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3359    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3360    used. */
3361 static int rtp_new_av_stream(HTTPContext *c,
3362                              int stream_index, struct sockaddr_in *dest_addr,
3363                              HTTPContext *rtsp_c)
3364 {
3365     AVFormatContext *ctx;
3366     AVStream *st;
3367     char *ipaddr;
3368     URLContext *h = NULL;
3369     uint8_t *dummy_buf;
3370     int max_packet_size;
3371
3372     /* now we can open the relevant output stream */
3373     ctx = avformat_alloc_context();
3374     if (!ctx)
3375         return -1;
3376     ctx->oformat = av_guess_format("rtp", NULL, NULL);
3377
3378     st = av_mallocz(sizeof(AVStream));
3379     if (!st)
3380         goto fail;
3381     st->codec= avcodec_alloc_context();
3382     ctx->nb_streams = 1;
3383     ctx->streams[0] = st;
3384
3385     if (!c->stream->feed ||
3386         c->stream->feed == c->stream)
3387         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3388     else
3389         memcpy(st,
3390                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3391                sizeof(AVStream));
3392     st->priv_data = NULL;
3393
3394     /* build destination RTP address */
3395     ipaddr = inet_ntoa(dest_addr->sin_addr);
3396
3397     switch(c->rtp_protocol) {
3398     case RTSP_LOWER_TRANSPORT_UDP:
3399     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3400         /* RTP/UDP case */
3401
3402         /* XXX: also pass as parameter to function ? */
3403         if (c->stream->is_multicast) {
3404             int ttl;
3405             ttl = c->stream->multicast_ttl;
3406             if (!ttl)
3407                 ttl = 16;
3408             snprintf(ctx->filename, sizeof(ctx->filename),
3409                      "rtp://%s:%d?multicast=1&ttl=%d",
3410                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3411         } else {
3412             snprintf(ctx->filename, sizeof(ctx->filename),
3413                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3414         }
3415
3416         if (url_open(&h, ctx->filename, URL_WRONLY) < 0)
3417             goto fail;
3418         c->rtp_handles[stream_index] = h;
3419         max_packet_size = url_get_max_packet_size(h);
3420         break;
3421     case RTSP_LOWER_TRANSPORT_TCP:
3422         /* RTP/TCP case */
3423         c->rtsp_c = rtsp_c;
3424         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3425         break;
3426     default:
3427         goto fail;
3428     }
3429
3430     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3431              ipaddr, ntohs(dest_addr->sin_port),
3432              c->stream->filename, stream_index, c->protocol);
3433
3434     /* normally, no packets should be output here, but the packet size may be checked */
3435     if (url_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3436         /* XXX: close stream */
3437         goto fail;
3438     }
3439     av_set_parameters(ctx, NULL);
3440     if (av_write_header(ctx) < 0) {
3441     fail:
3442         if (h)
3443             url_close(h);
3444         av_free(ctx);
3445         return -1;
3446     }
3447     url_close_dyn_buf(ctx->pb, &dummy_buf);
3448     av_free(dummy_buf);
3449
3450     c->rtp_ctx[stream_index] = ctx;
3451     return 0;
3452 }
3453
3454 /********************************************************************/
3455 /* ffserver initialization */
3456
3457 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec)
3458 {
3459     AVStream *fst;
3460
3461     fst = av_mallocz(sizeof(AVStream));
3462     if (!fst)
3463         return NULL;
3464     fst->codec= avcodec_alloc_context();
3465     fst->priv_data = av_mallocz(sizeof(FeedData));
3466     memcpy(fst->codec, codec, sizeof(AVCodecContext));
3467     fst->index = stream->nb_streams;
3468     av_set_pts_info(fst, 33, 1, 90000);
3469     stream->streams[stream->nb_streams++] = fst;
3470     return fst;
3471 }
3472
3473 /* return the stream number in the feed */
3474 static int add_av_stream(FFStream *feed, AVStream *st)
3475 {
3476     AVStream *fst;
3477     AVCodecContext *av, *av1;
3478     int i;
3479
3480     av = st->codec;
3481     for(i=0;i<feed->nb_streams;i++) {
3482         st = feed->streams[i];
3483         av1 = st->codec;
3484         if (av1->codec_id == av->codec_id &&
3485             av1->codec_type == av->codec_type &&
3486             av1->bit_rate == av->bit_rate) {
3487
3488             switch(av->codec_type) {
3489             case AVMEDIA_TYPE_AUDIO:
3490                 if (av1->channels == av->channels &&
3491                     av1->sample_rate == av->sample_rate)
3492                     goto found;
3493                 break;
3494             case AVMEDIA_TYPE_VIDEO:
3495                 if (av1->width == av->width &&
3496                     av1->height == av->height &&
3497                     av1->time_base.den == av->time_base.den &&
3498                     av1->time_base.num == av->time_base.num &&
3499                     av1->gop_size == av->gop_size)
3500                     goto found;
3501                 break;
3502             default:
3503                 abort();
3504             }
3505         }
3506     }
3507
3508     fst = add_av_stream1(feed, av);
3509     if (!fst)
3510         return -1;
3511     return feed->nb_streams - 1;
3512  found:
3513     return i;
3514 }
3515
3516 static void remove_stream(FFStream *stream)
3517 {
3518     FFStream **ps;
3519     ps = &first_stream;
3520     while (*ps != NULL) {
3521         if (*ps == stream)
3522             *ps = (*ps)->next;
3523         else
3524             ps = &(*ps)->next;
3525     }
3526 }
3527
3528 /* specific mpeg4 handling : we extract the raw parameters */
3529 static void extract_mpeg4_header(AVFormatContext *infile)
3530 {
3531     int mpeg4_count, i, size;
3532     AVPacket pkt;
3533     AVStream *st;
3534     const uint8_t *p;
3535
3536     mpeg4_count = 0;
3537     for(i=0;i<infile->nb_streams;i++) {
3538         st = infile->streams[i];
3539         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3540             st->codec->extradata_size == 0) {
3541             mpeg4_count++;
3542         }
3543     }
3544     if (!mpeg4_count)
3545         return;
3546
3547     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3548     while (mpeg4_count > 0) {
3549         if (av_read_packet(infile, &pkt) < 0)
3550             break;
3551         st = infile->streams[pkt.stream_index];
3552         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3553             st->codec->extradata_size == 0) {
3554             av_freep(&st->codec->extradata);
3555             /* fill extradata with the header */
3556             /* XXX: we make hard suppositions here ! */
3557             p = pkt.data;
3558             while (p < pkt.data + pkt.size - 4) {
3559                 /* stop when vop header is found */
3560                 if (p[0] == 0x00 && p[1] == 0x00 &&
3561                     p[2] == 0x01 && p[3] == 0xb6) {
3562                     size = p - pkt.data;
3563                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3564                     st->codec->extradata = av_malloc(size);
3565                     st->codec->extradata_size = size;
3566                     memcpy(st->codec->extradata, pkt.data, size);
3567                     break;
3568                 }
3569                 p++;
3570             }
3571             mpeg4_count--;
3572         }
3573         av_free_packet(&pkt);
3574     }
3575 }
3576
3577 /* compute the needed AVStream for each file */
3578 static void build_file_streams(void)
3579 {
3580     FFStream *stream, *stream_next;
3581     AVFormatContext *infile;
3582     int i, ret;
3583
3584     /* gather all streams */
3585     for(stream = first_stream; stream != NULL; stream = stream_next) {
3586         stream_next = stream->next;
3587         if (stream->stream_type == STREAM_TYPE_LIVE &&
3588             !stream->feed) {
3589             /* the stream comes from a file */
3590             /* try to open the file */
3591             /* open stream */
3592             stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
3593             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3594                 /* specific case : if transport stream output to RTP,
3595                    we use a raw transport stream reader */
3596                 stream->ap_in->mpeg2ts_raw = 1;
3597                 stream->ap_in->mpeg2ts_compute_pcr = 1;
3598             }
3599
3600             http_log("Opening file '%s'\n", stream->feed_filename);
3601             if ((ret = av_open_input_file(&infile, stream->feed_filename,
3602                                           stream->ifmt, 0, stream->ap_in)) < 0) {
3603                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3604                 /* remove stream (no need to spend more time on it) */
3605             fail:
3606                 remove_stream(stream);
3607             } else {
3608                 /* find all the AVStreams inside and reference them in
3609                    'stream' */
3610                 if (av_find_stream_info(infile) < 0) {
3611                     http_log("Could not find codec parameters from '%s'\n",
3612                              stream->feed_filename);
3613                     av_close_input_file(infile);
3614                     goto fail;
3615                 }
3616                 extract_mpeg4_header(infile);
3617
3618                 for(i=0;i<infile->nb_streams;i++)
3619                     add_av_stream1(stream, infile->streams[i]->codec);
3620
3621                 av_close_input_file(infile);
3622             }
3623         }
3624     }
3625 }
3626
3627 /* compute the needed AVStream for each feed */
3628 static void build_feed_streams(void)
3629 {
3630     FFStream *stream, *feed;
3631     int i;
3632
3633     /* gather all streams */
3634     for(stream = first_stream; stream != NULL; stream = stream->next) {
3635         feed = stream->feed;
3636         if (feed) {
3637             if (!stream->is_feed) {
3638                 /* we handle a stream coming from a feed */
3639                 for(i=0;i<stream->nb_streams;i++)
3640                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3641             }
3642         }
3643     }
3644
3645     /* gather all streams */
3646     for(stream = first_stream; stream != NULL; stream = stream->next) {
3647         feed = stream->feed;
3648         if (feed) {
3649             if (stream->is_feed) {
3650                 for(i=0;i<stream->nb_streams;i++)
3651                     stream->feed_streams[i] = i;
3652             }
3653         }
3654     }
3655
3656     /* create feed files if needed */
3657     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3658         int fd;
3659
3660         if (url_exist(feed->feed_filename)) {
3661             /* See if it matches */
3662             AVFormatContext *s;
3663             int matches = 0;
3664
3665             if (av_open_input_file(&s, feed->feed_filename, NULL, FFM_PACKET_SIZE, NULL) >= 0) {
3666                 /* Now see if it matches */
3667                 if (s->nb_streams == feed->nb_streams) {
3668                     matches = 1;
3669                     for(i=0;i<s->nb_streams;i++) {
3670                         AVStream *sf, *ss;
3671                         sf = feed->streams[i];
3672                         ss = s->streams[i];
3673
3674                         if (sf->index != ss->index ||
3675                             sf->id != ss->id) {
3676                             http_log("Index & Id do not match for stream %d (%s)\n",
3677                                    i, feed->feed_filename);
3678                             matches = 0;
3679                         } else {
3680                             AVCodecContext *ccf, *ccs;
3681
3682                             ccf = sf->codec;
3683                             ccs = ss->codec;
3684 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3685
3686                             if (CHECK_CODEC(codec) || CHECK_CODEC(codec_type)) {
3687                                 http_log("Codecs do not match for stream %d\n", i);
3688                                 matches = 0;
3689                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3690                                 http_log("Codec bitrates do not match for stream %d\n", i);
3691                                 matches = 0;
3692                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3693                                 if (CHECK_CODEC(time_base.den) ||
3694                                     CHECK_CODEC(time_base.num) ||
3695                                     CHECK_CODEC(width) ||
3696                                     CHECK_CODEC(height)) {
3697                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3698                                     matches = 0;
3699                                 }
3700                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3701                                 if (CHECK_CODEC(sample_rate) ||
3702                                     CHECK_CODEC(channels) ||
3703                                     CHECK_CODEC(frame_size)) {
3704                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3705                                     matches = 0;
3706                                 }
3707                             } else {
3708                                 http_log("Unknown codec type\n");
3709                                 matches = 0;
3710                             }
3711                         }
3712                         if (!matches)
3713                             break;
3714                     }
3715                 } else
3716                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3717                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3718
3719                 av_close_input_file(s);
3720             } else
3721                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3722                         feed->feed_filename);
3723
3724             if (!matches) {
3725                 if (feed->readonly) {
3726                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3727                         feed->feed_filename);
3728                     exit(1);
3729                 }
3730                 unlink(feed->feed_filename);
3731             }
3732         }
3733         if (!url_exist(feed->feed_filename)) {
3734             AVFormatContext s1 = {0}, *s = &s1;
3735
3736             if (feed->readonly) {
3737                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3738                     feed->feed_filename);
3739                 exit(1);
3740             }
3741
3742             /* only write the header of the ffm file */
3743             if (url_fopen(&s->pb, feed->feed_filename, URL_WRONLY) < 0) {
3744                 http_log("Could not open output feed file '%s'\n",
3745                          feed->feed_filename);
3746                 exit(1);
3747             }
3748             s->oformat = feed->fmt;
3749             s->nb_streams = feed->nb_streams;
3750             for(i=0;i<s->nb_streams;i++) {
3751                 AVStream *st;
3752                 st = feed->streams[i];
3753                 s->streams[i] = st;
3754             }
3755             av_set_parameters(s, NULL);
3756             if (av_write_header(s) < 0) {
3757                 http_log("Container doesn't supports the required parameters\n");
3758                 exit(1);
3759             }
3760             /* XXX: need better api */
3761             av_freep(&s->priv_data);
3762             url_fclose(s->pb);
3763         }
3764         /* get feed size and write index */
3765         fd = open(feed->feed_filename, O_RDONLY);
3766         if (fd < 0) {
3767             http_log("Could not open output feed file '%s'\n",
3768                     feed->feed_filename);
3769             exit(1);
3770         }
3771
3772         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3773         feed->feed_size = lseek(fd, 0, SEEK_END);
3774         /* ensure that we do not wrap before the end of file */
3775         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3776             feed->feed_max_size = feed->feed_size;
3777
3778         close(fd);
3779     }
3780 }
3781
3782 /* compute the bandwidth used by each stream */
3783 static void compute_bandwidth(void)
3784 {
3785     unsigned bandwidth;
3786     int i;
3787     FFStream *stream;
3788
3789     for(stream = first_stream; stream != NULL; stream = stream->next) {
3790         bandwidth = 0;
3791         for(i=0;i<stream->nb_streams;i++) {
3792             AVStream *st = stream->streams[i];
3793             switch(st->codec->codec_type) {
3794             case AVMEDIA_TYPE_AUDIO:
3795             case AVMEDIA_TYPE_VIDEO:
3796                 bandwidth += st->codec->bit_rate;
3797                 break;
3798             default:
3799                 break;
3800             }
3801         }
3802         stream->bandwidth = (bandwidth + 999) / 1000;
3803     }
3804 }
3805
3806 /* add a codec and set the default parameters */
3807 static void add_codec(FFStream *stream, AVCodecContext *av)
3808 {
3809     AVStream *st;
3810
3811     /* compute default parameters */
3812     switch(av->codec_type) {
3813     case AVMEDIA_TYPE_AUDIO:
3814         if (av->bit_rate == 0)
3815             av->bit_rate = 64000;
3816         if (av->sample_rate == 0)
3817             av->sample_rate = 22050;
3818         if (av->channels == 0)
3819             av->channels = 1;
3820         break;
3821     case AVMEDIA_TYPE_VIDEO:
3822         if (av->bit_rate == 0)
3823             av->bit_rate = 64000;
3824         if (av->time_base.num == 0){
3825             av->time_base.den = 5;
3826             av->time_base.num = 1;
3827         }
3828         if (av->width == 0 || av->height == 0) {
3829             av->width = 160;
3830             av->height = 128;
3831         }
3832         /* Bitrate tolerance is less for streaming */
3833         if (av->bit_rate_tolerance == 0)
3834             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3835                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3836         if (av->qmin == 0)
3837             av->qmin = 3;
3838         if (av->qmax == 0)
3839             av->qmax = 31;
3840         if (av->max_qdiff == 0)
3841             av->max_qdiff = 3;
3842         av->qcompress = 0.5;
3843         av->qblur = 0.5;
3844
3845         if (!av->nsse_weight)
3846             av->nsse_weight = 8;
3847
3848         av->frame_skip_cmp = FF_CMP_DCTMAX;
3849         av->me_method = ME_EPZS;
3850         av->rc_buffer_aggressivity = 1.0;
3851
3852         if (!av->rc_eq)
3853             av->rc_eq = "tex^qComp";
3854         if (!av->i_quant_factor)
3855             av->i_quant_factor = -0.8;
3856         if (!av->b_quant_factor)
3857             av->b_quant_factor = 1.25;
3858         if (!av->b_quant_offset)
3859             av->b_quant_offset = 1.25;
3860         if (!av->rc_max_rate)
3861             av->rc_max_rate = av->bit_rate * 2;
3862
3863         if (av->rc_max_rate && !av->rc_buffer_size) {
3864             av->rc_buffer_size = av->rc_max_rate;
3865         }
3866
3867
3868         break;
3869     default:
3870         abort();
3871     }
3872
3873     st = av_mallocz(sizeof(AVStream));
3874     if (!st)
3875         return;
3876     st->codec = avcodec_alloc_context();
3877     stream->streams[stream->nb_streams++] = st;
3878     memcpy(st->codec, av, sizeof(AVCodecContext));
3879 }
3880
3881 static enum CodecID opt_audio_codec(const char *arg)
3882 {
3883     AVCodec *p= avcodec_find_encoder_by_name(arg);
3884
3885     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3886         return CODEC_ID_NONE;
3887
3888     return p->id;
3889 }
3890
3891 static enum CodecID opt_video_codec(const char *arg)
3892 {
3893     AVCodec *p= avcodec_find_encoder_by_name(arg);
3894
3895     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3896         return CODEC_ID_NONE;
3897
3898     return p->id;
3899 }
3900
3901 /* simplistic plugin support */
3902
3903 #if HAVE_DLOPEN
3904 static void load_module(const char *filename)
3905 {
3906     void *dll;
3907     void (*init_func)(void);
3908     dll = dlopen(filename, RTLD_NOW);
3909     if (!dll) {
3910         fprintf(stderr, "Could not load module '%s' - %s\n",
3911                 filename, dlerror());
3912         return;
3913     }
3914
3915     init_func = dlsym(dll, "ffserver_module_init");
3916     if (!init_func) {
3917         fprintf(stderr,
3918                 "%s: init function 'ffserver_module_init()' not found\n",
3919                 filename);
3920         dlclose(dll);
3921     }
3922
3923     init_func();
3924 }
3925 #endif
3926
3927 static int ffserver_opt_default(const char *opt, const char *arg,
3928                        AVCodecContext *avctx, int type)
3929 {
3930     int ret = 0;
3931     const AVOption *o = av_find_opt(avctx, opt, NULL, type, type);
3932     if(o)
3933         ret = av_set_string3(avctx, opt, arg, 1, NULL);
3934     return ret;
3935 }
3936
3937 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
3938                                              const char *mime_type)
3939 {
3940     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3941
3942     if (fmt) {
3943         AVOutputFormat *stream_fmt;
3944         char stream_format_name[64];
3945
3946         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
3947         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
3948
3949         if (stream_fmt)
3950             fmt = stream_fmt;
3951     }
3952
3953     return fmt;
3954 }
3955
3956 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
3957 {
3958     va_list vl;
3959     va_start(vl, fmt);
3960     fprintf(stderr, "%s:%d: ", filename, line_num);
3961     vfprintf(stderr, fmt, vl);
3962     va_end(vl);
3963
3964     (*errors)++;
3965 }
3966
3967 static int parse_ffconfig(const char *filename)
3968 {
3969     FILE *f;
3970     char line[1024];
3971     char cmd[64];
3972     char arg[1024];
3973     const char *p;
3974     int val, errors, line_num;
3975     FFStream **last_stream, *stream, *redirect;
3976     FFStream **last_feed, *feed, *s;
3977     AVCodecContext audio_enc, video_enc;
3978     enum CodecID audio_id, video_id;
3979
3980     f = fopen(filename, "r");
3981     if (!f) {
3982         perror(filename);
3983         return -1;
3984     }
3985
3986     errors = 0;
3987     line_num = 0;
3988     first_stream = NULL;
3989     last_stream = &first_stream;
3990     first_feed = NULL;
3991     last_feed = &first_feed;
3992     stream = NULL;
3993     feed = NULL;
3994     redirect = NULL;
3995     audio_id = CODEC_ID_NONE;
3996     video_id = CODEC_ID_NONE;
3997
3998 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
3999     for(;;) {
4000         if (fgets(line, sizeof(line), f) == NULL)
4001             break;
4002         line_num++;
4003         p = line;
4004         while (isspace(*p))
4005             p++;
4006         if (*p == '\0' || *p == '#')
4007             continue;
4008
4009         get_arg(cmd, sizeof(cmd), &p);
4010
4011         if (!strcasecmp(cmd, "Port")) {
4012             get_arg(arg, sizeof(arg), &p);
4013             val = atoi(arg);
4014             if (val < 1 || val > 65536) {
4015                 ERROR("Invalid_port: %s\n", arg);
4016             }
4017             my_http_addr.sin_port = htons(val);
4018         } else if (!strcasecmp(cmd, "BindAddress")) {
4019             get_arg(arg, sizeof(arg), &p);
4020             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4021                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4022             }
4023         } else if (!strcasecmp(cmd, "NoDaemon")) {
4024             ffserver_daemon = 0;
4025         } else if (!strcasecmp(cmd, "RTSPPort")) {
4026             get_arg(arg, sizeof(arg), &p);
4027             val = atoi(arg);
4028             if (val < 1 || val > 65536) {
4029                 ERROR("%s:%d: Invalid port: %s\n", arg);
4030             }
4031             my_rtsp_addr.sin_port = htons(atoi(arg));
4032         } else if (!strcasecmp(cmd, "RTSPBindAddress")) {
4033             get_arg(arg, sizeof(arg), &p);
4034             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4035                 ERROR("Invalid host/IP address: %s\n", arg);
4036             }
4037         } else if (!strcasecmp(cmd, "MaxHTTPConnections")) {
4038             get_arg(arg, sizeof(arg), &p);
4039             val = atoi(arg);
4040             if (val < 1 || val > 65536) {
4041                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4042             }
4043             nb_max_http_connections = val;
4044         } else if (!strcasecmp(cmd, "MaxClients")) {
4045             get_arg(arg, sizeof(arg), &p);
4046             val = atoi(arg);
4047             if (val < 1 || val > nb_max_http_connections) {
4048                 ERROR("Invalid MaxClients: %s\n", arg);
4049             } else {
4050                 nb_max_connections = val;
4051             }
4052         } else if (!strcasecmp(cmd, "MaxBandwidth")) {
4053             int64_t llval;
4054             get_arg(arg, sizeof(arg), &p);
4055             llval = atoll(arg);
4056             if (llval < 10 || llval > 10000000) {
4057                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4058             } else
4059                 max_bandwidth = llval;
4060         } else if (!strcasecmp(cmd, "CustomLog")) {
4061             if (!ffserver_debug)
4062                 get_arg(logfilename, sizeof(logfilename), &p);
4063         } else if (!strcasecmp(cmd, "<Feed")) {
4064             /*********************************************/
4065             /* Feed related options */
4066             char *q;
4067             if (stream || feed) {
4068                 ERROR("Already in a tag\n");
4069             } else {
4070                 feed = av_mallocz(sizeof(FFStream));
4071                 get_arg(feed->filename, sizeof(feed->filename), &p);
4072                 q = strrchr(feed->filename, '>');
4073                 if (*q)
4074                     *q = '\0';
4075
4076                 for (s = first_feed; s; s = s->next) {
4077                     if (!strcmp(feed->filename, s->filename)) {
4078                         ERROR("Feed '%s' already registered\n", s->filename);
4079                     }
4080                 }
4081
4082                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4083                 /* defaut feed file */
4084                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4085                          "/tmp/%s.ffm", feed->filename);
4086                 feed->feed_max_size = 5 * 1024 * 1024;
4087                 feed->is_feed = 1;
4088                 feed->feed = feed; /* self feeding :-) */
4089
4090                 /* add in stream list */
4091                 *last_stream = feed;
4092                 last_stream = &feed->next;
4093                 /* add in feed list */
4094                 *last_feed = feed;
4095                 last_feed = &feed->next_feed;
4096             }
4097         } else if (!strcasecmp(cmd, "Launch")) {
4098             if (feed) {
4099                 int i;
4100
4101                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4102
4103                 for (i = 0; i < 62; i++) {
4104                     get_arg(arg, sizeof(arg), &p);
4105                     if (!arg[0])
4106                         break;
4107
4108                     feed->child_argv[i] = av_strdup(arg);
4109                 }
4110
4111                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4112
4113                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4114                     "http://%s:%d/%s",
4115                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4116                     inet_ntoa(my_http_addr.sin_addr),
4117                     ntohs(my_http_addr.sin_port), feed->filename);
4118             }
4119         } else if (!strcasecmp(cmd, "ReadOnlyFile")) {
4120             if (feed) {
4121                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4122                 feed->readonly = 1;
4123             } else if (stream) {
4124                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4125             }
4126         } else if (!strcasecmp(cmd, "File")) {
4127             if (feed) {
4128                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4129             } else if (stream)
4130                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4131         } else if (!strcasecmp(cmd, "Truncate")) {
4132             if (feed) {
4133                 get_arg(arg, sizeof(arg), &p);
4134                 feed->truncate = strtod(arg, NULL);
4135             }
4136         } else if (!strcasecmp(cmd, "FileMaxSize")) {
4137             if (feed) {
4138                 char *p1;
4139                 double fsize;
4140
4141                 get_arg(arg, sizeof(arg), &p);
4142                 p1 = arg;
4143                 fsize = strtod(p1, &p1);
4144                 switch(toupper(*p1)) {
4145                 case 'K':
4146                     fsize *= 1024;
4147                     break;
4148                 case 'M':
4149                     fsize *= 1024 * 1024;
4150                     break;
4151                 case 'G':
4152                     fsize *= 1024 * 1024 * 1024;
4153                     break;
4154                 }
4155                 feed->feed_max_size = (int64_t)fsize;
4156                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4157                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4158                 }
4159             }
4160         } else if (!strcasecmp(cmd, "</Feed>")) {
4161             if (!feed) {
4162                 ERROR("No corresponding <Feed> for </Feed>\n");
4163             }
4164             feed = NULL;
4165         } else if (!strcasecmp(cmd, "<Stream")) {
4166             /*********************************************/
4167             /* Stream related options */
4168             char *q;
4169             if (stream || feed) {
4170                 ERROR("Already in a tag\n");
4171             } else {
4172                 FFStream *s;
4173                 stream = av_mallocz(sizeof(FFStream));
4174                 get_arg(stream->filename, sizeof(stream->filename), &p);
4175                 q = strrchr(stream->filename, '>');
4176                 if (*q)
4177                     *q = '\0';
4178
4179                 for (s = first_stream; s; s = s->next) {
4180                     if (!strcmp(stream->filename, s->filename)) {
4181                         ERROR("Stream '%s' already registered\n", s->filename);
4182                     }
4183                 }
4184
4185                 stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4186                 avcodec_get_context_defaults2(&video_enc, AVMEDIA_TYPE_VIDEO);
4187                 avcodec_get_context_defaults2(&audio_enc, AVMEDIA_TYPE_AUDIO);
4188                 audio_id = CODEC_ID_NONE;
4189                 video_id = CODEC_ID_NONE;
4190                 if (stream->fmt) {
4191                     audio_id = stream->fmt->audio_codec;
4192                     video_id = stream->fmt->video_codec;
4193                 }
4194
4195                 *last_stream = stream;
4196                 last_stream = &stream->next;
4197             }
4198         } else if (!strcasecmp(cmd, "Feed")) {
4199             get_arg(arg, sizeof(arg), &p);
4200             if (stream) {
4201                 FFStream *sfeed;
4202
4203                 sfeed = first_feed;
4204                 while (sfeed != NULL) {
4205                     if (!strcmp(sfeed->filename, arg))
4206                         break;
4207                     sfeed = sfeed->next_feed;
4208                 }
4209                 if (!sfeed)
4210                     ERROR("feed '%s' not defined\n", arg);
4211                 else
4212                     stream->feed = sfeed;
4213             }
4214         } else if (!strcasecmp(cmd, "Format")) {
4215             get_arg(arg, sizeof(arg), &p);
4216             if (stream) {
4217                 if (!strcmp(arg, "status")) {
4218                     stream->stream_type = STREAM_TYPE_STATUS;
4219                     stream->fmt = NULL;
4220                 } else {
4221                     stream->stream_type = STREAM_TYPE_LIVE;
4222                     /* jpeg cannot be used here, so use single frame jpeg */
4223                     if (!strcmp(arg, "jpeg"))
4224                         strcpy(arg, "mjpeg");
4225                     stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4226                     if (!stream->fmt) {
4227                         ERROR("Unknown Format: %s\n", arg);
4228                     }
4229                 }
4230                 if (stream->fmt) {
4231                     audio_id = stream->fmt->audio_codec;
4232                     video_id = stream->fmt->video_codec;
4233                 }
4234             }
4235         } else if (!strcasecmp(cmd, "InputFormat")) {
4236             get_arg(arg, sizeof(arg), &p);
4237             if (stream) {
4238                 stream->ifmt = av_find_input_format(arg);
4239                 if (!stream->ifmt) {
4240                     ERROR("Unknown input format: %s\n", arg);
4241                 }
4242             }
4243         } else if (!strcasecmp(cmd, "FaviconURL")) {
4244             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4245                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4246             } else {
4247                 ERROR("FaviconURL only permitted for status streams\n");
4248             }
4249         } else if (!strcasecmp(cmd, "Author")) {
4250             if (stream)
4251                 get_arg(stream->author, sizeof(stream->author), &p);
4252         } else if (!strcasecmp(cmd, "Comment")) {
4253             if (stream)
4254                 get_arg(stream->comment, sizeof(stream->comment), &p);
4255         } else if (!strcasecmp(cmd, "Copyright")) {
4256             if (stream)
4257                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4258         } else if (!strcasecmp(cmd, "Title")) {
4259             if (stream)
4260                 get_arg(stream->title, sizeof(stream->title), &p);
4261         } else if (!strcasecmp(cmd, "Preroll")) {
4262             get_arg(arg, sizeof(arg), &p);
4263             if (stream)
4264                 stream->prebuffer = atof(arg) * 1000;
4265         } else if (!strcasecmp(cmd, "StartSendOnKey")) {
4266             if (stream)
4267                 stream->send_on_key = 1;
4268         } else if (!strcasecmp(cmd, "AudioCodec")) {
4269             get_arg(arg, sizeof(arg), &p);
4270             audio_id = opt_audio_codec(arg);
4271             if (audio_id == CODEC_ID_NONE) {
4272                 ERROR("Unknown AudioCodec: %s\n", arg);
4273             }
4274         } else if (!strcasecmp(cmd, "VideoCodec")) {
4275             get_arg(arg, sizeof(arg), &p);
4276             video_id = opt_video_codec(arg);
4277             if (video_id == CODEC_ID_NONE) {
4278                 ERROR("Unknown VideoCodec: %s\n", arg);
4279             }
4280         } else if (!strcasecmp(cmd, "MaxTime")) {
4281             get_arg(arg, sizeof(arg), &p);
4282             if (stream)
4283                 stream->max_time = atof(arg) * 1000;
4284         } else if (!strcasecmp(cmd, "AudioBitRate")) {
4285             get_arg(arg, sizeof(arg), &p);
4286             if (stream)
4287                 audio_enc.bit_rate = atoi(arg) * 1000;
4288         } else if (!strcasecmp(cmd, "AudioChannels")) {
4289             get_arg(arg, sizeof(arg), &p);
4290             if (stream)
4291                 audio_enc.channels = atoi(arg);
4292         } else if (!strcasecmp(cmd, "AudioSampleRate")) {
4293             get_arg(arg, sizeof(arg), &p);
4294             if (stream)
4295                 audio_enc.sample_rate = atoi(arg);
4296         } else if (!strcasecmp(cmd, "AudioQuality")) {
4297             get_arg(arg, sizeof(arg), &p);
4298             if (stream) {
4299 //                audio_enc.quality = atof(arg) * 1000;
4300             }
4301         } else if (!strcasecmp(cmd, "VideoBitRateRange")) {
4302             if (stream) {
4303                 int minrate, maxrate;
4304
4305                 get_arg(arg, sizeof(arg), &p);
4306
4307                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4308                     video_enc.rc_min_rate = minrate * 1000;
4309                     video_enc.rc_max_rate = maxrate * 1000;
4310                 } else {
4311                     ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4312                 }
4313             }
4314         } else if (!strcasecmp(cmd, "Debug")) {
4315             if (stream) {
4316                 get_arg(arg, sizeof(arg), &p);
4317                 video_enc.debug = strtol(arg,0,0);
4318             }
4319         } else if (!strcasecmp(cmd, "Strict")) {
4320             if (stream) {
4321                 get_arg(arg, sizeof(arg), &p);
4322                 video_enc.strict_std_compliance = atoi(arg);
4323             }
4324         } else if (!strcasecmp(cmd, "VideoBufferSize")) {
4325             if (stream) {
4326                 get_arg(arg, sizeof(arg), &p);
4327                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4328             }
4329         } else if (!strcasecmp(cmd, "VideoBitRateTolerance")) {
4330             if (stream) {
4331                 get_arg(arg, sizeof(arg), &p);
4332                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4333             }
4334         } else if (!strcasecmp(cmd, "VideoBitRate")) {
4335             get_arg(arg, sizeof(arg), &p);
4336             if (stream) {
4337                 video_enc.bit_rate = atoi(arg) * 1000;
4338             }
4339         } else if (!strcasecmp(cmd, "VideoSize")) {
4340             get_arg(arg, sizeof(arg), &p);
4341             if (stream) {
4342                 av_parse_video_frame_size(&video_enc.width, &video_enc.height, arg);
4343                 if ((video_enc.width % 16) != 0 ||
4344                     (video_enc.height % 16) != 0) {
4345                     ERROR("Image size must be a multiple of 16\n");
4346                 }
4347             }
4348         } else if (!strcasecmp(cmd, "VideoFrameRate")) {
4349             get_arg(arg, sizeof(arg), &p);
4350             if (stream) {
4351                 AVRational frame_rate;
4352                 if (av_parse_video_frame_rate(&frame_rate, arg) < 0) {
4353                     ERROR("Incorrect frame rate: %s\n", arg);
4354                 } else {
4355                     video_enc.time_base.num = frame_rate.den;
4356                     video_enc.time_base.den = frame_rate.num;
4357                 }
4358             }
4359         } else if (!strcasecmp(cmd, "VideoGopSize")) {
4360             get_arg(arg, sizeof(arg), &p);
4361             if (stream)
4362                 video_enc.gop_size = atoi(arg);
4363         } else if (!strcasecmp(cmd, "VideoIntraOnly")) {
4364             if (stream)
4365                 video_enc.gop_size = 1;
4366         } else if (!strcasecmp(cmd, "VideoHighQuality")) {
4367             if (stream)
4368                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4369         } else if (!strcasecmp(cmd, "Video4MotionVector")) {
4370             if (stream) {
4371                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4372                 video_enc.flags |= CODEC_FLAG_4MV;
4373             }
4374         } else if (!strcasecmp(cmd, "AVOptionVideo") ||
4375                    !strcasecmp(cmd, "AVOptionAudio")) {
4376             char arg2[1024];
4377             AVCodecContext *avctx;
4378             int type;
4379             get_arg(arg, sizeof(arg), &p);
4380             get_arg(arg2, sizeof(arg2), &p);
4381             if (!strcasecmp(cmd, "AVOptionVideo")) {
4382                 avctx = &video_enc;
4383                 type = AV_OPT_FLAG_VIDEO_PARAM;
4384             } else {
4385                 avctx = &audio_enc;
4386                 type = AV_OPT_FLAG_AUDIO_PARAM;
4387             }
4388             if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4389                 ERROR("AVOption error: %s %s\n", arg, arg2);
4390             }
4391         } else if (!strcasecmp(cmd, "VideoTag")) {
4392             get_arg(arg, sizeof(arg), &p);
4393             if ((strlen(arg) == 4) && stream)
4394                 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4395         } else if (!strcasecmp(cmd, "BitExact")) {
4396             if (stream)
4397                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4398         } else if (!strcasecmp(cmd, "DctFastint")) {
4399             if (stream)
4400                 video_enc.dct_algo  = FF_DCT_FASTINT;
4401         } else if (!strcasecmp(cmd, "IdctSimple")) {
4402             if (stream)
4403                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4404         } else if (!strcasecmp(cmd, "Qscale")) {
4405             get_arg(arg, sizeof(arg), &p);
4406             if (stream) {
4407                 video_enc.flags |= CODEC_FLAG_QSCALE;
4408                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4409             }
4410         } else if (!strcasecmp(cmd, "VideoQDiff")) {
4411             get_arg(arg, sizeof(arg), &p);
4412             if (stream) {
4413                 video_enc.max_qdiff = atoi(arg);
4414                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4415                     ERROR("VideoQDiff out of range\n");
4416                 }
4417             }
4418         } else if (!strcasecmp(cmd, "VideoQMax")) {
4419             get_arg(arg, sizeof(arg), &p);
4420             if (stream) {
4421                 video_enc.qmax = atoi(arg);
4422                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4423                     ERROR("VideoQMax out of range\n");
4424                 }
4425             }
4426         } else if (!strcasecmp(cmd, "VideoQMin")) {
4427             get_arg(arg, sizeof(arg), &p);
4428             if (stream) {
4429                 video_enc.qmin = atoi(arg);
4430                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4431                     ERROR("VideoQMin out of range\n");
4432                 }
4433             }
4434         } else if (!strcasecmp(cmd, "LumaElim")) {
4435             get_arg(arg, sizeof(arg), &p);
4436             if (stream)
4437                 video_enc.luma_elim_threshold = atoi(arg);
4438         } else if (!strcasecmp(cmd, "ChromaElim")) {
4439             get_arg(arg, sizeof(arg), &p);
4440             if (stream)
4441                 video_enc.chroma_elim_threshold = atoi(arg);
4442         } else if (!strcasecmp(cmd, "LumiMask")) {
4443             get_arg(arg, sizeof(arg), &p);
4444             if (stream)
4445                 video_enc.lumi_masking = atof(arg);
4446         } else if (!strcasecmp(cmd, "DarkMask")) {
4447             get_arg(arg, sizeof(arg), &p);
4448             if (stream)
4449                 video_enc.dark_masking = atof(arg);
4450         } else if (!strcasecmp(cmd, "NoVideo")) {
4451             video_id = CODEC_ID_NONE;
4452         } else if (!strcasecmp(cmd, "NoAudio")) {
4453             audio_id = CODEC_ID_NONE;
4454         } else if (!strcasecmp(cmd, "ACL")) {
4455             parse_acl_row(stream, feed, NULL, p, filename, line_num);
4456         } else if (!strcasecmp(cmd, "DynamicACL")) {
4457             if (stream) {
4458                 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4459             }
4460         } else if (!strcasecmp(cmd, "RTSPOption")) {
4461             get_arg(arg, sizeof(arg), &p);
4462             if (stream) {
4463                 av_freep(&stream->rtsp_option);
4464                 stream->rtsp_option = av_strdup(arg);
4465             }
4466         } else if (!strcasecmp(cmd, "MulticastAddress")) {
4467             get_arg(arg, sizeof(arg), &p);
4468             if (stream) {
4469                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4470                     ERROR("Invalid host/IP address: %s\n", arg);
4471                 }
4472                 stream->is_multicast = 1;
4473                 stream->loop = 1; /* default is looping */
4474             }
4475         } else if (!strcasecmp(cmd, "MulticastPort")) {
4476             get_arg(arg, sizeof(arg), &p);
4477             if (stream)
4478                 stream->multicast_port = atoi(arg);
4479         } else if (!strcasecmp(cmd, "MulticastTTL")) {
4480             get_arg(arg, sizeof(arg), &p);
4481             if (stream)
4482                 stream->multicast_ttl = atoi(arg);
4483         } else if (!strcasecmp(cmd, "NoLoop")) {
4484             if (stream)
4485                 stream->loop = 0;
4486         } else if (!strcasecmp(cmd, "</Stream>")) {
4487             if (!stream) {
4488                 ERROR("No corresponding <Stream> for </Stream>\n");
4489             } else {
4490                 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4491                     if (audio_id != CODEC_ID_NONE) {
4492                         audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4493                         audio_enc.codec_id = audio_id;
4494                         add_codec(stream, &audio_enc);
4495                     }
4496                     if (video_id != CODEC_ID_NONE) {
4497                         video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4498                         video_enc.codec_id = video_id;
4499                         add_codec(stream, &video_enc);
4500                     }
4501                 }
4502                 stream = NULL;
4503             }
4504         } else if (!strcasecmp(cmd, "<Redirect")) {
4505             /*********************************************/
4506             char *q;
4507             if (stream || feed || redirect) {
4508                 ERROR("Already in a tag\n");
4509             } else {
4510                 redirect = av_mallocz(sizeof(FFStream));
4511                 *last_stream = redirect;
4512                 last_stream = &redirect->next;
4513
4514                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4515                 q = strrchr(redirect->filename, '>');
4516                 if (*q)
4517                     *q = '\0';
4518                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4519             }
4520         } else if (!strcasecmp(cmd, "URL")) {
4521             if (redirect)
4522                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4523         } else if (!strcasecmp(cmd, "</Redirect>")) {
4524             if (!redirect) {
4525                 ERROR("No corresponding <Redirect> for </Redirect>\n");
4526             } else {
4527                 if (!redirect->feed_filename[0]) {
4528                     ERROR("No URL found for <Redirect>\n");
4529                 }
4530                 redirect = NULL;
4531             }
4532         } else if (!strcasecmp(cmd, "LoadModule")) {
4533             get_arg(arg, sizeof(arg), &p);
4534 #if HAVE_DLOPEN
4535             load_module(arg);
4536 #else
4537             ERROR("Module support not compiled into this version: '%s'\n", arg);
4538 #endif
4539         } else {
4540             ERROR("Incorrect keyword: '%s'\n", cmd);
4541         }
4542     }
4543 #undef ERROR
4544
4545     fclose(f);
4546     if (errors)
4547         return -1;
4548     else
4549         return 0;
4550 }
4551
4552 static void handle_child_exit(int sig)
4553 {
4554     pid_t pid;
4555     int status;
4556
4557     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4558         FFStream *feed;
4559
4560         for (feed = first_feed; feed; feed = feed->next) {
4561             if (feed->pid == pid) {
4562                 int uptime = time(0) - feed->pid_start;
4563
4564                 feed->pid = 0;
4565                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4566
4567                 if (uptime < 30)
4568                     /* Turn off any more restarts */
4569                     feed->child_argv = 0;
4570             }
4571         }
4572     }
4573
4574     need_to_start_children = 1;
4575 }
4576
4577 static void opt_debug(void)
4578 {
4579     ffserver_debug = 1;
4580     ffserver_daemon = 0;
4581     logfilename[0] = '-';
4582 }
4583
4584 static void show_help(void)
4585 {
4586     printf("usage: ffserver [options]\n"
4587            "Hyper fast multi format Audio/Video streaming server\n");
4588     printf("\n");
4589     show_help_options(options, "Main options:\n", 0, 0);
4590 }
4591
4592 static const OptionDef options[] = {
4593 #include "cmdutils_common_opts.h"
4594     { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4595     { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4596     { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4597     { NULL },
4598 };
4599
4600 int main(int argc, char **argv)
4601 {
4602     struct sigaction sigact;
4603
4604     av_register_all();
4605
4606     show_banner();
4607
4608     my_program_name = argv[0];
4609     my_program_dir = getcwd(0, 0);
4610     ffserver_daemon = 1;
4611
4612     parse_options(argc, argv, options, NULL);
4613
4614     unsetenv("http_proxy");             /* Kill the http_proxy */
4615
4616     av_lfg_init(&random_state, ff_random_get_seed());
4617
4618     memset(&sigact, 0, sizeof(sigact));
4619     sigact.sa_handler = handle_child_exit;
4620     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4621     sigaction(SIGCHLD, &sigact, 0);
4622
4623     if (parse_ffconfig(config_filename) < 0) {
4624         fprintf(stderr, "Incorrect config file - exiting.\n");
4625         exit(1);
4626     }
4627
4628     /* open log file if needed */
4629     if (logfilename[0] != '\0') {
4630         if (!strcmp(logfilename, "-"))
4631             logfile = stdout;
4632         else
4633             logfile = fopen(logfilename, "a");
4634         av_log_set_callback(http_av_log);
4635     }
4636
4637     build_file_streams();
4638
4639     build_feed_streams();
4640
4641     compute_bandwidth();
4642
4643     /* put the process in background and detach it from its TTY */
4644     if (ffserver_daemon) {
4645         int pid;
4646
4647         pid = fork();
4648         if (pid < 0) {
4649             perror("fork");
4650             exit(1);
4651         } else if (pid > 0) {
4652             /* parent : exit */
4653             exit(0);
4654         } else {
4655             /* child */
4656             setsid();
4657             close(0);
4658             open("/dev/null", O_RDWR);
4659             if (strcmp(logfilename, "-") != 0) {
4660                 close(1);
4661                 dup(0);
4662             }
4663             close(2);
4664             dup(0);
4665         }
4666     }
4667
4668     /* signal init */
4669     signal(SIGPIPE, SIG_IGN);
4670
4671     if (ffserver_daemon)
4672         chdir("/");
4673
4674     if (http_server() < 0) {
4675         http_log("Could not start server\n");
4676         exit(1);
4677     }
4678
4679     return 0;
4680 }