summaryrefslogtreecommitdiff
path: root/ffserver.c
diff options
context:
space:
mode:
authorPhilip Gladstone <philipjsg@users.sourceforge.net>2002-07-27 03:03:04 +0000
committerPhilip Gladstone <philipjsg@users.sourceforge.net>2002-07-27 03:03:04 +0000
commit8256c0a3416e619f186875b3162c52a7d302132c (patch)
treee38334d99014e0839f9d4cc63aebf74fb49d7e28 /ffserver.c
parent487ec9a0d92796a3c725d4ab750b39b2fa5d554c (diff)
* Make asf streaming work again. Now uses the output format asf_stream.
* Add ip address based acls for streams. I recommend adding ACL entries for all feeds to control who can submit stuff. You might also want to consider who can get to your status page. * Make logging work again if customlog == "-" Originally committed as revision 821 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'ffserver.c')
-rw-r--r--ffserver.c130
1 files changed, 116 insertions, 14 deletions
diff --git a/ffserver.c b/ffserver.c
index c7b2bc5907..c9bd4b92f0 100644
--- a/ffserver.c
+++ b/ffserver.c
@@ -154,6 +154,18 @@ enum StreamType {
STREAM_TYPE_REDIRECT,
};
+enum IPAddressAction {
+ IP_ALLOW = 1,
+ IP_DENY,
+};
+
+typedef struct IPAddressACL {
+ struct IPAddressACL *next;
+ enum IPAddressAction action;
+ struct in_addr first;
+ struct in_addr last;
+} IPAddressACL;
+
/* description of each stream of the ffserver.conf file */
typedef struct FFStream {
enum StreamType stream_type;
@@ -161,6 +173,7 @@ typedef struct FFStream {
struct FFStream *feed; /* feed we are using (can be null if
coming from file) */
AVOutputFormat *fmt;
+ IPAddressACL *acl;
int nb_streams;
int prebuffer; /* Number of millseconds early to start */
long max_time; /* Number of milliseconds to run */
@@ -957,6 +970,23 @@ static void get_word(char *buf, int buf_size, const char **pp)
*pp = p;
}
+static int validate_acl(FFStream *stream, HTTPContext *c)
+{
+ enum IPAddressAction last_action = IP_DENY;
+ IPAddressACL *acl;
+ struct in_addr *src = &c->from_addr.sin_addr;
+
+ for (acl = stream->acl; acl; acl = acl->next) {
+ if (src->s_addr >= acl->first.s_addr && src->s_addr <= acl->last.s_addr) {
+ return (acl->action == IP_ALLOW) ? 1 : 0;
+ }
+ last_action = acl->action;
+ }
+
+ /* Nothing matched, so return not the last action */
+ return (last_action == IP_DENY) ? 1 : 0;
+}
+
/* parse http request and prepare header */
static int http_parse_request(HTTPContext *c)
{
@@ -1077,7 +1107,7 @@ static int http_parse_request(HTTPContext *c)
stream = first_stream;
while (stream != NULL) {
- if (!strcmp(stream->filename, filename))
+ if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
break;
stream = stream->next;
}
@@ -1342,14 +1372,10 @@ static int http_parse_request(HTTPContext *c)
q += sprintf(q, "Pragma: no-cache\r\n");
/* for asf, we need extra headers */
- if (!strcmp(c->stream->fmt->name,"asf")) {
+ if (!strcmp(c->stream->fmt->name,"asf_stream")) {
/* Need to allocate a client id */
- static int wmp_session;
- if (!wmp_session)
- wmp_session = time(0) & 0xffffff;
-
- c->wmp_client_id = ++wmp_session;
+ c->wmp_client_id = random() & 0x7fffffff;
q += sprintf(q, "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);
mime_type = "application/octet-stream";
@@ -1719,6 +1745,12 @@ static int open_input_stream(HTTPContext *c, const char *info)
if (input_filename[0] == '\0')
return -1;
+#if 0
+ { time_t when = stream_pos / 1000000;
+ http_log("Stream pos = %lld, time=%s", stream_pos, ctime(&when));
+ }
+#endif
+
/* open stream */
if (av_open_input_file(&s, input_filename, NULL, buf_size, NULL) < 0) {
http_log("%s not found", input_filename);
@@ -3447,7 +3479,7 @@ int parse_ffconfig(const char *filename)
q = strrchr(stream->filename, '>');
if (*q)
*q = '\0';
- stream->fmt = guess_format(NULL, stream->filename, NULL);
+ stream->fmt = guess_stream_format(NULL, stream->filename, NULL);
memset(&audio_enc, 0, sizeof(AVCodecContext));
memset(&video_enc, 0, sizeof(AVCodecContext));
audio_id = CODEC_ID_NONE;
@@ -3485,7 +3517,7 @@ int parse_ffconfig(const char *filename)
/* jpeg cannot be used here, so use single frame jpeg */
if (!strcmp(arg, "jpeg"))
strcpy(arg, "singlejpeg");
- stream->fmt = guess_format(arg, NULL, NULL);
+ stream->fmt = guess_stream_format(arg, NULL, NULL);
if (!stream->fmt) {
fprintf(stderr, "%s:%d: Unknown Format: %s\n",
filename, line_num, arg);
@@ -3523,7 +3555,7 @@ int parse_ffconfig(const char *filename)
} else if (!strcasecmp(cmd, "Preroll")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
- stream->prebuffer = atoi(arg) * 1000;
+ stream->prebuffer = atof(arg) * 1000;
}
} else if (!strcasecmp(cmd, "StartSendOnKey")) {
if (stream) {
@@ -3548,7 +3580,7 @@ int parse_ffconfig(const char *filename)
} else if (!strcasecmp(cmd, "MaxTime")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
- stream->max_time = atoi(arg) * 1000;
+ stream->max_time = atof(arg) * 1000;
}
} else if (!strcasecmp(cmd, "AudioBitRate")) {
get_arg(arg, sizeof(arg), &p);
@@ -3630,6 +3662,72 @@ int parse_ffconfig(const char *filename)
video_id = CODEC_ID_NONE;
} else if (!strcasecmp(cmd, "NoAudio")) {
audio_id = CODEC_ID_NONE;
+ } else if (!strcasecmp(cmd, "ACL")) {
+ IPAddressACL acl;
+ struct hostent *he;
+
+ get_arg(arg, sizeof(arg), &p);
+ if (strcasecmp(arg, "allow") == 0) {
+ acl.action = IP_ALLOW;
+ } else if (strcasecmp(arg, "deny") == 0) {
+ acl.action = IP_DENY;
+ } else {
+ fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
+ filename, line_num, arg);
+ errors++;
+ }
+
+ get_arg(arg, sizeof(arg), &p);
+
+ he = gethostbyname(arg);
+ if (!he) {
+ fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
+ filename, line_num, arg);
+ errors++;
+ } else {
+ /* Only take the first */
+ acl.first = *(struct in_addr *) he->h_addr_list[0];
+ acl.last = acl.first;
+ }
+
+ get_arg(arg, sizeof(arg), &p);
+
+ if (arg[0]) {
+ he = gethostbyname(arg);
+ if (!he) {
+ fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
+ filename, line_num, arg);
+ errors++;
+ } else {
+ /* Only take the first */
+ acl.last = *(struct in_addr *) he->h_addr_list[0];
+ }
+ }
+
+ if (!errors) {
+ IPAddressACL *nacl = (IPAddressACL *) av_mallocz(sizeof(*nacl));
+ IPAddressACL **naclp = 0;
+
+ *nacl = acl;
+ nacl->next = 0;
+
+ if (stream) {
+ naclp = &stream->acl;
+ } else if (feed) {
+ naclp = &feed->acl;
+ } else {
+ fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
+ filename, line_num);
+ errors++;
+ }
+
+ if (naclp) {
+ while (*naclp)
+ naclp = &(*naclp)->next;
+
+ *naclp = nacl;
+ }
+ }
} else if (!strcasecmp(cmd, "RTSPOption")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
@@ -3830,6 +3928,8 @@ int main(int argc, char **argv)
putenv("http_proxy"); /* Kill the http_proxy */
+ srandom(gettime_ms() + (getpid() << 16));
+
/* address on which the server will handle HTTP connections */
my_http_addr.sin_family = AF_INET;
my_http_addr.sin_port = htons (8080);
@@ -3875,10 +3975,12 @@ int main(int argc, char **argv)
setsid();
chdir("/");
close(0);
- close(1);
- close(2);
open("/dev/null", O_RDWR);
- dup(0);
+ if (!strcmp(logfilename, "-")) {
+ close(1);
+ dup(0);
+ }
+ close(2);
dup(0);
}
}