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