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