barrier/lib/net/CTCPListenSocket.cpp

77 lines
1.5 KiB
C++

#include "CTCPListenSocket.h"
#include "CTCPSocket.h"
#include "CNetworkAddress.h"
#include "XIO.h"
#include "XSocket.h"
#include "CThread.h"
//
// CTCPListenSocket
//
CTCPListenSocket::CTCPListenSocket()
{
m_fd = CNetwork::socket(PF_INET, SOCK_STREAM, 0);
if (m_fd == CNetwork::Null) {
throw XSocketCreate();
}
}
CTCPListenSocket::~CTCPListenSocket()
{
try {
close();
}
catch (...) {
// ignore
}
}
void
CTCPListenSocket::bind(const CNetworkAddress& addr)
{
if (CNetwork::bind(m_fd, addr.getAddress(),
addr.getAddressLength()) == CNetwork::Error) {
if (CNetwork::getsockerror() == CNetwork::kEADDRINUSE) {
throw XSocketAddressInUse();
}
throw XSocketBind();
}
if (CNetwork::listen(m_fd, 3) == CNetwork::Error) {
throw XSocketBind();
}
}
IDataSocket*
CTCPListenSocket::accept()
{
// accept asynchronously so we can check for cancellation
CNetwork::PollEntry pfds[1];
pfds[0].fd = m_fd;
pfds[0].events = CNetwork::kPOLLIN;
for (;;) {
CThread::testCancel();
const int status = CNetwork::poll(pfds, 1, 10);
if (status > 0 && (pfds[0].revents & CNetwork::kPOLLIN) != 0) {
CNetwork::Address addr;
CNetwork::AddressLength addrlen = sizeof(addr);
CNetwork::Socket fd = CNetwork::accept(m_fd, &addr, &addrlen);
if (fd != CNetwork::Null) {
return new CTCPSocket(fd);
}
}
}
}
void
CTCPListenSocket::close()
{
if (m_fd == CNetwork::Null) {
throw XIOClosed();
}
if (CNetwork::close(m_fd) == CNetwork::Error) {
throw XIOClose();
}
m_fd = CNetwork::Null;
}