aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure62
-rw-r--r--configure.ac17
-rw-r--r--include/asterisk/autoconfig.h.in3
-rw-r--r--include/asterisk/http.h2
-rw-r--r--main/http.c52
-rw-r--r--main/manager.c12
6 files changed, 119 insertions, 29 deletions
diff --git a/configure b/configure
index 5e36bac66..c440f1898 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.ac Revision: 71732 .
+# From configure.ac Revision: 72539 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61.
#
@@ -16476,6 +16476,66 @@ _ACEOF
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+ #include <sys/sendfile.h>
+int
+main ()
+{
+sendfile(1, 0, NULL, 1);
+ ;
+ return 0;
+}
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ have_sendfile=yes
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ have_sendfile=no
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "${have_sendfile}" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SENDFILE 1
+_ACEOF
+
+fi
+
# do the package library checks now
diff --git a/configure.ac b/configure.ac
index 4c4a48c7a..9e8279d07 100644
--- a/configure.ac
+++ b/configure.ac
@@ -364,6 +364,23 @@ AC_CHECK_HEADER([libkern/OSAtomic.h],
AC_CHECK_SIZEOF(int)
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <stdlib.h>
+ #include <sys/sendfile.h>],
+ [sendfile(1, 0, NULL, 1);])
+ ],[
+ AC_MSG_RESULT(yes)
+ have_sendfile=yes
+ ],[
+ AC_MSG_RESULT(no)
+ have_sendfile=no
+ ]
+)
+if test "${have_sendfile}" = "yes"; then
+ AC_DEFINE([HAVE_SENDFILE], 1, [Define if your system has the sendfile syscall.])
+fi
+
# do the package library checks now
AST_EXT_LIB_CHECK([ALSA], [asound], [snd_spcm_init], [alsa/asoundlib.h], [-lm -ldl])
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 85618b9e3..3f175ddf0 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -394,6 +394,9 @@
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
+/* Define if your system has the sendfile syscall. */
+#undef HAVE_SENDFILE
+
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
diff --git a/include/asterisk/http.h b/include/asterisk/http.h
index 9d92ef5a7..b0215221e 100644
--- a/include/asterisk/http.h
+++ b/include/asterisk/http.h
@@ -147,7 +147,7 @@ int ssl_setup(struct tls_config *cfg);
content is specified)
\endverbatim
*/
-typedef struct ast_str *(*ast_http_callback)(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength);
+typedef struct ast_str *(*ast_http_callback)(struct server_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength);
/*! \brief Definition of a URI reachable in the embedded HTTP server */
struct ast_http_uri {
diff --git a/main/http.c b/main/http.c
index d6c4e25f3..f71ae0dfb 100644
--- a/main/http.c
+++ b/main/http.c
@@ -48,6 +48,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <fcntl.h>
#include <pthread.h>
+#ifdef HAVE_SENDFILE
+#include <sys/sendfile.h>
+#endif
+
#include "minimime/mm.h"
#include "asterisk/cli.h"
@@ -145,9 +149,8 @@ static const char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
return wkspace;
}
-static struct ast_str *static_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
+static struct ast_str *static_callback(struct server_instance *ser, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
{
- struct ast_str *result;
char *path;
char *ftype;
const char *mtype;
@@ -155,6 +158,8 @@ static struct ast_str *static_callback(struct sockaddr_in *req, const char *uri,
struct stat st;
int len;
int fd;
+ time_t t;
+ char buf[256];
/* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration
substantially more challenging, but this seems like a rather irritating feature creep on Asterisk. */
@@ -185,21 +190,28 @@ static struct ast_str *static_callback(struct sockaddr_in *req, const char *uri,
if (fd < 0)
goto out403;
- len = st.st_size + strlen(mtype) + 40;
- result = ast_str_create(len);
- if (result == NULL) /* XXX not really but... */
- goto out403;
+ time(&t);
+ strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
+ fprintf(ser->f, "HTTP/1.1 200 OK\r\n"
+ "Server: Asterisk/%s\r\n"
+ "Date: %s\r\n"
+ "Connection: close\r\n"
+ "Cache-Control: no-cache, no-store\r\n"
+ "Content-Length: %d\r\n"
+ "Content-type: %s\r\n\r\n",
+ ASTERISK_VERSION, buf, (int) st.st_size, mtype);
+
+ fflush(ser->f);
+
+#ifdef HAVE_SENDFILE
+ sendfile(ser->fd, fd, NULL, st.st_size);
+#else
+ while ((len = read(fd, buf, sizeof(buf))) > 0)
+ write(ser->fd, buf, len);
+#endif
- ast_str_append(&result, 0, "Content-type: %s\r\n\r\n", mtype);
- *contentlength = read(fd, result->str + result->used, st.st_size);
- if (*contentlength < 0) {
- close(fd);
- ast_free(result);
- goto out403;
- }
- result->used += *contentlength;
close(fd);
- return result;
+ return NULL;
out404:
*status = 404;
@@ -213,7 +225,7 @@ out403:
}
-static struct ast_str *httpstatus_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
+static struct ast_str *httpstatus_callback(struct server_instance *ser, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
{
struct ast_str *out = ast_str_create(512);
struct ast_variable *v;
@@ -541,7 +553,7 @@ static struct ast_str *handle_post(struct server_instance *ser, char *uri,
return ast_http_error(200, "OK", NULL, "File successfully uploaded.");
}
-static struct ast_str *handle_uri(struct sockaddr_in *sin, char *uri, int *status,
+static struct ast_str *handle_uri(struct server_instance *ser, char *uri, int *status,
char **title, int *contentlength, struct ast_variable **cookies,
unsigned int *static_content)
{
@@ -627,7 +639,7 @@ static struct ast_str *handle_uri(struct sockaddr_in *sin, char *uri, int *statu
if (urih) {
if (urih->static_content)
*static_content = 1;
- out = urih->callback(sin, uri, vars, status, title, contentlength);
+ out = urih->callback(ser, uri, vars, status, title, contentlength);
AST_RWLIST_UNLOCK(&uris);
} else {
out = ast_http_error(404, "Not Found", NULL,
@@ -834,14 +846,12 @@ static void *httpd_helper_thread(void *data)
out = ast_http_error(501, "Not Implemented", NULL,
"Attempt to use unimplemented / unsupported method");
else /* try to serve it */
- out = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content);
+ out = handle_uri(ser, uri, &status, &title, &contentlength, &vars, &static_content);
/* If they aren't mopped up already, clean up the cookies */
if (vars)
ast_variables_destroy(vars);
- if (out == NULL)
- out = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
if (out) {
time_t t = time(NULL);
char timebuf[256];
diff --git a/main/manager.c b/main/manager.c
index 2c66f5fb4..a905bc199 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -3182,19 +3182,19 @@ generic_callback_out:
return out;
}
-static struct ast_str *manager_http_callback(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
+static struct ast_str *manager_http_callback(struct server_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
{
- return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength);
+ return generic_http_callback(FORMAT_HTML, &ser->requestor, uri, params, status, title, contentlength);
}
-static struct ast_str *mxml_http_callback(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
+static struct ast_str *mxml_http_callback(struct server_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
{
- return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength);
+ return generic_http_callback(FORMAT_XML, &ser->requestor, uri, params, status, title, contentlength);
}
-static struct ast_str *rawman_http_callback(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
+static struct ast_str *rawman_http_callback(struct server_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
{
- return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength);
+ return generic_http_callback(FORMAT_RAW, &ser->requestor, uri, params, status, title, contentlength);
}
struct ast_http_uri rawmanuri = {