Statistics
| Branch: | Revision:

ffmpeg / ffserver.c @ a23c9c4a

History | View | Annotate | Download (147 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 0f4e8165 Ronald S. Bultje
#include "config.h"
23 3cf9ea7f Alex Beregszaszi
#ifndef HAVE_CLOSESOCKET
24 0f4e8165 Ronald S. Bultje
#define closesocket close
25
#endif
26
#include <string.h>
27
#include <stdlib.h>
28 773a21b8 Fabrice Bellard
#include "avformat.h"
29 c971ff19 Luca Abeni
#include "rtsp.h"
30
#include "rtp.h"
31 93115b82 Dave Yeo
#include "os_support.h"
32 773a21b8 Fabrice Bellard
33 85f07f22 Fabrice Bellard
#include <stdarg.h>
34
#include <unistd.h>
35
#include <fcntl.h>
36
#include <sys/ioctl.h>
37 b0c858d8 François Revol
#ifdef HAVE_SYS_POLL_H
38 85f07f22 Fabrice Bellard
#include <sys/poll.h>
39 b0c858d8 François Revol
#endif
40 85f07f22 Fabrice Bellard
#include <errno.h>
41
#include <sys/time.h>
42 4568325a Roman Shaposhnik
#undef time //needed because HAVE_AV_CONFIG_H is defined on top
43 85f07f22 Fabrice Bellard
#include <time.h>
44 5eb765ef Philip Gladstone
#include <sys/wait.h>
45 85f07f22 Fabrice Bellard
#include <signal.h>
46 18b67ae5 Måns Rullgård
#ifdef HAVE_DLFCN_H
47 2effd274 Fabrice Bellard
#include <dlfcn.h>
48 6638d424 Philip Gladstone
#endif
49 2effd274 Fabrice Bellard
50 0bdacf29 Alex Beregszaszi
#include "network.h"
51 f1cc88a5 Diego Biurrun
#include "version.h"
52 2effd274 Fabrice Bellard
#include "ffserver.h"
53 1df93ae9 Alex Beregszaszi
#include "random.h"
54 f7d78f36 Måns Rullgård
#include "avstring.h"
55 4ce5df08 Stefano Sabatini
#include "cmdutils.h"
56 85f07f22 Fabrice Bellard
57 c367d067 Michael Niedermayer
#undef exit
58
59 86074ed1 Stefano Sabatini
static const char program_name[] = "FFserver";
60
static const int program_birth_year = 2000;
61
62 85f07f22 Fabrice Bellard
/* maximum number of simultaneous HTTP connections */
63
#define HTTP_MAX_CONNECTIONS 2000
64
65
enum HTTPState {
66
    HTTPSTATE_WAIT_REQUEST,
67
    HTTPSTATE_SEND_HEADER,
68
    HTTPSTATE_SEND_DATA_HEADER,
69 2effd274 Fabrice Bellard
    HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
70 85f07f22 Fabrice Bellard
    HTTPSTATE_SEND_DATA_TRAILER,
71 115329f1 Diego Biurrun
    HTTPSTATE_RECEIVE_DATA,
72 2effd274 Fabrice Bellard
    HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
73
    HTTPSTATE_READY,
74
75
    RTSPSTATE_WAIT_REQUEST,
76
    RTSPSTATE_SEND_REPLY,
77 bc351386 Fabrice Bellard
    RTSPSTATE_SEND_PACKET,
78 85f07f22 Fabrice Bellard
};
79
80
const char *http_state[] = {
81 2effd274 Fabrice Bellard
    "HTTP_WAIT_REQUEST",
82
    "HTTP_SEND_HEADER",
83
84 85f07f22 Fabrice Bellard
    "SEND_DATA_HEADER",
85
    "SEND_DATA",
86
    "SEND_DATA_TRAILER",
87
    "RECEIVE_DATA",
88
    "WAIT_FEED",
89 2effd274 Fabrice Bellard
    "READY",
90
91
    "RTSP_WAIT_REQUEST",
92
    "RTSP_SEND_REPLY",
93 bc351386 Fabrice Bellard
    "RTSP_SEND_PACKET",
94 85f07f22 Fabrice Bellard
};
95
96 cde25790 Philip Gladstone
#define IOBUFFER_INIT_SIZE 8192
97 85f07f22 Fabrice Bellard
98
/* timeouts are in ms */
99 2effd274 Fabrice Bellard
#define HTTP_REQUEST_TIMEOUT (15 * 1000)
100
#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
101
102 85f07f22 Fabrice Bellard
#define SYNC_TIMEOUT (10 * 1000)
103
104 5eb765ef Philip Gladstone
typedef struct {
105 0c1a9eda Zdenek Kabelac
    int64_t count1, count2;
106 c3f58185 Alex Beregszaszi
    int64_t time1, time2;
107 5eb765ef Philip Gladstone
} DataRateData;
108
109 85f07f22 Fabrice Bellard
/* context associated with one connection */
110
typedef struct HTTPContext {
111
    enum HTTPState state;
112
    int fd; /* socket file descriptor */
113
    struct sockaddr_in from_addr; /* origin */
114
    struct pollfd *poll_entry; /* used when polling */
115 c3f58185 Alex Beregszaszi
    int64_t timeout;
116 0c1a9eda Zdenek Kabelac
    uint8_t *buffer_ptr, *buffer_end;
117 85f07f22 Fabrice Bellard
    int http_error;
118 edfdd798 Alex Beregszaszi
    int post;
119 85f07f22 Fabrice Bellard
    struct HTTPContext *next;
120 42a63c6a Philip Gladstone
    int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
121 0c1a9eda Zdenek Kabelac
    int64_t data_count;
122 85f07f22 Fabrice Bellard
    /* feed input */
123
    int feed_fd;
124
    /* input format handling */
125
    AVFormatContext *fmt_in;
126 c3f58185 Alex Beregszaszi
    int64_t start_time;            /* In milliseconds - this wraps fairly often */
127 0c1a9eda Zdenek Kabelac
    int64_t first_pts;            /* initial pts value */
128 e240a0bb Fabrice Bellard
    int64_t cur_pts;             /* current pts value from the stream in us */
129
    int64_t cur_frame_duration;  /* duration of the current frame in us */
130
    int cur_frame_bytes;       /* output frame size, needed to compute
131
                                  the time at which we send each
132
                                  packet */
133
    int pts_stream_index;        /* stream we choose as clock reference */
134
    int64_t cur_clock;           /* current clock reference value in us */
135 85f07f22 Fabrice Bellard
    /* output format handling */
136
    struct FFStream *stream;
137 cde25790 Philip Gladstone
    /* -1 is invalid stream */
138
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
139
    int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
140
    int switch_pending;
141 2effd274 Fabrice Bellard
    AVFormatContext fmt_ctx; /* instance of FFStream for one user */
142 85f07f22 Fabrice Bellard
    int last_packet_sent; /* true if last data packet was sent */
143 7434ba6d Philip Gladstone
    int suppress_log;
144 5eb765ef Philip Gladstone
    DataRateData datarate;
145 3120d2a2 Philip Gladstone
    int wmp_client_id;
146 7434ba6d Philip Gladstone
    char protocol[16];
147
    char method[16];
148
    char url[128];
149 cde25790 Philip Gladstone
    int buffer_size;
150 0c1a9eda Zdenek Kabelac
    uint8_t *buffer;
151 2effd274 Fabrice Bellard
    int is_packetized; /* if true, the stream is packetized */
152
    int packet_stream_index; /* current stream for output in state machine */
153 115329f1 Diego Biurrun
154 2effd274 Fabrice Bellard
    /* RTSP state specific */
155 0c1a9eda Zdenek Kabelac
    uint8_t *pb_buffer; /* XXX: use that in all the code */
156 2effd274 Fabrice Bellard
    ByteIOContext *pb;
157
    int seq; /* RTSP sequence number */
158 115329f1 Diego Biurrun
159 2effd274 Fabrice Bellard
    /* RTP state specific */
160
    enum RTSPProtocol rtp_protocol;
161
    char session_id[32]; /* session id */
162
    AVFormatContext *rtp_ctx[MAX_STREAMS];
163 e240a0bb Fabrice Bellard
164 bc351386 Fabrice Bellard
    /* RTP/UDP specific */
165
    URLContext *rtp_handles[MAX_STREAMS];
166
167
    /* RTP/TCP specific */
168
    struct HTTPContext *rtsp_c;
169
    uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
170 85f07f22 Fabrice Bellard
} HTTPContext;
171
172 a4d70941 Philip Gladstone
static AVFrame dummy_frame;
173
174 85f07f22 Fabrice Bellard
/* each generated stream is described here */
175
enum StreamType {
176
    STREAM_TYPE_LIVE,
177
    STREAM_TYPE_STATUS,
178 cde25790 Philip Gladstone
    STREAM_TYPE_REDIRECT,
179 85f07f22 Fabrice Bellard
};
180
181 8256c0a3 Philip Gladstone
enum IPAddressAction {
182
    IP_ALLOW = 1,
183
    IP_DENY,
184
};
185
186
typedef struct IPAddressACL {
187
    struct IPAddressACL *next;
188
    enum IPAddressAction action;
189 efa04ce2 Philip Gladstone
    /* These are in host order */
190 8256c0a3 Philip Gladstone
    struct in_addr first;
191
    struct in_addr last;
192
} IPAddressACL;
193
194 85f07f22 Fabrice Bellard
/* description of each stream of the ffserver.conf file */
195
typedef struct FFStream {
196
    enum StreamType stream_type;
197
    char filename[1024];     /* stream filename */
198 2effd274 Fabrice Bellard
    struct FFStream *feed;   /* feed we are using (can be null if
199
                                coming from file) */
200 e240a0bb Fabrice Bellard
    AVFormatParameters *ap_in; /* input parameters */
201
    AVInputFormat *ifmt;       /* if non NULL, force input format */
202 bd7cf6ad Fabrice Bellard
    AVOutputFormat *fmt;
203 8256c0a3 Philip Gladstone
    IPAddressACL *acl;
204 85f07f22 Fabrice Bellard
    int nb_streams;
205 42a63c6a Philip Gladstone
    int prebuffer;      /* Number of millseconds early to start */
206 c3f58185 Alex Beregszaszi
    int64_t max_time;      /* Number of milliseconds to run */
207 79c4ea3c Philip Gladstone
    int send_on_key;
208 85f07f22 Fabrice Bellard
    AVStream *streams[MAX_STREAMS];
209
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
210
    char feed_filename[1024]; /* file name of the feed storage, or
211
                                 input file name for a stream */
212 2ac887ba Philip Gladstone
    char author[512];
213
    char title[512];
214
    char copyright[512];
215
    char comment[512];
216 cde25790 Philip Gladstone
    pid_t pid;  /* Of ffmpeg process */
217 5eb765ef Philip Gladstone
    time_t pid_start;  /* Of ffmpeg process */
218 cde25790 Philip Gladstone
    char **child_argv;
219 85f07f22 Fabrice Bellard
    struct FFStream *next;
220 6edd6884 Fabrice Bellard
    int bandwidth; /* bandwidth, in kbits/s */
221 2effd274 Fabrice Bellard
    /* RTSP options */
222
    char *rtsp_option;
223 829ac53d Fabrice Bellard
    /* multicast specific */
224
    int is_multicast;
225
    struct in_addr multicast_ip;
226
    int multicast_port; /* first port used for multicast */
227 6edd6884 Fabrice Bellard
    int multicast_ttl;
228
    int loop; /* if true, send the stream in loops (only meaningful if file) */
229 829ac53d Fabrice Bellard
230 85f07f22 Fabrice Bellard
    /* feed specific */
231 2effd274 Fabrice Bellard
    int feed_opened;     /* true if someone is writing to the feed */
232 85f07f22 Fabrice Bellard
    int is_feed;         /* true if it is a feed */
233 e322ea48 Philip Gladstone
    int readonly;        /* True if writing is prohibited to the file */
234 a6e14edd Philip Gladstone
    int conns_served;
235 0c1a9eda Zdenek Kabelac
    int64_t bytes_served;
236 6b0bdc75 Alex Beregszaszi
    int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
237 8bfb108b Diego Biurrun
    int64_t feed_write_index;   /* current write position in feed (it wraps around) */
238 0c1a9eda Zdenek Kabelac
    int64_t feed_size;          /* current size of feed */
239 85f07f22 Fabrice Bellard
    struct FFStream *next_feed;
240
} FFStream;
241
242
typedef struct FeedData {
243
    long long data_count;
244 8bfb108b Diego Biurrun
    float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
245 85f07f22 Fabrice Bellard
} FeedData;
246
247 18405874 Alex Beregszaszi
static struct sockaddr_in my_http_addr;
248
static struct sockaddr_in my_rtsp_addr;
249 2effd274 Fabrice Bellard
250 33f5e2ec Alex Beregszaszi
static char logfilename[1024];
251
static HTTPContext *first_http_ctx;
252
static FFStream *first_feed;   /* contains only feeds */
253
static FFStream *first_stream; /* contains all streams, including feeds */
254 85f07f22 Fabrice Bellard
255 2effd274 Fabrice Bellard
static void new_connection(int server_fd, int is_rtsp);
256
static void close_connection(HTTPContext *c);
257
258
/* HTTP handling */
259
static int handle_connection(HTTPContext *c);
260 85f07f22 Fabrice Bellard
static int http_parse_request(HTTPContext *c);
261 5eb765ef Philip Gladstone
static int http_send_data(HTTPContext *c);
262 85f07f22 Fabrice Bellard
static void compute_stats(HTTPContext *c);
263
static int open_input_stream(HTTPContext *c, const char *info);
264
static int http_start_receive_data(HTTPContext *c);
265
static int http_receive_data(HTTPContext *c);
266 2effd274 Fabrice Bellard
267
/* RTSP handling */
268
static int rtsp_parse_request(HTTPContext *c);
269
static void rtsp_cmd_describe(HTTPContext *c, const char *url);
270 0df65975 Andriy Rysin
static void rtsp_cmd_options(HTTPContext *c, const char *url);
271 2effd274 Fabrice Bellard
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPHeader *h);
272
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPHeader *h);
273
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h);
274
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h);
275
276 829ac53d Fabrice Bellard
/* SDP handling */
277 115329f1 Diego Biurrun
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
278 829ac53d Fabrice Bellard
                                   struct in_addr my_ip);
279
280 2effd274 Fabrice Bellard
/* RTP handling */
281 115329f1 Diego Biurrun
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
282 bc351386 Fabrice Bellard
                                       FFStream *stream, const char *session_id,
283
                                       enum RTSPProtocol rtp_protocol);
284 115329f1 Diego Biurrun
static int rtp_new_av_stream(HTTPContext *c,
285 bc351386 Fabrice Bellard
                             int stream_index, struct sockaddr_in *dest_addr,
286
                             HTTPContext *rtsp_c);
287 85f07f22 Fabrice Bellard
288 cde25790 Philip Gladstone
static const char *my_program_name;
289 d6562d2c Philip Gladstone
static const char *my_program_dir;
290 cde25790 Philip Gladstone
291 2ac887ba Philip Gladstone
static int ffserver_debug;
292 2effd274 Fabrice Bellard
static int ffserver_daemon;
293 2ac887ba Philip Gladstone
static int no_launch;
294 5eb765ef Philip Gladstone
static int need_to_start_children;
295 2ac887ba Philip Gladstone
296 33f5e2ec Alex Beregszaszi
static int nb_max_connections;
297
static int nb_connections;
298 85f07f22 Fabrice Bellard
299 33f5e2ec Alex Beregszaszi
static int max_bandwidth;
300
static int current_bandwidth;
301 42a63c6a Philip Gladstone
302 c3f58185 Alex Beregszaszi
static int64_t cur_time;           // Making this global saves on passing it around everywhere
303 5eb765ef Philip Gladstone
304 1df93ae9 Alex Beregszaszi
static AVRandomState random_state;
305
306 85f07f22 Fabrice Bellard
static FILE *logfile = NULL;
307
308 115329f1 Diego Biurrun
static void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...)
309 85f07f22 Fabrice Bellard
{
310
    va_list ap;
311
    va_start(ap, fmt);
312 115329f1 Diego Biurrun
313 7434ba6d Philip Gladstone
    if (logfile) {
314 85f07f22 Fabrice Bellard
        vfprintf(logfile, fmt, ap);
315 7434ba6d Philip Gladstone
        fflush(logfile);
316
    }
317 85f07f22 Fabrice Bellard
    va_end(ap);
318
}
319
320 6edd6884 Fabrice Bellard
static char *ctime1(char *buf2)
321 7434ba6d Philip Gladstone
{
322
    time_t ti;
323 6edd6884 Fabrice Bellard
    char *p;
324 7434ba6d Philip Gladstone
325
    ti = time(NULL);
326
    p = ctime(&ti);
327
    strcpy(buf2, p);
328
    p = buf2 + strlen(p) - 1;
329
    if (*p == '\n')
330
        *p = '\0';
331 6edd6884 Fabrice Bellard
    return buf2;
332
}
333
334
static void log_connection(HTTPContext *c)
335
{
336
    char buf2[32];
337
338 115329f1 Diego Biurrun
    if (c->suppress_log)
339 6edd6884 Fabrice Bellard
        return;
340
341 115329f1 Diego Biurrun
    http_log("%s - - [%s] \"%s %s %s\" %d %"PRId64"\n",
342
             inet_ntoa(c->from_addr.sin_addr),
343
             ctime1(buf2), c->method, c->url,
344 6edd6884 Fabrice Bellard
             c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
345 cde25790 Philip Gladstone
}
346
347 0c1a9eda Zdenek Kabelac
static void update_datarate(DataRateData *drd, int64_t count)
348 5eb765ef Philip Gladstone
{
349
    if (!drd->time1 && !drd->count1) {
350
        drd->time1 = drd->time2 = cur_time;
351
        drd->count1 = drd->count2 = count;
352 eeffbdea Alex Beregszaszi
    } else if (cur_time - drd->time2 > 5000) {
353 33a4ecbe Alex Beregszaszi
        drd->time1 = drd->time2;
354
        drd->count1 = drd->count2;
355
        drd->time2 = cur_time;
356
        drd->count2 = count;
357 5eb765ef Philip Gladstone
    }
358
}
359
360
/* In bytes per second */
361 0c1a9eda Zdenek Kabelac
static int compute_datarate(DataRateData *drd, int64_t count)
362 5eb765ef Philip Gladstone
{
363
    if (cur_time == drd->time1)
364
        return 0;
365 115329f1 Diego Biurrun
366 5eb765ef Philip Gladstone
    return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
367
}
368
369 a782f209 Philip Gladstone
370 cde25790 Philip Gladstone
static void start_children(FFStream *feed)
371
{
372 2ac887ba Philip Gladstone
    if (no_launch)
373
        return;
374
375 cde25790 Philip Gladstone
    for (; feed; feed = feed->next) {
376 5eb765ef Philip Gladstone
        if (feed->child_argv && !feed->pid) {
377
            feed->pid_start = time(0);
378
379 cde25790 Philip Gladstone
            feed->pid = fork();
380
381
            if (feed->pid < 0) {
382
                fprintf(stderr, "Unable to create children\n");
383
                exit(1);
384
            }
385
            if (!feed->pid) {
386
                /* In child */
387
                char pathname[1024];
388
                char *slash;
389
                int i;
390
391 611c5741 Alex Beregszaszi
                for (i = 3; i < 256; i++)
392 5eb765ef Philip Gladstone
                    close(i);
393 cde25790 Philip Gladstone
394 5eb765ef Philip Gladstone
                if (!ffserver_debug) {
395 2ac887ba Philip Gladstone
                    i = open("/dev/null", O_RDWR);
396
                    if (i)
397
                        dup2(i, 0);
398
                    dup2(i, 1);
399
                    dup2(i, 2);
400 5eb765ef Philip Gladstone
                    if (i)
401
                        close(i);
402 2ac887ba Philip Gladstone
                }
403 cde25790 Philip Gladstone
404 f7d78f36 Måns Rullgård
                av_strlcpy(pathname, my_program_name, sizeof(pathname));
405 cde25790 Philip Gladstone
406
                slash = strrchr(pathname, '/');
407 611c5741 Alex Beregszaszi
                if (!slash)
408 cde25790 Philip Gladstone
                    slash = pathname;
409 611c5741 Alex Beregszaszi
                else
410 cde25790 Philip Gladstone
                    slash++;
411
                strcpy(slash, "ffmpeg");
412
413 d6562d2c Philip Gladstone
                /* This is needed to make relative pathnames work */
414
                chdir(my_program_dir);
415
416 a4d70941 Philip Gladstone
                signal(SIGPIPE, SIG_DFL);
417
418 cde25790 Philip Gladstone
                execvp(pathname, feed->child_argv);
419
420
                _exit(1);
421
            }
422
        }
423
    }
424 7434ba6d Philip Gladstone
}
425
426 2effd274 Fabrice Bellard
/* open a listening socket */
427
static int socket_open_listen(struct sockaddr_in *my_addr)
428 85f07f22 Fabrice Bellard
{
429 2effd274 Fabrice Bellard
    int server_fd, tmp;
430 85f07f22 Fabrice Bellard
431
    server_fd = socket(AF_INET,SOCK_STREAM,0);
432
    if (server_fd < 0) {
433
        perror ("socket");
434
        return -1;
435
    }
436 115329f1 Diego Biurrun
437 85f07f22 Fabrice Bellard
    tmp = 1;
438
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
439
440 2effd274 Fabrice Bellard
    if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
441 b17d099d Philip Gladstone
        char bindmsg[32];
442
        snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
443
        perror (bindmsg);
444 d96633bb Alex Beregszaszi
        closesocket(server_fd);
445 85f07f22 Fabrice Bellard
        return -1;
446
    }
447 115329f1 Diego Biurrun
448 85f07f22 Fabrice Bellard
    if (listen (server_fd, 5) < 0) {
449
        perror ("listen");
450 d96633bb Alex Beregszaszi
        closesocket(server_fd);
451 85f07f22 Fabrice Bellard
        return -1;
452
    }
453 ba472aaf Alex Beregszaszi
    ff_socket_nonblock(server_fd, 1);
454 2effd274 Fabrice Bellard
455
    return server_fd;
456
}
457
458 6edd6884 Fabrice Bellard
/* start all multicast streams */
459
static void start_multicast(void)
460
{
461
    FFStream *stream;
462
    char session_id[32];
463
    HTTPContext *rtp_c;
464
    struct sockaddr_in dest_addr;
465
    int default_port, stream_index;
466
467
    default_port = 6000;
468
    for(stream = first_stream; stream != NULL; stream = stream->next) {
469
        if (stream->is_multicast) {
470
            /* open the RTP connection */
471 1df93ae9 Alex Beregszaszi
            snprintf(session_id, sizeof(session_id), "%08x%08x",
472
                     av_random(&random_state), av_random(&random_state));
473 6edd6884 Fabrice Bellard
474
            /* choose a port if none given */
475
            if (stream->multicast_port == 0) {
476
                stream->multicast_port = default_port;
477
                default_port += 100;
478
            }
479
480
            dest_addr.sin_family = AF_INET;
481
            dest_addr.sin_addr = stream->multicast_ip;
482
            dest_addr.sin_port = htons(stream->multicast_port);
483
484 115329f1 Diego Biurrun
            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
485 bc351386 Fabrice Bellard
                                       RTSP_PROTOCOL_RTP_UDP_MULTICAST);
486 611c5741 Alex Beregszaszi
            if (!rtp_c)
487 6edd6884 Fabrice Bellard
                continue;
488 611c5741 Alex Beregszaszi
489 6edd6884 Fabrice Bellard
            if (open_input_stream(rtp_c, "") < 0) {
490 115329f1 Diego Biurrun
                fprintf(stderr, "Could not open input stream for stream '%s'\n",
491 6edd6884 Fabrice Bellard
                        stream->filename);
492
                continue;
493
            }
494
495
            /* open each RTP stream */
496 115329f1 Diego Biurrun
            for(stream_index = 0; stream_index < stream->nb_streams;
497 6edd6884 Fabrice Bellard
                stream_index++) {
498 115329f1 Diego Biurrun
                dest_addr.sin_port = htons(stream->multicast_port +
499 6edd6884 Fabrice Bellard
                                           2 * stream_index);
500 bc351386 Fabrice Bellard
                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
501 115329f1 Diego Biurrun
                    fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n",
502 0fa45e19 Fabrice Bellard
                            stream->filename, stream_index);
503
                    exit(1);
504 6edd6884 Fabrice Bellard
                }
505
            }
506
507
            /* change state to send data */
508
            rtp_c->state = HTTPSTATE_SEND_DATA;
509
        }
510
    }
511
}
512 2effd274 Fabrice Bellard
513
/* main loop of the http server */
514
static int http_server(void)
515
{
516
    int server_fd, ret, rtsp_server_fd, delay, delay1;
517
    struct pollfd poll_table[HTTP_MAX_CONNECTIONS + 2], *poll_entry;
518
    HTTPContext *c, *c_next;
519
520
    server_fd = socket_open_listen(&my_http_addr);
521
    if (server_fd < 0)
522
        return -1;
523 85f07f22 Fabrice Bellard
524 2effd274 Fabrice Bellard
    rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
525
    if (rtsp_server_fd < 0)
526
        return -1;
527 115329f1 Diego Biurrun
528 85f07f22 Fabrice Bellard
    http_log("ffserver started.\n");
529
530 cde25790 Philip Gladstone
    start_children(first_feed);
531
532 85f07f22 Fabrice Bellard
    first_http_ctx = NULL;
533
    nb_connections = 0;
534 6edd6884 Fabrice Bellard
535
    start_multicast();
536
537 85f07f22 Fabrice Bellard
    for(;;) {
538
        poll_entry = poll_table;
539
        poll_entry->fd = server_fd;
540
        poll_entry->events = POLLIN;
541
        poll_entry++;
542
543 2effd274 Fabrice Bellard
        poll_entry->fd = rtsp_server_fd;
544
        poll_entry->events = POLLIN;
545
        poll_entry++;
546
547 85f07f22 Fabrice Bellard
        /* wait for events on each HTTP handle */
548
        c = first_http_ctx;
549 2effd274 Fabrice Bellard
        delay = 1000;
550 85f07f22 Fabrice Bellard
        while (c != NULL) {
551
            int fd;
552
            fd = c->fd;
553
            switch(c->state) {
554 2effd274 Fabrice Bellard
            case HTTPSTATE_SEND_HEADER:
555
            case RTSPSTATE_SEND_REPLY:
556 bc351386 Fabrice Bellard
            case RTSPSTATE_SEND_PACKET:
557 85f07f22 Fabrice Bellard
                c->poll_entry = poll_entry;
558
                poll_entry->fd = fd;
559 2effd274 Fabrice Bellard
                poll_entry->events = POLLOUT;
560 85f07f22 Fabrice Bellard
                poll_entry++;
561
                break;
562
            case HTTPSTATE_SEND_DATA_HEADER:
563
            case HTTPSTATE_SEND_DATA:
564
            case HTTPSTATE_SEND_DATA_TRAILER:
565 2effd274 Fabrice Bellard
                if (!c->is_packetized) {
566
                    /* for TCP, we output as much as we can (may need to put a limit) */
567
                    c->poll_entry = poll_entry;
568
                    poll_entry->fd = fd;
569
                    poll_entry->events = POLLOUT;
570
                    poll_entry++;
571
                } else {
572 e240a0bb Fabrice Bellard
                    /* when ffserver is doing the timing, we work by
573
                       looking at which packet need to be sent every
574
                       10 ms */
575
                    delay1 = 10; /* one tick wait XXX: 10 ms assumed */
576
                    if (delay1 < delay)
577
                        delay = delay1;
578 2effd274 Fabrice Bellard
                }
579 85f07f22 Fabrice Bellard
                break;
580 2effd274 Fabrice Bellard
            case HTTPSTATE_WAIT_REQUEST:
581 85f07f22 Fabrice Bellard
            case HTTPSTATE_RECEIVE_DATA:
582
            case HTTPSTATE_WAIT_FEED:
583 2effd274 Fabrice Bellard
            case RTSPSTATE_WAIT_REQUEST:
584 85f07f22 Fabrice Bellard
                /* need to catch errors */
585
                c->poll_entry = poll_entry;
586
                poll_entry->fd = fd;
587 a6e14edd Philip Gladstone
                poll_entry->events = POLLIN;/* Maybe this will work */
588 85f07f22 Fabrice Bellard
                poll_entry++;
589
                break;
590
            default:
591
                c->poll_entry = NULL;
592
                break;
593
            }
594
            c = c->next;
595
        }
596
597
        /* wait for an event on one connection. We poll at least every
598
           second to handle timeouts */
599
        do {
600 2effd274 Fabrice Bellard
            ret = poll(poll_table, poll_entry - poll_table, delay);
601 8da4034f Alex Beregszaszi
            if (ret < 0 && ff_neterrno() != FF_NETERROR(EAGAIN) &&
602
                ff_neterrno() != FF_NETERROR(EINTR))
603 53e2f9ca Michael Niedermayer
                return -1;
604 e8d658df Luca Abeni
        } while (ret < 0);
605 115329f1 Diego Biurrun
606 c3f58185 Alex Beregszaszi
        cur_time = av_gettime() / 1000;
607 85f07f22 Fabrice Bellard
608 5eb765ef Philip Gladstone
        if (need_to_start_children) {
609
            need_to_start_children = 0;
610
            start_children(first_feed);
611
        }
612
613 85f07f22 Fabrice Bellard
        /* now handle the events */
614 2effd274 Fabrice Bellard
        for(c = first_http_ctx; c != NULL; c = c_next) {
615
            c_next = c->next;
616
            if (handle_connection(c) < 0) {
617 85f07f22 Fabrice Bellard
                /* close and free the connection */
618 7434ba6d Philip Gladstone
                log_connection(c);
619 2effd274 Fabrice Bellard
                close_connection(c);
620 85f07f22 Fabrice Bellard
            }
621
        }
622
623
        poll_entry = poll_table;
624 2effd274 Fabrice Bellard
        /* new HTTP connection request ? */
625 611c5741 Alex Beregszaszi
        if (poll_entry->revents & POLLIN)
626 2effd274 Fabrice Bellard
            new_connection(server_fd, 0);
627 85f07f22 Fabrice Bellard
        poll_entry++;
628 2effd274 Fabrice Bellard
        /* new RTSP connection request ? */
629 611c5741 Alex Beregszaszi
        if (poll_entry->revents & POLLIN)
630 2effd274 Fabrice Bellard
            new_connection(rtsp_server_fd, 1);
631 85f07f22 Fabrice Bellard
    }
632
}
633
634 2effd274 Fabrice Bellard
/* start waiting for a new HTTP/RTSP request */
635
static void start_wait_request(HTTPContext *c, int is_rtsp)
636 85f07f22 Fabrice Bellard
{
637 2effd274 Fabrice Bellard
    c->buffer_ptr = c->buffer;
638
    c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
639
640
    if (is_rtsp) {
641
        c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
642
        c->state = RTSPSTATE_WAIT_REQUEST;
643
    } else {
644
        c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
645
        c->state = HTTPSTATE_WAIT_REQUEST;
646
    }
647
}
648
649
static void new_connection(int server_fd, int is_rtsp)
650
{
651
    struct sockaddr_in from_addr;
652
    int fd, len;
653
    HTTPContext *c = NULL;
654
655
    len = sizeof(from_addr);
656 115329f1 Diego Biurrun
    fd = accept(server_fd, (struct sockaddr *)&from_addr,
657 2effd274 Fabrice Bellard
                &len);
658
    if (fd < 0)
659
        return;
660 ba472aaf Alex Beregszaszi
    ff_socket_nonblock(fd, 1);
661 2effd274 Fabrice Bellard
662
    /* XXX: should output a warning page when coming
663
       close to the connection limit */
664
    if (nb_connections >= nb_max_connections)
665
        goto fail;
666 115329f1 Diego Biurrun
667 2effd274 Fabrice Bellard
    /* add a new connection */
668
    c = av_mallocz(sizeof(HTTPContext));
669
    if (!c)
670
        goto fail;
671 115329f1 Diego Biurrun
672 2effd274 Fabrice Bellard
    c->fd = fd;
673
    c->poll_entry = NULL;
674
    c->from_addr = from_addr;
675
    c->buffer_size = IOBUFFER_INIT_SIZE;
676
    c->buffer = av_malloc(c->buffer_size);
677
    if (!c->buffer)
678
        goto fail;
679 8bc80f8b Philip Gladstone
680
    c->next = first_http_ctx;
681
    first_http_ctx = c;
682 2effd274 Fabrice Bellard
    nb_connections++;
683 115329f1 Diego Biurrun
684 2effd274 Fabrice Bellard
    start_wait_request(c, is_rtsp);
685
686
    return;
687
688
 fail:
689
    if (c) {
690
        av_free(c->buffer);
691
        av_free(c);
692
    }
693 d96633bb Alex Beregszaszi
    closesocket(fd);
694 2effd274 Fabrice Bellard
}
695
696
static void close_connection(HTTPContext *c)
697
{
698
    HTTPContext **cp, *c1;
699
    int i, nb_streams;
700
    AVFormatContext *ctx;
701
    URLContext *h;
702
    AVStream *st;
703
704
    /* remove connection from list */
705
    cp = &first_http_ctx;
706
    while ((*cp) != NULL) {
707
        c1 = *cp;
708 611c5741 Alex Beregszaszi
        if (c1 == c)
709 2effd274 Fabrice Bellard
            *cp = c->next;
710 611c5741 Alex Beregszaszi
        else
711 2effd274 Fabrice Bellard
            cp = &c1->next;
712
    }
713
714 bc351386 Fabrice Bellard
    /* remove references, if any (XXX: do it faster) */
715
    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
716
        if (c1->rtsp_c == c)
717
            c1->rtsp_c = NULL;
718
    }
719
720 2effd274 Fabrice Bellard
    /* remove connection associated resources */
721
    if (c->fd >= 0)
722 d96633bb Alex Beregszaszi
        closesocket(c->fd);
723 2effd274 Fabrice Bellard
    if (c->fmt_in) {
724
        /* close each frame parser */
725
        for(i=0;i<c->fmt_in->nb_streams;i++) {
726
            st = c->fmt_in->streams[i];
727 611c5741 Alex Beregszaszi
            if (st->codec->codec)
728 01f4895c Michael Niedermayer
                avcodec_close(st->codec);
729 2effd274 Fabrice Bellard
        }
730
        av_close_input_file(c->fmt_in);
731
    }
732
733
    /* free RTP output streams if any */
734
    nb_streams = 0;
735 115329f1 Diego Biurrun
    if (c->stream)
736 2effd274 Fabrice Bellard
        nb_streams = c->stream->nb_streams;
737 115329f1 Diego Biurrun
738 2effd274 Fabrice Bellard
    for(i=0;i<nb_streams;i++) {
739
        ctx = c->rtp_ctx[i];
740
        if (ctx) {
741
            av_write_trailer(ctx);
742
            av_free(ctx);
743
        }
744
        h = c->rtp_handles[i];
745 611c5741 Alex Beregszaszi
        if (h)
746 2effd274 Fabrice Bellard
            url_close(h);
747
    }
748 115329f1 Diego Biurrun
749 b88ba823 Mark Hills
    ctx = &c->fmt_ctx;
750
751 87638494 Philip Gladstone
    if (!c->last_packet_sent) {
752
        if (ctx->oformat) {
753
            /* prepare header */
754
            if (url_open_dyn_buf(&ctx->pb) >= 0) {
755
                av_write_trailer(ctx);
756 899681cd Björn Axelsson
                url_close_dyn_buf(ctx->pb, &c->pb_buffer);
757 87638494 Philip Gladstone
            }
758
        }
759
    }
760
761 115329f1 Diego Biurrun
    for(i=0; i<ctx->nb_streams; i++)
762 0bd53967 Alex Beregszaszi
        av_free(ctx->streams[i]);
763 f0ef6240 Philip Gladstone
764 edfdd798 Alex Beregszaszi
    if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
765 6edd6884 Fabrice Bellard
        current_bandwidth -= c->stream->bandwidth;
766 5400e092 Alex Beregszaszi
767
    /* signal that there is no feed if we are the feeder socket */
768
    if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
769
        c->stream->feed_opened = 0;
770
        close(c->feed_fd);
771
    }
772
773 2effd274 Fabrice Bellard
    av_freep(&c->pb_buffer);
774 bc351386 Fabrice Bellard
    av_freep(&c->packet_buffer);
775 2effd274 Fabrice Bellard
    av_free(c->buffer);
776
    av_free(c);
777
    nb_connections--;
778
}
779
780
static int handle_connection(HTTPContext *c)
781
{
782
    int len, ret;
783 115329f1 Diego Biurrun
784 85f07f22 Fabrice Bellard
    switch(c->state) {
785
    case HTTPSTATE_WAIT_REQUEST:
786 2effd274 Fabrice Bellard
    case RTSPSTATE_WAIT_REQUEST:
787 85f07f22 Fabrice Bellard
        /* timeout ? */
788
        if ((c->timeout - cur_time) < 0)
789
            return -1;
790
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
791
            return -1;
792
793
        /* no need to read if no events */
794
        if (!(c->poll_entry->revents & POLLIN))
795
            return 0;
796
        /* read the data */
797 1bc1cfdd Giancarlo Formicuccia
    read_loop:
798 c60202df Alex Beregszaszi
        len = recv(c->fd, c->buffer_ptr, 1, 0);
799 85f07f22 Fabrice Bellard
        if (len < 0) {
800 8da4034f Alex Beregszaszi
            if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
801
                ff_neterrno() != FF_NETERROR(EINTR))
802 85f07f22 Fabrice Bellard
                return -1;
803
        } else if (len == 0) {
804
            return -1;
805
        } else {
806 94d9ad5f Giancarlo Formicuccia
            /* search for end of request. */
807 0c1a9eda Zdenek Kabelac
            uint8_t *ptr;
808 85f07f22 Fabrice Bellard
            c->buffer_ptr += len;
809
            ptr = c->buffer_ptr;
810
            if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
811
                (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
812
                /* request found : parse it and reply */
813 2effd274 Fabrice Bellard
                if (c->state == HTTPSTATE_WAIT_REQUEST) {
814
                    ret = http_parse_request(c);
815
                } else {
816
                    ret = rtsp_parse_request(c);
817
                }
818
                if (ret < 0)
819 85f07f22 Fabrice Bellard
                    return -1;
820
            } else if (ptr >= c->buffer_end) {
821
                /* request too long: cannot do anything */
822
                return -1;
823 1bc1cfdd Giancarlo Formicuccia
            } else goto read_loop;
824 85f07f22 Fabrice Bellard
        }
825
        break;
826
827
    case HTTPSTATE_SEND_HEADER:
828
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
829
            return -1;
830
831 2effd274 Fabrice Bellard
        /* no need to write if no events */
832 85f07f22 Fabrice Bellard
        if (!(c->poll_entry->revents & POLLOUT))
833
            return 0;
834 c60202df Alex Beregszaszi
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
835 85f07f22 Fabrice Bellard
        if (len < 0) {
836 8da4034f Alex Beregszaszi
            if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
837
                ff_neterrno() != FF_NETERROR(EINTR)) {
838 85f07f22 Fabrice Bellard
                /* error : close connection */
839 2effd274 Fabrice Bellard
                av_freep(&c->pb_buffer);
840 85f07f22 Fabrice Bellard
                return -1;
841
            }
842
        } else {
843
            c->buffer_ptr += len;
844 2e04edb3 Philip Gladstone
            if (c->stream)
845
                c->stream->bytes_served += len;
846 a6e14edd Philip Gladstone
            c->data_count += len;
847 85f07f22 Fabrice Bellard
            if (c->buffer_ptr >= c->buffer_end) {
848 2effd274 Fabrice Bellard
                av_freep(&c->pb_buffer);
849 85f07f22 Fabrice Bellard
                /* if error, exit */
850 611c5741 Alex Beregszaszi
                if (c->http_error)
851 85f07f22 Fabrice Bellard
                    return -1;
852 2effd274 Fabrice Bellard
                /* all the buffer was sent : synchronize to the incoming stream */
853 85f07f22 Fabrice Bellard
                c->state = HTTPSTATE_SEND_DATA_HEADER;
854
                c->buffer_ptr = c->buffer_end = c->buffer;
855
            }
856
        }
857
        break;
858
859
    case HTTPSTATE_SEND_DATA:
860
    case HTTPSTATE_SEND_DATA_HEADER:
861
    case HTTPSTATE_SEND_DATA_TRAILER:
862 2effd274 Fabrice Bellard
        /* for packetized output, we consider we can always write (the
863
           input streams sets the speed). It may be better to verify
864
           that we do not rely too much on the kernel queues */
865
        if (!c->is_packetized) {
866
            if (c->poll_entry->revents & (POLLERR | POLLHUP))
867
                return -1;
868 115329f1 Diego Biurrun
869 2effd274 Fabrice Bellard
            /* no need to read if no events */
870
            if (!(c->poll_entry->revents & POLLOUT))
871
                return 0;
872
        }
873 5eb765ef Philip Gladstone
        if (http_send_data(c) < 0)
874 85f07f22 Fabrice Bellard
            return -1;
875 638831aa Alex Beregszaszi
        /* close connection if trailer sent */
876
        if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
877
            return -1;
878 85f07f22 Fabrice Bellard
        break;
879
    case HTTPSTATE_RECEIVE_DATA:
880
        /* no need to read if no events */
881
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
882
            return -1;
883
        if (!(c->poll_entry->revents & POLLIN))
884
            return 0;
885
        if (http_receive_data(c) < 0)
886
            return -1;
887
        break;
888
    case HTTPSTATE_WAIT_FEED:
889
        /* no need to read if no events */
890 a6e14edd Philip Gladstone
        if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
891 85f07f22 Fabrice Bellard
            return -1;
892
893
        /* nothing to do, we'll be waken up by incoming feed packets */
894
        break;
895 2effd274 Fabrice Bellard
896
    case RTSPSTATE_SEND_REPLY:
897
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
898
            av_freep(&c->pb_buffer);
899
            return -1;
900
        }
901
        /* no need to write if no events */
902
        if (!(c->poll_entry->revents & POLLOUT))
903
            return 0;
904 c60202df Alex Beregszaszi
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
905 2effd274 Fabrice Bellard
        if (len < 0) {
906 8da4034f Alex Beregszaszi
            if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
907
                ff_neterrno() != FF_NETERROR(EINTR)) {
908 2effd274 Fabrice Bellard
                /* error : close connection */
909
                av_freep(&c->pb_buffer);
910
                return -1;
911
            }
912
        } else {
913
            c->buffer_ptr += len;
914
            c->data_count += len;
915
            if (c->buffer_ptr >= c->buffer_end) {
916
                /* all the buffer was sent : wait for a new request */
917
                av_freep(&c->pb_buffer);
918
                start_wait_request(c, 1);
919
            }
920
        }
921
        break;
922 bc351386 Fabrice Bellard
    case RTSPSTATE_SEND_PACKET:
923
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
924
            av_freep(&c->packet_buffer);
925
            return -1;
926
        }
927
        /* no need to write if no events */
928
        if (!(c->poll_entry->revents & POLLOUT))
929
            return 0;
930 c60202df Alex Beregszaszi
        len = send(c->fd, c->packet_buffer_ptr,
931
                    c->packet_buffer_end - c->packet_buffer_ptr, 0);
932 bc351386 Fabrice Bellard
        if (len < 0) {
933 8da4034f Alex Beregszaszi
            if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
934
                ff_neterrno() != FF_NETERROR(EINTR)) {
935 bc351386 Fabrice Bellard
                /* error : close connection */
936
                av_freep(&c->packet_buffer);
937
                return -1;
938
            }
939
        } else {
940
            c->packet_buffer_ptr += len;
941
            if (c->packet_buffer_ptr >= c->packet_buffer_end) {
942
                /* all the buffer was sent : wait for a new request */
943
                av_freep(&c->packet_buffer);
944
                c->state = RTSPSTATE_WAIT_REQUEST;
945
            }
946
        }
947
        break;
948 2effd274 Fabrice Bellard
    case HTTPSTATE_READY:
949
        /* nothing to do */
950
        break;
951 85f07f22 Fabrice Bellard
    default:
952
        return -1;
953
    }
954
    return 0;
955
}
956
957 3120d2a2 Philip Gladstone
static int extract_rates(char *rates, int ratelen, const char *request)
958
{
959
    const char *p;
960
961
    for (p = request; *p && *p != '\r' && *p != '\n'; ) {
962
        if (strncasecmp(p, "Pragma:", 7) == 0) {
963
            const char *q = p + 7;
964
965
            while (*q && *q != '\n' && isspace(*q))
966
                q++;
967
968
            if (strncasecmp(q, "stream-switch-entry=", 20) == 0) {
969
                int stream_no;
970
                int rate_no;
971
972
                q += 20;
973
974 cde25790 Philip Gladstone
                memset(rates, 0xff, ratelen);
975 3120d2a2 Philip Gladstone
976
                while (1) {
977
                    while (*q && *q != '\n' && *q != ':')
978
                        q++;
979
980 611c5741 Alex Beregszaszi
                    if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
981 3120d2a2 Philip Gladstone
                        break;
982 611c5741 Alex Beregszaszi
983 3120d2a2 Philip Gladstone
                    stream_no--;
984 611c5741 Alex Beregszaszi
                    if (stream_no < ratelen && stream_no >= 0)
985 3120d2a2 Philip Gladstone
                        rates[stream_no] = rate_no;
986
987
                    while (*q && *q != '\n' && !isspace(*q))
988
                        q++;
989
                }
990
991
                return 1;
992
            }
993
        }
994
        p = strchr(p, '\n');
995
        if (!p)
996
            break;
997
998
        p++;
999
    }
1000
1001
    return 0;
1002
}
1003
1004 cde25790 Philip Gladstone
static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1005 3120d2a2 Philip Gladstone
{
1006
    int i;
1007 cde25790 Philip Gladstone
    int best_bitrate = 100000000;
1008
    int best = -1;
1009
1010
    for (i = 0; i < feed->nb_streams; i++) {
1011 01f4895c Michael Niedermayer
        AVCodecContext *feed_codec = feed->streams[i]->codec;
1012 cde25790 Philip Gladstone
1013
        if (feed_codec->codec_id != codec->codec_id ||
1014
            feed_codec->sample_rate != codec->sample_rate ||
1015
            feed_codec->width != codec->width ||
1016 611c5741 Alex Beregszaszi
            feed_codec->height != codec->height)
1017 cde25790 Philip Gladstone
            continue;
1018
1019
        /* Potential stream */
1020
1021 115329f1 Diego Biurrun
        /* We want the fastest stream less than bit_rate, or the slowest
1022 cde25790 Philip Gladstone
         * faster than bit_rate
1023
         */
1024
1025
        if (feed_codec->bit_rate <= bit_rate) {
1026
            if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1027
                best_bitrate = feed_codec->bit_rate;
1028
                best = i;
1029
            }
1030
        } else {
1031
            if (feed_codec->bit_rate < best_bitrate) {
1032
                best_bitrate = feed_codec->bit_rate;
1033
                best = i;
1034
            }
1035
        }
1036
    }
1037
1038
    return best;
1039
}
1040
1041
static int modify_current_stream(HTTPContext *c, char *rates)
1042
{
1043
    int i;
1044
    FFStream *req = c->stream;
1045
    int action_required = 0;
1046 3120d2a2 Philip Gladstone
1047 001bcd29 Philip Gladstone
    /* Not much we can do for a feed */
1048
    if (!req->feed)
1049
        return 0;
1050
1051 3120d2a2 Philip Gladstone
    for (i = 0; i < req->nb_streams; i++) {
1052 01f4895c Michael Niedermayer
        AVCodecContext *codec = req->streams[i]->codec;
1053 3120d2a2 Philip Gladstone
1054
        switch(rates[i]) {
1055
            case 0:
1056 cde25790 Philip Gladstone
                c->switch_feed_streams[i] = req->feed_streams[i];
1057 3120d2a2 Philip Gladstone
                break;
1058
            case 1:
1059 cde25790 Philip Gladstone
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1060 3120d2a2 Philip Gladstone
                break;
1061
            case 2:
1062 cde25790 Philip Gladstone
                /* Wants off or slow */
1063
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1064
#ifdef WANTS_OFF
1065
                /* This doesn't work well when it turns off the only stream! */
1066
                c->switch_feed_streams[i] = -2;
1067
                c->feed_streams[i] = -2;
1068
#endif
1069 3120d2a2 Philip Gladstone
                break;
1070
        }
1071
1072 cde25790 Philip Gladstone
        if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1073
            action_required = 1;
1074
    }
1075 3120d2a2 Philip Gladstone
1076 cde25790 Philip Gladstone
    return action_required;
1077
}
1078 3120d2a2 Philip Gladstone
1079
1080 cde25790 Philip Gladstone
static void do_switch_stream(HTTPContext *c, int i)
1081
{
1082
    if (c->switch_feed_streams[i] >= 0) {
1083 115329f1 Diego Biurrun
#ifdef PHILIP
1084 cde25790 Philip Gladstone
        c->feed_streams[i] = c->switch_feed_streams[i];
1085
#endif
1086 3120d2a2 Philip Gladstone
1087 cde25790 Philip Gladstone
        /* Now update the stream */
1088 3120d2a2 Philip Gladstone
    }
1089 cde25790 Philip Gladstone
    c->switch_feed_streams[i] = -1;
1090 3120d2a2 Philip Gladstone
}
1091 7434ba6d Philip Gladstone
1092 2effd274 Fabrice Bellard
/* XXX: factorize in utils.c ? */
1093
/* XXX: take care with different space meaning */
1094
static void skip_spaces(const char **pp)
1095
{
1096
    const char *p;
1097
    p = *pp;
1098
    while (*p == ' ' || *p == '\t')
1099
        p++;
1100
    *pp = p;
1101
}
1102
1103
static void get_word(char *buf, int buf_size, const char **pp)
1104
{
1105
    const char *p;
1106
    char *q;
1107
1108
    p = *pp;
1109
    skip_spaces(&p);
1110
    q = buf;
1111
    while (!isspace(*p) && *p != '\0') {
1112
        if ((q - buf) < buf_size - 1)
1113
            *q++ = *p;
1114
        p++;
1115
    }
1116
    if (buf_size > 0)
1117
        *q = '\0';
1118
    *pp = p;
1119
}
1120
1121 8256c0a3 Philip Gladstone
static int validate_acl(FFStream *stream, HTTPContext *c)
1122
{
1123
    enum IPAddressAction last_action = IP_DENY;
1124
    IPAddressACL *acl;
1125
    struct in_addr *src = &c->from_addr.sin_addr;
1126 2bd8416e Alex Beregszaszi
    unsigned long src_addr = src->s_addr;
1127 8256c0a3 Philip Gladstone
1128
    for (acl = stream->acl; acl; acl = acl->next) {
1129 611c5741 Alex Beregszaszi
        if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1130 8256c0a3 Philip Gladstone
            return (acl->action == IP_ALLOW) ? 1 : 0;
1131
        last_action = acl->action;
1132
    }
1133
1134
    /* Nothing matched, so return not the last action */
1135
    return (last_action == IP_DENY) ? 1 : 0;
1136
}
1137
1138 829ac53d Fabrice Bellard
/* compute the real filename of a file by matching it without its
1139
   extensions to all the stream filenames */
1140
static void compute_real_filename(char *filename, int max_size)
1141
{
1142
    char file1[1024];
1143
    char file2[1024];
1144
    char *p;
1145
    FFStream *stream;
1146
1147
    /* compute filename by matching without the file extensions */
1148 f7d78f36 Måns Rullgård
    av_strlcpy(file1, filename, sizeof(file1));
1149 829ac53d Fabrice Bellard
    p = strrchr(file1, '.');
1150
    if (p)
1151
        *p = '\0';
1152
    for(stream = first_stream; stream != NULL; stream = stream->next) {
1153 f7d78f36 Måns Rullgård
        av_strlcpy(file2, stream->filename, sizeof(file2));
1154 829ac53d Fabrice Bellard
        p = strrchr(file2, '.');
1155
        if (p)
1156
            *p = '\0';
1157
        if (!strcmp(file1, file2)) {
1158 f7d78f36 Måns Rullgård
            av_strlcpy(filename, stream->filename, max_size);
1159 829ac53d Fabrice Bellard
            break;
1160
        }
1161
    }
1162
}
1163
1164
enum RedirType {
1165
    REDIR_NONE,
1166
    REDIR_ASX,
1167
    REDIR_RAM,
1168
    REDIR_ASF,
1169
    REDIR_RTSP,
1170
    REDIR_SDP,
1171
};
1172
1173 85f07f22 Fabrice Bellard
/* parse http request and prepare header */
1174
static int http_parse_request(HTTPContext *c)
1175
{
1176
    char *p;
1177 829ac53d Fabrice Bellard
    enum RedirType redir_type;
1178 85f07f22 Fabrice Bellard
    char cmd[32];
1179 bae79c04 Alex Beregszaszi
    char info[1024], filename[1024];
1180 85f07f22 Fabrice Bellard
    char url[1024], *q;
1181
    char protocol[32];
1182
    char msg[1024];
1183
    const char *mime_type;
1184
    FFStream *stream;
1185 42a63c6a Philip Gladstone
    int i;
1186 3120d2a2 Philip Gladstone
    char ratebuf[32];
1187 cde25790 Philip Gladstone
    char *useragent = 0;
1188 85f07f22 Fabrice Bellard
1189
    p = c->buffer;
1190 2effd274 Fabrice Bellard
    get_word(cmd, sizeof(cmd), (const char **)&p);
1191 f7d78f36 Måns Rullgård
    av_strlcpy(c->method, cmd, sizeof(c->method));
1192 7434ba6d Philip Gladstone
1193 85f07f22 Fabrice Bellard
    if (!strcmp(cmd, "GET"))
1194 edfdd798 Alex Beregszaszi
        c->post = 0;
1195 85f07f22 Fabrice Bellard
    else if (!strcmp(cmd, "POST"))
1196 edfdd798 Alex Beregszaszi
        c->post = 1;
1197 85f07f22 Fabrice Bellard
    else
1198
        return -1;
1199
1200 2effd274 Fabrice Bellard
    get_word(url, sizeof(url), (const char **)&p);
1201 f7d78f36 Måns Rullgård
    av_strlcpy(c->url, url, sizeof(c->url));
1202 7434ba6d Philip Gladstone
1203 2effd274 Fabrice Bellard
    get_word(protocol, sizeof(protocol), (const char **)&p);
1204 85f07f22 Fabrice Bellard
    if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1205
        return -1;
1206 7434ba6d Philip Gladstone
1207 f7d78f36 Måns Rullgård
    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1208 90f9c440 Alex Beregszaszi
1209
    if (ffserver_debug)
1210 bb270c08 Diego Biurrun
        http_log("New connection: %s %s\n", cmd, url);
1211 115329f1 Diego Biurrun
1212 85f07f22 Fabrice Bellard
    /* find the filename and the optional info string in the request */
1213 bae79c04 Alex Beregszaszi
    p = strchr(url, '?');
1214 85f07f22 Fabrice Bellard
    if (p) {
1215 f7d78f36 Måns Rullgård
        av_strlcpy(info, p, sizeof(info));
1216 85f07f22 Fabrice Bellard
        *p = '\0';
1217 611c5741 Alex Beregszaszi
    } else
1218 85f07f22 Fabrice Bellard
        info[0] = '\0';
1219
1220 f7d78f36 Måns Rullgård
    av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1221 bae79c04 Alex Beregszaszi
1222 cde25790 Philip Gladstone
    for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1223
        if (strncasecmp(p, "User-Agent:", 11) == 0) {
1224
            useragent = p + 11;
1225
            if (*useragent && *useragent != '\n' && isspace(*useragent))
1226
                useragent++;
1227
            break;
1228
        }
1229
        p = strchr(p, '\n');
1230
        if (!p)
1231
            break;
1232
1233
        p++;
1234
    }
1235
1236 829ac53d Fabrice Bellard
    redir_type = REDIR_NONE;
1237
    if (match_ext(filename, "asx")) {
1238
        redir_type = REDIR_ASX;
1239 7434ba6d Philip Gladstone
        filename[strlen(filename)-1] = 'f';
1240 c2ce254c Philip Gladstone
    } else if (match_ext(filename, "asf") &&
1241 cde25790 Philip Gladstone
        (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1242
        /* if this isn't WMP or lookalike, return the redirector file */
1243 829ac53d Fabrice Bellard
        redir_type = REDIR_ASF;
1244
    } else if (match_ext(filename, "rpm,ram")) {
1245
        redir_type = REDIR_RAM;
1246 42a63c6a Philip Gladstone
        strcpy(filename + strlen(filename)-2, "m");
1247 829ac53d Fabrice Bellard
    } else if (match_ext(filename, "rtsp")) {
1248
        redir_type = REDIR_RTSP;
1249 bae79c04 Alex Beregszaszi
        compute_real_filename(filename, sizeof(filename) - 1);
1250 829ac53d Fabrice Bellard
    } else if (match_ext(filename, "sdp")) {
1251
        redir_type = REDIR_SDP;
1252 bae79c04 Alex Beregszaszi
        compute_real_filename(filename, sizeof(filename) - 1);
1253 42a63c6a Philip Gladstone
    }
1254 115329f1 Diego Biurrun
1255 bae79c04 Alex Beregszaszi
    // "redirect" / request to index.html
1256
    if (!strlen(filename))
1257 f7d78f36 Måns Rullgård
        av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1258 bae79c04 Alex Beregszaszi
1259 85f07f22 Fabrice Bellard
    stream = first_stream;
1260
    while (stream != NULL) {
1261 8256c0a3 Philip Gladstone
        if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1262 85f07f22 Fabrice Bellard
            break;
1263
        stream = stream->next;
1264
    }
1265
    if (stream == NULL) {
1266 d445a7e9 Philip Gladstone
        snprintf(msg, sizeof(msg), "File '%s' not found", url);
1267 85f07f22 Fabrice Bellard
        goto send_error;
1268
    }
1269 42a63c6a Philip Gladstone
1270 cde25790 Philip Gladstone
    c->stream = stream;
1271
    memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1272
    memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1273
1274
    if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1275
        c->http_error = 301;
1276
        q = c->buffer;
1277 d445a7e9 Philip Gladstone
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 301 Moved\r\n");
1278
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Location: %s\r\n", stream->feed_filename);
1279
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n");
1280
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1281
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Moved</title></head><body>\r\n");
1282
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "You should be <a href=\"%s\">redirected</a>.\r\n", stream->feed_filename);
1283
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n");
1284 cde25790 Philip Gladstone
1285
        /* prepare output buffer */
1286
        c->buffer_ptr = c->buffer;
1287
        c->buffer_end = q;
1288
        c->state = HTTPSTATE_SEND_HEADER;
1289
        return 0;
1290
    }
1291
1292 3120d2a2 Philip Gladstone
    /* If this is WMP, get the rate information */
1293
    if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1294 cde25790 Philip Gladstone
        if (modify_current_stream(c, ratebuf)) {
1295
            for (i = 0; i < sizeof(c->feed_streams) / sizeof(c->feed_streams[0]); i++) {
1296
                if (c->switch_feed_streams[i] >= 0)
1297
                    do_switch_stream(c, i);
1298
            }
1299
        }
1300 3120d2a2 Philip Gladstone
    }
1301
1302 755bfeab Diego Biurrun
    /* If already streaming this feed, do not let start another feeder. */
1303 d0a5513b Alex Beregszaszi
    if (stream->feed_opened) {
1304
        snprintf(msg, sizeof(msg), "This feed is already being received.");
1305
        goto send_error;
1306
    }
1307
1308 611c5741 Alex Beregszaszi
    if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1309 6edd6884 Fabrice Bellard
        current_bandwidth += stream->bandwidth;
1310 115329f1 Diego Biurrun
1311 edfdd798 Alex Beregszaszi
    if (c->post == 0 && max_bandwidth < current_bandwidth) {
1312 42a63c6a Philip Gladstone
        c->http_error = 200;
1313
        q = c->buffer;
1314 d445a7e9 Philip Gladstone
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 Server too busy\r\n");
1315
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n");
1316
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1317
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Too busy</title></head><body>\r\n");
1318 33f5e2ec Alex Beregszaszi
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The server is too busy to serve your request at this time.</p>\r\n");
1319
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec.</p>\r\n",
1320 6edd6884 Fabrice Bellard
            current_bandwidth, max_bandwidth);
1321 d445a7e9 Philip Gladstone
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n");
1322 42a63c6a Philip Gladstone
1323
        /* prepare output buffer */
1324
        c->buffer_ptr = c->buffer;
1325
        c->buffer_end = q;
1326
        c->state = HTTPSTATE_SEND_HEADER;
1327
        return 0;
1328
    }
1329 115329f1 Diego Biurrun
1330 829ac53d Fabrice Bellard
    if (redir_type != REDIR_NONE) {
1331 7434ba6d Philip Gladstone
        char *hostinfo = 0;
1332 115329f1 Diego Biurrun
1333 7434ba6d Philip Gladstone
        for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1334
            if (strncasecmp(p, "Host:", 5) == 0) {
1335
                hostinfo = p + 5;
1336
                break;
1337
            }
1338
            p = strchr(p, '\n');
1339
            if (!p)
1340
                break;
1341
1342
            p++;
1343
        }
1344
1345
        if (hostinfo) {
1346
            char *eoh;
1347
            char hostbuf[260];
1348
1349
            while (isspace(*hostinfo))
1350
                hostinfo++;
1351
1352
            eoh = strchr(hostinfo, '\n');
1353
            if (eoh) {
1354
                if (eoh[-1] == '\r')
1355
                    eoh--;
1356
1357
                if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1358
                    memcpy(hostbuf, hostinfo, eoh - hostinfo);
1359
                    hostbuf[eoh - hostinfo] = 0;
1360
1361
                    c->http_error = 200;
1362
                    q = c->buffer;
1363 829ac53d Fabrice Bellard
                    switch(redir_type) {
1364
                    case REDIR_ASX:
1365 d445a7e9 Philip Gladstone
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASX Follows\r\n");
1366
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n");
1367
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1368
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ASX Version=\"3\">\r\n");
1369 7c054ea7 Philip Gladstone
                        //q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<!-- Autogenerated by ffserver -->\r\n");
1370 115329f1 Diego Biurrun
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n",
1371 42a63c6a Philip Gladstone
                                hostbuf, filename, info);
1372 d445a7e9 Philip Gladstone
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</ASX>\r\n");
1373 829ac53d Fabrice Bellard
                        break;
1374
                    case REDIR_RAM:
1375 d445a7e9 Philip Gladstone
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RAM Follows\r\n");
1376
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: audio/x-pn-realaudio\r\n");
1377
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1378
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "# Autogenerated by ffserver\r\n");
1379 115329f1 Diego Biurrun
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n",
1380 42a63c6a Philip Gladstone
                                hostbuf, filename, info);
1381 829ac53d Fabrice Bellard
                        break;
1382
                    case REDIR_ASF:
1383 d445a7e9 Philip Gladstone
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASF Redirect follows\r\n");
1384
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n");
1385
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1386
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "[Reference]\r\n");
1387 115329f1 Diego Biurrun
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n",
1388 cde25790 Philip Gladstone
                                hostbuf, filename, info);
1389 829ac53d Fabrice Bellard
                        break;
1390
                    case REDIR_RTSP:
1391
                        {
1392
                            char hostname[256], *p;
1393
                            /* extract only hostname */
1394 f7d78f36 Måns Rullgård
                            av_strlcpy(hostname, hostbuf, sizeof(hostname));
1395 829ac53d Fabrice Bellard
                            p = strrchr(hostname, ':');
1396
                            if (p)
1397
                                *p = '\0';
1398 d445a7e9 Philip Gladstone
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RTSP Redirect follows\r\n");
1399 829ac53d Fabrice Bellard
                            /* XXX: incorrect mime type ? */
1400 d445a7e9 Philip Gladstone
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/x-rtsp\r\n");
1401
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1402 115329f1 Diego Biurrun
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n",
1403
                                         hostname, ntohs(my_rtsp_addr.sin_port),
1404 829ac53d Fabrice Bellard
                                         filename);
1405
                        }
1406
                        break;
1407
                    case REDIR_SDP:
1408
                        {
1409 0c1a9eda Zdenek Kabelac
                            uint8_t *sdp_data;
1410 829ac53d Fabrice Bellard
                            int sdp_data_size, len;
1411
                            struct sockaddr_in my_addr;
1412
1413 d445a7e9 Philip Gladstone
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1414
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/sdp\r\n");
1415
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1416 829ac53d Fabrice Bellard
1417
                            len = sizeof(my_addr);
1418
                            getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1419 115329f1 Diego Biurrun
1420 829ac53d Fabrice Bellard
                            /* XXX: should use a dynamic buffer */
1421 115329f1 Diego Biurrun
                            sdp_data_size = prepare_sdp_description(stream,
1422
                                                                    &sdp_data,
1423 829ac53d Fabrice Bellard
                                                                    my_addr.sin_addr);
1424
                            if (sdp_data_size > 0) {
1425
                                memcpy(q, sdp_data, sdp_data_size);
1426
                                q += sdp_data_size;
1427
                                *q = '\0';
1428
                                av_free(sdp_data);
1429
                            }
1430
                        }
1431
                        break;
1432
                    default:
1433 0f4e8165 Ronald S. Bultje
                        abort();
1434 829ac53d Fabrice Bellard
                        break;
1435 2effd274 Fabrice Bellard
                    }
1436 7434ba6d Philip Gladstone
1437
                    /* prepare output buffer */
1438
                    c->buffer_ptr = c->buffer;
1439
                    c->buffer_end = q;
1440
                    c->state = HTTPSTATE_SEND_HEADER;
1441
                    return 0;
1442
                }
1443
            }
1444
        }
1445
1446 d445a7e9 Philip Gladstone
        snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1447 7434ba6d Philip Gladstone
        goto send_error;
1448 85f07f22 Fabrice Bellard
    }
1449
1450 a6e14edd Philip Gladstone
    stream->conns_served++;
1451 7434ba6d Philip Gladstone
1452 85f07f22 Fabrice Bellard
    /* XXX: add there authenticate and IP match */
1453
1454 edfdd798 Alex Beregszaszi
    if (c->post) {
1455 85f07f22 Fabrice Bellard
        /* if post, it means a feed is being sent */
1456
        if (!stream->is_feed) {
1457 7434ba6d Philip Gladstone
            /* However it might be a status report from WMP! Lets log the data
1458
             * as it might come in handy one day
1459
             */
1460
            char *logline = 0;
1461 3120d2a2 Philip Gladstone
            int client_id = 0;
1462 115329f1 Diego Biurrun
1463 7434ba6d Philip Gladstone
            for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1464
                if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1465
                    logline = p;
1466
                    break;
1467
                }
1468 611c5741 Alex Beregszaszi
                if (strncasecmp(p, "Pragma: client-id=", 18) == 0)
1469 3120d2a2 Philip Gladstone
                    client_id = strtol(p + 18, 0, 10);
1470 7434ba6d Philip Gladstone
                p = strchr(p, '\n');
1471
                if (!p)
1472
                    break;
1473
1474
                p++;
1475
            }
1476
1477
            if (logline) {
1478
                char *eol = strchr(logline, '\n');
1479
1480
                logline += 17;
1481
1482
                if (eol) {
1483
                    if (eol[-1] == '\r')
1484
                        eol--;
1485 7906085f Falk Hüffner
                    http_log("%.*s\n", (int) (eol - logline), logline);
1486 7434ba6d Philip Gladstone
                    c->suppress_log = 1;
1487
                }
1488
            }
1489 3120d2a2 Philip Gladstone
1490 cde25790 Philip Gladstone
#ifdef DEBUG_WMP
1491
            http_log("\nGot request:\n%s\n", c->buffer);
1492 3120d2a2 Philip Gladstone
#endif
1493
1494
            if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1495
                HTTPContext *wmpc;
1496
1497
                /* Now we have to find the client_id */
1498
                for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1499
                    if (wmpc->wmp_client_id == client_id)
1500
                        break;
1501
                }
1502
1503 2d563d2f Alex Beregszaszi
                if (wmpc && modify_current_stream(wmpc, ratebuf))
1504
                    wmpc->switch_pending = 1;
1505 3120d2a2 Philip Gladstone
            }
1506 115329f1 Diego Biurrun
1507 d445a7e9 Philip Gladstone
            snprintf(msg, sizeof(msg), "POST command not handled");
1508 cb275dd9 Philip Gladstone
            c->stream = 0;
1509 85f07f22 Fabrice Bellard
            goto send_error;
1510
        }
1511
        if (http_start_receive_data(c) < 0) {
1512 d445a7e9 Philip Gladstone
            snprintf(msg, sizeof(msg), "could not open feed");
1513 85f07f22 Fabrice Bellard
            goto send_error;
1514
        }
1515
        c->http_error = 0;
1516
        c->state = HTTPSTATE_RECEIVE_DATA;
1517
        return 0;
1518
    }
1519
1520 cde25790 Philip Gladstone
#ifdef DEBUG_WMP
1521 611c5741 Alex Beregszaszi
    if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1522 cde25790 Philip Gladstone
        http_log("\nGot request:\n%s\n", c->buffer);
1523 3120d2a2 Philip Gladstone
#endif
1524
1525 85f07f22 Fabrice Bellard
    if (c->stream->stream_type == STREAM_TYPE_STATUS)
1526
        goto send_stats;
1527
1528
    /* open input stream */
1529
    if (open_input_stream(c, info) < 0) {
1530 d445a7e9 Philip Gladstone
        snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1531 85f07f22 Fabrice Bellard
        goto send_error;
1532
    }
1533
1534
    /* prepare http header */
1535
    q = c->buffer;
1536 d445a7e9 Philip Gladstone
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1537 85f07f22 Fabrice Bellard
    mime_type = c->stream->fmt->mime_type;
1538
    if (!mime_type)
1539 087fa475 Alex Beregszaszi
        mime_type = "application/x-octet-stream";
1540 d445a7e9 Philip Gladstone
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
1541 85f07f22 Fabrice Bellard
1542
    /* for asf, we need extra headers */
1543 8256c0a3 Philip Gladstone
    if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1544 3120d2a2 Philip Gladstone
        /* Need to allocate a client id */
1545
1546 1df93ae9 Alex Beregszaszi
        c->wmp_client_id = av_random(&random_state) & 0x7fffffff;
1547 3120d2a2 Philip Gladstone
1548 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);
1549 85f07f22 Fabrice Bellard
    }
1550 d445a7e9 Philip Gladstone
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1551
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1552 115329f1 Diego Biurrun
1553 85f07f22 Fabrice Bellard
    /* prepare output buffer */
1554
    c->http_error = 0;
1555
    c->buffer_ptr = c->buffer;
1556
    c->buffer_end = q;
1557
    c->state = HTTPSTATE_SEND_HEADER;
1558
    return 0;
1559
 send_error:
1560
    c->http_error = 404;
1561
    q = c->buffer;
1562 d445a7e9 Philip Gladstone
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 404 Not Found\r\n");
1563
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: %s\r\n", "text/html");
1564
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1565
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HTML>\n");
1566
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
1567
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<BODY>%s</BODY>\n", msg);
1568
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</HTML>\n");
1569 85f07f22 Fabrice Bellard
1570
    /* prepare output buffer */
1571
    c->buffer_ptr = c->buffer;
1572
    c->buffer_end = q;
1573
    c->state = HTTPSTATE_SEND_HEADER;
1574
    return 0;
1575
 send_stats:
1576
    compute_stats(c);
1577
    c->http_error = 200; /* horrible : we use this value to avoid
1578
                            going to the send data state */
1579
    c->state = HTTPSTATE_SEND_HEADER;
1580
    return 0;
1581
}
1582
1583 0c1a9eda Zdenek Kabelac
static void fmt_bytecount(ByteIOContext *pb, int64_t count)
1584 2ac887ba Philip Gladstone
{
1585
    static const char *suffix = " kMGTP";
1586
    const char *s;
1587
1588 611c5741 Alex Beregszaszi
    for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1589 2ac887ba Philip Gladstone
1590 4733abcb Måns Rullgård
    url_fprintf(pb, "%"PRId64"%c", count, *s);
1591 2ac887ba Philip Gladstone
}
1592
1593 85f07f22 Fabrice Bellard
static void compute_stats(HTTPContext *c)
1594
{
1595
    HTTPContext *c1;
1596
    FFStream *stream;
1597 2effd274 Fabrice Bellard
    char *p;
1598 85f07f22 Fabrice Bellard
    time_t ti;
1599 2effd274 Fabrice Bellard
    int i, len;
1600 899681cd Björn Axelsson
    ByteIOContext *pb;
1601 cde25790 Philip Gladstone
1602 899681cd Björn Axelsson
    if (url_open_dyn_buf(&pb) < 0) {
1603 2effd274 Fabrice Bellard
        /* XXX: return an error ? */
1604 cde25790 Philip Gladstone
        c->buffer_ptr = c->buffer;
1605 2effd274 Fabrice Bellard
        c->buffer_end = c->buffer;
1606
        return;
1607 cde25790 Philip Gladstone
    }
1608 85f07f22 Fabrice Bellard
1609 2effd274 Fabrice Bellard
    url_fprintf(pb, "HTTP/1.0 200 OK\r\n");
1610
    url_fprintf(pb, "Content-type: %s\r\n", "text/html");
1611
    url_fprintf(pb, "Pragma: no-cache\r\n");
1612
    url_fprintf(pb, "\r\n");
1613 115329f1 Diego Biurrun
1614 2effd274 Fabrice Bellard
    url_fprintf(pb, "<HEAD><TITLE>FFServer Status</TITLE>\n");
1615 611c5741 Alex Beregszaszi
    if (c->stream->feed_filename)
1616 2effd274 Fabrice Bellard
        url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1617
    url_fprintf(pb, "</HEAD>\n<BODY>");
1618
    url_fprintf(pb, "<H1>FFServer Status</H1>\n");
1619 85f07f22 Fabrice Bellard
    /* format status */
1620 2effd274 Fabrice Bellard
    url_fprintf(pb, "<H2>Available Streams</H2>\n");
1621
    url_fprintf(pb, "<TABLE cellspacing=0 cellpadding=4>\n");
1622
    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");
1623 85f07f22 Fabrice Bellard
    stream = first_stream;
1624
    while (stream != NULL) {
1625 42a63c6a Philip Gladstone
        char sfilename[1024];
1626
        char *eosf;
1627
1628 a6e14edd Philip Gladstone
        if (stream->feed != stream) {
1629 f7d78f36 Måns Rullgård
            av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1630 a6e14edd Philip Gladstone
            eosf = sfilename + strlen(sfilename);
1631
            if (eosf - sfilename >= 4) {
1632 611c5741 Alex Beregszaszi
                if (strcmp(eosf - 4, ".asf") == 0)
1633 a6e14edd Philip Gladstone
                    strcpy(eosf - 4, ".asx");
1634 611c5741 Alex Beregszaszi
                else if (strcmp(eosf - 3, ".rm") == 0)
1635 a6e14edd Philip Gladstone
                    strcpy(eosf - 3, ".ram");
1636 25e3e53d Luca Abeni
                else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1637 829ac53d Fabrice Bellard
                    /* generate a sample RTSP director if
1638
                       unicast. Generate an SDP redirector if
1639
                       multicast */
1640 2effd274 Fabrice Bellard
                    eosf = strrchr(sfilename, '.');
1641
                    if (!eosf)
1642
                        eosf = sfilename + strlen(sfilename);
1643 829ac53d Fabrice Bellard
                    if (stream->is_multicast)
1644
                        strcpy(eosf, ".sdp");
1645
                    else
1646
                        strcpy(eosf, ".rtsp");
1647 a6e14edd Philip Gladstone
                }
1648 42a63c6a Philip Gladstone
            }
1649 115329f1 Diego Biurrun
1650
            url_fprintf(pb, "<TR><TD><A HREF=\"/%s\">%s</A> ",
1651 a6e14edd Philip Gladstone
                         sfilename, stream->filename);
1652 2effd274 Fabrice Bellard
            url_fprintf(pb, "<td align=right> %d <td align=right> ",
1653 2ac887ba Philip Gladstone
                        stream->conns_served);
1654 2effd274 Fabrice Bellard
            fmt_bytecount(pb, stream->bytes_served);
1655 a6e14edd Philip Gladstone
            switch(stream->stream_type) {
1656
            case STREAM_TYPE_LIVE:
1657
                {
1658
                    int audio_bit_rate = 0;
1659
                    int video_bit_rate = 0;
1660 58445440 Zdenek Kabelac
                    const char *audio_codec_name = "";
1661
                    const char *video_codec_name = "";
1662
                    const char *audio_codec_name_extra = "";
1663
                    const char *video_codec_name_extra = "";
1664 a6e14edd Philip Gladstone
1665
                    for(i=0;i<stream->nb_streams;i++) {
1666
                        AVStream *st = stream->streams[i];
1667 01f4895c Michael Niedermayer
                        AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1668
                        switch(st->codec->codec_type) {
1669 a6e14edd Philip Gladstone
                        case CODEC_TYPE_AUDIO:
1670 01f4895c Michael Niedermayer
                            audio_bit_rate += st->codec->bit_rate;
1671 a6e14edd Philip Gladstone
                            if (codec) {
1672
                                if (*audio_codec_name)
1673
                                    audio_codec_name_extra = "...";
1674
                                audio_codec_name = codec->name;
1675
                            }
1676
                            break;
1677
                        case CODEC_TYPE_VIDEO:
1678 01f4895c Michael Niedermayer
                            video_bit_rate += st->codec->bit_rate;
1679 a6e14edd Philip Gladstone
                            if (codec) {
1680
                                if (*video_codec_name)
1681
                                    video_codec_name_extra = "...";
1682
                                video_codec_name = codec->name;
1683
                            }
1684
                            break;
1685 e240a0bb Fabrice Bellard
                        case CODEC_TYPE_DATA:
1686 01f4895c Michael Niedermayer
                            video_bit_rate += st->codec->bit_rate;
1687 e240a0bb Fabrice Bellard
                            break;
1688 a6e14edd Philip Gladstone
                        default:
1689 0f4e8165 Ronald S. Bultje
                            abort();
1690 79c4ea3c Philip Gladstone
                        }
1691 85f07f22 Fabrice Bellard
                    }
1692 115329f1 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",
1693 a6e14edd Philip Gladstone
                                 stream->fmt->name,
1694 6edd6884 Fabrice Bellard
                                 stream->bandwidth,
1695 a6e14edd Philip Gladstone
                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1696
                                 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
1697 611c5741 Alex Beregszaszi
                    if (stream->feed)
1698 2effd274 Fabrice Bellard
                        url_fprintf(pb, "<TD>%s", stream->feed->filename);
1699 611c5741 Alex Beregszaszi
                    else
1700 2effd274 Fabrice Bellard
                        url_fprintf(pb, "<TD>%s", stream->feed_filename);
1701
                    url_fprintf(pb, "\n");
1702 85f07f22 Fabrice Bellard
                }
1703 a6e14edd Philip Gladstone
                break;
1704
            default:
1705 2effd274 Fabrice Bellard
                url_fprintf(pb, "<TD align=center> - <TD align=right> - <TD align=right> - <td><td align=right> - <TD>\n");
1706 a6e14edd Philip Gladstone
                break;
1707 85f07f22 Fabrice Bellard
            }
1708
        }
1709
        stream = stream->next;
1710
    }
1711 2effd274 Fabrice Bellard
    url_fprintf(pb, "</TABLE>\n");
1712 a6e14edd Philip Gladstone
1713
    stream = first_stream;
1714
    while (stream != NULL) {
1715
        if (stream->feed == stream) {
1716 2effd274 Fabrice Bellard
            url_fprintf(pb, "<h2>Feed %s</h2>", stream->filename);
1717 cde25790 Philip Gladstone
            if (stream->pid) {
1718 2effd274 Fabrice Bellard
                url_fprintf(pb, "Running as pid %d.\n", stream->pid);
1719 cde25790 Philip Gladstone
1720 2effd274 Fabrice Bellard
#if defined(linux) && !defined(CONFIG_NOCUTILS)
1721
                {
1722
                    FILE *pid_stat;
1723
                    char ps_cmd[64];
1724
1725
                    /* This is somewhat linux specific I guess */
1726 115329f1 Diego Biurrun
                    snprintf(ps_cmd, sizeof(ps_cmd),
1727
                             "ps -o \"%%cpu,cputime\" --no-headers %d",
1728 2effd274 Fabrice Bellard
                             stream->pid);
1729 115329f1 Diego Biurrun
1730 2effd274 Fabrice Bellard
                    pid_stat = popen(ps_cmd, "r");
1731
                    if (pid_stat) {
1732
                        char cpuperc[10];
1733
                        char cpuused[64];
1734 115329f1 Diego Biurrun
1735
                        if (fscanf(pid_stat, "%10s %64s", cpuperc,
1736 2effd274 Fabrice Bellard
                                   cpuused) == 2) {
1737
                            url_fprintf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
1738
                                         cpuperc, cpuused);
1739
                        }
1740
                        fclose(pid_stat);
1741 cde25790 Philip Gladstone
                    }
1742
                }
1743
#endif
1744
1745 2effd274 Fabrice Bellard
                url_fprintf(pb, "<p>");
1746 cde25790 Philip Gladstone
            }
1747 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");
1748 a6e14edd Philip Gladstone
1749
            for (i = 0; i < stream->nb_streams; i++) {
1750
                AVStream *st = stream->streams[i];
1751 01f4895c Michael Niedermayer
                AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1752 b29f97d1 Zdenek Kabelac
                const char *type = "unknown";
1753 b582f314 Philip Gladstone
                char parameters[64];
1754
1755
                parameters[0] = 0;
1756 a6e14edd Philip Gladstone
1757 01f4895c Michael Niedermayer
                switch(st->codec->codec_type) {
1758 a6e14edd Philip Gladstone
                case CODEC_TYPE_AUDIO:
1759
                    type = "audio";
1760 acdc8520 Alex Beregszaszi
                    snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
1761 a6e14edd Philip Gladstone
                    break;
1762
                case CODEC_TYPE_VIDEO:
1763
                    type = "video";
1764 01f4895c Michael Niedermayer
                    snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
1765
                                st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
1766 a6e14edd Philip Gladstone
                    break;
1767
                default:
1768 0f4e8165 Ronald S. Bultje
                    abort();
1769 a6e14edd Philip Gladstone
                }
1770 2effd274 Fabrice Bellard
                url_fprintf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
1771 01f4895c Michael Niedermayer
                        i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
1772 a6e14edd Philip Gladstone
            }
1773 2effd274 Fabrice Bellard
            url_fprintf(pb, "</table>\n");
1774 a6e14edd Philip Gladstone
1775 115329f1 Diego Biurrun
        }
1776 a6e14edd Philip Gladstone
        stream = stream->next;
1777
    }
1778 115329f1 Diego Biurrun
1779 85f07f22 Fabrice Bellard
#if 0
1780
    {
1781
        float avg;
1782
        AVCodecContext *enc;
1783
        char buf[1024];
1784 115329f1 Diego Biurrun

1785 85f07f22 Fabrice Bellard
        /* feed status */
1786
        stream = first_feed;
1787
        while (stream != NULL) {
1788 2effd274 Fabrice Bellard
            url_fprintf(pb, "<H1>Feed '%s'</H1>\n", stream->filename);
1789
            url_fprintf(pb, "<TABLE>\n");
1790
            url_fprintf(pb, "<TR><TD>Parameters<TD>Frame count<TD>Size<TD>Avg bitrate (kbits/s)\n");
1791 85f07f22 Fabrice Bellard
            for(i=0;i<stream->nb_streams;i++) {
1792
                AVStream *st = stream->streams[i];
1793
                FeedData *fdata = st->priv_data;
1794 01f4895c Michael Niedermayer
                enc = st->codec;
1795 115329f1 Diego Biurrun

1796 85f07f22 Fabrice Bellard
                avcodec_string(buf, sizeof(buf), enc);
1797
                avg = fdata->avg_frame_size * (float)enc->rate * 8.0;
1798
                if (enc->codec->type == CODEC_TYPE_AUDIO && enc->frame_size > 0)
1799
                    avg /= enc->frame_size;
1800 949b1a13 Steve L'Homme
                url_fprintf(pb, "<TR><TD>%s <TD> %d <TD> %"PRId64" <TD> %0.1f\n",
1801 85f07f22 Fabrice Bellard
                             buf, enc->frame_number, fdata->data_count, avg / 1000.0);
1802
            }
1803 2effd274 Fabrice Bellard
            url_fprintf(pb, "</TABLE>\n");
1804 85f07f22 Fabrice Bellard
            stream = stream->next_feed;
1805
        }
1806
    }
1807
#endif
1808
1809
    /* connection status */
1810 2effd274 Fabrice Bellard
    url_fprintf(pb, "<H2>Connection Status</H2>\n");
1811 85f07f22 Fabrice Bellard
1812 2effd274 Fabrice Bellard
    url_fprintf(pb, "Number of connections: %d / %d<BR>\n",
1813 85f07f22 Fabrice Bellard
                 nb_connections, nb_max_connections);
1814
1815 2effd274 Fabrice Bellard
    url_fprintf(pb, "Bandwidth in use: %dk / %dk<BR>\n",
1816 6edd6884 Fabrice Bellard
                 current_bandwidth, max_bandwidth);
1817 42a63c6a Philip Gladstone
1818 2effd274 Fabrice Bellard
    url_fprintf(pb, "<TABLE>\n");
1819
    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");
1820 85f07f22 Fabrice Bellard
    c1 = first_http_ctx;
1821
    i = 0;
1822 2effd274 Fabrice Bellard
    while (c1 != NULL) {
1823 cde25790 Philip Gladstone
        int bitrate;
1824
        int j;
1825
1826
        bitrate = 0;
1827 2effd274 Fabrice Bellard
        if (c1->stream) {
1828
            for (j = 0; j < c1->stream->nb_streams; j++) {
1829 2d563d2f Alex Beregszaszi
                if (!c1->stream->feed)
1830 01f4895c Michael Niedermayer
                    bitrate += c1->stream->streams[j]->codec->bit_rate;
1831 2d563d2f Alex Beregszaszi
                else if (c1->feed_streams[j] >= 0)
1832
                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
1833 cde25790 Philip Gladstone
            }
1834
        }
1835
1836 85f07f22 Fabrice Bellard
        i++;
1837
        p = inet_ntoa(c1->from_addr.sin_addr);
1838 115329f1 Diego Biurrun
        url_fprintf(pb, "<TR><TD><B>%d</B><TD>%s%s<TD>%s<TD>%s<TD>%s<td align=right>",
1839
                    i,
1840
                    c1->stream ? c1->stream->filename : "",
1841 2effd274 Fabrice Bellard
                    c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
1842 115329f1 Diego Biurrun
                    p,
1843 2effd274 Fabrice Bellard
                    c1->protocol,
1844
                    http_state[c1->state]);
1845
        fmt_bytecount(pb, bitrate);
1846
        url_fprintf(pb, "<td align=right>");
1847
        fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
1848
        url_fprintf(pb, "<td align=right>");
1849
        fmt_bytecount(pb, c1->data_count);
1850
        url_fprintf(pb, "\n");
1851 85f07f22 Fabrice Bellard
        c1 = c1->next;
1852
    }
1853 2effd274 Fabrice Bellard
    url_fprintf(pb, "</TABLE>\n");
1854 115329f1 Diego Biurrun
1855 85f07f22 Fabrice Bellard
    /* date */
1856
    ti = time(NULL);
1857
    p = ctime(&ti);
1858 2effd274 Fabrice Bellard
    url_fprintf(pb, "<HR size=1 noshade>Generated at %s", p);
1859
    url_fprintf(pb, "</BODY>\n</HTML>\n");
1860 85f07f22 Fabrice Bellard
1861 2effd274 Fabrice Bellard
    len = url_close_dyn_buf(pb, &c->pb_buffer);
1862
    c->buffer_ptr = c->pb_buffer;
1863
    c->buffer_end = c->pb_buffer + len;
1864 85f07f22 Fabrice Bellard
}
1865
1866 2effd274 Fabrice Bellard
/* check if the parser needs to be opened for stream i */
1867
static void open_parser(AVFormatContext *s, int i)
1868 85f07f22 Fabrice Bellard
{
1869 2effd274 Fabrice Bellard
    AVStream *st = s->streams[i];
1870
    AVCodec *codec;
1871 31def229 Philip Gladstone
1872 01f4895c Michael Niedermayer
    if (!st->codec->codec) {
1873
        codec = avcodec_find_decoder(st->codec->codec_id);
1874 2effd274 Fabrice Bellard
        if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
1875 01f4895c Michael Niedermayer
            st->codec->parse_only = 1;
1876 611c5741 Alex Beregszaszi
            if (avcodec_open(st->codec, codec) < 0)
1877 01f4895c Michael Niedermayer
                st->codec->parse_only = 0;
1878 cde25790 Philip Gladstone
        }
1879
    }
1880 85f07f22 Fabrice Bellard
}
1881
1882
static int open_input_stream(HTTPContext *c, const char *info)
1883
{
1884
    char buf[128];
1885
    char input_filename[1024];
1886
    AVFormatContext *s;
1887 2effd274 Fabrice Bellard
    int buf_size, i;
1888 0c1a9eda Zdenek Kabelac
    int64_t stream_pos;
1889 85f07f22 Fabrice Bellard
1890
    /* find file name */
1891
    if (c->stream->feed) {
1892
        strcpy(input_filename, c->stream->feed->feed_filename);
1893
        buf_size = FFM_PACKET_SIZE;
1894
        /* compute position (absolute time) */
1895 611c5741 Alex Beregszaszi
        if (find_info_tag(buf, sizeof(buf), "date", info))
1896 f9436161 Stefano Sabatini
        {
1897 85f07f22 Fabrice Bellard
            stream_pos = parse_date(buf, 0);
1898 f9436161 Stefano Sabatini
            if (stream_pos == INT64_MIN)
1899
                return -1;
1900
        }
1901 611c5741 Alex Beregszaszi
        else if (find_info_tag(buf, sizeof(buf), "buffer", info)) {
1902 f747e6d3 Philip Gladstone
            int prebuffer = strtol(buf, 0, 10);
1903 0c1a9eda Zdenek Kabelac
            stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
1904 611c5741 Alex Beregszaszi
        } else
1905 0c1a9eda Zdenek Kabelac
            stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
1906 85f07f22 Fabrice Bellard
    } else {
1907
        strcpy(input_filename, c->stream->feed_filename);
1908
        buf_size = 0;
1909
        /* compute position (relative time) */
1910 611c5741 Alex Beregszaszi
        if (find_info_tag(buf, sizeof(buf), "date", info))
1911 f9436161 Stefano Sabatini
        {
1912 85f07f22 Fabrice Bellard
            stream_pos = parse_date(buf, 1);
1913 f9436161 Stefano Sabatini
            if (stream_pos == INT64_MIN)
1914
                return -1;
1915
        }
1916 611c5741 Alex Beregszaszi
        else
1917 85f07f22 Fabrice Bellard
            stream_pos = 0;
1918
    }
1919
    if (input_filename[0] == '\0')
1920
        return -1;
1921
1922 8256c0a3 Philip Gladstone
#if 0
1923
    { time_t when = stream_pos / 1000000;
1924 949b1a13 Steve L'Homme
    http_log("Stream pos = %"PRId64", time=%s", stream_pos, ctime(&when));
1925 8256c0a3 Philip Gladstone
    }
1926
#endif
1927
1928 85f07f22 Fabrice Bellard
    /* open stream */
1929 115329f1 Diego Biurrun
    if (av_open_input_file(&s, input_filename, c->stream->ifmt,
1930 e240a0bb Fabrice Bellard
                           buf_size, c->stream->ap_in) < 0) {
1931 2effd274 Fabrice Bellard
        http_log("%s not found", input_filename);
1932 85f07f22 Fabrice Bellard
        return -1;
1933 2effd274 Fabrice Bellard
    }
1934 9dc0bc3d Luca Abeni
    s->flags |= AVFMT_FLAG_GENPTS;
1935 85f07f22 Fabrice Bellard
    c->fmt_in = s;
1936 89da5781 Luca Abeni
    av_find_stream_info(c->fmt_in);
1937 115329f1 Diego Biurrun
1938 2effd274 Fabrice Bellard
    /* open each parser */
1939
    for(i=0;i<s->nb_streams;i++)
1940
        open_parser(s, i);
1941
1942
    /* choose stream as clock source (we favorize video stream if
1943
       present) for packet sending */
1944
    c->pts_stream_index = 0;
1945
    for(i=0;i<c->stream->nb_streams;i++) {
1946 115329f1 Diego Biurrun
        if (c->pts_stream_index == 0 &&
1947 01f4895c Michael Niedermayer
            c->stream->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
1948 2effd274 Fabrice Bellard
            c->pts_stream_index = i;
1949
        }
1950
    }
1951 85f07f22 Fabrice Bellard
1952 e8d27bc3 Philip Gladstone
#if 1
1953 611c5741 Alex Beregszaszi
    if (c->fmt_in->iformat->read_seek)
1954 e8d27bc3 Philip Gladstone
        c->fmt_in->iformat->read_seek(c->fmt_in, 0, stream_pos, 0);
1955 e240a0bb Fabrice Bellard
#endif
1956 2effd274 Fabrice Bellard
    /* set the start time (needed for maxtime and RTP packet timing) */
1957
    c->start_time = cur_time;
1958
    c->first_pts = AV_NOPTS_VALUE;
1959 85f07f22 Fabrice Bellard
    return 0;
1960
}
1961
1962 e240a0bb Fabrice Bellard
/* return the server clock (in us) */
1963
static int64_t get_server_clock(HTTPContext *c)
1964 2effd274 Fabrice Bellard
{
1965 e240a0bb Fabrice Bellard
    /* compute current pts value from system time */
1966 c3f58185 Alex Beregszaszi
    return (cur_time - c->start_time) * 1000;
1967 2effd274 Fabrice Bellard
}
1968
1969 e240a0bb Fabrice Bellard
/* return the estimated time at which the current packet must be sent
1970
   (in us) */
1971
static int64_t get_packet_send_clock(HTTPContext *c)
1972 2effd274 Fabrice Bellard
{
1973 e240a0bb Fabrice Bellard
    int bytes_left, bytes_sent, frame_bytes;
1974 115329f1 Diego Biurrun
1975 e240a0bb Fabrice Bellard
    frame_bytes = c->cur_frame_bytes;
1976 611c5741 Alex Beregszaszi
    if (frame_bytes <= 0)
1977 e240a0bb Fabrice Bellard
        return c->cur_pts;
1978 611c5741 Alex Beregszaszi
    else {
1979 e240a0bb Fabrice Bellard
        bytes_left = c->buffer_end - c->buffer_ptr;
1980
        bytes_sent = frame_bytes - bytes_left;
1981
        return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
1982 2effd274 Fabrice Bellard
    }
1983
}
1984
1985
1986
static int http_prepare_data(HTTPContext *c)
1987
{
1988
    int i, len, ret;
1989
    AVFormatContext *ctx;
1990
1991 bc351386 Fabrice Bellard
    av_freep(&c->pb_buffer);
1992 2effd274 Fabrice Bellard
    switch(c->state) {
1993
    case HTTPSTATE_SEND_DATA_HEADER:
1994
        memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
1995 f7d78f36 Måns Rullgård
        av_strlcpy(c->fmt_ctx.author, c->stream->author,
1996
                   sizeof(c->fmt_ctx.author));
1997
        av_strlcpy(c->fmt_ctx.comment, c->stream->comment,
1998
                   sizeof(c->fmt_ctx.comment));
1999
        av_strlcpy(c->fmt_ctx.copyright, c->stream->copyright,
2000
                   sizeof(c->fmt_ctx.copyright));
2001
        av_strlcpy(c->fmt_ctx.title, c->stream->title,
2002
                   sizeof(c->fmt_ctx.title));
2003 2effd274 Fabrice Bellard
2004
        /* open output stream by using specified codecs */
2005
        c->fmt_ctx.oformat = c->stream->fmt;
2006
        c->fmt_ctx.nb_streams = c->stream->nb_streams;
2007
        for(i=0;i<c->fmt_ctx.nb_streams;i++) {
2008
            AVStream *st;
2009 bb270c08 Diego Biurrun
            AVStream *src;
2010 2effd274 Fabrice Bellard
            st = av_mallocz(sizeof(AVStream));
2011 8d931070 Michael Niedermayer
            st->codec= avcodec_alloc_context();
2012 2effd274 Fabrice Bellard
            c->fmt_ctx.streams[i] = st;
2013
            /* if file or feed, then just take streams from FFStream struct */
2014 115329f1 Diego Biurrun
            if (!c->stream->feed ||
2015 2effd274 Fabrice Bellard
                c->stream->feed == c->stream)
2016 7c054ea7 Philip Gladstone
                src = c->stream->streams[i];
2017 2effd274 Fabrice Bellard
            else
2018 7c054ea7 Philip Gladstone
                src = c->stream->feed->streams[c->stream->feed_streams[i]];
2019
2020 bb270c08 Diego Biurrun
            *st = *src;
2021
            st->priv_data = 0;
2022 01f4895c Michael Niedermayer
            st->codec->frame_number = 0; /* XXX: should be done in
2023 2effd274 Fabrice Bellard
                                           AVStream, not in codec */
2024 a4d70941 Philip Gladstone
            /* I'm pretty sure that this is not correct...
2025
             * However, without it, we crash
2026
             */
2027 01f4895c Michael Niedermayer
            st->codec->coded_frame = &dummy_frame;
2028 2effd274 Fabrice Bellard
        }
2029
        c->got_key_frame = 0;
2030
2031
        /* prepare header and save header data in a stream */
2032
        if (url_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2033
            /* XXX: potential leak */
2034
            return -1;
2035
        }
2036 899681cd Björn Axelsson
        c->fmt_ctx.pb->is_streamed = 1;
2037 2effd274 Fabrice Bellard
2038 3c27199b Fabrice Bellard
        av_set_parameters(&c->fmt_ctx, NULL);
2039 f75cdda7 Alex Beregszaszi
        if (av_write_header(&c->fmt_ctx) < 0)
2040
            return -1;
2041 2effd274 Fabrice Bellard
2042 899681cd Björn Axelsson
        len = url_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2043 2effd274 Fabrice Bellard
        c->buffer_ptr = c->pb_buffer;
2044
        c->buffer_end = c->pb_buffer + len;
2045
2046
        c->state = HTTPSTATE_SEND_DATA;
2047 85f07f22 Fabrice Bellard
        c->last_packet_sent = 0;
2048
        break;
2049
    case HTTPSTATE_SEND_DATA:
2050
        /* find a new packet */
2051
        {
2052
            AVPacket pkt;
2053 115329f1 Diego Biurrun
2054 85f07f22 Fabrice Bellard
            /* read a packet from the input stream */
2055 611c5741 Alex Beregszaszi
            if (c->stream->feed)
2056 115329f1 Diego Biurrun
                ffm_set_write_index(c->fmt_in,
2057 85f07f22 Fabrice Bellard
                                    c->stream->feed->feed_write_index,
2058
                                    c->stream->feed->feed_size);
2059 ec3b2232 Philip Gladstone
2060 115329f1 Diego Biurrun
            if (c->stream->max_time &&
2061 611c5741 Alex Beregszaszi
                c->stream->max_time + c->start_time - cur_time < 0)
2062 ec3b2232 Philip Gladstone
                /* We have timed out */
2063
                c->state = HTTPSTATE_SEND_DATA_TRAILER;
2064 611c5741 Alex Beregszaszi
            else {
2065 6edd6884 Fabrice Bellard
            redo:
2066 2effd274 Fabrice Bellard
                if (av_read_frame(c->fmt_in, &pkt) < 0) {
2067
                    if (c->stream->feed && c->stream->feed->feed_opened) {
2068
                        /* if coming from feed, it means we reached the end of the
2069
                           ffm file, so must wait for more data */
2070
                        c->state = HTTPSTATE_WAIT_FEED;
2071
                        return 1; /* state changed */
2072
                    } else {
2073 6edd6884 Fabrice Bellard
                        if (c->stream->loop) {
2074
                            av_close_input_file(c->fmt_in);
2075
                            c->fmt_in = NULL;
2076
                            if (open_input_stream(c, "") < 0)
2077
                                goto no_loop;
2078
                            goto redo;
2079
                        } else {
2080
                        no_loop:
2081
                            /* must send trailer now because eof or error */
2082
                            c->state = HTTPSTATE_SEND_DATA_TRAILER;
2083
                        }
2084 2effd274 Fabrice Bellard
                    }
2085
                } else {
2086
                    /* update first pts if needed */
2087 1bc1cfdd Giancarlo Formicuccia
                    if (c->first_pts == AV_NOPTS_VALUE) {
2088 c0df9d75 Michael Niedermayer
                        c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2089 1bc1cfdd Giancarlo Formicuccia
                        c->start_time = cur_time;
2090
                    }
2091 2effd274 Fabrice Bellard
                    /* send it to the appropriate stream */
2092
                    if (c->stream->feed) {
2093
                        /* if coming from a feed, select the right stream */
2094
                        if (c->switch_pending) {
2095
                            c->switch_pending = 0;
2096
                            for(i=0;i<c->stream->nb_streams;i++) {
2097 611c5741 Alex Beregszaszi
                                if (c->switch_feed_streams[i] == pkt.stream_index)
2098
                                    if (pkt.flags & PKT_FLAG_KEY)
2099 2effd274 Fabrice Bellard
                                        do_switch_stream(c, i);
2100 611c5741 Alex Beregszaszi
                                if (c->switch_feed_streams[i] >= 0)
2101 2effd274 Fabrice Bellard
                                    c->switch_pending = 1;
2102
                            }
2103
                        }
2104 cde25790 Philip Gladstone
                        for(i=0;i<c->stream->nb_streams;i++) {
2105 2effd274 Fabrice Bellard
                            if (c->feed_streams[i] == pkt.stream_index) {
2106
                                pkt.stream_index = i;
2107 611c5741 Alex Beregszaszi
                                if (pkt.flags & PKT_FLAG_KEY)
2108 2effd274 Fabrice Bellard
                                    c->got_key_frame |= 1 << i;
2109 115329f1 Diego Biurrun
                                /* See if we have all the key frames, then
2110 2effd274 Fabrice Bellard
                                 * we start to send. This logic is not quite
2111 115329f1 Diego Biurrun
                                 * right, but it works for the case of a
2112 2effd274 Fabrice Bellard
                                 * single video stream with one or more
2113 115329f1 Diego Biurrun
                                 * audio streams (for which every frame is
2114
                                 * typically a key frame).
2115 2effd274 Fabrice Bellard
                                 */
2116 115329f1 Diego Biurrun
                                if (!c->stream->send_on_key ||
2117 611c5741 Alex Beregszaszi
                                    ((c->got_key_frame + 1) >> c->stream->nb_streams))
2118 2effd274 Fabrice Bellard
                                    goto send_it;
2119 cde25790 Philip Gladstone
                            }
2120
                        }
2121 2effd274 Fabrice Bellard
                    } else {
2122
                        AVCodecContext *codec;
2123 115329f1 Diego Biurrun
2124 2effd274 Fabrice Bellard
                    send_it:
2125
                        /* specific handling for RTP: we use several
2126
                           output stream (one for each RTP
2127
                           connection). XXX: need more abstract handling */
2128
                        if (c->is_packetized) {
2129 e240a0bb Fabrice Bellard
                            AVStream *st;
2130
                            /* compute send time and duration */
2131
                            st = c->fmt_in->streams[pkt.stream_index];
2132 c0df9d75 Michael Niedermayer
                            c->cur_pts = av_rescale_q(pkt.dts, st->time_base, AV_TIME_BASE_Q);
2133 e240a0bb Fabrice Bellard
                            if (st->start_time != AV_NOPTS_VALUE)
2134 c0df9d75 Michael Niedermayer
                                c->cur_pts -= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
2135
                            c->cur_frame_duration = av_rescale_q(pkt.duration, st->time_base, AV_TIME_BASE_Q);
2136 e240a0bb Fabrice Bellard
#if 0
2137
                            printf("index=%d pts=%0.3f duration=%0.6f\n",
2138
                                   pkt.stream_index,
2139 115329f1 Diego Biurrun
                                   (double)c->cur_pts /
2140 e240a0bb Fabrice Bellard
                                   AV_TIME_BASE,
2141 115329f1 Diego Biurrun
                                   (double)c->cur_frame_duration /
2142 e240a0bb Fabrice Bellard
                                   AV_TIME_BASE);
2143
#endif
2144
                            /* find RTP context */
2145 2effd274 Fabrice Bellard
                            c->packet_stream_index = pkt.stream_index;
2146
                            ctx = c->rtp_ctx[c->packet_stream_index];
2147 1b52b6bd Michael Niedermayer
                            if(!ctx) {
2148
                              av_free_packet(&pkt);
2149 1bc1cfdd Giancarlo Formicuccia
                              break;
2150 1b52b6bd Michael Niedermayer
                            }
2151 01f4895c Michael Niedermayer
                            codec = ctx->streams[0]->codec;
2152 6edd6884 Fabrice Bellard
                            /* only one stream per RTP connection */
2153
                            pkt.stream_index = 0;
2154 2effd274 Fabrice Bellard
                        } else {
2155
                            ctx = &c->fmt_ctx;
2156
                            /* Fudge here */
2157 01f4895c Michael Niedermayer
                            codec = ctx->streams[pkt.stream_index]->codec;
2158 85f07f22 Fabrice Bellard
                        }
2159 115329f1 Diego Biurrun
2160 492cd3a9 Michael Niedermayer
                        codec->coded_frame->key_frame = ((pkt.flags & PKT_FLAG_KEY) != 0);
2161 2effd274 Fabrice Bellard
                        if (c->is_packetized) {
2162 bc351386 Fabrice Bellard
                            int max_packet_size;
2163
                            if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP)
2164
                                max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2165
                            else
2166
                                max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
2167
                            ret = url_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2168 2effd274 Fabrice Bellard
                        } else {
2169
                            ret = url_open_dyn_buf(&ctx->pb);
2170
                        }
2171
                        if (ret < 0) {
2172
                            /* XXX: potential leak */
2173
                            return -1;
2174
                        }
2175 f1debfd0 Alex Beregszaszi
                        if (pkt.dts != AV_NOPTS_VALUE)
2176
                            pkt.dts = av_rescale_q(pkt.dts,
2177
                                c->fmt_in->streams[pkt.stream_index]->time_base,
2178
                                ctx->streams[pkt.stream_index]->time_base);
2179
                        if (pkt.pts != AV_NOPTS_VALUE)
2180
                            pkt.pts = av_rescale_q(pkt.pts,
2181
                                c->fmt_in->streams[pkt.stream_index]->time_base,
2182
                                ctx->streams[pkt.stream_index]->time_base);
2183 611c5741 Alex Beregszaszi
                        if (av_write_frame(ctx, &pkt))
2184 2effd274 Fabrice Bellard
                            c->state = HTTPSTATE_SEND_DATA_TRAILER;
2185 115329f1 Diego Biurrun
2186 899681cd Björn Axelsson
                        len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
2187 e240a0bb Fabrice Bellard
                        c->cur_frame_bytes = len;
2188 2effd274 Fabrice Bellard
                        c->buffer_ptr = c->pb_buffer;
2189
                        c->buffer_end = c->pb_buffer + len;
2190 115329f1 Diego Biurrun
2191 2effd274 Fabrice Bellard
                        codec->frame_number++;
2192 e240a0bb Fabrice Bellard
                        if (len == 0)
2193
                            goto redo;
2194 f747e6d3 Philip Gladstone
                    }
2195 2effd274 Fabrice Bellard
                    av_free_packet(&pkt);
2196 85f07f22 Fabrice Bellard
                }
2197
            }
2198
        }
2199
        break;
2200
    default:
2201
    case HTTPSTATE_SEND_DATA_TRAILER:
2202
        /* last packet test ? */
2203 2effd274 Fabrice Bellard
        if (c->last_packet_sent || c->is_packetized)
2204 85f07f22 Fabrice Bellard
            return -1;
2205 2effd274 Fabrice Bellard
        ctx = &c->fmt_ctx;
2206 85f07f22 Fabrice Bellard
        /* prepare header */
2207 2effd274 Fabrice Bellard
        if (url_open_dyn_buf(&ctx->pb) < 0) {
2208
            /* XXX: potential leak */
2209
            return -1;
2210
        }
2211
        av_write_trailer(ctx);
2212 899681cd Björn Axelsson
        len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
2213 2effd274 Fabrice Bellard
        c->buffer_ptr = c->pb_buffer;
2214
        c->buffer_end = c->pb_buffer + len;
2215
2216 85f07f22 Fabrice Bellard
        c->last_packet_sent = 1;
2217
        break;
2218
    }
2219
    return 0;
2220
}
2221
2222
/* should convert the format at the same time */
2223 bc351386 Fabrice Bellard
/* send data starting at c->buffer_ptr to the output connection
2224
   (either UDP or TCP connection) */
2225 5eb765ef Philip Gladstone
static int http_send_data(HTTPContext *c)
2226 85f07f22 Fabrice Bellard
{
2227 e240a0bb Fabrice Bellard
    int len, ret;
2228 85f07f22 Fabrice Bellard
2229 bc351386 Fabrice Bellard
    for(;;) {
2230
        if (c->buffer_ptr >= c->buffer_end) {
2231
            ret = http_prepare_data(c);
2232
            if (ret < 0)
2233
                return -1;
2234 611c5741 Alex Beregszaszi
            else if (ret != 0)
2235 bc351386 Fabrice Bellard
                /* state change requested */
2236
                break;
2237 2effd274 Fabrice Bellard
        } else {
2238 bc351386 Fabrice Bellard
            if (c->is_packetized) {
2239
                /* RTP data output */
2240
                len = c->buffer_end - c->buffer_ptr;
2241
                if (len < 4) {
2242
                    /* fail safe - should never happen */
2243
                fail1:
2244
                    c->buffer_ptr = c->buffer_end;
2245 2effd274 Fabrice Bellard
                    return 0;
2246
                }
2247 bc351386 Fabrice Bellard
                len = (c->buffer_ptr[0] << 24) |
2248
                    (c->buffer_ptr[1] << 16) |
2249
                    (c->buffer_ptr[2] << 8) |
2250
                    (c->buffer_ptr[3]);
2251
                if (len > (c->buffer_end - c->buffer_ptr))
2252
                    goto fail1;
2253 e240a0bb Fabrice Bellard
                if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2254
                    /* nothing to send yet: we can wait */
2255
                    return 0;
2256
                }
2257
2258
                c->data_count += len;
2259
                update_datarate(&c->datarate, c->data_count);
2260
                if (c->stream)
2261
                    c->stream->bytes_served += len;
2262
2263 bc351386 Fabrice Bellard
                if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP) {
2264
                    /* RTP packets are sent inside the RTSP TCP connection */
2265 899681cd Björn Axelsson
                    ByteIOContext *pb;
2266 bc351386 Fabrice Bellard
                    int interleaved_index, size;
2267
                    uint8_t header[4];
2268
                    HTTPContext *rtsp_c;
2269 115329f1 Diego Biurrun
2270 bc351386 Fabrice Bellard
                    rtsp_c = c->rtsp_c;
2271
                    /* if no RTSP connection left, error */
2272
                    if (!rtsp_c)
2273
                        return -1;
2274
                    /* if already sending something, then wait. */
2275 611c5741 Alex Beregszaszi
                    if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2276 bc351386 Fabrice Bellard
                        break;
2277 899681cd Björn Axelsson
                    if (url_open_dyn_buf(&pb) < 0)
2278 bc351386 Fabrice Bellard
                        goto fail1;
2279
                    interleaved_index = c->packet_stream_index * 2;
2280
                    /* RTCP packets are sent at odd indexes */
2281
                    if (c->buffer_ptr[1] == 200)
2282
                        interleaved_index++;
2283
                    /* write RTSP TCP header */
2284
                    header[0] = '$';
2285
                    header[1] = interleaved_index;
2286
                    header[2] = len >> 8;
2287
                    header[3] = len;
2288
                    put_buffer(pb, header, 4);
2289
                    /* write RTP packet data */
2290
                    c->buffer_ptr += 4;
2291
                    put_buffer(pb, c->buffer_ptr, len);
2292
                    size = url_close_dyn_buf(pb, &c->packet_buffer);
2293
                    /* prepare asynchronous TCP sending */
2294
                    rtsp_c->packet_buffer_ptr = c->packet_buffer;
2295
                    rtsp_c->packet_buffer_end = c->packet_buffer + size;
2296 e240a0bb Fabrice Bellard
                    c->buffer_ptr += len;
2297 115329f1 Diego Biurrun
2298 e240a0bb Fabrice Bellard
                    /* send everything we can NOW */
2299 c60202df Alex Beregszaszi
                    len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2300
                                rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2301 611c5741 Alex Beregszaszi
                    if (len > 0)
2302 e240a0bb Fabrice Bellard
                        rtsp_c->packet_buffer_ptr += len;
2303
                    if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2304
                        /* if we could not send all the data, we will
2305
                           send it later, so a new state is needed to
2306
                           "lock" the RTSP TCP connection */
2307
                        rtsp_c->state = RTSPSTATE_SEND_PACKET;
2308
                        break;
2309 611c5741 Alex Beregszaszi
                    } else
2310 e240a0bb Fabrice Bellard
                        /* all data has been sent */
2311
                        av_freep(&c->packet_buffer);
2312
                } else {
2313
                    /* send RTP packet directly in UDP */
2314 bc351386 Fabrice Bellard
                    c->buffer_ptr += 4;
2315 115329f1 Diego Biurrun
                    url_write(c->rtp_handles[c->packet_stream_index],
2316 bc351386 Fabrice Bellard
                              c->buffer_ptr, len);
2317 e240a0bb Fabrice Bellard
                    c->buffer_ptr += len;
2318
                    /* here we continue as we can send several packets per 10 ms slot */
2319 bc351386 Fabrice Bellard
                }
2320
            } else {
2321
                /* TCP data output */
2322 c60202df Alex Beregszaszi
                len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2323 bc351386 Fabrice Bellard
                if (len < 0) {
2324 8da4034f Alex Beregszaszi
                    if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2325 611c5741 Alex Beregszaszi
                        ff_neterrno() != FF_NETERROR(EINTR))
2326 bc351386 Fabrice Bellard
                        /* error : close connection */
2327
                        return -1;
2328 611c5741 Alex Beregszaszi
                    else
2329 bc351386 Fabrice Bellard
                        return 0;
2330 611c5741 Alex Beregszaszi
                } else
2331 bc351386 Fabrice Bellard
                    c->buffer_ptr += len;
2332 611c5741 Alex Beregszaszi
2333 e240a0bb Fabrice Bellard
                c->data_count += len;
2334
                update_datarate(&c->datarate, c->data_count);
2335
                if (c->stream)
2336
                    c->stream->bytes_served += len;
2337
                break;
2338 2effd274 Fabrice Bellard
            }
2339 85f07f22 Fabrice Bellard
        }
2340 bc351386 Fabrice Bellard
    } /* for(;;) */
2341 85f07f22 Fabrice Bellard
    return 0;
2342
}
2343
2344
static int http_start_receive_data(HTTPContext *c)
2345
{
2346
    int fd;
2347
2348
    if (c->stream->feed_opened)
2349
        return -1;
2350
2351 e322ea48 Philip Gladstone
    /* Don't permit writing to this one */
2352
    if (c->stream->readonly)
2353
        return -1;
2354
2355 85f07f22 Fabrice Bellard
    /* open feed */
2356
    fd = open(c->stream->feed_filename, O_RDWR);
2357
    if (fd < 0)
2358
        return -1;
2359
    c->feed_fd = fd;
2360 115329f1 Diego Biurrun
2361 85f07f22 Fabrice Bellard
    c->stream->feed_write_index = ffm_read_write_index(fd);
2362
    c->stream->feed_size = lseek(fd, 0, SEEK_END);
2363
    lseek(fd, 0, SEEK_SET);
2364
2365
    /* init buffer input */
2366
    c->buffer_ptr = c->buffer;
2367
    c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2368
    c->stream->feed_opened = 1;
2369
    return 0;
2370
}
2371 115329f1 Diego Biurrun
2372 85f07f22 Fabrice Bellard
static int http_receive_data(HTTPContext *c)
2373
{
2374
    HTTPContext *c1;
2375
2376 a6e14edd Philip Gladstone
    if (c->buffer_end > c->buffer_ptr) {
2377
        int len;
2378
2379 c60202df Alex Beregszaszi
        len = recv(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2380 a6e14edd Philip Gladstone
        if (len < 0) {
2381 8da4034f Alex Beregszaszi
            if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2382 611c5741 Alex Beregszaszi
                ff_neterrno() != FF_NETERROR(EINTR))
2383 a6e14edd Philip Gladstone
                /* error : close connection */
2384
                goto fail;
2385 611c5741 Alex Beregszaszi
        } else if (len == 0)
2386 a6e14edd Philip Gladstone
            /* end of connection : close it */
2387
            goto fail;
2388 611c5741 Alex Beregszaszi
        else {
2389 a6e14edd Philip Gladstone
            c->buffer_ptr += len;
2390
            c->data_count += len;
2391 5eb765ef Philip Gladstone
            update_datarate(&c->datarate, c->data_count);
2392 a6e14edd Philip Gladstone
        }
2393
    }
2394
2395 d445a7e9 Philip Gladstone
    if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2396
        if (c->buffer[0] != 'f' ||
2397
            c->buffer[1] != 'm') {
2398
            http_log("Feed stream has become desynchronized -- disconnecting\n");
2399
            goto fail;
2400
        }
2401
    }
2402
2403 85f07f22 Fabrice Bellard
    if (c->buffer_ptr >= c->buffer_end) {
2404 f747e6d3 Philip Gladstone
        FFStream *feed = c->stream;
2405 85f07f22 Fabrice Bellard
        /* a packet has been received : write it in the store, except
2406
           if header */
2407
        if (c->data_count > FFM_PACKET_SIZE) {
2408 115329f1 Diego Biurrun
2409 949b1a13 Steve L'Homme
            //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2410 85f07f22 Fabrice Bellard
            /* XXX: use llseek or url_seek */
2411
            lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2412
            write(c->feed_fd, c->buffer, FFM_PACKET_SIZE);
2413 115329f1 Diego Biurrun
2414 85f07f22 Fabrice Bellard
            feed->feed_write_index += FFM_PACKET_SIZE;
2415
            /* update file size */
2416
            if (feed->feed_write_index > c->stream->feed_size)
2417
                feed->feed_size = feed->feed_write_index;
2418
2419
            /* handle wrap around if max file size reached */
2420 6b0bdc75 Alex Beregszaszi
            if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2421 85f07f22 Fabrice Bellard
                feed->feed_write_index = FFM_PACKET_SIZE;
2422
2423
            /* write index */
2424
            ffm_write_write_index(c->feed_fd, feed->feed_write_index);
2425
2426
            /* wake up any waiting connections */
2427
            for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2428 115329f1 Diego Biurrun
                if (c1->state == HTTPSTATE_WAIT_FEED &&
2429 611c5741 Alex Beregszaszi
                    c1->stream->feed == c->stream->feed)
2430 85f07f22 Fabrice Bellard
                    c1->state = HTTPSTATE_SEND_DATA;
2431
            }
2432 f747e6d3 Philip Gladstone
        } else {
2433
            /* We have a header in our hands that contains useful data */
2434
            AVFormatContext s;
2435 bd7cf6ad Fabrice Bellard
            AVInputFormat *fmt_in;
2436 f747e6d3 Philip Gladstone
            int i;
2437
2438
            memset(&s, 0, sizeof(s));
2439
2440 899681cd Björn Axelsson
            url_open_buf(&s.pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
2441
            s.pb->is_streamed = 1;
2442 f747e6d3 Philip Gladstone
2443 bd7cf6ad Fabrice Bellard
            /* use feed output format name to find corresponding input format */
2444
            fmt_in = av_find_input_format(feed->fmt->name);
2445
            if (!fmt_in)
2446
                goto fail;
2447
2448 98486a6b Roman Shaposhnik
            if (fmt_in->priv_data_size > 0) {
2449
                s.priv_data = av_mallocz(fmt_in->priv_data_size);
2450
                if (!s.priv_data)
2451
                    goto fail;
2452 bb270c08 Diego Biurrun
            } else
2453
                s.priv_data = NULL;
2454 ec3b2232 Philip Gladstone
2455 bd7cf6ad Fabrice Bellard
            if (fmt_in->read_header(&s, 0) < 0) {
2456 ec3b2232 Philip Gladstone
                av_freep(&s.priv_data);
2457 f747e6d3 Philip Gladstone
                goto fail;
2458
            }
2459
2460
            /* Now we have the actual streams */
2461
            if (s.nb_streams != feed->nb_streams) {
2462 ec3b2232 Philip Gladstone
                av_freep(&s.priv_data);
2463 f747e6d3 Philip Gladstone
                goto fail;
2464
            }
2465 611c5741 Alex Beregszaszi
            for (i = 0; i < s.nb_streams; i++)
2466 115329f1 Diego Biurrun
                memcpy(feed->streams[i]->codec,
2467 01f4895c Michael Niedermayer
                       s.streams[i]->codec, sizeof(AVCodecContext));
2468 ec3b2232 Philip Gladstone
            av_freep(&s.priv_data);
2469 85f07f22 Fabrice Bellard
        }
2470
        c->buffer_ptr = c->buffer;
2471
    }
2472
2473
    return 0;
2474
 fail:
2475
    c->stream->feed_opened = 0;
2476
    close(c->feed_fd);
2477
    return -1;
2478
}
2479
2480 2effd274 Fabrice Bellard
/********************************************************************/
2481
/* RTSP handling */
2482
2483
static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2484
{
2485
    const char *str;
2486
    time_t ti;
2487
    char *p;
2488
    char buf2[32];
2489
2490
    switch(error_number) {
2491 7e665cd3 Luca Abeni
    case RTSP_STATUS_OK:
2492
        str = "OK";
2493
        break;
2494
    case RTSP_STATUS_METHOD:
2495
        str = "Method Not Allowed";
2496
        break;
2497
    case RTSP_STATUS_BANDWIDTH:
2498
        str = "Not Enough Bandwidth";
2499
        break;
2500
    case RTSP_STATUS_SESSION:
2501
        str = "Session Not Found";
2502
        break;
2503
    case RTSP_STATUS_STATE:
2504
        str = "Method Not Valid in This State";
2505
        break;
2506
    case RTSP_STATUS_AGGREGATE:
2507
        str = "Aggregate operation not allowed";
2508
        break;
2509
    case RTSP_STATUS_ONLY_AGGREGATE:
2510
        str = "Only aggregate operation allowed";
2511
        break;
2512
    case RTSP_STATUS_TRANSPORT:
2513
        str = "Unsupported transport";
2514
        break;
2515
    case RTSP_STATUS_INTERNAL:
2516
        str = "Internal Server Error";
2517
        break;
2518
    case RTSP_STATUS_SERVICE:
2519
        str = "Service Unavailable";
2520
        break;
2521
    case RTSP_STATUS_VERSION:
2522
        str = "RTSP Version not supported";
2523
        break;
2524 2effd274 Fabrice Bellard
    default:
2525
        str = "Unknown Error";
2526
        break;
2527
    }
2528 115329f1 Diego Biurrun
2529 2effd274 Fabrice Bellard
    url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2530
    url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2531
2532
    /* output GMT time */
2533
    ti = time(NULL);
2534
    p = ctime(&ti);
2535
    strcpy(buf2, p);
2536
    p = buf2 + strlen(p) - 1;
2537
    if (*p == '\n')
2538
        *p = '\0';
2539
    url_fprintf(c->pb, "Date: %s GMT\r\n", buf2);
2540
}
2541
2542
static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2543
{
2544
    rtsp_reply_header(c, error_number);
2545
    url_fprintf(c->pb, "\r\n");
2546
}
2547
2548
static int rtsp_parse_request(HTTPContext *c)
2549
{
2550
    const char *p, *p1, *p2;
2551
    char cmd[32];
2552
    char url[1024];
2553
    char protocol[32];
2554
    char line[1024];
2555
    int len;
2556
    RTSPHeader header1, *header = &header1;
2557 115329f1 Diego Biurrun
2558 2effd274 Fabrice Bellard
    c->buffer_ptr[0] = '\0';
2559
    p = c->buffer;
2560 115329f1 Diego Biurrun
2561 2effd274 Fabrice Bellard
    get_word(cmd, sizeof(cmd), &p);
2562
    get_word(url, sizeof(url), &p);
2563
    get_word(protocol, sizeof(protocol), &p);
2564
2565 f7d78f36 Måns Rullgård
    av_strlcpy(c->method, cmd, sizeof(c->method));
2566
    av_strlcpy(c->url, url, sizeof(c->url));
2567
    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2568 2effd274 Fabrice Bellard
2569 899681cd Björn Axelsson
    if (url_open_dyn_buf(&c->pb) < 0) {
2570 2effd274 Fabrice Bellard
        /* XXX: cannot do more */
2571
        c->pb = NULL; /* safety */
2572
        return -1;
2573
    }
2574
2575
    /* check version name */
2576
    if (strcmp(protocol, "RTSP/1.0") != 0) {
2577
        rtsp_reply_error(c, RTSP_STATUS_VERSION);
2578
        goto the_end;
2579
    }
2580
2581
    /* parse each header line */
2582
    memset(header, 0, sizeof(RTSPHeader));
2583
    /* skip to next line */
2584
    while (*p != '\n' && *p != '\0')
2585
        p++;
2586
    if (*p == '\n')
2587
        p++;
2588
    while (*p != '\0') {
2589
        p1 = strchr(p, '\n');
2590
        if (!p1)
2591
            break;
2592
        p2 = p1;
2593
        if (p2 > p && p2[-1] == '\r')
2594
            p2--;
2595
        /* skip empty line */
2596
        if (p2 == p)
2597
            break;
2598
        len = p2 - p;
2599
        if (len > sizeof(line) - 1)
2600
            len = sizeof(line) - 1;
2601
        memcpy(line, p, len);
2602
        line[len] = '\0';
2603
        rtsp_parse_line(header, line);
2604
        p = p1 + 1;
2605
    }
2606
2607
    /* handle sequence number */
2608
    c->seq = header->seq;
2609
2610 611c5741 Alex Beregszaszi
    if (!strcmp(cmd, "DESCRIBE"))
2611 2effd274 Fabrice Bellard
        rtsp_cmd_describe(c, url);
2612 611c5741 Alex Beregszaszi
    else if (!strcmp(cmd, "OPTIONS"))
2613 0df65975 Andriy Rysin
        rtsp_cmd_options(c, url);
2614 611c5741 Alex Beregszaszi
    else if (!strcmp(cmd, "SETUP"))
2615 2effd274 Fabrice Bellard
        rtsp_cmd_setup(c, url, header);
2616 611c5741 Alex Beregszaszi
    else if (!strcmp(cmd, "PLAY"))
2617 2effd274 Fabrice Bellard
        rtsp_cmd_play(c, url, header);
2618 611c5741 Alex Beregszaszi
    else if (!strcmp(cmd, "PAUSE"))
2619 2effd274 Fabrice Bellard
        rtsp_cmd_pause(c, url, header);
2620 611c5741 Alex Beregszaszi
    else if (!strcmp(cmd, "TEARDOWN"))
2621 2effd274 Fabrice Bellard
        rtsp_cmd_teardown(c, url, header);
2622 611c5741 Alex Beregszaszi
    else
2623 2effd274 Fabrice Bellard
        rtsp_reply_error(c, RTSP_STATUS_METHOD);
2624 611c5741 Alex Beregszaszi
2625 2effd274 Fabrice Bellard
 the_end:
2626
    len = url_close_dyn_buf(c->pb, &c->pb_buffer);
2627
    c->pb = NULL; /* safety */
2628
    if (len < 0) {
2629
        /* XXX: cannot do more */
2630
        return -1;
2631
    }
2632
    c->buffer_ptr = c->pb_buffer;
2633
    c->buffer_end = c->pb_buffer + len;
2634
    c->state = RTSPSTATE_SEND_REPLY;
2635
    return 0;
2636
}
2637
2638 115329f1 Diego Biurrun
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2639 829ac53d Fabrice Bellard
                                   struct in_addr my_ip)
2640 2effd274 Fabrice Bellard
{
2641 dd723472 Luca Abeni
    AVFormatContext *avc;
2642
    AVStream avs[MAX_STREAMS];
2643
    int i;
2644 115329f1 Diego Biurrun
2645 dd723472 Luca Abeni
    avc =  av_alloc_format_context();
2646
    if (avc == NULL) {
2647 2effd274 Fabrice Bellard
        return -1;
2648 dd723472 Luca Abeni
    }
2649
    if (stream->title[0] != 0) {
2650
        av_strlcpy(avc->title, stream->title, sizeof(avc->title));
2651
    } else {
2652
        av_strlcpy(avc->title, "No Title", sizeof(avc->title));
2653
    }
2654
    avc->nb_streams = stream->nb_streams;
2655
    if (stream->is_multicast) {
2656
        snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2657
                 inet_ntoa(stream->multicast_ip),
2658
                 stream->multicast_port, stream->multicast_ttl);
2659
    }
2660 115329f1 Diego Biurrun
2661 2effd274 Fabrice Bellard
    for(i = 0; i < stream->nb_streams; i++) {
2662 dd723472 Luca Abeni
        avc->streams[i] = &avs[i];
2663
        avc->streams[i]->codec = stream->streams[i]->codec;
2664 2effd274 Fabrice Bellard
    }
2665 dd723472 Luca Abeni
    *pbuffer = av_mallocz(2048);
2666
    avf_sdp_create(&avc, 1, *pbuffer, 2048);
2667
    av_free(avc);