Statistics
| Branch: | Revision:

ffmpeg / ffserver.c @ d9d86e00

History | View | Annotate | Download (155 KB)

1 85f07f22 Fabrice Bellard
/*
2
 * Multiple format streaming server
3 773a21b8 Fabrice Bellard
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4 85f07f22 Fabrice Bellard
 *
5 b78e7197 Diego Biurrun
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8 773a21b8 Fabrice Bellard
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10 b78e7197 Diego Biurrun
 * version 2.1 of the License, or (at your option) any later version.
11 85f07f22 Fabrice Bellard
 *
12 b78e7197 Diego Biurrun
 * FFmpeg is distributed in the hope that it will be useful,
13 85f07f22 Fabrice Bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 773a21b8 Fabrice Bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16 85f07f22 Fabrice Bellard
 *
17 773a21b8 Fabrice Bellard
 * You should have received a copy of the GNU Lesser General Public
18 b78e7197 Diego Biurrun
 * License along with FFmpeg; if not, write to the Free Software
19 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 85f07f22 Fabrice Bellard
 */
21 364a9607 Diego Biurrun
22 29d3ed3b Aurelien Jacobs
#define _XOPEN_SOURCE 600
23
24 0f4e8165 Ronald S. Bultje
#include "config.h"
25 b250f9c6 Aurelien Jacobs
#if !HAVE_CLOSESOCKET
26 0f4e8165 Ronald S. Bultje
#define closesocket close
27
#endif
28
#include <string.h>
29 ea452b54 Aurelien Jacobs
#include <strings.h>
30 0f4e8165 Ronald S. Bultje
#include <stdlib.h>
31 245976da Diego Biurrun
#include "libavformat/avformat.h"
32
#include "libavformat/network.h"
33
#include "libavformat/os_support.h"
34 302879cb Luca Abeni
#include "libavformat/rtpdec.h"
35 245976da Diego Biurrun
#include "libavformat/rtsp.h"
36 959da985 Stefano Sabatini
#include "libavutil/avstring.h"
37 042819c5 Baptiste Coudurier
#include "libavutil/lfg.h"
38
#include "libavutil/random_seed.h"
39 737eb597 Reinhard Tartler
#include "libavutil/parseutils.h"
40 7ab08864 Baptiste Coudurier
#include "libavcodec/opt.h"
41 85f07f22 Fabrice Bellard
#include <stdarg.h>
42
#include <unistd.h>
43
#include <fcntl.h>
44
#include <sys/ioctl.h>
45 b250f9c6 Aurelien Jacobs
#if HAVE_POLL_H
46 f8cda19e Luca Abeni
#include <poll.h>
47 b0c858d8 François Revol
#endif
48 85f07f22 Fabrice Bellard
#include <errno.h>
49
#include <sys/time.h>
50
#include <time.h>
51 5eb765ef Philip Gladstone
#include <sys/wait.h>
52 85f07f22 Fabrice Bellard
#include <signal.h>
53 b250f9c6 Aurelien Jacobs
#if HAVE_DLFCN_H
54 2effd274 Fabrice Bellard
#include <dlfcn.h>
55 6638d424 Philip Gladstone
#endif
56 2effd274 Fabrice Bellard
57 4ce5df08 Stefano Sabatini
#include "cmdutils.h"
58 85f07f22 Fabrice Bellard
59 64555bd9 Michael Niedermayer
const char program_name[] = "FFserver";
60 ea9c581f Stefano Sabatini
const int program_birth_year = 2000;
61 86074ed1 Stefano Sabatini
62 5a635bc7 Stefano Sabatini
static const OptionDef options[];
63
64 85f07f22 Fabrice Bellard
enum HTTPState {
65
    HTTPSTATE_WAIT_REQUEST,
66
    HTTPSTATE_SEND_HEADER,
67
    HTTPSTATE_SEND_DATA_HEADER,
68 2effd274 Fabrice Bellard
    HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
69 85f07f22 Fabrice Bellard
    HTTPSTATE_SEND_DATA_TRAILER,
70 115329f1 Diego Biurrun
    HTTPSTATE_RECEIVE_DATA,
71 2effd274 Fabrice Bellard
    HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
72
    HTTPSTATE_READY,
73
74
    RTSPSTATE_WAIT_REQUEST,
75
    RTSPSTATE_SEND_REPLY,
76 bc351386 Fabrice Bellard
    RTSPSTATE_SEND_PACKET,
77 85f07f22 Fabrice Bellard
};
78
79 9507a12e Baptiste Coudurier
static const char *http_state[] = {
80 2effd274 Fabrice Bellard
    "HTTP_WAIT_REQUEST",
81
    "HTTP_SEND_HEADER",
82
83 85f07f22 Fabrice Bellard
    "SEND_DATA_HEADER",
84
    "SEND_DATA",
85
    "SEND_DATA_TRAILER",
86
    "RECEIVE_DATA",
87
    "WAIT_FEED",
88 2effd274 Fabrice Bellard
    "READY",
89
90
    "RTSP_WAIT_REQUEST",
91
    "RTSP_SEND_REPLY",
92 bc351386 Fabrice Bellard
    "RTSP_SEND_PACKET",
93 85f07f22 Fabrice Bellard
};
94
95 aff88101 Aurelien Jacobs
#if !FF_API_MAX_STREAMS
96
#define MAX_STREAMS 20
97
#endif
98
99 cde25790 Philip Gladstone
#define IOBUFFER_INIT_SIZE 8192
100 85f07f22 Fabrice Bellard
101
/* timeouts are in ms */
102 2effd274 Fabrice Bellard
#define HTTP_REQUEST_TIMEOUT (15 * 1000)
103
#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
104
105 85f07f22 Fabrice Bellard
#define SYNC_TIMEOUT (10 * 1000)
106
107 b516ecdd Ronald S. Bultje
typedef struct RTSPActionServerSetup {
108
    uint32_t ipaddr;
109
    char transport_option[512];
110
} RTSPActionServerSetup;
111
112 5eb765ef Philip Gladstone
typedef struct {
113 0c1a9eda Zdenek Kabelac
    int64_t count1, count2;
114 c3f58185 Alex Beregszaszi
    int64_t time1, time2;
115 5eb765ef Philip Gladstone
} DataRateData;
116
117 85f07f22 Fabrice Bellard
/* context associated with one connection */
118
typedef struct HTTPContext {
119
    enum HTTPState state;
120
    int fd; /* socket file descriptor */
121
    struct sockaddr_in from_addr; /* origin */
122
    struct pollfd *poll_entry; /* used when polling */
123 c3f58185 Alex Beregszaszi
    int64_t timeout;
124 0c1a9eda Zdenek Kabelac
    uint8_t *buffer_ptr, *buffer_end;
125 85f07f22 Fabrice Bellard
    int http_error;
126 edfdd798 Alex Beregszaszi
    int post;
127 19c8c4ec Ronald S. Bultje
    int chunked_encoding;
128
    int chunk_size;               /* 0 if it needs to be read */
129 85f07f22 Fabrice Bellard
    struct HTTPContext *next;
130 42a63c6a Philip Gladstone
    int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
131 0c1a9eda Zdenek Kabelac
    int64_t data_count;
132 85f07f22 Fabrice Bellard
    /* feed input */
133
    int feed_fd;
134
    /* input format handling */
135
    AVFormatContext *fmt_in;
136 c3f58185 Alex Beregszaszi
    int64_t start_time;            /* In milliseconds - this wraps fairly often */
137 0c1a9eda Zdenek Kabelac
    int64_t first_pts;            /* initial pts value */
138 e240a0bb Fabrice Bellard
    int64_t cur_pts;             /* current pts value from the stream in us */
139
    int64_t cur_frame_duration;  /* duration of the current frame in us */
140
    int cur_frame_bytes;       /* output frame size, needed to compute
141
                                  the time at which we send each
142
                                  packet */
143
    int pts_stream_index;        /* stream we choose as clock reference */
144
    int64_t cur_clock;           /* current clock reference value in us */
145 85f07f22 Fabrice Bellard
    /* output format handling */
146
    struct FFStream *stream;
147 cde25790 Philip Gladstone
    /* -1 is invalid stream */
148
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
149
    int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
150
    int switch_pending;
151 2effd274 Fabrice Bellard
    AVFormatContext fmt_ctx; /* instance of FFStream for one user */
152 85f07f22 Fabrice Bellard
    int last_packet_sent; /* true if last data packet was sent */
153 7434ba6d Philip Gladstone
    int suppress_log;
154 5eb765ef Philip Gladstone
    DataRateData datarate;
155 3120d2a2 Philip Gladstone
    int wmp_client_id;
156 7434ba6d Philip Gladstone
    char protocol[16];
157
    char method[16];
158
    char url[128];
159 cde25790 Philip Gladstone
    int buffer_size;
160 0c1a9eda Zdenek Kabelac
    uint8_t *buffer;
161 2effd274 Fabrice Bellard
    int is_packetized; /* if true, the stream is packetized */
162
    int packet_stream_index; /* current stream for output in state machine */
163 115329f1 Diego Biurrun
164 2effd274 Fabrice Bellard
    /* RTSP state specific */
165 0c1a9eda Zdenek Kabelac
    uint8_t *pb_buffer; /* XXX: use that in all the code */
166 ae628ec1 Anton Khirnov
    AVIOContext *pb;
167 2effd274 Fabrice Bellard
    int seq; /* RTSP sequence number */
168 115329f1 Diego Biurrun
169 2effd274 Fabrice Bellard
    /* RTP state specific */
170 90abbdba Ronald S. Bultje
    enum RTSPLowerTransport rtp_protocol;
171 2effd274 Fabrice Bellard
    char session_id[32]; /* session id */
172
    AVFormatContext *rtp_ctx[MAX_STREAMS];
173 e240a0bb Fabrice Bellard
174 bc351386 Fabrice Bellard
    /* RTP/UDP specific */
175
    URLContext *rtp_handles[MAX_STREAMS];
176
177
    /* RTP/TCP specific */
178
    struct HTTPContext *rtsp_c;
179
    uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
180 85f07f22 Fabrice Bellard
} HTTPContext;
181
182
/* each generated stream is described here */
183
enum StreamType {
184
    STREAM_TYPE_LIVE,
185
    STREAM_TYPE_STATUS,
186 cde25790 Philip Gladstone
    STREAM_TYPE_REDIRECT,
187 85f07f22 Fabrice Bellard
};
188
189 8256c0a3 Philip Gladstone
enum IPAddressAction {
190
    IP_ALLOW = 1,
191
    IP_DENY,
192
};
193
194
typedef struct IPAddressACL {
195
    struct IPAddressACL *next;
196
    enum IPAddressAction action;
197 efa04ce2 Philip Gladstone
    /* These are in host order */
198 8256c0a3 Philip Gladstone
    struct in_addr first;
199
    struct in_addr last;
200
} IPAddressACL;
201
202 85f07f22 Fabrice Bellard
/* description of each stream of the ffserver.conf file */
203
typedef struct FFStream {
204
    enum StreamType stream_type;
205
    char filename[1024];     /* stream filename */
206 2effd274 Fabrice Bellard
    struct FFStream *feed;   /* feed we are using (can be null if
207
                                coming from file) */
208 e240a0bb Fabrice Bellard
    AVFormatParameters *ap_in; /* input parameters */
209
    AVInputFormat *ifmt;       /* if non NULL, force input format */
210 bd7cf6ad Fabrice Bellard
    AVOutputFormat *fmt;
211 8256c0a3 Philip Gladstone
    IPAddressACL *acl;
212 58f48adb Benjamin Larsson
    char dynamic_acl[1024];
213 85f07f22 Fabrice Bellard
    int nb_streams;
214 42a63c6a Philip Gladstone
    int prebuffer;      /* Number of millseconds early to start */
215 c3f58185 Alex Beregszaszi
    int64_t max_time;      /* Number of milliseconds to run */
216 79c4ea3c Philip Gladstone
    int send_on_key;
217 85f07f22 Fabrice Bellard
    AVStream *streams[MAX_STREAMS];
218
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
219
    char feed_filename[1024]; /* file name of the feed storage, or
220
                                 input file name for a stream */
221 2ac887ba Philip Gladstone
    char author[512];
222
    char title[512];
223
    char copyright[512];
224
    char comment[512];
225 cde25790 Philip Gladstone
    pid_t pid;  /* Of ffmpeg process */
226 5eb765ef Philip Gladstone
    time_t pid_start;  /* Of ffmpeg process */
227 cde25790 Philip Gladstone
    char **child_argv;
228 85f07f22 Fabrice Bellard
    struct FFStream *next;
229 177d2564 Baptiste Coudurier
    unsigned bandwidth; /* bandwidth, in kbits/s */
230 2effd274 Fabrice Bellard
    /* RTSP options */
231
    char *rtsp_option;
232 829ac53d Fabrice Bellard
    /* multicast specific */
233
    int is_multicast;
234
    struct in_addr multicast_ip;
235
    int multicast_port; /* first port used for multicast */
236 6edd6884 Fabrice Bellard
    int multicast_ttl;
237
    int loop; /* if true, send the stream in loops (only meaningful if file) */
238 829ac53d Fabrice Bellard
239 85f07f22 Fabrice Bellard
    /* feed specific */
240 2effd274 Fabrice Bellard
    int feed_opened;     /* true if someone is writing to the feed */
241 85f07f22 Fabrice Bellard
    int is_feed;         /* true if it is a feed */
242 e322ea48 Philip Gladstone
    int readonly;        /* True if writing is prohibited to the file */
243 861ec13a Baptiste Coudurier
    int truncate;        /* True if feeder connection truncate the feed file */
244 a6e14edd Philip Gladstone
    int conns_served;
245 0c1a9eda Zdenek Kabelac
    int64_t bytes_served;
246 6b0bdc75 Alex Beregszaszi
    int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
247 8bfb108b Diego Biurrun
    int64_t feed_write_index;   /* current write position in feed (it wraps around) */
248 0c1a9eda Zdenek Kabelac
    int64_t feed_size;          /* current size of feed */
249 85f07f22 Fabrice Bellard
    struct FFStream *next_feed;
250
} FFStream;
251
252
typedef struct FeedData {
253
    long long data_count;
254 8bfb108b Diego Biurrun
    float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
255 85f07f22 Fabrice Bellard
} FeedData;
256
257 18405874 Alex Beregszaszi
static struct sockaddr_in my_http_addr;
258
static struct sockaddr_in my_rtsp_addr;
259 2effd274 Fabrice Bellard
260 33f5e2ec Alex Beregszaszi
static char logfilename[1024];
261
static HTTPContext *first_http_ctx;
262
static FFStream *first_feed;   /* contains only feeds */
263
static FFStream *first_stream; /* contains all streams, including feeds */
264 85f07f22 Fabrice Bellard
265 2effd274 Fabrice Bellard
static void new_connection(int server_fd, int is_rtsp);
266
static void close_connection(HTTPContext *c);
267
268
/* HTTP handling */
269
static int handle_connection(HTTPContext *c);
270 85f07f22 Fabrice Bellard
static int http_parse_request(HTTPContext *c);
271 5eb765ef Philip Gladstone
static int http_send_data(HTTPContext *c);
272 dca21085 Stefano Sabatini
static void compute_status(HTTPContext *c);
273 85f07f22 Fabrice Bellard
static int open_input_stream(HTTPContext *c, const char *info);
274
static int http_start_receive_data(HTTPContext *c);
275
static int http_receive_data(HTTPContext *c);
276 2effd274 Fabrice Bellard
277
/* RTSP handling */
278
static int rtsp_parse_request(HTTPContext *c);
279
static void rtsp_cmd_describe(HTTPContext *c, const char *url);
280 0df65975 Andriy Rysin
static void rtsp_cmd_options(HTTPContext *c, const char *url);
281 a9e534d5 Ronald S. Bultje
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
282
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
283
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
284
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
285 2effd274 Fabrice Bellard
286 829ac53d Fabrice Bellard
/* SDP handling */
287 115329f1 Diego Biurrun
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
288 829ac53d Fabrice Bellard
                                   struct in_addr my_ip);
289
290 2effd274 Fabrice Bellard
/* RTP handling */
291 115329f1 Diego Biurrun
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
292 bc351386 Fabrice Bellard
                                       FFStream *stream, const char *session_id,
293 90abbdba Ronald S. Bultje
                                       enum RTSPLowerTransport rtp_protocol);
294 115329f1 Diego Biurrun
static int rtp_new_av_stream(HTTPContext *c,
295 bc351386 Fabrice Bellard
                             int stream_index, struct sockaddr_in *dest_addr,
296
                             HTTPContext *rtsp_c);
297 85f07f22 Fabrice Bellard
298 cde25790 Philip Gladstone
static const char *my_program_name;
299 d6562d2c Philip Gladstone
static const char *my_program_dir;
300 cde25790 Philip Gladstone
301 6675a5bf Stefano Sabatini
static const char *config_filename = "/etc/ffserver.conf";
302
303 2ac887ba Philip Gladstone
static int ffserver_debug;
304 2effd274 Fabrice Bellard
static int ffserver_daemon;
305 2ac887ba Philip Gladstone
static int no_launch;
306 5eb765ef Philip Gladstone
static int need_to_start_children;
307 2ac887ba Philip Gladstone
308 1c9ff179 Stefano Sabatini
/* maximum number of simultaneous HTTP connections */
309
static unsigned int nb_max_http_connections = 2000;
310 4af92de6 Stefano Sabatini
static unsigned int nb_max_connections = 5;
311
static unsigned int nb_connections;
312 85f07f22 Fabrice Bellard
313 f69bb0cc Baptiste Coudurier
static uint64_t max_bandwidth = 1000;
314 1ad8289e Baptiste Coudurier
static uint64_t current_bandwidth;
315 42a63c6a Philip Gladstone
316 c3f58185 Alex Beregszaszi
static int64_t cur_time;           // Making this global saves on passing it around everywhere
317 5eb765ef Philip Gladstone
318 042819c5 Baptiste Coudurier
static AVLFG random_state;
319 1df93ae9 Alex Beregszaszi
320 85f07f22 Fabrice Bellard
static FILE *logfile = NULL;
321
322 22f73dcc Måns Rullgård
/* FIXME: make ffserver work with IPv6 */
323
/* resolve host with also IP address parsing */
324
static int resolve_host(struct in_addr *sin_addr, const char *hostname)
325
{
326
327
    if (!ff_inet_aton(hostname, sin_addr)) {
328
#if HAVE_GETADDRINFO
329
        struct addrinfo *ai, *cur;
330
        struct addrinfo hints;
331
        memset(&hints, 0, sizeof(hints));
332
        hints.ai_family = AF_INET;
333
        if (getaddrinfo(hostname, NULL, &hints, &ai))
334
            return -1;
335
        /* getaddrinfo returns a linked list of addrinfo structs.
336
         * Even if we set ai_family = AF_INET above, make sure
337
         * that the returned one actually is of the correct type. */
338
        for (cur = ai; cur; cur = cur->ai_next) {
339
            if (cur->ai_family == AF_INET) {
340
                *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
341
                freeaddrinfo(ai);
342
                return 0;
343
            }
344
        }
345
        freeaddrinfo(ai);
346
        return -1;
347
#else
348
        struct hostent *hp;
349
        hp = gethostbyname(hostname);
350
        if (!hp)
351
            return -1;
352
        memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
353
#endif
354
    }
355
    return 0;
356
}
357
358 9fd3442f Baptiste Coudurier
static char *ctime1(char *buf2)
359
{
360
    time_t ti;
361
    char *p;
362
363
    ti = time(NULL);
364
    p = ctime(&ti);
365
    strcpy(buf2, p);
366
    p = buf2 + strlen(p) - 1;
367
    if (*p == '\n')
368
        *p = '\0';
369
    return buf2;
370
}
371
372 bcd3ce59 Baptiste Coudurier
static void http_vlog(const char *fmt, va_list vargs)
373 85f07f22 Fabrice Bellard
{
374 124ed1c0 Baptiste Coudurier
    static int print_prefix = 1;
375 7434ba6d Philip Gladstone
    if (logfile) {
376 124ed1c0 Baptiste Coudurier
        if (print_prefix) {
377 9fd3442f Baptiste Coudurier
            char buf[32];
378
            ctime1(buf);
379
            fprintf(logfile, "%s ", buf);
380 124ed1c0 Baptiste Coudurier
        }
381
        print_prefix = strstr(fmt, "\n") != NULL;
382 bcd3ce59 Baptiste Coudurier
        vfprintf(logfile, fmt, vargs);
383 7434ba6d Philip Gladstone
        fflush(logfile);
384
    }
385 bcd3ce59 Baptiste Coudurier
}
386
387 efa6ce99 Mans Rullgard
#ifdef __GNUC__
388
__attribute__ ((format (printf, 1, 2)))
389
#endif
390
static void http_log(const char *fmt, ...)
391 bcd3ce59 Baptiste Coudurier
{
392
    va_list vargs;
393
    va_start(vargs, fmt);
394
    http_vlog(fmt, vargs);
395
    va_end(vargs);
396
}
397
398
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
399
{
400
    static int print_prefix = 1;
401
    AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
402 49ceb58b Michael Niedermayer
    if (level > av_log_get_level())
403 bcd3ce59 Baptiste Coudurier
        return;
404
    if (print_prefix && avc)
405 59e7894c Baptiste Coudurier
        http_log("[%s @ %p]", avc->item_name(ptr), ptr);
406 bcd3ce59 Baptiste Coudurier
    print_prefix = strstr(fmt, "\n") != NULL;
407
    http_vlog(fmt, vargs);
408 85f07f22 Fabrice Bellard
}
409
410 6edd6884 Fabrice Bellard
static void log_connection(HTTPContext *c)
411
{
412 115329f1 Diego Biurrun
    if (c->suppress_log)
413 6edd6884 Fabrice Bellard
        return;
414
415 82e0be62 Baptiste Coudurier
    http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
416
             inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
417 6edd6884 Fabrice Bellard
             c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
418 cde25790 Philip Gladstone
}
419
420 0c1a9eda Zdenek Kabelac
static void update_datarate(DataRateData *drd, int64_t count)
421 5eb765ef Philip Gladstone
{
422
    if (!drd->time1 && !drd->count1) {
423
        drd->time1 = drd->time2 = cur_time;
424
        drd->count1 = drd->count2 = count;
425 eeffbdea Alex Beregszaszi
    } else if (cur_time - drd->time2 > 5000) {
426 33a4ecbe Alex Beregszaszi
        drd->time1 = drd->time2;
427
        drd->count1 = drd->count2;
428
        drd->time2 = cur_time;
429
        drd->count2 = count;
430 5eb765ef Philip Gladstone
    }
431
}
432
433
/* In bytes per second */
434 0c1a9eda Zdenek Kabelac
static int compute_datarate(DataRateData *drd, int64_t count)
435 5eb765ef Philip Gladstone
{
436
    if (cur_time == drd->time1)
437
        return 0;
438 115329f1 Diego Biurrun
439 5eb765ef Philip Gladstone
    return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
440
}
441
442 a782f209 Philip Gladstone
443 cde25790 Philip Gladstone
static void start_children(FFStream *feed)
444
{
445 2ac887ba Philip Gladstone
    if (no_launch)
446
        return;
447
448 cde25790 Philip Gladstone
    for (; feed; feed = feed->next) {
449 5eb765ef Philip Gladstone
        if (feed->child_argv && !feed->pid) {
450
            feed->pid_start = time(0);
451
452 cde25790 Philip Gladstone
            feed->pid = fork();
453
454
            if (feed->pid < 0) {
455 b4befb99 Baptiste Coudurier
                http_log("Unable to create children\n");
456 cde25790 Philip Gladstone
                exit(1);
457
            }
458
            if (!feed->pid) {
459
                /* In child */
460
                char pathname[1024];
461
                char *slash;
462
                int i;
463
464 40444a59 Stefano Sabatini
                av_strlcpy(pathname, my_program_name, sizeof(pathname));
465
466
                slash = strrchr(pathname, '/');
467
                if (!slash)
468
                    slash = pathname;
469
                else
470
                    slash++;
471
                strcpy(slash, "ffmpeg");
472
473 8bf61f5b Stefano Sabatini
                http_log("Launch commandline: ");
474
                http_log("%s ", pathname);
475
                for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
476
                    http_log("%s ", feed->child_argv[i]);
477
                http_log("\n");
478 40444a59 Stefano Sabatini
479 611c5741 Alex Beregszaszi
                for (i = 3; i < 256; i++)
480 5eb765ef Philip Gladstone
                    close(i);
481 cde25790 Philip Gladstone
482 5eb765ef Philip Gladstone
                if (!ffserver_debug) {
483 2ac887ba Philip Gladstone
                    i = open("/dev/null", O_RDWR);
484 3296409d Baptiste Coudurier
                    if (i != -1) {
485 2ac887ba Philip Gladstone
                        dup2(i, 0);
486 3296409d Baptiste Coudurier
                        dup2(i, 1);
487
                        dup2(i, 2);
488 5eb765ef Philip Gladstone
                        close(i);
489 3296409d Baptiste Coudurier
                    }
490 2ac887ba Philip Gladstone
                }
491 cde25790 Philip Gladstone
492 d6562d2c Philip Gladstone
                /* This is needed to make relative pathnames work */
493
                chdir(my_program_dir);
494
495 a4d70941 Philip Gladstone
                signal(SIGPIPE, SIG_DFL);
496
497 cde25790 Philip Gladstone
                execvp(pathname, feed->child_argv);
498
499
                _exit(1);
500
            }
501
        }
502
    }
503 7434ba6d Philip Gladstone
}
504
505 2effd274 Fabrice Bellard
/* open a listening socket */
506
static int socket_open_listen(struct sockaddr_in *my_addr)
507 85f07f22 Fabrice Bellard
{
508 2effd274 Fabrice Bellard
    int server_fd, tmp;
509 85f07f22 Fabrice Bellard
510
    server_fd = socket(AF_INET,SOCK_STREAM,0);
511
    if (server_fd < 0) {
512
        perror ("socket");
513
        return -1;
514
    }
515 115329f1 Diego Biurrun
516 85f07f22 Fabrice Bellard
    tmp = 1;
517
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
518
519 2effd274 Fabrice Bellard
    if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
520 b17d099d Philip Gladstone
        char bindmsg[32];
521
        snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
522
        perror (bindmsg);
523 d96633bb Alex Beregszaszi
        closesocket(server_fd);
524 85f07f22 Fabrice Bellard
        return -1;
525
    }
526 115329f1 Diego Biurrun
527 85f07f22 Fabrice Bellard
    if (listen (server_fd, 5) < 0) {
528
        perror ("listen");
529 d96633bb Alex Beregszaszi
        closesocket(server_fd);
530 85f07f22 Fabrice Bellard
        return -1;
531
    }
532 ba472aaf Alex Beregszaszi
    ff_socket_nonblock(server_fd, 1);
533 2effd274 Fabrice Bellard
534
    return server_fd;
535
}
536
537 6edd6884 Fabrice Bellard
/* start all multicast streams */
538
static void start_multicast(void)
539
{
540
    FFStream *stream;
541
    char session_id[32];
542
    HTTPContext *rtp_c;
543
    struct sockaddr_in dest_addr;
544
    int default_port, stream_index;
545
546
    default_port = 6000;
547
    for(stream = first_stream; stream != NULL; stream = stream->next) {
548
        if (stream->is_multicast) {
549
            /* open the RTP connection */
550 1df93ae9 Alex Beregszaszi
            snprintf(session_id, sizeof(session_id), "%08x%08x",
551 042819c5 Baptiste Coudurier
                     av_lfg_get(&random_state), av_lfg_get(&random_state));
552 6edd6884 Fabrice Bellard
553
            /* choose a port if none given */
554
            if (stream->multicast_port == 0) {
555
                stream->multicast_port = default_port;
556
                default_port += 100;
557
            }
558
559
            dest_addr.sin_family = AF_INET;
560
            dest_addr.sin_addr = stream->multicast_ip;
561
            dest_addr.sin_port = htons(stream->multicast_port);
562
563 115329f1 Diego Biurrun
            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
564 90abbdba Ronald S. Bultje
                                       RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
565 611c5741 Alex Beregszaszi
            if (!rtp_c)
566 6edd6884 Fabrice Bellard
                continue;
567 611c5741 Alex Beregszaszi
568 6edd6884 Fabrice Bellard
            if (open_input_stream(rtp_c, "") < 0) {
569 b4befb99 Baptiste Coudurier
                http_log("Could not open input stream for stream '%s'\n",
570
                         stream->filename);
571 6edd6884 Fabrice Bellard
                continue;
572
            }
573
574
            /* open each RTP stream */
575 115329f1 Diego Biurrun
            for(stream_index = 0; stream_index < stream->nb_streams;
576 6edd6884 Fabrice Bellard
                stream_index++) {
577 115329f1 Diego Biurrun
                dest_addr.sin_port = htons(stream->multicast_port +
578 6edd6884 Fabrice Bellard
                                           2 * stream_index);
579 bc351386 Fabrice Bellard
                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
580 b4befb99 Baptiste Coudurier
                    http_log("Could not open output stream '%s/streamid=%d'\n",
581
                             stream->filename, stream_index);
582 0fa45e19 Fabrice Bellard
                    exit(1);
583 6edd6884 Fabrice Bellard
                }
584
            }
585
586
            /* change state to send data */
587
            rtp_c->state = HTTPSTATE_SEND_DATA;
588
        }
589
    }
590
}
591 2effd274 Fabrice Bellard
592
/* main loop of the http server */
593
static int http_server(void)
594
{
595 d2a1ea1d Baptiste Coudurier
    int server_fd = 0, rtsp_server_fd = 0;
596
    int ret, delay, delay1;
597 1c9ff179 Stefano Sabatini
    struct pollfd *poll_table, *poll_entry;
598 2effd274 Fabrice Bellard
    HTTPContext *c, *c_next;
599
600 a7f361eb Baptiste Coudurier
    if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
601 1c9ff179 Stefano Sabatini
        http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
602
        return -1;
603
    }
604
605 d2a1ea1d Baptiste Coudurier
    if (my_http_addr.sin_port) {
606 2b9cd1e7 Baptiste Coudurier
        server_fd = socket_open_listen(&my_http_addr);
607
        if (server_fd < 0)
608
            return -1;
609 d2a1ea1d Baptiste Coudurier
    }
610 85f07f22 Fabrice Bellard
611 d2a1ea1d Baptiste Coudurier
    if (my_rtsp_addr.sin_port) {
612 2b9cd1e7 Baptiste Coudurier
        rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
613
        if (rtsp_server_fd < 0)
614
            return -1;
615 d2a1ea1d Baptiste Coudurier
    }
616
617
    if (!rtsp_server_fd && !server_fd) {
618
        http_log("HTTP and RTSP disabled.\n");
619
        return -1;
620
    }
621 115329f1 Diego Biurrun
622 a3341b9d Baptiste Coudurier
    http_log("FFserver started.\n");
623 85f07f22 Fabrice Bellard
624 cde25790 Philip Gladstone
    start_children(first_feed);
625
626 6edd6884 Fabrice Bellard
    start_multicast();
627
628 85f07f22 Fabrice Bellard
    for(;;) {
629
        poll_entry = poll_table;
630 d2a1ea1d Baptiste Coudurier
        if (server_fd) {
631 2b9cd1e7 Baptiste Coudurier
            poll_entry->fd = server_fd;
632
            poll_entry->events = POLLIN;
633
            poll_entry++;
634 d2a1ea1d Baptiste Coudurier
        }
635
        if (rtsp_server_fd) {
636 2b9cd1e7 Baptiste Coudurier
            poll_entry->fd = rtsp_server_fd;
637
            poll_entry->events = POLLIN;
638
            poll_entry++;
639 d2a1ea1d Baptiste Coudurier
        }
640 2effd274 Fabrice Bellard
641 85f07f22 Fabrice Bellard
        /* wait for events on each HTTP handle */
642
        c = first_http_ctx;
643 2effd274 Fabrice Bellard
        delay = 1000;
644 85f07f22 Fabrice Bellard
        while (c != NULL) {
645
            int fd;
646
            fd = c->fd;
647
            switch(c->state) {
648 2effd274 Fabrice Bellard
            case HTTPSTATE_SEND_HEADER:
649
            case RTSPSTATE_SEND_REPLY:
650 bc351386 Fabrice Bellard
            case RTSPSTATE_SEND_PACKET:
651 85f07f22 Fabrice Bellard
                c->poll_entry = poll_entry;
652
                poll_entry->fd = fd;
653 2effd274 Fabrice Bellard
                poll_entry->events = POLLOUT;
654 85f07f22 Fabrice Bellard
                poll_entry++;
655
                break;
656
            case HTTPSTATE_SEND_DATA_HEADER:
657
            case HTTPSTATE_SEND_DATA:
658
            case HTTPSTATE_SEND_DATA_TRAILER:
659 2effd274 Fabrice Bellard
                if (!c->is_packetized) {
660
                    /* for TCP, we output as much as we can (may need to put a limit) */
661
                    c->poll_entry = poll_entry;
662
                    poll_entry->fd = fd;
663
                    poll_entry->events = POLLOUT;
664
                    poll_entry++;
665
                } else {
666 e240a0bb Fabrice Bellard
                    /* when ffserver is doing the timing, we work by
667
                       looking at which packet need to be sent every
668
                       10 ms */
669
                    delay1 = 10; /* one tick wait XXX: 10 ms assumed */
670
                    if (delay1 < delay)
671
                        delay = delay1;
672 2effd274 Fabrice Bellard
                }
673 85f07f22 Fabrice Bellard
                break;
674 2effd274 Fabrice Bellard
            case HTTPSTATE_WAIT_REQUEST:
675 85f07f22 Fabrice Bellard
            case HTTPSTATE_RECEIVE_DATA:
676
            case HTTPSTATE_WAIT_FEED:
677 2effd274 Fabrice Bellard
            case RTSPSTATE_WAIT_REQUEST:
678 85f07f22 Fabrice Bellard
                /* need to catch errors */
679
                c->poll_entry = poll_entry;
680
                poll_entry->fd = fd;
681 a6e14edd Philip Gladstone
                poll_entry->events = POLLIN;/* Maybe this will work */
682 85f07f22 Fabrice Bellard
                poll_entry++;
683
                break;
684
            default:
685
                c->poll_entry = NULL;
686
                break;
687
            }
688
            c = c->next;
689
        }
690
691
        /* wait for an event on one connection. We poll at least every
692
           second to handle timeouts */
693
        do {
694 2effd274 Fabrice Bellard
            ret = poll(poll_table, poll_entry - poll_table, delay);
695 28c4741a Martin Storsjö
            if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
696
                ff_neterrno() != AVERROR(EINTR))
697 53e2f9ca Michael Niedermayer
                return -1;
698 e8d658df Luca Abeni
        } while (ret < 0);
699 115329f1 Diego Biurrun
700 c3f58185 Alex Beregszaszi
        cur_time = av_gettime() / 1000;
701 85f07f22 Fabrice Bellard
702 5eb765ef Philip Gladstone
        if (need_to_start_children) {
703
            need_to_start_children = 0;
704
            start_children(first_feed);
705
        }
706
707 85f07f22 Fabrice Bellard
        /* now handle the events */
708 2effd274 Fabrice Bellard
        for(c = first_http_ctx; c != NULL; c = c_next) {
709
            c_next = c->next;
710
            if (handle_connection(c) < 0) {
711 85f07f22 Fabrice Bellard
                /* close and free the connection */
712 7434ba6d Philip Gladstone
                log_connection(c);
713 2effd274 Fabrice Bellard
                close_connection(c);
714 85f07f22 Fabrice Bellard
            }
715
        }
716
717
        poll_entry = poll_table;
718 d2a1ea1d Baptiste Coudurier
        if (server_fd) {
719 2b9cd1e7 Baptiste Coudurier
            /* new HTTP connection request ? */
720
            if (poll_entry->revents & POLLIN)
721
                new_connection(server_fd, 0);
722
            poll_entry++;
723 d2a1ea1d Baptiste Coudurier
        }
724
        if (rtsp_server_fd) {
725 2b9cd1e7 Baptiste Coudurier
            /* new RTSP connection request ? */
726
            if (poll_entry->revents & POLLIN)
727
                new_connection(rtsp_server_fd, 1);
728 d2a1ea1d Baptiste Coudurier
        }
729 85f07f22 Fabrice Bellard
    }
730
}
731
732 2effd274 Fabrice Bellard
/* start waiting for a new HTTP/RTSP request */
733
static void start_wait_request(HTTPContext *c, int is_rtsp)
734 85f07f22 Fabrice Bellard
{
735 2effd274 Fabrice Bellard
    c->buffer_ptr = c->buffer;
736
    c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
737
738
    if (is_rtsp) {
739
        c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
740
        c->state = RTSPSTATE_WAIT_REQUEST;
741
    } else {
742
        c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
743
        c->state = HTTPSTATE_WAIT_REQUEST;
744
    }
745
}
746
747 0bdd8b85 Baptiste Coudurier
static void http_send_too_busy_reply(int fd)
748
{
749
    char buffer[300];
750
    int len = snprintf(buffer, sizeof(buffer),
751 2a22187f Howard Chu
                       "HTTP/1.0 503 Server too busy\r\n"
752 0bdd8b85 Baptiste Coudurier
                       "Content-type: text/html\r\n"
753
                       "\r\n"
754
                       "<html><head><title>Too busy</title></head><body>\r\n"
755
                       "<p>The server is too busy to serve your request at this time.</p>\r\n"
756
                       "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
757
                       "</body></html>\r\n",
758
                       nb_connections, nb_max_connections);
759
    send(fd, buffer, len, 0);
760
}
761
762
763 2effd274 Fabrice Bellard
static void new_connection(int server_fd, int is_rtsp)
764
{
765
    struct sockaddr_in from_addr;
766
    int fd, len;
767
    HTTPContext *c = NULL;
768
769
    len = sizeof(from_addr);
770 115329f1 Diego Biurrun
    fd = accept(server_fd, (struct sockaddr *)&from_addr,
771 2effd274 Fabrice Bellard
                &len);
772 050056d0 Baptiste Coudurier
    if (fd < 0) {
773
        http_log("error during accept %s\n", strerror(errno));
774 2effd274 Fabrice Bellard
        return;
775 050056d0 Baptiste Coudurier
    }
776 ba472aaf Alex Beregszaszi
    ff_socket_nonblock(fd, 1);
777 2effd274 Fabrice Bellard
778 0bdd8b85 Baptiste Coudurier
    if (nb_connections >= nb_max_connections) {
779
        http_send_too_busy_reply(fd);
780 2effd274 Fabrice Bellard
        goto fail;
781 0bdd8b85 Baptiste Coudurier
    }
782 115329f1 Diego Biurrun
783 2effd274 Fabrice Bellard
    /* add a new connection */
784
    c = av_mallocz(sizeof(HTTPContext));
785
    if (!c)
786
        goto fail;
787 115329f1 Diego Biurrun
788 2effd274 Fabrice Bellard
    c->fd = fd;
789
    c->poll_entry = NULL;
790
    c->from_addr = from_addr;
791
    c->buffer_size = IOBUFFER_INIT_SIZE;
792
    c->buffer = av_malloc(c->buffer_size);
793
    if (!c->buffer)
794
        goto fail;
795 8bc80f8b Philip Gladstone
796
    c->next = first_http_ctx;
797
    first_http_ctx = c;
798 2effd274 Fabrice Bellard
    nb_connections++;
799 115329f1 Diego Biurrun
800 2effd274 Fabrice Bellard
    start_wait_request(c, is_rtsp);
801
802
    return;
803
804
 fail:
805
    if (c) {
806
        av_free(c->buffer);
807
        av_free(c);
808
    }
809 d96633bb Alex Beregszaszi
    closesocket(fd);
810 2effd274 Fabrice Bellard
}
811
812
static void close_connection(HTTPContext *c)
813
{
814
    HTTPContext **cp, *c1;
815
    int i, nb_streams;
816
    AVFormatContext *ctx;
817
    URLContext *h;
818
    AVStream *st;
819
820
    /* remove connection from list */
821
    cp = &first_http_ctx;
822
    while ((*cp) != NULL) {
823
        c1 = *cp;
824 611c5741 Alex Beregszaszi
        if (c1 == c)
825 2effd274 Fabrice Bellard
            *cp = c->next;
826 611c5741 Alex Beregszaszi
        else
827 2effd274 Fabrice Bellard
            cp = &c1->next;
828
    }
829
830 bc351386 Fabrice Bellard
    /* remove references, if any (XXX: do it faster) */
831
    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
832
        if (c1->rtsp_c == c)
833
            c1->rtsp_c = NULL;
834
    }
835
836 2effd274 Fabrice Bellard
    /* remove connection associated resources */
837
    if (c->fd >= 0)
838 d96633bb Alex Beregszaszi
        closesocket(c->fd);
839 2effd274 Fabrice Bellard
    if (c->fmt_in) {
840
        /* close each frame parser */
841
        for(i=0;i<c->fmt_in->nb_streams;i++) {
842
            st = c->fmt_in->streams[i];
843 611c5741 Alex Beregszaszi
            if (st->codec->codec)
844 01f4895c Michael Niedermayer
                avcodec_close(st->codec);
845 2effd274 Fabrice Bellard
        }
846
        av_close_input_file(c->fmt_in);
847
    }
848
849
    /* free RTP output streams if any */
850
    nb_streams = 0;
851 115329f1 Diego Biurrun
    if (c->stream)
852 2effd274 Fabrice Bellard
        nb_streams = c->stream->nb_streams;
853 115329f1 Diego Biurrun
854 2effd274 Fabrice Bellard
    for(i=0;i<nb_streams;i++) {
855
        ctx = c->rtp_ctx[i];
856
        if (ctx) {
857
            av_write_trailer(ctx);
858 ea4f8aab Howard Chu
            av_metadata_free(&ctx->metadata);
859
            av_free(ctx->streams[0]);
860 2effd274 Fabrice Bellard
            av_free(ctx);
861
        }
862
        h = c->rtp_handles[i];
863 611c5741 Alex Beregszaszi
        if (h)
864 2effd274 Fabrice Bellard
            url_close(h);
865
    }
866 115329f1 Diego Biurrun
867 b88ba823 Mark Hills
    ctx = &c->fmt_ctx;
868
869 637b638e Baptiste Coudurier
    if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
870 87638494 Philip Gladstone
        if (ctx->oformat) {
871
            /* prepare header */
872
            if (url_open_dyn_buf(&ctx->pb) >= 0) {
873
                av_write_trailer(ctx);
874 f8b06be9 Baptiste Coudurier
                av_freep(&c->pb_buffer);
875 899681cd Björn Axelsson
                url_close_dyn_buf(ctx->pb, &c->pb_buffer);
876 87638494 Philip Gladstone
            }
877
        }
878
    }
879
880 115329f1 Diego Biurrun
    for(i=0; i<ctx->nb_streams; i++)
881 0bd53967 Alex Beregszaszi
        av_free(ctx->streams[i]);
882 f0ef6240 Philip Gladstone
883 edfdd798 Alex Beregszaszi
    if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
884 6edd6884 Fabrice Bellard
        current_bandwidth -= c->stream->bandwidth;
885 5400e092 Alex Beregszaszi
886
    /* signal that there is no feed if we are the feeder socket */
887
    if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
888
        c->stream->feed_opened = 0;
889
        close(c->feed_fd);
890
    }
891
892 2effd274 Fabrice Bellard
    av_freep(&c->pb_buffer);
893 bc351386 Fabrice Bellard
    av_freep(&c->packet_buffer);
894 2effd274 Fabrice Bellard
    av_free(c->buffer);
895
    av_free(c);
896
    nb_connections--;
897
}
898
899
static int handle_connection(HTTPContext *c)
900
{
901
    int len, ret;
902 115329f1 Diego Biurrun
903 85f07f22 Fabrice Bellard
    switch(c->state) {
904
    case HTTPSTATE_WAIT_REQUEST:
905 2effd274 Fabrice Bellard
    case RTSPSTATE_WAIT_REQUEST:
906 85f07f22 Fabrice Bellard
        /* timeout ? */
907
        if ((c->timeout - cur_time) < 0)
908
            return -1;
909
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
910
            return -1;
911
912
        /* no need to read if no events */
913
        if (!(c->poll_entry->revents & POLLIN))
914
            return 0;
915
        /* read the data */
916 1bc1cfdd Giancarlo Formicuccia
    read_loop:
917 c60202df Alex Beregszaszi
        len = recv(c->fd, c->buffer_ptr, 1, 0);
918 85f07f22 Fabrice Bellard
        if (len < 0) {
919 28c4741a Martin Storsjö
            if (ff_neterrno() != AVERROR(EAGAIN) &&
920
                ff_neterrno() != AVERROR(EINTR))
921 85f07f22 Fabrice Bellard
                return -1;
922
        } else if (len == 0) {
923
            return -1;
924
        } else {
925 94d9ad5f Giancarlo Formicuccia
            /* search for end of request. */
926 0c1a9eda Zdenek Kabelac
            uint8_t *ptr;
927 85f07f22 Fabrice Bellard
            c->buffer_ptr += len;
928
            ptr = c->buffer_ptr;
929
            if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
930
                (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
931
                /* request found : parse it and reply */
932 2effd274 Fabrice Bellard
                if (c->state == HTTPSTATE_WAIT_REQUEST) {
933
                    ret = http_parse_request(c);
934
                } else {
935
                    ret = rtsp_parse_request(c);
936
                }
937
                if (ret < 0)
938 85f07f22 Fabrice Bellard
                    return -1;
939
            } else if (ptr >= c->buffer_end) {
940
                /* request too long: cannot do anything */
941
                return -1;
942 1bc1cfdd Giancarlo Formicuccia
            } else goto read_loop;
943 85f07f22 Fabrice Bellard
        }
944
        break;
945
946
    case HTTPSTATE_SEND_HEADER:
947
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
948
            return -1;
949
950 2effd274 Fabrice Bellard
        /* no need to write if no events */
951 85f07f22 Fabrice Bellard
        if (!(c->poll_entry->revents & POLLOUT))
952
            return 0;
953 c60202df Alex Beregszaszi
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
954 85f07f22 Fabrice Bellard
        if (len < 0) {
955 28c4741a Martin Storsjö
            if (ff_neterrno() != AVERROR(EAGAIN) &&
956
                ff_neterrno() != AVERROR(EINTR)) {
957 85f07f22 Fabrice Bellard
                /* error : close connection */
958 2effd274 Fabrice Bellard
                av_freep(&c->pb_buffer);
959 85f07f22 Fabrice Bellard
                return -1;
960
            }
961
        } else {
962
            c->buffer_ptr += len;
963 2e04edb3 Philip Gladstone
            if (c->stream)
964
                c->stream->bytes_served += len;
965 a6e14edd Philip Gladstone
            c->data_count += len;
966 85f07f22 Fabrice Bellard
            if (c->buffer_ptr >= c->buffer_end) {
967 2effd274 Fabrice Bellard
                av_freep(&c->pb_buffer);
968 85f07f22 Fabrice Bellard
                /* if error, exit */
969 611c5741 Alex Beregszaszi
                if (c->http_error)
970 85f07f22 Fabrice Bellard
                    return -1;
971 2effd274 Fabrice Bellard
                /* all the buffer was sent : synchronize to the incoming stream */
972 85f07f22 Fabrice Bellard
                c->state = HTTPSTATE_SEND_DATA_HEADER;
973
                c->buffer_ptr = c->buffer_end = c->buffer;
974
            }
975
        }
976
        break;
977
978
    case HTTPSTATE_SEND_DATA:
979
    case HTTPSTATE_SEND_DATA_HEADER:
980
    case HTTPSTATE_SEND_DATA_TRAILER:
981 2effd274 Fabrice Bellard
        /* for packetized output, we consider we can always write (the
982
           input streams sets the speed). It may be better to verify
983
           that we do not rely too much on the kernel queues */
984
        if (!c->is_packetized) {
985
            if (c->poll_entry->revents & (POLLERR | POLLHUP))
986
                return -1;
987 115329f1 Diego Biurrun
988 2effd274 Fabrice Bellard
            /* no need to read if no events */
989
            if (!(c->poll_entry->revents & POLLOUT))
990
                return 0;
991
        }
992 5eb765ef Philip Gladstone
        if (http_send_data(c) < 0)
993 85f07f22 Fabrice Bellard
            return -1;
994 638831aa Alex Beregszaszi
        /* close connection if trailer sent */
995
        if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
996
            return -1;
997 85f07f22 Fabrice Bellard
        break;
998
    case HTTPSTATE_RECEIVE_DATA:
999
        /* no need to read if no events */
1000
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
1001
            return -1;
1002
        if (!(c->poll_entry->revents & POLLIN))
1003
            return 0;
1004
        if (http_receive_data(c) < 0)
1005
            return -1;
1006
        break;
1007
    case HTTPSTATE_WAIT_FEED:
1008
        /* no need to read if no events */
1009 a6e14edd Philip Gladstone
        if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1010 85f07f22 Fabrice Bellard
            return -1;
1011
1012
        /* nothing to do, we'll be waken up by incoming feed packets */
1013
        break;
1014 2effd274 Fabrice Bellard
1015
    case RTSPSTATE_SEND_REPLY:
1016
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1017
            av_freep(&c->pb_buffer);
1018
            return -1;
1019
        }
1020
        /* no need to write if no events */
1021
        if (!(c->poll_entry->revents & POLLOUT))
1022
            return 0;
1023 c60202df Alex Beregszaszi
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1024 2effd274 Fabrice Bellard
        if (len < 0) {
1025 28c4741a Martin Storsjö
            if (ff_neterrno() != AVERROR(EAGAIN) &&
1026
                ff_neterrno() != AVERROR(EINTR)) {
1027 2effd274 Fabrice Bellard
                /* error : close connection */
1028
                av_freep(&c->pb_buffer);
1029
                return -1;
1030
            }
1031
        } else {
1032
            c->buffer_ptr += len;
1033
            c->data_count += len;
1034
            if (c->buffer_ptr >= c->buffer_end) {
1035
                /* all the buffer was sent : wait for a new request */
1036
                av_freep(&c->pb_buffer);
1037
                start_wait_request(c, 1);
1038
            }
1039
        }
1040
        break;
1041 bc351386 Fabrice Bellard
    case RTSPSTATE_SEND_PACKET:
1042
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1043
            av_freep(&c->packet_buffer);
1044
            return -1;
1045
        }
1046
        /* no need to write if no events */
1047
        if (!(c->poll_entry->revents & POLLOUT))
1048
            return 0;
1049 c60202df Alex Beregszaszi
        len = send(c->fd, c->packet_buffer_ptr,
1050
                    c->packet_buffer_end - c->packet_buffer_ptr, 0);
1051 bc351386 Fabrice Bellard
        if (len < 0) {
1052 28c4741a Martin Storsjö
            if (ff_neterrno() != AVERROR(EAGAIN) &&
1053
                ff_neterrno() != AVERROR(EINTR)) {
1054 bc351386 Fabrice Bellard
                /* error : close connection */
1055
                av_freep(&c->packet_buffer);
1056
                return -1;
1057
            }
1058
        } else {
1059
            c->packet_buffer_ptr += len;
1060
            if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1061
                /* all the buffer was sent : wait for a new request */
1062
                av_freep(&c->packet_buffer);
1063
                c->state = RTSPSTATE_WAIT_REQUEST;
1064
            }
1065
        }
1066
        break;
1067 2effd274 Fabrice Bellard
    case HTTPSTATE_READY:
1068
        /* nothing to do */
1069
        break;
1070 85f07f22 Fabrice Bellard
    default:
1071
        return -1;
1072
    }
1073
    return 0;
1074
}
1075
1076 3120d2a2 Philip Gladstone
static int extract_rates(char *rates, int ratelen, const char *request)
1077
{
1078
    const char *p;
1079
1080
    for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1081
        if (strncasecmp(p, "Pragma:", 7) == 0) {
1082
            const char *q = p + 7;
1083
1084
            while (*q && *q != '\n' && isspace(*q))
1085
                q++;
1086
1087
            if (strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1088
                int stream_no;
1089
                int rate_no;
1090
1091
                q += 20;
1092
1093 cde25790 Philip Gladstone
                memset(rates, 0xff, ratelen);
1094 3120d2a2 Philip Gladstone
1095
                while (1) {
1096
                    while (*q && *q != '\n' && *q != ':')
1097
                        q++;
1098
1099 611c5741 Alex Beregszaszi
                    if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1100 3120d2a2 Philip Gladstone
                        break;
1101 611c5741 Alex Beregszaszi
1102 3120d2a2 Philip Gladstone
                    stream_no--;
1103 611c5741 Alex Beregszaszi
                    if (stream_no < ratelen && stream_no >= 0)
1104 3120d2a2 Philip Gladstone
                        rates[stream_no] = rate_no;
1105
1106
                    while (*q && *q != '\n' && !isspace(*q))
1107
                        q++;
1108
                }
1109
1110
                return 1;
1111
            }
1112
        }
1113
        p = strchr(p, '\n');
1114
        if (!p)
1115
            break;
1116
1117
        p++;
1118
    }
1119
1120
    return 0;
1121
}
1122
1123 cde25790 Philip Gladstone
static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1124 3120d2a2 Philip Gladstone
{
1125
    int i;
1126 cde25790 Philip Gladstone
    int best_bitrate = 100000000;
1127
    int best = -1;
1128
1129
    for (i = 0; i < feed->nb_streams; i++) {
1130 01f4895c Michael Niedermayer
        AVCodecContext *feed_codec = feed->streams[i]->codec;
1131 cde25790 Philip Gladstone
1132
        if (feed_codec->codec_id != codec->codec_id ||
1133
            feed_codec->sample_rate != codec->sample_rate ||
1134
            feed_codec->width != codec->width ||
1135 611c5741 Alex Beregszaszi
            feed_codec->height != codec->height)
1136 cde25790 Philip Gladstone
            continue;
1137
1138
        /* Potential stream */
1139
1140 115329f1 Diego Biurrun
        /* We want the fastest stream less than bit_rate, or the slowest
1141 cde25790 Philip Gladstone
         * faster than bit_rate
1142
         */
1143
1144
        if (feed_codec->bit_rate <= bit_rate) {
1145
            if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1146
                best_bitrate = feed_codec->bit_rate;
1147
                best = i;
1148
            }
1149
        } else {
1150
            if (feed_codec->bit_rate < best_bitrate) {
1151
                best_bitrate = feed_codec->bit_rate;
1152
                best = i;
1153
            }
1154
        }
1155
    }
1156
1157
    return best;
1158
}
1159
1160
static int modify_current_stream(HTTPContext *c, char *rates)
1161
{
1162
    int i;
1163
    FFStream *req = c->stream;
1164
    int action_required = 0;
1165 3120d2a2 Philip Gladstone
1166 001bcd29 Philip Gladstone
    /* Not much we can do for a feed */
1167
    if (!req->feed)
1168
        return 0;
1169
1170 3120d2a2 Philip Gladstone
    for (i = 0; i < req->nb_streams; i++) {
1171 01f4895c Michael Niedermayer
        AVCodecContext *codec = req->streams[i]->codec;
1172 3120d2a2 Philip Gladstone
1173
        switch(rates[i]) {
1174
            case 0:
1175 cde25790 Philip Gladstone
                c->switch_feed_streams[i] = req->feed_streams[i];
1176 3120d2a2 Philip Gladstone
                break;
1177
            case 1:
1178 cde25790 Philip Gladstone
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1179 3120d2a2 Philip Gladstone
                break;
1180
            case 2:
1181 cde25790 Philip Gladstone
                /* Wants off or slow */
1182
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1183
#ifdef WANTS_OFF
1184
                /* This doesn't work well when it turns off the only stream! */
1185
                c->switch_feed_streams[i] = -2;
1186
                c->feed_streams[i] = -2;
1187
#endif
1188 3120d2a2 Philip Gladstone
                break;
1189
        }
1190
1191 cde25790 Philip Gladstone
        if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1192
            action_required = 1;
1193
    }
1194 3120d2a2 Philip Gladstone
1195 cde25790 Philip Gladstone
    return action_required;
1196
}
1197 3120d2a2 Philip Gladstone
1198 2effd274 Fabrice Bellard
/* XXX: factorize in utils.c ? */
1199
/* XXX: take care with different space meaning */
1200
static void skip_spaces(const char **pp)
1201
{
1202
    const char *p;
1203
    p = *pp;
1204
    while (*p == ' ' || *p == '\t')
1205
        p++;
1206
    *pp = p;
1207
}
1208
1209
static void get_word(char *buf, int buf_size, const char **pp)
1210
{
1211
    const char *p;
1212
    char *q;
1213
1214
    p = *pp;
1215
    skip_spaces(&p);
1216
    q = buf;
1217
    while (!isspace(*p) && *p != '\0') {
1218
        if ((q - buf) < buf_size - 1)
1219
            *q++ = *p;
1220
        p++;
1221
    }
1222
    if (buf_size > 0)
1223
        *q = '\0';
1224
    *pp = p;
1225
}
1226
1227 c64c0a9b Benjamin Larsson
static void get_arg(char *buf, int buf_size, const char **pp)
1228
{
1229
    const char *p;
1230
    char *q;
1231
    int quote;
1232
1233
    p = *pp;
1234
    while (isspace(*p)) p++;
1235
    q = buf;
1236
    quote = 0;
1237
    if (*p == '\"' || *p == '\'')
1238
        quote = *p++;
1239
    for(;;) {
1240
        if (quote) {
1241
            if (*p == quote)
1242
                break;
1243
        } else {
1244
            if (isspace(*p))
1245
                break;
1246
        }
1247
        if (*p == '\0')
1248
            break;
1249
        if ((q - buf) < buf_size - 1)
1250
            *q++ = *p;
1251
        p++;
1252
    }
1253
    *q = '\0';
1254
    if (quote && *p == quote)
1255
        p++;
1256
    *pp = p;
1257
}
1258
1259 58f48adb Benjamin Larsson
static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1260
                         const char *p, const char *filename, int line_num)
1261
{
1262
    char arg[1024];
1263
    IPAddressACL acl;
1264
    int errors = 0;
1265
1266
    get_arg(arg, sizeof(arg), &p);
1267
    if (strcasecmp(arg, "allow") == 0)
1268
        acl.action = IP_ALLOW;
1269
    else if (strcasecmp(arg, "deny") == 0)
1270
        acl.action = IP_DENY;
1271
    else {
1272
        fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1273
                filename, line_num, arg);
1274
        errors++;
1275
    }
1276
1277
    get_arg(arg, sizeof(arg), &p);
1278
1279
    if (resolve_host(&acl.first, arg) != 0) {
1280
        fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1281
                filename, line_num, arg);
1282
        errors++;
1283
    } else
1284
        acl.last = acl.first;
1285
1286
    get_arg(arg, sizeof(arg), &p);
1287
1288
    if (arg[0]) {
1289
        if (resolve_host(&acl.last, arg) != 0) {
1290
            fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1291
                    filename, line_num, arg);
1292
            errors++;
1293
        }
1294
    }
1295
1296
    if (!errors) {
1297
        IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1298
        IPAddressACL **naclp = 0;
1299
1300
        acl.next = 0;
1301
        *nacl = acl;
1302
1303
        if (stream)
1304
            naclp = &stream->acl;
1305
        else if (feed)
1306
            naclp = &feed->acl;
1307
        else if (ext_acl)
1308
            naclp = &ext_acl;
1309
        else {
1310
            fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1311
                    filename, line_num);
1312
            errors++;
1313
        }
1314
1315
        if (naclp) {
1316
            while (*naclp)
1317
                naclp = &(*naclp)->next;
1318
1319
            *naclp = nacl;
1320
        }
1321
    }
1322
}
1323
1324
1325
static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
1326
{
1327
    FILE* f;
1328
    char line[1024];
1329
    char  cmd[1024];
1330
    IPAddressACL *acl = NULL;
1331
    int line_num = 0;
1332
    const char *p;
1333
1334
    f = fopen(stream->dynamic_acl, "r");
1335
    if (!f) {
1336
        perror(stream->dynamic_acl);
1337
        return NULL;
1338
    }
1339
1340
    acl = av_mallocz(sizeof(IPAddressACL));
1341
1342
    /* Build ACL */
1343
    for(;;) {
1344
        if (fgets(line, sizeof(line), f) == NULL)
1345
            break;
1346
        line_num++;
1347
        p = line;
1348
        while (isspace(*p))
1349
            p++;
1350
        if (*p == '\0' || *p == '#')
1351
            continue;
1352
        get_arg(cmd, sizeof(cmd), &p);
1353
1354
        if (!strcasecmp(cmd, "ACL"))
1355
            parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1356
    }
1357
    fclose(f);
1358
    return acl;
1359
}
1360
1361
1362
static void free_acl_list(IPAddressACL *in_acl)
1363
{
1364
    IPAddressACL *pacl,*pacl2;
1365
1366
    pacl = in_acl;
1367
    while(pacl) {
1368
        pacl2 = pacl;
1369
        pacl = pacl->next;
1370
        av_freep(pacl2);
1371
    }
1372
}
1373
1374
static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
1375 8256c0a3 Philip Gladstone
{
1376
    enum IPAddressAction last_action = IP_DENY;
1377
    IPAddressACL *acl;
1378
    struct in_addr *src = &c->from_addr.sin_addr;
1379 2bd8416e Alex Beregszaszi
    unsigned long src_addr = src->s_addr;
1380 8256c0a3 Philip Gladstone
1381 58f48adb Benjamin Larsson
    for (acl = in_acl; acl; acl = acl->next) {
1382 611c5741 Alex Beregszaszi
        if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1383 8256c0a3 Philip Gladstone
            return (acl->action == IP_ALLOW) ? 1 : 0;
1384
        last_action = acl->action;
1385
    }
1386
1387
    /* Nothing matched, so return not the last action */
1388
    return (last_action == IP_DENY) ? 1 : 0;
1389
}
1390
1391 58f48adb Benjamin Larsson
static int validate_acl(FFStream *stream, HTTPContext *c)
1392
{
1393
    int ret = 0;
1394
    IPAddressACL *acl;
1395
1396
1397
    /* if stream->acl is null validate_acl_list will return 1 */
1398
    ret = validate_acl_list(stream->acl, c);
1399
1400
    if (stream->dynamic_acl[0]) {
1401
        acl = parse_dynamic_acl(stream, c);
1402
1403
        ret = validate_acl_list(acl, c);
1404
1405
        free_acl_list(acl);
1406
    }
1407
1408
    return ret;
1409
}
1410
1411 829ac53d Fabrice Bellard
/* compute the real filename of a file by matching it without its
1412
   extensions to all the stream filenames */
1413
static void compute_real_filename(char *filename, int max_size)
1414
{
1415
    char file1[1024];
1416
    char file2[1024];
1417
    char *p;
1418
    FFStream *stream;
1419
1420
    /* compute filename by matching without the file extensions */
1421 f7d78f36 Måns Rullgård
    av_strlcpy(file1, filename, sizeof(file1));
1422 829ac53d Fabrice Bellard
    p = strrchr(file1, '.');
1423
    if (p)
1424
        *p = '\0';
1425
    for(stream = first_stream; stream != NULL; stream = stream->next) {
1426 f7d78f36 Måns Rullgård
        av_strlcpy(file2, stream->filename, sizeof(file2));
1427 829ac53d Fabrice Bellard
        p = strrchr(file2, '.');
1428
        if (p)
1429
            *p = '\0';
1430
        if (!strcmp(file1, file2)) {
1431 f7d78f36 Måns Rullgård
            av_strlcpy(filename, stream->filename, max_size);
1432 829ac53d Fabrice Bellard
            break;
1433
        }
1434
    }
1435
}
1436
1437
enum RedirType {
1438
    REDIR_NONE,
1439
    REDIR_ASX,
1440
    REDIR_RAM,
1441
    REDIR_ASF,
1442
    REDIR_RTSP,
1443
    REDIR_SDP,
1444
};
1445
1446 85f07f22 Fabrice Bellard
/* parse http request and prepare header */
1447
static int http_parse_request(HTTPContext *c)
1448
{
1449
    char *p;
1450 829ac53d Fabrice Bellard
    enum RedirType redir_type;
1451 85f07f22 Fabrice Bellard
    char cmd[32];
1452 bae79c04 Alex Beregszaszi
    char info[1024], filename[1024];
1453 85f07f22 Fabrice Bellard
    char url[1024], *q;
1454
    char protocol[32];
1455
    char msg[1024];
1456
    const char *mime_type;
1457
    FFStream *stream;
1458 42a63c6a Philip Gladstone
    int i;
1459 3120d2a2 Philip Gladstone
    char ratebuf[32];
1460 cde25790 Philip Gladstone
    char *useragent = 0;
1461 85f07f22 Fabrice Bellard
1462
    p = c->buffer;
1463 2effd274 Fabrice Bellard
    get_word(cmd, sizeof(cmd), (const char **)&p);
1464 f7d78f36 Måns Rullgård
    av_strlcpy(c->method, cmd, sizeof(c->method));
1465 7434ba6d Philip Gladstone
1466 85f07f22 Fabrice Bellard
    if (!strcmp(cmd, "GET"))
1467 edfdd798 Alex Beregszaszi
        c->post = 0;
1468 85f07f22 Fabrice Bellard
    else if (!strcmp(cmd, "POST"))
1469 edfdd798 Alex Beregszaszi
        c->post = 1;
1470 85f07f22 Fabrice Bellard
    else
1471
        return -1;
1472
1473 2effd274 Fabrice Bellard
    get_word(url, sizeof(url), (const char **)&p);
1474 f7d78f36 Måns Rullgård
    av_strlcpy(c->url, url, sizeof(c->url));
1475 7434ba6d Philip Gladstone
1476 2effd274 Fabrice Bellard
    get_word(protocol, sizeof(protocol), (const char **)&p);
1477 85f07f22 Fabrice Bellard
    if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1478
        return -1;
1479 7434ba6d Philip Gladstone
1480 f7d78f36 Måns Rullgård
    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1481 90f9c440 Alex Beregszaszi
1482
    if (ffserver_debug)
1483 77553ae3 Baptiste Coudurier
        http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1484 115329f1 Diego Biurrun
1485 85f07f22 Fabrice Bellard
    /* find the filename and the optional info string in the request */
1486 bae79c04 Alex Beregszaszi
    p = strchr(url, '?');
1487 85f07f22 Fabrice Bellard
    if (p) {
1488 f7d78f36 Måns Rullgård
        av_strlcpy(info, p, sizeof(info));
1489 85f07f22 Fabrice Bellard
        *p = '\0';
1490 611c5741 Alex Beregszaszi
    } else
1491 85f07f22 Fabrice Bellard
        info[0] = '\0';
1492
1493 f7d78f36 Måns Rullgård
    av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1494 bae79c04 Alex Beregszaszi
1495 cde25790 Philip Gladstone
    for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1496
        if (strncasecmp(p, "User-Agent:", 11) == 0) {
1497
            useragent = p + 11;
1498
            if (*useragent && *useragent != '\n' && isspace(*useragent))
1499
                useragent++;
1500
            break;
1501
        }
1502
        p = strchr(p, '\n');
1503
        if (!p)
1504
            break;
1505
1506
        p++;
1507
    }
1508
1509 829ac53d Fabrice Bellard
    redir_type = REDIR_NONE;
1510 aa13b573 Stefano Sabatini
    if (av_match_ext(filename, "asx")) {
1511 829ac53d Fabrice Bellard
        redir_type = REDIR_ASX;
1512 7434ba6d Philip Gladstone
        filename[strlen(filename)-1] = 'f';
1513 aa13b573 Stefano Sabatini
    } else if (av_match_ext(filename, "asf") &&
1514 cde25790 Philip Gladstone
        (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1515
        /* if this isn't WMP or lookalike, return the redirector file */
1516 829ac53d Fabrice Bellard
        redir_type = REDIR_ASF;
1517 aa13b573 Stefano Sabatini
    } else if (av_match_ext(filename, "rpm,ram")) {
1518 829ac53d Fabrice Bellard
        redir_type = REDIR_RAM;
1519 42a63c6a Philip Gladstone
        strcpy(filename + strlen(filename)-2, "m");
1520 aa13b573 Stefano Sabatini
    } else if (av_match_ext(filename, "rtsp")) {
1521 829ac53d Fabrice Bellard
        redir_type = REDIR_RTSP;
1522 bae79c04 Alex Beregszaszi
        compute_real_filename(filename, sizeof(filename) - 1);
1523 aa13b573 Stefano Sabatini
    } else if (av_match_ext(filename, "sdp")) {
1524 829ac53d Fabrice Bellard
        redir_type = REDIR_SDP;
1525 bae79c04 Alex Beregszaszi
        compute_real_filename(filename, sizeof(filename) - 1);
1526 42a63c6a Philip Gladstone
    }
1527 115329f1 Diego Biurrun
1528 bae79c04 Alex Beregszaszi
    // "redirect" / request to index.html
1529
    if (!strlen(filename))
1530 f7d78f36 Måns Rullgård
        av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1531 bae79c04 Alex Beregszaszi
1532 85f07f22 Fabrice Bellard
    stream = first_stream;
1533
    while (stream != NULL) {
1534 8256c0a3 Philip Gladstone
        if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1535 85f07f22 Fabrice Bellard
            break;
1536
        stream = stream->next;
1537
    }
1538
    if (stream == NULL) {
1539 d445a7e9 Philip Gladstone
        snprintf(msg, sizeof(msg), "File '%s' not found", url);
1540 77553ae3 Baptiste Coudurier
        http_log("File '%s' not found\n", url);
1541 85f07f22 Fabrice Bellard
        goto send_error;
1542
    }
1543 42a63c6a Philip Gladstone
1544 cde25790 Philip Gladstone
    c->stream = stream;
1545
    memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1546
    memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1547
1548
    if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1549
        c->http_error = 301;
1550
        q = c->buffer;
1551 a3aa4fed Baptiste Coudurier
        q += snprintf(q, c->buffer_size,
1552
                      "HTTP/1.0 301 Moved\r\n"
1553
                      "Location: %s\r\n"
1554
                      "Content-type: text/html\r\n"
1555
                      "\r\n"
1556
                      "<html><head><title>Moved</title></head><body>\r\n"
1557
                      "You should be <a href=\"%s\">redirected</a>.\r\n"
1558
                      "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1559 cde25790 Philip Gladstone
        /* prepare output buffer */
1560
        c->buffer_ptr = c->buffer;
1561
        c->buffer_end = q;
1562
        c->state = HTTPSTATE_SEND_HEADER;
1563
        return 0;
1564
    }
1565
1566 3120d2a2 Philip Gladstone
    /* If this is WMP, get the rate information */
1567
    if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1568 cde25790 Philip Gladstone
        if (modify_current_stream(c, ratebuf)) {
1569 37d3e066 Aurelien Jacobs
            for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1570 cde25790 Philip Gladstone
                if (c->switch_feed_streams[i] >= 0)
1571 305ca590 Reinhard Tartler
                    c->switch_feed_streams[i] = -1;
1572 cde25790 Philip Gladstone
            }
1573
        }
1574 3120d2a2 Philip Gladstone
    }
1575
1576 d8f28a77 Baptiste Coudurier
    if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1577
        current_bandwidth += stream->bandwidth;
1578
1579 755bfeab Diego Biurrun
    /* If already streaming this feed, do not let start another feeder. */
1580 d0a5513b Alex Beregszaszi
    if (stream->feed_opened) {
1581
        snprintf(msg, sizeof(msg), "This feed is already being received.");
1582 77553ae3 Baptiste Coudurier
        http_log("Feed '%s' already being received\n", stream->feed_filename);
1583 d0a5513b Alex Beregszaszi
        goto send_error;
1584
    }
1585
1586 edfdd798 Alex Beregszaszi
    if (c->post == 0 && max_bandwidth < current_bandwidth) {
1587 0aee2a57 Howard Chu
        c->http_error = 503;
1588 42a63c6a Philip Gladstone
        q = c->buffer;
1589 a3aa4fed Baptiste Coudurier
        q += snprintf(q, c->buffer_size,
1590 0aee2a57 Howard Chu
                      "HTTP/1.0 503 Server too busy\r\n"
1591 a3aa4fed Baptiste Coudurier
                      "Content-type: text/html\r\n"
1592
                      "\r\n"
1593
                      "<html><head><title>Too busy</title></head><body>\r\n"
1594
                      "<p>The server is too busy to serve your request at this time.</p>\r\n"
1595 0be4b8d9 Baptiste Coudurier
                      "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1596
                      "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1597 a3aa4fed Baptiste Coudurier
                      "</body></html>\r\n", current_bandwidth, max_bandwidth);
1598 42a63c6a Philip Gladstone
        /* prepare output buffer */
1599
        c->buffer_ptr = c->buffer;
1600
        c->buffer_end = q;
1601
        c->state = HTTPSTATE_SEND_HEADER;
1602
        return 0;
1603
    }
1604 115329f1 Diego Biurrun
1605 829ac53d Fabrice Bellard
    if (redir_type != REDIR_NONE) {
1606 7434ba6d Philip Gladstone
        char *hostinfo = 0;
1607 115329f1 Diego Biurrun
1608 7434ba6d Philip Gladstone
        for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1609
            if (strncasecmp(p, "Host:", 5) == 0) {
1610
                hostinfo = p + 5;
1611
                break;
1612
            }
1613
            p = strchr(p, '\n');
1614
            if (!p)
1615
                break;
1616
1617
            p++;
1618
        }
1619
1620
        if (hostinfo) {
1621
            char *eoh;
1622
            char hostbuf[260];
1623
1624
            while (isspace(*hostinfo))
1625
                hostinfo++;
1626
1627
            eoh = strchr(hostinfo, '\n');
1628
            if (eoh) {
1629
                if (eoh[-1] == '\r')
1630
                    eoh--;
1631
1632
                if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1633
                    memcpy(hostbuf, hostinfo, eoh - hostinfo);
1634
                    hostbuf[eoh - hostinfo] = 0;
1635
1636
                    c->http_error = 200;
1637
                    q = c->buffer;
1638 829ac53d Fabrice Bellard
                    switch(redir_type) {
1639
                    case REDIR_ASX:
1640 a3aa4fed Baptiste Coudurier
                        q += snprintf(q, c->buffer_size,
1641
                                      "HTTP/1.0 200 ASX Follows\r\n"
1642
                                      "Content-type: video/x-ms-asf\r\n"
1643
                                      "\r\n"
1644
                                      "<ASX Version=\"3\">\r\n"
1645
                                      //"<!-- Autogenerated by ffserver -->\r\n"
1646
                                      "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1647
                                      "</ASX>\r\n", hostbuf, filename, info);
1648 829ac53d Fabrice Bellard
                        break;
1649
                    case REDIR_RAM:
1650 a3aa4fed Baptiste Coudurier
                        q += snprintf(q, c->buffer_size,
1651
                                      "HTTP/1.0 200 RAM Follows\r\n"
1652
                                      "Content-type: audio/x-pn-realaudio\r\n"
1653
                                      "\r\n"
1654
                                      "# Autogenerated by ffserver\r\n"
1655
                                      "http://%s/%s%s\r\n", hostbuf, filename, info);
1656 829ac53d Fabrice Bellard
                        break;
1657
                    case REDIR_ASF:
1658 a3aa4fed Baptiste Coudurier
                        q += snprintf(q, c->buffer_size,
1659
                                      "HTTP/1.0 200 ASF Redirect follows\r\n"
1660
                                      "Content-type: video/x-ms-asf\r\n"
1661
                                      "\r\n"
1662
                                      "[Reference]\r\n"
1663
                                      "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1664 829ac53d Fabrice Bellard
                        break;
1665
                    case REDIR_RTSP:
1666
                        {
1667
                            char hostname[256], *p;
1668
                            /* extract only hostname */
1669 f7d78f36 Måns Rullgård
                            av_strlcpy(hostname, hostbuf, sizeof(hostname));
1670 829ac53d Fabrice Bellard
                            p = strrchr(hostname, ':');
1671
                            if (p)
1672
                                *p = '\0';
1673 a3aa4fed Baptiste Coudurier
                            q += snprintf(q, c->buffer_size,
1674
                                          "HTTP/1.0 200 RTSP Redirect follows\r\n"
1675
                                          /* XXX: incorrect mime type ? */
1676
                                          "Content-type: application/x-rtsp\r\n"
1677
                                          "\r\n"
1678
                                          "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1679 829ac53d Fabrice Bellard
                        }
1680
                        break;
1681
                    case REDIR_SDP:
1682
                        {
1683 0c1a9eda Zdenek Kabelac
                            uint8_t *sdp_data;
1684 829ac53d Fabrice Bellard
                            int sdp_data_size, len;
1685
                            struct sockaddr_in my_addr;
1686
1687 a3aa4fed Baptiste Coudurier
                            q += snprintf(q, c->buffer_size,
1688
                                          "HTTP/1.0 200 OK\r\n"
1689
                                          "Content-type: application/sdp\r\n"
1690
                                          "\r\n");
1691 829ac53d Fabrice Bellard
1692
                            len = sizeof(my_addr);
1693
                            getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1694 115329f1 Diego Biurrun
1695 829ac53d Fabrice Bellard
                            /* XXX: should use a dynamic buffer */
1696 115329f1 Diego Biurrun
                            sdp_data_size = prepare_sdp_description(stream,
1697
                                                                    &sdp_data,
1698 829ac53d Fabrice Bellard
                                                                    my_addr.sin_addr);
1699
                            if (sdp_data_size > 0) {
1700
                                memcpy(q, sdp_data, sdp_data_size);
1701
                                q += sdp_data_size;
1702
                                *q = '\0';
1703
                                av_free(sdp_data);
1704
                            }
1705
                        }
1706
                        break;
1707
                    default:
1708 0f4e8165 Ronald S. Bultje
                        abort();
1709 829ac53d Fabrice Bellard
                        break;
1710 2effd274 Fabrice Bellard
                    }
1711 7434ba6d Philip Gladstone
1712
                    /* prepare output buffer */
1713
                    c->buffer_ptr = c->buffer;
1714
                    c->buffer_end = q;
1715
                    c->state = HTTPSTATE_SEND_HEADER;
1716
                    return 0;
1717
                }
1718
            }
1719
        }
1720
1721 d445a7e9 Philip Gladstone
        snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1722 7434ba6d Philip Gladstone
        goto send_error;
1723 85f07f22 Fabrice Bellard
    }
1724
1725 a6e14edd Philip Gladstone
    stream->conns_served++;
1726 7434ba6d Philip Gladstone
1727 85f07f22 Fabrice Bellard
    /* XXX: add there authenticate and IP match */
1728
1729 edfdd798 Alex Beregszaszi
    if (c->post) {
1730 85f07f22 Fabrice Bellard
        /* if post, it means a feed is being sent */
1731
        if (!stream->is_feed) {
1732 e16190fa Diego Biurrun
            /* However it might be a status report from WMP! Let us log the
1733
             * data as it might come in handy one day. */
1734 7434ba6d Philip Gladstone
            char *logline = 0;
1735 3120d2a2 Philip Gladstone
            int client_id = 0;
1736 115329f1 Diego Biurrun
1737 7434ba6d Philip Gladstone
            for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1738
                if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1739
                    logline = p;
1740
                    break;
1741
                }
1742 611c5741 Alex Beregszaszi
                if (strncasecmp(p, "Pragma: client-id=", 18) == 0)
1743 3120d2a2 Philip Gladstone
                    client_id = strtol(p + 18, 0, 10);
1744 7434ba6d Philip Gladstone
                p = strchr(p, '\n');
1745
                if (!p)
1746
                    break;
1747
1748
                p++;
1749
            }
1750
1751
            if (logline) {
1752
                char *eol = strchr(logline, '\n');
1753
1754
                logline += 17;
1755
1756
                if (eol) {
1757
                    if (eol[-1] == '\r')
1758
                        eol--;
1759 7906085f Falk Hüffner
                    http_log("%.*s\n", (int) (eol - logline), logline);
1760 7434ba6d Philip Gladstone
                    c->suppress_log = 1;
1761
                }
1762
            }
1763 3120d2a2 Philip Gladstone
1764 cde25790 Philip Gladstone
#ifdef DEBUG_WMP
1765
            http_log("\nGot request:\n%s\n", c->buffer);
1766 3120d2a2 Philip Gladstone
#endif
1767
1768
            if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1769
                HTTPContext *wmpc;
1770
1771
                /* Now we have to find the client_id */
1772
                for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1773
                    if (wmpc->wmp_client_id == client_id)
1774
                        break;
1775
                }
1776
1777 2d563d2f Alex Beregszaszi
                if (wmpc && modify_current_stream(wmpc, ratebuf))
1778
                    wmpc->switch_pending = 1;
1779 3120d2a2 Philip Gladstone
            }
1780 115329f1 Diego Biurrun
1781 d445a7e9 Philip Gladstone
            snprintf(msg, sizeof(msg), "POST command not handled");
1782 cb275dd9 Philip Gladstone
            c->stream = 0;
1783 85f07f22 Fabrice Bellard
            goto send_error;
1784
        }
1785
        if (http_start_receive_data(c) < 0) {
1786 d445a7e9 Philip Gladstone
            snprintf(msg, sizeof(msg), "could not open feed");
1787 85f07f22 Fabrice Bellard
            goto send_error;
1788
        }
1789
        c->http_error = 0;
1790
        c->state = HTTPSTATE_RECEIVE_DATA;
1791
        return 0;
1792
    }
1793
1794 cde25790 Philip Gladstone
#ifdef DEBUG_WMP
1795 611c5741 Alex Beregszaszi
    if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1796 cde25790 Philip Gladstone
        http_log("\nGot request:\n%s\n", c->buffer);
1797 3120d2a2 Philip Gladstone
#endif
1798
1799 85f07f22 Fabrice Bellard
    if (c->stream->stream_type == STREAM_TYPE_STATUS)
1800 dca21085 Stefano Sabatini
        goto send_status;
1801 85f07f22 Fabrice Bellard
1802
    /* open input stream */
1803
    if (open_input_stream(c, info) < 0) {
1804 d445a7e9 Philip Gladstone
        snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1805 85f07f22 Fabrice Bellard
        goto send_error;
1806
    }
1807
1808
    /* prepare http header */
1809
    q = c->buffer;
1810 d445a7e9 Philip Gladstone
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1811 85f07f22 Fabrice Bellard
    mime_type = c->stream->fmt->mime_type;
1812
    if (!mime_type)
1813 087fa475 Alex Beregszaszi
        mime_type = "application/x-octet-stream";
1814 d445a7e9 Philip Gladstone
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
1815 85f07f22 Fabrice Bellard
1816
    /* for asf, we need extra headers */
1817 8256c0a3 Philip Gladstone
    if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1818 3120d2a2 Philip Gladstone
        /* Need to allocate a client id */
1819
1820 042819c5 Baptiste Coudurier
        c->wmp_client_id = av_lfg_get(&random_state);
1821 3120d2a2 Philip Gladstone
1822 d445a7e9 Philip Gladstone
        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);
1823 85f07f22 Fabrice Bellard
    }
1824 d445a7e9 Philip Gladstone
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1825
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1826 115329f1 Diego Biurrun
1827 85f07f22 Fabrice Bellard
    /* prepare output buffer */
1828
    c->http_error = 0;
1829
    c->buffer_ptr = c->buffer;
1830
    c->buffer_end = q;
1831
    c->state = HTTPSTATE_SEND_HEADER;
1832
    return 0;
1833
 send_error:
1834
    c->http_error = 404;
1835
    q = c->buffer;
1836 a3aa4fed Baptiste Coudurier
    q += snprintf(q, c->buffer_size,
1837
                  "HTTP/1.0 404 Not Found\r\n"
1838
                  "Content-type: text/html\r\n"
1839
                  "\r\n"
1840 5e567aae Diego Biurrun
                  "<html>\n"
1841
                  "<head><title>404 Not Found</title></head>\n"
1842
                  "<body>%s</body>\n"
1843
                  "</html>\n", msg);
1844 85f07f22 Fabrice Bellard
    /* prepare output buffer */
1845
    c->buffer_ptr = c->buffer;
1846
    c->buffer_end = q;
1847
    c->state = HTTPSTATE_SEND_HEADER;
1848
    return 0;
1849 dca21085 Stefano Sabatini
 send_status:
1850
    compute_status(c);
1851 85f07f22 Fabrice Bellard
    c->http_error = 200; /* horrible : we use this value to avoid
1852
                            going to the send data state */
1853
    c->state = HTTPSTATE_SEND_HEADER;
1854
    return 0;
1855
}
1856
1857 ae628ec1 Anton Khirnov
static void fmt_bytecount(AVIOContext *pb, int64_t count)
1858 2ac887ba Philip Gladstone
{
1859
    static const char *suffix = " kMGTP";
1860
    const char *s;
1861
1862 611c5741 Alex Beregszaszi
    for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1863 2ac887ba Philip Gladstone
1864 d9d86e00 Anton Khirnov
    avio_printf(pb, "%"PRId64"%c", count, *s);
1865 2ac887ba Philip Gladstone
}
1866
1867 dca21085 Stefano Sabatini
static void compute_status(HTTPContext *c)
1868 85f07f22 Fabrice Bellard
{
1869
    HTTPContext *c1;
1870
    FFStream *stream;
1871 2effd274 Fabrice Bellard
    char *p;
1872 85f07f22 Fabrice Bellard
    time_t ti;
1873 2effd274 Fabrice Bellard
    int i, len;
1874 ae628ec1 Anton Khirnov
    AVIOContext *pb;
1875 cde25790 Philip Gladstone
1876 899681cd Björn Axelsson
    if (url_open_dyn_buf(&pb) < 0) {
1877 2effd274 Fabrice Bellard
        /* XXX: return an error ? */
1878 cde25790 Philip Gladstone
        c->buffer_ptr = c->buffer;
1879 2effd274 Fabrice Bellard
        c->buffer_end = c->buffer;
1880
        return;
1881 cde25790 Philip Gladstone
    }
1882 85f07f22 Fabrice Bellard
1883 d9d86e00 Anton Khirnov
    avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1884
    avio_printf(pb, "Content-type: %s\r\n", "text/html");
1885
    avio_printf(pb, "Pragma: no-cache\r\n");
1886
    avio_printf(pb, "\r\n");
1887 115329f1 Diego Biurrun
1888 d9d86e00 Anton Khirnov
    avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1889 0679719d Erik Hovland
    if (c->stream->feed_filename[0])
1890 d9d86e00 Anton Khirnov
        avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1891
    avio_printf(pb, "</head>\n<body>");
1892
    avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1893 85f07f22 Fabrice Bellard
    /* format status */
1894 d9d86e00 Anton Khirnov
    avio_printf(pb, "<h2>Available Streams</h2>\n");
1895
    avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1896
    avio_printf(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");
1897 85f07f22 Fabrice Bellard
    stream = first_stream;
1898
    while (stream != NULL) {
1899 42a63c6a Philip Gladstone
        char sfilename[1024];
1900
        char *eosf;
1901
1902 a6e14edd Philip Gladstone
        if (stream->feed != stream) {
1903 f7d78f36 Måns Rullgård
            av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1904 a6e14edd Philip Gladstone
            eosf = sfilename + strlen(sfilename);
1905
            if (eosf - sfilename >= 4) {
1906 611c5741 Alex Beregszaszi
                if (strcmp(eosf - 4, ".asf") == 0)
1907 a6e14edd Philip Gladstone
                    strcpy(eosf - 4, ".asx");
1908 611c5741 Alex Beregszaszi
                else if (strcmp(eosf - 3, ".rm") == 0)
1909 a6e14edd Philip Gladstone
                    strcpy(eosf - 3, ".ram");
1910 25e3e53d Luca Abeni
                else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1911 829ac53d Fabrice Bellard
                    /* generate a sample RTSP director if
1912
                       unicast. Generate an SDP redirector if
1913
                       multicast */
1914 2effd274 Fabrice Bellard
                    eosf = strrchr(sfilename, '.');
1915
                    if (!eosf)
1916
                        eosf = sfilename + strlen(sfilename);
1917 829ac53d Fabrice Bellard
                    if (stream->is_multicast)
1918
                        strcpy(eosf, ".sdp");
1919
                    else
1920
                        strcpy(eosf, ".rtsp");
1921 a6e14edd Philip Gladstone
                }
1922 42a63c6a Philip Gladstone
            }
1923 115329f1 Diego Biurrun
1924 d9d86e00 Anton Khirnov
            avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1925 a6e14edd Philip Gladstone
                         sfilename, stream->filename);
1926 d9d86e00 Anton Khirnov
            avio_printf(pb, "<td align=right> %d <td align=right> ",
1927 2ac887ba Philip Gladstone
                        stream->conns_served);
1928 2effd274 Fabrice Bellard
            fmt_bytecount(pb, stream->bytes_served);
1929 a6e14edd Philip Gladstone
            switch(stream->stream_type) {
1930 ace21da3 Baptiste Coudurier
            case STREAM_TYPE_LIVE: {
1931 a6e14edd Philip Gladstone
                    int audio_bit_rate = 0;
1932
                    int video_bit_rate = 0;
1933 58445440 Zdenek Kabelac
                    const char *audio_codec_name = "";
1934
                    const char *video_codec_name = "";
1935
                    const char *audio_codec_name_extra = "";
1936
                    const char *video_codec_name_extra = "";
1937 a6e14edd Philip Gladstone
1938
                    for(i=0;i<stream->nb_streams;i++) {
1939
                        AVStream *st = stream->streams[i];
1940 01f4895c Michael Niedermayer
                        AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1941
                        switch(st->codec->codec_type) {
1942 72415b2a Stefano Sabatini
                        case AVMEDIA_TYPE_AUDIO:
1943 01f4895c Michael Niedermayer
                            audio_bit_rate += st->codec->bit_rate;
1944 a6e14edd Philip Gladstone
                            if (codec) {
1945
                                if (*audio_codec_name)
1946
                                    audio_codec_name_extra = "...";
1947
                                audio_codec_name = codec->name;
1948
                            }
1949
                            break;
1950 72415b2a Stefano Sabatini
                        case AVMEDIA_TYPE_VIDEO:
1951 01f4895c Michael Niedermayer
                            video_bit_rate += st->codec->bit_rate;
1952 a6e14edd Philip Gladstone
                            if (codec) {
1953
                                if (*video_codec_name)
1954
                                    video_codec_name_extra = "...";
1955
                                video_codec_name = codec->name;
1956
                            }
1957
                            break;
1958 72415b2a Stefano Sabatini
                        case AVMEDIA_TYPE_DATA:
1959 01f4895c Michael Niedermayer
                            video_bit_rate += st->codec->bit_rate;
1960 e240a0bb Fabrice Bellard
                            break;
1961 a6e14edd Philip Gladstone
                        default:
1962 0f4e8165 Ronald S. Bultje
                            abort();
1963 79c4ea3c Philip Gladstone
                        }
1964 85f07f22 Fabrice Bellard
                    }
1965 d9d86e00 Anton Khirnov
                    avio_printf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
1966 a6e14edd Philip Gladstone
                                 stream->fmt->name,
1967 6edd6884 Fabrice Bellard
                                 stream->bandwidth,
1968 a6e14edd Philip Gladstone
                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1969
                                 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
1970 611c5741 Alex Beregszaszi
                    if (stream->feed)
1971 d9d86e00 Anton Khirnov
                        avio_printf(pb, "<td>%s", stream->feed->filename);
1972 611c5741 Alex Beregszaszi
                    else
1973 d9d86e00 Anton Khirnov
                        avio_printf(pb, "<td>%s", stream->feed_filename);
1974
                    avio_printf(pb, "\n");
1975 85f07f22 Fabrice Bellard
                }
1976 a6e14edd Philip Gladstone
                break;
1977
            default:
1978 d9d86e00 Anton Khirnov
                avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
1979 a6e14edd Philip Gladstone
                break;
1980 85f07f22 Fabrice Bellard
            }
1981
        }
1982
        stream = stream->next;
1983
    }
1984 d9d86e00 Anton Khirnov
    avio_printf(pb, "</table>\n");
1985 a6e14edd Philip Gladstone
1986
    stream = first_stream;
1987
    while (stream != NULL) {
1988
        if (stream->feed == stream) {
1989 d9d86e00 Anton Khirnov
            avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
1990 cde25790 Philip Gladstone
            if (stream->pid) {
1991 d9d86e00 Anton Khirnov
                avio_printf(pb, "Running as pid %d.\n", stream->pid);
1992 cde25790 Philip Gladstone
1993 2effd274 Fabrice Bellard
#if defined(linux) && !defined(CONFIG_NOCUTILS)
1994
                {
1995
                    FILE *pid_stat;
1996
                    char ps_cmd[64];
1997
1998
                    /* This is somewhat linux specific I guess */
1999 115329f1 Diego Biurrun
                    snprintf(ps_cmd, sizeof(ps_cmd),
2000
                             "ps -o \"%%cpu,cputime\" --no-headers %d",
2001 2effd274 Fabrice Bellard
                             stream->pid);
2002 115329f1 Diego Biurrun
2003 2effd274 Fabrice Bellard
                    pid_stat = popen(ps_cmd, "r");
2004
                    if (pid_stat) {
2005
                        char cpuperc[10];
2006
                        char cpuused[64];
2007 115329f1 Diego Biurrun
2008
                        if (fscanf(pid_stat, "%10s %64s", cpuperc,
2009 2effd274 Fabrice Bellard
                                   cpuused) == 2) {
2010 d9d86e00 Anton Khirnov
                            avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2011 2effd274 Fabrice Bellard
                                         cpuperc, cpuused);
2012
                        }
2013
                        fclose(pid_stat);
2014 cde25790 Philip Gladstone
                    }
2015
                }
2016
#endif
2017
2018 d9d86e00 Anton Khirnov
                avio_printf(pb, "<p>");
2019 cde25790 Philip Gladstone
            }
2020 d9d86e00 Anton Khirnov
            avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
2021 a6e14edd Philip Gladstone
2022
            for (i = 0; i < stream->nb_streams; i++) {
2023
                AVStream *st = stream->streams[i];
2024 01f4895c Michael Niedermayer
                AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2025 b29f97d1 Zdenek Kabelac
                const char *type = "unknown";
2026 b582f314 Philip Gladstone
                char parameters[64];
2027
2028
                parameters[0] = 0;
2029 a6e14edd Philip Gladstone
2030 01f4895c Michael Niedermayer
                switch(st->codec->codec_type) {
2031 72415b2a Stefano Sabatini
                case AVMEDIA_TYPE_AUDIO:
2032 a6e14edd Philip Gladstone
                    type = "audio";
2033 acdc8520 Alex Beregszaszi
                    snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2034 a6e14edd Philip Gladstone
                    break;
2035 72415b2a Stefano Sabatini
                case AVMEDIA_TYPE_VIDEO:
2036 a6e14edd Philip Gladstone
                    type = "video";
2037 01f4895c Michael Niedermayer
                    snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2038
                                st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2039 a6e14edd Philip Gladstone
                    break;
2040
                default:
2041 0f4e8165 Ronald S. Bultje
                    abort();
2042 a6e14edd Philip Gladstone
                }
2043 d9d86e00 Anton Khirnov
                avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2044 01f4895c Michael Niedermayer
                        i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2045 a6e14edd Philip Gladstone
            }
2046 d9d86e00 Anton Khirnov
            avio_printf(pb, "</table>\n");
2047 a6e14edd Philip Gladstone
2048 115329f1 Diego Biurrun
        }
2049 a6e14edd Philip Gladstone
        stream = stream->next;
2050
    }
2051 115329f1 Diego Biurrun
2052 85f07f22 Fabrice Bellard
    /* connection status */
2053 d9d86e00 Anton Khirnov
    avio_printf(pb, "<h2>Connection Status</h2>\n");
2054 85f07f22 Fabrice Bellard
2055 d9d86e00 Anton Khirnov
    avio_printf(pb, "Number of connections: %d / %d<br>\n",
2056 85f07f22 Fabrice Bellard
                 nb_connections, nb_max_connections);
2057
2058 d9d86e00 Anton Khirnov
    avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2059 6edd6884 Fabrice Bellard
                 current_bandwidth, max_bandwidth);
2060 42a63c6a Philip Gladstone
2061 d9d86e00 Anton Khirnov
    avio_printf(pb, "<table>\n");
2062
    avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2063 85f07f22 Fabrice Bellard
    c1 = first_http_ctx;
2064
    i = 0;
2065 2effd274 Fabrice Bellard
    while (c1 != NULL) {
2066 cde25790 Philip Gladstone
        int bitrate;
2067
        int j;
2068
2069
        bitrate = 0;
2070 2effd274 Fabrice Bellard
        if (c1->stream) {
2071
            for (j = 0; j < c1->stream->nb_streams; j++) {
2072 2d563d2f Alex Beregszaszi
                if (!c1->stream->feed)
2073 01f4895c Michael Niedermayer
                    bitrate += c1->stream->streams[j]->codec->bit_rate;
2074 2d563d2f Alex Beregszaszi
                else if (c1->feed_streams[j] >= 0)
2075
                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2076 cde25790 Philip Gladstone
            }
2077
        }
2078
2079 85f07f22 Fabrice Bellard
        i++;
2080
        p = inet_ntoa(c1->from_addr.sin_addr);
2081 d9d86e00 Anton Khirnov
        avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2082 115329f1 Diego Biurrun
                    i,
2083
                    c1->stream ? c1->stream->filename : "",
2084 2effd274 Fabrice Bellard
                    c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2085 115329f1 Diego Biurrun
                    p,
2086 2effd274 Fabrice Bellard
                    c1->protocol,
2087
                    http_state[c1->state]);
2088
        fmt_bytecount(pb, bitrate);
2089 d9d86e00 Anton Khirnov
        avio_printf(pb, "<td align=right>");
2090 2effd274 Fabrice Bellard
        fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2091 d9d86e00 Anton Khirnov
        avio_printf(pb, "<td align=right>");
2092 2effd274 Fabrice Bellard
        fmt_bytecount(pb, c1->data_count);
2093 d9d86e00 Anton Khirnov
        avio_printf(pb, "\n");
2094 85f07f22 Fabrice Bellard
        c1 = c1->next;
2095
    }
2096 d9d86e00 Anton Khirnov
    avio_printf(pb, "</table>\n");
2097 115329f1 Diego Biurrun
2098 85f07f22 Fabrice Bellard
    /* date */
2099
    ti = time(NULL);
2100
    p = ctime(&ti);
2101 d9d86e00 Anton Khirnov
    avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2102
    avio_printf(pb, "</body>\n</html>\n");
2103 85f07f22 Fabrice Bellard
2104 2effd274 Fabrice Bellard
    len = url_close_dyn_buf(pb, &c->pb_buffer);
2105
    c->buffer_ptr = c->pb_buffer;
2106
    c->buffer_end = c->pb_buffer + len;
2107 85f07f22 Fabrice Bellard
}
2108
2109 2effd274 Fabrice Bellard
/* check if the parser needs to be opened for stream i */
2110
static void open_parser(AVFormatContext *s, int i)
2111 85f07f22 Fabrice Bellard
{
2112 2effd274 Fabrice Bellard
    AVStream *st = s->streams[i];
2113
    AVCodec *codec;
2114 31def229 Philip Gladstone
2115 01f4895c Michael Niedermayer
    if (!st->codec->codec) {
2116
        codec = avcodec_find_decoder(st->codec->codec_id);
2117 2effd274 Fabrice Bellard
        if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
2118 01f4895c Michael Niedermayer
            st->codec->parse_only = 1;
2119 611c5741 Alex Beregszaszi
            if (avcodec_open(st->codec, codec) < 0)
2120 01f4895c Michael Niedermayer
                st->codec->parse_only = 0;
2121 cde25790 Philip Gladstone
        }
2122
    }
2123 85f07f22 Fabrice Bellard
}
2124
2125
static int open_input_stream(HTTPContext *c, const char *info)
2126
{
2127
    char buf[128];
2128
    char input_filename[1024];
2129
    AVFormatContext *s;
2130 c351cc7f Baptiste Coudurier
    int buf_size, i, ret;
2131 0c1a9eda Zdenek Kabelac
    int64_t stream_pos;
2132 85f07f22 Fabrice Bellard
2133
    /* find file name */
2134
    if (c->stream->feed) {
2135
        strcpy(input_filename, c->stream->feed->feed_filename);
2136
        buf_size = FFM_PACKET_SIZE;
2137
        /* compute position (absolute time) */
2138 ab0287fc Anton Khirnov
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2139 9fcae973 Anton Khirnov
            if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2140
                return ret;
2141 ab0287fc Anton Khirnov
        } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2142 f747e6d3 Philip Gladstone
            int prebuffer = strtol(buf, 0, 10);
2143 0c1a9eda Zdenek Kabelac
            stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2144 611c5741 Alex Beregszaszi
        } else
2145 0c1a9eda Zdenek Kabelac
            stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2146 85f07f22 Fabrice Bellard
    } else {
2147
        strcpy(input_filename, c->stream->feed_filename);
2148
        buf_size = 0;
2149
        /* compute position (relative time) */
2150 ab0287fc Anton Khirnov
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2151 9fcae973 Anton Khirnov
            if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2152
                return ret;
2153 ace21da3 Baptiste Coudurier
        } else
2154 85f07f22 Fabrice Bellard
            stream_pos = 0;
2155
    }
2156
    if (input_filename[0] == '\0')
2157
        return -1;
2158
2159
    /* open stream */
2160 c351cc7f Baptiste Coudurier
    if ((ret = av_open_input_file(&s, input_filename, c->stream->ifmt,
2161
                                  buf_size, c->stream->ap_in)) < 0) {
2162
        http_log("could not open %s: %d\n", input_filename, ret);
2163 85f07f22 Fabrice Bellard
        return -1;
2164 2effd274 Fabrice Bellard
    }
2165 9dc0bc3d Luca Abeni
    s->flags |= AVFMT_FLAG_GENPTS;
2166 85f07f22 Fabrice Bellard
    c->fmt_in = s;
2167 85fe4ae0 Baptiste Coudurier
    if (strcmp(s->iformat->name, "ffm") && av_find_stream_info(c->fmt_in) < 0) {
2168 20f93c3c Baptiste Coudurier
        http_log("Could not find stream info '%s'\n", input_filename);
2169
        av_close_input_file(s);
2170
        return -1;
2171
    }
2172 115329f1 Diego Biurrun
2173 2effd274 Fabrice Bellard
    /* open each parser */
2174
    for(i=0;i<s->nb_streams;i++)
2175
        open_parser(s, i);
2176
2177
    /* choose stream as clock source (we favorize video stream if
2178
       present) for packet sending */
2179
    c->pts_stream_index = 0;
2180
    for(i=0;i<c->stream->nb_streams;i++) {
2181 115329f1 Diego Biurrun
        if (c->pts_stream_index == 0 &&
2182 72415b2a Stefano Sabatini
            c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2183 2effd274 Fabrice Bellard
            c->pts_stream_index = i;
2184
        }
2185
    }
2186 85f07f22 Fabrice Bellard
2187 e8d27bc3 Philip Gladstone
#if 1
2188 611c5741 Alex Beregszaszi
    if (c->fmt_in->iformat->read_seek)
2189 60a04f7f Baptiste Coudurier
        av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2190 e240a0bb Fabrice Bellard
#endif
2191 2effd274 Fabrice Bellard
    /* set the start time (needed for maxtime and RTP packet timing) */
2192
    c->start_time = cur_time;
2193
    c->first_pts = AV_NOPTS_VALUE;
2194 85f07f22 Fabrice Bellard
    return 0;
2195
}
2196
2197 e240a0bb Fabrice Bellard
/* return the server clock (in us) */
2198
static int64_t get_server_clock(HTTPContext *c)
2199 2effd274 Fabrice Bellard
{
2200 e240a0bb Fabrice Bellard
    /* compute current pts value from system time */
2201 c3f58185 Alex Beregszaszi
    return (cur_time - c->start_time) * 1000;
2202 2effd274 Fabrice Bellard
}
2203
2204 e240a0bb Fabrice Bellard
/* return the estimated time at which the current packet must be sent
2205
   (in us) */
2206
static int64_t get_packet_send_clock(HTTPContext *c)
2207 2effd274 Fabrice Bellard
{
2208 e240a0bb Fabrice Bellard
    int bytes_left, bytes_sent, frame_bytes;
2209 115329f1 Diego Biurrun
2210 e240a0bb Fabrice Bellard
    frame_bytes = c->cur_frame_bytes;
2211 611c5741 Alex Beregszaszi
    if (frame_bytes <= 0)
2212 e240a0bb Fabrice Bellard
        return c->cur_pts;
2213 611c5741 Alex Beregszaszi
    else {
2214 e240a0bb Fabrice Bellard
        bytes_left = c->buffer_end - c->buffer_ptr;
2215
        bytes_sent = frame_bytes - bytes_left;
2216
        return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2217 2effd274 Fabrice Bellard
    }
2218
}
2219
2220
2221
static int http_prepare_data(HTTPContext *c)
2222
{
2223
    int i, len, ret;
2224
    AVFormatContext *ctx;
2225
2226 bc351386 Fabrice Bellard
    av_freep(&c->pb_buffer);
2227 2effd274 Fabrice Bellard
    switch(c->state) {
2228
    case HTTPSTATE_SEND_DATA_HEADER:
2229
        memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2230 2ef6c124 Stefano Sabatini
        av_metadata_set2(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2231
        av_metadata_set2(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2232
        av_metadata_set2(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2233
        av_metadata_set2(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2234 2effd274 Fabrice Bellard
2235 3d9cc27d Baptiste Coudurier
        for(i=0;i<c->stream->nb_streams;i++) {
2236 2effd274 Fabrice Bellard
            AVStream *st;
2237 bb270c08 Diego Biurrun
            AVStream *src;
2238 2effd274 Fabrice Bellard
            st = av_mallocz(sizeof(AVStream));
2239
            c->fmt_ctx.streams[i] = st;
2240
            /* if file or feed, then just take streams from FFStream struct */
2241 115329f1 Diego Biurrun
            if (!c->stream->feed ||
2242 2effd274 Fabrice Bellard
                c->stream->feed == c->stream)
2243 7c054ea7 Philip Gladstone
                src = c->stream->streams[i];
2244 2effd274 Fabrice Bellard
            else
2245 7c054ea7 Philip Gladstone
                src = c->stream->feed->streams[c->stream->feed_streams[i]];
2246
2247 bb270c08 Diego Biurrun
            *st = *src;
2248
            st->priv_data = 0;
2249 01f4895c Michael Niedermayer
            st->codec->frame_number = 0; /* XXX: should be done in
2250 2effd274 Fabrice Bellard
                                           AVStream, not in codec */
2251
        }
2252 3d9cc27d Baptiste Coudurier
        /* set output format parameters */
2253
        c->fmt_ctx.oformat = c->stream->fmt;
2254
        c->fmt_ctx.nb_streams = c->stream->nb_streams;
2255
2256 2effd274 Fabrice Bellard
        c->got_key_frame = 0;
2257
2258
        /* prepare header and save header data in a stream */
2259
        if (url_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2260
            /* XXX: potential leak */
2261
            return -1;
2262
        }
2263 899681cd Björn Axelsson
        c->fmt_ctx.pb->is_streamed = 1;
2264 2effd274 Fabrice Bellard
2265 8aae202e Baptiste Coudurier
        /*
2266
         * HACK to avoid mpeg ps muxer to spit many underflow errors
2267
         * Default value from FFmpeg
2268
         * Try to set it use configuration option
2269
         */
2270
        c->fmt_ctx.preload   = (int)(0.5*AV_TIME_BASE);
2271
        c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2272
2273 3c27199b Fabrice Bellard
        av_set_parameters(&c->fmt_ctx, NULL);
2274 929a9b75 Baptiste Coudurier
        if (av_write_header(&c->fmt_ctx) < 0) {
2275
            http_log("Error writing output header\n");
2276 f75cdda7 Alex Beregszaszi
            return -1;
2277 929a9b75 Baptiste Coudurier
        }
2278 ea4f8aab Howard Chu
        av_metadata_free(&c->fmt_ctx.metadata);
2279 2effd274 Fabrice Bellard
2280 899681cd Björn Axelsson
        len = url_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2281 2effd274 Fabrice Bellard
        c->buffer_ptr = c->pb_buffer;
2282
        c->buffer_end = c->pb_buffer + len;
2283
2284
        c->state = HTTPSTATE_SEND_DATA;
2285 85f07f22 Fabrice Bellard
        c->last_packet_sent = 0;
2286
        break;
2287
    case HTTPSTATE_SEND_DATA:
2288
        /* find a new packet */
2289 3b371676 Baptiste Coudurier
        /* read a packet from the input stream */
2290
        if (c->stream->feed)
2291
            ffm_set_write_index(c->fmt_in,
2292
                                c->stream->feed->feed_write_index,
2293
                                c->stream->feed->feed_size);
2294
2295
        if (c->stream->max_time &&
2296
            c->stream->max_time + c->start_time - cur_time < 0)
2297
            /* We have timed out */
2298
            c->state = HTTPSTATE_SEND_DATA_TRAILER;
2299
        else {
2300
            AVPacket pkt;
2301
        redo:
2302 d9aac267 Howard Chu
            ret = av_read_frame(c->fmt_in, &pkt);
2303
            if (ret < 0) {
2304
                if (c->stream->feed) {
2305 3b371676 Baptiste Coudurier
                    /* if coming from feed, it means we reached the end of the
2306
                       ffm file, so must wait for more data */
2307
                    c->state = HTTPSTATE_WAIT_FEED;
2308
                    return 1; /* state changed */
2309 d9aac267 Howard Chu
                } else if (ret == AVERROR(EAGAIN)) {
2310
                    /* input not ready, come back later */
2311
                    return 0;
2312 2effd274 Fabrice Bellard
                } else {
2313 3b371676 Baptiste Coudurier
                    if (c->stream->loop) {
2314
                        av_close_input_file(c->fmt_in);
2315
                        c->fmt_in = NULL;
2316
                        if (open_input_stream(c, "") < 0)
2317
                            goto no_loop;
2318
                        goto redo;
2319
                    } else {
2320
                    no_loop:
2321
                        /* must send trailer now because eof or error */
2322
                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2323 1bc1cfdd Giancarlo Formicuccia
                    }
2324 3b371676 Baptiste Coudurier
                }
2325
            } else {
2326 084a8912 Baptiste Coudurier
                int source_index = pkt.stream_index;
2327 3b371676 Baptiste Coudurier
                /* update first pts if needed */
2328
                if (c->first_pts == AV_NOPTS_VALUE) {
2329
                    c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2330
                    c->start_time = cur_time;
2331
                }
2332
                /* send it to the appropriate stream */
2333
                if (c->stream->feed) {
2334
                    /* if coming from a feed, select the right stream */
2335
                    if (c->switch_pending) {
2336
                        c->switch_pending = 0;
2337 cde25790 Philip Gladstone
                        for(i=0;i<c->stream->nb_streams;i++) {
2338 3b371676 Baptiste Coudurier
                            if (c->switch_feed_streams[i] == pkt.stream_index)
2339 cc947f04 Jean-Daniel Dupas
                                if (pkt.flags & AV_PKT_FLAG_KEY)
2340 305ca590 Reinhard Tartler
                                    c->switch_feed_streams[i] = -1;
2341 3b371676 Baptiste Coudurier
                            if (c->switch_feed_streams[i] >= 0)
2342
                                c->switch_pending = 1;
2343 cde25790 Philip Gladstone
                        }
2344 3b371676 Baptiste Coudurier
                    }
2345
                    for(i=0;i<c->stream->nb_streams;i++) {
2346 a5ba4ced Martin Storsjö
                        if (c->stream->feed_streams[i] == pkt.stream_index) {
2347 78728064 Baptiste Coudurier
                            AVStream *st = c->fmt_in->streams[source_index];
2348 3b371676 Baptiste Coudurier
                            pkt.stream_index = i;
2349 cc947f04 Jean-Daniel Dupas
                            if (pkt.flags & AV_PKT_FLAG_KEY &&
2350 72415b2a Stefano Sabatini
                                (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2351 180b7026 Baptiste Coudurier
                                 c->stream->nb_streams == 1))
2352 0332f549 Baptiste Coudurier
                                c->got_key_frame = 1;
2353
                            if (!c->stream->send_on_key || c->got_key_frame)
2354 3b371676 Baptiste Coudurier
                                goto send_it;
2355
                        }
2356
                    }
2357
                } else {
2358
                    AVCodecContext *codec;
2359 dc3a6a36 Baptiste Coudurier
                    AVStream *ist, *ost;
2360
                send_it:
2361
                    ist = c->fmt_in->streams[source_index];
2362 3b371676 Baptiste Coudurier
                    /* specific handling for RTP: we use several
2363
                       output stream (one for each RTP
2364
                       connection). XXX: need more abstract handling */
2365
                    if (c->is_packetized) {
2366
                        /* compute send time and duration */
2367 8f56ccca Baptiste Coudurier
                        c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2368 f475f35f Martin Storsjö
                        c->cur_pts -= c->first_pts;
2369 8f56ccca Baptiste Coudurier
                        c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2370 3b371676 Baptiste Coudurier
                        /* find RTP context */
2371
                        c->packet_stream_index = pkt.stream_index;
2372
                        ctx = c->rtp_ctx[c->packet_stream_index];
2373
                        if(!ctx) {
2374 8a0b55ff Baptiste Coudurier
                            av_free_packet(&pkt);
2375 3b371676 Baptiste Coudurier
                            break;
2376 8a0b55ff Baptiste Coudurier
                        }
2377 3b371676 Baptiste Coudurier
                        codec = ctx->streams[0]->codec;
2378
                        /* only one stream per RTP connection */
2379
                        pkt.stream_index = 0;
2380
                    } else {
2381
                        ctx = &c->fmt_ctx;
2382
                        /* Fudge here */
2383 3ab29d8e Baptiste Coudurier
                        codec = ctx->streams[pkt.stream_index]->codec;
2384 3b371676 Baptiste Coudurier
                    }
2385
2386
                    if (c->is_packetized) {
2387
                        int max_packet_size;
2388 90abbdba Ronald S. Bultje
                        if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2389 3b371676 Baptiste Coudurier
                            max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2390
                        else
2391
                            max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
2392
                        ret = url_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2393
                    } else {
2394
                        ret = url_open_dyn_buf(&ctx->pb);
2395
                    }
2396
                    if (ret < 0) {
2397
                        /* XXX: potential leak */
2398
                        return -1;
2399
                    }
2400 3ab29d8e Baptiste Coudurier
                    ost = ctx->streams[pkt.stream_index];
2401
2402 b0675954 Baptiste Coudurier
                    ctx->pb->is_streamed = 1;
2403 3b371676 Baptiste Coudurier
                    if (pkt.dts != AV_NOPTS_VALUE)
2404 d80904cc Baptiste Coudurier
                        pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2405 3b371676 Baptiste Coudurier
                    if (pkt.pts != AV_NOPTS_VALUE)
2406 d80904cc Baptiste Coudurier
                        pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2407
                    pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2408 3766ed72 Baptiste Coudurier
                    if (av_write_frame(ctx, &pkt) < 0) {
2409
                        http_log("Error writing frame to output\n");
2410 3b371676 Baptiste Coudurier
                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2411 3766ed72 Baptiste Coudurier
                    }
2412 3b371676 Baptiste Coudurier
2413
                    len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
2414
                    c->cur_frame_bytes = len;
2415
                    c->buffer_ptr = c->pb_buffer;
2416
                    c->buffer_end = c->pb_buffer + len;
2417
2418
                    codec->frame_number++;
2419
                    if (len == 0) {
2420
                        av_free_packet(&pkt);
2421
                        goto redo;
2422 f747e6d3 Philip Gladstone
                    }
2423 85f07f22 Fabrice Bellard
                }
2424 3b371676 Baptiste Coudurier
                av_free_packet(&pkt);
2425 85f07f22 Fabrice Bellard
            }
2426 3b371676 Baptiste Coudurier
        }
2427 85f07f22 Fabrice Bellard
        break;
2428
    default:
2429
    case HTTPSTATE_SEND_DATA_TRAILER:
2430
        /* last packet test ? */
2431 2effd274 Fabrice Bellard
        if (c->last_packet_sent || c->is_packetized)
2432 85f07f22 Fabrice Bellard
            return -1;
2433 2effd274 Fabrice Bellard
        ctx = &c->fmt_ctx;
2434 85f07f22 Fabrice Bellard
        /* prepare header */
2435 2effd274 Fabrice Bellard
        if (url_open_dyn_buf(&ctx->pb) < 0) {
2436
            /* XXX: potential leak */
2437
            return -1;
2438
        }
2439 58bd615f Baptiste Coudurier
        c->fmt_ctx.pb->is_streamed = 1;
2440 2effd274 Fabrice Bellard
        av_write_trailer(ctx);
2441 899681cd Björn Axelsson
        len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
2442 2effd274 Fabrice Bellard
        c->buffer_ptr = c->pb_buffer;
2443
        c->buffer_end = c->pb_buffer + len;
2444
2445 85f07f22 Fabrice Bellard
        c->last_packet_sent = 1;
2446
        break;
2447
    }
2448
    return 0;
2449
}
2450
2451
/* should convert the format at the same time */
2452 bc351386 Fabrice Bellard
/* send data starting at c->buffer_ptr to the output connection
2453
   (either UDP or TCP connection) */
2454 5eb765ef Philip Gladstone
static int http_send_data(HTTPContext *c)
2455 85f07f22 Fabrice Bellard
{
2456 e240a0bb Fabrice Bellard
    int len, ret;
2457 85f07f22 Fabrice Bellard
2458 bc351386 Fabrice Bellard
    for(;;) {
2459
        if (c->buffer_ptr >= c->buffer_end) {
2460
            ret = http_prepare_data(c);
2461
            if (ret < 0)
2462
                return -1;
2463 611c5741 Alex Beregszaszi
            else if (ret != 0)
2464 bc351386 Fabrice Bellard
                /* state change requested */
2465
                break;
2466 2effd274 Fabrice Bellard
        } else {
2467 bc351386 Fabrice Bellard
            if (c->is_packetized) {
2468
                /* RTP data output */
2469
                len = c->buffer_end - c->buffer_ptr;
2470
                if (len < 4) {
2471
                    /* fail safe - should never happen */
2472
                fail1:
2473
                    c->buffer_ptr = c->buffer_end;
2474 2effd274 Fabrice Bellard
                    return 0;
2475
                }
2476 bc351386 Fabrice Bellard
                len = (c->buffer_ptr[0] << 24) |
2477
                    (c->buffer_ptr[1] << 16) |
2478
                    (c->buffer_ptr[2] << 8) |
2479
                    (c->buffer_ptr[3]);
2480
                if (len > (c->buffer_end - c->buffer_ptr))
2481
                    goto fail1;
2482 e240a0bb Fabrice Bellard
                if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2483
                    /* nothing to send yet: we can wait */
2484
                    return 0;
2485
                }
2486
2487
                c->data_count += len;
2488
                update_datarate(&c->datarate, c->data_count);
2489
                if (c->stream)
2490
                    c->stream->bytes_served += len;
2491
2492 90abbdba Ronald S. Bultje
                if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2493 bc351386 Fabrice Bellard
                    /* RTP packets are sent inside the RTSP TCP connection */
2494 ae628ec1 Anton Khirnov
                    AVIOContext *pb;
2495 bc351386 Fabrice Bellard
                    int interleaved_index, size;
2496
                    uint8_t header[4];
2497
                    HTTPContext *rtsp_c;
2498 115329f1 Diego Biurrun
2499 bc351386 Fabrice Bellard
                    rtsp_c = c->rtsp_c;
2500
                    /* if no RTSP connection left, error */
2501
                    if (!rtsp_c)
2502
                        return -1;
2503
                    /* if already sending something, then wait. */
2504 611c5741 Alex Beregszaszi
                    if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2505 bc351386 Fabrice Bellard
                        break;
2506 899681cd Björn Axelsson
                    if (url_open_dyn_buf(&pb) < 0)
2507 bc351386 Fabrice Bellard
                        goto fail1;
2508
                    interleaved_index = c->packet_stream_index * 2;
2509
                    /* RTCP packets are sent at odd indexes */
2510
                    if (c->buffer_ptr[1] == 200)
2511
                        interleaved_index++;
2512
                    /* write RTSP TCP header */
2513
                    header[0] = '$';
2514
                    header[1] = interleaved_index;
2515
                    header[2] = len >> 8;
2516
                    header[3] = len;
2517 77eb5504 Anton Khirnov
                    avio_write(pb, header, 4);
2518 bc351386 Fabrice Bellard
                    /* write RTP packet data */
2519
                    c->buffer_ptr += 4;
2520 77eb5504 Anton Khirnov
                    avio_write(pb, c->buffer_ptr, len);
2521 bc351386 Fabrice Bellard
                    size = url_close_dyn_buf(pb, &c->packet_buffer);
2522
                    /* prepare asynchronous TCP sending */
2523
                    rtsp_c->packet_buffer_ptr = c->packet_buffer;
2524
                    rtsp_c->packet_buffer_end = c->packet_buffer + size;
2525 e240a0bb Fabrice Bellard
                    c->buffer_ptr += len;
2526 115329f1 Diego Biurrun
2527 e240a0bb Fabrice Bellard
                    /* send everything we can NOW */
2528 c60202df Alex Beregszaszi
                    len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2529
                                rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2530 611c5741 Alex Beregszaszi
                    if (len > 0)
2531 e240a0bb Fabrice Bellard
                        rtsp_c->packet_buffer_ptr += len;
2532
                    if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2533
                        /* if we could not send all the data, we will
2534
                           send it later, so a new state is needed to
2535
                           "lock" the RTSP TCP connection */
2536
                        rtsp_c->state = RTSPSTATE_SEND_PACKET;
2537
                        break;
2538 611c5741 Alex Beregszaszi
                    } else
2539 e240a0bb Fabrice Bellard
                        /* all data has been sent */
2540
                        av_freep(&c->packet_buffer);
2541
                } else {
2542
                    /* send RTP packet directly in UDP */
2543 bc351386 Fabrice Bellard
                    c->buffer_ptr += 4;
2544 115329f1 Diego Biurrun
                    url_write(c->rtp_handles[c->packet_stream_index],
2545 bc351386 Fabrice Bellard
                              c->buffer_ptr, len);
2546 e240a0bb Fabrice Bellard
                    c->buffer_ptr += len;
2547
                    /* here we continue as we can send several packets per 10 ms slot */
2548 bc351386 Fabrice Bellard
                }
2549
            } else {
2550
                /* TCP data output */
2551 c60202df Alex Beregszaszi
                len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2552 bc351386 Fabrice Bellard
                if (len < 0) {
2553 28c4741a Martin Storsjö
                    if (ff_neterrno() != AVERROR(EAGAIN) &&
2554
                        ff_neterrno() != AVERROR(EINTR))
2555 bc351386 Fabrice Bellard
                        /* error : close connection */
2556
                        return -1;
2557 611c5741 Alex Beregszaszi
                    else
2558 bc351386 Fabrice Bellard
                        return 0;
2559 611c5741 Alex Beregszaszi
                } else
2560 bc351386 Fabrice Bellard
                    c->buffer_ptr += len;
2561 611c5741 Alex Beregszaszi
2562 e240a0bb Fabrice Bellard
                c->data_count += len;
2563
                update_datarate(&c->datarate, c->data_count);
2564
                if (c->stream)
2565
                    c->stream->bytes_served += len;
2566
                break;
2567 2effd274 Fabrice Bellard
            }
2568 85f07f22 Fabrice Bellard
        }
2569 bc351386 Fabrice Bellard
    } /* for(;;) */
2570 85f07f22 Fabrice Bellard
    return 0;
2571
}
2572
2573
static int http_start_receive_data(HTTPContext *c)
2574
{
2575
    int fd;
2576
2577
    if (c->stream->feed_opened)
2578
        return -1;
2579
2580 e322ea48 Philip Gladstone
    /* Don't permit writing to this one */
2581
    if (c->stream->readonly)
2582
        return -1;
2583
2584 85f07f22 Fabrice Bellard
    /* open feed */
2585
    fd = open(c->stream->feed_filename, O_RDWR);
2586 929a9b75 Baptiste Coudurier
    if (fd < 0) {
2587
        http_log("Error opening feeder file: %s\n", strerror(errno));
2588 85f07f22 Fabrice Bellard
        return -1;
2589 929a9b75 Baptiste Coudurier
    }
2590 85f07f22 Fabrice Bellard
    c->feed_fd = fd;
2591 115329f1 Diego Biurrun
2592 861ec13a Baptiste Coudurier
    if (c->stream->truncate) {
2593
        /* truncate feed file */
2594
        ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2595
        ftruncate(c->feed_fd, FFM_PACKET_SIZE);
2596
        http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2597
    } else {
2598 1f611549 Baptiste Coudurier
        if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2599
            http_log("Error reading write index from feed file: %s\n", strerror(errno));
2600
            return -1;
2601
        }
2602 861ec13a Baptiste Coudurier
    }
2603
2604 7e24aa0c Baptiste Coudurier
    c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2605 85f07f22 Fabrice Bellard
    c->stream->feed_size = lseek(fd, 0, SEEK_END);
2606
    lseek(fd, 0, SEEK_SET);
2607
2608
    /* init buffer input */
2609
    c->buffer_ptr = c->buffer;
2610
    c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2611
    c->stream->feed_opened = 1;
2612 fd7bec5e Måns Rullgård
    c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2613 85f07f22 Fabrice Bellard
    return 0;
2614
}
2615 115329f1 Diego Biurrun
2616 85f07f22 Fabrice Bellard
static int http_receive_data(HTTPContext *c)
2617
{
2618
    HTTPContext *c1;
2619 19c8c4ec Ronald S. Bultje
    int len, loop_run = 0;
2620 85f07f22 Fabrice Bellard
2621 19c8c4ec Ronald S. Bultje
    while (c->chunked_encoding && !c->chunk_size &&
2622
           c->buffer_end > c->buffer_ptr) {
2623
        /* read chunk header, if present */
2624
        len = recv(c->fd, c->buffer_ptr, 1, 0);
2625
2626
        if (len < 0) {
2627 28c4741a Martin Storsjö
            if (ff_neterrno() != AVERROR(EAGAIN) &&
2628
                ff_neterrno() != AVERROR(EINTR))
2629 19c8c4ec Ronald S. Bultje
                /* error : close connection */
2630
                goto fail;
2631 686d6f40 Howard Chu
            return 0;
2632 19c8c4ec Ronald S. Bultje
        } else if (len == 0) {
2633
            /* end of connection : close it */
2634
            goto fail;
2635
        } else if (c->buffer_ptr - c->buffer >= 2 &&
2636
                   !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2637
            c->chunk_size = strtol(c->buffer, 0, 16);
2638
            if (c->chunk_size == 0) // end of stream
2639
                goto fail;
2640
            c->buffer_ptr = c->buffer;
2641
            break;
2642
        } else if (++loop_run > 10) {
2643
            /* no chunk header, abort */
2644
            goto fail;
2645
        } else {
2646
            c->buffer_ptr++;
2647
        }
2648
    }
2649 a6e14edd Philip Gladstone
2650 19c8c4ec Ronald S. Bultje
    if (c->buffer_end > c->buffer_ptr) {
2651
        len = recv(c->fd, c->buffer_ptr,
2652
                   FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2653 a6e14edd Philip Gladstone
        if (len < 0) {
2654 28c4741a Martin Storsjö
            if (ff_neterrno() != AVERROR(EAGAIN) &&
2655
                ff_neterrno() != AVERROR(EINTR))
2656 a6e14edd Philip Gladstone
                /* error : close connection */
2657
                goto fail;
2658 611c5741 Alex Beregszaszi
        } else if (len == 0)
2659 a6e14edd Philip Gladstone
            /* end of connection : close it */
2660
            goto fail;
2661 611c5741 Alex Beregszaszi
        else {
2662 19c8c4ec Ronald S. Bultje
            c->chunk_size -= len;
2663 a6e14edd Philip Gladstone
            c->buffer_ptr += len;
2664
            c->data_count += len;
2665 5eb765ef Philip Gladstone
            update_datarate(&c->datarate, c->data_count);
2666 a6e14edd Philip Gladstone
        }
2667
    }
2668
2669 d445a7e9 Philip Gladstone
    if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2670
        if (c->buffer[0] != 'f' ||
2671
            c->buffer[1] != 'm') {
2672
            http_log("Feed stream has become desynchronized -- disconnecting\n");
2673
            goto fail;
2674
        }
2675
    }
2676
2677 85f07f22 Fabrice Bellard
    if (c->buffer_ptr >= c->buffer_end) {