#include <sys/time.h>
#undef time //needed because HAVE_AV_CONFIG_H is defined on top
#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/wait.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
#include <signal.h>
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
+#include "network.h"
#include "version.h"
#include "ffserver.h"
#include "random.h"
#define IOBUFFER_INIT_SIZE 8192
-/* coef for exponential mean for bitrate estimation in statistics */
-#define AVG_COEF 0.9
-
/* timeouts are in ms */
#define HTTP_REQUEST_TIMEOUT (15 * 1000)
#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
float avg_frame_size; /* frame size averraged over last frames with exponential mean */
} FeedData;
-struct sockaddr_in my_http_addr;
-struct sockaddr_in my_rtsp_addr;
+static struct sockaddr_in my_http_addr;
+static struct sockaddr_in my_rtsp_addr;
static char logfilename[1024];
static HTTPContext *first_http_ctx;
closesocket(server_fd);
return -1;
}
- fcntl(server_fd, F_SETFL, O_NONBLOCK);
+ ff_socket_nonblock(server_fd, 1);
return server_fd;
}
second to handle timeouts */
do {
ret = poll(poll_table, poll_entry - poll_table, delay);
- if (ret < 0 && errno != EAGAIN && errno != EINTR)
+ if (ret < 0 && ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR))
return -1;
- } while (ret <= 0);
+ } while (ret < 0);
cur_time = av_gettime() / 1000;
&len);
if (fd < 0)
return;
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ ff_socket_nonblock(fd, 1);
/* XXX: should output a warning page when coming
close to the connection limit */
read_loop:
len = recv(c->fd, c->buffer_ptr, 1, 0);
if (len < 0) {
- if (errno != EAGAIN && errno != EINTR)
+ if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR))
return -1;
} else if (len == 0) {
return -1;
return 0;
len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
if (len < 0) {
- if (errno != EAGAIN && errno != EINTR) {
+ if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR)) {
/* error : close connection */
av_freep(&c->pb_buffer);
return -1;
return 0;
len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
if (len < 0) {
- if (errno != EAGAIN && errno != EINTR) {
+ if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR)) {
/* error : close connection */
av_freep(&c->pb_buffer);
return -1;
len = send(c->fd, c->packet_buffer_ptr,
c->packet_buffer_end - c->packet_buffer_ptr, 0);
if (len < 0) {
- if (errno != EAGAIN && errno != EINTR) {
+ if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR)) {
/* error : close connection */
av_freep(&c->packet_buffer);
return -1;
enum IPAddressAction last_action = IP_DENY;
IPAddressACL *acl;
struct in_addr *src = &c->from_addr.sin_addr;
- unsigned long src_addr = ntohl(src->s_addr);
+ unsigned long src_addr = src->s_addr;
for (acl = stream->acl; acl; acl = acl->next) {
if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr) {
q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
mime_type = c->stream->fmt->mime_type;
if (!mime_type)
- mime_type = "application/x-octet_stream";
+ mime_type = "application/x-octet-stream";
q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
/* for asf, we need extra headers */
return 0;
}
-/* in bit/s */
-#define SHORT_TERM_BANDWIDTH 8000000
-
/* should convert the format at the same time */
/* send data starting at c->buffer_ptr to the output connection
(either UDP or TCP connection) */
/* TCP data output */
len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
if (len < 0) {
- if (errno != EAGAIN && errno != EINTR) {
+ if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR)) {
/* error : close connection */
return -1;
} else {
len = recv(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
if (len < 0) {
- if (errno != EAGAIN && errno != EINTR) {
+ if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
+ ff_neterrno() != FF_NETERROR(EINTR)) {
/* error : close connection */
goto fail;
}
char buf2[32];
switch(error_number) {
-#define DEF(n, c, s) case c: str = s; break;
-#include "rtspcodes.h"
-#undef DEF
+ case RTSP_STATUS_OK:
+ str = "OK";
+ break;
+ case RTSP_STATUS_METHOD:
+ str = "Method Not Allowed";
+ break;
+ case RTSP_STATUS_BANDWIDTH:
+ str = "Not Enough Bandwidth";
+ break;
+ case RTSP_STATUS_SESSION:
+ str = "Session Not Found";
+ break;
+ case RTSP_STATUS_STATE:
+ str = "Method Not Valid in This State";
+ break;
+ case RTSP_STATUS_AGGREGATE:
+ str = "Aggregate operation not allowed";
+ break;
+ case RTSP_STATUS_ONLY_AGGREGATE:
+ str = "Only aggregate operation allowed";
+ break;
+ case RTSP_STATUS_TRANSPORT:
+ str = "Unsupported transport";
+ break;
+ case RTSP_STATUS_INTERNAL:
+ str = "Internal Server Error";
+ break;
+ case RTSP_STATUS_SERVICE:
+ str = "Service Unavailable";
+ break;
+ case RTSP_STATUS_VERSION:
+ str = "RTSP Version not supported";
+ break;
default:
str = "Unknown Error";
break;
dest_addr = rtp_c->from_addr;
dest_addr.sin_port = htons(th->client_port_min);
- /* add transport option if needed */
- if (ff_rtsp_callback) {
- setup.ipaddr = ntohl(dest_addr.sin_addr.s_addr);
- if (ff_rtsp_callback(RTSP_ACTION_SERVER_SETUP, rtp_c->session_id,
- (char *)&setup, sizeof(setup),
- stream->rtsp_option) < 0) {
- rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
- return;
- }
- dest_addr.sin_addr.s_addr = htonl(setup.ipaddr);
- }
-
/* setup stream */
if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h)
{
HTTPContext *rtp_c;
+ char session_id[32];
rtp_c = find_rtp_session_with_url(url, h->session_id);
if (!rtp_c) {
return;
}
+ pstrcpy(session_id, sizeof(session_id), rtp_c->session_id);
+
/* abort the session */
close_connection(rtp_c);
- if (ff_rtsp_callback) {
- ff_rtsp_callback(RTSP_ACTION_SERVER_TEARDOWN, rtp_c->session_id,
- NULL, 0,
- rtp_c->stream->rtsp_option);
- }
-
/* now everything is OK, so we can send the connection parameters */
rtsp_reply_header(c, RTSP_STATUS_OK);
/* session ID */
- url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
+ url_fprintf(c->pb, "Session: %s\r\n", session_id);
url_fprintf(c->pb, "\r\n");
}
c->stream->feed->streams[c->stream->feed_streams[stream_index]],
sizeof(AVStream));
}
+ st->priv_data = NULL;
/* build destination RTP address */
ipaddr = inet_ntoa(dest_addr->sin_addr);
if (!strcasecmp(cmd, "Port")) {
get_arg(arg, sizeof(arg), &p);
- my_http_addr.sin_port = htons (atoi(arg));
+ val = atoi(arg);
+ if (val < 1 || val > 65536) {
+ fprintf(stderr, "%s:%d: Invalid port: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ my_http_addr.sin_port = htons(val);
} else if (!strcasecmp(cmd, "BindAddress")) {
get_arg(arg, sizeof(arg), &p);
- if (!inet_aton(arg, &my_http_addr.sin_addr)) {
- fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
+ if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
+ fprintf(stderr, "%s:%d: Invalid host/IP address: %s\n",
filename, line_num, arg);
errors++;
}
ffserver_daemon = 0;
} else if (!strcasecmp(cmd, "RTSPPort")) {
get_arg(arg, sizeof(arg), &p);
- my_rtsp_addr.sin_port = htons (atoi(arg));
+ val = atoi(arg);
+ if (val < 1 || val > 65536) {
+ fprintf(stderr, "%s:%d: Invalid port: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ my_rtsp_addr.sin_port = htons(atoi(arg));
} else if (!strcasecmp(cmd, "RTSPBindAddress")) {
get_arg(arg, sizeof(arg), &p);
- if (!inet_aton(arg, &my_rtsp_addr.sin_addr)) {
- fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
+ if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
+ fprintf(stderr, "%s:%d: Invalid host/IP address: %s\n",
filename, line_num, arg);
errors++;
}
feed->child_argv = (char **) av_mallocz(64 * sizeof(char *));
for (i = 0; i < 62; i++) {
- char argbuf[256];
-
- get_arg(argbuf, sizeof(argbuf), &p);
- if (!argbuf[0])
+ get_arg(arg, sizeof(arg), &p);
+ if (!arg[0])
break;
- feed->child_argv[i] = av_malloc(strlen(argbuf) + 1);
- strcpy(feed->child_argv[i], argbuf);
+ feed->child_argv[i] = av_strdup(arg);
}
feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
fprintf(stderr, "%s:%d: No corresponding <Feed> for </Feed>\n",
filename, line_num);
errors++;
-#if 0
- } else {
- /* Make sure that we start out clean */
- if (unlink(feed->feed_filename) < 0
- && errno != ENOENT) {
- fprintf(stderr, "%s:%d: Unable to clean old feed file '%s': %s\n",
- filename, line_num, feed->feed_filename, strerror(errno));
- errors++;
- }
-#endif
}
feed = NULL;
} else if (!strcasecmp(cmd, "<Stream")) {
video_id = stream->fmt->video_codec;
}
} else if (!strcasecmp(cmd, "InputFormat")) {
+ get_arg(arg, sizeof(arg), &p);
stream->ifmt = av_find_input_format(arg);
if (!stream->ifmt) {
fprintf(stderr, "%s:%d: Unknown input format: %s\n",
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) {
get_arg(arg, sizeof(arg), &p);
- he = gethostbyname(arg);
- if (!he) {
+ if (resolve_host(&acl.first, arg) != 0) {
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.s_addr = ntohl(((struct in_addr *) he->h_addr_list[0])->s_addr);
acl.last = acl.first;
}
get_arg(arg, sizeof(arg), &p);
if (arg[0]) {
- he = gethostbyname(arg);
- if (!he) {
+ if (resolve_host(&acl.last, arg) != 0) {
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.s_addr = ntohl(((struct in_addr *) he->h_addr_list[0])->s_addr);
}
}
IPAddressACL *nacl = (IPAddressACL *) av_mallocz(sizeof(*nacl));
IPAddressACL **naclp = 0;
+ acl.next = 0;
*nacl = acl;
- nacl->next = 0;
if (stream) {
naclp = &stream->acl;
get_arg(arg, sizeof(arg), &p);
if (stream) {
av_freep(&stream->rtsp_option);
- /* XXX: av_strdup ? */
- stream->rtsp_option = av_malloc(strlen(arg) + 1);
- if (stream->rtsp_option) {
- strcpy(stream->rtsp_option, arg);
- }
+ stream->rtsp_option = av_strdup(arg);
}
} else if (!strcasecmp(cmd, "MulticastAddress")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
- if (!inet_aton(arg, &stream->multicast_ip)) {
- fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
+ if (resolve_host(&stream->multicast_ip, arg) != 0) {
+ fprintf(stderr, "%s:%d: Invalid host/IP address: %s\n",
filename, line_num, arg);
errors++;
}
return 0;
}
-
-#if 0
-static void write_packet(FFCodec *ffenc,
- uint8_t *buf, int size)
-{
- PacketHeader hdr;
- AVCodecContext *enc = &ffenc->enc;
- uint8_t *wptr;
- mk_header(&hdr, enc, size);
- wptr = http_fifo.wptr;
- fifo_write(&http_fifo, (uint8_t *)&hdr, sizeof(hdr), &wptr);
- fifo_write(&http_fifo, buf, size, &wptr);
- /* atomic modification of wptr */
- http_fifo.wptr = wptr;
- ffenc->data_count += size;
- ffenc->avg_frame_size = ffenc->avg_frame_size * AVG_COEF + size * (1.0 - AVG_COEF);
-}
-#endif
-
static void show_banner(void)
{
printf("ffserver version " FFMPEG_VERSION ", Copyright (c) 2000-2006 Fabrice Bellard, et al.\n");