X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fhttp.c;h=1bbd4a1803b060ea42a989f067adacea8a97d90f;hb=0d45377ca625dc66907c18bb3f524f9d6c354236;hp=74fdf668b4b87518f6d74dfacda66a77efbee4d8;hpb=f3fe3fc7be5a8f3ab944a72f51dbc828d2ad743d;p=pazpar2-moved-to-github.git diff --git a/src/http.c b/src/http.c index 74fdf66..1bbd4a1 100644 --- a/src/http.c +++ b/src/http.c @@ -1,5 +1,5 @@ /* This file is part of Pazpar2. - Copyright (C) 2006-2013 Index Data + Copyright (C) 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 @@ -655,6 +655,7 @@ static struct http_buf *http_serialize_response(struct http_channel *c, FILE *lf = yaz_log_file(); yaz_log(YLOG_LOG, "Response:"); fwrite(wrbuf_buf(c->wrbuf), 1, wrbuf_len(c->wrbuf), lf); + fputc('\n', lf); } return http_buf_bywrbuf(c->http_server, c->wrbuf); } @@ -758,7 +759,6 @@ static int http_proxy(struct http_request *rq) struct http_proxy *p = c->proxy; struct http_header *hp; struct http_buf *requestbuf; - char server_port[16] = ""; struct conf_server *ser = c->server; if (!p) // This is a new connection. Create a proxy channel @@ -818,13 +818,12 @@ static int http_proxy(struct http_request *rq) "X-Pazpar2-Version", PACKAGE_VERSION); hp = http_header_append(c, hp, "X-Pazpar2-Server-Host", ser->host); - sprintf(server_port, "%d", ser->port); hp = http_header_append(c, hp, - "X-Pazpar2-Server-Port", server_port); + "X-Pazpar2-Server-Port", ser->port); yaz_snprintf(server_via, sizeof(server_via), "1.1 %s:%s (%s/%s)", - ser->host ? ser->host : "@", - server_port, PACKAGE_NAME, PACKAGE_VERSION); + ser->host, ser->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); } @@ -841,6 +840,16 @@ void http_send_response(struct http_channel *ch) struct http_response *rs = ch->response; struct http_buf *hb; + yaz_timing_stop(ch->yt); + if (ch->request) + { + yaz_log(YLOG_LOG, "Response: %6.5f %d %s%s%s ", + yaz_timing_get_real(ch->yt), + iochan_getfd(ch->iochan), + ch->request->path, + *ch->request->search ? "?" : "", + ch->request->search); + } assert(rs); hb = http_serialize_response(ch, rs); if (!hb) @@ -936,6 +945,7 @@ static void http_io(IOCHAN i, int event) fflush(hc->http_server->record_file); } #endif + yaz_timing_start(hc->yt); if (!(hc->request = http_parse_request(hc, &hc->iqueue, reqlen))) { yaz_log(YLOG_WARN, "Failed to parse request"); @@ -943,7 +953,9 @@ static void http_io(IOCHAN i, int event) return; } hc->response = 0; - yaz_log(YLOG_LOG, "Request: %s %s%s%s", hc->request->method, + yaz_log(YLOG_LOG, "Request: - %d %s %s%s%s", + iochan_getfd(i), + hc->request->method, hc->request->path, *hc->request->search ? "?" : "", hc->request->search); @@ -1123,6 +1135,7 @@ static void http_channel_destroy(IOCHAN i) http_buf_destroy_queue(s->http_server, s->proxy->oqueue); xfree(s->proxy); } + yaz_timing_destroy(&s->yt); http_buf_destroy_queue(s->http_server, s->iqueue); http_buf_destroy_queue(s->http_server, s->oqueue); http_fire_observers(s); @@ -1170,6 +1183,7 @@ static struct http_channel *http_channel_create(http_server_t hs, } strcpy(r->addr, addr); r->observers = 0; + r->yt = yaz_timing_create(); return r; } @@ -1178,21 +1192,21 @@ static struct http_channel *http_channel_create(http_server_t hs, static void http_accept(IOCHAN i, int event) { char host[256]; - struct sockaddr addr; + struct sockaddr_storage addr; int fd = iochan_getfd(i); - socklen_t len; + socklen_t len = sizeof addr; int s; IOCHAN c; struct http_channel *ch; struct conf_server *server = iochan_getdata(i); - len = sizeof addr; - if ((s = accept(fd, &addr, &len)) < 0) + if ((s = accept(fd, (struct sockaddr *) &addr, &len)) < 0) { yaz_log(YLOG_WARN|YLOG_ERRNO, "accept"); return; } - if (getnameinfo(&addr, len, host, sizeof(host)-1, 0, 0, NI_NUMERICHOST)) + if (getnameinfo((struct sockaddr *) &addr, len, host, sizeof(host)-1, 0, 0, + NI_NUMERICHOST)) { yaz_log(YLOG_WARN|YLOG_ERRNO, "getnameinfo"); CLOSESOCKET(s); @@ -1212,19 +1226,17 @@ 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, - const char *record_fname) +int http_init(struct conf_server *server, const char *record_fname) { IOCHAN c; - int l; + int s = -1; int one = 1; - const char *pp; FILE *record_file = 0; - struct addrinfo hints, *ai = 0; + struct addrinfo hints, *af = 0, *ai; int error; int ipv6_only = -1; - yaz_log(YLOG_LOG, "HTTP listener %s", addr); + yaz_log(YLOG_LOG, "HTTP listener %s:%s", server->host, server->port); hints.ai_flags = 0; hints.ai_family = AF_UNSPEC; @@ -1235,70 +1247,76 @@ int http_init(const char *addr, struct conf_server *server, hints.ai_canonname = NULL; hints.ai_next = NULL; - pp = strchr(addr, ':'); - if (pp) + if (!strcmp(server->host, "@")) { - WRBUF w = wrbuf_alloc(); - wrbuf_write(w, addr, pp - addr); - if (!strcmp(wrbuf_cstr(w), "@")) - { /* IPV4 + IPV6 .. same as YAZ */ - ipv6_only = 0; - hints.ai_flags = AI_PASSIVE; - hints.ai_family = AF_INET6; - error = getaddrinfo(0, pp + 1, &hints, &ai); - } - else - error = getaddrinfo(wrbuf_cstr(w), pp + 1, &hints, &ai); - wrbuf_destroy(w); - } - else - { - /* default for no host given is IPV4 */ + ipv6_only = 0; hints.ai_flags = AI_PASSIVE; - hints.ai_family = AF_INET; - error = getaddrinfo(0, addr, &hints, &ai); + error = getaddrinfo(0, server->port, &hints, &af); } + else + error = getaddrinfo(server->host, server->port, &hints, &af); + if (error) { - yaz_log(YLOG_FATAL, "Failed to resolve %s: %s", addr, + yaz_log(YLOG_FATAL, "Failed to resolve %s: %s", server->host, gai_strerror(error)); return 1; } - l = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (l < 0) + for (ai = af; ai; ai = ai->ai_next) + { + if (ai->ai_family == AF_INET6) + { + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s != -1) + break; + } + } + if (s == -1) + { + for (ai = af; ai; ai = ai->ai_next) + { + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s != -1) + break; + } + } + if (s == -1) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "socket"); - freeaddrinfo(ai); + freeaddrinfo(af); return 1; } - if (ipv6_only >= 0 && - setsockopt(l, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6_only, sizeof(ipv6_only))) + if (ipv6_only >= 0 && ai->ai_family == AF_INET6 && + setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6_only, sizeof(ipv6_only))) { - yaz_log(YLOG_FATAL|YLOG_ERRNO, "setsockopt IPV6_V6ONLY %s %d", addr, - ipv6_only); - freeaddrinfo(ai); - CLOSESOCKET(l); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "setsockopt IPV6_V6ONLY %s:%s %d", + server->host, server->port, ipv6_only); + freeaddrinfo(af); + CLOSESOCKET(s); return 1; } - if (setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { - yaz_log(YLOG_FATAL|YLOG_ERRNO, "setsockopt SO_REUSEADDR %s", addr); - freeaddrinfo(ai); - CLOSESOCKET(l); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "setsockopt SO_REUSEADDR %s:%s", + server->host, server->port); + freeaddrinfo(af); + CLOSESOCKET(s); return 1; } - if (bind(l, ai->ai_addr, ai->ai_addrlen) < 0) + if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { - yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind %s", addr); - freeaddrinfo(ai); - CLOSESOCKET(l); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind %s:%s", + server->host, server->port); + freeaddrinfo(af); + CLOSESOCKET(s); return 1; } - freeaddrinfo(ai); - if (listen(l, SOMAXCONN) < 0) + freeaddrinfo(af); + if (listen(s, SOMAXCONN) < 0) { - yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen %s", addr); - CLOSESOCKET(l); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen %s:%s", + server->host, server->port); + CLOSESOCKET(s); return 1; } @@ -1308,16 +1326,16 @@ int http_init(const char *addr, struct conf_server *server, if (!record_file) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "fopen %s", record_fname); - CLOSESOCKET(l); + CLOSESOCKET(s); return 1; } } server->http_server = http_server_create(); server->http_server->record_file = record_file; - server->http_server->listener_socket = l; + server->http_server->listener_socket = s; - c = iochan_create(l, http_accept, EVENT_INPUT | EVENT_EXCEPT, "http_server"); + c = iochan_create(s, http_accept, EVENT_INPUT | EVENT_EXCEPT, "http_server"); iochan_setdata(c, server); iochan_add(server->iochan_man, c);