bool Socket::openTcp(const IPAddress& host, int port, int flags) { #ifndef NDEBUG setLoggingPrefix("Socket(tcp:%s:%d)", host.str().c_str(), port); #endif flags |= O_NONBLOCK | O_CLOEXEC; int typeMask = 0; #if defined(SOCK_NONBLOCK) if (flags & O_NONBLOCK) { flags &= ~O_NONBLOCK; typeMask |= SOCK_NONBLOCK; } #endif #if defined(SOCK_CLOEXEC) if (flags & O_CLOEXEC) { flags &= ~O_CLOEXEC; typeMask |= SOCK_CLOEXEC; } #endif fd_ = ::socket(host.family(), SOCK_STREAM | typeMask, IPPROTO_TCP); if (fd_ < 0) { TRACE("socket creation error: %s", strerror(errno)); return false; } if (flags) { if (fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL) | flags) < 0) { // error } } int rv = ::connect(fd_, (struct sockaddr*) host.data(), host.size()); if (rv == 0) { TRACE("connect: instant success (fd:%d)", fd_); state_ = Operational; return true; } else if (/*rv < 0 &&*/ errno == EINPROGRESS) { TRACE("connect: backgrounding (fd:%d)", fd_); state_ = Connecting; setMode(Write); return true; } else { TRACE("could not connect to %s:%d: %s", host.str().c_str(), port, strerror(errno)); ::close(fd_); fd_ = -1; return false; } }