1efbfdb0cSShuo Chen#include "Socket.h" 2efbfdb0cSShuo Chen#include "InetAddress.h" 3efbfdb0cSShuo Chen 4efbfdb0cSShuo Chen#include <assert.h> 5efbfdb0cSShuo Chen#include <unistd.h> 6efbfdb0cSShuo Chen#include <netinet/in.h> 7a52ee0fdSShuo Chen#include <netinet/tcp.h> 8efbfdb0cSShuo Chen#include <sys/socket.h> 9efbfdb0cSShuo Chen 10efbfdb0cSShuo ChenSocket::Socket(int sockfd) 11efbfdb0cSShuo Chen : sockfd_(sockfd) 12efbfdb0cSShuo Chen{ 13efbfdb0cSShuo Chen assert(sockfd_ >= 0); 14efbfdb0cSShuo Chen} 15efbfdb0cSShuo Chen 16efbfdb0cSShuo ChenSocket::~Socket() 17efbfdb0cSShuo Chen{ 18efbfdb0cSShuo Chen if (sockfd_ >= 0) 19efbfdb0cSShuo Chen { 20efbfdb0cSShuo Chen int ret = ::close(sockfd_); 21efbfdb0cSShuo Chen assert(ret == 0); (void)ret; 22efbfdb0cSShuo Chen } 23efbfdb0cSShuo Chen} 24efbfdb0cSShuo Chen 25efbfdb0cSShuo Chenvoid Socket::bindOrDie(const InetAddress& addr) 26efbfdb0cSShuo Chen{ 2724ca08a8SShuo Chen int ret = ::bind(sockfd_, addr.get_sockaddr(), addr.length()); 28efbfdb0cSShuo Chen if (ret) 29efbfdb0cSShuo Chen { 30efbfdb0cSShuo Chen perror("Socket::bindOrDie"); 31efbfdb0cSShuo Chen abort(); 32efbfdb0cSShuo Chen } 33efbfdb0cSShuo Chen} 34efbfdb0cSShuo Chen 35efbfdb0cSShuo Chenvoid Socket::listenOrDie() 36efbfdb0cSShuo Chen{ 37efbfdb0cSShuo Chen int ret = ::listen(sockfd_, SOMAXCONN); 38efbfdb0cSShuo Chen if (ret) 39efbfdb0cSShuo Chen { 40efbfdb0cSShuo Chen perror("Socket::listen"); 41efbfdb0cSShuo Chen abort(); 42efbfdb0cSShuo Chen } 43efbfdb0cSShuo Chen} 44efbfdb0cSShuo Chen 458f04b50cSShuo Chenint Socket::connect(const InetAddress& addr) 468f04b50cSShuo Chen{ 4724ca08a8SShuo Chen return ::connect(sockfd_, addr.get_sockaddr(), addr.length()); 488f04b50cSShuo Chen} 498f04b50cSShuo Chen 50a52ee0fdSShuo Chenvoid Socket::shutdownWrite() 51a52ee0fdSShuo Chen{ 52a52ee0fdSShuo Chen if (::shutdown(sockfd_, SHUT_WR) < 0) 53a52ee0fdSShuo Chen { 54a52ee0fdSShuo Chen perror("Socket::shutdownWrite"); 55a52ee0fdSShuo Chen } 56a52ee0fdSShuo Chen} 57a52ee0fdSShuo Chen 588f04b50cSShuo Chenvoid Socket::setReuseAddr(bool on) 598f04b50cSShuo Chen{ 608f04b50cSShuo Chen int optval = on ? 1 : 0; 61a52ee0fdSShuo Chen if (::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, 62a52ee0fdSShuo Chen &optval, sizeof optval) < 0) 63a52ee0fdSShuo Chen { 64a52ee0fdSShuo Chen perror("Socket::setReuseAddr"); 65a52ee0fdSShuo Chen } 66a52ee0fdSShuo Chen} 67a52ee0fdSShuo Chen 68a52ee0fdSShuo Chenvoid Socket::setTcpNoDelay(bool on) 69a52ee0fdSShuo Chen{ 70a52ee0fdSShuo Chen int optval = on ? 1 : 0; 71a52ee0fdSShuo Chen if (::setsockopt(sockfd_, IPPROTO_TCP, TCP_NODELAY, 72a52ee0fdSShuo Chen &optval, static_cast<socklen_t>(sizeof optval)) < 0) 73a52ee0fdSShuo Chen { 74a52ee0fdSShuo Chen perror("Socket::setTcpNoDelay"); 75a52ee0fdSShuo Chen } 768f04b50cSShuo Chen} 778f04b50cSShuo Chen 78f41285cfSShuo ChenInetAddress Socket::getLocalAddr() const 79f41285cfSShuo Chen{ 80eef48d84SShuo Chen struct sockaddr_storage localaddr; 8124ca08a8SShuo Chen socklen_t addrlen = sizeof localaddr; 82eef48d84SShuo Chen struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&localaddr); 83eef48d84SShuo Chen if (::getsockname(sockfd_, addr, &addrlen) < 0) 84f41285cfSShuo Chen { 85f41285cfSShuo Chen perror("Socket::getLocalAddr"); 86f41285cfSShuo Chen } 87eef48d84SShuo Chen return InetAddress(*addr); 88f41285cfSShuo Chen} 89f41285cfSShuo Chen 90f41285cfSShuo ChenInetAddress Socket::getPeerAddr() const 91f41285cfSShuo Chen{ 92eef48d84SShuo Chen struct sockaddr_storage peeraddr; 9324ca08a8SShuo Chen socklen_t addrlen = sizeof peeraddr; 94eef48d84SShuo Chen struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&peeraddr); 95eef48d84SShuo Chen if (::getpeername(sockfd_, addr, &addrlen) < 0) 96f41285cfSShuo Chen { 97f41285cfSShuo Chen perror("Socket::getPeerAddr"); 98f41285cfSShuo Chen } 99eef48d84SShuo Chen return InetAddress(*addr); 100f41285cfSShuo Chen} 101f41285cfSShuo Chen 1028bdf4aafSShuo Chenint Socket::recv(void* buf, int len) 103efbfdb0cSShuo Chen{ 104e146b157SShuo Chen#ifdef TEMP_FAILURE_RETRY 1058bdf4aafSShuo Chen return TEMP_FAILURE_RETRY(::recv(sockfd_, buf, len, 0)); 106e146b157SShuo Chen#else 107e146b157SShuo Chen return ::recv(sockfd_, buf, len, 0); 108e146b157SShuo Chen#endif 109aafef3ccSShuo Chen} 110aafef3ccSShuo Chen 1118bdf4aafSShuo Chenint Socket::send(const void* buf, int len) 112aafef3ccSShuo Chen{ 113e146b157SShuo Chen#ifdef TEMP_FAILURE_RETRY 1148bdf4aafSShuo Chen return TEMP_FAILURE_RETRY(::send(sockfd_, buf, len, 0)); 115e146b157SShuo Chen#else 116e146b157SShuo Chen return ::send(sockfd_, buf, len, 0); 117e146b157SShuo Chen#endif 118aafef3ccSShuo Chen} 119aafef3ccSShuo Chen 12024ca08a8SShuo ChenSocket Socket::createTCP(sa_family_t family) 121aafef3ccSShuo Chen{ 12224ca08a8SShuo Chen int sockfd = ::socket(family, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); 123aafef3ccSShuo Chen assert(sockfd >= 0); 124aafef3ccSShuo Chen return Socket(sockfd); 125aafef3ccSShuo Chen} 126aafef3ccSShuo Chen 12724ca08a8SShuo ChenSocket Socket::createUDP(sa_family_t family) 128aafef3ccSShuo Chen{ 12924ca08a8SShuo Chen int sockfd = ::socket(family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); 130efbfdb0cSShuo Chen assert(sockfd >= 0); 131efbfdb0cSShuo Chen return Socket(sockfd); 132efbfdb0cSShuo Chen} 133efbfdb0cSShuo Chen 134