[asterisk-commits] branch oej/test-this-branch r17044 - in
/team/oej/test-this-branch: ./ apps/ ...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Mon Apr 3 01:02:55 MST 2006
Author: oej
Date: Mon Apr 3 03:02:40 2006
New Revision: 17044
URL: http://svn.digium.com/view/asterisk?rev=17044&view=rev
Log:
Update to trunk, resolve conflict
Added:
team/oej/test-this-branch/doc/ajam.txt
- copied unchanged from r17009, trunk/doc/ajam.txt
team/oej/test-this-branch/static-http/
- copied from r17009, trunk/static-http/
team/oej/test-this-branch/static-http/ajamdemo.html
- copied unchanged from r17009, trunk/static-http/ajamdemo.html
team/oej/test-this-branch/static-http/astman.css
- copied unchanged from r17009, trunk/static-http/astman.css
team/oej/test-this-branch/static-http/astman.js
- copied unchanged from r17009, trunk/static-http/astman.js
team/oej/test-this-branch/static-http/prototype.js
- copied unchanged from r17009, trunk/static-http/prototype.js
Modified:
team/oej/test-this-branch/ (props changed)
team/oej/test-this-branch/Makefile
team/oej/test-this-branch/apps/app_rpt.c
team/oej/test-this-branch/cli.c
team/oej/test-this-branch/configs/http.conf.sample
team/oej/test-this-branch/configs/manager.conf.sample
team/oej/test-this-branch/http.c
team/oej/test-this-branch/include/asterisk/http.h
team/oej/test-this-branch/include/asterisk/manager.h
team/oej/test-this-branch/loader.c
team/oej/test-this-branch/manager.c
Propchange: team/oej/test-this-branch/
------------------------------------------------------------------------------
automerge = http://edvina.net/training/
Propchange: team/oej/test-this-branch/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Apr 3 03:02:40 2006
@@ -1,1 +1,1 @@
-/trunk:1-16843
+/trunk:1-17025
Modified: team/oej/test-this-branch/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/Makefile?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/Makefile (original)
+++ team/oej/test-this-branch/Makefile Mon Apr 3 03:02:40 2006
@@ -568,6 +568,13 @@
datafiles: all
if [ x`$(ID) -un` = xroot ]; then sh build_tools/mkpkgconfig $(DESTDIR)/usr/lib/pkgconfig; fi
+ # Should static HTTP be installed during make samples or even with its own target ala
+ # webvoicemail? There are portions here that *could* be customized but might also be
+ # improved a lot. I'll put it here for now.
+ mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/static-http
+ for x in static-http/*; do \
+ install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/static-http ; \
+ done
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/priv-callerintros
for x in sounds/digits/*.gsm; do \
Modified: team/oej/test-this-branch/apps/app_rpt.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/apps/app_rpt.c?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/apps/app_rpt.c (original)
+++ team/oej/test-this-branch/apps/app_rpt.c Mon Apr 3 03:02:40 2006
@@ -608,7 +608,6 @@
/* Debug mode */
static int rpt_do_debug(int fd, int argc, char *argv[]);
static int rpt_do_dump(int fd, int argc, char *argv[]);
-static int rpt_do_frog(int fd, int argc, char *argv[]);
static char debug_usage[] =
"Usage: rpt debug level {0-7}\n"
@@ -618,10 +617,6 @@
"Usage: rpt dump <nodename>\n"
" Dumps struct debug info to log\n";
-static char frog_usage[] =
-"Usage: frog [warp_factor]\n"
-" Performs frog-in-a-blender calculations (Jacobsen Corollary)\n";
-
static struct ast_cli_entry cli_debug =
{ { "rpt", "debug", "level" }, rpt_do_debug,
"Enable app_rpt debugging", debug_usage };
@@ -629,10 +624,6 @@
static struct ast_cli_entry cli_dump =
{ { "rpt", "dump" }, rpt_do_dump,
"Dump app_rpt structs for debugging", dump_usage };
-
-static struct ast_cli_entry cli_frog =
- { { "frog" }, rpt_do_frog,
- "Perform frog-in-a-blender calculations", frog_usage };
/*
* Telemetry defaults
@@ -777,26 +768,6 @@
return RESULT_SUCCESS;
}
}
- return RESULT_FAILURE;
-}
-
-/*
-* Perform frong-in-a-blender calculations (Jacobsen Corollary)
-*/
-
-static int rpt_do_frog(int fd, int argc, char *argv[])
-{
- double warpone = 75139293848.398696166028333356763;
- double warpfactor = 1.0;
-
- if (argc > 2) return RESULT_SHOWUSAGE;
- if ((argc > 1) && (sscanf(argv[1],"%lf",&warpfactor) != 1))
- return RESULT_SHOWUSAGE;
-
- ast_cli(fd, "A frog in a blender with a base diameter of 3 inches going\n");
- ast_cli(fd, "%lf RPM will be travelling at warp factor %lf,\n",
- warpfactor * warpfactor * warpfactor * warpone,warpfactor);
- ast_cli(fd,"based upon the Jacobsen Frog Corollary.\n");
return RESULT_FAILURE;
}
@@ -7066,7 +7037,6 @@
/* Unregister cli extensions */
ast_cli_unregister(&cli_debug);
ast_cli_unregister(&cli_dump);
- ast_cli_unregister(&cli_frog);
return i;
}
@@ -7078,7 +7048,6 @@
/* Register cli extensions */
ast_cli_register(&cli_debug);
ast_cli_register(&cli_dump);
- ast_cli_register(&cli_frog);
return ast_register_application(app, rpt_exec, synopsis, descrip);
}
Modified: team/oej/test-this-branch/cli.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/cli.c?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/cli.c (original)
+++ team/oej/test-this-branch/cli.c Mon Apr 3 03:02:40 2006
@@ -138,6 +138,10 @@
" Optional regular expression pattern is matched to group names for each\n"
" channel.\n";
+static char frog_help[] =
+"Usage: frog [warp_factor]\n"
+" Performs frog-in-a-blender calculations (Jacobsen Corollary)\n";
+
static int handle_load(int fd, int argc, char *argv[])
{
if (argc != 2)
@@ -257,6 +261,28 @@
}
return RESULT_SUCCESS;
}
+
+/*
+* Perform frong-in-a-blender calculations (Jacobsen Corollary)
+*/
+
+static int handle_frog(int fd, int argc, char *argv[])
+{
+ double warpone = 75139293848.0;
+ double warpfactor = 1.0;
+
+ if (argc > 2)
+ return RESULT_SHOWUSAGE;
+ if (argc > 1 && sscanf(argv[1], "%lf", &warpfactor) != 1)
+ return RESULT_SHOWUSAGE;
+
+ ast_cli(fd, "A frog in a blender with a base diameter of 3 inches going\n");
+ ast_cli(fd, "%.0f RPM will be travelling at warp factor %f,\n",
+ warpfactor * warpfactor * warpfactor * warpone, warpfactor);
+ ast_cli(fd, "based upon the Jacobsen Frog Corollary.\n");
+ return RESULT_SUCCESS;
+}
+
#define MODLIST_FORMAT "%-30s %-40.40s %-10d\n"
#define MODLIST_FORMAT2 "%-30s %-40.40s %-10s\n"
@@ -918,6 +944,7 @@
{ { "_command", "matchesarray", NULL }, handle_commandmatchesarray, "Returns command matches array", commandmatchesarray_help },
{ { "debug", "channel", NULL }, handle_debugchan, "Enable debugging on a channel", debugchan_help, complete_ch_3 },
{ { "debug", "level", NULL }, handle_debuglevel, "Set global debug level", debuglevel_help },
+ { { "frog", NULL }, handle_frog,"Perform frog-in-a-blender calculations", frog_help },
{ { "group", "show", "channels", NULL }, group_show_channels, "Show active channels with group(s)", group_show_channels_help},
{ { "help", NULL }, handle_help, "Display help list, or specific help on a command", help_help, complete_help },
{ { "load", NULL }, handle_load, "Load a dynamic module by name", load_help, complete_fn },
Modified: team/oej/test-this-branch/configs/http.conf.sample
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/configs/http.conf.sample?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/configs/http.conf.sample (original)
+++ team/oej/test-this-branch/configs/http.conf.sample Mon Apr 3 03:02:40 2006
@@ -4,15 +4,20 @@
;
[general]
;
-; Whether HTTP interface is enabled or not.
+; Whether HTTP interface is enabled or not. Default is no.
;
-enabled=no
+;enabled=yes
;
-; Address to bind to
+; Whether Asterisk should serve static content from http-static
+; Default is no.
+;
+;enablestatic=yes
+;
+; Address to bind to. Default is 0.0.0.0
;
bindaddr=127.0.0.1
;
-; Port to bind to
+; Port to bind to (default is 8088)
;
bindport=8088
;
Modified: team/oej/test-this-branch/configs/manager.conf.sample
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/configs/manager.conf.sample?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/configs/manager.conf.sample (original)
+++ team/oej/test-this-branch/configs/manager.conf.sample Mon Apr 3 03:02:40 2006
@@ -13,11 +13,18 @@
; ---------------------------- SECURITY NOTE -------------------------------
; Note that you should not enable the AMI on a public IP address. If needed,
; block this TCP port with iptables (or another FW software) and reach it
-; with IPsec, SSH, or SSL vpn tunnel
+; with IPsec, SSH, or SSL vpn tunnel. You can also make the manager
+; interface available over http if Asterisk's http server is enabled in
+; http.conf and if both "enabled" and "webenabled" are set to yes in
+; this file. Both default to no. httptimeout provides the maximum
+; timeout in seconds before a web based session is discarded. The
+; default is 60 seconds.
;
[general]
enabled = no
+;webenabled = yes
port = 5038
+;httptimeout = 60
bindaddr = 0.0.0.0
;displayconnects = yes
;
Modified: team/oej/test-this-branch/http.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/http.c?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/http.c (original)
+++ team/oej/test-this-branch/http.c Mon Apr 3 03:02:40 2006
@@ -33,19 +33,23 @@
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/signal.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
+#include "asterisk.h"
#include "asterisk/cli.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
+#include "asterisk/options.h"
+#include "asterisk/config.h"
#define MAX_PREFIX 80
-#define DEFAULT_PREFIX "asterisk"
+#define DEFAULT_PREFIX "/asterisk"
struct ast_http_server_instance {
FILE *f;
@@ -61,6 +65,100 @@
static char prefix[MAX_PREFIX];
static int prefix_len = 0;
static struct sockaddr_in oldsin;
+static int enablestatic=0;
+
+/* Limit the kinds of files we're willing to serve up */
+static struct {
+ char *ext;
+ char *mtype;
+} mimetypes[] = {
+ { "png", "image/png" },
+ { "jpg", "image/jpeg" },
+ { "js", "application/x-javascript" },
+ { "wav", "audio/x-wav" },
+ { "mp3", "audio/mpeg" },
+};
+
+static char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
+{
+ int x;
+ if (ftype) {
+ for (x=0;x<sizeof(mimetypes) / sizeof(mimetypes[0]); x++) {
+ if (!strcasecmp(ftype, mimetypes[x].ext))
+ return mimetypes[x].mtype;
+ }
+ }
+ snprintf(wkspace, wkspacelen, "text/%s", ftype ? ftype : "plain");
+ return wkspace;
+}
+
+static char *static_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
+{
+ char result[4096];
+ char *c=result;
+ char *path;
+ char *ftype, *mtype;
+ char wkspace[80];
+ struct stat st;
+ int len;
+ int fd;
+ void *blob;
+
+ /* 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. */
+ if (!enablestatic || ast_strlen_zero(uri))
+ goto out403;
+ /* Disallow any funny filenames at all */
+ if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0]))
+ goto out403;
+ if (strstr(uri, "/.."))
+ goto out403;
+
+ if ((ftype = strrchr(uri, '.')))
+ ftype++;
+ mtype=ftype2mtype(ftype, wkspace, sizeof(wkspace));
+
+ /* Cap maximum length */
+ len = strlen(uri) + strlen(ast_config_AST_VAR_DIR) + strlen("/static-http/") + 5;
+ if (len > 1024)
+ goto out403;
+
+ path = alloca(len);
+ sprintf(path, "%s/static-http/%s", ast_config_AST_VAR_DIR, uri);
+ if (stat(path, &st))
+ goto out404;
+ if (S_ISDIR(st.st_mode))
+ goto out404;
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ goto out403;
+
+ len = st.st_size + strlen(mtype) + 40;
+
+ blob = malloc(len);
+ if (blob) {
+ c = blob;
+ sprintf(c, "Content-type: %s\r\n\r\n", mtype);
+ c += strlen(c);
+ *contentlength = read(fd, c, st.st_size);
+ if (*contentlength < 0) {
+ close(fd);
+ free(blob);
+ goto out403;
+ }
+ }
+ return blob;
+
+out404:
+ *status = 404;
+ *title = strdup("Not Found");
+ return ast_http_error(404, "Not Found", NULL, "Nothing to see here. Move along.");
+
+out403:
+ *status = 403;
+ *title = strdup("Access Denied");
+ return ast_http_error(403, "Access Denied", NULL, "Sorry, I cannot let you do that, Dave.");
+}
static char *httpstatus_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
@@ -86,7 +184,15 @@
ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
v = vars;
while(v) {
- ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
+ if (strncasecmp(v->name, "cookie_", 7))
+ ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
+ v = v->next;
+ }
+ ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+ v = vars;
+ while(v) {
+ if (!strncasecmp(v->name, "cookie_", 7))
+ ast_build_string(&c, &reslen, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
v = v->next;
}
ast_build_string(&c, &reslen, "</table><center><font size=\"-1\"><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body>\r\n");
@@ -98,6 +204,13 @@
.description = "Asterisk HTTP General Status",
.uri = "httpstatus",
.has_subtree = 0,
+};
+
+static struct ast_http_uri staticuri = {
+ .callback = static_callback,
+ .description = "Asterisk HTTP Static Delivery",
+ .uri = "static",
+ .has_subtree = 1,
};
char *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
@@ -153,7 +266,7 @@
}
}
-static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength)
+static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies)
{
char *c;
char *turi;
@@ -165,8 +278,6 @@
struct ast_variable *vars=NULL, *v, *prev = NULL;
- if (*uri == '/')
- uri++;
params = strchr(uri, '?');
if (params) {
*params = '\0';
@@ -176,9 +287,9 @@
if (val) {
*val = '\0';
val++;
+ ast_uri_decode(val);
} else
val = "";
- ast_uri_decode(val);
ast_uri_decode(var);
if ((v = ast_variable_new(var, val))) {
if (vars)
@@ -189,6 +300,11 @@
}
}
}
+ if (prev)
+ prev->next = *cookies;
+ else
+ vars = *cookies;
+ *cookies = NULL;
ast_uri_decode(uri);
if (!strncasecmp(uri, prefix, prefix_len)) {
uri += prefix_len;
@@ -216,6 +332,11 @@
if (urih) {
c = urih->callback(sin, uri, vars, status, title, contentlength);
ast_variables_destroy(vars);
+ } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
+ /* Special case: If no prefix, and no URI, send to /static/index.html */
+ c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "This is not the page you are looking for...");
+ *status = 302;
+ *title = strdup("Moved Temporarily");
} else {
c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this serer.");
*status = 404;
@@ -227,9 +348,12 @@
static void *ast_httpd_helper_thread(void *data)
{
char buf[4096];
+ char cookie[4096];
char timebuf[256];
struct ast_http_server_instance *ser = data;
+ struct ast_variable *var, *prev=NULL, *vars=NULL;
char *uri, *c, *title=NULL;
+ char *vname, *vval;
int status = 200, contentlength = 0;
time_t t;
@@ -252,25 +376,68 @@
*c = '\0';
}
}
+
+ while (fgets(cookie, sizeof(cookie), ser->f)) {
+ /* Trim trailing characters */
+ while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
+ cookie[strlen(cookie) - 1] = '\0';
+ }
+ if (ast_strlen_zero(cookie))
+ break;
+ if (!strncasecmp(cookie, "Cookie: ", 8)) {
+ vname = cookie + 8;
+ vval = strchr(vname, '=');
+ if (vval) {
+ /* Ditch the = and the quotes */
+ *vval = '\0';
+ vval++;
+ if (*vval)
+ vval++;
+ if (strlen(vval))
+ vval[strlen(vval) - 1] = '\0';
+ var = ast_variable_new(vname, vval);
+ if (var) {
+ if (prev)
+ prev->next = var;
+ else
+ vars = var;
+ prev = var;
+ }
+ }
+ }
+ }
+
if (*uri) {
if (!strcasecmp(buf, "get"))
- c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength);
+ c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
else
c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
} else
c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
+
+ /* If they aren't mopped up already, clean up the cookies */
+ if (vars)
+ ast_variables_destroy(vars);
+
if (!c)
c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
if (c) {
time(&t);
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
- ast_cli(ser->fd, "HTTP/1.1 GET %d %s\r\n", status, title ? title : "OK");
+ ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
ast_cli(ser->fd, "Server: Asterisk\r\n");
ast_cli(ser->fd, "Date: %s\r\n", timebuf);
- if (contentlength)
- ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
ast_cli(ser->fd, "Connection: close\r\n");
- ast_cli(ser->fd, "%s", c);
+ if (contentlength) {
+ char *tmp;
+ tmp = strstr(c, "\r\n\r\n");
+ if (tmp) {
+ ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
+ write(ser->fd, c, (tmp + 4 - c));
+ write(ser->fd, tmp + 4, contentlength);
+ }
+ } else
+ ast_cli(ser->fd, "%s", c);
free(c);
}
if (title)
@@ -288,6 +455,8 @@
int sinlen;
struct ast_http_server_instance *ser;
pthread_t launched;
+ pthread_attr_t attr;
+
for (;;) {
ast_wait_for_input(httpfd, -1);
sinlen = sizeof(sin);
@@ -297,25 +466,43 @@
ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
continue;
}
- if (!(ser = ast_calloc(1, sizeof(*ser)))) {
- close(fd);
- continue;
- }
- ser->fd = fd;
- if ((ser->f = fdopen(ser->fd, "w+"))) {
- if (ast_pthread_create(&launched, NULL, ast_httpd_helper_thread, ser)) {
- ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
- fclose(ser->f);
+ ser = ast_calloc(1, sizeof(*ser));
+ if (ser) {
+ ser->fd = fd;
+ memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
+ if ((ser->f = fdopen(ser->fd, "w+"))) {
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (ast_pthread_create(&launched, &attr, ast_httpd_helper_thread, ser)) {
+ ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
+ fclose(ser->f);
+ free(ser);
+ }
+ } else {
+ ast_log(LOG_WARNING, "fdopen failed!\n");
+ close(ser->fd);
free(ser);
}
} else {
- ast_log(LOG_WARNING, "fdopen failed!\n");
close(ser->fd);
free(ser);
}
}
return NULL;
}
+
+char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, int buflen)
+{
+ char *c;
+ c = buf;
+ ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val);
+ if (expires)
+ ast_build_string(&c, &buflen, "; Max-Age=%d", expires);
+ ast_build_string(&c, &buflen, "\r\n");
+ return buf;
+}
+
static void http_server_start(struct sockaddr_in *sin)
{
@@ -383,6 +570,7 @@
struct ast_config *cfg;
struct ast_variable *v;
int enabled=0;
+ int newenablestatic=0;
struct sockaddr_in sin;
struct hostent *hp;
struct ast_hostent ahp;
@@ -396,6 +584,8 @@
while(v) {
if (!strcasecmp(v->name, "enabled"))
enabled = ast_true(v->value);
+ else if (!strcasecmp(v->name, "enablestatic"))
+ newenablestatic = ast_true(v->value);
else if (!strcasecmp(v->name, "bindport"))
sin.sin_port = ntohs(atoi(v->value));
else if (!strcasecmp(v->name, "bindaddr")) {
@@ -404,8 +594,15 @@
} else {
ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
}
- } else if (!strcasecmp(v->name, "prefix"))
- ast_copy_string(newprefix, v->value, sizeof(newprefix));
+ } else if (!strcasecmp(v->name, "prefix")) {
+ if (!ast_strlen_zero(v->value)) {
+ newprefix[0] = '/';
+ ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
+ } else {
+ newprefix[0] = '\0';
+ }
+
+ }
v = v->next;
}
ast_config_destroy(cfg);
@@ -416,6 +613,7 @@
ast_copy_string(prefix, newprefix, sizeof(prefix));
prefix_len = strlen(prefix);
}
+ enablestatic = newenablestatic;
http_server_start(&sin);
return 0;
}
@@ -437,7 +635,7 @@
ast_cli(fd, "Enabled URI's:\n");
urih = uris;
while(urih){
- ast_cli(fd, "/%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
+ ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
urih = urih->next;
}
if (!uris)
@@ -462,6 +660,7 @@
int ast_http_init(void)
{
ast_http_uri_link(&statusuri);
+ ast_http_uri_link(&staticuri);
ast_cli_register_multiple(http_cli, sizeof(http_cli) / sizeof(http_cli[0]));
return __ast_http_load(0);
}
Modified: team/oej/test-this-branch/include/asterisk/http.h
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/include/asterisk/http.h?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/include/asterisk/http.h (original)
+++ team/oej/test-this-branch/include/asterisk/http.h Mon Apr 3 03:02:40 2006
@@ -58,6 +58,8 @@
/* Destroy an HTTP server */
void ast_http_uri_unlink(struct ast_http_uri *urihandler);
+char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, int buflen);
+
int ast_http_init(void);
int ast_http_reload(void);
Modified: team/oej/test-this-branch/include/asterisk/manager.h
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/include/asterisk/manager.h?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/include/asterisk/manager.h (original)
+++ team/oej/test-this-branch/include/asterisk/manager.h Mon Apr 3 03:02:40 2006
@@ -124,11 +124,6 @@
/* Export manager structures */
#define AST_MAX_MANHEADERS 80
#define AST_MAX_MANHEADER_LEN 256
-
-struct eventqent {
- struct eventqent *next;
- char eventdata[1];
-};
struct ast_manager_user {
char username[80];
@@ -141,8 +136,7 @@
struct ast_manager_user *next;
};
-
-struct mansession {
+static struct mansession {
/*! Execution thread */
pthread_t t;
/*! Thread lock -- don't use in action callbacks, it's already taken care of */
@@ -155,6 +149,18 @@
int busy;
/*! Whether or not we're "dead" */
int dead;
+ /*! Whether an HTTP manager is in use */
+ int inuse;
+ /*! Whether an HTTP session should be destroyed */
+ int needdestroy;
+ /*! Whether an HTTP session has someone waiting on events */
+ pthread_t waiting_thread;
+ /*! Unique manager identifer */
+ unsigned long managerid;
+ /*! Session timeout if HTTP */
+ time_t sessiontimeout;
+ /*! Output from manager interface */
+ char *outputstr;
/*! Logged in username */
char username[80];
/*! Authentication challenge */
@@ -174,7 +180,7 @@
/* Timeout for ast_carefulwrite() */
int writetimeout;
struct mansession *next;
-};
+} *sessions = NULL;
struct message {
int hdrcount;
Modified: team/oej/test-this-branch/loader.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/loader.c?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/loader.c (original)
+++ team/oej/test-this-branch/loader.c Mon Apr 3 03:02:40 2006
@@ -375,18 +375,18 @@
/* print some debugging info for new modules */
if (m->state == MS_NEW &&
(m->cb.exported_symbols || m->cb.required_symbols))
- ast_log(LOG_WARNING,
+ ast_log(LOG_NOTICE,
"module %-30s exports %p requires %p state %s(%d)\n",
m->resource, m->cb.exported_symbols,
m->cb.required_symbols,
st_name(m->state), m->state);
}
- ast_log(LOG_WARNING, "---- fixup (%s): %d modules, %d new ---\n",
+ ast_log(LOG_DEBUG, "---- fixup (%s): %d modules, %d new ---\n",
caller, total, new);
for (;;cycle++) {
int again = 0; /* set if we need another round */
- ast_log(LOG_WARNING, "---- fixup: cycle %d ---\n", cycle);
+ ast_log(LOG_DEBUG, "---- fixup: cycle %d ---\n", cycle);
AST_LIST_TRAVERSE(&module_list, m, next) {
if (resolve(m))
again = 1; /* something changed */
@@ -417,7 +417,7 @@
if (!again) /* we are done */
break;
}
- ast_log(LOG_WARNING, "---- fixup complete ---\n");
+ ast_log(LOG_DEBUG, "---- fixup complete ---\n");
in_fixup--;
return 0;
}
Modified: team/oej/test-this-branch/manager.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/manager.c?rev=17044&r1=17043&r2=17044&view=diff
==============================================================================
--- team/oej/test-this-branch/manager.c (original)
+++ team/oej/test-this-branch/manager.c Mon Apr 3 03:02:40 2006
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netdb.h>
@@ -64,6 +65,7 @@
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
+#include "asterisk/http.h"
struct fast_originate_helper {
char tech[AST_MAX_MANHEADER_LEN];
@@ -81,11 +83,20 @@
struct ast_variable *vars;
};
+struct eventqent {
+ int usecount;
+ int category;
+ ast_mutex_t lock;
+ struct eventqent *next;
+ char eventdata[1];
+};
+
static int enabled = 0;
static int portno = DEFAULT_MANAGER_PORT;
static int asock = -1;
static int displayconnects = 1;
static int timestampevents = 0;
+static int httptimeout = 60;
static pthread_t t;
AST_MUTEX_DEFINE_STATIC(sessionlock);
@@ -93,6 +104,8 @@
static struct ast_manager_user *amus =NULL;
AST_MUTEX_DEFINE_STATIC(amulock);
static int block_sockets = 0;
+static int num_sessions = 0;
+struct eventqent *master_eventq = NULL;
static struct permalias {
int num;
@@ -221,11 +234,168 @@
return ret;
}
+static void xml_copy_escape(char **dst, int *maxlen, const char *src, int lower)
+{
+ while (*src && (*maxlen > 6)) {
+ switch(*src) {
+ case '<':
+ strcpy(*dst, "<");
+ (*dst) += 4;
+ *maxlen -= 4;
+ break;
+ case '>':
+ strcpy(*dst, ">");
+ (*dst) += 4;
+ *maxlen -= 4;
+ break;
+ case '\"':
+ strcpy(*dst, """);
+ (*dst) += 6;
+ *maxlen -= 6;
+ break;
+ case '\'':
+ strcpy(*dst, "'");
+ (*dst) += 6;
+ *maxlen -= 6;
+ break;
+ case '&':
+ strcpy(*dst, "&");
+ (*dst) += 4;
+ *maxlen -= 4;
+ break;
+ default:
+ *(*dst)++ = lower ? tolower(*src) : *src;
+ (*maxlen)--;
+ }
+ src++;
+ }
+}
+static char *xml_translate(char *in, struct ast_variable *vars)
+{
+ struct ast_variable *v;
+ char *dest=NULL;
+ char *out, *tmp, *var, *val;
+ char *objtype=NULL;
+ int colons = 0;
+ int breaks = 0;
+ int len;
+ int count = 1;
+ int escaped = 0;
+ int inobj = 0;
+ int x;
+ v = vars;
+ while(v) {
+ if (!dest && !strcasecmp(v->name, "ajaxdest"))
+ dest = v->value;
+ else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
+ objtype = v->value;
+ v = v->next;
+ }
+ if (!dest)
+ dest = "unknown";
+ if (!objtype)
+ objtype = "generic";
+ for (x=0;in[x];x++) {
+ if (in[x] == ':')
+ colons++;
+ else if (in[x] == '\n')
+ breaks++;
+ else if (strchr("&\"<>", in[x]))
+ escaped++;
+ }
+ len = strlen(in) + colons * 5 + breaks * (40 + strlen(dest) + strlen(objtype)) + escaped * 10; /* foo="bar", "<response type=\"object\" id=\"dest\"", "&" */
+ out = malloc(len);
+ if (!out)
+ return 0;
+ tmp = out;
+ while(*in) {
+ var = in;
+ while (*in && (*in >= 32)) in++;
+ if (*in) {
+ if ((count > 3) && inobj) {
+ ast_build_string(&tmp, &len, " /></response>\n");
+ inobj = 0;
+ }
+ count = 0;
+ while (*in && (*in < 32)) {
+ *in = '\0';
+ in++;
+ count++;
+ }
+ val = strchr(var, ':');
+ if (val) {
+ *val = '\0';
+ val++;
+ if (*val == ' ')
+ val++;
+ if (!inobj) {
+ ast_build_string(&tmp, &len, "<response type='object' id='%s'><%s", dest, objtype);
+ inobj = 1;
+ }
+ ast_build_string(&tmp, &len, " ");
+ xml_copy_escape(&tmp, &len, var, 1);
+ ast_build_string(&tmp, &len, "='");
+ xml_copy_escape(&tmp, &len, val, 0);
+ ast_build_string(&tmp, &len, "'");
+ }
+ }
+ }
+ if (inobj)
+ ast_build_string(&tmp, &len, " /></response>\n");
+ return out;
+}
+
+static char *html_translate(char *in)
+{
+ int x;
+ int colons = 0;
+ int breaks = 0;
+ int len;
+ int count=1;
+ char *tmp, *var, *val, *out;
+ for (x=0;in[x];x++) {
+ if (in[x] == ':')
+ colons++;
+ if (in[x] == '\n')
+ breaks++;
+ }
+ len = strlen(in) + colons * 40 + breaks * 40; /* <tr><td></td><td></td></tr>, "<tr><td colspan=\"2\"><hr></td></tr> */
+ out = malloc(len);
+ if (!out)
+ return 0;
+ tmp = out;
+ while(*in) {
+ var = in;
+ while (*in && (*in >= 32)) in++;
+ if (*in) {
+ if ((count % 4) == 0){
+ ast_build_string(&tmp, &len, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+ }
+ count = 0;
+ while (*in && (*in < 32)) {
+ *in = '\0';
+ in++;
+ count++;
+ }
+ val = strchr(var, ':');
+ if (val) {
+ *val = '\0';
+ val++;
+ if (*val == ' ')
+ val++;
+ ast_build_string(&tmp, &len, "<tr><td>%s</td><td>%s</td></tr>\r\n", var, val);
+ }
+ }
+ }
+ return out;
+}
+
void astman_append(struct mansession *s, const char *fmt, ...)
{
char *stuff;
int res;
va_list ap;
+ char *tmp;
va_start(ap, fmt);
res = vasprintf(&stuff, fmt, ap);
@@ -233,7 +403,17 @@
if (res == -1) {
ast_log(LOG_ERROR, "Memory allocation failure\n");
} else {
- ast_carefulwrite(s->fd, stuff, strlen(stuff), 100);
+ if (s->fd > -1)
+ ast_carefulwrite(s->fd, stuff, strlen(stuff), 100);
+ else {
+ tmp = realloc(s->outputstr, (s->outputstr ? strlen(s->outputstr) : 0) + strlen(stuff) + 1);
+ if (tmp) {
+ if (!s->outputstr)
+ tmp[0] = '\0';
+ s->outputstr = tmp;
+ strcat(s->outputstr, stuff);
+ }
+ }
free(stuff);
}
}
@@ -299,6 +479,23 @@
return RESULT_SUCCESS;
}
+/*! \brief handle_showmanconn: CLI command show manager connected */
+/* Should change to "manager show connected" */
+static int handle_showmaneventq(int fd, int argc, char *argv[])
+{
+ struct eventqent *s;
+ ast_mutex_lock(&sessionlock);
+ s = master_eventq;
+ while (s) {
+ ast_cli(fd, "Usecount: %d\n",s->usecount);
+ ast_cli(fd, "Category: %d\n", s->category);
+ ast_cli(fd, "Event:\n%s", s->eventdata);
+ s = s->next;
+ }
+ ast_mutex_unlock(&sessionlock);
+ return RESULT_SUCCESS;
+}
+
static char showmancmd_help[] =
"Usage: show manager command <actionname>\n"
" Shows the detailed description for a specific Asterisk manager interface command.\n";
@@ -312,6 +509,11 @@
" Prints a listing of the users that are currently connected to the\n"
"Asterisk manager interface.\n";
+static char showmaneventq_help[] =
+"Usage: show manager eventq\n"
+" Prints a listing of all events pending in the Asterisk manger\n"
+"event queue.\n";
+
static struct ast_cli_entry show_mancmd_cli =
{ { "show", "manager", "command", NULL },
handle_showmancmd, "Show a manager interface command", showmancmd_help, complete_show_mancmd };
@@ -324,6 +526,7 @@
{ { "show", "manager", "connected", NULL },
handle_showmanconn, "Show connected manager interface users", showmanconn_help };
+<<<<<<< .working
static int handle_showmanager(int fd, int argc, char *argv[])
{
@@ -415,16 +618,36 @@
{ { "manager", "show", "user" }, handle_showmanager, "Display information on a specific manager", showmanager_help};
+static struct ast_cli_entry show_maneventq_cli =
+ { { "show", "manager", "eventq", NULL },
+ handle_showmaneventq, "Show manager interface queued events", showmaneventq_help };
+
+static void unuse_eventqent(struct eventqent *e)
+{
+ /* XXX Need to atomically decrement the users. Change this to atomic_dec
+ one day when we have such a beast XXX */
+ int val;
+ ast_mutex_lock(&e->lock);
+ e->usecount--;
+ val = !e->usecount && e->next;
+ ast_mutex_unlock(&e->lock);
+ /* Wake up sleeping beauty */
+ if (val)
+ pthread_kill(t, SIGURG);
+}
+
static void free_session(struct mansession *s)
{
struct eventqent *eqe;
if (s->fd > -1)
close(s->fd);
+ if (s->outputstr)
+ free(s->outputstr);
ast_mutex_destroy(&s->__lock);
while(s->eventq) {
eqe = s->eventq;
s->eventq = s->eventq->next;
- free(eqe);
+ unuse_eventqent(eqe);
}
free(s);
}
@@ -446,6 +669,7 @@
else
sessions = cur->next;
free_session(s);
+ num_sessions--;
} else
ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
ast_mutex_unlock(&sessionlock);
@@ -706,7 +930,7 @@
return -1;
}
}
- } else if (password && !strcasecmp(password, pass)) {
+ } else if (password && !strcmp(password, pass)) {
break;
} else {
ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), user);
@@ -733,13 +957,105 @@
/*! \brief PING: Manager PING */
static char mandescr_ping[] =
-"Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the "
+"Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the\n"
" manager connection open.\n"
"Variables: NONE\n";
static int action_ping(struct mansession *s, struct message *m)
{
astman_send_response(s, m, "Pong", NULL);
+ return 0;
+}
+
+/*! \brief WAITEVENT: Manager WAITEVENT */
+static char mandescr_waitevent[] =
+"Description: A 'WaitEvent' action will ellicit a 'Success' response. Whenever\n"
+"a manager event is queued. Once WaitEvent has been called on an HTTP manager\n"
+"session, events will be generated and queued.\n"
+"Variables: \n"
+" Timeout: Maximum time to wait for events\n";
+
+static int action_waitevent(struct mansession *s, struct message *m)
+{
+ char *timeouts = astman_get_header(m, "Timeout");
+ int timeout = -1, max;
+ int x;
+ int needexit = 0;
+ time_t now;
+ struct eventqent *eqe;
+ char *id = astman_get_header(m,"ActionID");
+ char idText[256]="";
+
+ if (!ast_strlen_zero(id))
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+
+ if (!ast_strlen_zero(timeouts)) {
+ sscanf(timeouts, "%i", &timeout);
+ }
+
+ ast_mutex_lock(&s->__lock);
+ if (s->waiting_thread != AST_PTHREADT_NULL) {
+ pthread_kill(s->waiting_thread, SIGURG);
+ }
+ if (s->sessiontimeout) {
+ time(&now);
+ max = s->sessiontimeout - now - 10;
+ if (max < 0)
+ max = 0;
+ if ((timeout < 0) || (timeout > max))
+ timeout = max;
+ if (!s->send_events)
+ s->send_events = -1;
+ /* Once waitevent is called, always queue events from now on */
+ if (s->busy == 1)
+ s->busy = 2;
+ }
+ ast_mutex_unlock(&s->__lock);
+ s->waiting_thread = pthread_self();
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Starting waiting for an event!\n");
+ for (x=0;((x<timeout) || (timeout < 0)); x++) {
+ ast_mutex_lock(&s->__lock);
+ if (s->eventq && s->eventq->next)
+ needexit = 1;
+ if (s->waiting_thread != pthread_self())
+ needexit = 1;
+ if (s->needdestroy)
+ needexit = 1;
+ ast_mutex_unlock(&s->__lock);
+ if (needexit)
+ break;
+ if (s->fd > 0) {
+ if (ast_wait_for_input(s->fd, 1000))
+ break;
+ } else {
+ sleep(1);
+ }
+ }
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Finished waiting for an event!\n");
+ ast_mutex_lock(&s->__lock);
+ if (s->waiting_thread == pthread_self()) {
+ astman_send_response(s, m, "Success", "Waiting for Event...");
+ /* Only show events if we're the most recent waiter */
+ while(s->eventq->next) {
+ eqe = s->eventq->next;
+ if (((s->readperm & eqe->category) == eqe->category) &&
+ ((s->send_events & eqe->category) == eqe->category)) {
+ astman_append(s, "%s", eqe->eventdata);
+ }
+ unuse_eventqent(s->eventq);
+ s->eventq = eqe;
+ }
+ astman_append(s,
+ "Event: WaitEventComplete\r\n"
+ "%s"
+ "\r\n",idText);
+ s->waiting_thread = AST_PTHREADT_NULL;
+ } else {
+ ast_log(LOG_DEBUG, "Abandoning event request!\n");
+ }
+ ast_mutex_unlock(&s->__lock);
return 0;
}
@@ -1433,6 +1749,30 @@
return 0;
}
+static int process_events(struct mansession *s)
+{
+ struct eventqent *eqe;
+ int ret = 0;
+ ast_mutex_lock(&s->__lock);
+ if (s->fd > -1) {
+ s->busy--;
+ if (!s->eventq)
+ s->eventq = master_eventq;
+ while(s->eventq->next) {
+ eqe = s->eventq->next;
+ if ((s->authenticated && (s->readperm & eqe->category) == eqe->category) &&
+ ((s->send_events & eqe->category) == eqe->category)) {
+ if (!ret && ast_carefulwrite(s->fd, eqe->eventdata, strlen(eqe->eventdata), s->writetimeout) < 0)
+ ret = -1;
+ }
+ unuse_eventqent(s->eventq);
+ s->eventq = eqe;
+ }
+ }
+ ast_mutex_unlock(&s->__lock);
+ return ret;
+}
+
static int process_message(struct mansession *s, struct message *m)
{
char action[80] = "";
@@ -1440,6 +1780,7 @@
char *id = astman_get_header(m,"ActionID");
char idText[256] = "";
char iabuf[INET_ADDRSTRLEN];
+ int ret = 0;
ast_copy_string(action, astman_get_header(m, "Action"), sizeof(action));
ast_log( LOG_DEBUG, "Manager received command '%s'\n", action );
@@ -1448,9 +1789,9 @@
astman_send_error(s, m, "Missing action in request");
return 0;
}
- if (!ast_strlen_zero(id)) {
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n",id);
- }
+ if (!ast_strlen_zero(id)) {
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n",id);
+ }
if (!s->authenticated) {
if (!strcasecmp(action, "Challenge")) {
char *authtype;
@@ -1478,10 +1819,10 @@
s->authenticated = 1;
if (option_verbose > 1) {
if ( displayconnects ) {
- ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged on from %s\n", s->username, ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ ast_verbose(VERBOSE_PREFIX_2 "%sManager '%s' logged on from %s\n", (s->sessiontimeout ? "HTTP " : ""), s->username, ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
}
}
- ast_log(LOG_EVENT, "Manager '%s' logged on from %s\n", s->username, ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->sessiontimeout ? "HTTP " : ""), s->username, ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
astman_send_ack(s, m, "Authentication accepted");
}
[... 570 lines stripped ...]
More information about the asterisk-commits
mailing list