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