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