* 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
pull/126/head
Philip Gladstone 23 years ago
parent 487ec9a0d9
commit 8256c0a341
  1. 128
      ffserver.c

@ -154,6 +154,18 @@ enum StreamType {
STREAM_TYPE_REDIRECT, 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 */ /* description of each stream of the ffserver.conf file */
typedef struct FFStream { typedef struct FFStream {
enum StreamType stream_type; enum StreamType stream_type;
@ -161,6 +173,7 @@ typedef struct FFStream {
struct FFStream *feed; /* feed we are using (can be null if struct FFStream *feed; /* feed we are using (can be null if
coming from file) */ coming from file) */
AVOutputFormat *fmt; AVOutputFormat *fmt;
IPAddressACL *acl;
int nb_streams; int nb_streams;
int prebuffer; /* Number of millseconds early to start */ int prebuffer; /* Number of millseconds early to start */
long max_time; /* Number of milliseconds to run */ 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; *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 */ /* parse http request and prepare header */
static int http_parse_request(HTTPContext *c) static int http_parse_request(HTTPContext *c)
{ {
@ -1077,7 +1107,7 @@ static int http_parse_request(HTTPContext *c)
stream = first_stream; stream = first_stream;
while (stream != NULL) { while (stream != NULL) {
if (!strcmp(stream->filename, filename)) if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
break; break;
stream = stream->next; stream = stream->next;
} }
@ -1342,14 +1372,10 @@ static int http_parse_request(HTTPContext *c)
q += sprintf(q, "Pragma: no-cache\r\n"); q += sprintf(q, "Pragma: no-cache\r\n");
/* for asf, we need extra headers */ /* 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 */ /* 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); 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"; mime_type = "application/octet-stream";
@ -1719,6 +1745,12 @@ static int open_input_stream(HTTPContext *c, const char *info)
if (input_filename[0] == '\0') if (input_filename[0] == '\0')
return -1; return -1;
#if 0
{ time_t when = stream_pos / 1000000;
http_log("Stream pos = %lld, time=%s", stream_pos, ctime(&when));
}
#endif
/* open stream */ /* open stream */
if (av_open_input_file(&s, input_filename, NULL, buf_size, NULL) < 0) { if (av_open_input_file(&s, input_filename, NULL, buf_size, NULL) < 0) {
http_log("%s not found", input_filename); http_log("%s not found", input_filename);
@ -3447,7 +3479,7 @@ int parse_ffconfig(const char *filename)
q = strrchr(stream->filename, '>'); q = strrchr(stream->filename, '>');
if (*q) if (*q)
*q = '\0'; *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(&audio_enc, 0, sizeof(AVCodecContext));
memset(&video_enc, 0, sizeof(AVCodecContext)); memset(&video_enc, 0, sizeof(AVCodecContext));
audio_id = CODEC_ID_NONE; 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 */ /* jpeg cannot be used here, so use single frame jpeg */
if (!strcmp(arg, "jpeg")) if (!strcmp(arg, "jpeg"))
strcpy(arg, "singlejpeg"); strcpy(arg, "singlejpeg");
stream->fmt = guess_format(arg, NULL, NULL); stream->fmt = guess_stream_format(arg, NULL, NULL);
if (!stream->fmt) { if (!stream->fmt) {
fprintf(stderr, "%s:%d: Unknown Format: %s\n", fprintf(stderr, "%s:%d: Unknown Format: %s\n",
filename, line_num, arg); filename, line_num, arg);
@ -3523,7 +3555,7 @@ int parse_ffconfig(const char *filename)
} else if (!strcasecmp(cmd, "Preroll")) { } else if (!strcasecmp(cmd, "Preroll")) {
get_arg(arg, sizeof(arg), &p); get_arg(arg, sizeof(arg), &p);
if (stream) { if (stream) {
stream->prebuffer = atoi(arg) * 1000; stream->prebuffer = atof(arg) * 1000;
} }
} else if (!strcasecmp(cmd, "StartSendOnKey")) { } else if (!strcasecmp(cmd, "StartSendOnKey")) {
if (stream) { if (stream) {
@ -3548,7 +3580,7 @@ int parse_ffconfig(const char *filename)
} else if (!strcasecmp(cmd, "MaxTime")) { } else if (!strcasecmp(cmd, "MaxTime")) {
get_arg(arg, sizeof(arg), &p); get_arg(arg, sizeof(arg), &p);
if (stream) { if (stream) {
stream->max_time = atoi(arg) * 1000; stream->max_time = atof(arg) * 1000;
} }
} else if (!strcasecmp(cmd, "AudioBitRate")) { } else if (!strcasecmp(cmd, "AudioBitRate")) {
get_arg(arg, sizeof(arg), &p); get_arg(arg, sizeof(arg), &p);
@ -3630,6 +3662,72 @@ int parse_ffconfig(const char *filename)
video_id = CODEC_ID_NONE; video_id = CODEC_ID_NONE;
} else if (!strcasecmp(cmd, "NoAudio")) { } else if (!strcasecmp(cmd, "NoAudio")) {
audio_id = CODEC_ID_NONE; 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")) { } else if (!strcasecmp(cmd, "RTSPOption")) {
get_arg(arg, sizeof(arg), &p); get_arg(arg, sizeof(arg), &p);
if (stream) { if (stream) {
@ -3830,6 +3928,8 @@ int main(int argc, char **argv)
putenv("http_proxy"); /* Kill the http_proxy */ putenv("http_proxy"); /* Kill the http_proxy */
srandom(gettime_ms() + (getpid() << 16));
/* address on which the server will handle HTTP connections */ /* address on which the server will handle HTTP connections */
my_http_addr.sin_family = AF_INET; my_http_addr.sin_family = AF_INET;
my_http_addr.sin_port = htons (8080); my_http_addr.sin_port = htons (8080);
@ -3875,10 +3975,12 @@ int main(int argc, char **argv)
setsid(); setsid();
chdir("/"); chdir("/");
close(0); close(0);
close(1);
close(2);
open("/dev/null", O_RDWR); open("/dev/null", O_RDWR);
if (!strcmp(logfilename, "-")) {
close(1);
dup(0); dup(0);
}
close(2);
dup(0); dup(0);
} }
} }

Loading…
Cancel
Save