/* * Start listening * @param endpoint the SocketAddress to listen on * @param backlog the backlog * @return true if it succeeded, false otherwise */ bool TCPAcceptingSocket::Listen(const SocketAddress &endpoint, int backlog) { struct sockaddr server_address; int reuse_flag = 1; if (m_sd != ola::io::INVALID_DESCRIPTOR) return false; if (!endpoint.ToSockAddr(&server_address, sizeof(server_address))) return false; int sd = socket(endpoint.Family(), SOCK_STREAM, 0); if (sd < 0) { OLA_WARN << "socket() failed: " << strerror(errno); return false; } int ok = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&reuse_flag), sizeof(reuse_flag)); if (ok < 0) { OLA_WARN << "can't set reuse for " << sd << ", " << strerror(errno); close(sd); return false; } if (bind(sd, &server_address, sizeof(server_address)) == -1) { OLA_WARN << "bind to " << endpoint << " failed, " << strerror(errno); close(sd); return false; } if (listen(sd, backlog)) { OLA_WARN << "listen on " << endpoint << " failed, " << strerror(errno); return false; } m_sd = sd; return true; }
/* * Start listening * @param endpoint the SocketAddress to listen on * @param backlog the backlog * @return true if it succeeded, false otherwise */ bool TCPAcceptingSocket::Listen(const SocketAddress &endpoint, int backlog) { struct sockaddr server_address; int reuse_flag = 1; if (m_handle != ola::io::INVALID_DESCRIPTOR) return false; if (!endpoint.ToSockAddr(&server_address, sizeof(server_address))) return false; int sd = socket(endpoint.Family(), SOCK_STREAM, 0); if (sd < 0) { OLA_WARN << "socket() failed: " << strerror(errno); return false; } SocketCloser closer(sd); #ifdef _WIN32 ola::io::DescriptorHandle temp_handle; temp_handle.m_handle.m_fd = sd; temp_handle.m_type = ola::io::SOCKET_DESCRIPTOR; if (!ola::io::ConnectedDescriptor::SetNonBlocking(temp_handle)) { #else if (!ola::io::ConnectedDescriptor::SetNonBlocking(sd)) { #endif OLA_WARN << "Failed to mark TCP accept socket as non-blocking"; return false; } int ok = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&reuse_flag), sizeof(reuse_flag)); if (ok < 0) { OLA_WARN << "can't set reuse for " << sd << ", " << strerror(errno); return false; } if (bind(sd, &server_address, sizeof(server_address)) == -1) { OLA_WARN << "bind to " << endpoint << " failed, " << strerror(errno); return false; } if (listen(sd, backlog)) { OLA_WARN << "listen on " << endpoint << " failed, " << strerror(errno); return false; } #ifdef _WIN32 m_handle.m_handle.m_fd = closer.Release(); m_handle.m_type = ola::io::SOCKET_DESCRIPTOR; #else m_handle = closer.Release(); #endif return true; } /* * Stop listening & close this socket * @return true if close succeeded, false otherwise */ bool TCPAcceptingSocket::Close() { bool ret = true; if (m_handle != ola::io::INVALID_DESCRIPTOR) { #ifdef _WIN32 if (closesocket(m_handle.m_handle.m_fd)) { #else if (close(m_handle)) { #endif OLA_WARN << "close() failed " << strerror(errno); ret = false; } } m_handle = ola::io::INVALID_DESCRIPTOR; return ret; } /* * Accept new connections * @return a new connected socket */ void TCPAcceptingSocket::PerformRead() { if (m_handle == ola::io::INVALID_DESCRIPTOR) return; while (1) { struct sockaddr_in cli_address; socklen_t length = sizeof(cli_address); #ifdef _WIN32 int sd = accept(m_handle.m_handle.m_fd, (struct sockaddr*) &cli_address, &length); #else int sd = accept(m_handle, (struct sockaddr*) &cli_address, &length); #endif if (sd < 0) { #ifdef _WIN32 if (WSAGetLastError() == WSAEWOULDBLOCK) { #else if (errno == EWOULDBLOCK) { #endif return; } OLA_WARN << "accept() failed, " << strerror(errno); return; } if (m_factory) { // The callback takes ownership of the new socket descriptor // coverity[RESOURCE_LEAK] m_factory->NewTCPSocket(sd); } else { OLA_WARN << "Accepted new TCP Connection but no factory registered"; #ifdef _WIN32 closesocket(sd); #else close(sd); #endif } } } /** * Get the local IPAddress and port for this socket */ GenericSocketAddress TCPAcceptingSocket::GetLocalAddress() const { #ifdef _WIN32 return ola::network::GetLocalAddress(m_handle.m_handle.m_fd); #else return ola::network::GetLocalAddress(m_handle); #endif } } // namespace network } // namespace ola