X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fhttp.c;h=69533c6c97a0142bc6b96dbfcc34927b8e6cff9b;hb=de634461a0500801cd71d6a42aff032fa083a127;hp=b1d7b439d0568ba58480b218ef2b28601a59d18e;hpb=cc178327044177f177d0474b757f53bcd86b4d42;p=pazpar2-moved-to-github.git diff --git a/src/http.c b/src/http.c index b1d7b43..69533c6 100644 --- a/src/http.c +++ b/src/http.c @@ -1,5 +1,5 @@ /* This file is part of Pazpar2. - Copyright (C) 2006-2008 Index Data + Copyright (C) 2006-2009 Index Data Pazpar2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -17,6 +17,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#if HAVE_CONFIG_H +#include +#endif + #include #ifdef WIN32 #include @@ -28,9 +32,6 @@ typedef int socklen_t; #endif #include -#if HAVE_SYS_UIO_H -#include -#endif #include #if HAVE_UNISTD_H @@ -49,10 +50,6 @@ typedef int socklen_t; #include #include -#if HAVE_CONFIG_H -#include -#endif - #if HAVE_NETINET_IN_H #include #endif @@ -74,7 +71,8 @@ typedef int socklen_t; #define MAX_HTTP_HEADER 4096 static void proxy_io(IOCHAN i, int event); -static struct http_channel *http_create(const char *addr); +static struct http_channel *http_create(const char *addr, + struct conf_server *server); static void http_destroy(IOCHAN i); // If this is set, we proxy normal HTTP requests @@ -102,7 +100,7 @@ static const char *http_lookup_header(struct http_header *header, return 0; } -static struct http_buf *http_buf_create() +static struct http_buf *http_buf_create(void) { struct http_buf *r; @@ -233,12 +231,13 @@ static void urldecode(char *i, char *o) *(o++) = ' '; i++; } - else if (*i == '%') + else if (*i == '%' && i[1] && i[2]) { + int v; i++; - sscanf(i, "%2hhx", o); + sscanf(i, "%2x", &v); + *o++ = v; i += 2; - o++; } else *(o++) = *(i++); @@ -353,7 +352,7 @@ static int package_check(const char *buf, int sz) while (*cp == ' ') cp++; content_len = 0; - while (*cp && isdigit(*cp)) + while (*cp && isdigit(*(const unsigned char *)cp)) content_len = content_len*10 + (*cp++ - '0'); if (content_len < 0) /* prevent negative offsets */ content_len = 0; @@ -406,7 +405,7 @@ struct http_response *http_parse_response_buf(struct http_channel *c, const char return 0; *(value++) = '\0'; h->name = nmem_strdup(c->nmem, p); - while (isspace(*value)) + while (isspace(*(const unsigned char *) value)) value++; if (value >= p2) // Empty header; { @@ -591,7 +590,8 @@ struct http_request *http_parse_request(struct http_channel *c, r->content_len = start + len - buf; r->content_buf = buf; - if (!strcmp(content_type, "application/x-www-form-urlencoded")) + if (!yaz_strcmp_del("application/x-www-form-urlencoded", + content_type, "; ")) { http_parse_arguments(r, c->nmem, r->content_buf); } @@ -704,10 +704,10 @@ struct http_header * http_header_append(struct http_channel *ch, static int is_inprogress(void) { #ifdef WIN32 - if (WSAGetLastError() != WSAEWOULDBLOCK) + if (WSAGetLastError() == WSAEWOULDBLOCK) return 1; #else - if (errno != EINPROGRESS) + if (errno == EINPROGRESS) return 1; #endif return 0; @@ -736,7 +736,7 @@ static int http_proxy(struct http_request *rq) struct http_buf *requestbuf; char server_via[128] = ""; char server_port[16] = ""; - struct conf_server *ser = global_parameters.server; + struct conf_server *ser = c->server; if (!p) // This is a new connection. Create a proxy channel { @@ -795,7 +795,8 @@ static int http_proxy(struct http_request *rq) hp = http_header_append(c, hp, "X-Pazpar2-Server-Port", server_port); sprintf(server_via, "1.1 %s:%s (%s/%s)", - ser->host, server_port, PACKAGE_NAME, PACKAGE_VERSION); + ser->host ? ser->host : "@", + server_port, PACKAGE_NAME, PACKAGE_VERSION); hp = http_header_append(c, hp, "Via" , server_via); hp = http_header_append(c, hp, "X-Forwarded-For", c->addr); } @@ -890,6 +891,8 @@ static void http_io(IOCHAN i, int event) hc->request->path, *hc->request->search ? "?" : "", hc->request->search); + if (hc->request->content_buf) + yaz_log(YLOG_LOG, "%s", hc->request->content_buf); if (http_weshouldproxy(hc->request)) http_proxy(hc->request); else @@ -1062,7 +1065,8 @@ static void http_destroy(IOCHAN i) iochan_destroy(i); } -static struct http_channel *http_create(const char *addr) +static struct http_channel *http_create(const char *addr, + struct conf_server *server) { struct http_channel *r = http_channel_freelist; @@ -1078,6 +1082,7 @@ static struct http_channel *http_create(const char *addr) r->nmem = nmem_create(); r->wrbuf = wrbuf_alloc(); } + r->server = server; r->proxy = 0; r->iochan = 0; r->iqueue = r->oqueue = 0; @@ -1105,6 +1110,7 @@ static void http_accept(IOCHAN i, int event) int s; IOCHAN c; struct http_channel *ch; + struct conf_server *server = iochan_getdata(i); len = sizeof addr; if ((s = accept(fd, (struct sockaddr *) &addr, &len)) < 0) @@ -1117,15 +1123,17 @@ static void http_accept(IOCHAN i, int event) yaz_log(YLOG_DEBUG, "New command connection"); c = iochan_create(s, http_io, EVENT_INPUT | EVENT_EXCEPT); - ch = http_create(inet_ntoa(addr.sin_addr)); + ch = http_create(inet_ntoa(addr.sin_addr), server); ch->iochan = c; iochan_setdata(c, ch); pazpar2_add_channel(c); } +static int listener_socket = 0; + /* Create a http-channel listener, syntax [host:]port */ -void http_init(const char *addr) +int http_init(const char *addr, struct conf_server *server) { IOCHAN c; int l; @@ -1150,7 +1158,7 @@ void http_init(const char *addr) hostname[len] = '\0'; if (!(he = gethostbyname(hostname))){ yaz_log(YLOG_FATAL, "Unable to resolve '%s'", hostname); - exit(1); + return 1; } memcpy(&myaddr.sin_addr.s_addr, he->h_addr_list[0], he->h_length); @@ -1165,27 +1173,44 @@ void http_init(const char *addr) myaddr.sin_port = htons(port); if (!(p = getprotobyname("tcp"))) { - abort(); + return 1; } if ((l = socket(PF_INET, SOCK_STREAM, p->p_proto)) < 0) yaz_log(YLOG_FATAL|YLOG_ERRNO, "socket"); if (setsockopt(l, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one)) < 0) - abort(); + return 1; if (bind(l, (struct sockaddr *) &myaddr, sizeof myaddr) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind"); - exit(1); + return 1; } if (listen(l, SOMAXCONN) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen"); - exit(1); + return 1; } + listener_socket = l; + c = iochan_create(l, http_accept, EVENT_INPUT | EVENT_EXCEPT); + iochan_setdata(c, server); pazpar2_add_channel(c); + return 0; +} + +void http_close_server(void) +{ + /* break the event_loop (select) by closing down the HTTP listener sock */ + if (listener_socket) + { +#ifdef WIN32 + closesocket(listener_socket); +#else + close(listener_socket); +#endif + } } void http_set_proxyaddr(char *host, char *base_url) @@ -1275,7 +1300,9 @@ void http_observer_set_data2(http_channel_observer_t obs, void *data2) /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab */ +