base: Abstract the AF_INET-ness out of ListenSocket.

Put them into a subclass called ListenSocketInet.

Change-Id: I035621463a7f799c1d36a500ed933dc056238e5e
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/69163
Maintainer: Bobby Bruce <bbruce@ucdavis.edu>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jui-min Lee <fcrh@google.com>
Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu>
This commit is contained in:
Gabe Black
2023-03-18 09:13:56 -07:00
parent ea623eb6e5
commit c00e3b2570
3 changed files with 75 additions and 47 deletions

View File

@@ -173,11 +173,7 @@ ListenSocket::acceptCloexec(int sockfd, struct sockaddr *addr,
//
//
ListenSocket::ListenSocket(const std::string &_name, int port)
: Named(_name), listening(false), fd(-1), _port(port)
{}
ListenSocket::ListenSocket() : ListenSocket("<unnammed>", -1) {}
ListenSocket::ListenSocket(const std::string &_name) : Named(_name) {}
ListenSocket::~ListenSocket()
{
@@ -185,9 +181,41 @@ ListenSocket::~ListenSocket()
close(fd);
}
// Open a connection. Accept will block, so if you don't want it to,
// make sure a connection is ready before you call accept.
int
ListenSocket::accept()
{
struct sockaddr_in sockaddr;
socklen_t slen = sizeof (sockaddr);
int sfd = acceptCloexec(fd, (struct sockaddr *)&sockaddr, &slen);
if (sfd == -1)
return -1;
return sfd;
}
ListenSocketInet::ListenSocketInet(const std::string &_name, int port)
: ListenSocket(_name), _port(port)
{}
int
ListenSocketInet::accept()
{
int sfd = ListenSocket::accept();
if (sfd == -1)
return -1;
int i = 1;
int ret = ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(i));
warn_if(ret < 0, "ListenSocket(accept): setsockopt() TCP_NODELAY failed!");
return sfd;
}
// Create a socket and configure it for listening
bool
ListenSocket::listen(int port)
ListenSocketInet::listen(int port)
{
panic_if(listening, "Socket already listening!");
@@ -228,13 +256,12 @@ ListenSocket::listen(int port)
return false;
}
listening = true;
anyListening = true;
setListening();
return true;
}
void
ListenSocket::listen()
ListenSocketInet::listen()
{
while (!listen(_port)) {
_port++;
@@ -245,35 +272,16 @@ ListenSocket::listen()
}
void
ListenSocket::output(std::ostream &os) const
ListenSocketInet::output(std::ostream &os) const
{
os << "port " << _port;
}
// Open a connection. Accept will block, so if you don't want it to,
// make sure a connection is ready before you call accept.
int
ListenSocket::accept()
{
struct sockaddr_in sockaddr;
socklen_t slen = sizeof (sockaddr);
int sfd = acceptCloexec(fd, (struct sockaddr *)&sockaddr, &slen);
if (sfd == -1)
return -1;
int i = 1;
int ret = ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(i));
warn_if(ret < 0, "ListenSocket(accept): setsockopt() TCP_NODELAY failed!");
return sfd;
}
ListenSocketConfig
listenSocketInetConfig(int port)
{
return ListenSocketConfig([port](const std::string &name) {
return std::make_unique<ListenSocket>(name, port);
return std::make_unique<ListenSocketInet>(name, port);
});
}

View File

@@ -93,31 +93,34 @@ class ListenSocket : public Named
static void loopbackOnly();
protected:
bool listening;
int fd;
int _port;
bool listening = false;
int fd = -1;
void
setListening()
{
listening = true;
anyListening = true;
}
/*
* cleanup resets the static variables back to their default values.
*/
static void cleanup();
virtual bool listen(int port);
ListenSocket(const std::string &_name);
public:
/**
* @ingroup api_socket
* @{
*/
ListenSocket(const std::string &_name, int port);
ListenSocket();
virtual ~ListenSocket();
virtual int accept();
virtual void listen() = 0;
virtual void listen();
virtual void output(std::ostream &os) const;
virtual void output(std::ostream &os) const = 0;
int getfd() const { return fd; }
bool islistening() const { return listening; }
@@ -130,6 +133,13 @@ class ListenSocket : public Named
/** @} */ // end of api_socket
};
inline static std::ostream &
operator << (std::ostream &os, const ListenSocket &socket)
{
socket.output(os);
return os;
}
using ListenSocketPtr = std::unique_ptr<ListenSocket>;
class ListenSocketConfig
@@ -155,14 +165,24 @@ class ListenSocketConfig
static inline ListenSocketConfig listenSocketEmptyConfig() { return {}; }
ListenSocketConfig listenSocketInetConfig(int port);
// AF_INET based sockets.
inline static std::ostream &
operator << (std::ostream &os, const ListenSocket &socket)
class ListenSocketInet : public ListenSocket
{
socket.output(os);
return os;
}
protected:
int _port;
virtual bool listen(int port);
public:
ListenSocketInet(const std::string &_name, int port);
int accept() override;
void listen() override;
void output(std::ostream &os) const override;
};
ListenSocketConfig listenSocketInetConfig(int port);
} // namespace gem5

View File

@@ -118,10 +118,10 @@ TEST(UnixSocketAddrTest, TruncatedFileBasedSocket)
EXPECT_EQ(truncated_addr, sock_addr.formattedPath);
}
class MockListenSocket : public ListenSocket
class MockListenSocket : public ListenSocketInet
{
public:
MockListenSocket(int port) : ListenSocket("mock", port) {}
MockListenSocket(int port) : ListenSocketInet("mock", port) {}
/*
* This mock Listen Socket is used to ensure the static variables are reset
* back to their default values after deconstruction (i.e., after a test