mem-cache: Add more compression stats
[gem5.git] / src / base / socket.cc
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 * Authors: Nathan Binkert
32 * Bobby R. Bruce
33 */
34
35 #include "base/socket.hh"
36
37 #include <netinet/in.h>
38 #include <netinet/tcp.h>
39 #include <sys/socket.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42
43 #include <cerrno>
44
45 #include "base/logging.hh"
46 #include "base/types.hh"
47 #include "sim/byteswap.hh"
48
49 using namespace std;
50
51 bool ListenSocket::listeningDisabled = false;
52 bool ListenSocket::anyListening = false;
53
54 bool ListenSocket::bindToLoopback = false;
55
56 void
57 ListenSocket::cleanup()
58 {
59 listeningDisabled = false;
60 anyListening = false;
61 bindToLoopback = false;
62 }
63
64 void
65 ListenSocket::disableAll()
66 {
67 if (anyListening)
68 panic("Too late to disable all listeners, already have a listener");
69 listeningDisabled = true;
70 }
71
72 bool
73 ListenSocket::allDisabled()
74 {
75 return listeningDisabled;
76 }
77
78 void
79 ListenSocket::loopbackOnly()
80 {
81 if (anyListening)
82 panic("Too late to bind to loopback, already have a listener");
83 bindToLoopback = true;
84 }
85
86 ////////////////////////////////////////////////////////////////////////
87 //
88 //
89
90 ListenSocket::ListenSocket()
91 : listening(false), fd(-1)
92 {}
93
94 ListenSocket::~ListenSocket()
95 {
96 if (fd != -1)
97 close(fd);
98 }
99
100 // Create a socket and configure it for listening
101 bool
102 ListenSocket::listen(int port, bool reuse)
103 {
104 if (listening)
105 panic("Socket already listening!");
106
107 fd = ::socket(PF_INET, SOCK_STREAM, 0);
108 if (fd < 0)
109 panic("Can't create socket:%s !", strerror(errno));
110
111 if (reuse) {
112 int i = 1;
113 if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i,
114 sizeof(i)) < 0)
115 panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!");
116 }
117
118 struct sockaddr_in sockaddr;
119 sockaddr.sin_family = PF_INET;
120 sockaddr.sin_addr.s_addr =
121 htobe<in_addr_t>(bindToLoopback ? INADDR_LOOPBACK : INADDR_ANY);
122 sockaddr.sin_port = htons(port);
123 // finally clear sin_zero
124 memset(&sockaddr.sin_zero, 0, sizeof(sockaddr.sin_zero));
125 int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr));
126 if (ret != 0) {
127 if (ret == -1 && errno != EADDRINUSE)
128 panic("ListenSocket(listen): bind() failed!");
129 return false;
130 }
131
132 if (::listen(fd, 1) == -1) {
133 if (errno != EADDRINUSE)
134 panic("ListenSocket(listen): listen() failed!");
135
136 return false;
137 }
138
139 listening = true;
140 anyListening = true;
141 return true;
142 }
143
144
145 // Open a connection. Accept will block, so if you don't want it to,
146 // make sure a connection is ready before you call accept.
147 int
148 ListenSocket::accept(bool nodelay)
149 {
150 struct sockaddr_in sockaddr;
151 socklen_t slen = sizeof (sockaddr);
152 int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen);
153 if (sfd != -1 && nodelay) {
154 int i = 1;
155 if (::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i,
156 sizeof(i)) < 0)
157 warn("ListenSocket(accept): setsockopt() TCP_NODELAY failed!");
158 }
159
160 return sfd;
161 }