ffserver: Avoid busylooping while reading non-blocking input
[ffmpeg.git] / ffserver.c
1 /*
2  * Multiple format streaming server
3  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #define _XOPEN_SOURCE 600
23
24 #include "config.h"
25 #if !HAVE_CLOSESOCKET
26 #define closesocket close
27 #endif
28 #include <string.h>
29 #include <strings.h>
30 #include <stdlib.h>
31 #include "libavformat/avformat.h"
32 #include "libavformat/network.h"
33 #include "libavformat/os_support.h"
34 #include "libavformat/rtpdec.h"
35 #include "libavformat/rtsp.h"
36 #include "libavutil/avstring.h"
37 #include "libavutil/lfg.h"
38 #include "libavutil/random_seed.h"
39 #include "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             return 0;
2633         } else if (len == 0) {
2634             /* end of connection : close it */
2635             goto fail;
2636         } else if (c->buffer_ptr - c->buffer >= 2 &&
2637                    !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2638             c->chunk_size = strtol(c->buffer, 0, 16);
2639             if (c->chunk_size == 0) // end of stream
2640                 goto fail;
2641             c->buffer_ptr = c->buffer;
2642             break;
2643         } else if (++loop_run > 10) {
2644             /* no chunk header, abort */
2645             goto fail;
2646         } else {
2647             c->buffer_ptr++;
2648         }
2649     }
2650
2651     if (c->buffer_end > c->buffer_ptr) {
2652         len = recv(c->fd, c->buffer_ptr,
2653                    FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2654         if (len < 0) {
2655             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2656                 ff_neterrno() != FF_NETERROR(EINTR))
2657                 /* error : close connection */
2658                 goto fail;
2659         } else if (len == 0)
2660             /* end of connection : close it */
2661             goto fail;
2662         else {
2663             c->chunk_size -= len;
2664             c->buffer_ptr += len;
2665             c->data_count += len;
2666             update_datarate(&c->datarate, c->data_count);
2667         }
2668     }
2669
2670     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2671         if (c->buffer[0] != 'f' ||
2672             c->buffer[1] != 'm') {
2673             http_log("Feed stream has become desynchronized -- disconnecting\n");
2674             goto fail;
2675         }
2676     }
2677
2678     if (c->buffer_ptr >= c->buffer_end) {
2679         FFStream *feed = c->stream;
2680         /* a packet has been received : write it in the store, except
2681            if header */
2682         if (c->data_count > FFM_PACKET_SIZE) {
2683
2684             //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2685             /* XXX: use llseek or url_seek */
2686             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2687             if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2688                 http_log("Error writing to feed file: %s\n", strerror(errno));
2689                 goto fail;
2690             }
2691
2692             feed->feed_write_index += FFM_PACKET_SIZE;
2693             /* update file size */
2694             if (feed->feed_write_index > c->stream->feed_size)
2695                 feed->feed_size = feed->feed_write_index;
2696
2697             /* handle wrap around if max file size reached */
2698             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2699                 feed->feed_write_index = FFM_PACKET_SIZE;
2700
2701             /* write index */
2702             if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2703                 http_log("Error writing index to feed file: %s\n", strerror(errno));
2704                 goto fail;
2705             }
2706
2707             /* wake up any waiting connections */
2708             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2709                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2710                     c1->stream->feed == c->stream->feed)
2711                     c1->state = HTTPSTATE_SEND_DATA;
2712             }
2713         } else {
2714             /* We have a header in our hands that contains useful data */
2715             AVFormatContext *s = NULL;
2716             ByteIOContext *pb;
2717             AVInputFormat *fmt_in;
2718             int i;
2719
2720             /* use feed output format name to find corresponding input format */
2721             fmt_in = av_find_input_format(feed->fmt->name);
2722             if (!fmt_in)
2723                 goto fail;
2724
2725             url_open_buf(&pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
2726             pb->is_streamed = 1;
2727
2728             if (av_open_input_stream(&s, pb, c->stream->feed_filename, fmt_in, NULL) < 0) {
2729                 av_free(pb);
2730                 goto fail;
2731             }
2732
2733             /* Now we have the actual streams */
2734             if (s->nb_streams != feed->nb_streams) {
2735                 av_close_input_stream(s);
2736                 av_free(pb);
2737                 http_log("Feed '%s' stream number does not match registered feed\n",
2738                          c->stream->feed_filename);
2739                 goto fail;
2740             }
2741
2742             for (i = 0; i < s->nb_streams; i++) {
2743                 AVStream *fst = feed->streams[i];
2744                 AVStream *st = s->streams[i];
2745                 memcpy(fst->codec, st->codec, sizeof(AVCodecContext));
2746                 if (fst->codec->extradata_size) {
2747                     fst->codec->extradata = av_malloc(fst->codec->extradata_size);
2748                     if (!fst->codec->extradata)
2749                         goto fail;
2750                     memcpy(fst->codec->extradata, st->codec->extradata,
2751                            fst->codec->extradata_size);
2752                 }
2753             }
2754
2755             av_close_input_stream(s);
2756             av_free(pb);
2757         }
2758         c->buffer_ptr = c->buffer;
2759     }
2760
2761     return 0;
2762  fail:
2763     c->stream->feed_opened = 0;
2764     close(c->feed_fd);
2765     /* wake up any waiting connections to stop waiting for feed */
2766     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2767         if (c1->state == HTTPSTATE_WAIT_FEED &&
2768             c1->stream->feed == c->stream->feed)
2769             c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2770     }
2771     return -1;
2772 }
2773
2774 /********************************************************************/
2775 /* RTSP handling */
2776
2777 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2778 {
2779     const char *str;
2780     time_t ti;
2781     struct tm *tm;
2782     char buf2[32];
2783
2784     switch(error_number) {
2785     case RTSP_STATUS_OK:
2786         str = "OK";
2787         break;
2788     case RTSP_STATUS_METHOD:
2789         str = "Method Not Allowed";
2790         break;
2791     case RTSP_STATUS_BANDWIDTH:
2792         str = "Not Enough Bandwidth";
2793         break;
2794     case RTSP_STATUS_SESSION:
2795         str = "Session Not Found";
2796         break;
2797     case RTSP_STATUS_STATE:
2798         str = "Method Not Valid in This State";
2799         break;
2800     case RTSP_STATUS_AGGREGATE:
2801         str = "Aggregate operation not allowed";
2802         break;
2803     case RTSP_STATUS_ONLY_AGGREGATE:
2804         str = "Only aggregate operation allowed";
2805         break;
2806     case RTSP_STATUS_TRANSPORT:
2807         str = "Unsupported transport";
2808         break;
2809     case RTSP_STATUS_INTERNAL:
2810         str = "Internal Server Error";
2811         break;
2812     case RTSP_STATUS_SERVICE:
2813         str = "Service Unavailable";
2814         break;
2815     case RTSP_STATUS_VERSION:
2816         str = "RTSP Version not supported";
2817         break;
2818     default:
2819         str = "Unknown Error";
2820         break;
2821     }
2822
2823     url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2824     url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2825
2826     /* output GMT time */
2827     ti = time(NULL);
2828     tm = gmtime(&ti);
2829     strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2830     url_fprintf(c->pb, "Date: %s GMT\r\n", buf2);
2831 }
2832
2833 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2834 {
2835     rtsp_reply_header(c, error_number);
2836     url_fprintf(c->pb, "\r\n");
2837 }
2838
2839 static int rtsp_parse_request(HTTPContext *c)
2840 {
2841     const char *p, *p1, *p2;
2842     char cmd[32];
2843     char url[1024];
2844     char protocol[32];
2845     char line[1024];
2846     int len;
2847     RTSPMessageHeader header1, *header = &header1;
2848
2849     c->buffer_ptr[0] = '\0';
2850     p = c->buffer;
2851
2852     get_word(cmd, sizeof(cmd), &p);
2853     get_word(url, sizeof(url), &p);
2854     get_word(protocol, sizeof(protocol), &p);
2855
2856     av_strlcpy(c->method, cmd, sizeof(c->method));
2857     av_strlcpy(c->url, url, sizeof(c->url));
2858     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2859
2860     if (url_open_dyn_buf(&c->pb) < 0) {
2861         /* XXX: cannot do more */
2862         c->pb = NULL; /* safety */
2863         return -1;
2864     }
2865
2866     /* check version name */
2867     if (strcmp(protocol, "RTSP/1.0") != 0) {
2868         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2869         goto the_end;
2870     }
2871
2872     /* parse each header line */
2873     memset(header, 0, sizeof(*header));
2874     /* skip to next line */
2875     while (*p != '\n' && *p != '\0')
2876         p++;
2877     if (*p == '\n')
2878         p++;
2879     while (*p != '\0') {
2880         p1 = strchr(p, '\n');
2881         if (!p1)
2882             break;
2883         p2 = p1;
2884         if (p2 > p && p2[-1] == '\r')
2885             p2--;
2886         /* skip empty line */
2887         if (p2 == p)
2888             break;
2889         len = p2 - p;
2890         if (len > sizeof(line) - 1)
2891             len = sizeof(line) - 1;
2892         memcpy(line, p, len);
2893         line[len] = '\0';
2894         ff_rtsp_parse_line(header, line, NULL);
2895         p = p1 + 1;
2896     }
2897
2898     /* handle sequence number */
2899     c->seq = header->seq;
2900
2901     if (!strcmp(cmd, "DESCRIBE"))
2902         rtsp_cmd_describe(c, url);
2903     else if (!strcmp(cmd, "OPTIONS"))
2904         rtsp_cmd_options(c, url);
2905     else if (!strcmp(cmd, "SETUP"))
2906         rtsp_cmd_setup(c, url, header);
2907     else if (!strcmp(cmd, "PLAY"))
2908         rtsp_cmd_play(c, url, header);
2909     else if (!strcmp(cmd, "PAUSE"))
2910         rtsp_cmd_pause(c, url, header);
2911     else if (!strcmp(cmd, "TEARDOWN"))
2912         rtsp_cmd_teardown(c, url, header);
2913     else
2914         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2915
2916  the_end:
2917     len = url_close_dyn_buf(c->pb, &c->pb_buffer);
2918     c->pb = NULL; /* safety */
2919     if (len < 0) {
2920         /* XXX: cannot do more */
2921         return -1;
2922     }
2923     c->buffer_ptr = c->pb_buffer;
2924     c->buffer_end = c->pb_buffer + len;
2925     c->state = RTSPSTATE_SEND_REPLY;
2926     return 0;
2927 }
2928
2929 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2930                                    struct in_addr my_ip)
2931 {
2932     AVFormatContext *avc;
2933     AVStream avs[MAX_STREAMS];
2934     int i;
2935
2936     avc =  avformat_alloc_context();
2937     if (avc == NULL) {
2938         return -1;
2939     }
2940     av_metadata_set2(&avc->metadata, "title",
2941                      stream->title[0] ? stream->title : "No Title", 0);
2942     avc->nb_streams = stream->nb_streams;
2943     if (stream->is_multicast) {
2944         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2945                  inet_ntoa(stream->multicast_ip),
2946                  stream->multicast_port, stream->multicast_ttl);
2947     } else {
2948         snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2949     }
2950
2951     for(i = 0; i < stream->nb_streams; i++) {
2952         avc->streams[i] = &avs[i];
2953         avc->streams[i]->codec = stream->streams[i]->codec;
2954     }
2955     *pbuffer = av_mallocz(2048);
2956     avf_sdp_create(&avc, 1, *pbuffer, 2048);
2957     av_free(avc);
2958
2959     return strlen(*pbuffer);
2960 }
2961
2962 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2963 {
2964 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2965     url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2966     url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2967     url_fprintf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2968     url_fprintf(c->pb, "\r\n");
2969 }
2970
2971 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2972 {
2973     FFStream *stream;
2974     char path1[1024];
2975     const char *path;
2976     uint8_t *content;
2977     int content_length, len;
2978     struct sockaddr_in my_addr;
2979
2980     /* find which url is asked */
2981     ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2982     path = path1;
2983     if (*path == '/')
2984         path++;
2985
2986     for(stream = first_stream; stream != NULL; stream = stream->next) {
2987         if (!stream->is_feed &&
2988             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2989             !strcmp(path, stream->filename)) {
2990             goto found;
2991         }
2992     }
2993     /* no stream found */
2994     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2995     return;
2996
2997  found:
2998     /* prepare the media description in sdp format */
2999
3000     /* get the host IP */
3001     len = sizeof(my_addr);
3002     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3003     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3004     if (content_length < 0) {
3005         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3006         return;
3007     }
3008     rtsp_reply_header(c, RTSP_STATUS_OK);
3009     url_fprintf(c->pb, "Content-Type: application/sdp\r\n");
3010     url_fprintf(c->pb, "Content-Length: %d\r\n", content_length);
3011     url_fprintf(c->pb, "\r\n");
3012     put_buffer(c->pb, content, content_length);
3013 }
3014
3015 static HTTPContext *find_rtp_session(const char *session_id)
3016 {
3017     HTTPContext *c;
3018
3019     if (session_id[0] == '\0')
3020         return NULL;
3021
3022     for(c = first_http_ctx; c != NULL; c = c->next) {
3023         if (!strcmp(c->session_id, session_id))
3024             return c;
3025     }
3026     return NULL;
3027 }
3028
3029 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3030 {
3031     RTSPTransportField *th;
3032     int i;
3033
3034     for(i=0;i<h->nb_transports;i++) {
3035         th = &h->transports[i];
3036         if (th->lower_transport == lower_transport)
3037             return th;
3038     }
3039     return NULL;
3040 }
3041
3042 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3043                            RTSPMessageHeader *h)
3044 {
3045     FFStream *stream;
3046     int stream_index, rtp_port, rtcp_port;
3047     char buf[1024];
3048     char path1[1024];
3049     const char *path;
3050     HTTPContext *rtp_c;
3051     RTSPTransportField *th;
3052     struct sockaddr_in dest_addr;
3053     RTSPActionServerSetup setup;
3054
3055     /* find which url is asked */
3056     ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3057     path = path1;
3058     if (*path == '/')
3059         path++;
3060
3061     /* now check each stream */
3062     for(stream = first_stream; stream != NULL; stream = stream->next) {
3063         if (!stream->is_feed &&
3064             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3065             /* accept aggregate filenames only if single stream */
3066             if (!strcmp(path, stream->filename)) {
3067                 if (stream->nb_streams != 1) {
3068                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3069                     return;
3070                 }
3071                 stream_index = 0;
3072                 goto found;
3073             }
3074
3075             for(stream_index = 0; stream_index < stream->nb_streams;
3076                 stream_index++) {
3077                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3078                          stream->filename, stream_index);
3079                 if (!strcmp(path, buf))
3080                     goto found;
3081             }
3082         }
3083     }
3084     /* no stream found */
3085     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3086     return;
3087  found:
3088
3089     /* generate session id if needed */
3090     if (h->session_id[0] == '\0')
3091         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3092                  av_lfg_get(&random_state), av_lfg_get(&random_state));
3093
3094     /* find rtp session, and create it if none found */
3095     rtp_c = find_rtp_session(h->session_id);
3096     if (!rtp_c) {
3097         /* always prefer UDP */
3098         th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3099         if (!th) {
3100             th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3101             if (!th) {
3102                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3103                 return;
3104             }
3105         }
3106
3107         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3108                                    th->lower_transport);
3109         if (!rtp_c) {
3110             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3111             return;
3112         }
3113
3114         /* open input stream */
3115         if (open_input_stream(rtp_c, "") < 0) {
3116             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3117             return;
3118         }
3119     }
3120
3121     /* test if stream is OK (test needed because several SETUP needs
3122        to be done for a given file) */
3123     if (rtp_c->stream != stream) {
3124         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3125         return;
3126     }
3127
3128     /* test if stream is already set up */
3129     if (rtp_c->rtp_ctx[stream_index]) {
3130         rtsp_reply_error(c, RTSP_STATUS_STATE);
3131         return;
3132     }
3133
3134     /* check transport */
3135     th = find_transport(h, rtp_c->rtp_protocol);
3136     if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3137                 th->client_port_min <= 0)) {
3138         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3139         return;
3140     }
3141
3142     /* setup default options */
3143     setup.transport_option[0] = '\0';
3144     dest_addr = rtp_c->from_addr;
3145     dest_addr.sin_port = htons(th->client_port_min);
3146
3147     /* setup stream */
3148     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3149         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3150         return;
3151     }
3152
3153     /* now everything is OK, so we can send the connection parameters */
3154     rtsp_reply_header(c, RTSP_STATUS_OK);
3155     /* session ID */
3156     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3157
3158     switch(rtp_c->rtp_protocol) {
3159     case RTSP_LOWER_TRANSPORT_UDP:
3160         rtp_port = rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3161         rtcp_port = rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3162         url_fprintf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3163                     "client_port=%d-%d;server_port=%d-%d",
3164                     th->client_port_min, th->client_port_max,
3165                     rtp_port, rtcp_port);
3166         break;
3167     case RTSP_LOWER_TRANSPORT_TCP:
3168         url_fprintf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3169                     stream_index * 2, stream_index * 2 + 1);
3170         break;
3171     default:
3172         break;
3173     }
3174     if (setup.transport_option[0] != '\0')
3175         url_fprintf(c->pb, ";%s", setup.transport_option);
3176     url_fprintf(c->pb, "\r\n");
3177
3178
3179     url_fprintf(c->pb, "\r\n");
3180 }
3181
3182
3183 /* find an rtp connection by using the session ID. Check consistency
3184    with filename */
3185 static HTTPContext *find_rtp_session_with_url(const char *url,
3186                                               const char *session_id)
3187 {
3188     HTTPContext *rtp_c;
3189     char path1[1024];
3190     const char *path;
3191     char buf[1024];
3192     int s;
3193
3194     rtp_c = find_rtp_session(session_id);
3195     if (!rtp_c)
3196         return NULL;
3197
3198     /* find which url is asked */
3199     ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3200     path = path1;
3201     if (*path == '/')
3202         path++;
3203     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3204     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3205       snprintf(buf, sizeof(buf), "%s/streamid=%d",
3206         rtp_c->stream->filename, s);
3207       if(!strncmp(path, buf, sizeof(buf))) {
3208     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3209         return rtp_c;
3210       }
3211     }
3212     return NULL;
3213 }
3214
3215 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3216 {
3217     HTTPContext *rtp_c;
3218
3219     rtp_c = find_rtp_session_with_url(url, h->session_id);
3220     if (!rtp_c) {
3221         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3222         return;
3223     }
3224
3225     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3226         rtp_c->state != HTTPSTATE_WAIT_FEED &&
3227         rtp_c->state != HTTPSTATE_READY) {
3228         rtsp_reply_error(c, RTSP_STATUS_STATE);
3229         return;
3230     }
3231
3232     rtp_c->state = HTTPSTATE_SEND_DATA;
3233
3234     /* now everything is OK, so we can send the connection parameters */
3235     rtsp_reply_header(c, RTSP_STATUS_OK);
3236     /* session ID */
3237     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3238     url_fprintf(c->pb, "\r\n");
3239 }
3240
3241 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3242 {
3243     HTTPContext *rtp_c;
3244
3245     rtp_c = find_rtp_session_with_url(url, h->session_id);
3246     if (!rtp_c) {
3247         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3248         return;
3249     }
3250
3251     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3252         rtp_c->state != HTTPSTATE_WAIT_FEED) {
3253         rtsp_reply_error(c, RTSP_STATUS_STATE);
3254         return;
3255     }
3256
3257     rtp_c->state = HTTPSTATE_READY;
3258     rtp_c->first_pts = AV_NOPTS_VALUE;
3259     /* now everything is OK, so we can send the connection parameters */
3260     rtsp_reply_header(c, RTSP_STATUS_OK);
3261     /* session ID */
3262     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3263     url_fprintf(c->pb, "\r\n");
3264 }
3265
3266 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3267 {
3268     HTTPContext *rtp_c;
3269     char session_id[32];
3270
3271     rtp_c = find_rtp_session_with_url(url, h->session_id);
3272     if (!rtp_c) {
3273         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3274         return;
3275     }
3276
3277     av_strlcpy(session_id, rtp_c->session_id, sizeof(session_id));
3278
3279     /* abort the session */
3280     close_connection(rtp_c);
3281
3282     /* now everything is OK, so we can send the connection parameters */
3283     rtsp_reply_header(c, RTSP_STATUS_OK);
3284     /* session ID */
3285     url_fprintf(c->pb, "Session: %s\r\n", session_id);
3286     url_fprintf(c->pb, "\r\n");
3287 }
3288
3289
3290 /********************************************************************/
3291 /* RTP handling */
3292
3293 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3294                                        FFStream *stream, const char *session_id,
3295                                        enum RTSPLowerTransport rtp_protocol)
3296 {
3297     HTTPContext *c = NULL;
3298     const char *proto_str;
3299
3300     /* XXX: should output a warning page when coming
3301        close to the connection limit */
3302     if (nb_connections >= nb_max_connections)
3303         goto fail;
3304
3305     /* add a new connection */
3306     c = av_mallocz(sizeof(HTTPContext));
3307     if (!c)
3308         goto fail;
3309
3310     c->fd = -1;
3311     c->poll_entry = NULL;
3312     c->from_addr = *from_addr;
3313     c->buffer_size = IOBUFFER_INIT_SIZE;
3314     c->buffer = av_malloc(c->buffer_size);
3315     if (!c->buffer)
3316         goto fail;
3317     nb_connections++;
3318     c->stream = stream;
3319     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3320     c->state = HTTPSTATE_READY;
3321     c->is_packetized = 1;
3322     c->rtp_protocol = rtp_protocol;
3323
3324     /* protocol is shown in statistics */
3325     switch(c->rtp_protocol) {
3326     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3327         proto_str = "MCAST";
3328         break;
3329     case RTSP_LOWER_TRANSPORT_UDP:
3330         proto_str = "UDP";
3331         break;
3332     case RTSP_LOWER_TRANSPORT_TCP:
3333         proto_str = "TCP";
3334         break;
3335     default:
3336         proto_str = "???";
3337         break;
3338     }
3339     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3340     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3341
3342     current_bandwidth += stream->bandwidth;
3343
3344     c->next = first_http_ctx;
3345     first_http_ctx = c;
3346     return c;
3347
3348  fail:
3349     if (c) {
3350         av_free(c->buffer);
3351         av_free(c);
3352     }
3353     return NULL;
3354 }
3355
3356 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3357    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3358    used. */
3359 static int rtp_new_av_stream(HTTPContext *c,
3360                              int stream_index, struct sockaddr_in *dest_addr,
3361                              HTTPContext *rtsp_c)
3362 {
3363     AVFormatContext *ctx;
3364     AVStream *st;
3365     char *ipaddr;
3366     URLContext *h = NULL;
3367     uint8_t *dummy_buf;
3368     int max_packet_size;
3369
3370     /* now we can open the relevant output stream */
3371     ctx = avformat_alloc_context();
3372     if (!ctx)
3373         return -1;
3374     ctx->oformat = av_guess_format("rtp", NULL, NULL);
3375
3376     st = av_mallocz(sizeof(AVStream));
3377     if (!st)
3378         goto fail;
3379     st->codec= avcodec_alloc_context();
3380     ctx->nb_streams = 1;
3381     ctx->streams[0] = st;
3382
3383     if (!c->stream->feed ||
3384         c->stream->feed == c->stream)
3385         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3386     else
3387         memcpy(st,
3388                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3389                sizeof(AVStream));
3390     st->priv_data = NULL;
3391
3392     /* build destination RTP address */
3393     ipaddr = inet_ntoa(dest_addr->sin_addr);
3394
3395     switch(c->rtp_protocol) {
3396     case RTSP_LOWER_TRANSPORT_UDP:
3397     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3398         /* RTP/UDP case */
3399
3400         /* XXX: also pass as parameter to function ? */
3401         if (c->stream->is_multicast) {
3402             int ttl;
3403             ttl = c->stream->multicast_ttl;
3404             if (!ttl)
3405                 ttl = 16;
3406             snprintf(ctx->filename, sizeof(ctx->filename),
3407                      "rtp://%s:%d?multicast=1&ttl=%d",
3408                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3409         } else {
3410             snprintf(ctx->filename, sizeof(ctx->filename),
3411                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3412         }
3413
3414         if (url_open(&h, ctx->filename, URL_WRONLY) < 0)
3415             goto fail;
3416         c->rtp_handles[stream_index] = h;
3417         max_packet_size = url_get_max_packet_size(h);
3418         break;
3419     case RTSP_LOWER_TRANSPORT_TCP:
3420         /* RTP/TCP case */
3421         c->rtsp_c = rtsp_c;
3422         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3423         break;
3424     default:
3425         goto fail;
3426     }
3427
3428     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3429              ipaddr, ntohs(dest_addr->sin_port),
3430              c->stream->filename, stream_index, c->protocol);
3431
3432     /* normally, no packets should be output here, but the packet size may be checked */
3433     if (url_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3434         /* XXX: close stream */
3435         goto fail;
3436     }
3437     av_set_parameters(ctx, NULL);
3438     if (av_write_header(ctx) < 0) {
3439     fail:
3440         if (h)
3441             url_close(h);
3442         av_free(ctx);
3443         return -1;
3444     }
3445     url_close_dyn_buf(ctx->pb, &dummy_buf);
3446     av_free(dummy_buf);
3447
3448     c->rtp_ctx[stream_index] = ctx;
3449     return 0;
3450 }
3451
3452 /********************************************************************/
3453 /* ffserver initialization */
3454
3455 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec)
3456 {
3457     AVStream *fst;
3458
3459     fst = av_mallocz(sizeof(AVStream));
3460     if (!fst)
3461         return NULL;
3462     fst->codec= avcodec_alloc_context();
3463     fst->priv_data = av_mallocz(sizeof(FeedData));
3464     memcpy(fst->codec, codec, sizeof(AVCodecContext));
3465     fst->index = stream->nb_streams;
3466     av_set_pts_info(fst, 33, 1, 90000);
3467     stream->streams[stream->nb_streams++] = fst;
3468     return fst;
3469 }
3470
3471 /* return the stream number in the feed */
3472 static int add_av_stream(FFStream *feed, AVStream *st)
3473 {
3474     AVStream *fst;
3475     AVCodecContext *av, *av1;
3476     int i;
3477
3478     av = st->codec;
3479     for(i=0;i<feed->nb_streams;i++) {
3480         st = feed->streams[i];
3481         av1 = st->codec;
3482         if (av1->codec_id == av->codec_id &&
3483             av1->codec_type == av->codec_type &&
3484             av1->bit_rate == av->bit_rate) {
3485
3486             switch(av->codec_type) {
3487             case AVMEDIA_TYPE_AUDIO:
3488                 if (av1->channels == av->channels &&
3489                     av1->sample_rate == av->sample_rate)
3490                     goto found;
3491                 break;
3492             case AVMEDIA_TYPE_VIDEO:
3493                 if (av1->width == av->width &&
3494                     av1->height == av->height &&
3495                     av1->time_base.den == av->time_base.den &&
3496                     av1->time_base.num == av->time_base.num &&
3497                     av1->gop_size == av->gop_size)
3498                     goto found;
3499                 break;
3500             default:
3501                 abort();
3502             }
3503         }
3504     }
3505
3506     fst = add_av_stream1(feed, av);
3507     if (!fst)
3508         return -1;
3509     return feed->nb_streams - 1;
3510  found:
3511     return i;
3512 }
3513
3514 static void remove_stream(FFStream *stream)
3515 {
3516     FFStream **ps;
3517     ps = &first_stream;
3518     while (*ps != NULL) {
3519         if (*ps == stream)
3520             *ps = (*ps)->next;
3521         else
3522             ps = &(*ps)->next;
3523     }
3524 }
3525
3526 /* specific mpeg4 handling : we extract the raw parameters */
3527 static void extract_mpeg4_header(AVFormatContext *infile)
3528 {
3529     int mpeg4_count, i, size;
3530     AVPacket pkt;
3531     AVStream *st;
3532     const uint8_t *p;
3533
3534     mpeg4_count = 0;
3535     for(i=0;i<infile->nb_streams;i++) {
3536         st = infile->streams[i];
3537         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3538             st->codec->extradata_size == 0) {
3539             mpeg4_count++;
3540         }
3541     }
3542     if (!mpeg4_count)
3543         return;
3544
3545     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3546     while (mpeg4_count > 0) {
3547         if (av_read_packet(infile, &pkt) < 0)
3548             break;
3549         st = infile->streams[pkt.stream_index];
3550         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3551             st->codec->extradata_size == 0) {
3552             av_freep(&st->codec->extradata);
3553             /* fill extradata with the header */
3554             /* XXX: we make hard suppositions here ! */
3555             p = pkt.data;
3556             while (p < pkt.data + pkt.size - 4) {
3557                 /* stop when vop header is found */
3558                 if (p[0] == 0x00 && p[1] == 0x00 &&
3559                     p[2] == 0x01 && p[3] == 0xb6) {
3560                     size = p - pkt.data;
3561                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3562                     st->codec->extradata = av_malloc(size);
3563                     st->codec->extradata_size = size;
3564                     memcpy(st->codec->extradata, pkt.data, size);
3565                     break;
3566                 }
3567                 p++;
3568             }
3569             mpeg4_count--;
3570         }
3571         av_free_packet(&pkt);
3572     }
3573 }
3574
3575 /* compute the needed AVStream for each file */
3576 static void build_file_streams(void)
3577 {
3578     FFStream *stream, *stream_next;
3579     AVFormatContext *infile;
3580     int i, ret;
3581
3582     /* gather all streams */
3583     for(stream = first_stream; stream != NULL; stream = stream_next) {
3584         stream_next = stream->next;
3585         if (stream->stream_type == STREAM_TYPE_LIVE &&
3586             !stream->feed) {
3587             /* the stream comes from a file */
3588             /* try to open the file */
3589             /* open stream */
3590             stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
3591             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3592                 /* specific case : if transport stream output to RTP,
3593                    we use a raw transport stream reader */
3594                 stream->ap_in->mpeg2ts_raw = 1;
3595                 stream->ap_in->mpeg2ts_compute_pcr = 1;
3596             }
3597
3598             http_log("Opening file '%s'\n", stream->feed_filename);
3599             if ((ret = av_open_input_file(&infile, stream->feed_filename,
3600                                           stream->ifmt, 0, stream->ap_in)) < 0) {
3601                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3602                 /* remove stream (no need to spend more time on it) */
3603             fail:
3604                 remove_stream(stream);
3605             } else {
3606                 /* find all the AVStreams inside and reference them in
3607                    'stream' */
3608                 if (av_find_stream_info(infile) < 0) {
3609                     http_log("Could not find codec parameters from '%s'\n",
3610                              stream->feed_filename);
3611                     av_close_input_file(infile);
3612                     goto fail;
3613                 }
3614                 extract_mpeg4_header(infile);
3615
3616                 for(i=0;i<infile->nb_streams;i++)
3617                     add_av_stream1(stream, infile->streams[i]->codec);
3618
3619                 av_close_input_file(infile);
3620             }
3621         }
3622     }
3623 }
3624
3625 /* compute the needed AVStream for each feed */
3626 static void build_feed_streams(void)
3627 {
3628     FFStream *stream, *feed;
3629     int i;
3630
3631     /* gather all streams */
3632     for(stream = first_stream; stream != NULL; stream = stream->next) {
3633         feed = stream->feed;
3634         if (feed) {
3635             if (!stream->is_feed) {
3636                 /* we handle a stream coming from a feed */
3637                 for(i=0;i<stream->nb_streams;i++)
3638                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3639             }
3640         }
3641     }
3642
3643     /* gather all streams */
3644     for(stream = first_stream; stream != NULL; stream = stream->next) {
3645         feed = stream->feed;
3646         if (feed) {
3647             if (stream->is_feed) {
3648                 for(i=0;i<stream->nb_streams;i++)
3649                     stream->feed_streams[i] = i;
3650             }
3651         }
3652     }
3653
3654     /* create feed files if needed */
3655     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3656         int fd;
3657
3658         if (url_exist(feed->feed_filename)) {
3659             /* See if it matches */
3660             AVFormatContext *s;
3661             int matches = 0;
3662
3663             if (av_open_input_file(&s, feed->feed_filename, NULL, FFM_PACKET_SIZE, NULL) >= 0) {
3664                 /* Now see if it matches */
3665                 if (s->nb_streams == feed->nb_streams) {
3666                     matches = 1;
3667                     for(i=0;i<s->nb_streams;i++) {
3668                         AVStream *sf, *ss;
3669                         sf = feed->streams[i];
3670                         ss = s->streams[i];
3671
3672                         if (sf->index != ss->index ||
3673                             sf->id != ss->id) {
3674                             http_log("Index & Id do not match for stream %d (%s)\n",
3675                                    i, feed->feed_filename);
3676                             matches = 0;
3677                         } else {
3678                             AVCodecContext *ccf, *ccs;
3679
3680                             ccf = sf->codec;
3681                             ccs = ss->codec;
3682 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3683
3684                             if (CHECK_CODEC(codec) || CHECK_CODEC(codec_type)) {
3685                                 http_log("Codecs do not match for stream %d\n", i);
3686                                 matches = 0;
3687                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3688                                 http_log("Codec bitrates do not match for stream %d\n", i);
3689                                 matches = 0;
3690                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3691                                 if (CHECK_CODEC(time_base.den) ||
3692                                     CHECK_CODEC(time_base.num) ||
3693                                     CHECK_CODEC(width) ||
3694                                     CHECK_CODEC(height)) {
3695                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3696                                     matches = 0;
3697                                 }
3698                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3699                                 if (CHECK_CODEC(sample_rate) ||
3700                                     CHECK_CODEC(channels) ||
3701                                     CHECK_CODEC(frame_size)) {
3702                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3703                                     matches = 0;
3704                                 }
3705                             } else {
3706                                 http_log("Unknown codec type\n");
3707                                 matches = 0;
3708                             }
3709                         }
3710                         if (!matches)
3711                             break;
3712                     }
3713                 } else
3714                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3715                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3716
3717                 av_close_input_file(s);
3718             } else
3719                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3720                         feed->feed_filename);
3721
3722             if (!matches) {
3723                 if (feed->readonly) {
3724                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3725                         feed->feed_filename);
3726                     exit(1);
3727                 }
3728                 unlink(feed->feed_filename);
3729             }
3730         }
3731         if (!url_exist(feed->feed_filename)) {
3732             AVFormatContext s1 = {0}, *s = &s1;
3733
3734             if (feed->readonly) {
3735                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3736                     feed->feed_filename);
3737                 exit(1);
3738             }
3739
3740             /* only write the header of the ffm file */
3741             if (url_fopen(&s->pb, feed->feed_filename, URL_WRONLY) < 0) {
3742                 http_log("Could not open output feed file '%s'\n",
3743                          feed->feed_filename);
3744                 exit(1);
3745             }
3746             s->oformat = feed->fmt;
3747             s->nb_streams = feed->nb_streams;
3748             for(i=0;i<s->nb_streams;i++) {
3749                 AVStream *st;
3750                 st = feed->streams[i];
3751                 s->streams[i] = st;
3752             }
3753             av_set_parameters(s, NULL);
3754             if (av_write_header(s) < 0) {
3755                 http_log("Container doesn't supports the required parameters\n");
3756                 exit(1);
3757             }
3758             /* XXX: need better api */
3759             av_freep(&s->priv_data);
3760             url_fclose(s->pb);
3761         }
3762         /* get feed size and write index */
3763         fd = open(feed->feed_filename, O_RDONLY);
3764         if (fd < 0) {
3765             http_log("Could not open output feed file '%s'\n",
3766                     feed->feed_filename);
3767             exit(1);
3768         }
3769
3770         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3771         feed->feed_size = lseek(fd, 0, SEEK_END);
3772         /* ensure that we do not wrap before the end of file */
3773         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3774             feed->feed_max_size = feed->feed_size;
3775
3776         close(fd);
3777     }
3778 }
3779
3780 /* compute the bandwidth used by each stream */
3781 static void compute_bandwidth(void)
3782 {
3783     unsigned bandwidth;
3784     int i;
3785     FFStream *stream;
3786
3787     for(stream = first_stream; stream != NULL; stream = stream->next) {
3788         bandwidth = 0;
3789         for(i=0;i<stream->nb_streams;i++) {
3790             AVStream *st = stream->streams[i];
3791             switch(st->codec->codec_type) {
3792             case AVMEDIA_TYPE_AUDIO:
3793             case AVMEDIA_TYPE_VIDEO:
3794                 bandwidth += st->codec->bit_rate;
3795                 break;
3796             default:
3797                 break;
3798             }
3799         }
3800         stream->bandwidth = (bandwidth + 999) / 1000;
3801     }
3802 }
3803
3804 /* add a codec and set the default parameters */
3805 static void add_codec(FFStream *stream, AVCodecContext *av)
3806 {
3807     AVStream *st;
3808
3809     /* compute default parameters */
3810     switch(av->codec_type) {
3811     case AVMEDIA_TYPE_AUDIO:
3812         if (av->bit_rate == 0)
3813             av->bit_rate = 64000;
3814         if (av->sample_rate == 0)
3815             av->sample_rate = 22050;
3816         if (av->channels == 0)
3817             av->channels = 1;
3818         break;
3819     case AVMEDIA_TYPE_VIDEO:
3820         if (av->bit_rate == 0)
3821             av->bit_rate = 64000;
3822         if (av->time_base.num == 0){
3823             av->time_base.den = 5;
3824             av->time_base.num = 1;
3825         }
3826         if (av->width == 0 || av->height == 0) {
3827             av->width = 160;
3828             av->height = 128;
3829         }
3830         /* Bitrate tolerance is less for streaming */
3831         if (av->bit_rate_tolerance == 0)
3832             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3833                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3834         if (av->qmin == 0)
3835             av->qmin = 3;
3836         if (av->qmax == 0)
3837             av->qmax = 31;
3838         if (av->max_qdiff == 0)
3839             av->max_qdiff = 3;
3840         av->qcompress = 0.5;
3841         av->qblur = 0.5;
3842
3843         if (!av->nsse_weight)
3844             av->nsse_weight = 8;
3845
3846         av->frame_skip_cmp = FF_CMP_DCTMAX;
3847         if (!av->me_method)
3848             av->me_method = ME_EPZS;
3849         av->rc_buffer_aggressivity = 1.0;
3850
3851         if (!av->rc_eq)
3852             av->rc_eq = "tex^qComp";
3853         if (!av->i_quant_factor)
3854             av->i_quant_factor = -0.8;
3855         if (!av->b_quant_factor)
3856             av->b_quant_factor = 1.25;
3857         if (!av->b_quant_offset)
3858             av->b_quant_offset = 1.25;
3859         if (!av->rc_max_rate)
3860             av->rc_max_rate = av->bit_rate * 2;
3861
3862         if (av->rc_max_rate && !av->rc_buffer_size) {
3863             av->rc_buffer_size = av->rc_max_rate;
3864         }
3865
3866
3867         break;
3868     default:
3869         abort();
3870     }
3871
3872     st = av_mallocz(sizeof(AVStream));
3873     if (!st)
3874         return;
3875     st->codec = avcodec_alloc_context();
3876     stream->streams[stream->nb_streams++] = st;
3877     memcpy(st->codec, av, sizeof(AVCodecContext));
3878 }
3879
3880 static enum CodecID opt_audio_codec(const char *arg)
3881 {
3882     AVCodec *p= avcodec_find_encoder_by_name(arg);
3883
3884     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3885         return CODEC_ID_NONE;
3886
3887     return p->id;
3888 }
3889
3890 static enum CodecID opt_video_codec(const char *arg)
3891 {
3892     AVCodec *p= avcodec_find_encoder_by_name(arg);
3893
3894     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3895         return CODEC_ID_NONE;
3896
3897     return p->id;
3898 }
3899
3900 /* simplistic plugin support */
3901
3902 #if HAVE_DLOPEN
3903 static void load_module(const char *filename)
3904 {
3905     void *dll;
3906     void (*init_func)(void);
3907     dll = dlopen(filename, RTLD_NOW);
3908     if (!dll) {
3909         fprintf(stderr, "Could not load module '%s' - %s\n",
3910                 filename, dlerror());
3911         return;
3912     }
3913
3914     init_func = dlsym(dll, "ffserver_module_init");
3915     if (!init_func) {
3916         fprintf(stderr,
3917                 "%s: init function 'ffserver_module_init()' not found\n",
3918                 filename);
3919         dlclose(dll);
3920     }
3921
3922     init_func();
3923 }
3924 #endif
3925
3926 static int ffserver_opt_default(const char *opt, const char *arg,
3927                        AVCodecContext *avctx, int type)
3928 {
3929     int ret = 0;
3930     const AVOption *o = av_find_opt(avctx, opt, NULL, type, type);
3931     if(o)
3932         ret = av_set_string3(avctx, opt, arg, 1, NULL);
3933     return ret;
3934 }
3935
3936 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
3937                                              const char *mime_type)
3938 {
3939     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3940
3941     if (fmt) {
3942         AVOutputFormat *stream_fmt;
3943         char stream_format_name[64];
3944
3945         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
3946         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
3947
3948         if (stream_fmt)
3949             fmt = stream_fmt;
3950     }
3951
3952     return fmt;
3953 }
3954
3955 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
3956 {
3957     va_list vl;
3958     va_start(vl, fmt);
3959     fprintf(stderr, "%s:%d: ", filename, line_num);
3960     vfprintf(stderr, fmt, vl);
3961     va_end(vl);
3962
3963     (*errors)++;
3964 }
3965
3966 static int parse_ffconfig(const char *filename)
3967 {
3968     FILE *f;
3969     char line[1024];
3970     char cmd[64];
3971     char arg[1024];
3972     const char *p;
3973     int val, errors, line_num;
3974     FFStream **last_stream, *stream, *redirect;
3975     FFStream **last_feed, *feed, *s;
3976     AVCodecContext audio_enc, video_enc;
3977     enum CodecID audio_id, video_id;
3978
3979     f = fopen(filename, "r");
3980     if (!f) {
3981         perror(filename);
3982         return -1;
3983     }
3984
3985     errors = 0;
3986     line_num = 0;
3987     first_stream = NULL;
3988     last_stream = &first_stream;
3989     first_feed = NULL;
3990     last_feed = &first_feed;
3991     stream = NULL;
3992     feed = NULL;
3993     redirect = NULL;
3994     audio_id = CODEC_ID_NONE;
3995     video_id = CODEC_ID_NONE;
3996
3997 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
3998     for(;;) {
3999         if (fgets(line, sizeof(line), f) == NULL)
4000             break;
4001         line_num++;
4002         p = line;
4003         while (isspace(*p))
4004             p++;
4005         if (*p == '\0' || *p == '#')
4006             continue;
4007
4008         get_arg(cmd, sizeof(cmd), &p);
4009
4010         if (!strcasecmp(cmd, "Port")) {
4011             get_arg(arg, sizeof(arg), &p);
4012             val = atoi(arg);
4013             if (val < 1 || val > 65536) {
4014                 ERROR("Invalid_port: %s\n", arg);
4015             }
4016             my_http_addr.sin_port = htons(val);
4017         } else if (!strcasecmp(cmd, "BindAddress")) {
4018             get_arg(arg, sizeof(arg), &p);
4019             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4020                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4021             }
4022         } else if (!strcasecmp(cmd, "NoDaemon")) {
4023             ffserver_daemon = 0;
4024         } else if (!strcasecmp(cmd, "RTSPPort")) {
4025             get_arg(arg, sizeof(arg), &p);
4026             val = atoi(arg);
4027             if (val < 1 || val > 65536) {
4028                 ERROR("%s:%d: Invalid port: %s\n", arg);
4029             }
4030             my_rtsp_addr.sin_port = htons(atoi(arg));
4031         } else if (!strcasecmp(cmd, "RTSPBindAddress")) {
4032             get_arg(arg, sizeof(arg), &p);
4033             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4034                 ERROR("Invalid host/IP address: %s\n", arg);
4035             }
4036         } else if (!strcasecmp(cmd, "MaxHTTPConnections")) {
4037             get_arg(arg, sizeof(arg), &p);
4038             val = atoi(arg);
4039             if (val < 1 || val > 65536) {
4040                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4041             }
4042             nb_max_http_connections = val;
4043         } else if (!strcasecmp(cmd, "MaxClients")) {
4044             get_arg(arg, sizeof(arg), &p);
4045             val = atoi(arg);
4046             if (val < 1 || val > nb_max_http_connections) {
4047                 ERROR("Invalid MaxClients: %s\n", arg);
4048             } else {
4049                 nb_max_connections = val;
4050             }
4051         } else if (!strcasecmp(cmd, "MaxBandwidth")) {
4052             int64_t llval;
4053             get_arg(arg, sizeof(arg), &p);
4054             llval = atoll(arg);
4055             if (llval < 10 || llval > 10000000) {
4056                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4057             } else
4058                 max_bandwidth = llval;
4059         } else if (!strcasecmp(cmd, "CustomLog")) {
4060             if (!ffserver_debug)
4061                 get_arg(logfilename, sizeof(logfilename), &p);
4062         } else if (!strcasecmp(cmd, "<Feed")) {
4063             /*********************************************/
4064             /* Feed related options */
4065             char *q;
4066             if (stream || feed) {
4067                 ERROR("Already in a tag\n");
4068             } else {
4069                 feed = av_mallocz(sizeof(FFStream));
4070                 get_arg(feed->filename, sizeof(feed->filename), &p);
4071                 q = strrchr(feed->filename, '>');
4072                 if (*q)
4073                     *q = '\0';
4074
4075                 for (s = first_feed; s; s = s->next) {
4076                     if (!strcmp(feed->filename, s->filename)) {
4077                         ERROR("Feed '%s' already registered\n", s->filename);
4078                     }
4079                 }
4080
4081                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4082                 /* defaut feed file */
4083                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4084                          "/tmp/%s.ffm", feed->filename);
4085                 feed->feed_max_size = 5 * 1024 * 1024;
4086                 feed->is_feed = 1;
4087                 feed->feed = feed; /* self feeding :-) */
4088
4089                 /* add in stream list */
4090                 *last_stream = feed;
4091                 last_stream = &feed->next;
4092                 /* add in feed list */
4093                 *last_feed = feed;
4094                 last_feed = &feed->next_feed;
4095             }
4096         } else if (!strcasecmp(cmd, "Launch")) {
4097             if (feed) {
4098                 int i;
4099
4100                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4101
4102                 for (i = 0; i < 62; i++) {
4103                     get_arg(arg, sizeof(arg), &p);
4104                     if (!arg[0])
4105                         break;
4106
4107                     feed->child_argv[i] = av_strdup(arg);
4108                 }
4109
4110                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4111
4112                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4113                     "http://%s:%d/%s",
4114                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4115                     inet_ntoa(my_http_addr.sin_addr),
4116                     ntohs(my_http_addr.sin_port), feed->filename);
4117             }
4118         } else if (!strcasecmp(cmd, "ReadOnlyFile")) {
4119             if (feed) {
4120                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4121                 feed->readonly = 1;
4122             } else if (stream) {
4123                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4124             }
4125         } else if (!strcasecmp(cmd, "File")) {
4126             if (feed) {
4127                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4128             } else if (stream)
4129                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4130         } else if (!strcasecmp(cmd, "Truncate")) {
4131             if (feed) {
4132                 get_arg(arg, sizeof(arg), &p);
4133                 feed->truncate = strtod(arg, NULL);
4134             }
4135         } else if (!strcasecmp(cmd, "FileMaxSize")) {
4136             if (feed) {
4137                 char *p1;
4138                 double fsize;
4139
4140                 get_arg(arg, sizeof(arg), &p);
4141                 p1 = arg;
4142                 fsize = strtod(p1, &p1);
4143                 switch(toupper(*p1)) {
4144                 case 'K':
4145                     fsize *= 1024;
4146                     break;
4147                 case 'M':
4148                     fsize *= 1024 * 1024;
4149                     break;
4150                 case 'G':
4151                     fsize *= 1024 * 1024 * 1024;
4152                     break;
4153                 }
4154                 feed->feed_max_size = (int64_t)fsize;
4155                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4156                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4157                 }
4158             }
4159         } else if (!strcasecmp(cmd, "</Feed>")) {
4160             if (!feed) {
4161                 ERROR("No corresponding <Feed> for </Feed>\n");
4162             }
4163             feed = NULL;
4164         } else if (!strcasecmp(cmd, "<Stream")) {
4165             /*********************************************/
4166             /* Stream related options */
4167             char *q;
4168             if (stream || feed) {
4169                 ERROR("Already in a tag\n");
4170             } else {
4171                 FFStream *s;
4172                 stream = av_mallocz(sizeof(FFStream));
4173                 get_arg(stream->filename, sizeof(stream->filename), &p);
4174                 q = strrchr(stream->filename, '>');
4175                 if (*q)
4176                     *q = '\0';
4177
4178                 for (s = first_stream; s; s = s->next) {
4179                     if (!strcmp(stream->filename, s->filename)) {
4180                         ERROR("Stream '%s' already registered\n", s->filename);
4181                     }
4182                 }
4183
4184                 stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4185                 avcodec_get_context_defaults2(&video_enc, AVMEDIA_TYPE_VIDEO);
4186                 avcodec_get_context_defaults2(&audio_enc, AVMEDIA_TYPE_AUDIO);
4187                 audio_id = CODEC_ID_NONE;
4188                 video_id = CODEC_ID_NONE;
4189                 if (stream->fmt) {
4190                     audio_id = stream->fmt->audio_codec;
4191                     video_id = stream->fmt->video_codec;
4192                 }
4193
4194                 *last_stream = stream;
4195                 last_stream = &stream->next;
4196             }
4197         } else if (!strcasecmp(cmd, "Feed")) {
4198             get_arg(arg, sizeof(arg), &p);
4199             if (stream) {
4200                 FFStream *sfeed;
4201
4202                 sfeed = first_feed;
4203                 while (sfeed != NULL) {
4204                     if (!strcmp(sfeed->filename, arg))
4205                         break;
4206                     sfeed = sfeed->next_feed;
4207                 }
4208                 if (!sfeed)
4209                     ERROR("feed '%s' not defined\n", arg);
4210                 else
4211                     stream->feed = sfeed;
4212             }
4213         } else if (!strcasecmp(cmd, "Format")) {
4214             get_arg(arg, sizeof(arg), &p);
4215             if (stream) {
4216                 if (!strcmp(arg, "status")) {
4217                     stream->stream_type = STREAM_TYPE_STATUS;
4218                     stream->fmt = NULL;
4219                 } else {
4220                     stream->stream_type = STREAM_TYPE_LIVE;
4221                     /* jpeg cannot be used here, so use single frame jpeg */
4222                     if (!strcmp(arg, "jpeg"))
4223                         strcpy(arg, "mjpeg");
4224                     stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4225                     if (!stream->fmt) {
4226                         ERROR("Unknown Format: %s\n", arg);
4227                     }
4228                 }
4229                 if (stream->fmt) {
4230                     audio_id = stream->fmt->audio_codec;
4231                     video_id = stream->fmt->video_codec;
4232                 }
4233             }
4234         } else if (!strcasecmp(cmd, "InputFormat")) {
4235             get_arg(arg, sizeof(arg), &p);
4236             if (stream) {
4237                 stream->ifmt = av_find_input_format(arg);
4238                 if (!stream->ifmt) {
4239                     ERROR("Unknown input format: %s\n", arg);
4240                 }
4241             }
4242         } else if (!strcasecmp(cmd, "FaviconURL")) {
4243             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4244                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4245             } else {
4246                 ERROR("FaviconURL only permitted for status streams\n");
4247             }
4248         } else if (!strcasecmp(cmd, "Author")) {
4249             if (stream)
4250                 get_arg(stream->author, sizeof(stream->author), &p);
4251         } else if (!strcasecmp(cmd, "Comment")) {
4252             if (stream)
4253                 get_arg(stream->comment, sizeof(stream->comment), &p);
4254         } else if (!strcasecmp(cmd, "Copyright")) {
4255             if (stream)
4256                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4257         } else if (!strcasecmp(cmd, "Title")) {
4258             if (stream)
4259                 get_arg(stream->title, sizeof(stream->title), &p);
4260         } else if (!strcasecmp(cmd, "Preroll")) {
4261             get_arg(arg, sizeof(arg), &p);
4262             if (stream)
4263                 stream->prebuffer = atof(arg) * 1000;
4264         } else if (!strcasecmp(cmd, "StartSendOnKey")) {
4265             if (stream)
4266                 stream->send_on_key = 1;
4267         } else if (!strcasecmp(cmd, "AudioCodec")) {
4268             get_arg(arg, sizeof(arg), &p);
4269             audio_id = opt_audio_codec(arg);
4270             if (audio_id == CODEC_ID_NONE) {
4271                 ERROR("Unknown AudioCodec: %s\n", arg);
4272             }
4273         } else if (!strcasecmp(cmd, "VideoCodec")) {
4274             get_arg(arg, sizeof(arg), &p);
4275             video_id = opt_video_codec(arg);
4276             if (video_id == CODEC_ID_NONE) {
4277                 ERROR("Unknown VideoCodec: %s\n", arg);
4278             }
4279         } else if (!strcasecmp(cmd, "MaxTime")) {
4280             get_arg(arg, sizeof(arg), &p);
4281             if (stream)
4282                 stream->max_time = atof(arg)&n