X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuhttpd.git;a=blobdiff_plain;f=listen.c;h=2a54888a8b80b68681e2ca7bbb17d0297f44c2e0;hp=c4b6b2bb9faeab050ade6e257e04f463bfd3908e;hb=HEAD;hpb=8515c92b9302b258be10df5c5cee240dd4b137f6 diff --git a/listen.c b/listen.c index c4b6b2b..2a54888 100644 --- a/listen.c +++ b/listen.c @@ -1,20 +1,20 @@ /* * uhttpd - Tiny single-threaded httpd * - * Copyright (C) 2010-2012 Jo-Philipp Wich - * Copyright (C) 2012 Felix Fietkau + * Copyright (C) 2010-2013 Jo-Philipp Wich + * Copyright (C) 2013 Felix Fietkau * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include @@ -52,31 +52,47 @@ static void uh_block_listener(struct listener *l) l->blocked = true; } -void uh_unblock_listeners(void) +static void uh_poll_listeners(struct uloop_timeout *timeout) { struct listener *l; - if (!n_blocked && conf.max_requests && - n_clients >= conf.max_requests) + if ((!n_blocked && conf.max_connections) || + n_clients >= conf.max_connections) return; list_for_each_entry(l, &listeners, list) { if (!l->blocked) continue; + l->fd.cb(&l->fd, ULOOP_READ); + if (n_clients >= conf.max_connections) + break; + n_blocked--; l->blocked = false; uloop_fd_add(&l->fd, ULOOP_READ); } } +void uh_unblock_listeners(void) +{ + static struct uloop_timeout poll_timer = { + .cb = uh_poll_listeners + }; + + uloop_timeout_set(&poll_timer, 1); +} + static void listener_cb(struct uloop_fd *fd, unsigned int events) { struct listener *l = container_of(fd, struct listener, fd); - uh_accept_client(fd->fd); + while (1) { + if (!uh_accept_client(fd->fd, l->tls)) + break; + } - if (conf.max_requests && n_clients >= conf.max_requests) + if (conf.max_connections && n_clients >= conf.max_connections) uh_block_listener(l); } @@ -91,15 +107,17 @@ void uh_setup_listeners(void) /* TCP keep-alive */ if (conf.tcp_keepalive > 0) { #ifdef linux - int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt; + int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt, tcp_fstopn; tcp_ka_idl = 1; tcp_ka_cnt = 3; tcp_ka_int = conf.tcp_keepalive; + tcp_fstopn = 5; setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)); setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)); setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)); + setsockopt(sock, SOL_TCP, TCP_FASTOPEN, &tcp_fstopn, sizeof(tcp_fstopn)); #endif setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)); @@ -171,6 +189,7 @@ int uh_socket_bind(const char *host, const char *port, bool tls) l->fd.fd = sock; l->tls = tls; + l->addr = *(struct sockaddr_in6 *)p->ai_addr; list_add_tail(&l->list, &listeners); bound++; @@ -185,3 +204,21 @@ error: return bound; } + +int uh_first_tls_port(int family) +{ + struct listener *l; + int tls_port = -1; + + list_for_each_entry(l, &listeners, list) { + if (!l->tls || l->addr.sin6_family != family) + continue; + + if (tls_port != -1 && ntohs(l->addr.sin6_port) != 443) + continue; + + tls_port = ntohs(l->addr.sin6_port); + } + + return tls_port; +}