gem5  v22.1.0.0
socket.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 The Regents of the University of California
3  * All rights reserved
4  *
5  * Copyright (c) 2002-2005 The Regents of The University of Michigan
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met: redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer;
12  * redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution;
15  * neither the name of the copyright holders nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "base/socket.hh"
33 
34 #include <netinet/in.h>
35 #include <netinet/tcp.h>
36 #include <sys/socket.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 
40 #include <cerrno>
41 
42 #include "base/logging.hh"
43 #include "base/types.hh"
44 #include "sim/byteswap.hh"
45 
46 namespace gem5
47 {
48 
50 bool ListenSocket::anyListening = false;
51 
52 bool ListenSocket::bindToLoopback = false;
53 
54 void
56 {
57  listeningDisabled = false;
58  anyListening = false;
59  bindToLoopback = false;
60 }
61 
62 void
64 {
65  if (anyListening)
66  panic("Too late to disable all listeners, already have a listener");
67  listeningDisabled = true;
68 }
69 
70 bool
72 {
73  return listeningDisabled;
74 }
75 
76 void
78 {
79  if (anyListening)
80  panic("Too late to bind to loopback, already have a listener");
81  bindToLoopback = true;
82 }
83 
84 // Wrappers to stub out SOCK_CLOEXEC/accept4 availability
85 
86 int
87 ListenSocket::socketCloexec(int domain, int type, int protocol)
88 {
89 #ifdef SOCK_CLOEXEC
90  type |= SOCK_CLOEXEC;
91 #endif
92  return ::socket(domain, type, protocol);
93 }
94 
95 int
96 ListenSocket::acceptCloexec(int sockfd, struct sockaddr *addr,
97  socklen_t *addrlen)
98 {
99 #if defined(_GNU_SOURCE) && defined(SOCK_CLOEXEC)
100  return ::accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
101 #else
102  return ::accept(sockfd, addr, addrlen);
103 #endif
104 }
105 
107 //
108 //
109 
111  : listening(false), fd(-1)
112 {}
113 
115 {
116  if (fd != -1)
117  close(fd);
118 }
119 
120 // Create a socket and configure it for listening
121 bool
122 ListenSocket::listen(int port, bool reuse)
123 {
124  if (listening)
125  panic("Socket already listening!");
126 
127  // only create socket if not already created by a previous call
128  if (fd == -1) {
129  fd = socketCloexec(PF_INET, SOCK_STREAM, 0);
130  if (fd < 0)
131  panic("Can't create socket:%s !", strerror(errno));
132  }
133 
134  if (reuse) {
135  int i = 1;
136  if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i,
137  sizeof(i)) < 0)
138  panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!");
139  }
140 
141  struct sockaddr_in sockaddr;
142  sockaddr.sin_family = PF_INET;
143  sockaddr.sin_addr.s_addr =
144  htobe<in_addr_t>(bindToLoopback ? INADDR_LOOPBACK : INADDR_ANY);
145  sockaddr.sin_port = htons(port);
146  // finally clear sin_zero
147  std::memset(&sockaddr.sin_zero, 0, sizeof(sockaddr.sin_zero));
148  int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr));
149  if (ret != 0) {
150  if (ret == -1 && errno != EADDRINUSE)
151  panic("ListenSocket(listen): bind() failed!");
152  return false;
153  }
154 
155  if (::listen(fd, 1) == -1) {
156  if (errno != EADDRINUSE)
157  panic("ListenSocket(listen): listen() failed!");
158  // User may decide to retry with a different port later; however, the
159  // socket is already bound to a port and the next bind will surely
160  // fail. We'll close the socket and reset fd to -1 so our user can
161  // retry with a cleaner state.
162  close(fd);
163  fd = -1;
164  return false;
165  }
166 
167  listening = true;
168  anyListening = true;
169  return true;
170 }
171 
172 
173 // Open a connection. Accept will block, so if you don't want it to,
174 // make sure a connection is ready before you call accept.
175 int
176 ListenSocket::accept(bool nodelay)
177 {
178  struct sockaddr_in sockaddr;
179  socklen_t slen = sizeof (sockaddr);
180  int sfd = acceptCloexec(fd, (struct sockaddr *)&sockaddr, &slen);
181  if (sfd != -1 && nodelay) {
182  int i = 1;
183  if (::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i,
184  sizeof(i)) < 0)
185  warn("ListenSocket(accept): setsockopt() TCP_NODELAY failed!");
186  }
187 
188  return sfd;
189 }
190 
191 } // namespace gem5
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
static bool anyListening
Definition: socket.hh:46
virtual bool listen(int port, bool reuse=true)
Definition: socket.cc:122
static bool bindToLoopback
Definition: socket.hh:48
static bool listeningDisabled
The following variables are only used by socket unit tests: listeningDisabled, anyListening,...
Definition: socket.hh:45
static void loopbackOnly()
Definition: socket.cc:77
virtual int accept(bool nodelay=false)
Definition: socket.cc:176
static int socketCloexec(int domain, int type, int protocol)
Definition: socket.cc:87
static void cleanup()
Definition: socket.cc:55
static bool allDisabled()
Definition: socket.cc:71
virtual ~ListenSocket()
Definition: socket.cc:114
static void disableAll()
Definition: socket.cc:63
static int acceptCloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
Definition: socket.cc:96
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define warn(...)
Definition: logging.hh:246
Bitfield< 14, 12 > fd
Definition: types.hh:150
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 7, 4 > domain
Definition: misc_types.hh:430
Bitfield< 3 > addr
Definition: types.hh:84
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....

Generated on Wed Dec 21 2022 10:22:29 for gem5 by doxygen 1.9.1