From 5042462dccba27c667f02d9998176bd56534a86e Mon Sep 17 00:00:00 2001 From: David Troy Date: Sat, 1 Apr 2006 16:12:53 +0000 Subject: Populating trunk git-svn-id: http://svncommunity.digium.com/svn/astmanproxy/trunk@10 f02b47b9-160a-0410-81a6-dc3441afb0ec --- common.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 common.c (limited to 'common.c') diff --git a/common.c b/common.c new file mode 100644 index 0000000..5f63c15 --- /dev/null +++ b/common.c @@ -0,0 +1,147 @@ +#include "astmanproxy.h" + +/* This routine based on get_input from Asterisk manager.c */ +/* Good generic line-based input routine for \r\n\r\n terminated input */ +/* Used by standard.c and other input handlers */ +int get_input(struct mansession *s, char *output) +{ + /* output must have at least sizeof(s->inbuf) space */ + int res; + int x; + struct pollfd fds[1]; + char iabuf[INET_ADDRSTRLEN]; + + debugmsg("in get_input"); + + /* Look for \r\n from the front, our preferred end of line */ + for (x=0;xinlen;x++) { + int xtra = 0; + if (s->inbuf[x] == '\n') { + if (x && s->inbuf[x-1] == '\r') { + xtra = 1; + } + /* Copy output data not including \r\n */ + memcpy(output, s->inbuf, x - xtra); + /* Add trailing \0 */ + output[x-xtra] = '\0'; + /* Move remaining data back to the front */ + memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x); + s->inlen -= (x + 1); + return 1; + } + } + + if (s->inlen >= sizeof(s->inbuf) - 1) { + if (debug) + debugmsg("Warning: Got long line with no end from %s: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->inbuf); + s->inlen = 0; + } + debugmsg("attempting poll operation"); + fds[0].fd = s->fd; + fds[0].events = POLLIN; + res = poll(fds, 1, -1); + debugmsg("returned from poll op"); + if (res < 0 && debug) { + debugmsg("Select returned error"); + } else if (res > 0) { + pthread_mutex_lock(&s->lock); + debugmsg("attempting socket read in get_input..."); + res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen); + pthread_mutex_unlock(&s->lock); + if (res < 1) + return -1; + } + s->inlen += res; + s->inbuf[s->inlen] = '\0'; + return 0; + /* We have some input, but it's not ready for processing */ +} + +char *astman_get_header(struct message *m, char *var) +{ + char cmp[80]; + int x; + snprintf(cmp, sizeof(cmp), "%s: ", var); + for (x=0;xhdrcount;x++) + if (!strncasecmp(cmp, m->headers[x], strlen(cmp))) + return m->headers[x] + strlen(cmp); + return ""; +} + +int AddHeader(struct message *m, const char *fmt, ...) { + va_list ap; + + int res; + + if (m->hdrcount < MAX_HEADERS - 1) { + va_start(ap, fmt); + vsprintf(m->headers[m->hdrcount], fmt, ap); + va_end(ap); + m->hdrcount++; + res = 0; + } else + res = 1; + + return res; +} + +/* Recursive thread safe replacement of inet_ntoa */ +const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia) +{ + return inet_ntop(AF_INET, &ia, buf, bufsiz); +} + + +int connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec) +{ + int flags, n, error; + socklen_t len; + fd_set rset, wset; + struct timeval tval; + + flags = fcntl(sockfd, F_GETFL, 0); + fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + + error = 0; + if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0) + if (errno != EINPROGRESS) + return(-1); + + /* Do whatever we want while the connect is taking place. */ + + if (n == 0) + goto done; /* connect completed immediately */ + + 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 (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); + } + +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(0); +} -- cgit