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