summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Troy <dave@popvox.com>2006-04-06 22:30:00 +0000
committerDavid Troy <dave@popvox.com>2006-04-06 22:30:00 +0000
commitca4ed8c2cbec7db4d9001e4f5725dcb3ea71399a (patch)
tree591c62db1580fa484cba98912634da2688358920
parent012c2fcfbfec0a7d2676c393a9fdc9fee74fa09b (diff)
downloadastmanproxy-ca4ed8c2cbec7db4d9001e4f5725dcb3ea71399a.zip
astmanproxy-ca4ed8c2cbec7db4d9001e4f5725dcb3ea71399a.tar.gz
astmanproxy-ca4ed8c2cbec7db4d9001e4f5725dcb3ea71399a.tar.xz
git-svn-id: http://svncommunity.digium.com/svn/astmanproxy/branches/1.20pre@89 f02b47b9-160a-0410-81a6-dc3441afb0ec
-rw-r--r--TODO2
-rwxr-xr-xperl/soapclient.pl17
-rw-r--r--src/astmanproxy.c9
-rw-r--r--src/soap.c157
-rw-r--r--src/ssl.c73
5 files changed, 68 insertions, 190 deletions
diff --git a/TODO b/TODO
index 8083f1c..d360db5 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,6 @@
fix non-blocking in ast_connect
+fix reconnect to lost asterisk server (socket reuse)
+check s->connect construct
kill autodisconnect concept; this would be managed by inputcomplete/outputcomplete in drivers?
finish SOAP handler
diff --git a/perl/soapclient.pl b/perl/soapclient.pl
deleted file mode 100755
index 76c766c..0000000
--- a/perl/soapclient.pl
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/perl -w
-#
-# This is for testing only; the thought is to add content handlers
-# to http.c to deal with 1) REST (default), 2) XML/XMLRPC,
-# 3) SOAP http data input
-#
-# Do not expect this to do anything right now
-
-use SOAP::Lite;
-
-print SOAP::Lite
- -> uri('http://localhost:1234/astmanproxy')
- -> proxy('http://localhost:1234/')
- -> astman('Action: Ping')
- -> result . "\n";
-
-exit(0);
diff --git a/src/astmanproxy.c b/src/astmanproxy.c
index dbbb05c..a22f1b8 100644
--- a/src/astmanproxy.c
+++ b/src/astmanproxy.c
@@ -120,7 +120,7 @@ void leave(int sig) {
void Version( void )
{
- printf("astmanproxy: Version %s, (C) David C. Troy\n", PROXY_VERSION);
+ printf("astmanproxy: Version %s, (C) David C. Troy 2005-2006\n", PROXY_VERSION);
return;
}
@@ -345,7 +345,8 @@ void *HandleAsterisk(struct mansession *s)
if (!WriteClients(&m))
break;
} else if (res < 0) {
- if (debug)
+ /* TODO: do we need to do more than this here? or something different? */
+ if ( debug )
debugmsg("asterisk@%s: Not connected", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
if ( ConnectAsterisk(s) )
break;
@@ -385,8 +386,8 @@ int ConnectAsterisk(struct mansession *s) {
for ( ;; ) {
if ( ast_connect(s) == -1 ) {
if (debug)
- debugmsg("asterisk@%s: Connect failed, Retrying (%d) %s",
- ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), r, strerror(errno) );
+ debugmsg("asterisk@%s: Connect failed, Retrying (%d) %s [%d]",
+ ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), r, strerror(errno), errno );
if (pc.maxretries && (++r>pc.maxretries) ) {
res = 1;
break;
diff --git a/src/soap.c b/src/soap.c
deleted file mode 100644
index 8a8d245..0000000
--- a/src/soap.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Asterisk Manager Proxy
- Copyright (c) 2005 David C. Troy <dave@popvox.com>
-
- 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 */
diff --git a/src/ssl.c b/src/ssl.c
index c77d57a..9f9ff0f 100644
--- a/src/ssl.c
+++ b/src/ssl.c
@@ -340,6 +340,7 @@ int ast_connect(struct mansession *a) {
return -1;
if (a->server->use_ssl) {
+ debugmsg("initiating ssl connection");
if ((s=sec_getslot())!=-1) { /* find a slot for the ssl handle */
sec_channel[s].fd = fd; /* remember the real fd */
@@ -360,6 +361,7 @@ int ast_connect(struct mansession *a) {
}
}
+ debugmsg("returning ast_connect with %d", fd);
pthread_mutex_lock(&a->lock);
a->fd = fd;
pthread_mutex_unlock(&a->lock);
@@ -369,22 +371,69 @@ int ast_connect(struct mansession *a) {
int connect_nonb(struct mansession *a)
{
- int s, flags, one=1;
+ int flags, n, error;
+ socklen_t len;
+ fd_set rset, wset;
+ struct timeval tval;
+ int nsec = 1, sockfd;
+
+ sockfd = get_real_fd(a->fd);
+
+ flags = fcntl(sockfd, F_GETFL, 0);
+ fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+
+ error = 0;
+ if ( (n = connect(sockfd, (struct sockaddr *) &a->sin, sizeof(a->sin)) ) < 0 ) {
+ /* TODO: This seems like the nine pound hammer to me... */
+ /* perhaps something a bit more elegant; errno seems to change too */
+ if (errno == EISCONN || errno == 103 || errno==111) {
+ debugmsg("connect_nonb: error %d, closing old fd and grabbing a new one...", errno);
+ /* looks like our old socket died, let's round up a new one and try again */
+ close_sock(a->fd);
+ pthread_mutex_lock(&a->lock);
+ a->fd = socket(AF_INET, SOCK_STREAM, 0);
+ pthread_mutex_unlock(&a->lock);
+ return(-1);
+ }
+ if (errno != EINPROGRESS)
+ return(-1);
+ }
- s = get_real_fd(a->fd);
+ /* Do whatever we want while the connect is taking place. */
-/* flags = fcntl(s, F_GETFL, 0);
- fcntl(s, F_SETFL, flags | O_NONBLOCK); */
+ if (n == 0)
+ goto done; /* connect completed immediately */
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one))==-1) {
- (void)close(s);
- return -1;
+ FD_ZERO(&rset);
+ FD_SET(sockfd, &rset);
+ wset = rset;
+ tval.tv_sec = nsec;
+ tval.tv_usec = 0;
+
+ if ( (n = select(sockfd+1, &rset, &wset, NULL,
+ nsec ? &tval : NULL)) == 0) {
+ /*close(sockfd);*/ /* we want to retry */
+ errno = ETIMEDOUT;
+ return(-1);
}
- if (connect(s, (struct sockaddr *) &a->sin, sizeof(a->sin)) < 0) {
- if (errno != EINPROGRESS)
- return -1;
+ if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
+ len = sizeof(error);
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+ return(-1); /* Solaris pending error */
+ } else {
+ /*err_quit("select error: sockfd not set");*/
+ logmsg("select error: sockfd not set");
+ return(-1);
}
- return s;
-}
+done:
+ fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
+
+ if (error) {
+ /* close(sockfd); */ /* disable for now, we want to retry... */
+ errno = error;
+ return(-1);
+ }
+ return(sockfd);
+}