| 371 | } |
| 372 | |
| 373 | int Socket::initialize() { |
| 374 | addrinfo hints{}; |
| 375 | memset(&hints, 0, sizeof hints); // make sure the struct is empty |
| 376 | hints.ai_family = AF_UNSPEC; |
| 377 | hints.ai_socktype = SOCK_STREAM; |
| 378 | hints.ai_flags = AI_CANONNAME; |
| 379 | if (listeners_ > 0 && !is_loopback_only_) |
| 380 | hints.ai_flags = AI_PASSIVE; |
| 381 | hints.ai_protocol = 0; /* any protocol */ |
| 382 | |
| 383 | const char* const gai_node = [this]() -> const char* { |
| 384 | if (is_loopback_only_) return "localhost"; |
| 385 | if (!is_loopback_only_ && listeners_ > 0) return nullptr; // all non-localhost server sockets listen on wildcard address |
| 386 | if (!requested_hostname_.empty()) return requested_hostname_.c_str(); |
| 387 | return nullptr; |
| 388 | }(); |
| 389 | const auto gai_service = std::to_string(port_); |
| 390 | addrinfo* getaddrinfo_result = nullptr; |
| 391 | const int errcode = getaddrinfo(gai_node, gai_service.c_str(), &hints, &getaddrinfo_result); |
| 392 | const std::unique_ptr<addrinfo, util::addrinfo_deleter> addr_info{ getaddrinfo_result }; |
| 393 | getaddrinfo_result = nullptr; |
| 394 | if (errcode != 0) { |
| 395 | logger_->log_error("getaddrinfo: %s", get_last_getaddrinfo_err_str(errcode)); |
| 396 | return -1; |
| 397 | } |
| 398 | socket_file_descriptor_ = INVALID_SOCKET; |
| 399 | |
| 400 | // AI_CANONNAME always sets ai_canonname of the first addrinfo structure |
| 401 | canonical_hostname_ = !IsNullOrEmpty(addr_info->ai_canonname) ? addr_info->ai_canonname : requested_hostname_; |
| 402 | |
| 403 | const auto conn_result = port_ > 0 ? createConnection(addr_info.get()) : -1; |
| 404 | if (conn_result == 0 && nonBlocking_) { |
| 405 | // Put the socket in non-blocking mode: |
| 406 | const auto err = set_non_blocking(socket_file_descriptor_); |
| 407 | if (err) logger_->log_info("Couldn't make socket non-blocking: %s", err.message()); |
| 408 | else logger_->log_debug("Successfully applied O_NONBLOCK to fd"); |
| 409 | } |
| 410 | return conn_result; |
| 411 | } |
| 412 | |
| 413 | int16_t Socket::select_descriptor(const uint16_t msec) { |
| 414 | if (listeners_ == 0) { |
nothing calls this directly
no test coverage detected