avserver.c 155 KB
Newer Older
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
1 2
/*
 * Multiple format streaming server
3
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
4
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
11
 *
12
 * Libav is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with Libav; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
20
 */
21

22
#include "config.h"
23
#if !HAVE_CLOSESOCKET
24 25 26 27
#define closesocket close
#endif
#include <string.h>
#include <stdlib.h>
28
#include "libavformat/avformat.h"
29
// FIXME those are internal headers, avserver _really_ shouldn't use them
30
#include "libavformat/ffm.h"
31 32
#include "libavformat/network.h"
#include "libavformat/os_support.h"
33
#include "libavformat/rtpdec.h"
34
#include "libavformat/rtsp.h"
35
#include "libavformat/avio_internal.h"
36 37 38
#include "libavformat/internal.h"
#include "libavformat/url.h"

39
#include "libavutil/avstring.h"
40
#include "libavutil/lfg.h"
41
#include "libavutil/dict.h"
42
#include "libavutil/mathematics.h"
43
#include "libavutil/random_seed.h"
44
#include "libavutil/parseutils.h"
45
#include "libavutil/opt.h"
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
46 47 48 49
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
50
#if HAVE_POLL_H
51
#include <poll.h>
52
#endif
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
53 54
#include <errno.h>
#include <time.h>
55
#include <sys/wait.h>
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
56
#include <signal.h>
57
#if HAVE_DLFCN_H
58
#include <dlfcn.h>
59
#endif
60

61
#include "cmdutils.h"
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
62

Anton Khirnov's avatar
Anton Khirnov committed
63
const char program_name[] = "avserver";
64
const int program_birth_year = 2000;
65

66 67
static const OptionDef options[];

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
68 69 70 71
enum HTTPState {
    HTTPSTATE_WAIT_REQUEST,
    HTTPSTATE_SEND_HEADER,
    HTTPSTATE_SEND_DATA_HEADER,
72
    HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
73
    HTTPSTATE_SEND_DATA_TRAILER,
74
    HTTPSTATE_RECEIVE_DATA,
75 76 77 78 79
    HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
    HTTPSTATE_READY,

    RTSPSTATE_WAIT_REQUEST,
    RTSPSTATE_SEND_REPLY,
80
    RTSPSTATE_SEND_PACKET,
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
81 82
};

Baptiste Coudurier's avatar
Baptiste Coudurier committed
83
static const char *http_state[] = {
84 85 86
    "HTTP_WAIT_REQUEST",
    "HTTP_SEND_HEADER",

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
87 88 89 90 91
    "SEND_DATA_HEADER",
    "SEND_DATA",
    "SEND_DATA_TRAILER",
    "RECEIVE_DATA",
    "WAIT_FEED",
92 93 94 95
    "READY",

    "RTSP_WAIT_REQUEST",
    "RTSP_SEND_REPLY",
96
    "RTSP_SEND_PACKET",
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
97 98
};

99 100
#define MAX_STREAMS 20

Philip Gladstone's avatar
Philip Gladstone committed
101
#define IOBUFFER_INIT_SIZE 8192
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
102 103

/* timeouts are in ms */
104 105 106
#define HTTP_REQUEST_TIMEOUT (15 * 1000)
#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
107 108
#define SYNC_TIMEOUT (10 * 1000)

109 110 111 112 113
typedef struct RTSPActionServerSetup {
    uint32_t ipaddr;
    char transport_option[512];
} RTSPActionServerSetup;

114
typedef struct {
115
    int64_t count1, count2;
116
    int64_t time1, time2;
117 118
} DataRateData;

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
119 120 121 122 123 124
/* context associated with one connection */
typedef struct HTTPContext {
    enum HTTPState state;
    int fd; /* socket file descriptor */
    struct sockaddr_in from_addr; /* origin */
    struct pollfd *poll_entry; /* used when polling */
125
    int64_t timeout;
126
    uint8_t *buffer_ptr, *buffer_end;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
127
    int http_error;
128
    int post;
129 130
    int chunked_encoding;
    int chunk_size;               /* 0 if it needs to be read */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
131
    struct HTTPContext *next;
132
    int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
133
    int64_t data_count;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
134 135 136 137
    /* feed input */
    int feed_fd;
    /* input format handling */
    AVFormatContext *fmt_in;
138
    int64_t start_time;            /* In milliseconds - this wraps fairly often */
139
    int64_t first_pts;            /* initial pts value */
140 141 142 143 144 145 146
    int64_t cur_pts;             /* current pts value from the stream in us */
    int64_t cur_frame_duration;  /* duration of the current frame in us */
    int cur_frame_bytes;       /* output frame size, needed to compute
                                  the time at which we send each
                                  packet */
    int pts_stream_index;        /* stream we choose as clock reference */
    int64_t cur_clock;           /* current clock reference value in us */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
147 148
    /* output format handling */
    struct FFStream *stream;
Philip Gladstone's avatar
Philip Gladstone committed
149 150 151 152
    /* -1 is invalid stream */
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
    int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
    int switch_pending;
153
    AVFormatContext fmt_ctx; /* instance of FFStream for one user */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
154
    int last_packet_sent; /* true if last data packet was sent */
155
    int suppress_log;
156
    DataRateData datarate;
157
    int wmp_client_id;
158 159 160
    char protocol[16];
    char method[16];
    char url[128];
Philip Gladstone's avatar
Philip Gladstone committed
161
    int buffer_size;
162
    uint8_t *buffer;
163 164
    int is_packetized; /* if true, the stream is packetized */
    int packet_stream_index; /* current stream for output in state machine */
165

166
    /* RTSP state specific */
167
    uint8_t *pb_buffer; /* XXX: use that in all the code */
168
    AVIOContext *pb;
169
    int seq; /* RTSP sequence number */
170

171
    /* RTP state specific */
172
    enum RTSPLowerTransport rtp_protocol;
173 174
    char session_id[32]; /* session id */
    AVFormatContext *rtp_ctx[MAX_STREAMS];
175

176 177 178 179 180 181
    /* RTP/UDP specific */
    URLContext *rtp_handles[MAX_STREAMS];

    /* RTP/TCP specific */
    struct HTTPContext *rtsp_c;
    uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
182 183 184 185 186 187
} HTTPContext;

/* each generated stream is described here */
enum StreamType {
    STREAM_TYPE_LIVE,
    STREAM_TYPE_STATUS,
Philip Gladstone's avatar
Philip Gladstone committed
188
    STREAM_TYPE_REDIRECT,
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
189 190
};

191 192 193 194 195 196 197 198
enum IPAddressAction {
    IP_ALLOW = 1,
    IP_DENY,
};

typedef struct IPAddressACL {
    struct IPAddressACL *next;
    enum IPAddressAction action;
199
    /* These are in host order */
200 201 202 203
    struct in_addr first;
    struct in_addr last;
} IPAddressACL;

Anton Khirnov's avatar
Anton Khirnov committed
204
/* description of each stream of the avserver.conf file */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
205 206 207
typedef struct FFStream {
    enum StreamType stream_type;
    char filename[1024];     /* stream filename */
208 209
    struct FFStream *feed;   /* feed we are using (can be null if
                                coming from file) */
210
    AVDictionary *in_opts;   /* input parameters */
211
    AVInputFormat *ifmt;       /* if non NULL, force input format */
212
    AVOutputFormat *fmt;
213
    IPAddressACL *acl;
214
    char dynamic_acl[1024];
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
215
    int nb_streams;
216
    int prebuffer;      /* Number of millseconds early to start */
217
    int64_t max_time;      /* Number of milliseconds to run */
218
    int send_on_key;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
219 220 221 222
    AVStream *streams[MAX_STREAMS];
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
    char feed_filename[1024]; /* file name of the feed storage, or
                                 input file name for a stream */
223 224 225 226
    char author[512];
    char title[512];
    char copyright[512];
    char comment[512];
227 228
    pid_t pid;  /* of avconv process */
    time_t pid_start;  /* of avconv process */
Philip Gladstone's avatar
Philip Gladstone committed
229
    char **child_argv;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
230
    struct FFStream *next;
231
    unsigned bandwidth; /* bandwidth, in kbits/s */
232 233
    /* RTSP options */
    char *rtsp_option;
234 235 236 237
    /* multicast specific */
    int is_multicast;
    struct in_addr multicast_ip;
    int multicast_port; /* first port used for multicast */
238 239
    int multicast_ttl;
    int loop; /* if true, send the stream in loops (only meaningful if file) */
240

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
241
    /* feed specific */
242
    int feed_opened;     /* true if someone is writing to the feed */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
243
    int is_feed;         /* true if it is a feed */
244
    int readonly;        /* True if writing is prohibited to the file */
245
    int truncate;        /* True if feeder connection truncate the feed file */
246
    int conns_served;
247
    int64_t bytes_served;
248
    int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
Diego Biurrun's avatar
Diego Biurrun committed
249
    int64_t feed_write_index;   /* current write position in feed (it wraps around) */
250
    int64_t feed_size;          /* current size of feed */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
251 252 253 254 255
    struct FFStream *next_feed;
} FFStream;

typedef struct FeedData {
    long long data_count;
Diego Biurrun's avatar
Diego Biurrun committed
256
    float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
257 258
} FeedData;

259 260
static struct sockaddr_in my_http_addr;
static struct sockaddr_in my_rtsp_addr;
261

262 263 264 265
static char logfilename[1024];
static HTTPContext *first_http_ctx;
static FFStream *first_feed;   /* contains only feeds */
static FFStream *first_stream; /* contains all streams, including feeds */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
266

267 268 269 270 271
static void new_connection(int server_fd, int is_rtsp);
static void close_connection(HTTPContext *c);

/* HTTP handling */
static int handle_connection(HTTPContext *c);
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
272
static int http_parse_request(HTTPContext *c);
273
static int http_send_data(HTTPContext *c);
274
static void compute_status(HTTPContext *c);
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
275 276 277
static int open_input_stream(HTTPContext *c, const char *info);
static int http_start_receive_data(HTTPContext *c);
static int http_receive_data(HTTPContext *c);
278 279 280 281

/* RTSP handling */
static int rtsp_parse_request(HTTPContext *c);
static void rtsp_cmd_describe(HTTPContext *c, const char *url);
282
static void rtsp_cmd_options(HTTPContext *c, const char *url);
283 284 285 286
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
287

288
/* SDP handling */
289
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
290 291
                                   struct in_addr my_ip);

292
/* RTP handling */
293
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
294
                                       FFStream *stream, const char *session_id,
295
                                       enum RTSPLowerTransport rtp_protocol);
296
static int rtp_new_av_stream(HTTPContext *c,
297 298
                             int stream_index, struct sockaddr_in *dest_addr,
                             HTTPContext *rtsp_c);
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
299

Philip Gladstone's avatar
Philip Gladstone committed
300
static const char *my_program_name;
301
static const char *my_program_dir;
Philip Gladstone's avatar
Philip Gladstone committed
302

Anton Khirnov's avatar
Anton Khirnov committed
303
static const char *config_filename = "/etc/avserver.conf";
304

Anton Khirnov's avatar
Anton Khirnov committed
305 306
static int avserver_debug;
static int avserver_daemon;
307
static int no_launch;
308
static int need_to_start_children;
309

310 311
/* maximum number of simultaneous HTTP connections */
static unsigned int nb_max_http_connections = 2000;
312 313
static unsigned int nb_max_connections = 5;
static unsigned int nb_connections;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
314

315
static uint64_t max_bandwidth = 1000;
316
static uint64_t current_bandwidth;
317

318
static int64_t cur_time;           // Making this global saves on passing it around everywhere
319

320
static AVLFG random_state;
321

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
322 323
static FILE *logfile = NULL;

324 325 326 327 328
void exit_program(int ret)
{
    exit(ret);
}

Anton Khirnov's avatar
Anton Khirnov committed
329
/* FIXME: make avserver work with IPv6 */
330 331 332 333 334 335 336
/* resolve host with also IP address parsing */
static int resolve_host(struct in_addr *sin_addr, const char *hostname)
{

    if (!ff_inet_aton(hostname, sin_addr)) {
#if HAVE_GETADDRINFO
        struct addrinfo *ai, *cur;
337
        struct addrinfo hints = { 0 };
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
        hints.ai_family = AF_INET;
        if (getaddrinfo(hostname, NULL, &hints, &ai))
            return -1;
        /* getaddrinfo returns a linked list of addrinfo structs.
         * Even if we set ai_family = AF_INET above, make sure
         * that the returned one actually is of the correct type. */
        for (cur = ai; cur; cur = cur->ai_next) {
            if (cur->ai_family == AF_INET) {
                *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
                freeaddrinfo(ai);
                return 0;
            }
        }
        freeaddrinfo(ai);
        return -1;
#else
        struct hostent *hp;
        hp = gethostbyname(hostname);
        if (!hp)
            return -1;
        memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
#endif
    }
    return 0;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
364 365 366 367 368 369 370 371 372 373 374 375 376 377
static char *ctime1(char *buf2)
{
    time_t ti;
    char *p;

    ti = time(NULL);
    p = ctime(&ti);
    strcpy(buf2, p);
    p = buf2 + strlen(p) - 1;
    if (*p == '\n')
        *p = '\0';
    return buf2;
}

Baptiste Coudurier's avatar
Baptiste Coudurier committed
378
static void http_vlog(const char *fmt, va_list vargs)
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
379
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
380
    static int print_prefix = 1;
381
    if (logfile) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
382
        if (print_prefix) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
383 384 385
            char buf[32];
            ctime1(buf);
            fprintf(logfile, "%s ", buf);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
386 387
        }
        print_prefix = strstr(fmt, "\n") != NULL;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
388
        vfprintf(logfile, fmt, vargs);
389 390
        fflush(logfile);
    }
Baptiste Coudurier's avatar
Baptiste Coudurier committed
391 392
}

393 394 395 396
#ifdef __GNUC__
__attribute__ ((format (printf, 1, 2)))
#endif
static void http_log(const char *fmt, ...)
Baptiste Coudurier's avatar
Baptiste Coudurier committed
397 398 399 400 401 402 403 404 405 406 407
{
    va_list vargs;
    va_start(vargs, fmt);
    http_vlog(fmt, vargs);
    va_end(vargs);
}

static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
{
    static int print_prefix = 1;
    AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
408
    if (level > av_log_get_level())
Baptiste Coudurier's avatar
Baptiste Coudurier committed
409 410
        return;
    if (print_prefix && avc)
411
        http_log("[%s @ %p]", avc->item_name(ptr), ptr);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
412 413
    print_prefix = strstr(fmt, "\n") != NULL;
    http_vlog(fmt, vargs);
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
414 415
}

416 417
static void log_connection(HTTPContext *c)
{
418
    if (c->suppress_log)
419 420
        return;

421 422
    http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
             inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
423
             c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
Philip Gladstone's avatar
Philip Gladstone committed
424 425
}

426
static void update_datarate(DataRateData *drd, int64_t count)
427 428 429 430
{
    if (!drd->time1 && !drd->count1) {
        drd->time1 = drd->time2 = cur_time;
        drd->count1 = drd->count2 = count;
431
    } else if (cur_time - drd->time2 > 5000) {
Alex Beregszaszi's avatar
Alex Beregszaszi committed
432 433 434 435
        drd->time1 = drd->time2;
        drd->count1 = drd->count2;
        drd->time2 = cur_time;
        drd->count2 = count;
436 437 438 439
    }
}

/* In bytes per second */
440
static int compute_datarate(DataRateData *drd, int64_t count)
441 442 443
{
    if (cur_time == drd->time1)
        return 0;
444

445 446 447
    return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
}

448

Philip Gladstone's avatar
Philip Gladstone committed
449 450
static void start_children(FFStream *feed)
{
451 452 453
    if (no_launch)
        return;

Philip Gladstone's avatar
Philip Gladstone committed
454
    for (; feed; feed = feed->next) {
455 456 457
        if (feed->child_argv && !feed->pid) {
            feed->pid_start = time(0);

Philip Gladstone's avatar
Philip Gladstone committed
458 459 460
            feed->pid = fork();

            if (feed->pid < 0) {
461
                http_log("Unable to create children\n");
Philip Gladstone's avatar
Philip Gladstone committed
462 463 464 465 466 467 468 469
                exit(1);
            }
            if (!feed->pid) {
                /* In child */
                char pathname[1024];
                char *slash;
                int i;

470 471 472 473 474 475 476
                av_strlcpy(pathname, my_program_name, sizeof(pathname));

                slash = strrchr(pathname, '/');
                if (!slash)
                    slash = pathname;
                else
                    slash++;
477
                strcpy(slash, "avconv");
478

Diego Biurrun's avatar
Diego Biurrun committed
479
                http_log("Launch command line: ");
Stefano Sabatini's avatar
Stefano Sabatini committed
480 481 482 483
                http_log("%s ", pathname);
                for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
                    http_log("%s ", feed->child_argv[i]);
                http_log("\n");
484

485
                for (i = 3; i < 256; i++)
486
                    close(i);
Philip Gladstone's avatar
Philip Gladstone committed
487

Anton Khirnov's avatar
Anton Khirnov committed
488
                if (!avserver_debug) {
489
                    i = open("/dev/null", O_RDWR);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
490
                    if (i != -1) {
491
                        dup2(i, 0);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
492 493
                        dup2(i, 1);
                        dup2(i, 2);
494
                        close(i);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
495
                    }
496
                }
Philip Gladstone's avatar
Philip Gladstone committed
497

498 499 500
                /* This is needed to make relative pathnames work */
                chdir(my_program_dir);

501 502
                signal(SIGPIPE, SIG_DFL);

Philip Gladstone's avatar
Philip Gladstone committed
503 504 505 506 507 508
                execvp(pathname, feed->child_argv);

                _exit(1);
            }
        }
    }
509 510
}

511 512
/* open a listening socket */
static int socket_open_listen(struct sockaddr_in *my_addr)
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
513
{
514
    int server_fd, tmp;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
515 516 517 518 519 520

    server_fd = socket(AF_INET,SOCK_STREAM,0);
    if (server_fd < 0) {
        perror ("socket");
        return -1;
    }
521

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
522 523 524
    tmp = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));

525
    my_addr->sin_family = AF_INET;
526
    if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
527 528 529
        char bindmsg[32];
        snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
        perror (bindmsg);
530
        closesocket(server_fd);
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
531 532
        return -1;
    }
533

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
534 535
    if (listen (server_fd, 5) < 0) {
        perror ("listen");
536
        closesocket(server_fd);
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
537 538
        return -1;
    }
539
    ff_socket_nonblock(server_fd, 1);
540 541 542 543

    return server_fd;
}

544 545 546 547 548 549 550 551 552 553 554 555 556
/* start all multicast streams */
static void start_multicast(void)
{
    FFStream *stream;
    char session_id[32];
    HTTPContext *rtp_c;
    struct sockaddr_in dest_addr;
    int default_port, stream_index;

    default_port = 6000;
    for(stream = first_stream; stream != NULL; stream = stream->next) {
        if (stream->is_multicast) {
            /* open the RTP connection */
557
            snprintf(session_id, sizeof(session_id), "%08x%08x",
558
                     av_lfg_get(&random_state), av_lfg_get(&random_state));
559 560 561 562 563 564 565 566 567 568 569

            /* choose a port if none given */
            if (stream->multicast_port == 0) {
                stream->multicast_port = default_port;
                default_port += 100;
            }

            dest_addr.sin_family = AF_INET;
            dest_addr.sin_addr = stream->multicast_ip;
            dest_addr.sin_port = htons(stream->multicast_port);

570
            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
571
                                       RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
572
            if (!rtp_c)
573
                continue;
574

575
            if (open_input_stream(rtp_c, "") < 0) {
576 577
                http_log("Could not open input stream for stream '%s'\n",
                         stream->filename);
578 579 580 581
                continue;
            }

            /* open each RTP stream */
582
            for(stream_index = 0; stream_index < stream->nb_streams;
583
                stream_index++) {
584
                dest_addr.sin_port = htons(stream->multicast_port +
585
                                           2 * stream_index);
586
                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
587 588
                    http_log("Could not open output stream '%s/streamid=%d'\n",
                             stream->filename, stream_index);
589
                    exit(1);
590 591 592 593 594 595 596 597
                }
            }

            /* change state to send data */
            rtp_c->state = HTTPSTATE_SEND_DATA;
        }
    }
}
598 599 600 601

/* main loop of the http server */
static int http_server(void)
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
602 603
    int server_fd = 0, rtsp_server_fd = 0;
    int ret, delay, delay1;
604
    struct pollfd *poll_table, *poll_entry;
605 606
    HTTPContext *c, *c_next;

607
    if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
608 609 610 611
        http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
        return -1;
    }

Baptiste Coudurier's avatar
Baptiste Coudurier committed
612
    if (my_http_addr.sin_port) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
613 614 615
        server_fd = socket_open_listen(&my_http_addr);
        if (server_fd < 0)
            return -1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
616
    }
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
617

Baptiste Coudurier's avatar
Baptiste Coudurier committed
618
    if (my_rtsp_addr.sin_port) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
619 620 621
        rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
        if (rtsp_server_fd < 0)
            return -1;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
622 623 624 625 626 627
    }

    if (!rtsp_server_fd && !server_fd) {
        http_log("HTTP and RTSP disabled.\n");
        return -1;
    }
628

Anton Khirnov's avatar
Anton Khirnov committed
629
    http_log("AVserver started.\n");
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
630

Philip Gladstone's avatar
Philip Gladstone committed
631 632
    start_children(first_feed);

633 634
    start_multicast();

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
635 636
    for(;;) {
        poll_entry = poll_table;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
637
        if (server_fd) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
638 639 640
            poll_entry->fd = server_fd;
            poll_entry->events = POLLIN;
            poll_entry++;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
641 642
        }
        if (rtsp_server_fd) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
643 644 645
            poll_entry->fd = rtsp_server_fd;
            poll_entry->events = POLLIN;
            poll_entry++;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
646
        }
647

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
648 649
        /* wait for events on each HTTP handle */
        c = first_http_ctx;
650
        delay = 1000;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
651 652 653 654
        while (c != NULL) {
            int fd;
            fd = c->fd;
            switch(c->state) {
655 656
            case HTTPSTATE_SEND_HEADER:
            case RTSPSTATE_SEND_REPLY:
657
            case RTSPSTATE_SEND_PACKET:
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
658 659
                c->poll_entry = poll_entry;
                poll_entry->fd = fd;
660
                poll_entry->events = POLLOUT;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
661 662 663 664 665
                poll_entry++;
                break;
            case HTTPSTATE_SEND_DATA_HEADER:
            case HTTPSTATE_SEND_DATA:
            case HTTPSTATE_SEND_DATA_TRAILER:
666 667 668 669 670 671 672
                if (!c->is_packetized) {
                    /* for TCP, we output as much as we can (may need to put a limit) */
                    c->poll_entry = poll_entry;
                    poll_entry->fd = fd;
                    poll_entry->events = POLLOUT;
                    poll_entry++;
                } else {
Anton Khirnov's avatar
Anton Khirnov committed
673
                    /* when avserver is doing the timing, we work by
674 675 676 677 678
                       looking at which packet need to be sent every
                       10 ms */
                    delay1 = 10; /* one tick wait XXX: 10 ms assumed */
                    if (delay1 < delay)
                        delay = delay1;
679
                }
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
680
                break;
681
            case HTTPSTATE_WAIT_REQUEST:
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
682 683
            case HTTPSTATE_RECEIVE_DATA:
            case HTTPSTATE_WAIT_FEED:
684
            case RTSPSTATE_WAIT_REQUEST:
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
685 686 687
                /* need to catch errors */
                c->poll_entry = poll_entry;
                poll_entry->fd = fd;
688
                poll_entry->events = POLLIN;/* Maybe this will work */
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
689 690 691 692 693 694 695 696 697 698 699 700
                poll_entry++;
                break;
            default:
                c->poll_entry = NULL;
                break;
            }
            c = c->next;
        }

        /* wait for an event on one connection. We poll at least every
           second to handle timeouts */
        do {
701
            ret = poll(poll_table, poll_entry - poll_table, delay);
702 703
            if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
                ff_neterrno() != AVERROR(EINTR))
704
                return -1;
705
        } while (ret < 0);
706

707
        cur_time = av_gettime() / 1000;
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
708

709 710 711 712 713
        if (need_to_start_children) {
            need_to_start_children = 0;
            start_children(first_feed);
        }

Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
714
        /* now handle the events */
715 716 717
        for(c = first_http_ctx; c != NULL; c = c_next) {
            c_next = c->next;
            if (handle_connection(c) < 0) {
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
718
                /* close and free the connection */
719
                log_connection(c);
720
                close_connection(c);
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
721 722 723 724
            }
        }

        poll_entry = poll_table;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
725
        if (server_fd) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
726 727 728 729
            /* new HTTP connection request ? */
            if (poll_entry->revents & POLLIN)
                new_connection(server_fd, 0);
            poll_entry++;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
730 731
        }
        if (rtsp_server_fd) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
732 733 734
            /* new RTSP connection request ? */
            if (poll_entry->revents & POLLIN)
                new_connection(rtsp_server_fd, 1);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
735
        }
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
736 737 738
    }
}

739 740
/* start waiting for a new HTTP/RTSP request */
static void start_wait_request(HTTPContext *c, int is_rtsp)
Fabrice Bellard's avatar
merge  
Fabrice Bellard committed
741
{
742 743 744 745 746 747 748 749 750 751 752 753
    c->buffer_ptr = c->buffer;
    c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */

    if (is_rtsp) {
        c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
        c->state = RTSPSTATE_WAIT_REQUEST;
    } else {
        c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
        c->state = HTTPSTATE_WAIT_REQUEST;
    }
}

754 755 756 757
static void http_send_too_busy_reply(int fd)
{
    char buffer[300];
    int len = snprintf(buffer, sizeof(buffer),
Howard Chu's avatar
Howard Chu committed
758
                       "HTTP/1.0 503 Server too busy\r\n"
759 760 761 762 763 764 765 766 767 768 769
                       "Content-type: text/html\r\n"
                       "\r\n"
                       "<html><head><title>Too busy</title></head><body>\r\n"
                       "<p>The server is too busy to serve your request at this time.</p>\r\n"
                       "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
                       "</body></html>\r\n",
                       nb_connections, nb_max_connections);
    send(fd, buffer, len, 0);
}


770 771 772 773 774 775 776
static void new_connection(int server_fd, int is_rtsp)
{
    struct sockaddr_in from_addr;
    int fd, len;
    HTTPContext *c = NULL;

    len = sizeof(from_addr);
777
    fd = accept(server_fd, (struct sockaddr *)&from_addr,
778
                &len);
Baptiste Coudurier's avatar
Baptiste Coudurier committed
779 780
    if (fd < 0) {
        http_log("error during accept %s\n", strerror(errno));
781
        return;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
782
    }
783
    ff_socket_nonblock(fd, 1);
784

785 786
    if (nb_connections >= nb_max_connections) {
        http_send_too_busy_reply(fd);
787
        goto fail;
788
    }
789

790 791 792 793
    /* add a new connection */
    c = av_mallocz(sizeof(HTTPContext));
    if (!c)
        goto fail;
794

795 796 797 798 799 800 801
    c->fd = fd;
    c->poll_entry = NULL;
    c->from_addr = from_addr;
    c->buffer_size = IOBUFFER_INIT_SIZE;
    c->buffer = av_malloc(c->buffer_size);
    if (!c->buffer)
        goto fail;
802 803 804

    c->next = first_http_ctx;
    first_http_ctx = c;
805
    nb_connections++;
806

807 808 809 810 811 812 813 814 815
    start_wait_request(c, is_rtsp);

    return;

 fail:
    if (c) {
        av_free(c->buffer);
        av_free(c);
    }
816
    closesocket(fd);
817 818 819 820 821 822 823 824 825 826 827 828 829 830
}

static void close_connection(HTTPContext *c)
{
    HTTPContext **cp, *c1;
    int i, nb_streams;
    AVFormatContext *ctx;
    URLContext *h;
    AVStream *st;

    /* remove connection from list */
    cp = &first_http_ctx;
    while ((*cp) != NULL) {
        c1 = *cp;
831
        if (c1 == c)
832
            *cp = c->next;
833
        else
834 835 836
            cp = &c1->next;
    }

837 838 839 840 841 842
    /* remove references, if any (XXX: do it faster) */
    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
        if (c1->rtsp_c == c)
            c1->rtsp_c = NULL;
    }

843 844
    /* remove connection associated resources */
    if (c->fd >= 0)
845
        closesocket(c->fd);
846 847 848 849
    if (c->fmt_in) {
        /* close each frame parser */
        for(i=0;i<c->fmt_in->nb_streams;i++) {
            st = c->fmt_in->streams[i];
850
            if (st->codec->codec)
851
                avcodec_close(st->codec);
852
        }
853
        avformat_close_input(&c->fmt_in);
854 855 856 857
    }

    /* free RTP output streams if any */
    nb_streams = 0;
858
    if (c->stream)
859
        nb_streams = c->stream->nb_streams;
860

861 862 863 864
    for(i=0;i<nb_streams;i++) {
        ctx = c->rtp_ctx[i];
        if (ctx) {
            av_write_trailer(ctx);
865
            av_dict_free(&ctx->metadata);