1#include "Socket.h"
2#include "InetAddress.h"
3
4#include <assert.h>
5#include <unistd.h>
6#include <netinet/in.h>
7#include <netinet/tcp.h>
8#include <sys/socket.h>
9
10Socket::Socket(int sockfd)
11  : sockfd_(sockfd)
12{
13  assert(sockfd_ >= 0);
14}
15
16Socket::~Socket()
17{
18  if (sockfd_ >= 0)
19  {
20    int ret = ::close(sockfd_);
21    assert(ret == 0); (void)ret;
22  }
23}
24
25void Socket::bindOrDie(const InetAddress& addr)
26{
27  int ret = ::bind(sockfd_, addr.get_sockaddr(), addr.length());
28  if (ret)
29  {
30    perror("Socket::bindOrDie");
31    abort();
32  }
33}
34
35void Socket::listenOrDie()
36{
37  int ret = ::listen(sockfd_, SOMAXCONN);
38  if (ret)
39  {
40    perror("Socket::listen");
41    abort();
42  }
43}
44
45int Socket::connect(const InetAddress& addr)
46{
47  return ::connect(sockfd_, addr.get_sockaddr(), addr.length());
48}
49
50void Socket::shutdownWrite()
51{
52  if (::shutdown(sockfd_, SHUT_WR) < 0)
53  {
54    perror("Socket::shutdownWrite");
55  }
56}
57
58void Socket::setReuseAddr(bool on)
59{
60  int optval = on ? 1 : 0;
61  if (::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR,
62                   &optval, sizeof optval) < 0)
63  {
64    perror("Socket::setReuseAddr");
65  }
66}
67
68void Socket::setTcpNoDelay(bool on)
69{
70  int optval = on ? 1 : 0;
71  if (::setsockopt(sockfd_, IPPROTO_TCP, TCP_NODELAY,
72               &optval, static_cast<socklen_t>(sizeof optval)) < 0)
73  {
74    perror("Socket::setTcpNoDelay");
75  }
76}
77
78InetAddress Socket::getLocalAddr() const
79{
80  struct sockaddr_storage localaddr;
81  socklen_t addrlen = sizeof localaddr;
82  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&localaddr);
83  if (::getsockname(sockfd_, addr, &addrlen) < 0)
84  {
85    perror("Socket::getLocalAddr");
86  }
87  return InetAddress(*addr);
88}
89
90InetAddress Socket::getPeerAddr() const
91{
92  struct sockaddr_storage peeraddr;
93  socklen_t addrlen = sizeof peeraddr;
94  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&peeraddr);
95  if (::getpeername(sockfd_, addr, &addrlen) < 0)
96  {
97    perror("Socket::getPeerAddr");
98  }
99  return InetAddress(*addr);
100}
101
102int Socket::recv(void* buf, int len)
103{
104#ifdef TEMP_FAILURE_RETRY
105  return TEMP_FAILURE_RETRY(::recv(sockfd_, buf, len, 0));
106#else
107  return ::recv(sockfd_, buf, len, 0);
108#endif
109}
110
111int Socket::send(const void* buf, int len)
112{
113#ifdef TEMP_FAILURE_RETRY
114  return TEMP_FAILURE_RETRY(::send(sockfd_, buf, len, 0));
115#else
116  return ::send(sockfd_, buf, len, 0);
117#endif
118}
119
120Socket Socket::createTCP(sa_family_t family)
121{
122  int sockfd = ::socket(family, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
123  assert(sockfd >= 0);
124  return Socket(sockfd);
125}
126
127Socket Socket::createUDP(sa_family_t family)
128{
129  int sockfd = ::socket(family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
130  assert(sockfd >= 0);
131  return Socket(sockfd);
132}
133
134