00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #define _XOPEN_SOURCE 600
00023
00024 #include "config.h"
00025 #if !HAVE_CLOSESOCKET
00026 #define closesocket close
00027 #endif
00028 #include <string.h>
00029 #include <strings.h>
00030 #include <stdlib.h>
00031 #include "libavformat/avformat.h"
00032 #include "libavformat/network.h"
00033 #include "libavformat/os_support.h"
00034 #include "libavformat/rtpdec.h"
00035 #include "libavformat/rtsp.h"
00036 #include "libavutil/avstring.h"
00037 #include "libavutil/lfg.h"
00038 #include "libavutil/random_seed.h"
00039 #include "libavcore/parseutils.h"
00040 #include "libavcodec/opt.h"
00041 #include <stdarg.h>
00042 #include <unistd.h>
00043 #include <fcntl.h>
00044 #include <sys/ioctl.h>
00045 #if HAVE_POLL_H
00046 #include <poll.h>
00047 #endif
00048 #include <errno.h>
00049 #include <sys/time.h>
00050 #include <time.h>
00051 #include <sys/wait.h>
00052 #include <signal.h>
00053 #if HAVE_DLFCN_H
00054 #include <dlfcn.h>
00055 #endif
00056
00057 #include "cmdutils.h"
00058
00059 const char program_name[] = "FFserver";
00060 const int program_birth_year = 2000;
00061
00062 static const OptionDef options[];
00063
00064 enum HTTPState {
00065 HTTPSTATE_WAIT_REQUEST,
00066 HTTPSTATE_SEND_HEADER,
00067 HTTPSTATE_SEND_DATA_HEADER,
00068 HTTPSTATE_SEND_DATA,
00069 HTTPSTATE_SEND_DATA_TRAILER,
00070 HTTPSTATE_RECEIVE_DATA,
00071 HTTPSTATE_WAIT_FEED,
00072 HTTPSTATE_READY,
00073
00074 RTSPSTATE_WAIT_REQUEST,
00075 RTSPSTATE_SEND_REPLY,
00076 RTSPSTATE_SEND_PACKET,
00077 };
00078
00079 static const char *http_state[] = {
00080 "HTTP_WAIT_REQUEST",
00081 "HTTP_SEND_HEADER",
00082
00083 "SEND_DATA_HEADER",
00084 "SEND_DATA",
00085 "SEND_DATA_TRAILER",
00086 "RECEIVE_DATA",
00087 "WAIT_FEED",
00088 "READY",
00089
00090 "RTSP_WAIT_REQUEST",
00091 "RTSP_SEND_REPLY",
00092 "RTSP_SEND_PACKET",
00093 };
00094
00095 #if !FF_API_MAX_STREAMS
00096 #define MAX_STREAMS 20
00097 #endif
00098
00099 #define IOBUFFER_INIT_SIZE 8192
00100
00101
00102 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
00103 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
00104
00105 #define SYNC_TIMEOUT (10 * 1000)
00106
00107 typedef struct RTSPActionServerSetup {
00108 uint32_t ipaddr;
00109 char transport_option[512];
00110 } RTSPActionServerSetup;
00111
00112 typedef struct {
00113 int64_t count1, count2;
00114 int64_t time1, time2;
00115 } DataRateData;
00116
00117
00118 typedef struct HTTPContext {
00119 enum HTTPState state;
00120 int fd;
00121 struct sockaddr_in from_addr;
00122 struct pollfd *poll_entry;
00123 int64_t timeout;
00124 uint8_t *buffer_ptr, *buffer_end;
00125 int http_error;
00126 int post;
00127 int chunked_encoding;
00128 int chunk_size;
00129 struct HTTPContext *next;
00130 int got_key_frame;
00131 int64_t data_count;
00132
00133 int feed_fd;
00134
00135 AVFormatContext *fmt_in;
00136 int64_t start_time;
00137 int64_t first_pts;
00138 int64_t cur_pts;
00139 int64_t cur_frame_duration;
00140 int cur_frame_bytes;
00141
00142
00143 int pts_stream_index;
00144 int64_t cur_clock;
00145
00146 struct FFStream *stream;
00147
00148 int feed_streams[MAX_STREAMS];
00149 int switch_feed_streams[MAX_STREAMS];
00150 int switch_pending;
00151 AVFormatContext fmt_ctx;
00152 int last_packet_sent;
00153 int suppress_log;
00154 DataRateData datarate;
00155 int wmp_client_id;
00156 char protocol[16];
00157 char method[16];
00158 char url[128];
00159 int buffer_size;
00160 uint8_t *buffer;
00161 int is_packetized;
00162 int packet_stream_index;
00163
00164
00165 uint8_t *pb_buffer;
00166 ByteIOContext *pb;
00167 int seq;
00168
00169
00170 enum RTSPLowerTransport rtp_protocol;
00171 char session_id[32];
00172 AVFormatContext *rtp_ctx[MAX_STREAMS];
00173
00174
00175 URLContext *rtp_handles[MAX_STREAMS];
00176
00177
00178 struct HTTPContext *rtsp_c;
00179 uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
00180 } HTTPContext;
00181
00182
00183 enum StreamType {
00184 STREAM_TYPE_LIVE,
00185 STREAM_TYPE_STATUS,
00186 STREAM_TYPE_REDIRECT,
00187 };
00188
00189 enum IPAddressAction {
00190 IP_ALLOW = 1,
00191 IP_DENY,
00192 };
00193
00194 typedef struct IPAddressACL {
00195 struct IPAddressACL *next;
00196 enum IPAddressAction action;
00197
00198 struct in_addr first;
00199 struct in_addr last;
00200 } IPAddressACL;
00201
00202
00203 typedef struct FFStream {
00204 enum StreamType stream_type;
00205 char filename[1024];
00206 struct FFStream *feed;
00207
00208 AVFormatParameters *ap_in;
00209 AVInputFormat *ifmt;
00210 AVOutputFormat *fmt;
00211 IPAddressACL *acl;
00212 char dynamic_acl[1024];
00213 int nb_streams;
00214 int prebuffer;
00215 int64_t max_time;
00216 int send_on_key;
00217 AVStream *streams[MAX_STREAMS];
00218 int feed_streams[MAX_STREAMS];
00219 char feed_filename[1024];
00220
00221 char author[512];
00222 char title[512];
00223 char copyright[512];
00224 char comment[512];
00225 pid_t pid;
00226 time_t pid_start;
00227 char **child_argv;
00228 struct FFStream *next;
00229 unsigned bandwidth;
00230
00231 char *rtsp_option;
00232
00233 int is_multicast;
00234 struct in_addr multicast_ip;
00235 int multicast_port;
00236 int multicast_ttl;
00237 int loop;
00238
00239
00240 int feed_opened;
00241 int is_feed;
00242 int readonly;
00243 int truncate;
00244 int conns_served;
00245 int64_t bytes_served;
00246 int64_t feed_max_size;
00247 int64_t feed_write_index;
00248 int64_t feed_size;
00249 struct FFStream *next_feed;
00250 } FFStream;
00251
00252 typedef struct FeedData {
00253 long long data_count;
00254 float avg_frame_size;
00255 } FeedData;
00256
00257 static struct sockaddr_in my_http_addr;
00258 static struct sockaddr_in my_rtsp_addr;
00259
00260 static char logfilename[1024];
00261 static HTTPContext *first_http_ctx;
00262 static FFStream *first_feed;
00263 static FFStream *first_stream;
00264
00265 static void new_connection(int server_fd, int is_rtsp);
00266 static void close_connection(HTTPContext *c);
00267
00268
00269 static int handle_connection(HTTPContext *c);
00270 static int http_parse_request(HTTPContext *c);
00271 static int http_send_data(HTTPContext *c);
00272 static void compute_status(HTTPContext *c);
00273 static int open_input_stream(HTTPContext *c, const char *info);
00274 static int http_start_receive_data(HTTPContext *c);
00275 static int http_receive_data(HTTPContext *c);
00276
00277
00278 static int rtsp_parse_request(HTTPContext *c);
00279 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
00280 static void rtsp_cmd_options(HTTPContext *c, const char *url);
00281 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00282 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00283 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00284 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00285
00286
00287 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
00288 struct in_addr my_ip);
00289
00290
00291 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
00292 FFStream *stream, const char *session_id,
00293 enum RTSPLowerTransport rtp_protocol);
00294 static int rtp_new_av_stream(HTTPContext *c,
00295 int stream_index, struct sockaddr_in *dest_addr,
00296 HTTPContext *rtsp_c);
00297
00298 static const char *my_program_name;
00299 static const char *my_program_dir;
00300
00301 static const char *config_filename = "/etc/ffserver.conf";
00302
00303 static int ffserver_debug;
00304 static int ffserver_daemon;
00305 static int no_launch;
00306 static int need_to_start_children;
00307
00308
00309 static unsigned int nb_max_http_connections = 2000;
00310 static unsigned int nb_max_connections = 5;
00311 static unsigned int nb_connections;
00312
00313 static uint64_t max_bandwidth = 1000;
00314 static uint64_t current_bandwidth;
00315
00316 static int64_t cur_time;
00317
00318 static AVLFG random_state;
00319
00320 static FILE *logfile = NULL;
00321
00322
00323
00324 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
00325 {
00326
00327 if (!ff_inet_aton(hostname, sin_addr)) {
00328 #if HAVE_GETADDRINFO
00329 struct addrinfo *ai, *cur;
00330 struct addrinfo hints;
00331 memset(&hints, 0, sizeof(hints));
00332 hints.ai_family = AF_INET;
00333 if (getaddrinfo(hostname, NULL, &hints, &ai))
00334 return -1;
00335
00336
00337
00338 for (cur = ai; cur; cur = cur->ai_next) {
00339 if (cur->ai_family == AF_INET) {
00340 *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
00341 freeaddrinfo(ai);
00342 return 0;
00343 }
00344 }
00345 freeaddrinfo(ai);
00346 return -1;
00347 #else
00348 struct hostent *hp;
00349 hp = gethostbyname(hostname);
00350 if (!hp)
00351 return -1;
00352 memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
00353 #endif
00354 }
00355 return 0;
00356 }
00357
00358 static char *ctime1(char *buf2)
00359 {
00360 time_t ti;
00361 char *p;
00362
00363 ti = time(NULL);
00364 p = ctime(&ti);
00365 strcpy(buf2, p);
00366 p = buf2 + strlen(p) - 1;
00367 if (*p == '\n')
00368 *p = '\0';
00369 return buf2;
00370 }
00371
00372 static void http_vlog(const char *fmt, va_list vargs)
00373 {
00374 static int print_prefix = 1;
00375 if (logfile) {
00376 if (print_prefix) {
00377 char buf[32];
00378 ctime1(buf);
00379 fprintf(logfile, "%s ", buf);
00380 }
00381 print_prefix = strstr(fmt, "\n") != NULL;
00382 vfprintf(logfile, fmt, vargs);
00383 fflush(logfile);
00384 }
00385 }
00386
00387 static void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...)
00388 {
00389 va_list vargs;
00390 va_start(vargs, fmt);
00391 http_vlog(fmt, vargs);
00392 va_end(vargs);
00393 }
00394
00395 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
00396 {
00397 static int print_prefix = 1;
00398 AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
00399 if (level > av_log_get_level())
00400 return;
00401 if (print_prefix && avc)
00402 http_log("[%s @ %p]", avc->item_name(ptr), ptr);
00403 print_prefix = strstr(fmt, "\n") != NULL;
00404 http_vlog(fmt, vargs);
00405 }
00406
00407 static void log_connection(HTTPContext *c)
00408 {
00409 if (c->suppress_log)
00410 return;
00411
00412 http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
00413 inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
00414 c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
00415 }
00416
00417 static void update_datarate(DataRateData *drd, int64_t count)
00418 {
00419 if (!drd->time1 && !drd->count1) {
00420 drd->time1 = drd->time2 = cur_time;
00421 drd->count1 = drd->count2 = count;
00422 } else if (cur_time - drd->time2 > 5000) {
00423 drd->time1 = drd->time2;
00424 drd->count1 = drd->count2;
00425 drd->time2 = cur_time;
00426 drd->count2 = count;
00427 }
00428 }
00429
00430
00431 static int compute_datarate(DataRateData *drd, int64_t count)
00432 {
00433 if (cur_time == drd->time1)
00434 return 0;
00435
00436 return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
00437 }
00438
00439
00440 static void start_children(FFStream *feed)
00441 {
00442 if (no_launch)
00443 return;
00444
00445 for (; feed; feed = feed->next) {
00446 if (feed->child_argv && !feed->pid) {
00447 feed->pid_start = time(0);
00448
00449 feed->pid = fork();
00450
00451 if (feed->pid < 0) {
00452 http_log("Unable to create children\n");
00453 exit(1);
00454 }
00455 if (!feed->pid) {
00456
00457 char pathname[1024];
00458 char *slash;
00459 int i;
00460
00461 av_strlcpy(pathname, my_program_name, sizeof(pathname));
00462
00463 slash = strrchr(pathname, '/');
00464 if (!slash)
00465 slash = pathname;
00466 else
00467 slash++;
00468 strcpy(slash, "ffmpeg");
00469
00470 http_log("Launch commandline: ");
00471 http_log("%s ", pathname);
00472 for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
00473 http_log("%s ", feed->child_argv[i]);
00474 http_log("\n");
00475
00476 for (i = 3; i < 256; i++)
00477 close(i);
00478
00479 if (!ffserver_debug) {
00480 i = open("/dev/null", O_RDWR);
00481 if (i != -1) {
00482 dup2(i, 0);
00483 dup2(i, 1);
00484 dup2(i, 2);
00485 close(i);
00486 }
00487 }
00488
00489
00490 chdir(my_program_dir);
00491
00492 signal(SIGPIPE, SIG_DFL);
00493
00494 execvp(pathname, feed->child_argv);
00495
00496 _exit(1);
00497 }
00498 }
00499 }
00500 }
00501
00502
00503 static int socket_open_listen(struct sockaddr_in *my_addr)
00504 {
00505 int server_fd, tmp;
00506
00507 server_fd = socket(AF_INET,SOCK_STREAM,0);
00508 if (server_fd < 0) {
00509 perror ("socket");
00510 return -1;
00511 }
00512
00513 tmp = 1;
00514 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
00515
00516 if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
00517 char bindmsg[32];
00518 snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
00519 perror (bindmsg);
00520 closesocket(server_fd);
00521 return -1;
00522 }
00523
00524 if (listen (server_fd, 5) < 0) {
00525 perror ("listen");
00526 closesocket(server_fd);
00527 return -1;
00528 }
00529 ff_socket_nonblock(server_fd, 1);
00530
00531 return server_fd;
00532 }
00533
00534
00535 static void start_multicast(void)
00536 {
00537 FFStream *stream;
00538 char session_id[32];
00539 HTTPContext *rtp_c;
00540 struct sockaddr_in dest_addr;
00541 int default_port, stream_index;
00542
00543 default_port = 6000;
00544 for(stream = first_stream; stream != NULL; stream = stream->next) {
00545 if (stream->is_multicast) {
00546
00547 snprintf(session_id, sizeof(session_id), "%08x%08x",
00548 av_lfg_get(&random_state), av_lfg_get(&random_state));
00549
00550
00551 if (stream->multicast_port == 0) {
00552 stream->multicast_port = default_port;
00553 default_port += 100;
00554 }
00555
00556 dest_addr.sin_family = AF_INET;
00557 dest_addr.sin_addr = stream->multicast_ip;
00558 dest_addr.sin_port = htons(stream->multicast_port);
00559
00560 rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
00561 RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
00562 if (!rtp_c)
00563 continue;
00564
00565 if (open_input_stream(rtp_c, "") < 0) {
00566 http_log("Could not open input stream for stream '%s'\n",
00567 stream->filename);
00568 continue;
00569 }
00570
00571
00572 for(stream_index = 0; stream_index < stream->nb_streams;
00573 stream_index++) {
00574 dest_addr.sin_port = htons(stream->multicast_port +
00575 2 * stream_index);
00576 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
00577 http_log("Could not open output stream '%s/streamid=%d'\n",
00578 stream->filename, stream_index);
00579 exit(1);
00580 }
00581 }
00582
00583
00584 rtp_c->state = HTTPSTATE_SEND_DATA;
00585 }
00586 }
00587 }
00588
00589
00590 static int http_server(void)
00591 {
00592 int server_fd = 0, rtsp_server_fd = 0;
00593 int ret, delay, delay1;
00594 struct pollfd *poll_table, *poll_entry;
00595 HTTPContext *c, *c_next;
00596
00597 if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
00598 http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
00599 return -1;
00600 }
00601
00602 if (my_http_addr.sin_port) {
00603 server_fd = socket_open_listen(&my_http_addr);
00604 if (server_fd < 0)
00605 return -1;
00606 }
00607
00608 if (my_rtsp_addr.sin_port) {
00609 rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
00610 if (rtsp_server_fd < 0)
00611 return -1;
00612 }
00613
00614 if (!rtsp_server_fd && !server_fd) {
00615 http_log("HTTP and RTSP disabled.\n");
00616 return -1;
00617 }
00618
00619 http_log("FFserver started.\n");
00620
00621 start_children(first_feed);
00622
00623 start_multicast();
00624
00625 for(;;) {
00626 poll_entry = poll_table;
00627 if (server_fd) {
00628 poll_entry->fd = server_fd;
00629 poll_entry->events = POLLIN;
00630 poll_entry++;
00631 }
00632 if (rtsp_server_fd) {
00633 poll_entry->fd = rtsp_server_fd;
00634 poll_entry->events = POLLIN;
00635 poll_entry++;
00636 }
00637
00638
00639 c = first_http_ctx;
00640 delay = 1000;
00641 while (c != NULL) {
00642 int fd;
00643 fd = c->fd;
00644 switch(c->state) {
00645 case HTTPSTATE_SEND_HEADER:
00646 case RTSPSTATE_SEND_REPLY:
00647 case RTSPSTATE_SEND_PACKET:
00648 c->poll_entry = poll_entry;
00649 poll_entry->fd = fd;
00650 poll_entry->events = POLLOUT;
00651 poll_entry++;
00652 break;
00653 case HTTPSTATE_SEND_DATA_HEADER:
00654 case HTTPSTATE_SEND_DATA:
00655 case HTTPSTATE_SEND_DATA_TRAILER:
00656 if (!c->is_packetized) {
00657
00658 c->poll_entry = poll_entry;
00659 poll_entry->fd = fd;
00660 poll_entry->events = POLLOUT;
00661 poll_entry++;
00662 } else {
00663
00664
00665
00666 delay1 = 10;
00667 if (delay1 < delay)
00668 delay = delay1;
00669 }
00670 break;
00671 case HTTPSTATE_WAIT_REQUEST:
00672 case HTTPSTATE_RECEIVE_DATA:
00673 case HTTPSTATE_WAIT_FEED:
00674 case RTSPSTATE_WAIT_REQUEST:
00675
00676 c->poll_entry = poll_entry;
00677 poll_entry->fd = fd;
00678 poll_entry->events = POLLIN;
00679 poll_entry++;
00680 break;
00681 default:
00682 c->poll_entry = NULL;
00683 break;
00684 }
00685 c = c->next;
00686 }
00687
00688
00689
00690 do {
00691 ret = poll(poll_table, poll_entry - poll_table, delay);
00692 if (ret < 0 && ff_neterrno() != FF_NETERROR(EAGAIN) &&
00693 ff_neterrno() != FF_NETERROR(EINTR))
00694 return -1;
00695 } while (ret < 0);
00696
00697 cur_time = av_gettime() / 1000;
00698
00699 if (need_to_start_children) {
00700 need_to_start_children = 0;
00701 start_children(first_feed);
00702 }
00703
00704
00705 for(c = first_http_ctx; c != NULL; c = c_next) {
00706 c_next = c->next;
00707 if (handle_connection(c) < 0) {
00708
00709 log_connection(c);
00710 close_connection(c);
00711 }
00712 }
00713
00714 poll_entry = poll_table;
00715 if (server_fd) {
00716
00717 if (poll_entry->revents & POLLIN)
00718 new_connection(server_fd, 0);
00719 poll_entry++;
00720 }
00721 if (rtsp_server_fd) {
00722
00723 if (poll_entry->revents & POLLIN)
00724 new_connection(rtsp_server_fd, 1);
00725 }
00726 }
00727 }
00728
00729
00730 static void start_wait_request(HTTPContext *c, int is_rtsp)
00731 {
00732 c->buffer_ptr = c->buffer;
00733 c->buffer_end = c->buffer + c->buffer_size - 1;
00734
00735 if (is_rtsp) {
00736 c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
00737 c->state = RTSPSTATE_WAIT_REQUEST;
00738 } else {
00739 c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
00740 c->state = HTTPSTATE_WAIT_REQUEST;
00741 }
00742 }
00743
00744 static void http_send_too_busy_reply(int fd)
00745 {
00746 char buffer[300];
00747 int len = snprintf(buffer, sizeof(buffer),
00748 "HTTP/1.0 503 Server too busy\r\n"
00749 "Content-type: text/html\r\n"
00750 "\r\n"
00751 "<html><head><title>Too busy</title></head><body>\r\n"
00752 "<p>The server is too busy to serve your request at this time.</p>\r\n"
00753 "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
00754 "</body></html>\r\n",
00755 nb_connections, nb_max_connections);
00756 send(fd, buffer, len, 0);
00757 }
00758
00759
00760 static void new_connection(int server_fd, int is_rtsp)
00761 {
00762 struct sockaddr_in from_addr;
00763 int fd, len;
00764 HTTPContext *c = NULL;
00765
00766 len = sizeof(from_addr);
00767 fd = accept(server_fd, (struct sockaddr *)&from_addr,
00768 &len);
00769 if (fd < 0) {
00770 http_log("error during accept %s\n", strerror(errno));
00771 return;
00772 }
00773 ff_socket_nonblock(fd, 1);
00774
00775 if (nb_connections >= nb_max_connections) {
00776 http_send_too_busy_reply(fd);
00777 goto fail;
00778 }
00779
00780
00781 c = av_mallocz(sizeof(HTTPContext));
00782 if (!c)
00783 goto fail;
00784
00785 c->fd = fd;
00786 c->poll_entry = NULL;
00787 c->from_addr = from_addr;
00788 c->buffer_size = IOBUFFER_INIT_SIZE;
00789 c->buffer = av_malloc(c->buffer_size);
00790 if (!c->buffer)
00791 goto fail;
00792
00793 c->next = first_http_ctx;
00794 first_http_ctx = c;
00795 nb_connections++;
00796
00797 start_wait_request(c, is_rtsp);
00798
00799 return;
00800
00801 fail:
00802 if (c) {
00803 av_free(c->buffer);
00804 av_free(c);
00805 }
00806 closesocket(fd);
00807 }
00808
00809 static void close_connection(HTTPContext *c)
00810 {
00811 HTTPContext **cp, *c1;
00812 int i, nb_streams;
00813 AVFormatContext *ctx;
00814 URLContext *h;
00815 AVStream *st;
00816
00817
00818 cp = &first_http_ctx;
00819 while ((*cp) != NULL) {
00820 c1 = *cp;
00821 if (c1 == c)
00822 *cp = c->next;
00823 else
00824 cp = &c1->next;
00825 }
00826
00827
00828 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
00829 if (c1->rtsp_c == c)
00830 c1->rtsp_c = NULL;
00831 }
00832
00833
00834 if (c->fd >= 0)
00835 closesocket(c->fd);
00836 if (c->fmt_in) {
00837
00838 for(i=0;i<c->fmt_in->nb_streams;i++) {
00839 st = c->fmt_in->streams[i];
00840 if (st->codec->codec)
00841 avcodec_close(st->codec);
00842 }
00843 av_close_input_file(c->fmt_in);
00844 }
00845
00846
00847 nb_streams = 0;
00848 if (c->stream)
00849 nb_streams = c->stream->nb_streams;
00850
00851 for(i=0;i<nb_streams;i++) {
00852 ctx = c->rtp_ctx[i];
00853 if (ctx) {
00854 av_write_trailer(ctx);
00855 av_metadata_free(&ctx->metadata);
00856 av_free(ctx->streams[0]);
00857 av_free(ctx);
00858 }
00859 h = c->rtp_handles[i];
00860 if (h)
00861 url_close(h);
00862 }
00863
00864 ctx = &c->fmt_ctx;
00865
00866 if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
00867 if (ctx->oformat) {
00868
00869 if (url_open_dyn_buf(&ctx->pb) >= 0) {
00870 av_write_trailer(ctx);
00871 av_freep(&c->pb_buffer);
00872 url_close_dyn_buf(ctx->pb, &c->pb_buffer);
00873 }
00874 }
00875 }
00876
00877 for(i=0; i<ctx->nb_streams; i++)
00878 av_free(ctx->streams[i]);
00879
00880 if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
00881 current_bandwidth -= c->stream->bandwidth;
00882
00883
00884 if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
00885 c->stream->feed_opened = 0;
00886 close(c->feed_fd);
00887 }
00888
00889 av_freep(&c->pb_buffer);
00890 av_freep(&c->packet_buffer);
00891 av_free(c->buffer);
00892 av_free(c);
00893 nb_connections--;
00894 }
00895
00896 static int handle_connection(HTTPContext *c)
00897 {
00898 int len, ret;
00899
00900 switch(c->state) {
00901 case HTTPSTATE_WAIT_REQUEST:
00902 case RTSPSTATE_WAIT_REQUEST:
00903
00904 if ((c->timeout - cur_time) < 0)
00905 return -1;
00906 if (c->poll_entry->revents & (POLLERR | POLLHUP))
00907 return -1;
00908
00909
00910 if (!(c->poll_entry->revents & POLLIN))
00911 return 0;
00912
00913 read_loop:
00914 len = recv(c->fd, c->buffer_ptr, 1, 0);
00915 if (len < 0) {
00916 if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
00917 ff_neterrno() != FF_NETERROR(EINTR))
00918 return -1;
00919 } else if (len == 0) {
00920 return -1;
00921 } else {
00922
00923 uint8_t *ptr;
00924 c->buffer_ptr += len;
00925 ptr = c->buffer_ptr;
00926 if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
00927 (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
00928
00929 if (c->state == HTTPSTATE_WAIT_REQUEST) {
00930 ret = http_parse_request(c);
00931 } else {
00932 ret = rtsp_parse_request(c);
00933 }
00934 if (ret < 0)
00935 return -1;
00936 } else if (ptr >= c->buffer_end) {
00937
00938 return -1;
00939 } else goto read_loop;
00940 }
00941 break;
00942
00943 case HTTPSTATE_SEND_HEADER:
00944 if (c->poll_entry->revents & (POLLERR | POLLHUP))
00945 return -1;
00946
00947
00948 if (!(c->poll_entry->revents & POLLOUT))
00949 return 0;
00950 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
00951 if (len < 0) {
00952 if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
00953 ff_neterrno() != FF_NETERROR(EINTR)) {
00954
00955 av_freep(&c->pb_buffer);
00956 return -1;
00957 }
00958 } else {
00959 c->buffer_ptr += len;
00960 if (c->stream)
00961 c->stream->bytes_served += len;
00962 c->data_count += len;
00963 if (c->buffer_ptr >= c->buffer_end) {
00964 av_freep(&c->pb_buffer);
00965
00966 if (c->http_error)
00967 return -1;
00968
00969 c->state = HTTPSTATE_SEND_DATA_HEADER;
00970 c->buffer_ptr = c->buffer_end = c->buffer;
00971 }
00972 }
00973 break;
00974
00975 case HTTPSTATE_SEND_DATA:
00976 case HTTPSTATE_SEND_DATA_HEADER:
00977 case HTTPSTATE_SEND_DATA_TRAILER:
00978
00979
00980
00981 if (!c->is_packetized) {
00982 if (c->poll_entry->revents & (POLLERR | POLLHUP))
00983 return -1;
00984
00985
00986 if (!(c->poll_entry->revents & POLLOUT))
00987 return 0;
00988 }
00989 if (http_send_data(c) < 0)
00990 return -1;
00991
00992 if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
00993 return -1;
00994 break;
00995 case HTTPSTATE_RECEIVE_DATA:
00996
00997 if (c->poll_entry->revents & (POLLERR | POLLHUP))
00998 return -1;
00999 if (!(c->poll_entry->revents & POLLIN))
01000 return 0;
01001 if (http_receive_data(c) < 0)
01002 return -1;
01003 break;
01004 case HTTPSTATE_WAIT_FEED:
01005
01006 if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
01007 return -1;
01008
01009
01010 break;
01011
01012 case RTSPSTATE_SEND_REPLY:
01013 if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
01014 av_freep(&c->pb_buffer);
01015 return -1;
01016 }
01017
01018 if (!(c->poll_entry->revents & POLLOUT))
01019 return 0;
01020 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
01021 if (len < 0) {
01022 if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
01023 ff_neterrno() != FF_NETERROR(EINTR)) {
01024
01025 av_freep(&c->pb_buffer);
01026 return -1;
01027 }
01028 } else {
01029 c->buffer_ptr += len;
01030 c->data_count += len;
01031 if (c->buffer_ptr >= c->buffer_end) {
01032
01033 av_freep(&c->pb_buffer);
01034 start_wait_request(c, 1);
01035 }
01036 }
01037 break;
01038 case RTSPSTATE_SEND_PACKET:
01039 if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
01040 av_freep(&c->packet_buffer);
01041 return -1;
01042 }
01043
01044 if (!(c->poll_entry->revents & POLLOUT))
01045 return 0;
01046 len = send(c->fd, c->packet_buffer_ptr,
01047 c->packet_buffer_end - c->packet_buffer_ptr, 0);
01048 if (len < 0) {
01049 if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
01050 ff_neterrno() != FF_NETERROR(EINTR)) {
01051
01052 av_freep(&c->packet_buffer);
01053 return -1;
01054 }
01055 } else {
01056 c->packet_buffer_ptr += len;
01057 if (c->packet_buffer_ptr >= c->packet_buffer_end) {
01058
01059 av_freep(&c->packet_buffer);
01060 c->state = RTSPSTATE_WAIT_REQUEST;
01061 }
01062 }
01063 break;
01064 case HTTPSTATE_READY:
01065
01066 break;
01067 default:
01068 return -1;
01069 }
01070 return 0;
01071 }
01072
01073 static int extract_rates(char *rates, int ratelen, const char *request)
01074 {
01075 const char *p;
01076
01077 for (p = request; *p && *p != '\r' && *p != '\n'; ) {
01078 if (strncasecmp(p, "Pragma:", 7) == 0) {
01079 const char *q = p + 7;
01080
01081 while (*q && *q != '\n' && isspace(*q))
01082 q++;
01083
01084 if (strncasecmp(q, "stream-switch-entry=", 20) == 0) {
01085 int stream_no;
01086 int rate_no;
01087
01088 q += 20;
01089
01090 memset(rates, 0xff, ratelen);
01091
01092 while (1) {
01093 while (*q && *q != '\n' && *q != ':')
01094 q++;
01095
01096 if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
01097 break;
01098
01099 stream_no--;
01100 if (stream_no < ratelen && stream_no >= 0)
01101 rates[stream_no] = rate_no;
01102
01103 while (*q && *q != '\n' && !isspace(*q))
01104 q++;
01105 }
01106
01107 return 1;
01108 }
01109 }
01110 p = strchr(p, '\n');
01111 if (!p)
01112 break;
01113
01114 p++;
01115 }
01116
01117 return 0;
01118 }
01119
01120 static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
01121 {
01122 int i;
01123 int best_bitrate = 100000000;
01124 int best = -1;
01125
01126 for (i = 0; i < feed->nb_streams; i++) {
01127 AVCodecContext *feed_codec = feed->streams[i]->codec;
01128
01129 if (feed_codec->codec_id != codec->codec_id ||
01130 feed_codec->sample_rate != codec->sample_rate ||
01131 feed_codec->width != codec->width ||
01132 feed_codec->height != codec->height)
01133 continue;
01134
01135
01136
01137
01138
01139
01140
01141 if (feed_codec->bit_rate <= bit_rate) {
01142 if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
01143 best_bitrate = feed_codec->bit_rate;
01144 best = i;
01145 }
01146 } else {
01147 if (feed_codec->bit_rate < best_bitrate) {
01148 best_bitrate = feed_codec->bit_rate;
01149 best = i;
01150 }
01151 }
01152 }
01153
01154 return best;
01155 }
01156
01157 static int modify_current_stream(HTTPContext *c, char *rates)
01158 {
01159 int i;
01160 FFStream *req = c->stream;
01161 int action_required = 0;
01162
01163
01164 if (!req->feed)
01165 return 0;
01166
01167 for (i = 0; i < req->nb_streams; i++) {
01168 AVCodecContext *codec = req->streams[i]->codec;
01169
01170 switch(rates[i]) {
01171 case 0:
01172 c->switch_feed_streams[i] = req->feed_streams[i];
01173 break;
01174 case 1:
01175 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
01176 break;
01177 case 2:
01178
01179 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
01180 #ifdef WANTS_OFF
01181
01182 c->switch_feed_streams[i] = -2;
01183 c->feed_streams[i] = -2;
01184 #endif
01185 break;
01186 }
01187
01188 if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
01189 action_required = 1;
01190 }
01191
01192 return action_required;
01193 }
01194
01195
01196 static void do_switch_stream(HTTPContext *c, int i)
01197 {
01198 if (c->switch_feed_streams[i] >= 0) {
01199 #ifdef PHILIP
01200 c->feed_streams[i] = c->switch_feed_streams[i];
01201 #endif
01202
01203
01204 }
01205 c->switch_feed_streams[i] = -1;
01206 }
01207
01208
01209
01210 static void skip_spaces(const char **pp)
01211 {
01212 const char *p;
01213 p = *pp;
01214 while (*p == ' ' || *p == '\t')
01215 p++;
01216 *pp = p;
01217 }
01218
01219 static void get_word(char *buf, int buf_size, const char **pp)
01220 {
01221 const char *p;
01222 char *q;
01223
01224 p = *pp;
01225 skip_spaces(&p);
01226 q = buf;
01227 while (!isspace(*p) && *p != '\0') {
01228 if ((q - buf) < buf_size - 1)
01229 *q++ = *p;
01230 p++;
01231 }
01232 if (buf_size > 0)
01233 *q = '\0';
01234 *pp = p;
01235 }
01236
01237 static void get_arg(char *buf, int buf_size, const char **pp)
01238 {
01239 const char *p;
01240 char *q;
01241 int quote;
01242
01243 p = *pp;
01244 while (isspace(*p)) p++;
01245 q = buf;
01246 quote = 0;
01247 if (*p == '\"' || *p == '\'')
01248 quote = *p++;
01249 for(;;) {
01250 if (quote) {
01251 if (*p == quote)
01252 break;
01253 } else {
01254 if (isspace(*p))
01255 break;
01256 }
01257 if (*p == '\0')
01258 break;
01259 if ((q - buf) < buf_size - 1)
01260 *q++ = *p;
01261 p++;
01262 }
01263 *q = '\0';
01264 if (quote && *p == quote)
01265 p++;
01266 *pp = p;
01267 }
01268
01269 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
01270 const char *p, const char *filename, int line_num)
01271 {
01272 char arg[1024];
01273 IPAddressACL acl;
01274 int errors = 0;
01275
01276 get_arg(arg, sizeof(arg), &p);
01277 if (strcasecmp(arg, "allow") == 0)
01278 acl.action = IP_ALLOW;
01279 else if (strcasecmp(arg, "deny") == 0)
01280 acl.action = IP_DENY;
01281 else {
01282 fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
01283 filename, line_num, arg);
01284 errors++;
01285 }
01286
01287 get_arg(arg, sizeof(arg), &p);
01288
01289 if (resolve_host(&acl.first, arg) != 0) {
01290 fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
01291 filename, line_num, arg);
01292 errors++;
01293 } else
01294 acl.last = acl.first;
01295
01296 get_arg(arg, sizeof(arg), &p);
01297
01298 if (arg[0]) {
01299 if (resolve_host(&acl.last, arg) != 0) {
01300 fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
01301 filename, line_num, arg);
01302 errors++;
01303 }
01304 }
01305
01306 if (!errors) {
01307 IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
01308 IPAddressACL **naclp = 0;
01309
01310 acl.next = 0;
01311 *nacl = acl;
01312
01313 if (stream)
01314 naclp = &stream->acl;
01315 else if (feed)
01316 naclp = &feed->acl;
01317 else if (ext_acl)
01318 naclp = &ext_acl;
01319 else {
01320 fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
01321 filename, line_num);
01322 errors++;
01323 }
01324
01325 if (naclp) {
01326 while (*naclp)
01327 naclp = &(*naclp)->next;
01328
01329 *naclp = nacl;
01330 }
01331 }
01332 }
01333
01334
01335 static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
01336 {
01337 FILE* f;
01338 char line[1024];
01339 char cmd[1024];
01340 IPAddressACL *acl = NULL;
01341 int line_num = 0;
01342 const char *p;
01343
01344 f = fopen(stream->dynamic_acl, "r");
01345 if (!f) {
01346 perror(stream->dynamic_acl);
01347 return NULL;
01348 }
01349
01350 acl = av_mallocz(sizeof(IPAddressACL));
01351
01352
01353 for(;;) {
01354 if (fgets(line, sizeof(line), f) == NULL)
01355 break;
01356 line_num++;
01357 p = line;
01358 while (isspace(*p))
01359 p++;
01360 if (*p == '\0' || *p == '#')
01361 continue;
01362 get_arg(cmd, sizeof(cmd), &p);
01363
01364 if (!strcasecmp(cmd, "ACL"))
01365 parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
01366 }
01367 fclose(f);
01368 return acl;
01369 }
01370
01371
01372 static void free_acl_list(IPAddressACL *in_acl)
01373 {
01374 IPAddressACL *pacl,*pacl2;
01375
01376 pacl = in_acl;
01377 while(pacl) {
01378 pacl2 = pacl;
01379 pacl = pacl->next;
01380 av_freep(pacl2);
01381 }
01382 }
01383
01384 static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
01385 {
01386 enum IPAddressAction last_action = IP_DENY;
01387 IPAddressACL *acl;
01388 struct in_addr *src = &c->from_addr.sin_addr;
01389 unsigned long src_addr = src->s_addr;
01390
01391 for (acl = in_acl; acl; acl = acl->next) {
01392 if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
01393 return (acl->action == IP_ALLOW) ? 1 : 0;
01394 last_action = acl->action;
01395 }
01396
01397
01398 return (last_action == IP_DENY) ? 1 : 0;
01399 }
01400
01401 static int validate_acl(FFStream *stream, HTTPContext *c)
01402 {
01403 int ret = 0;
01404 IPAddressACL *acl;
01405
01406
01407
01408 ret = validate_acl_list(stream->acl, c);
01409
01410 if (stream->dynamic_acl[0]) {
01411 acl = parse_dynamic_acl(stream, c);
01412
01413 ret = validate_acl_list(acl, c);
01414
01415 free_acl_list(acl);
01416 }
01417
01418 return ret;
01419 }
01420
01421
01422
01423 static void compute_real_filename(char *filename, int max_size)
01424 {
01425 char file1[1024];
01426 char file2[1024];
01427 char *p;
01428 FFStream *stream;
01429
01430
01431 av_strlcpy(file1, filename, sizeof(file1));
01432 p = strrchr(file1, '.');
01433 if (p)
01434 *p = '\0';
01435 for(stream = first_stream; stream != NULL; stream = stream->next) {
01436 av_strlcpy(file2, stream->filename, sizeof(file2));
01437 p = strrchr(file2, '.');
01438 if (p)
01439 *p = '\0';
01440 if (!strcmp(file1, file2)) {
01441 av_strlcpy(filename, stream->filename, max_size);
01442 break;
01443 }
01444 }
01445 }
01446
01447 enum RedirType {
01448 REDIR_NONE,
01449 REDIR_ASX,
01450 REDIR_RAM,
01451 REDIR_ASF,
01452 REDIR_RTSP,
01453 REDIR_SDP,
01454 };
01455
01456
01457 static int http_parse_request(HTTPContext *c)
01458 {
01459 char *p;
01460 enum RedirType redir_type;
01461 char cmd[32];
01462 char info[1024], filename[1024];
01463 char url[1024], *q;
01464 char protocol[32];
01465 char msg[1024];
01466 const char *mime_type;
01467 FFStream *stream;
01468 int i;
01469 char ratebuf[32];
01470 char *useragent = 0;
01471
01472 p = c->buffer;
01473 get_word(cmd, sizeof(cmd), (const char **)&p);
01474 av_strlcpy(c->method, cmd, sizeof(c->method));
01475
01476 if (!strcmp(cmd, "GET"))
01477 c->post = 0;
01478 else if (!strcmp(cmd, "POST"))
01479 c->post = 1;
01480 else
01481 return -1;
01482
01483 get_word(url, sizeof(url), (const char **)&p);
01484 av_strlcpy(c->url, url, sizeof(c->url));
01485
01486 get_word(protocol, sizeof(protocol), (const char **)&p);
01487 if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
01488 return -1;
01489
01490 av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
01491
01492 if (ffserver_debug)
01493 http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
01494
01495
01496 p = strchr(url, '?');
01497 if (p) {
01498 av_strlcpy(info, p, sizeof(info));
01499 *p = '\0';
01500 } else
01501 info[0] = '\0';
01502
01503 av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
01504
01505 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
01506 if (strncasecmp(p, "User-Agent:", 11) == 0) {
01507 useragent = p + 11;
01508 if (*useragent && *useragent != '\n' && isspace(*useragent))
01509 useragent++;
01510 break;
01511 }
01512 p = strchr(p, '\n');
01513 if (!p)
01514 break;
01515
01516 p++;
01517 }
01518
01519 redir_type = REDIR_NONE;
01520 if (av_match_ext(filename, "asx")) {
01521 redir_type = REDIR_ASX;
01522 filename[strlen(filename)-1] = 'f';
01523 } else if (av_match_ext(filename, "asf") &&
01524 (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) {
01525
01526 redir_type = REDIR_ASF;
01527 } else if (av_match_ext(filename, "rpm,ram")) {
01528 redir_type = REDIR_RAM;
01529 strcpy(filename + strlen(filename)-2, "m");
01530 } else if (av_match_ext(filename, "rtsp")) {
01531 redir_type = REDIR_RTSP;
01532 compute_real_filename(filename, sizeof(filename) - 1);
01533 } else if (av_match_ext(filename, "sdp")) {
01534 redir_type = REDIR_SDP;
01535 compute_real_filename(filename, sizeof(filename) - 1);
01536 }
01537
01538
01539 if (!strlen(filename))
01540 av_strlcpy(filename, "index.html", sizeof(filename) - 1);
01541
01542 stream = first_stream;
01543 while (stream != NULL) {
01544 if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
01545 break;
01546 stream = stream->next;
01547 }
01548 if (stream == NULL) {
01549 snprintf(msg, sizeof(msg), "File '%s' not found", url);
01550 http_log("File '%s' not found\n", url);
01551 goto send_error;
01552 }
01553
01554 c->stream = stream;
01555 memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
01556 memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
01557
01558 if (stream->stream_type == STREAM_TYPE_REDIRECT) {
01559 c->http_error = 301;
01560 q = c->buffer;
01561 q += snprintf(q, c->buffer_size,
01562 "HTTP/1.0 301 Moved\r\n"
01563 "Location: %s\r\n"
01564 "Content-type: text/html\r\n"
01565 "\r\n"
01566 "<html><head><title>Moved</title></head><body>\r\n"
01567 "You should be <a href=\"%s\">redirected</a>.\r\n"
01568 "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
01569
01570 c->buffer_ptr = c->buffer;
01571 c->buffer_end = q;
01572 c->state = HTTPSTATE_SEND_HEADER;
01573 return 0;
01574 }
01575
01576
01577 if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
01578 if (modify_current_stream(c, ratebuf)) {
01579 for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
01580 if (c->switch_feed_streams[i] >= 0)
01581 do_switch_stream(c, i);
01582 }
01583 }
01584 }
01585
01586 if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
01587 current_bandwidth += stream->bandwidth;
01588
01589
01590 if (stream->feed_opened) {
01591 snprintf(msg, sizeof(msg), "This feed is already being received.");
01592 http_log("Feed '%s' already being received\n", stream->feed_filename);
01593 goto send_error;
01594 }
01595
01596 if (c->post == 0 && max_bandwidth < current_bandwidth) {
01597 c->http_error = 503;
01598 q = c->buffer;
01599 q += snprintf(q, c->buffer_size,
01600 "HTTP/1.0 503 Server too busy\r\n"
01601 "Content-type: text/html\r\n"
01602 "\r\n"
01603 "<html><head><title>Too busy</title></head><body>\r\n"
01604 "<p>The server is too busy to serve your request at this time.</p>\r\n"
01605 "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
01606 "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
01607 "</body></html>\r\n", current_bandwidth, max_bandwidth);
01608
01609 c->buffer_ptr = c->buffer;
01610 c->buffer_end = q;
01611 c->state = HTTPSTATE_SEND_HEADER;
01612 return 0;
01613 }
01614
01615 if (redir_type != REDIR_NONE) {
01616 char *hostinfo = 0;
01617
01618 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
01619 if (strncasecmp(p, "Host:", 5) == 0) {
01620 hostinfo = p + 5;
01621 break;
01622 }
01623 p = strchr(p, '\n');
01624 if (!p)
01625 break;
01626
01627 p++;
01628 }
01629
01630 if (hostinfo) {
01631 char *eoh;
01632 char hostbuf[260];
01633
01634 while (isspace(*hostinfo))
01635 hostinfo++;
01636
01637 eoh = strchr(hostinfo, '\n');
01638 if (eoh) {
01639 if (eoh[-1] == '\r')
01640 eoh--;
01641
01642 if (eoh - hostinfo < sizeof(hostbuf) - 1) {
01643 memcpy(hostbuf, hostinfo, eoh - hostinfo);
01644 hostbuf[eoh - hostinfo] = 0;
01645
01646 c->http_error = 200;
01647 q = c->buffer;
01648 switch(redir_type) {
01649 case REDIR_ASX:
01650 q += snprintf(q, c->buffer_size,
01651 "HTTP/1.0 200 ASX Follows\r\n"
01652 "Content-type: video/x-ms-asf\r\n"
01653 "\r\n"
01654 "<ASX Version=\"3\">\r\n"
01655
01656 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
01657 "</ASX>\r\n", hostbuf, filename, info);
01658 break;
01659 case REDIR_RAM:
01660 q += snprintf(q, c->buffer_size,
01661 "HTTP/1.0 200 RAM Follows\r\n"
01662 "Content-type: audio/x-pn-realaudio\r\n"
01663 "\r\n"
01664 "# Autogenerated by ffserver\r\n"
01665 "http://%s/%s%s\r\n", hostbuf, filename, info);
01666 break;
01667 case REDIR_ASF:
01668 q += snprintf(q, c->buffer_size,
01669 "HTTP/1.0 200 ASF Redirect follows\r\n"
01670 "Content-type: video/x-ms-asf\r\n"
01671 "\r\n"
01672 "[Reference]\r\n"
01673 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
01674 break;
01675 case REDIR_RTSP:
01676 {
01677 char hostname[256], *p;
01678
01679 av_strlcpy(hostname, hostbuf, sizeof(hostname));
01680 p = strrchr(hostname, ':');
01681 if (p)
01682 *p = '\0';
01683 q += snprintf(q, c->buffer_size,
01684 "HTTP/1.0 200 RTSP Redirect follows\r\n"
01685
01686 "Content-type: application/x-rtsp\r\n"
01687 "\r\n"
01688 "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
01689 }
01690 break;
01691 case REDIR_SDP:
01692 {
01693 uint8_t *sdp_data;
01694 int sdp_data_size, len;
01695 struct sockaddr_in my_addr;
01696
01697 q += snprintf(q, c->buffer_size,
01698 "HTTP/1.0 200 OK\r\n"
01699 "Content-type: application/sdp\r\n"
01700 "\r\n");
01701
01702 len = sizeof(my_addr);
01703 getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
01704
01705
01706 sdp_data_size = prepare_sdp_description(stream,
01707 &sdp_data,
01708 my_addr.sin_addr);
01709 if (sdp_data_size > 0) {
01710 memcpy(q, sdp_data, sdp_data_size);
01711 q += sdp_data_size;
01712 *q = '\0';
01713 av_free(sdp_data);
01714 }
01715 }
01716 break;
01717 default:
01718 abort();
01719 break;
01720 }
01721
01722
01723 c->buffer_ptr = c->buffer;
01724 c->buffer_end = q;
01725 c->state = HTTPSTATE_SEND_HEADER;
01726 return 0;
01727 }
01728 }
01729 }
01730
01731 snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
01732 goto send_error;
01733 }
01734
01735 stream->conns_served++;
01736
01737
01738
01739 if (c->post) {
01740
01741 if (!stream->is_feed) {
01742
01743
01744 char *logline = 0;
01745 int client_id = 0;
01746
01747 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
01748 if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
01749 logline = p;
01750 break;
01751 }
01752 if (strncasecmp(p, "Pragma: client-id=", 18) == 0)
01753 client_id = strtol(p + 18, 0, 10);
01754 p = strchr(p, '\n');
01755 if (!p)
01756 break;
01757
01758 p++;
01759 }
01760
01761 if (logline) {
01762 char *eol = strchr(logline, '\n');
01763
01764 logline += 17;
01765
01766 if (eol) {
01767 if (eol[-1] == '\r')
01768 eol--;
01769 http_log("%.*s\n", (int) (eol - logline), logline);
01770 c->suppress_log = 1;
01771 }
01772 }
01773
01774 #ifdef DEBUG_WMP
01775 http_log("\nGot request:\n%s\n", c->buffer);
01776 #endif
01777
01778 if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
01779 HTTPContext *wmpc;
01780
01781
01782 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
01783 if (wmpc->wmp_client_id == client_id)
01784 break;
01785 }
01786
01787 if (wmpc && modify_current_stream(wmpc, ratebuf))
01788 wmpc->switch_pending = 1;
01789 }
01790
01791 snprintf(msg, sizeof(msg), "POST command not handled");
01792 c->stream = 0;
01793 goto send_error;
01794 }
01795 if (http_start_receive_data(c) < 0) {
01796 snprintf(msg, sizeof(msg), "could not open feed");
01797 goto send_error;
01798 }
01799 c->http_error = 0;
01800 c->state = HTTPSTATE_RECEIVE_DATA;
01801 return 0;
01802 }
01803
01804 #ifdef DEBUG_WMP
01805 if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
01806 http_log("\nGot request:\n%s\n", c->buffer);
01807 #endif
01808
01809 if (c->stream->stream_type == STREAM_TYPE_STATUS)
01810 goto send_status;
01811
01812
01813 if (open_input_stream(c, info) < 0) {
01814 snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
01815 goto send_error;
01816 }
01817
01818
01819 q = c->buffer;
01820 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
01821 mime_type = c->stream->fmt->mime_type;
01822 if (!mime_type)
01823 mime_type = "application/x-octet-stream";
01824 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
01825
01826
01827 if (!strcmp(c->stream->fmt->name,"asf_stream")) {
01828
01829
01830 c->wmp_client_id = av_lfg_get(&random_state);
01831
01832 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);
01833 }
01834 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
01835 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
01836
01837
01838 c->http_error = 0;
01839 c->buffer_ptr = c->buffer;
01840 c->buffer_end = q;
01841 c->state = HTTPSTATE_SEND_HEADER;
01842 return 0;
01843 send_error:
01844 c->http_error = 404;
01845 q = c->buffer;
01846 q += snprintf(q, c->buffer_size,
01847 "HTTP/1.0 404 Not Found\r\n"
01848 "Content-type: text/html\r\n"
01849 "\r\n"
01850 "<html>\n"
01851 "<head><title>404 Not Found</title></head>\n"
01852 "<body>%s</body>\n"
01853 "</html>\n", msg);
01854
01855 c->buffer_ptr = c->buffer;
01856 c->buffer_end = q;
01857 c->state = HTTPSTATE_SEND_HEADER;
01858 return 0;
01859 send_status:
01860 compute_status(c);
01861 c->http_error = 200;
01862
01863 c->state = HTTPSTATE_SEND_HEADER;
01864 return 0;
01865 }
01866
01867 static void fmt_bytecount(ByteIOContext *pb, int64_t count)
01868 {
01869 static const char *suffix = " kMGTP";
01870 const char *s;
01871
01872 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
01873
01874 url_fprintf(pb, "%"PRId64"%c", count, *s);
01875 }
01876
01877 static void compute_status(HTTPContext *c)
01878 {
01879 HTTPContext *c1;
01880 FFStream *stream;
01881 char *p;
01882 time_t ti;
01883 int i, len;
01884 ByteIOContext *pb;
01885
01886 if (url_open_dyn_buf(&pb) < 0) {
01887
01888 c->buffer_ptr = c->buffer;
01889 c->buffer_end = c->buffer;
01890 return;
01891 }
01892
01893 url_fprintf(pb, "HTTP/1.0 200 OK\r\n");
01894 url_fprintf(pb, "Content-type: %s\r\n", "text/html");
01895 url_fprintf(pb, "Pragma: no-cache\r\n");
01896 url_fprintf(pb, "\r\n");
01897
01898 url_fprintf(pb, "<html><head><title>%s Status</title>\n", program_name);
01899 if (c->stream->feed_filename[0])
01900 url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
01901 url_fprintf(pb, "</head>\n<body>");
01902 url_fprintf(pb, "<h1>%s Status</h1>\n", program_name);
01903
01904 url_fprintf(pb, "<h2>Available Streams</h2>\n");
01905 url_fprintf(pb, "<table cellspacing=0 cellpadding=4>\n");
01906 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");
01907 stream = first_stream;
01908 while (stream != NULL) {
01909 char sfilename[1024];
01910 char *eosf;
01911
01912 if (stream->feed != stream) {
01913 av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
01914 eosf = sfilename + strlen(sfilename);
01915 if (eosf - sfilename >= 4) {
01916 if (strcmp(eosf - 4, ".asf") == 0)
01917 strcpy(eosf - 4, ".asx");
01918 else if (strcmp(eosf - 3, ".rm") == 0)
01919 strcpy(eosf - 3, ".ram");
01920 else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
01921
01922
01923
01924 eosf = strrchr(sfilename, '.');
01925 if (!eosf)
01926 eosf = sfilename + strlen(sfilename);
01927 if (stream->is_multicast)
01928 strcpy(eosf, ".sdp");
01929 else
01930 strcpy(eosf, ".rtsp");
01931 }
01932 }
01933
01934 url_fprintf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
01935 sfilename, stream->filename);
01936 url_fprintf(pb, "<td align=right> %d <td align=right> ",
01937 stream->conns_served);
01938 fmt_bytecount(pb, stream->bytes_served);
01939 switch(stream->stream_type) {
01940 case STREAM_TYPE_LIVE: {
01941 int audio_bit_rate = 0;
01942 int video_bit_rate = 0;
01943 const char *audio_codec_name = "";
01944 const char *video_codec_name = "";
01945 const char *audio_codec_name_extra = "";
01946 const char *video_codec_name_extra = "";
01947
01948 for(i=0;i<stream->nb_streams;i++) {
01949 AVStream *st = stream->streams[i];
01950 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
01951 switch(st->codec->codec_type) {
01952 case AVMEDIA_TYPE_AUDIO:
01953 audio_bit_rate += st->codec->bit_rate;
01954 if (codec) {
01955 if (*audio_codec_name)
01956 audio_codec_name_extra = "...";
01957 audio_codec_name = codec->name;
01958 }
01959 break;
01960 case AVMEDIA_TYPE_VIDEO:
01961 video_bit_rate += st->codec->bit_rate;
01962 if (codec) {
01963 if (*video_codec_name)
01964 video_codec_name_extra = "...";
01965 video_codec_name = codec->name;
01966 }
01967 break;
01968 case AVMEDIA_TYPE_DATA:
01969 video_bit_rate += st->codec->bit_rate;
01970 break;
01971 default:
01972 abort();
01973 }
01974 }
01975 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",
01976 stream->fmt->name,
01977 stream->bandwidth,
01978 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
01979 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
01980 if (stream->feed)
01981 url_fprintf(pb, "<td>%s", stream->feed->filename);
01982 else
01983 url_fprintf(pb, "<td>%s", stream->feed_filename);
01984 url_fprintf(pb, "\n");
01985 }
01986 break;
01987 default:
01988 url_fprintf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
01989 break;
01990 }
01991 }
01992 stream = stream->next;
01993 }
01994 url_fprintf(pb, "</table>\n");
01995
01996 stream = first_stream;
01997 while (stream != NULL) {
01998 if (stream->feed == stream) {
01999 url_fprintf(pb, "<h2>Feed %s</h2>", stream->filename);
02000 if (stream->pid) {
02001 url_fprintf(pb, "Running as pid %d.\n", stream->pid);
02002
02003 #if defined(linux) && !defined(CONFIG_NOCUTILS)
02004 {
02005 FILE *pid_stat;
02006 char ps_cmd[64];
02007
02008
02009 snprintf(ps_cmd, sizeof(ps_cmd),
02010 "ps -o \"%%cpu,cputime\" --no-headers %d",
02011 stream->pid);
02012
02013 pid_stat = popen(ps_cmd, "r");
02014 if (pid_stat) {
02015 char cpuperc[10];
02016 char cpuused[64];
02017
02018 if (fscanf(pid_stat, "%10s %64s", cpuperc,
02019 cpuused) == 2) {
02020 url_fprintf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
02021 cpuperc, cpuused);
02022 }
02023 fclose(pid_stat);
02024 }
02025 }
02026 #endif
02027
02028 url_fprintf(pb, "<p>");
02029 }
02030 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");
02031
02032 for (i = 0; i < stream->nb_streams; i++) {
02033 AVStream *st = stream->streams[i];
02034 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
02035 const char *type = "unknown";
02036 char parameters[64];
02037
02038 parameters[0] = 0;
02039
02040 switch(st->codec->codec_type) {
02041 case AVMEDIA_TYPE_AUDIO:
02042 type = "audio";
02043 snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
02044 break;
02045 case AVMEDIA_TYPE_VIDEO:
02046 type = "video";
02047 snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
02048 st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
02049 break;
02050 default:
02051 abort();
02052 }
02053 url_fprintf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
02054 i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
02055 }
02056 url_fprintf(pb, "</table>\n");
02057
02058 }
02059 stream = stream->next;
02060 }
02061
02062
02063 url_fprintf(pb, "<h2>Connection Status</h2>\n");
02064
02065 url_fprintf(pb, "Number of connections: %d / %d<br>\n",
02066 nb_connections, nb_max_connections);
02067
02068 url_fprintf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
02069 current_bandwidth, max_bandwidth);
02070
02071 url_fprintf(pb, "<table>\n");
02072 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");
02073 c1 = first_http_ctx;
02074 i = 0;
02075 while (c1 != NULL) {
02076 int bitrate;
02077 int j;
02078
02079 bitrate = 0;
02080 if (c1->stream) {
02081 for (j = 0; j < c1->stream->nb_streams; j++) {
02082 if (!c1->stream->feed)
02083 bitrate += c1->stream->streams[j]->codec->bit_rate;
02084 else if (c1->feed_streams[j] >= 0)
02085 bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
02086 }
02087 }
02088
02089 i++;
02090 p = inet_ntoa(c1->from_addr.sin_addr);
02091 url_fprintf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
02092 i,
02093 c1->stream ? c1->stream->filename : "",
02094 c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
02095 p,
02096 c1->protocol,
02097 http_state[c1->state]);
02098 fmt_bytecount(pb, bitrate);
02099 url_fprintf(pb, "<td align=right>");
02100 fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
02101 url_fprintf(pb, "<td align=right>");
02102 fmt_bytecount(pb, c1->data_count);
02103 url_fprintf(pb, "\n");
02104 c1 = c1->next;
02105 }
02106 url_fprintf(pb, "</table>\n");
02107
02108
02109 ti = time(NULL);
02110 p = ctime(&ti);
02111 url_fprintf(pb, "<hr size=1 noshade>Generated at %s", p);
02112 url_fprintf(pb, "</body>\n</html>\n");
02113
02114 len = url_close_dyn_buf(pb, &c->pb_buffer);
02115 c->buffer_ptr = c->pb_buffer;
02116 c->buffer_end = c->pb_buffer + len;
02117 }
02118
02119
02120 static void open_parser(AVFormatContext *s, int i)
02121 {
02122 AVStream *st = s->streams[i];
02123 AVCodec *codec;
02124
02125 if (!st->codec->codec) {
02126 codec = avcodec_find_decoder(st->codec->codec_id);
02127 if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
02128 st->codec->parse_only = 1;
02129 if (avcodec_open(st->codec, codec) < 0)
02130 st->codec->parse_only = 0;
02131 }
02132 }
02133 }
02134
02135 static int open_input_stream(HTTPContext *c, const char *info)
02136 {
02137 char buf[128];
02138 char input_filename[1024];
02139 AVFormatContext *s;
02140 int buf_size, i, ret;
02141 int64_t stream_pos;
02142
02143
02144 if (c->stream->feed) {
02145 strcpy(input_filename, c->stream->feed->feed_filename);
02146 buf_size = FFM_PACKET_SIZE;
02147
02148 if (find_info_tag(buf, sizeof(buf), "date", info)) {
02149 stream_pos = parse_date(buf, 0);
02150 if (stream_pos == INT64_MIN)
02151 return -1;
02152 } else if (find_info_tag(buf, sizeof(buf), "buffer", info)) {
02153 int prebuffer = strtol(buf, 0, 10);
02154 stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
02155 } else
02156 stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
02157 } else {
02158 strcpy(input_filename, c->stream->feed_filename);
02159 buf_size = 0;
02160
02161 if (find_info_tag(buf, sizeof(buf), "date", info)) {
02162 stream_pos = parse_date(buf, 1);
02163 if (stream_pos == INT64_MIN)
02164 return -1;
02165 } else
02166 stream_pos = 0;
02167 }
02168 if (input_filename[0] == '\0')
02169 return -1;
02170
02171
02172 if ((ret = av_open_input_file(&s, input_filename, c->stream->ifmt,
02173 buf_size, c->stream->ap_in)) < 0) {
02174 http_log("could not open %s: %d\n", input_filename, ret);
02175 return -1;
02176 }
02177 s->flags |= AVFMT_FLAG_GENPTS;
02178 c->fmt_in = s;
02179 if (strcmp(s->iformat->name, "ffm") && av_find_stream_info(c->fmt_in) < 0) {
02180 http_log("Could not find stream info '%s'\n", input_filename);
02181 av_close_input_file(s);
02182 return -1;
02183 }
02184
02185
02186 for(i=0;i<s->nb_streams;i++)
02187 open_parser(s, i);
02188
02189
02190
02191 c->pts_stream_index = 0;
02192 for(i=0;i<c->stream->nb_streams;i++) {
02193 if (c->pts_stream_index == 0 &&
02194 c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
02195 c->pts_stream_index = i;
02196 }
02197 }
02198
02199 #if 1
02200 if (c->fmt_in->iformat->read_seek)
02201 av_seek_frame(c->fmt_in, -1, stream_pos, 0);
02202 #endif
02203
02204 c->start_time = cur_time;
02205 c->first_pts = AV_NOPTS_VALUE;
02206 return 0;
02207 }
02208
02209
02210 static int64_t get_server_clock(HTTPContext *c)
02211 {
02212
02213 return (cur_time - c->start_time) * 1000;
02214 }
02215
02216
02217
02218 static int64_t get_packet_send_clock(HTTPContext *c)
02219 {
02220 int bytes_left, bytes_sent, frame_bytes;
02221
02222 frame_bytes = c->cur_frame_bytes;
02223 if (frame_bytes <= 0)
02224 return c->cur_pts;
02225 else {
02226 bytes_left = c->buffer_end - c->buffer_ptr;
02227 bytes_sent = frame_bytes - bytes_left;
02228 return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
02229 }
02230 }
02231
02232
02233 static int http_prepare_data(HTTPContext *c)
02234 {
02235 int i, len, ret;
02236 AVFormatContext *ctx;
02237
02238 av_freep(&c->pb_buffer);
02239 switch(c->state) {
02240 case HTTPSTATE_SEND_DATA_HEADER:
02241 memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
02242 av_metadata_set2(&c->fmt_ctx.metadata, "author" , c->stream->author , 0);
02243 av_metadata_set2(&c->fmt_ctx.metadata, "comment" , c->stream->comment , 0);
02244 av_metadata_set2(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
02245 av_metadata_set2(&c->fmt_ctx.metadata, "title" , c->stream->title , 0);
02246
02247 for(i=0;i<c->stream->nb_streams;i++) {
02248 AVStream *st;
02249 AVStream *src;
02250 st = av_mallocz(sizeof(AVStream));
02251 c->fmt_ctx.streams[i] = st;
02252
02253 if (!c->stream->feed ||
02254 c->stream->feed == c->stream)
02255 src = c->stream->streams[i];
02256 else
02257 src = c->stream->feed->streams[c->stream->feed_streams[i]];
02258
02259 *st = *src;
02260 st->priv_data = 0;
02261 st->codec->frame_number = 0;
02262
02263 }
02264
02265 c->fmt_ctx.oformat = c->stream->fmt;
02266 c->fmt_ctx.nb_streams = c->stream->nb_streams;
02267
02268 c->got_key_frame = 0;
02269
02270
02271 if (url_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
02272
02273 return -1;
02274 }
02275 c->fmt_ctx.pb->is_streamed = 1;
02276
02277
02278
02279
02280
02281
02282 c->fmt_ctx.preload = (int)(0.5*AV_TIME_BASE);
02283 c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
02284
02285 av_set_parameters(&c->fmt_ctx, NULL);
02286 if (av_write_header(&c->fmt_ctx) < 0) {
02287 http_log("Error writing output header\n");
02288 return -1;
02289 }
02290 av_metadata_free(&c->fmt_ctx.metadata);
02291
02292 len = url_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
02293 c->buffer_ptr = c->pb_buffer;
02294 c->buffer_end = c->pb_buffer + len;
02295
02296 c->state = HTTPSTATE_SEND_DATA;
02297 c->last_packet_sent = 0;
02298 break;
02299 case HTTPSTATE_SEND_DATA:
02300
02301
02302 if (c->stream->feed)
02303 ffm_set_write_index(c->fmt_in,
02304 c->stream->feed->feed_write_index,
02305 c->stream->feed->feed_size);
02306
02307 if (c->stream->max_time &&
02308 c->stream->max_time + c->start_time - cur_time < 0)
02309
02310 c->state = HTTPSTATE_SEND_DATA_TRAILER;
02311 else {
02312 AVPacket pkt;
02313 redo:
02314 ret = av_read_frame(c->fmt_in, &pkt);
02315 if (ret < 0) {
02316 if (c->stream->feed) {
02317
02318
02319 c->state = HTTPSTATE_WAIT_FEED;
02320 return 1;
02321 } else if (ret == AVERROR(EAGAIN)) {
02322
02323 return 0;
02324 } else {
02325 if (c->stream->loop) {
02326 av_close_input_file(c->fmt_in);
02327 c->fmt_in = NULL;
02328 if (open_input_stream(c, "") < 0)
02329 goto no_loop;
02330 goto redo;
02331 } else {
02332 no_loop:
02333
02334 c->state = HTTPSTATE_SEND_DATA_TRAILER;
02335 }
02336 }
02337 } else {
02338 int source_index = pkt.stream_index;
02339
02340 if (c->first_pts == AV_NOPTS_VALUE) {
02341 c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
02342 c->start_time = cur_time;
02343 }
02344
02345 if (c->stream->feed) {
02346
02347 if (c->switch_pending) {
02348 c->switch_pending = 0;
02349 for(i=0;i<c->stream->nb_streams;i++) {
02350 if (c->switch_feed_streams[i] == pkt.stream_index)
02351 if (pkt.flags & AV_PKT_FLAG_KEY)
02352 do_switch_stream(c, i);
02353 if (c->switch_feed_streams[i] >= 0)
02354 c->switch_pending = 1;
02355 }
02356 }
02357 for(i=0;i<c->stream->nb_streams;i++) {
02358 if (c->stream->feed_streams[i] == pkt.stream_index) {
02359 AVStream *st = c->fmt_in->streams[source_index];
02360 pkt.stream_index = i;
02361 if (pkt.flags & AV_PKT_FLAG_KEY &&
02362 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
02363 c->stream->nb_streams == 1))
02364 c->got_key_frame = 1;
02365 if (!c->stream->send_on_key || c->got_key_frame)
02366 goto send_it;
02367 }
02368 }
02369 } else {
02370 AVCodecContext *codec;
02371 AVStream *ist, *ost;
02372 send_it:
02373 ist = c->fmt_in->streams[source_index];
02374
02375
02376
02377 if (c->is_packetized) {
02378
02379 c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
02380 c->cur_pts -= c->first_pts;
02381 c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
02382
02383 c->packet_stream_index = pkt.stream_index;
02384 ctx = c->rtp_ctx[c->packet_stream_index];
02385 if(!ctx) {
02386 av_free_packet(&pkt);
02387 break;
02388 }
02389 codec = ctx->streams[0]->codec;
02390
02391 pkt.stream_index = 0;
02392 } else {
02393 ctx = &c->fmt_ctx;
02394
02395 codec = ctx->streams[pkt.stream_index]->codec;
02396 }
02397
02398 if (c->is_packetized) {
02399 int max_packet_size;
02400 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
02401 max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
02402 else
02403 max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
02404 ret = url_open_dyn_packet_buf(&ctx->pb, max_packet_size);
02405 } else {
02406 ret = url_open_dyn_buf(&ctx->pb);
02407 }
02408 if (ret < 0) {
02409
02410 return -1;
02411 }
02412 ost = ctx->streams[pkt.stream_index];
02413
02414 ctx->pb->is_streamed = 1;
02415 if (pkt.dts != AV_NOPTS_VALUE)
02416 pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
02417 if (pkt.pts != AV_NOPTS_VALUE)
02418 pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
02419 pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
02420 if (av_write_frame(ctx, &pkt) < 0) {
02421 http_log("Error writing frame to output\n");
02422 c->state = HTTPSTATE_SEND_DATA_TRAILER;
02423 }
02424
02425 len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
02426 c->cur_frame_bytes = len;
02427 c->buffer_ptr = c->pb_buffer;
02428 c->buffer_end = c->pb_buffer + len;
02429
02430 codec->frame_number++;
02431 if (len == 0) {
02432 av_free_packet(&pkt);
02433 goto redo;
02434 }
02435 }
02436 av_free_packet(&pkt);
02437 }
02438 }
02439 break;
02440 default:
02441 case HTTPSTATE_SEND_DATA_TRAILER:
02442
02443 if (c->last_packet_sent || c->is_packetized)
02444 return -1;
02445 ctx = &c->fmt_ctx;
02446
02447 if (url_open_dyn_buf(&ctx->pb) < 0) {
02448
02449 return -1;
02450 }
02451 c->fmt_ctx.pb->is_streamed = 1;
02452 av_write_trailer(ctx);
02453 len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
02454 c->buffer_ptr = c->pb_buffer;
02455 c->buffer_end = c->pb_buffer + len;
02456
02457 c->last_packet_sent = 1;
02458 break;
02459 }
02460 return 0;
02461 }
02462
02463
02464
02465
02466 static int http_send_data(HTTPContext *c)
02467 {
02468 int len, ret;
02469
02470 for(;;) {
02471 if (c->buffer_ptr >= c->buffer_end) {
02472 ret = http_prepare_data(c);
02473 if (ret < 0)
02474 return -1;
02475 else if (ret != 0)
02476
02477 break;
02478 } else {
02479 if (c->is_packetized) {
02480
02481 len = c->buffer_end - c->buffer_ptr;
02482 if (len < 4) {
02483
02484 fail1:
02485 c->buffer_ptr = c->buffer_end;
02486 return 0;
02487 }
02488 len = (c->buffer_ptr[0] << 24) |
02489 (c->buffer_ptr[1] << 16) |
02490 (c->buffer_ptr[2] << 8) |
02491 (c->buffer_ptr[3]);
02492 if (len > (c->buffer_end - c->buffer_ptr))
02493 goto fail1;
02494 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
02495
02496 return 0;
02497 }
02498
02499 c->data_count += len;
02500 update_datarate(&c->datarate, c->data_count);
02501 if (c->stream)
02502 c->stream->bytes_served += len;
02503
02504 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
02505
02506 ByteIOContext *pb;
02507 int interleaved_index, size;
02508 uint8_t header[4];
02509 HTTPContext *rtsp_c;
02510
02511 rtsp_c = c->rtsp_c;
02512
02513 if (!rtsp_c)
02514 return -1;
02515
02516 if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
02517 break;
02518 if (url_open_dyn_buf(&pb) < 0)
02519 goto fail1;
02520 interleaved_index = c->packet_stream_index * 2;
02521
02522 if (c->buffer_ptr[1] == 200)
02523 interleaved_index++;
02524
02525 header[0] = '$';
02526 header[1] = interleaved_index;
02527 header[2] = len >> 8;
02528 header[3] = len;
02529 put_buffer(pb, header, 4);
02530
02531 c->buffer_ptr += 4;
02532 put_buffer(pb, c->buffer_ptr, len);
02533 size = url_close_dyn_buf(pb, &c->packet_buffer);
02534
02535 rtsp_c->packet_buffer_ptr = c->packet_buffer;
02536 rtsp_c->packet_buffer_end = c->packet_buffer + size;
02537 c->buffer_ptr += len;
02538
02539
02540 len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
02541 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
02542 if (len > 0)
02543 rtsp_c->packet_buffer_ptr += len;
02544 if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
02545
02546
02547
02548 rtsp_c->state = RTSPSTATE_SEND_PACKET;
02549 break;
02550 } else
02551
02552 av_freep(&c->packet_buffer);
02553 } else {
02554
02555 c->buffer_ptr += 4;
02556 url_write(c->rtp_handles[c->packet_stream_index],
02557 c->buffer_ptr, len);
02558 c->buffer_ptr += len;
02559
02560 }
02561 } else {
02562
02563 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
02564 if (len < 0) {
02565 if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
02566 ff_neterrno() != FF_NETERROR(EINTR))
02567
02568 return -1;
02569 else
02570 return 0;
02571 } else
02572 c->buffer_ptr += len;
02573
02574 c->data_count += len;
02575 update_datarate(&c->datarate, c->data_count);
02576 if (c->stream)
02577 c->stream->bytes_served += len;
02578 break;
02579 }
02580 }
02581 }
02582 return 0;
02583 }
02584
02585 static int http_start_receive_data(HTTPContext *c)
02586 {
02587 int fd;
02588
02589 if (c->stream->feed_opened)
02590 return -1;
02591
02592
02593 if (c->stream->readonly)
02594 return -1;
02595
02596
02597 fd = open(c->stream->feed_filename, O_RDWR);
02598 if (fd < 0) {
02599 http_log("Error opening feeder file: %s\n", strerror(errno));
02600 return -1;
02601 }
02602 c->feed_fd = fd;
02603
02604 if (c->stream->truncate) {
02605
02606 ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
02607 ftruncate(c->feed_fd, FFM_PACKET_SIZE);
02608 http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
02609 } else {
02610 if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
02611 http_log("Error reading write index from feed file: %s\n", strerror(errno));
02612 return -1;
02613 }
02614 }
02615
02616 c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
02617 c->stream->feed_size = lseek(fd, 0, SEEK_END);
02618 lseek(fd, 0, SEEK_SET);
02619
02620
02621 c->buffer_ptr = c->buffer;
02622 c->buffer_end = c->buffer + FFM_PACKET_SIZE;
02623 c->stream->feed_opened = 1;
02624 c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
02625 return 0;
02626 }
02627
02628 static int http_receive_data(HTTPContext *c)
02629 {
02630 HTTPContext *c1;
02631 int len, loop_run = 0;
02632
02633 while (c->chunked_encoding && !c->chunk_size &&
02634 c->buffer_end > c->buffer_ptr) {
02635
02636 len = recv(c->fd, c->buffer_ptr, 1, 0);
02637
02638 if (len < 0) {
02639 if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
02640 ff_neterrno() != FF_NETERROR(EINTR))
02641
02642 goto fail;
02643 return 0;
02644 } else if (len == 0) {
02645
02646 goto fail;
02647 } else if (c->buffer_ptr - c->buffer >= 2 &&
02648 !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
02649 c->chunk_size = strtol(c->buffer, 0, 16);
02650 if (c->chunk_size == 0)
02651 goto fail;
02652 c->buffer_ptr = c->buffer;
02653 break;
02654 } else if (++loop_run > 10) {
02655
02656 goto fail;
02657 } else {
02658 c->buffer_ptr++;
02659 }
02660 }
02661
02662 if (c->buffer_end > c->buffer_ptr) {
02663 len = recv(c->fd, c->buffer_ptr,
02664 FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
02665 if (len < 0) {
02666 if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
02667 ff_neterrno() != FF_NETERROR(EINTR))
02668
02669 goto fail;
02670 } else if (len == 0)
02671
02672 goto fail;
02673 else {
02674 c->chunk_size -= len;
02675 c->buffer_ptr += len;
02676 c->data_count += len;
02677 update_datarate(&c->datarate, c->data_count);
02678 }
02679 }
02680
02681 if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
02682 if (c->buffer[0] != 'f' ||
02683 c->buffer[1] != 'm') {
02684 http_log("Feed stream has become desynchronized -- disconnecting\n");
02685 goto fail;
02686 }
02687 }
02688
02689 if (c->buffer_ptr >= c->buffer_end) {
02690 FFStream *feed = c->stream;
02691
02692
02693 if (c->data_count > FFM_PACKET_SIZE) {
02694
02695
02696
02697 lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
02698 if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
02699 http_log("Error writing to feed file: %s\n", strerror(errno));
02700 goto fail;
02701 }
02702
02703 feed->feed_write_index += FFM_PACKET_SIZE;
02704
02705 if (feed->feed_write_index > c->stream->feed_size)
02706 feed->feed_size = feed->feed_write_index;
02707
02708
02709 if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
02710 feed->feed_write_index = FFM_PACKET_SIZE;
02711
02712
02713 if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
02714 http_log("Error writing index to feed file: %s\n", strerror(errno));
02715 goto fail;
02716 }
02717
02718
02719 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
02720 if (c1->state == HTTPSTATE_WAIT_FEED &&
02721 c1->stream->feed == c->stream->feed)
02722 c1->state = HTTPSTATE_SEND_DATA;
02723 }
02724 } else {
02725
02726 AVFormatContext *s = NULL;
02727 ByteIOContext *pb;
02728 AVInputFormat *fmt_in;
02729 int i;
02730
02731
02732 fmt_in = av_find_input_format(feed->fmt->name);
02733 if (!fmt_in)
02734 goto fail;
02735
02736 url_open_buf(&pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
02737 pb->is_streamed = 1;
02738
02739 if (av_open_input_stream(&s, pb, c->stream->feed_filename, fmt_in, NULL) < 0) {
02740 av_free(pb);
02741 goto fail;
02742 }
02743
02744
02745 if (s->nb_streams != feed->nb_streams) {
02746 av_close_input_stream(s);
02747 av_free(pb);
02748 http_log("Feed '%s' stream number does not match registered feed\n",
02749 c->stream->feed_filename);
02750 goto fail;
02751 }
02752
02753 for (i = 0; i < s->nb_streams; i++) {
02754 AVStream *fst = feed->streams[i];
02755 AVStream *st = s->streams[i];
02756 avcodec_copy_context(fst->codec, st->codec);
02757 }
02758
02759 av_close_input_stream(s);
02760 av_free(pb);
02761 }
02762 c->buffer_ptr = c->buffer;
02763 }
02764
02765 return 0;
02766 fail:
02767 c->stream->feed_opened = 0;
02768 close(c->feed_fd);
02769
02770 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
02771 if (c1->state == HTTPSTATE_WAIT_FEED &&
02772 c1->stream->feed == c->stream->feed)
02773 c1->state = HTTPSTATE_SEND_DATA_TRAILER;
02774 }
02775 return -1;
02776 }
02777
02778
02779
02780
02781 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
02782 {
02783 const char *str;
02784 time_t ti;
02785 struct tm *tm;
02786 char buf2[32];
02787
02788 switch(error_number) {
02789 case RTSP_STATUS_OK:
02790 str = "OK";
02791 break;
02792 case RTSP_STATUS_METHOD:
02793 str = "Method Not Allowed";
02794 break;
02795 case RTSP_STATUS_BANDWIDTH:
02796 str = "Not Enough Bandwidth";
02797 break;
02798 case RTSP_STATUS_SESSION:
02799 str = "Session Not Found";
02800 break;
02801 case RTSP_STATUS_STATE:
02802 str = "Method Not Valid in This State";
02803 break;
02804 case RTSP_STATUS_AGGREGATE:
02805 str = "Aggregate operation not allowed";
02806 break;
02807 case RTSP_STATUS_ONLY_AGGREGATE:
02808 str = "Only aggregate operation allowed";
02809 break;
02810 case RTSP_STATUS_TRANSPORT:
02811 str = "Unsupported transport";
02812 break;
02813 case RTSP_STATUS_INTERNAL:
02814 str = "Internal Server Error";
02815 break;
02816 case RTSP_STATUS_SERVICE:
02817 str = "Service Unavailable";
02818 break;
02819 case RTSP_STATUS_VERSION:
02820 str = "RTSP Version not supported";
02821 break;
02822 default:
02823 str = "Unknown Error";
02824 break;
02825 }
02826
02827 url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
02828 url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
02829
02830
02831 ti = time(NULL);
02832 tm = gmtime(&ti);
02833 strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
02834 url_fprintf(c->pb, "Date: %s GMT\r\n", buf2);
02835 }
02836
02837 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
02838 {
02839 rtsp_reply_header(c, error_number);
02840 url_fprintf(c->pb, "\r\n");
02841 }
02842
02843 static int rtsp_parse_request(HTTPContext *c)
02844 {
02845 const char *p, *p1, *p2;
02846 char cmd[32];
02847 char url[1024];
02848 char protocol[32];
02849 char line[1024];
02850 int len;
02851 RTSPMessageHeader header1, *header = &header1;
02852
02853 c->buffer_ptr[0] = '\0';
02854 p = c->buffer;
02855
02856 get_word(cmd, sizeof(cmd), &p);
02857 get_word(url, sizeof(url), &p);
02858 get_word(protocol, sizeof(protocol), &p);
02859
02860 av_strlcpy(c->method, cmd, sizeof(c->method));
02861 av_strlcpy(c->url, url, sizeof(c->url));
02862 av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
02863
02864 if (url_open_dyn_buf(&c->pb) < 0) {
02865
02866 c->pb = NULL;
02867 return -1;
02868 }
02869
02870
02871 if (strcmp(protocol, "RTSP/1.0") != 0) {
02872 rtsp_reply_error(c, RTSP_STATUS_VERSION);
02873 goto the_end;
02874 }
02875
02876
02877 memset(header, 0, sizeof(*header));
02878
02879 while (*p != '\n' && *p != '\0')
02880 p++;
02881 if (*p == '\n')
02882 p++;
02883 while (*p != '\0') {
02884 p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
02885 if (!p1)
02886 break;
02887 p2 = p1;
02888 if (p2 > p && p2[-1] == '\r')
02889 p2--;
02890
02891 if (p2 == p)
02892 break;
02893 len = p2 - p;
02894 if (len > sizeof(line) - 1)
02895 len = sizeof(line) - 1;
02896 memcpy(line, p, len);
02897 line[len] = '\0';
02898 ff_rtsp_parse_line(header, line, NULL, NULL);
02899 p = p1 + 1;
02900 }
02901
02902
02903 c->seq = header->seq;
02904
02905 if (!strcmp(cmd, "DESCRIBE"))
02906 rtsp_cmd_describe(c, url);
02907 else if (!strcmp(cmd, "OPTIONS"))
02908 rtsp_cmd_options(c, url);
02909 else if (!strcmp(cmd, "SETUP"))
02910 rtsp_cmd_setup(c, url, header);
02911 else if (!strcmp(cmd, "PLAY"))
02912 rtsp_cmd_play(c, url, header);
02913 else if (!strcmp(cmd, "PAUSE"))
02914 rtsp_cmd_pause(c, url, header);
02915 else if (!strcmp(cmd, "TEARDOWN"))
02916 rtsp_cmd_teardown(c, url, header);
02917 else
02918 rtsp_reply_error(c, RTSP_STATUS_METHOD);
02919
02920 the_end:
02921 len = url_close_dyn_buf(c->pb, &c->pb_buffer);
02922 c->pb = NULL;
02923 if (len < 0) {
02924
02925 return -1;
02926 }
02927 c->buffer_ptr = c->pb_buffer;
02928 c->buffer_end = c->pb_buffer + len;
02929 c->state = RTSPSTATE_SEND_REPLY;
02930 return 0;
02931 }
02932
02933 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
02934 struct in_addr my_ip)
02935 {
02936 AVFormatContext *avc;
02937 AVStream *avs = NULL;
02938 int i;
02939
02940 avc = avformat_alloc_context();
02941 if (avc == NULL) {
02942 return -1;
02943 }
02944 av_metadata_set2(&avc->metadata, "title",
02945 stream->title[0] ? stream->title : "No Title", 0);
02946 avc->nb_streams = stream->nb_streams;
02947 if (stream->is_multicast) {
02948 snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
02949 inet_ntoa(stream->multicast_ip),
02950 stream->multicast_port, stream->multicast_ttl);
02951 } else {
02952 snprintf(avc->filename, 1024, "rtp://0.0.0.0");
02953 }
02954
02955 #if !FF_API_MAX_STREAMS
02956 if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
02957 !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
02958 goto sdp_done;
02959 #endif
02960 if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
02961 !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
02962 goto sdp_done;
02963
02964 for(i = 0; i < stream->nb_streams; i++) {
02965 avc->streams[i] = &avs[i];
02966 avc->streams[i]->codec = stream->streams[i]->codec;
02967 }
02968 *pbuffer = av_mallocz(2048);
02969 avf_sdp_create(&avc, 1, *pbuffer, 2048);
02970
02971 sdp_done:
02972 #if !FF_API_MAX_STREAMS
02973 av_free(avc->streams);
02974 #endif
02975 av_metadata_free(&avc->metadata);
02976 av_free(avc);
02977 av_free(avs);
02978
02979 return strlen(*pbuffer);
02980 }
02981
02982 static void rtsp_cmd_options(HTTPContext *c, const char *url)
02983 {
02984
02985 url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
02986 url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
02987 url_fprintf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
02988 url_fprintf(c->pb, "\r\n");
02989 }
02990
02991 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
02992 {
02993 FFStream *stream;
02994 char path1[1024];
02995 const char *path;
02996 uint8_t *content;
02997 int content_length, len;
02998 struct sockaddr_in my_addr;
02999
03000
03001 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
03002 path = path1;
03003 if (*path == '/')
03004 path++;
03005
03006 for(stream = first_stream; stream != NULL; stream = stream->next) {
03007 if (!stream->is_feed &&
03008 stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
03009 !strcmp(path, stream->filename)) {
03010 goto found;
03011 }
03012 }
03013
03014 rtsp_reply_error(c, RTSP_STATUS_SERVICE);
03015 return;
03016
03017 found:
03018
03019
03020
03021 len = sizeof(my_addr);
03022 getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
03023 content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
03024 if (content_length < 0) {
03025 rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
03026 return;
03027 }
03028 rtsp_reply_header(c, RTSP_STATUS_OK);
03029 url_fprintf(c->pb, "Content-Base: %s/\r\n", url);
03030 url_fprintf(c->pb, "Content-Type: application/sdp\r\n");
03031 url_fprintf(c->pb, "Content-Length: %d\r\n", content_length);
03032 url_fprintf(c->pb, "\r\n");
03033 put_buffer(c->pb, content, content_length);
03034 av_free(content);
03035 }
03036
03037 static HTTPContext *find_rtp_session(const char *session_id)
03038 {
03039 HTTPContext *c;
03040
03041 if (session_id[0] == '\0')
03042 return NULL;
03043
03044 for(c = first_http_ctx; c != NULL; c = c->next) {
03045 if (!strcmp(c->session_id, session_id))
03046 return c;
03047 }
03048 return NULL;
03049 }
03050
03051 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
03052 {
03053 RTSPTransportField *th;
03054 int i;
03055
03056 for(i=0;i<h->nb_transports;i++) {
03057 th = &h->transports[i];
03058 if (th->lower_transport == lower_transport)
03059 return th;
03060 }
03061 return NULL;
03062 }
03063
03064 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
03065 RTSPMessageHeader *h)
03066 {
03067 FFStream *stream;
03068 int stream_index, rtp_port, rtcp_port;
03069 char buf[1024];
03070 char path1[1024];
03071 const char *path;
03072 HTTPContext *rtp_c;
03073 RTSPTransportField *th;
03074 struct sockaddr_in dest_addr;
03075 RTSPActionServerSetup setup;
03076
03077
03078 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
03079 path = path1;
03080 if (*path == '/')
03081 path++;
03082
03083
03084 for(stream = first_stream; stream != NULL; stream = stream->next) {
03085 if (!stream->is_feed &&
03086 stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
03087
03088 if (!strcmp(path, stream->filename)) {
03089 if (stream->nb_streams != 1) {
03090 rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
03091 return;
03092 }
03093 stream_index = 0;
03094 goto found;
03095 }
03096
03097 for(stream_index = 0; stream_index < stream->nb_streams;
03098 stream_index++) {
03099 snprintf(buf, sizeof(buf), "%s/streamid=%d",
03100 stream->filename, stream_index);
03101 if (!strcmp(path, buf))
03102 goto found;
03103 }
03104 }
03105 }
03106
03107 rtsp_reply_error(c, RTSP_STATUS_SERVICE);
03108 return;
03109 found:
03110
03111
03112 if (h->session_id[0] == '\0')
03113 snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
03114 av_lfg_get(&random_state), av_lfg_get(&random_state));
03115
03116
03117 rtp_c = find_rtp_session(h->session_id);
03118 if (!rtp_c) {
03119
03120 th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
03121 if (!th) {
03122 th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
03123 if (!th) {
03124 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
03125 return;
03126 }
03127 }
03128
03129 rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
03130 th->lower_transport);
03131 if (!rtp_c) {
03132 rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
03133 return;
03134 }
03135
03136
03137 if (open_input_stream(rtp_c, "") < 0) {
03138 rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
03139 return;
03140 }
03141 }
03142
03143
03144
03145 if (rtp_c->stream != stream) {
03146 rtsp_reply_error(c, RTSP_STATUS_SERVICE);
03147 return;
03148 }
03149
03150
03151 if (rtp_c->rtp_ctx[stream_index]) {
03152 rtsp_reply_error(c, RTSP_STATUS_STATE);
03153 return;
03154 }
03155
03156
03157 th = find_transport(h, rtp_c->rtp_protocol);
03158 if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
03159 th->client_port_min <= 0)) {
03160 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
03161 return;
03162 }
03163
03164
03165 setup.transport_option[0] = '\0';
03166 dest_addr = rtp_c->from_addr;
03167 dest_addr.sin_port = htons(th->client_port_min);
03168
03169
03170 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
03171 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
03172 return;
03173 }
03174
03175
03176 rtsp_reply_header(c, RTSP_STATUS_OK);
03177
03178 url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
03179
03180 switch(rtp_c->rtp_protocol) {
03181 case RTSP_LOWER_TRANSPORT_UDP:
03182 rtp_port = rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
03183 rtcp_port = rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
03184 url_fprintf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
03185 "client_port=%d-%d;server_port=%d-%d",
03186 th->client_port_min, th->client_port_max,
03187 rtp_port, rtcp_port);
03188 break;
03189 case RTSP_LOWER_TRANSPORT_TCP:
03190 url_fprintf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
03191 stream_index * 2, stream_index * 2 + 1);
03192 break;
03193 default:
03194 break;
03195 }
03196 if (setup.transport_option[0] != '\0')
03197 url_fprintf(c->pb, ";%s", setup.transport_option);
03198 url_fprintf(c->pb, "\r\n");
03199
03200
03201 url_fprintf(c->pb, "\r\n");
03202 }
03203
03204
03205
03206
03207 static HTTPContext *find_rtp_session_with_url(const char *url,
03208 const char *session_id)
03209 {
03210 HTTPContext *rtp_c;
03211 char path1[1024];
03212 const char *path;
03213 char buf[1024];
03214 int s;
03215
03216 rtp_c = find_rtp_session(session_id);
03217 if (!rtp_c)
03218 return NULL;
03219
03220
03221 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
03222 path = path1;
03223 if (*path == '/')
03224 path++;
03225 if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
03226 for(s=0; s<rtp_c->stream->nb_streams; ++s) {
03227 snprintf(buf, sizeof(buf), "%s/streamid=%d",
03228 rtp_c->stream->filename, s);
03229 if(!strncmp(path, buf, sizeof(buf))) {
03230
03231 return rtp_c;
03232 }
03233 }
03234 return NULL;
03235 }
03236
03237 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
03238 {
03239 HTTPContext *rtp_c;
03240
03241 rtp_c = find_rtp_session_with_url(url, h->session_id);
03242 if (!rtp_c) {
03243 rtsp_reply_error(c, RTSP_STATUS_SESSION);
03244 return;
03245 }
03246
03247 if (rtp_c->state != HTTPSTATE_SEND_DATA &&
03248 rtp_c->state != HTTPSTATE_WAIT_FEED &&
03249 rtp_c->state != HTTPSTATE_READY) {
03250 rtsp_reply_error(c, RTSP_STATUS_STATE);
03251 return;
03252 }
03253
03254 rtp_c->state = HTTPSTATE_SEND_DATA;
03255
03256
03257 rtsp_reply_header(c, RTSP_STATUS_OK);
03258
03259 url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
03260 url_fprintf(c->pb, "\r\n");
03261 }
03262
03263 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
03264 {
03265 HTTPContext *rtp_c;
03266
03267 rtp_c = find_rtp_session_with_url(url, h->session_id);
03268 if (!rtp_c) {
03269 rtsp_reply_error(c, RTSP_STATUS_SESSION);
03270 return;
03271 }
03272
03273 if (rtp_c->state != HTTPSTATE_SEND_DATA &&
03274 rtp_c->state != HTTPSTATE_WAIT_FEED) {
03275 rtsp_reply_error(c, RTSP_STATUS_STATE);
03276 return;
03277 }
03278
03279 rtp_c->state = HTTPSTATE_READY;
03280 rtp_c->first_pts = AV_NOPTS_VALUE;
03281
03282 rtsp_reply_header(c, RTSP_STATUS_OK);
03283
03284 url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
03285 url_fprintf(c->pb, "\r\n");
03286 }
03287
03288 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
03289 {
03290 HTTPContext *rtp_c;
03291 char session_id[32];
03292
03293 rtp_c = find_rtp_session_with_url(url, h->session_id);
03294 if (!rtp_c) {
03295 rtsp_reply_error(c, RTSP_STATUS_SESSION);
03296 return;
03297 }
03298
03299 av_strlcpy(session_id, rtp_c->session_id, sizeof(session_id));
03300
03301
03302 close_connection(rtp_c);
03303
03304
03305 rtsp_reply_header(c, RTSP_STATUS_OK);
03306
03307 url_fprintf(c->pb, "Session: %s\r\n", session_id);
03308 url_fprintf(c->pb, "\r\n");
03309 }
03310
03311
03312
03313
03314
03315 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
03316 FFStream *stream, const char *session_id,
03317 enum RTSPLowerTransport rtp_protocol)
03318 {
03319 HTTPContext *c = NULL;
03320 const char *proto_str;
03321
03322
03323
03324 if (nb_connections >= nb_max_connections)
03325 goto fail;
03326
03327
03328 c = av_mallocz(sizeof(HTTPContext));
03329 if (!c)
03330 goto fail;
03331
03332 c->fd = -1;
03333 c->poll_entry = NULL;
03334 c->from_addr = *from_addr;
03335 c->buffer_size = IOBUFFER_INIT_SIZE;
03336 c->buffer = av_malloc(c->buffer_size);
03337 if (!c->buffer)
03338 goto fail;
03339 nb_connections++;
03340 c->stream = stream;
03341 av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
03342 c->state = HTTPSTATE_READY;
03343 c->is_packetized = 1;
03344 c->rtp_protocol = rtp_protocol;
03345
03346
03347 switch(c->rtp_protocol) {
03348 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
03349 proto_str = "MCAST";
03350 break;
03351 case RTSP_LOWER_TRANSPORT_UDP:
03352 proto_str = "UDP";
03353 break;
03354 case RTSP_LOWER_TRANSPORT_TCP:
03355 proto_str = "TCP";
03356 break;
03357 default:
03358 proto_str = "???";
03359 break;
03360 }
03361 av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
03362 av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
03363
03364 current_bandwidth += stream->bandwidth;
03365
03366 c->next = first_http_ctx;
03367 first_http_ctx = c;
03368 return c;
03369
03370 fail:
03371 if (c) {
03372 av_free(c->buffer);
03373 av_free(c);
03374 }
03375 return NULL;
03376 }
03377
03378
03379
03380
03381 static int rtp_new_av_stream(HTTPContext *c,
03382 int stream_index, struct sockaddr_in *dest_addr,
03383 HTTPContext *rtsp_c)
03384 {
03385 AVFormatContext *ctx;
03386 AVStream *st;
03387 char *ipaddr;
03388 URLContext *h = NULL;
03389 uint8_t *dummy_buf;
03390 int max_packet_size;
03391
03392
03393 ctx = avformat_alloc_context();
03394 if (!ctx)
03395 return -1;
03396 ctx->oformat = av_guess_format("rtp", NULL, NULL);
03397
03398 st = av_mallocz(sizeof(AVStream));
03399 if (!st)
03400 goto fail;
03401 ctx->nb_streams = 1;
03402 ctx->streams[0] = st;
03403
03404 if (!c->stream->feed ||
03405 c->stream->feed == c->stream)
03406 memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
03407 else
03408 memcpy(st,
03409 c->stream->feed->streams[c->stream->feed_streams[stream_index]],
03410 sizeof(AVStream));
03411 st->priv_data = NULL;
03412
03413
03414 ipaddr = inet_ntoa(dest_addr->sin_addr);
03415
03416 switch(c->rtp_protocol) {
03417 case RTSP_LOWER_TRANSPORT_UDP:
03418 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
03419
03420
03421
03422 if (c->stream->is_multicast) {
03423 int ttl;
03424 ttl = c->stream->multicast_ttl;
03425 if (!ttl)
03426 ttl = 16;
03427 snprintf(ctx->filename, sizeof(ctx->filename),
03428 "rtp://%s:%d?multicast=1&ttl=%d",
03429 ipaddr, ntohs(dest_addr->sin_port), ttl);
03430 } else {
03431 snprintf(ctx->filename, sizeof(ctx->filename),
03432 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
03433 }
03434
03435 if (url_open(&h, ctx->filename, URL_WRONLY) < 0)
03436 goto fail;
03437 c->rtp_handles[stream_index] = h;
03438 max_packet_size = url_get_max_packet_size(h);
03439 break;
03440 case RTSP_LOWER_TRANSPORT_TCP:
03441
03442 c->rtsp_c = rtsp_c;
03443 max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
03444 break;
03445 default:
03446 goto fail;
03447 }
03448
03449 http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
03450 ipaddr, ntohs(dest_addr->sin_port),
03451 c->stream->filename, stream_index, c->protocol);
03452
03453
03454 if (url_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
03455
03456 goto fail;
03457 }
03458 av_set_parameters(ctx, NULL);
03459 if (av_write_header(ctx) < 0) {
03460 fail:
03461 if (h)
03462 url_close(h);
03463 av_free(ctx);
03464 return -1;
03465 }
03466 url_close_dyn_buf(ctx->pb, &dummy_buf);
03467 av_free(dummy_buf);
03468
03469 c->rtp_ctx[stream_index] = ctx;
03470 return 0;
03471 }
03472
03473
03474
03475
03476 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
03477 {
03478 AVStream *fst;
03479
03480 fst = av_mallocz(sizeof(AVStream));
03481 if (!fst)
03482 return NULL;
03483 if (copy) {
03484 fst->codec= avcodec_alloc_context();
03485 memcpy(fst->codec, codec, sizeof(AVCodecContext));
03486 if (codec->extradata_size) {
03487 fst->codec->extradata = av_malloc(codec->extradata_size);
03488 memcpy(fst->codec->extradata, codec->extradata,
03489 codec->extradata_size);
03490 }
03491 } else {
03492
03493
03494
03495 fst->codec = codec;
03496 }
03497 fst->priv_data = av_mallocz(sizeof(FeedData));
03498 fst->index = stream->nb_streams;
03499 av_set_pts_info(fst, 33, 1, 90000);
03500 fst->sample_aspect_ratio = (AVRational){0,1};
03501 stream->streams[stream->nb_streams++] = fst;
03502 return fst;
03503 }
03504
03505
03506 static int add_av_stream(FFStream *feed, AVStream *st)
03507 {
03508 AVStream *fst;
03509 AVCodecContext *av, *av1;
03510 int i;
03511
03512 av = st->codec;
03513 for(i=0;i<feed->nb_streams;i++) {
03514 st = feed->streams[i];
03515 av1 = st->codec;
03516 if (av1->codec_id == av->codec_id &&
03517 av1->codec_type == av->codec_type &&
03518 av1->bit_rate == av->bit_rate) {
03519
03520 switch(av->codec_type) {
03521 case AVMEDIA_TYPE_AUDIO:
03522 if (av1->channels == av->channels &&
03523 av1->sample_rate == av->sample_rate)
03524 goto found;
03525 break;
03526 case AVMEDIA_TYPE_VIDEO:
03527 if (av1->width == av->width &&
03528 av1->height == av->height &&
03529 av1->time_base.den == av->time_base.den &&
03530 av1->time_base.num == av->time_base.num &&
03531 av1->gop_size == av->gop_size)
03532 goto found;
03533 break;
03534 default:
03535 abort();
03536 }
03537 }
03538 }
03539
03540 fst = add_av_stream1(feed, av, 0);
03541 if (!fst)
03542 return -1;
03543 return feed->nb_streams - 1;
03544 found:
03545 return i;
03546 }
03547
03548 static void remove_stream(FFStream *stream)
03549 {
03550 FFStream **ps;
03551 ps = &first_stream;
03552 while (*ps != NULL) {
03553 if (*ps == stream)
03554 *ps = (*ps)->next;
03555 else
03556 ps = &(*ps)->next;
03557 }
03558 }
03559
03560
03561 static void extract_mpeg4_header(AVFormatContext *infile)
03562 {
03563 int mpeg4_count, i,