diff --git a/sources/network/unix/tcp_socket.cpp b/sources/network/unix/tcp_socket.cpp index 0a9d0b8..af665dd 100644 --- a/sources/network/unix/tcp_socket.cpp +++ b/sources/network/unix/tcp_socket.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include namespace tacopie { @@ -106,28 +107,45 @@ tcp_socket::send(const std::vector& data, std::size_t size_to_write) { void tcp_socket::connect(const std::string& host, std::uint32_t port) { + //! Reset host and port + m_host = host; + m_port = port; + create_socket_if_necessary(); check_or_set_type(type::CLIENT); + struct sockaddr_un server_addr_un; + struct sockaddr_in server_addr_in; + + //! Handle case of unix sockets if port is 0 + bool is_unix_socket = m_port == 0; + if (is_unix_socket) { + std::memset(&server_addr_un, 0, sizeof(server_addr_un)); + server_addr_un.sun_family = AF_UNIX; + strncpy(server_addr_un.sun_path, host.c_str(), sizeof(server_addr_un.sun_path) - 1); + } + else { + struct addrinfo* result = nullptr; + struct addrinfo hints; - struct addrinfo* result = nullptr; - struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_INET; - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_INET; + if (getaddrinfo(host.c_str(), nullptr, &hints, &result) != 0) { __TACOPIE_THROW(error, "getaddrinfo() failure"); } - if (getaddrinfo(host.c_str(), nullptr, &hints, &result) != 0) { __TACOPIE_THROW(error, "getaddrinfo() failure"); } + std::memset(&server_addr_in, 0, sizeof(server_addr_in)); + server_addr_in.sin_addr = ((struct sockaddr_in*) (result->ai_addr))->sin_addr; + server_addr_in.sin_port = htons(port); + server_addr_in.sin_family = AF_INET; - struct sockaddr_in server_addr; - std::memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_addr = ((struct sockaddr_in*) (result->ai_addr))->sin_addr; - server_addr.sin_port = htons(port); - server_addr.sin_family = AF_INET; + freeaddrinfo(result); + } - freeaddrinfo(result); + socklen_t addr_len = is_unix_socket ? sizeof(server_addr_un) : sizeof(server_addr_in); + const struct sockaddr* server_addr = is_unix_socket ? (const struct sockaddr*) &server_addr_un : (const struct sockaddr*) &server_addr_in; - if (::connect(m_fd, (const struct sockaddr*) &server_addr, sizeof(server_addr)) == -1) { __TACOPIE_THROW(error, "connect() failure"); } + if (::connect(m_fd, server_addr, addr_len) == -1) { __TACOPIE_THROW(error, "connect() failure"); } } //! @@ -136,24 +154,42 @@ tcp_socket::connect(const std::string& host, std::uint32_t port) { void tcp_socket::bind(const std::string& host, std::uint32_t port) { + //! Reset host and port + m_host = host; + m_port = port; + create_socket_if_necessary(); check_or_set_type(type::SERVER); - struct addrinfo* result = nullptr; + struct sockaddr_un server_addr_un; + struct sockaddr_in server_addr_in; - if (getaddrinfo(host.c_str(), nullptr, nullptr, &result) != 0) { - __TACOPIE_THROW(error, "getaddrinfo() failure"); + //! Handle case of unix sockets if port is 0 + bool is_unix_socket = m_port == 0; + if (is_unix_socket) { + std::memset(&server_addr_un, 0, sizeof(server_addr_un)); + server_addr_un.sun_family = AF_UNIX; + strncpy(server_addr_un.sun_path, host.c_str(), sizeof(server_addr_un.sun_path) - 1); } + else { + struct addrinfo* result = nullptr; + + if (getaddrinfo(host.c_str(), nullptr, nullptr, &result) != 0) { + __TACOPIE_THROW(error, "getaddrinfo() failure"); + } - struct sockaddr_in server_addr; - std::memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_addr = ((struct sockaddr_in*) (result->ai_addr))->sin_addr; - server_addr.sin_port = htons(port); - server_addr.sin_family = AF_INET; + std::memset(&server_addr_in, 0, sizeof(server_addr_in)); + server_addr_in.sin_addr = ((struct sockaddr_in*) (result->ai_addr))->sin_addr; + server_addr_in.sin_port = htons(port); + server_addr_in.sin_family = AF_INET; + + freeaddrinfo(result); + } - freeaddrinfo(result); + socklen_t addr_len = is_unix_socket ? sizeof(server_addr_un) : sizeof(server_addr_in); + const struct sockaddr* server_addr = is_unix_socket ? (const struct sockaddr*) &server_addr_un : (const struct sockaddr*) &server_addr_in; - if (::bind(m_fd, (const struct sockaddr*) &server_addr, sizeof(server_addr)) == -1) { __TACOPIE_THROW(error, "bind() failure"); } + if (::bind(m_fd, server_addr, addr_len) == -1) { __TACOPIE_THROW(error, "bind() failure"); } } void @@ -204,7 +240,8 @@ tcp_socket::create_socket_if_necessary(void) { if (m_fd != __TACOPIE_INVALID_FD) { return; } //! new TCP socket - m_fd = socket(AF_INET, SOCK_STREAM, 0); + //! handle case of unix sockets by checking whether the port is 0 or not + m_fd = socket(m_port == 0 ? AF_UNIX : AF_INET, SOCK_STREAM, 0); m_type = type::UNKNOWN; if (m_fd == __TACOPIE_INVALID_FD) { __TACOPIE_THROW(error, "tcp_socket::create_socket_if_necessary: socket() failure"); }