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