rcpp_framework/libs/brynet/net/Socket.hpp

227 lines
4.7 KiB
C++
Raw Normal View History

2020-11-24 15:41:18 +01:00
#pragma once
#include <brynet/base/NonCopyable.hpp>
#include <brynet/net/SocketLibFunction.hpp>
2021-04-30 16:10:14 +02:00
#include <exception>
#include <memory>
#include <stdexcept>
#include <string>
2020-11-24 15:41:18 +01:00
namespace brynet { namespace net {
2021-04-30 16:10:14 +02:00
class TcpConnection;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
class UniqueFd final : public brynet::base::NonCopyable
{
public:
explicit UniqueFd(BrynetSocketFD fd)
: mFD(fd)
{}
~UniqueFd()
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
brynet::net::base::SocketClose(mFD);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
UniqueFd(const UniqueFd& other) = delete;
UniqueFd& operator=(const UniqueFd& other) = delete;
BrynetSocketFD getFD() const
{
return mFD;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
private:
BrynetSocketFD mFD;
};
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
class TcpSocket : public brynet::base::NonCopyable
{
private:
class TcpSocketDeleter
{
public:
void operator()(TcpSocket* ptr) const
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
delete ptr;
2020-11-24 15:41:18 +01:00
}
};
2021-04-30 16:10:14 +02:00
public:
using Ptr = std::unique_ptr<TcpSocket, TcpSocketDeleter>;
public:
static Ptr Create(BrynetSocketFD fd, bool serverSide)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
class make_unique_enabler : public TcpSocket
2020-11-24 15:41:18 +01:00
{
public:
2021-04-30 16:10:14 +02:00
make_unique_enabler(BrynetSocketFD fd, bool serverSide)
: TcpSocket(fd, serverSide)
{}
2020-11-24 15:41:18 +01:00
};
2021-04-30 16:10:14 +02:00
return Ptr(new make_unique_enabler(fd, serverSide));
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
public:
void setNodelay() const
{
brynet::net::base::SocketNodelay(mFD);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool setNonblock() const
{
return brynet::net::base::SocketNonblock(mFD);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void setSendSize(int sdSize) const
{
brynet::net::base::SocketSetSendSize(mFD, sdSize);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void setRecvSize(int rdSize) const
{
brynet::net::base::SocketSetRecvSize(mFD, rdSize);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
std::string getRemoteIP() const
{
return brynet::net::base::GetIPOfSocket(mFD);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool isServerSide() const
{
return mServerSide;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
protected:
TcpSocket(BrynetSocketFD fd, bool serverSide)
: mFD(fd),
mServerSide(serverSide)
{
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
virtual ~TcpSocket()
{
brynet::net::base::SocketClose(mFD);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
BrynetSocketFD getFD() const
{
return mFD;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
private:
const BrynetSocketFD mFD;
const bool mServerSide;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
friend class TcpConnection;
};
class EintrError : public std::exception
{
};
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
class AcceptError : public std::runtime_error
{
public:
explicit AcceptError(int errorCode)
: std::runtime_error(std::to_string(errorCode)),
mErrorCode(errorCode)
{}
int getErrorCode() const
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return mErrorCode;
}
private:
int mErrorCode;
};
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
class ListenSocket : public brynet::base::NonCopyable
{
private:
class ListenSocketDeleter
2020-11-24 15:41:18 +01:00
{
public:
2021-04-30 16:10:14 +02:00
void operator()(ListenSocket* ptr) const
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
delete ptr;
2020-11-24 15:41:18 +01:00
}
};
2021-04-30 16:10:14 +02:00
public:
using Ptr = std::unique_ptr<ListenSocket, ListenSocketDeleter>;
public:
TcpSocket::Ptr accept()
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
const auto clientFD = brynet::net::base::Accept(mFD, nullptr, nullptr);
if (clientFD == BRYNET_INVALID_SOCKET)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
if (BRYNET_ERRNO == EMFILE)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
// Thanks libev and muduo.
// Read the section named "The special problem of
// accept()ing when you can't" in libev's doc.
// By Marc Lehmann, author of libev.
mIdle.reset();
TcpSocket::Create(brynet::net::base::Accept(mFD, nullptr, nullptr), true);
mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
2020-11-24 15:41:18 +01:00
}
#endif
2021-04-30 16:10:14 +02:00
if (BRYNET_ERRNO == EINTR)
{
throw EintrError();
}
else
{
throw AcceptError(BRYNET_ERRNO);
2020-11-24 15:41:18 +01:00
}
}
2021-04-30 16:10:14 +02:00
return TcpSocket::Create(clientFD, true);
}
public:
static Ptr Create(BrynetSocketFD fd)
{
class make_unique_enabler : public ListenSocket
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
public:
explicit make_unique_enabler(BrynetSocketFD fd)
: ListenSocket(fd)
{}
};
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
return Ptr(new make_unique_enabler(fd));
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
protected:
explicit ListenSocket(BrynetSocketFD fd)
: mFD(fd)
{
2020-11-24 15:41:18 +01:00
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
2021-04-30 16:10:14 +02:00
mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
virtual ~ListenSocket()
{
brynet::net::base::SocketClose(mFD);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
private:
const BrynetSocketFD mFD;
2020-11-24 15:41:18 +01:00
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
2021-04-30 16:10:14 +02:00
brynet::net::TcpSocket::Ptr mIdle;
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
friend class TcpConnection;
};
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
}}// namespace brynet::net