Coverage Report

Created: 2024-06-24 06:12

/src/muduo/muduo/net/SocketsOps.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2010, Shuo Chen.  All rights reserved.
2
// http://code.google.com/p/muduo/
3
//
4
// Use of this source code is governed by a BSD-style license
5
// that can be found in the License file.
6
7
// Author: Shuo Chen (chenshuo at chenshuo dot com)
8
9
#include "muduo/net/SocketsOps.h"
10
11
#include "muduo/base/Logging.h"
12
#include "muduo/base/Types.h"
13
#include "muduo/net/Endian.h"
14
15
#include <errno.h>
16
#include <fcntl.h>
17
#include <stdio.h>  // snprintf
18
#include <sys/socket.h>
19
#include <sys/uio.h>  // readv
20
#include <unistd.h>
21
22
using namespace muduo;
23
using namespace muduo::net;
24
25
namespace
26
{
27
28
typedef struct sockaddr SA;
29
30
31
#if VALGRIND || defined (NO_ACCEPT4)
32
void setNonBlockAndCloseOnExec(int sockfd)
33
{
34
  // non-block
35
  int flags = ::fcntl(sockfd, F_GETFL, 0);
36
  flags |= O_NONBLOCK;
37
  int ret = ::fcntl(sockfd, F_SETFL, flags);
38
  // FIXME check
39
40
  // close-on-exec
41
  flags = ::fcntl(sockfd, F_GETFD, 0);
42
  flags |= FD_CLOEXEC;
43
  ret = ::fcntl(sockfd, F_SETFD, flags);
44
  // FIXME check
45
46
  (void)ret;
47
}
48
#endif
49
50
}  // namespace
51
52
const struct sockaddr* sockets::sockaddr_cast(const struct sockaddr_in6* addr)
53
0
{
54
0
  return static_cast<const struct sockaddr*>(implicit_cast<const void*>(addr));
55
0
}
56
57
struct sockaddr* sockets::sockaddr_cast(struct sockaddr_in6* addr)
58
0
{
59
0
  return static_cast<struct sockaddr*>(implicit_cast<void*>(addr));
60
0
}
61
62
const struct sockaddr* sockets::sockaddr_cast(const struct sockaddr_in* addr)
63
0
{
64
0
  return static_cast<const struct sockaddr*>(implicit_cast<const void*>(addr));
65
0
}
66
67
const struct sockaddr_in* sockets::sockaddr_in_cast(const struct sockaddr* addr)
68
0
{
69
0
  return static_cast<const struct sockaddr_in*>(implicit_cast<const void*>(addr));
70
0
}
71
72
const struct sockaddr_in6* sockets::sockaddr_in6_cast(const struct sockaddr* addr)
73
0
{
74
0
  return static_cast<const struct sockaddr_in6*>(implicit_cast<const void*>(addr));
75
0
}
76
77
int sockets::createNonblockingOrDie(sa_family_t family)
78
0
{
79
#if VALGRIND
80
  int sockfd = ::socket(family, SOCK_STREAM, IPPROTO_TCP);
81
  if (sockfd < 0)
82
  {
83
    LOG_SYSFATAL << "sockets::createNonblockingOrDie";
84
  }
85
86
  setNonBlockAndCloseOnExec(sockfd);
87
#else
88
0
  int sockfd = ::socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
89
0
  if (sockfd < 0)
90
0
  {
91
0
    LOG_SYSFATAL << "sockets::createNonblockingOrDie";
92
0
  }
93
0
#endif
94
0
  return sockfd;
95
0
}
96
97
void sockets::bindOrDie(int sockfd, const struct sockaddr* addr)
98
0
{
99
0
  int ret = ::bind(sockfd, addr, static_cast<socklen_t>(sizeof(struct sockaddr_in6)));
100
0
  if (ret < 0)
101
0
  {
102
0
    LOG_SYSFATAL << "sockets::bindOrDie";
103
0
  }
104
0
}
105
106
void sockets::listenOrDie(int sockfd)
107
0
{
108
0
  int ret = ::listen(sockfd, SOMAXCONN);
109
0
  if (ret < 0)
110
0
  {
111
0
    LOG_SYSFATAL << "sockets::listenOrDie";
112
0
  }
113
0
}
114
115
int sockets::accept(int sockfd, struct sockaddr_in6* addr)
116
0
{
117
0
  socklen_t addrlen = static_cast<socklen_t>(sizeof *addr);
118
#if VALGRIND || defined (NO_ACCEPT4)
119
  int connfd = ::accept(sockfd, sockaddr_cast(addr), &addrlen);
120
  setNonBlockAndCloseOnExec(connfd);
121
#else
122
0
  int connfd = ::accept4(sockfd, sockaddr_cast(addr),
123
0
                         &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
124
0
#endif
125
0
  if (connfd < 0)
126
0
  {
127
0
    int savedErrno = errno;
128
0
    LOG_SYSERR << "Socket::accept";
129
0
    switch (savedErrno)
130
0
    {
131
0
      case EAGAIN:
132
0
      case ECONNABORTED:
133
0
      case EINTR:
134
0
      case EPROTO: // ???
135
0
      case EPERM:
136
0
      case EMFILE: // per-process lmit of open file desctiptor ???
137
        // expected errors
138
0
        errno = savedErrno;
139
0
        break;
140
0
      case EBADF:
141
0
      case EFAULT:
142
0
      case EINVAL:
143
0
      case ENFILE:
144
0
      case ENOBUFS:
145
0
      case ENOMEM:
146
0
      case ENOTSOCK:
147
0
      case EOPNOTSUPP:
148
        // unexpected errors
149
0
        LOG_FATAL << "unexpected error of ::accept " << savedErrno;
150
0
        break;
151
0
      default:
152
0
        LOG_FATAL << "unknown error of ::accept " << savedErrno;
153
0
        break;
154
0
    }
155
0
  }
156
0
  return connfd;
157
0
}
158
159
int sockets::connect(int sockfd, const struct sockaddr* addr)
160
0
{
161
0
  return ::connect(sockfd, addr, static_cast<socklen_t>(sizeof(struct sockaddr_in6)));
162
0
}
163
164
ssize_t sockets::read(int sockfd, void *buf, size_t count)
165
0
{
166
0
  return ::read(sockfd, buf, count);
167
0
}
168
169
ssize_t sockets::readv(int sockfd, const struct iovec *iov, int iovcnt)
170
0
{
171
0
  return ::readv(sockfd, iov, iovcnt);
172
0
}
173
174
ssize_t sockets::write(int sockfd, const void *buf, size_t count)
175
0
{
176
0
  return ::write(sockfd, buf, count);
177
0
}
178
179
void sockets::close(int sockfd)
180
0
{
181
0
  if (::close(sockfd) < 0)
182
0
  {
183
0
    LOG_SYSERR << "sockets::close";
184
0
  }
185
0
}
186
187
void sockets::shutdownWrite(int sockfd)
188
0
{
189
0
  if (::shutdown(sockfd, SHUT_WR) < 0)
190
0
  {
191
0
    LOG_SYSERR << "sockets::shutdownWrite";
192
0
  }
193
0
}
194
195
void sockets::toIpPort(char* buf, size_t size,
196
                       const struct sockaddr* addr)
197
0
{
198
0
  if (addr->sa_family == AF_INET6)
199
0
  {
200
0
    buf[0] = '[';
201
0
    toIp(buf+1, size-1, addr);
202
0
    size_t end = ::strlen(buf);
203
0
    const struct sockaddr_in6* addr6 = sockaddr_in6_cast(addr);
204
0
    uint16_t port = sockets::networkToHost16(addr6->sin6_port);
205
0
    assert(size > end);
206
0
    snprintf(buf+end, size-end, "]:%u", port);
207
0
    return;
208
0
  }
209
0
  toIp(buf, size, addr);
210
0
  size_t end = ::strlen(buf);
211
0
  const struct sockaddr_in* addr4 = sockaddr_in_cast(addr);
212
0
  uint16_t port = sockets::networkToHost16(addr4->sin_port);
213
0
  assert(size > end);
214
0
  snprintf(buf+end, size-end, ":%u", port);
215
0
}
216
217
void sockets::toIp(char* buf, size_t size,
218
                   const struct sockaddr* addr)
219
0
{
220
0
  if (addr->sa_family == AF_INET)
221
0
  {
222
0
    assert(size >= INET_ADDRSTRLEN);
223
0
    const struct sockaddr_in* addr4 = sockaddr_in_cast(addr);
224
0
    ::inet_ntop(AF_INET, &addr4->sin_addr, buf, static_cast<socklen_t>(size));
225
0
  }
226
0
  else if (addr->sa_family == AF_INET6)
227
0
  {
228
0
    assert(size >= INET6_ADDRSTRLEN);
229
0
    const struct sockaddr_in6* addr6 = sockaddr_in6_cast(addr);
230
0
    ::inet_ntop(AF_INET6, &addr6->sin6_addr, buf, static_cast<socklen_t>(size));
231
0
  }
232
0
}
233
234
void sockets::fromIpPort(const char* ip, uint16_t port,
235
                         struct sockaddr_in* addr)
236
0
{
237
0
  addr->sin_family = AF_INET;
238
0
  addr->sin_port = hostToNetwork16(port);
239
0
  if (::inet_pton(AF_INET, ip, &addr->sin_addr) <= 0)
240
0
  {
241
0
    LOG_SYSERR << "sockets::fromIpPort";
242
0
  }
243
0
}
244
245
void sockets::fromIpPort(const char* ip, uint16_t port,
246
                         struct sockaddr_in6* addr)
247
0
{
248
0
  addr->sin6_family = AF_INET6;
249
0
  addr->sin6_port = hostToNetwork16(port);
250
0
  if (::inet_pton(AF_INET6, ip, &addr->sin6_addr) <= 0)
251
0
  {
252
0
    LOG_SYSERR << "sockets::fromIpPort";
253
0
  }
254
0
}
255
256
int sockets::getSocketError(int sockfd)
257
0
{
258
0
  int optval;
259
0
  socklen_t optlen = static_cast<socklen_t>(sizeof optval);
260
261
0
  if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0)
262
0
  {
263
0
    return errno;
264
0
  }
265
0
  else
266
0
  {
267
0
    return optval;
268
0
  }
269
0
}
270
271
struct sockaddr_in6 sockets::getLocalAddr(int sockfd)
272
0
{
273
0
  struct sockaddr_in6 localaddr;
274
0
  memZero(&localaddr, sizeof localaddr);
275
0
  socklen_t addrlen = static_cast<socklen_t>(sizeof localaddr);
276
0
  if (::getsockname(sockfd, sockaddr_cast(&localaddr), &addrlen) < 0)
277
0
  {
278
0
    LOG_SYSERR << "sockets::getLocalAddr";
279
0
  }
280
0
  return localaddr;
281
0
}
282
283
struct sockaddr_in6 sockets::getPeerAddr(int sockfd)
284
0
{
285
0
  struct sockaddr_in6 peeraddr;
286
0
  memZero(&peeraddr, sizeof peeraddr);
287
0
  socklen_t addrlen = static_cast<socklen_t>(sizeof peeraddr);
288
0
  if (::getpeername(sockfd, sockaddr_cast(&peeraddr), &addrlen) < 0)
289
0
  {
290
0
    LOG_SYSERR << "sockets::getPeerAddr";
291
0
  }
292
0
  return peeraddr;
293
0
}
294
295
bool sockets::isSelfConnect(int sockfd)
296
0
{
297
0
  struct sockaddr_in6 localaddr = getLocalAddr(sockfd);
298
0
  struct sockaddr_in6 peeraddr = getPeerAddr(sockfd);
299
0
  if (localaddr.sin6_family == AF_INET)
300
0
  {
301
0
    const struct sockaddr_in* laddr4 = reinterpret_cast<struct sockaddr_in*>(&localaddr);
302
0
    const struct sockaddr_in* raddr4 = reinterpret_cast<struct sockaddr_in*>(&peeraddr);
303
0
    return laddr4->sin_port == raddr4->sin_port
304
0
        && laddr4->sin_addr.s_addr == raddr4->sin_addr.s_addr;
305
0
  }
306
0
  else if (localaddr.sin6_family == AF_INET6)
307
0
  {
308
0
    return localaddr.sin6_port == peeraddr.sin6_port
309
0
        && memcmp(&localaddr.sin6_addr, &peeraddr.sin6_addr, sizeof localaddr.sin6_addr) == 0;
310
0
  }
311
0
  else
312
0
  {
313
0
    return false;
314
0
  }
315
0
}
316