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