Statistics
| Branch: | Revision:

ffmpeg / ffserver.c @ ca402f32

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