X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Fhttp.c;h=6580381a4d2feeb0f7c60cf34454dff2eca3d915;hb=87e9791ee9a652b3665d59ca5bf0e927e935e666;hp=7c69871905ff640d89fd55ec6ed456fe5c7072f9;hpb=8df7977676dd0909eceba9bc2a82c4e9523b1bed;p=pazpar2-moved-to-github.git diff --git a/src/http.c b/src/http.c index 7c69871..6580381 100644 --- a/src/http.c +++ b/src/http.c @@ -1,5 +1,5 @@ /* This file is part of Pazpar2. - Copyright (C) 2006-2011 Index Data + Copyright (C) 2006-2013 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 @@ -21,6 +21,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #endif +#if HAVE_SYS_TIME_H +#include +#endif + #include #ifdef WIN32 #include @@ -66,6 +70,7 @@ typedef int socklen_t; #include "ppmutex.h" #include "session.h" #include "http.h" +#include "parameters.h" #define MAX_HTTP_HEADER 4096 @@ -94,18 +99,12 @@ static void http_server_incref(http_server_t hs); struct http_server { - struct http_buf *http_buf_freelist; - int http_buf_freelist_count; - int http_buf_freelist_max; - - struct http_channel *http_channel_freelist; - int http_channel_freelist_count; - int http_channel_freelist_max; YAZ_MUTEX mutex; int listener_socket; int ref_count; http_sessions_t http_sessions; struct sockaddr_in *proxy_addr; + FILE *record_file; }; struct http_channel_observer_s { @@ -128,18 +127,7 @@ const char *http_lookup_header(struct http_header *header, static struct http_buf *http_buf_create(http_server_t hs) { - struct http_buf *r = 0; - - yaz_mutex_enter(hs->mutex); - if (hs->http_buf_freelist) - { - r = hs->http_buf_freelist; - hs->http_buf_freelist = hs->http_buf_freelist->next; - hs->http_buf_freelist_count--; - } - yaz_mutex_leave(hs->mutex); - if (!r) - r = xmalloc(sizeof(struct http_buf)); + struct http_buf *r = xmalloc(sizeof(*r)); r->offset = 0; r->len = 0; r->next = 0; @@ -148,20 +136,7 @@ static struct http_buf *http_buf_create(http_server_t hs) static void http_buf_destroy(http_server_t hs, struct http_buf *b) { - yaz_mutex_enter(hs->mutex); - if (hs->http_buf_freelist_max > 0 && hs->http_buf_freelist_count > hs->http_buf_freelist_max) { - xfree(b); - while (b = hs->http_buf_freelist) { - xfree(b); - hs->http_buf_freelist = hs->http_buf_freelist->next; - } - } - else { - b->next = hs->http_buf_freelist; - hs->http_buf_freelist = b; - hs->http_buf_freelist_count++; - } - yaz_mutex_leave(hs->mutex); + xfree(b); } static void http_buf_destroy_queue(http_server_t hs, struct http_buf *b) @@ -675,6 +650,12 @@ static struct http_buf *http_serialize_response(struct http_channel *c, if (r->payload) wrbuf_puts(c->wrbuf, r->payload); + if (global_parameters.dump_records > 1) + { + FILE *lf = yaz_log_file(); + yaz_log(YLOG_LOG, "Response:"); + fwrite(wrbuf_buf(c->wrbuf), 1, wrbuf_len(c->wrbuf), lf); + } return http_buf_bywrbuf(c->http_server, c->wrbuf); } @@ -715,12 +696,12 @@ static int http_weshouldproxy(struct http_request *rq) } -struct http_header * http_header_append(struct http_channel *ch, - struct http_header * hp, - const char *name, +struct http_header * http_header_append(struct http_channel *ch, + struct http_header * hp, + const char *name, const char *value) { - struct http_header *hpnew = 0; + struct http_header *hpnew = 0; if (!hp | !ch) return 0; @@ -732,18 +713,18 @@ struct http_header * http_header_append(struct http_channel *ch, hpnew = nmem_malloc(ch->nmem, sizeof *hpnew); hpnew->name = nmem_strdup(ch->nmem, name); hpnew->value = nmem_strdup(ch->nmem, value); - + hpnew->next = 0; hp->next = hpnew; hp = hp->next; - + return hpnew; } return hp; } - + static int is_inprogress(void) { #ifdef WIN32 @@ -754,7 +735,7 @@ static int is_inprogress(void) return 1; #endif return 0; -} +} static void enable_nonblock(int sock) { @@ -764,7 +745,7 @@ static void enable_nonblock(int sock) if (ioctlsocket(sock, FIONBIO, &flags) < 0) yaz_log(YLOG_FATAL|YLOG_ERRNO, "ioctlsocket"); #else - if ((flags = fcntl(sock, F_GETFL, 0)) < 0) + if ((flags = fcntl(sock, F_GETFL, 0)) < 0) yaz_log(YLOG_FATAL|YLOG_ERRNO, "fcntl"); if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) yaz_log(YLOG_FATAL|YLOG_ERRNO, "fcntl2"); @@ -799,10 +780,10 @@ static int http_proxy(struct http_request *rq) abort(); enable_nonblock(sock); if (connect(sock, (struct sockaddr *) - c->server->http_server->proxy_addr, + c->server->http_server->proxy_addr, sizeof(*c->server->http_server->proxy_addr)) < 0) { - if (!is_inprogress()) + if (!is_inprogress()) { yaz_log(YLOG_WARN|YLOG_ERRNO, "Proxy connect"); return -1; @@ -827,27 +808,27 @@ static int http_proxy(struct http_request *rq) yaz_log(YLOG_WARN, "Failed to find Host header in proxy"); return -1; } - + // Add new header about paraz2 version, host, remote client address, etc. { char server_via[128]; hp = rq->headers; - hp = http_header_append(c, hp, + hp = http_header_append(c, hp, "X-Pazpar2-Version", PACKAGE_VERSION); - hp = http_header_append(c, hp, + hp = http_header_append(c, hp, "X-Pazpar2-Server-Host", ser->host); sprintf(server_port, "%d", ser->port); - hp = http_header_append(c, hp, + hp = http_header_append(c, hp, "X-Pazpar2-Server-Port", server_port); - yaz_snprintf(server_via, sizeof(server_via), - "1.1 %s:%s (%s/%s)", + yaz_snprintf(server_via, sizeof(server_via), + "1.1 %s:%s (%s/%s)", 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); } - + requestbuf = http_serialize_request(rq); http_buf_enqueue(&p->oqueue, requestbuf); @@ -900,7 +881,7 @@ static void http_io(IOCHAN i, int event) { int res, reqlen; struct http_buf *htbuf; - + htbuf = http_buf_create(hc->http_server); res = recv(iochan_getfd(i), htbuf->buf, HTTP_BUF_SIZE -1, 0); if (res == -1 && errno == EAGAIN) @@ -910,7 +891,18 @@ static void http_io(IOCHAN i, int event) } if (res <= 0) { +#if HAVE_SYS_TIME_H + if (hc->http_server->record_file) + { + struct timeval tv; + gettimeofday(&tv, 0); + fprintf(hc->http_server->record_file, "r %lld %lld %lld 0\n", + (long long) tv.tv_sec, (long long) tv.tv_usec, + (long long) iochan_getfd(i)); + } +#endif http_buf_destroy(hc->http_server, htbuf); + fflush(hc->http_server->record_file); http_channel_destroy(i); return; } @@ -927,6 +919,23 @@ static void http_io(IOCHAN i, int event) return; // we have a complete HTTP request nmem_reset(hc->nmem); +#if HAVE_SYS_TIME_H + if (hc->http_server->record_file) + { + struct timeval tv; + int sz = 0; + struct http_buf *hb; + for (hb = hc->iqueue; hb; hb = hb->next) + sz += hb->len; + gettimeofday(&tv, 0); + fprintf(hc->http_server->record_file, "r %lld %lld %lld %d\n", + (long long) tv.tv_sec, (long long) tv.tv_usec, + (long long) iochan_getfd(i), sz); + for (hb = hc->iqueue; hb; hb = hb->next) + fwrite(hb->buf, 1, hb->len, hc->http_server->record_file); + fflush(hc->http_server->record_file); + } + #endif if (!(hc->request = http_parse_request(hc, &hc->iqueue, reqlen))) { yaz_log(YLOG_WARN, "Failed to parse request"); @@ -967,6 +976,21 @@ static void http_io(IOCHAN i, int event) } if (res == wb->len) { +#if HAVE_SYS_TIME_H + if (hc->http_server->record_file) + { + struct timeval tv; + int sz = wb->offset + wb->len; + gettimeofday(&tv, 0); + fprintf(hc->http_server->record_file, "w %lld %lld %lld %d\n", + (long long) tv.tv_sec, (long long) tv.tv_usec, + (long long) iochan_getfd(i), sz); + fwrite(wb->buf, 1, wb->offset + wb->len, + hc->http_server->record_file); + fputc('\n', hc->http_server->record_file); + fflush(hc->http_server->record_file); + } + #endif hc->oqueue = hc->oqueue->next; http_buf_destroy(hc->http_server, wb); } @@ -990,7 +1014,7 @@ static void http_io(IOCHAN i, int event) } } } - if (!hc->oqueue && hc->proxy && !hc->proxy->iochan) + if (!hc->oqueue && hc->proxy && !hc->proxy->iochan) http_channel_destroy(i); // Server closed; we're done } else @@ -1062,7 +1086,7 @@ static void proxy_io(IOCHAN pi, int event) return; } if (res == htbuf->len) - { + { struct http_buf *np = htbuf->next; http_buf_destroy(hc->http_server, htbuf); pc->oqueue = np; @@ -1080,6 +1104,7 @@ static void proxy_io(IOCHAN pi, int event) default: yaz_log(YLOG_WARN, "Unexpected event on connection"); http_channel_destroy(hc->iochan); + break; } } @@ -1113,22 +1138,6 @@ static void http_channel_destroy(IOCHAN i) http_server = s->http_server; /* save it for destroy (decref) */ - yaz_mutex_enter(s->http_server->mutex); - if (s->http_server->http_channel_freelist_max > 0 && s->http_server->http_channel_freelist_count > s->http_server->http_channel_freelist_max) { - while ((s->next = s->http_server->http_channel_freelist)) { - nmem_destroy(s->next->nmem); - wrbuf_destroy(s->next->wrbuf); - xfree(s->next); - s->http_server->http_channel_freelist = s->http_server->http_channel_freelist->next; - } - } - else { - s->next = s->http_server->http_channel_freelist; - s->http_server->http_channel_freelist = s; - s->http_server->http_channel_freelist_count++; - } - yaz_mutex_leave(s->http_server->mutex); - http_server_destroy(http_server); #ifdef WIN32 @@ -1137,6 +1146,9 @@ static void http_channel_destroy(IOCHAN i) close(iochan_getfd(i)); #endif iochan_destroy(i); + nmem_destroy(s->nmem); + wrbuf_destroy(s->wrbuf); + xfree(s); } static struct http_channel *http_channel_create(http_server_t hs, @@ -1145,25 +1157,10 @@ static struct http_channel *http_channel_create(http_server_t hs, { struct http_channel *r; - yaz_mutex_enter(hs->mutex); - r = hs->http_channel_freelist; - if (r) { - hs->http_channel_freelist = r->next; - hs->http_channel_freelist_count--; - } - yaz_mutex_leave(hs->mutex); + r = xmalloc(sizeof(struct http_channel)); + r->nmem = nmem_create(); + r->wrbuf = wrbuf_alloc(); - if (r) - { - nmem_reset(r->nmem); - wrbuf_rewind(r->wrbuf); - } - else - { - r = xmalloc(sizeof(struct http_channel)); - r->nmem = nmem_create(); - r->wrbuf = wrbuf_alloc(); - } http_server_incref(hs); r->http_server = hs; r->http_sessions = hs->http_sessions; @@ -1208,7 +1205,7 @@ 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, "http_session_socket"); - + ch = http_channel_create(server->http_server, inet_ntoa(addr.sin_addr), server); ch->iochan = c; @@ -1217,7 +1214,8 @@ static void http_accept(IOCHAN i, int event) } /* Create a http-channel listener, syntax [host:]port */ -int http_init(const char *addr, struct conf_server *server) +int http_init(const char *addr, struct conf_server *server, + const char *record_fname) { IOCHAN c; int l; @@ -1226,9 +1224,21 @@ int http_init(const char *addr, struct conf_server *server) int one = 1; const char *pp; short port; + FILE *record_file = 0; yaz_log(YLOG_LOG, "HTTP listener %s", addr); + + if (record_fname) + { + record_file = fopen(record_fname, "wb"); + if (!record_file) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "fopen %s", record_fname); + return 1; + } + } + memset(&myaddr, 0, sizeof myaddr); myaddr.sin_family = AF_INET; pp = strchr(addr, ':'); @@ -1267,12 +1277,12 @@ int http_init(const char *addr, struct conf_server *server) &one, sizeof(one)) < 0) return 1; - if (bind(l, (struct sockaddr *) &myaddr, sizeof myaddr) < 0) + if (bind(l, (struct sockaddr *) &myaddr, sizeof myaddr) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind"); return 1; } - if (listen(l, SOMAXCONN) < 0) + if (listen(l, SOMAXCONN) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen"); return 1; @@ -1280,6 +1290,7 @@ int http_init(const char *addr, struct conf_server *server) server->http_server = http_server_create(); + server->http_server->record_file = record_file; server->http_server->listener_socket = l; c = iochan_create(l, http_accept, EVENT_INPUT | EVENT_EXCEPT, "http_server"); @@ -1400,13 +1411,7 @@ http_server_t http_server_create(void) hs->ref_count = 1; hs->http_sessions = 0; - hs->http_channel_freelist = 0; - hs->http_channel_freelist_count = 0; - hs->http_channel_freelist_max = 10; - - hs->http_buf_freelist = 0; - hs->http_buf_freelist_count = 0; - hs->http_buf_freelist_max = 10; + hs->record_file = 0; return hs; } @@ -1422,25 +1427,11 @@ void http_server_destroy(http_server_t hs) if (r == 0) { - struct http_buf *b = hs->http_buf_freelist; - struct http_channel *c = hs->http_channel_freelist; - while (b) - { - struct http_buf *b_next = b->next; - xfree(b); - b = b_next; - } - while (c) - { - struct http_channel *c_next = c->next; - nmem_destroy(c->nmem); - wrbuf_destroy(c->wrbuf); - xfree(c); - c = c_next; - } http_sessions_destroy(hs->http_sessions); xfree(hs->proxy_addr); yaz_mutex_destroy(&hs->mutex); + if (hs->record_file) + fclose(hs->record_file); xfree(hs); } }