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