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