From: Adam Dickmeiss Date: Thu, 16 May 2013 14:00:27 +0000 (+0200) Subject: HTTP server: host=@ listens on IPV6 and IPV4 if possible X-Git-Tag: v1.6.31~22 X-Git-Url: http://lists.indexdata.com/cgi-bin?a=commitdiff_plain;h=1c320abd379ba19f7ab6ff3ed3a31fb72873990b;p=pazpar2-moved-to-github.git HTTP server: host=@ listens on IPV6 and IPV4 if possible Also, allow ports to be given as names (not just integers). Fix @-notation on systems that don't support IPV6 sockets. --- diff --git a/src/http.c b/src/http.c index 74fdf66..6748bbe 100644 --- a/src/http.c +++ b/src/http.c @@ -758,7 +758,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 +817,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); } @@ -1212,19 +1210,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 +1231,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); 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); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "setsockopt IPV6_V6ONLY %s:%s %d", + server->host, server->port, ipv6_only); freeaddrinfo(ai); - CLOSESOCKET(l); + 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); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "setsockopt SO_REUSEADDR %s:%s", + server->host, server->port); freeaddrinfo(ai); - CLOSESOCKET(l); + 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); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind %s:%s", + server->host, server->port); freeaddrinfo(ai); - CLOSESOCKET(l); + CLOSESOCKET(s); return 1; } freeaddrinfo(ai); - if (listen(l, SOMAXCONN) < 0) + 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 +1310,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); diff --git a/src/http.h b/src/http.h index dfe7446..1b1ae10 100644 --- a/src/http.h +++ b/src/http.h @@ -104,8 +104,7 @@ void http_mutex_init(struct conf_server *server); void http_server_destroy(http_server_t hs); void http_set_proxyaddr(const char *url, struct conf_server *ser); -int http_init(const char *addr, struct conf_server *ser, - const char *record_fname); +int http_init(struct conf_server *ser, const char *record_fname); void http_close_server(struct conf_server *ser); void http_addheader(struct http_response *r, const char *name, const char *value); diff --git a/src/pazpar2_config.c b/src/pazpar2_config.c index 22e047d..d6053ae 100644 --- a/src/pazpar2_config.c +++ b/src/pazpar2_config.c @@ -782,7 +782,7 @@ static struct conf_server *server_create(struct conf_config *config, struct conf_server *server = nmem_malloc(nmem, sizeof(struct conf_server)); xmlChar *server_id = xmlGetProp(node, (xmlChar *) "id"); - server->host = 0; + server->host = "@"; server->port = 0; server->proxy_host = 0; server->proxy_port = 0; @@ -811,10 +811,12 @@ static struct conf_server *server_create(struct conf_config *config, { xmlChar *port = xmlGetProp(n, (xmlChar *) "port"); xmlChar *host = xmlGetProp(n, (xmlChar *) "host"); + if (port) - server->port = atoi((const char *) port); + server->port = nmem_strdup(nmem, (const char *) port); if (host) server->host = nmem_strdup(nmem, (const char *) host); + xmlFree(port); xmlFree(host); } @@ -918,6 +920,11 @@ static struct conf_server *server_create(struct conf_config *config, return 0; } } + if (!server->port) + { + yaz_log(YLOG_FATAL, "No listening port given"); + return 0; + } if (server->service) { struct conf_service *s; @@ -1139,28 +1146,27 @@ int config_start_listeners(struct conf_config *conf, conf->iochan_man = iochan_man_create(conf->no_threads); for (ser = conf->servers; ser; ser = ser->next) { - WRBUF w = wrbuf_alloc(); + WRBUF w; int r; ser->iochan_man = conf->iochan_man; if (listener_override) { - wrbuf_puts(w, listener_override); - listener_override = 0; /* only first server is overriden */ - } - else - { - if (ser->host) - wrbuf_puts(w, ser->host); - if (ser->port) + const char *cp = strrchr(listener_override, ':'); + if (cp) { - if (wrbuf_len(w)) - wrbuf_puts(w, ":"); - wrbuf_printf(w, "%d", ser->port); + ser->host = nmem_strdupn(conf->nmem, listener_override, + cp - listener_override); + ser->port = nmem_strdup(conf->nmem, cp + 1); + } + else + { + ser->host = "@"; + ser->port = nmem_strdup(conf->nmem, listener_override); } + listener_override = 0; /* only first server is overriden */ } - r = http_init(wrbuf_cstr(w), ser, record_fname); - wrbuf_destroy(w); + r = http_init(ser, record_fname); if (r) return -1; diff --git a/src/pazpar2_config.h b/src/pazpar2_config.h index c20bae6..deacda7 100644 --- a/src/pazpar2_config.h +++ b/src/pazpar2_config.h @@ -143,7 +143,7 @@ int conf_service_sortkey_field_id(struct conf_service *service, const char * nam struct conf_server { char *host; - int port; + char *port; char *proxy_host; int proxy_port; char *myurl;