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