From 8c5e24cab7e89f74bbc363223fe00dd45edb28e2 Mon Sep 17 00:00:00 2001 From: David Troy Date: Tue, 4 Apr 2006 23:01:38 +0000 Subject: git-svn-id: http://svncommunity.digium.com/svn/astmanproxy/branches/1.20pre@86 f02b47b9-160a-0410-81a6-dc3441afb0ec --- TODO | 2 +- perl/soapclient.pl | 6 +- src/soap.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 src/soap.c diff --git a/TODO b/TODO index bb0f233..8083f1c 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,6 @@ fix non-blocking in ast_connect kill autodisconnect concept; this would be managed by inputcomplete/outputcomplete in drivers? +finish SOAP handler 'connected' flag; do not set until we get "authentication accepted' back from server Check for module versions; do not run without modules installed @@ -12,4 +13,3 @@ SetInputFormat proxyaction? clean up autodisconnect vs. inputcomplete/outputcomplete deal with http non-conformity better -SOAP handler? diff --git a/perl/soapclient.pl b/perl/soapclient.pl index 2ab9c2f..4fb4d0f 100755 --- a/perl/soapclient.pl +++ b/perl/soapclient.pl @@ -3,9 +3,9 @@ use SOAP::Lite; print SOAP::Lite - -> uri('http://www.soaplite.com/Demo') - -> proxy('http://services.soaplite.com/hibye.cgi') - -> hi() + -> uri('http://localhost:1234/astmanproxy') + -> proxy('http://localhost:1234/') + -> astman('Action: Ping') -> result . "\n"; exit(0); diff --git a/src/soap.c b/src/soap.c new file mode 100644 index 0000000..8a8d245 --- /dev/null +++ b/src/soap.c @@ -0,0 +1,157 @@ +/* Asterisk Manager Proxy + Copyright (c) 2005 David C. Troy + + This program is free software, distributed under the terms of + the GNU General Public License. + + HTTP Input Handler +*/ + +#include "astmanproxy.h" + +int ParseHTTPInput(char *buf, struct message *m) { + char *n, *v; + + n = buf; + while ( (v = strstr(n, "=")) ) { + v += 1; + debugmsg("n: %s, v: %s", n, v); + strncat(m->headers[m->hdrcount], n, v-n-1); + strcat(m->headers[m->hdrcount], ": "); + + if ( (n = strstr(v, "&")) ) { + n += 1; + } else { + n = (v + strlen(v) + 1); + } + strncat(m->headers[m->hdrcount], v, n-v-1); + debugmsg("got hdr: %s", m->headers[m->hdrcount]); + m->hdrcount++; + } + + return (m->hdrcount > 0); +} + +int HTTPHeader(struct mansession *s, char *status) { + + + time_t t; + struct tm tm; + char date[80]; + char ctype[15], hdr[MAX_LEN]; + + time(&t); + localtime_r(&t, &tm); + strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm); + + if ( !strcasecmp("xml", s->output->formatname) ) + sprintf(ctype, "text/xml"); + else + sprintf(ctype, "text/plain"); + + if (!strcmp("200 OK", status) ) + sprintf(hdr, + "HTTP/1.1 %s\r\n" + "Date: %s\r\n" + "Content-Type: %s\r\n" + "Connection: close\r\n" + "Server: %s/%s\r\n\r\n", status, + date, ctype, PROXY_BANNER, PROXY_VERSION); + else + sprintf(hdr, + "HTTP/1.1 %s\r\n" + "Date: %s\r\n" + "Status: %s\r\n" + "Server: %s/%s\r\n\r\n", status, date, status, PROXY_BANNER, PROXY_VERSION); + + pthread_mutex_lock(&s->lock); + s->inputcomplete = 1; + ast_carefulwrite(s->fd, hdr, strlen(hdr), s->writetimeout); + pthread_mutex_unlock(&s->lock); + debugmsg("http header: %s", hdr); + + return 0; +} + +int _read(struct mansession *s, struct message *m) { + + /* Note: No single line may be longer than MAX_LEN/s->inbuf, as per get_input */ + /* No HTTP Input may be longer than BUFSIZE */ + + char line[MAX_LEN], method[10], formdata[MAX_LEN], status[15]; + int res, clength = 0; + + memset(method, 0, sizeof method); + memset(formdata, 0, sizeof formdata); + memset(status, 0, sizeof status); + + /* for http, don't do get_input forever */ + for (;;) { + + if (s->inputcomplete && !s->outputcomplete) + continue; + else if (s->inputcomplete && s->outputcomplete) + return -1; + + memset(line, 0, sizeof line); + res = get_input(s, line); + debugmsg("res=%d, line: %s",res, line); + + if (res > 0) { + debugmsg("Got http: %s", line); + + if ( !clength && !strncasecmp(line, "Content-Length: ", 16) ) + clength = atoi(line+16); + + if (!*method) { + if ( !strncmp(line,"POST",4) ) { + strncpy(method, line, 4); + } else if ( !strncmp(line,"GET",3)) { + if ( strlen(line) > 14 ) { + /* GET / HTTP/1.1 ---- this is bad */ + /* GET /?Action=Ping&ActionID=Foo HTTP/1.1 */ + strncpy(method, line, 3); + memcpy(formdata, line+6, strstr(line, " HTTP")-line-6); + sprintf(status, "200 OK"); + } else + sprintf(status, "501 Not Implemented"); + } + } + } else if (res == 0) { + if (*method && !*formdata) { + if ( !strcasecmp(method, "POST") && clength && s->inlen==clength) { + pthread_mutex_lock(&s->lock); + strncpy(formdata, s->inbuf, clength); + s->inlen = 0; + pthread_mutex_unlock(&s->lock); + sprintf(status, "200 OK"); + } + } + } + + if (res < 0) + break; + + if (*status) { + HTTPHeader(s, status); + + /* now, let's transform and copy into a standard message block */ + if (!strcmp("200 OK", status) ) { + res = ParseHTTPInput(formdata, m); + return res; + } else { + pthread_mutex_lock(&s->lock); + s->outputcomplete = 1; + pthread_mutex_unlock(&s->lock); + return 0; + } + } + } + return -1; +} + +int _autodisconnect() { + return 1; +} + +/* We do not define a _write or _onconnect method */ -- cgit