ffserver.c

Go to the documentation of this file.
00001 /*
00002  * Multiple format streaming server
00003  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "config.h"
00023 #ifndef HAVE_CLOSESOCKET
00024 #define closesocket close
00025 #endif
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include "libavutil/random.h"
00029 #include "libavutil/avstring.h"
00030 #include "libavformat/avformat.h"
00031 #include "libavformat/network.h"
00032 #include "libavformat/os_support.h"
00033 #include "libavformat/rtp.h"
00034 #include "libavformat/rtsp.h"
00035 #include "libavcodec/opt.h"
00036 #include <stdarg.h>
00037 #include <unistd.h>
00038 #include <fcntl.h>
00039 #include <sys/ioctl.h>
00040 #ifdef HAVE_POLL_H
00041 #include <poll.h>
00042 #endif
00043 #include <errno.h>
00044 #include <sys/time.h>
00045 #undef time //needed because HAVE_AV_CONFIG_H is defined on top
00046 #include <time.h>
00047 #include <sys/wait.h>
00048 #include <signal.h>
00049 #ifdef HAVE_DLFCN_H
00050 #include <dlfcn.h>
00051 #endif
00052 
00053 #include "cmdutils.h"
00054 
00055 #undef exit
00056 
00057 const char program_name[] = "FFserver";
00058 const int program_birth_year = 2000;
00059 
00060 static const OptionDef options[];
00061 
00062 /* maximum number of simultaneous HTTP connections */
00063 #define HTTP_MAX_CONNECTIONS 2000
00064 
00065 enum HTTPState {
00066     HTTPSTATE_WAIT_REQUEST,
00067     HTTPSTATE_SEND_HEADER,
00068     HTTPSTATE_SEND_DATA_HEADER,
00069     HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
00070     HTTPSTATE_SEND_DATA_TRAILER,
00071     HTTPSTATE_RECEIVE_DATA,
00072     HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
00073     HTTPSTATE_READY,
00074 
00075     RTSPSTATE_WAIT_REQUEST,
00076     RTSPSTATE_SEND_REPLY,
00077     RTSPSTATE_SEND_PACKET,
00078 };
00079 
00080 static const char *http_state[] = {
00081     "HTTP_WAIT_REQUEST",
00082     "HTTP_SEND_HEADER",
00083 
00084     "SEND_DATA_HEADER",
00085     "SEND_DATA",
00086     "SEND_DATA_TRAILER",
00087     "RECEIVE_DATA",
00088     "WAIT_FEED",
00089     "READY",
00090 
00091     "RTSP_WAIT_REQUEST",
00092     "RTSP_SEND_REPLY",
00093     "RTSP_SEND_PACKET",
00094 };
00095 
00096 #define IOBUFFER_INIT_SIZE 8192
00097 
00098 /* timeouts are in ms */
00099 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
00100 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
00101 
00102 #define SYNC_TIMEOUT (10 * 1000)
00103 
00104 typedef struct {
00105     int64_t count1, count2;
00106     int64_t time1, time2;
00107 } DataRateData;
00108 
00109 /* context associated with one connection */
00110 typedef struct HTTPContext {
00111     enum HTTPState state;
00112     int fd; /* socket file descriptor */
00113     struct sockaddr_in from_addr; /* origin */
00114     struct pollfd *poll_entry; /* used when polling */
00115     int64_t timeout;
00116     uint8_t *buffer_ptr, *buffer_end;
00117     int http_error;
00118     int post;
00119     struct HTTPContext *next;
00120     int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
00121     int64_t data_count;
00122     /* feed input */
00123     int feed_fd;
00124     /* input format handling */
00125     AVFormatContext *fmt_in;
00126     int64_t start_time;            /* In milliseconds - this wraps fairly often */
00127     int64_t first_pts;            /* initial pts value */
00128     int64_t cur_pts;             /* current pts value from the stream in us */
00129     int64_t cur_frame_duration;  /* duration of the current frame in us */
00130     int cur_frame_bytes;       /* output frame size, needed to compute
00131                                   the time at which we send each
00132                                   packet */
00133     int pts_stream_index;        /* stream we choose as clock reference */
00134     int64_t cur_clock;           /* current clock reference value in us */
00135     /* output format handling */
00136     struct FFStream *stream;
00137     /* -1 is invalid stream */
00138     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
00139     int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
00140     int switch_pending;
00141     AVFormatContext fmt_ctx; /* instance of FFStream for one user */
00142     int last_packet_sent; /* true if last data packet was sent */
00143     int suppress_log;
00144     DataRateData datarate;
00145     int wmp_client_id;
00146     char protocol[16];
00147     char method[16];
00148     char url[128];
00149     int buffer_size;
00150     uint8_t *buffer;
00151     int is_packetized; /* if true, the stream is packetized */
00152     int packet_stream_index; /* current stream for output in state machine */
00153 
00154     /* RTSP state specific */
00155     uint8_t *pb_buffer; /* XXX: use that in all the code */
00156     ByteIOContext *pb;
00157     int seq; /* RTSP sequence number */
00158 
00159     /* RTP state specific */
00160     enum RTSPProtocol rtp_protocol;
00161     char session_id[32]; /* session id */
00162     AVFormatContext *rtp_ctx[MAX_STREAMS];
00163 
00164     /* RTP/UDP specific */
00165     URLContext *rtp_handles[MAX_STREAMS];
00166 
00167     /* RTP/TCP specific */
00168     struct HTTPContext *rtsp_c;
00169     uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
00170 } HTTPContext;
00171 
00172 /* each generated stream is described here */
00173 enum StreamType {
00174     STREAM_TYPE_LIVE,
00175     STREAM_TYPE_STATUS,
00176     STREAM_TYPE_REDIRECT,
00177 };
00178 
00179 enum IPAddressAction {
00180     IP_ALLOW = 1,
00181     IP_DENY,
00182 };
00183 
00184 typedef struct IPAddressACL {
00185     struct IPAddressACL *next;
00186     enum IPAddressAction action;
00187     /* These are in host order */
00188     struct in_addr first;
00189     struct in_addr last;
00190 } IPAddressACL;
00191 
00192 /* description of each stream of the ffserver.conf file */
00193 typedef struct FFStream {
00194     enum StreamType stream_type;
00195     char filename[1024];     /* stream filename */
00196     struct FFStream *feed;   /* feed we are using (can be null if
00197                                 coming from file) */
00198     AVFormatParameters *ap_in; /* input parameters */
00199     AVInputFormat *ifmt;       /* if non NULL, force input format */
00200     AVOutputFormat *fmt;
00201     IPAddressACL *acl;
00202     int nb_streams;
00203     int prebuffer;      /* Number of millseconds early to start */
00204     int64_t max_time;      /* Number of milliseconds to run */
00205     int send_on_key;
00206     AVStream *streams[MAX_STREAMS];
00207     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
00208     char feed_filename[1024]; /* file name of the feed storage, or
00209                                  input file name for a stream */
00210     char author[512];
00211     char title[512];
00212     char copyright[512];
00213     char comment[512];
00214     pid_t pid;  /* Of ffmpeg process */
00215     time_t pid_start;  /* Of ffmpeg process */
00216     char **child_argv;
00217     struct FFStream *next;
00218     unsigned bandwidth; /* bandwidth, in kbits/s */
00219     /* RTSP options */
00220     char *rtsp_option;
00221     /* multicast specific */
00222     int is_multicast;
00223     struct in_addr multicast_ip;
00224     int multicast_port; /* first port used for multicast */
00225     int multicast_ttl;
00226     int loop; /* if true, send the stream in loops (only meaningful if file) */
00227 
00228     /* feed specific */
00229     int feed_opened;     /* true if someone is writing to the feed */
00230     int is_feed;         /* true if it is a feed */
00231     int readonly;        /* True if writing is prohibited to the file */
00232     int conns_served;
00233     int64_t bytes_served;
00234     int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
00235     int64_t feed_write_index;   /* current write position in feed (it wraps around) */
00236     int64_t feed_size;          /* current size of feed */
00237     struct FFStream *next_feed;
00238 } FFStream;
00239 
00240 typedef struct FeedData {
00241     long long data_count;
00242     float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
00243 } FeedData;
00244 
00245 static struct sockaddr_in my_http_addr;
00246 static struct sockaddr_in my_rtsp_addr;
00247 
00248 static char logfilename[1024];
00249 static HTTPContext *first_http_ctx;
00250 static FFStream *first_feed;   /* contains only feeds */
00251 static FFStream *first_stream; /* contains all streams, including feeds */
00252 
00253 static void new_connection(int server_fd, int is_rtsp);
00254 static void close_connection(HTTPContext *c);
00255 
00256 /* HTTP handling */
00257 static int handle_connection(HTTPContext *c);
00258 static int http_parse_request(HTTPContext *c);
00259 static int http_send_data(HTTPContext *c);
00260 static void compute_status(HTTPContext *c);
00261 static int open_input_stream(HTTPContext *c, const char *info);
00262 static int http_start_receive_data(HTTPContext *c);
00263 static int http_receive_data(HTTPContext *c);
00264 
00265 /* RTSP handling */
00266 static int rtsp_parse_request(HTTPContext *c);
00267 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
00268 static void rtsp_cmd_options(HTTPContext *c, const char *url);
00269 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPHeader *h);
00270 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPHeader *h);
00271 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h);
00272 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h);
00273 
00274 /* SDP handling */
00275 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
00276                                    struct in_addr my_ip);
00277 
00278 /* RTP handling */
00279 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
00280                                        FFStream *stream, const char *session_id,
00281                                        enum RTSPProtocol rtp_protocol);
00282 static int rtp_new_av_stream(HTTPContext *c,
00283                              int stream_index, struct sockaddr_in *dest_addr,
00284                              HTTPContext *rtsp_c);
00285 
00286 static const char *my_program_name;
00287 static const char *my_program_dir;
00288 
00289 static const char *config_filename;
00290 static int ffserver_debug;
00291 static int ffserver_daemon;
00292 static int no_launch;
00293 static int need_to_start_children;
00294 
00295 static int nb_max_connections = 5;
00296 static int nb_connections;
00297 
00298 static uint64_t max_bandwidth = 1000;
00299 static uint64_t current_bandwidth;
00300 
00301 static int64_t cur_time;           // Making this global saves on passing it around everywhere
00302 
00303 static AVRandomState random_state;
00304 
00305 static FILE *logfile = NULL;
00306 
00307 static char *ctime1(char *buf2)
00308 {
00309     time_t ti;
00310     char *p;
00311 
00312     ti = time(NULL);
00313     p = ctime(&ti);
00314     strcpy(buf2, p);
00315     p = buf2 + strlen(p) - 1;
00316     if (*p == '\n')
00317         *p = '\0';
00318     return buf2;
00319 }
00320 
00321 static void http_vlog(const char *fmt, va_list vargs)
00322 {
00323     static int print_prefix = 1;
00324     if (logfile) {
00325         if (print_prefix) {
00326             char buf[32];
00327             ctime1(buf);
00328             fprintf(logfile, "%s ", buf);
00329         }
00330         print_prefix = strstr(fmt, "\n") != NULL;
00331         vfprintf(logfile, fmt, vargs);
00332         fflush(logfile);
00333     }
00334 }
00335 
00336 void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...)
00337 {
00338     va_list vargs;
00339     va_start(vargs, fmt);
00340     http_vlog(fmt, vargs);
00341     va_end(vargs);
00342 }
00343 
00344 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
00345 {
00346     static int print_prefix = 1;
00347     AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
00348     if (level > av_log_level)
00349         return;
00350     if (print_prefix && avc)
00351         http_log("[%s @ %p]", avc->item_name(ptr), ptr);
00352     print_prefix = strstr(fmt, "\n") != NULL;
00353     http_vlog(fmt, vargs);
00354 }
00355 
00356 static void log_connection(HTTPContext *c)
00357 {
00358     if (c->suppress_log)
00359         return;
00360 
00361     http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
00362              inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
00363              c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
00364 }
00365 
00366 static void update_datarate(DataRateData *drd, int64_t count)
00367 {
00368     if (!drd->time1 && !drd->count1) {
00369         drd->time1 = drd->time2 = cur_time;
00370         drd->count1 = drd->count2 = count;
00371     } else if (cur_time - drd->time2 > 5000) {
00372         drd->time1 = drd->time2;
00373         drd->count1 = drd->count2;
00374         drd->time2 = cur_time;
00375         drd->count2 = count;
00376     }
00377 }
00378 
00379 /* In bytes per second */
00380 static int compute_datarate(DataRateData *drd, int64_t count)
00381 {
00382     if (cur_time == drd->time1)
00383         return 0;
00384 
00385     return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
00386 }
00387 
00388 
00389 static void start_children(FFStream *feed)
00390 {
00391     if (no_launch)
00392         return;
00393 
00394     for (; feed; feed = feed->next) {
00395         if (feed->child_argv && !feed->pid) {
00396             feed->pid_start = time(0);
00397 
00398             feed->pid = fork();
00399 
00400             if (feed->pid < 0) {
00401                 http_log("Unable to create children\n");
00402                 exit(1);
00403             }
00404             if (!feed->pid) {
00405                 /* In child */
00406                 char pathname[1024];
00407                 char *slash;
00408                 int i;
00409 
00410                 av_strlcpy(pathname, my_program_name, sizeof(pathname));
00411 
00412                 slash = strrchr(pathname, '/');
00413                 if (!slash)
00414                     slash = pathname;
00415                 else
00416                     slash++;
00417                 strcpy(slash, "ffmpeg");
00418 
00419                 http_log("Launch commandline: ");
00420                 http_log("%s ", pathname);
00421                 for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
00422                     http_log("%s ", feed->child_argv[i]);
00423                 http_log("\n");
00424 
00425                 for (i = 3; i < 256; i++)
00426                     close(i);
00427 
00428                 if (!ffserver_debug) {
00429                     i = open("/dev/null", O_RDWR);
00430                     if (i != -1) {
00431                         dup2(i, 0);
00432                         dup2(i, 1);
00433                         dup2(i, 2);
00434                         close(i);
00435                     }
00436                 }
00437 
00438                 /* This is needed to make relative pathnames work */
00439                 chdir(my_program_dir);
00440 
00441                 signal(SIGPIPE, SIG_DFL);
00442 
00443                 execvp(pathname, feed->child_argv);
00444 
00445                 _exit(1);
00446             }
00447         }
00448     }
00449 }
00450 
00451 /* open a listening socket */
00452 static int socket_open_listen(struct sockaddr_in *my_addr)
00453 {
00454     int server_fd, tmp;
00455 
00456     server_fd = socket(AF_INET,SOCK_STREAM,0);
00457     if (server_fd < 0) {
00458         perror ("socket");
00459         return -1;
00460     }
00461 
00462     tmp = 1;
00463     setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
00464 
00465     if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
00466         char bindmsg[32];
00467         snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
00468         perror (bindmsg);
00469         closesocket(server_fd);
00470         return -1;
00471     }
00472 
00473     if (listen (server_fd, 5) < 0) {
00474         perror ("listen");
00475         closesocket(server_fd);
00476         return -1;
00477     }
00478     ff_socket_nonblock(server_fd, 1);
00479 
00480     return server_fd;
00481 }
00482 
00483 /* start all multicast streams */
00484 static void start_multicast(void)
00485 {
00486     FFStream *stream;
00487     char session_id[32];
00488     HTTPContext *rtp_c;
00489     struct sockaddr_in dest_addr;
00490     int default_port, stream_index;
00491 
00492     default_port = 6000;
00493     for(stream = first_stream; stream != NULL; stream = stream->next) {
00494         if (stream->is_multicast) {
00495             /* open the RTP connection */
00496             snprintf(session_id, sizeof(session_id), "%08x%08x",
00497                      av_random(&random_state), av_random(&random_state));
00498 
00499             /* choose a port if none given */
00500             if (stream->multicast_port == 0) {
00501                 stream->multicast_port = default_port;
00502                 default_port += 100;
00503             }
00504 
00505             dest_addr.sin_family = AF_INET;
00506             dest_addr.sin_addr = stream->multicast_ip;
00507             dest_addr.sin_port = htons(stream->multicast_port);
00508 
00509             rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
00510                                        RTSP_PROTOCOL_RTP_UDP_MULTICAST);
00511             if (!rtp_c)
00512                 continue;
00513 
00514             if (open_input_stream(rtp_c, "") < 0) {
00515                 http_log("Could not open input stream for stream '%s'\n",
00516                          stream->filename);
00517                 continue;
00518             }
00519 
00520             /* open each RTP stream */
00521             for(stream_index = 0; stream_index < stream->nb_streams;
00522                 stream_index++) {
00523                 dest_addr.sin_port = htons(stream->multicast_port +
00524                                            2 * stream_index);
00525                 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
00526                     http_log("Could not open output stream '%s/streamid=%d'\n",
00527                              stream->filename, stream_index);
00528                     exit(1);
00529                 }
00530             }
00531 
00532             /* change state to send data */
00533             rtp_c->state = HTTPSTATE_SEND_DATA;
00534         }
00535     }
00536 }
00537 
00538 /* main loop of the http server */
00539 static int http_server(void)
00540 {
00541     int server_fd = 0, rtsp_server_fd = 0;
00542     int ret, delay, delay1;
00543     struct pollfd poll_table[HTTP_MAX_CONNECTIONS + 2], *poll_entry;
00544     HTTPContext *c, *c_next;
00545 
00546     if (my_http_addr.sin_port) {
00547         server_fd = socket_open_listen(&my_http_addr);
00548         if (server_fd < 0)
00549             return -1;
00550     }
00551 
00552     if (my_rtsp_addr.sin_port) {
00553         rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
00554         if (rtsp_server_fd < 0)
00555             return -1;
00556     }
00557 
00558     if (!rtsp_server_fd && !server_fd) {
00559         http_log("HTTP and RTSP disabled.\n");
00560         return -1;
00561     }
00562 
00563     http_log("ffserver started.\n");
00564 
00565     start_children(first_feed);
00566 
00567     start_multicast();
00568 
00569     for(;;) {
00570         poll_entry = poll_table;
00571         if (server_fd) {
00572             poll_entry->fd = server_fd;
00573             poll_entry->events = POLLIN;
00574             poll_entry++;
00575         }
00576         if (rtsp_server_fd) {
00577             poll_entry->fd = rtsp_server_fd;
00578             poll_entry->events = POLLIN;
00579             poll_entry++;
00580         }
00581 
00582         /* wait for events on each HTTP handle */
00583         c = first_http_ctx;
00584         delay = 1000;
00585         while (c != NULL) {
00586             int fd;
00587             fd = c->fd;
00588             switch(c->state) {
00589             case HTTPSTATE_SEND_HEADER:
00590             case RTSPSTATE_SEND_REPLY:
00591             case RTSPSTATE_SEND_PACKET:
00592                 c->poll_entry = poll_entry;
00593                 poll_entry->fd = fd;
00594                 poll_entry->events = POLLOUT;
00595                 poll_entry++;
00596                 break;
00597             case HTTPSTATE_SEND_DATA_HEADER:
00598             case HTTPSTATE_SEND_DATA:
00599             case HTTPSTATE_SEND_DATA_TRAILER:
00600                 if (!c->is_packetized) {
00601                     /* for TCP, we output as much as we can (may need to put a limit) */
00602                     c->poll_entry = poll_entry;
00603                     poll_entry->fd = fd;
00604                     poll_entry->events = POLLOUT;
00605                     poll_entry++;
00606                 } else {
00607                     /* when ffserver is doing the timing, we work by
00608                        looking at which packet need to be sent every
00609                        10 ms */
00610                     delay1 = 10; /* one tick wait XXX: 10 ms assumed */
00611                     if (delay1 < delay)
00612                         delay = delay1;
00613                 }
00614                 break;
00615             case HTTPSTATE_WAIT_REQUEST:
00616             case HTTPSTATE_RECEIVE_DATA:
00617             case HTTPSTATE_WAIT_FEED:
00618             case RTSPSTATE_WAIT_REQUEST:
00619                 /* need to catch errors */
00620                 c->poll_entry = poll_entry;
00621                 poll_entry->fd = fd;
00622                 poll_entry->events = POLLIN;/* Maybe this will work */
00623                 poll_entry++;
00624                 break;
00625             default:
00626                 c->poll_entry = NULL;
00627                 break;
00628             }
00629             c = c->next;
00630         }
00631 
00632         /* wait for an event on one connection. We poll at least every
00633            second to handle timeouts */
00634         do {
00635             ret = poll(poll_table, poll_entry - poll_table, delay);
00636             if (ret < 0 && ff_neterrno() != FF_NETERROR(EAGAIN) &&
00637                 ff_neterrno() != FF_NETERROR(EINTR))
00638                 return -1;
00639         } while (ret < 0);
00640 
00641         cur_time = av_gettime() / 1000;
00642 
00643         if (need_to_start_children) {
00644             need_to_start_children = 0;
00645             start_children(first_feed);
00646         }
00647 
00648         /* now handle the events */
00649         for(c = first_http_ctx; c != NULL; c = c_next) {
00650             c_next = c->next;
00651             if (handle_connection(c) < 0) {
00652                 /* close and free the connection */
00653                 log_connection(c);
00654                 close_connection(c);
00655             }
00656         }
00657 
00658         poll_entry = poll_table;
00659         if (server_fd) {
00660             /* new HTTP connection request ? */
00661             if (poll_entry->revents & POLLIN)
00662                 new_connection(server_fd, 0);
00663             poll_entry++;
00664         }
00665         if (rtsp_server_fd) {
00666             /* new RTSP connection request ? */
00667             if (poll_entry->revents & POLLIN)
00668                 new_connection(rtsp_server_fd, 1);
00669         }
00670     }
00671 }
00672 
00673 /* start waiting for a new HTTP/RTSP request */
00674 static void start_wait_request(HTTPContext *c, int is_rtsp)
00675 {
00676     c->buffer_ptr = c->buffer;
00677     c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
00678 
00679     if (is_rtsp) {
00680         c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
00681         c->state = RTSPSTATE_WAIT_REQUEST;
00682     } else {
00683         c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
00684         c->state = HTTPSTATE_WAIT_REQUEST;
00685     }
00686 }
00687 
00688 static void new_connection(int server_fd, int is_rtsp)
00689 {
00690     struct sockaddr_in from_addr;
00691     int fd, len;
00692     HTTPContext *c = NULL;
00693 
00694     len = sizeof(from_addr);
00695     fd = accept(server_fd, (struct sockaddr *)&from_addr,
00696                 &len);
00697     if (fd < 0) {
00698         http_log("error during accept %s\n", strerror(errno));
00699         return;
00700     }
00701     ff_socket_nonblock(fd, 1);
00702 
00703     /* XXX: should output a warning page when coming
00704        close to the connection limit */
00705     if (nb_connections >= nb_max_connections)
00706         goto fail;
00707 
00708     /* add a new connection */
00709     c = av_mallocz(sizeof(HTTPContext));
00710     if (!c)
00711         goto fail;
00712 
00713     c->fd = fd;
00714     c->poll_entry = NULL;
00715     c->from_addr = from_addr;
00716     c->buffer_size = IOBUFFER_INIT_SIZE;
00717     c->buffer = av_malloc(c->buffer_size);
00718     if (!c->buffer)
00719         goto fail;
00720 
00721     c->next = first_http_ctx;
00722     first_http_ctx = c;
00723     nb_connections++;
00724 
00725     start_wait_request(c, is_rtsp);
00726 
00727     return;
00728 
00729  fail:
00730     if (c) {
00731         av_free(c->buffer);
00732         av_free(c);
00733     }
00734     closesocket(fd);
00735 }
00736 
00737 static void close_connection(HTTPContext *c)
00738 {
00739     HTTPContext **cp, *c1;
00740     int i, nb_streams;
00741     AVFormatContext *ctx;
00742     URLContext *h;
00743     AVStream *st;
00744 
00745     /* remove connection from list */
00746     cp = &first_http_ctx;
00747     while ((*cp) != NULL) {
00748         c1 = *cp;
00749         if (c1 == c)
00750             *cp = c->next;
00751         else
00752             cp = &c1->next;
00753     }
00754 
00755     /* remove references, if any (XXX: do it faster) */
00756     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
00757         if (c1->rtsp_c == c)
00758             c1->rtsp_c = NULL;
00759     }
00760 
00761     /* remove connection associated resources */
00762     if (c->fd >= 0)
00763         closesocket(c->fd);
00764     if (c->fmt_in) {
00765         /* close each frame parser */
00766         for(i=0;i<c->fmt_in->nb_streams;i++) {
00767             st = c->fmt_in->streams[i];
00768             if (st->codec->codec)
00769                 avcodec_close(st->codec);
00770         }
00771         av_close_input_file(c->fmt_in);
00772     }
00773 
00774     /* free RTP output streams if any */
00775     nb_streams = 0;
00776     if (c->stream)
00777         nb_streams = c->stream->nb_streams;
00778 
00779     for(i=0;i<nb_streams;i++) {
00780         ctx = c->rtp_ctx[i];
00781         if (ctx) {
00782             av_write_trailer(ctx);
00783             av_free(ctx);
00784         }
00785         h = c->rtp_handles[i];
00786         if (h)
00787             url_close(h);
00788     }
00789 
00790     ctx = &c->fmt_ctx;
00791 
00792     if (!c->last_packet_sent) {
00793         if (ctx->oformat) {
00794             /* prepare header */
00795             if (url_open_dyn_buf(&ctx->pb) >= 0) {
00796                 av_write_trailer(ctx);
00797                 av_freep(&c->pb_buffer);
00798                 url_close_dyn_buf(ctx->pb, &c->pb_buffer);
00799             }
00800         }
00801     }
00802 
00803     for(i=0; i<ctx->nb_streams; i++)
00804         av_free(ctx->streams[i]);
00805 
00806     if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
00807         current_bandwidth -= c->stream->bandwidth;
00808 
00809     /* signal that there is no feed if we are the feeder socket */
00810     if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
00811         c->stream->feed_opened = 0;
00812         close(c->feed_fd);
00813     }
00814 
00815     av_freep(&c->pb_buffer);
00816     av_freep(&c->packet_buffer);
00817     av_free(c->buffer);
00818     av_free(c);
00819     nb_connections--;
00820 }
00821 
00822 static int handle_connection(HTTPContext *c)
00823 {
00824     int len, ret;
00825 
00826     switch(c->state) {
00827     case HTTPSTATE_WAIT_REQUEST:
00828     case RTSPSTATE_WAIT_REQUEST:
00829         /* timeout ? */
00830         if ((c->timeout - cur_time) < 0)
00831             return -1;
00832         if (c->poll_entry->revents & (POLLERR | POLLHUP))
00833             return -1;
00834 
00835         /* no need to read if no events */
00836         if (!(c->poll_entry->revents & POLLIN))
00837             return 0;
00838         /* read the data */
00839     read_loop:
00840         len = recv(c->fd, c->buffer_ptr, 1, 0);
00841         if (len < 0) {
00842             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
00843                 ff_neterrno() != FF_NETERROR(EINTR))
00844                 return -1;
00845         } else if (len == 0) {
00846             return -1;
00847         } else {
00848             /* search for end of request. */
00849             uint8_t *ptr;
00850             c->buffer_ptr += len;
00851             ptr = c->buffer_ptr;
00852             if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
00853                 (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
00854                 /* request found : parse it and reply */
00855                 if (c->state == HTTPSTATE_WAIT_REQUEST) {
00856                     ret = http_parse_request(c);
00857                 } else {
00858                     ret = rtsp_parse_request(c);
00859                 }
00860                 if (ret < 0)
00861                     return -1;
00862             } else if (ptr >= c->buffer_end) {
00863                 /* request too long: cannot do anything */
00864                 return -1;
00865             } else goto read_loop;
00866         }
00867         break;
00868 
00869     case HTTPSTATE_SEND_HEADER:
00870         if (c->poll_entry->revents & (POLLERR | POLLHUP))
00871             return -1;
00872 
00873         /* no need to write if no events */
00874         if (!(c->poll_entry->revents & POLLOUT))
00875             return 0;
00876         len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
00877         if (len < 0) {
00878             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
00879                 ff_neterrno() != FF_NETERROR(EINTR)) {
00880                 /* error : close connection */
00881                 av_freep(&c->pb_buffer);
00882                 return -1;
00883             }
00884         } else {
00885             c->buffer_ptr += len;
00886             if (c->stream)
00887                 c->stream->bytes_served += len;
00888             c->data_count += len;
00889             if (c->buffer_ptr >= c->buffer_end) {
00890                 av_freep(&c->pb_buffer);
00891                 /* if error, exit */
00892                 if (c->http_error)
00893                     return -1;
00894                 /* all the buffer was sent : synchronize to the incoming stream */
00895                 c->state = HTTPSTATE_SEND_DATA_HEADER;
00896                 c->buffer_ptr = c->buffer_end = c->buffer;
00897             }
00898         }
00899         break;
00900 
00901     case HTTPSTATE_SEND_DATA:
00902     case HTTPSTATE_SEND_DATA_HEADER:
00903     case HTTPSTATE_SEND_DATA_TRAILER:
00904         /* for packetized output, we consider we can always write (the
00905            input streams sets the speed). It may be better to verify
00906            that we do not rely too much on the k