Statistics
| Branch: | Revision:

ffmpeg / ffserver.c @ d370e3e9

History | View | Annotate | Download (156 KB)

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