Listen both IPv4 and IPv6 sockets.
This commit is contained in:
parent
6d35f7e470
commit
f11c2a94b4
|
@ -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<EventHandler*>::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<EventHandler*> 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
|
||||
|
|
|
@ -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<socklen_t>(sizeof(val))) == -1) {
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif // IPV6_V6ONLY
|
||||
|
||||
if(bind(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue