diff --git a/examples/spdyd.cc b/examples/spdyd.cc index 8fce25ab..959ceb7c 100644 --- a/examples/spdyd.cc +++ b/examples/spdyd.cc @@ -118,6 +118,10 @@ private: bool mark_del_; }; +namespace { +void on_close(Sessions &sessions, EventHandler *hd); +} // namespace + class Sessions { public: Sessions(int max_events, SSL_CTX *ssl_ctx) @@ -126,6 +130,11 @@ public: {} ~Sessions() { + for(std::set::iterator i = handlers_.begin(), + eoi = handlers_.end(); i != eoi; ++i) { + on_close(*this, *i); + delete *i; + } SSL_CTX_free(ssl_ctx_); } void add_handler(EventHandler *handler) @@ -829,21 +838,37 @@ int reactor() return -1; } SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, 0); - int sfd = make_listen_socket(config.port); - if(sfd == -1) { - std::cerr << "Could not listen on port " << config.port << std::endl; - return -1; - } - make_non_block(sfd); const size_t MAX_EVENTS = 256; Sessions sessions(MAX_EVENTS, ssl_ctx); - ListenEventHandler *listen_hd = new ListenEventHandler(sfd); - if(sessions.add_poll(listen_hd) == -1) { - std::cerr << "Adding listening socket to poll failed." << std::endl; + + int families[] = { AF_INET, AF_INET6 }; + bool bind_ok = false; + for(int i = 0; i < 2; ++i) { + const char* ipv = (families[i] == AF_INET ? "IPv4" : "IPv6"); + int sfd = make_listen_socket(config.port, families[i]); + if(sfd == -1) { + std::cerr << ipv << ": Could not listen on port " << config.port + << std::endl; + } + make_non_block(sfd); + + ListenEventHandler *listen_hd = new ListenEventHandler(sfd); + if(sessions.add_poll(listen_hd) == -1) { + std::cerr << ipv << ": Adding listening socket to poll failed." + << std::endl; + delete listen_hd; + } + sessions.add_handler(listen_hd); + if(config.verbose) { + std::cout << ipv << ": listen on port " << config.port << std::endl; + } + bind_ok = true; + } + if(!bind_ok) { return -1; } - sessions.add_handler(listen_hd); + std::vector del_list; while(1) { int n = sessions.poll(-1); @@ -880,7 +905,6 @@ int reactor() del_list.clear(); } } - on_close(sessions, listen_hd); return 0; } } // namespace diff --git a/examples/spdylay_ssl.cc b/examples/spdylay_ssl.cc index 3e1ddc40..37c04d89 100644 --- a/examples/spdylay_ssl.cc +++ b/examples/spdylay_ssl.cc @@ -159,7 +159,7 @@ int connect_to(const std::string& host, uint16_t port) return fd; } -int make_listen_socket(uint16_t port) +int make_listen_socket(uint16_t port, int family) { addrinfo hints; int fd = -1; @@ -167,7 +167,7 @@ int make_listen_socket(uint16_t port) char service[10]; snprintf(service, sizeof(service), "%u", port); memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; #ifdef AI_ADDRCONFIG @@ -190,6 +190,16 @@ int make_listen_socket(uint16_t port) close(fd); continue; } +#ifdef IPV6_V6ONLY + if(family == AF_INET6) { + if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, + static_cast(sizeof(val))) == -1) { + close(fd); + continue; + } + } +#endif // IPV6_V6ONLY + if(bind(fd, rp->ai_addr, rp->ai_addrlen) == 0) { break; } diff --git a/examples/spdylay_ssl.h b/examples/spdylay_ssl.h index 95ced793..2cde92d2 100644 --- a/examples/spdylay_ssl.h +++ b/examples/spdylay_ssl.h @@ -62,7 +62,7 @@ private: int connect_to(const std::string& host, uint16_t port); -int make_listen_socket(uint16_t port); +int make_listen_socket(uint16_t port, int family); int make_non_block(int fd);