init repo.

This commit is contained in:
tqcq
2024-02-23 18:07:37 +08:00
commit 1a9e41d167
512 changed files with 191774 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
#include "sled/network/async_resolver.h"
#include "sled/network/async_resolver_interface.h"
#include "sled/ref_counted_base.h"
#include "sled/synchronization/mutex.h"
#include "sled/task_queue/task_queue_base.h"
#include <thread>
namespace sled {
struct AsyncResolver::State : public RefCountedBase {
Mutex mutex;
enum class Status {
kLive,
kDead,
} status = Status::kLive;
};
int
ResolveHostname(const std::string &hostname,
int family,
std::vector<IPAddress> *addresses)
{
if (!addresses) { return -1; }
addresses->clear();
struct addrinfo *result = nullptr;
struct addrinfo hints = {0};
hints.ai_family = family;
hints.ai_flags = AI_ADDRCONFIG;
int ret = getaddrinfo(hostname.c_str(), nullptr, &hints, &result);
if (ret != 0) { return ret; }
struct addrinfo *cursor = result;
for (; cursor; cursor = cursor->ai_next) {
if (family == AF_UNSPEC || cursor->ai_family == family) {
IPAddress ip;
if (IPFromAddrInfo(cursor, &ip)) { addresses->push_back(ip); }
}
}
freeaddrinfo(result);
return 0;
}
AsyncResolver::AsyncResolver() : error_(-1), state_(new State) {}
AsyncResolver::~AsyncResolver()
{
MutexLock lock(&state_->mutex);
;
state_->status = State::Status::kDead;
}
void
AsyncResolver::Start(const SocketAddress &addr)
{
Start(addr, addr.family());
}
void
AsyncResolver::Start(const SocketAddress &addr, int family)
{
addr_ = addr;
auto caller_task_queue = TaskQueueBase::Current();
auto state = state_;
auto thread_function = [this, addr, family, caller_task_queue, state] {
std::vector<IPAddress> addresses;
int error = ResolveHostname(addr.hostname(), family, &addresses);
caller_task_queue->PostTask([this, error, &addresses, state] {
bool live;
{
MutexLock lock(&state->mutex);
live = state->status == State::Status::kLive;
}
if (live) { ResolveDone(std::move(addresses), error); }
});
};
// TODO: Add new thread run function
std::thread(thread_function).detach();
}
bool
AsyncResolver::GetResolvedAddress(int family, SocketAddress *addr) const
{
if (error_ != 0 || addresses_.empty()) { return false; }
*addr = addr_;
for (size_t i = 0; i < addresses_.size(); ++i) {
if (family == addresses_[i].family()) {
addr->SetResolvedIP(addresses_[i]);
return true;
}
}
return false;
}
int
AsyncResolver::GetError() const
{
return error_;
}
void
AsyncResolver::Destroy(bool wait)
{
destroy_called_ = true;
MaybeSelfDestruct();
}
const std::vector<IPAddress> &
AsyncResolver::addresses() const
{
return addresses_;
}
void
AsyncResolver::ResolveDone(std::vector<IPAddress> addresses, int error)
{
addresses_ = addresses;
error_ = error;
recursion_check_ = true;
SignalDone(this);
MaybeSelfDestruct();
}
void
AsyncResolver::MaybeSelfDestruct()
{
if (!recursion_check_) {
delete this;
} else {
recursion_check_ = false;
}
}
}// namespace sled

289
src/network/ip_address.cc Normal file
View File

@@ -0,0 +1,289 @@
#include "sled/network/ip_address.h"
#include <netinet/in.h>
namespace sled {
static const in6_addr kV4MappedPrefix = {
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0}}};
static const in6_addr kPrivateNetworkPrefix = {{{0xFD}}};
bool
IPAddress::operator==(const IPAddress &other) const
{
if (family_ != other.family_) { return false; }
if (family_ == AF_INET) {
return ::memcmp(&u_.ip4, &other.u_.ip4, sizeof(u_.ip4)) == 0;
}
if (family_ == AF_INET6) {
return ::memcmp(&u_.ip6, &other.u_.ip6, sizeof(u_.ip6)) == 0;
}
return family_ == AF_UNSPEC;
}
bool
IPAddress::operator!=(const IPAddress &other) const
{
return !((*this) == other);
}
bool
IPAddress::operator<(const IPAddress &other) const
{
if (family_ != other.family_) {
if (family_ == AF_UNSPEC) { return true; }
if (family_ == AF_INET && other.family_ == AF_INET6) { return true; }
return false;
}
switch (family_) {
case AF_INET: {
return NetworkToHost32(u_.ip4.s_addr)
< NetworkToHost32(other.u_.ip4.s_addr);
}
case AF_INET6: {
return ::memcmp(&u_.ip6, &other.u_.ip6, sizeof(u_.ip6)) < 0;
}
return ::memcmp(&u_.ip6.s6_addr, &other.u_.ip6.s6_addr, 16) < 0;
}
return false;
}
int
IPAddress::overhead() const
{
switch (family_) {
case AF_INET:
return 20;
case AF_INET6:
return 40;
default:
return 0;
}
}
uint32_t
IPAddress::v4AddressAsHostOrderInteger() const
{
if (family_ == AF_INET) {
return NetworkToHost32(u_.ip4.s_addr);
} else {
return 0;
}
}
bool
IPAddress::IsNil() const
{
return IPIsUnspec(*this);
}
size_t
IPAddress::Size() const
{
switch (family_) {
case AF_INET:
return sizeof(in_addr);
case AF_INET6:
return sizeof(in6_addr);
default:
return 0;
}
}
std::string
IPAddress::ToString() const
{
if (family_ != AF_INET && family_ != AF_INET6) { return std::string(); }
char buf[INET6_ADDRSTRLEN] = {0};
const void *src = &u_.ip4;
if (family_ == AF_INET6) { src = &u_.ip6; }
if (::inet_ntop(family_, src, buf, sizeof(buf)) == 0) {
return std::string();
}
return std::string(buf);
}
in_addr
IPAddress::ipv4_address() const
{
return u_.ip4;
}
in6_addr
IPAddress::ipv6_address() const
{
return u_.ip6;
}
bool
IPIsHelper(const IPAddress &ip, const in6_addr &tomatch, int length)
{
in6_addr addr = ip.ipv6_address();
return ::memcmp(&addr, &tomatch, (length >> 3)) == 0;
}
bool
IPFromAddrInfo(struct addrinfo *info, IPAddress *out)
{
if (!info || !info->ai_addr) { return false; }
if (info->ai_addr->sa_family == AF_INET) {
// ipv4
sockaddr_in *addr = reinterpret_cast<sockaddr_in *>(info->ai_addr);
*out = IPAddress(addr->sin_addr);
return true;
} else if (info->ai_addr->sa_family == AF_INET6) {
// ipv6
sockaddr_in6 *addr = reinterpret_cast<sockaddr_in6 *>(info->ai_addr);
*out = IPAddress(addr->sin6_addr);
return true;
}
return false;
}
bool
IPFromString(const std::string &str, IPAddress *out)
{
if (!out) { return false; }
in_addr addr;
if (::inet_pton(AF_INET, str.c_str(), &addr) == 0) {
in6_addr addr6;
if (::inet_pton(AF_INET6, str.c_str(), &addr6) == 0) {
*out = IPAddress();
return false;
}
*out = IPAddress(addr6);
} else {
// RETURN VALUE is -1(invalid family) or 1(success)
*out = IPAddress(addr);
}
return true;
}
bool
IPIsAny(const IPAddress &ip)
{
switch (ip.family()) {
case AF_INET:
return ip == IPAddress(INADDR_ANY);
case AF_INET6:
return ip == IPAddress(in6addr_any) || ip == IPAddress(kV4MappedPrefix);
case AF_UNSPEC:
return false;
}
return false;
}
static bool
IPIsLinkLocalV4(const IPAddress &ip)
{
uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
return ((ip_in_host_order >> 16) == ((169 << 8) | 254));
}
static bool
IPIsLinkLocalV6(const IPAddress &ip)
{
in6_addr addr = ip.ipv6_address();
return (addr.s6_addr[0] == 0xFE && (addr.s6_addr[1] & 0xC0) == 0x80);
}
bool
IPIsLinkLocal(const IPAddress &ip)
{
switch (ip.family()) {
case AF_INET:
return IPIsLinkLocalV4(ip);
case AF_INET6:
return IPIsLinkLocalV6(ip);
}
return false;
}
static bool
IPIsPrivateNetworkV4(const IPAddress &ip)
{
uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
return ((ip_in_host_order >> 24) == 10)
|| ((ip_in_host_order >> 20) == ((172 << 4) | 1))
|| ((ip_in_host_order >> 16) == ((192 << 8) | 168));
}
static bool
IPIsPrivateNetworkV6(const IPAddress &ip)
{
return IPIsHelper(ip, kPrivateNetworkPrefix, 8);
}
// like "192.168.111.222"
bool
IPIsPrivateNetwork(const IPAddress &ip)
{
switch (ip.family()) {
case AF_INET:
return IPIsPrivateNetworkV4(ip);
case AF_INET6:
return IPIsPrivateNetworkV6(ip);
}
return false;
}
static bool
IPIsSharedNetworkV4(const IPAddress &ip)
{
uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
return (ip_in_host_order >> 22) == ((100 << 2) | 1);
}
// like "100.72.16.122"
bool
IPIsSharedNetwork(const IPAddress &ip)
{
if (ip.family() == AF_INET) { return IPIsSharedNetworkV4(ip); }
return false;
}
static bool
IPIsLoopbackV4(const IPAddress &ip)
{
uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
return ((ip_in_host_order >> 24) == 127);
}
static bool
IPIsLoopbackV6(const IPAddress &ip)
{
return ip == IPAddress(in6addr_loopback);
}
bool
IPIsLoopback(const IPAddress &ip)
{
switch (ip.family()) {
case AF_INET:
return IPIsLoopbackV4(ip);
case AF_INET6:
return IPIsLoopbackV6(ip);
}
return false;
}
bool
IPIsPrivate(const IPAddress &ip)
{
return IPIsLinkLocal(ip) || IPIsLoopback(ip) || IPIsPrivateNetwork(ip)
|| IPIsSharedNetwork(ip);
}
bool
IPIsUnspec(const IPAddress &ip)
{
return ip.family() == AF_UNSPEC;
}
}// namespace sled

View File

@@ -0,0 +1,27 @@
#include "sled/network/null_socket_server.h"
namespace sled {
NullSocketServer::NullSocketServer() = default;
NullSocketServer::~NullSocketServer() {}
bool
NullSocketServer::Wait(TimeDelta max_wait_duration, bool process_io)
{
event_.Wait(max_wait_duration);
return true;
}
void
NullSocketServer::WakeUp()
{
event_.Set();
}
Socket *
NullSocketServer::CreateSocket(int family, int type)
{
return nullptr;
}
}// namespace sled

View File

@@ -0,0 +1,827 @@
#include "sled/network/physical_socket_server.h"
#include "sled/network/async_resolver.h"
#include "sled/network/socket.h"
#include "sled/synchronization/event.h"
#include "sled/synchronization/mutex.h"
#include "sled/time_utils.h"
#include <array>
#include <errno.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <unistd.h>
namespace {
class ScopedSetTrue {
public:
ScopedSetTrue(bool *value) : value_(value) { *value_ = true; }
~ScopedSetTrue() { *value_ = false; }
private:
bool *value_;
};
}// namespace
namespace sled {
class Signaler : public Dispatcher {
public:
Signaler(PhysicalSocketServer *ss, bool &flag_to_clear)
: ss_(ss),
afd_([] {
std::array<int, 2> afd = {INVALID_SOCKET, INVALID_SOCKET};
if (pipe(afd.data()) < 0) {
// TODO: add log here
}
return afd;
}()),
fSignaled_(false),
flag_to_clear_(flag_to_clear)
{
ss_->Add(this);
}
~Signaler() override
{
ss_->Remove(this);
close(afd_[0]);
close(afd_[1]);
}
virtual void Signal()
{
MutexLock lock(&mutex_);
if (!fSignaled_) {
const uint8_t b[1] = {0};
const ssize_t res = write(afd_[1], b, sizeof(b));
fSignaled_ = true;
}
}
uint32_t GetRequestedEvents() override { return DE_READ; }
void OnEvent(uint32_t ff, int err) override
{
MutexLock lock(&mutex_);
if (fSignaled_) {
uint8_t b[4];
const ssize_t res = read(afd_[0], b, sizeof(b));
fSignaled_ = false;
}
flag_to_clear_ = false;
}
int GetDescriptor() override { return afd_[0]; }
bool IsDescriptorClosed() override { return false; }
private:
PhysicalSocketServer *const ss_;
const std::array<int, 2> afd_;
bool fSignaled_;
Mutex mutex_;
bool &flag_to_clear_;
};
PhysicalSocketServer::PhysicalSocketServer() : fWait_(false)
{
signal_wakeup_ = new Signaler(this, fWait_);
}
PhysicalSocketServer::~PhysicalSocketServer() { delete signal_wakeup_; }
void
PhysicalSocketServer::WakeUp()
{
signal_wakeup_->Signal();
}
Socket *
PhysicalSocketServer::CreateSocket(int family, int type)
{
SocketDispatcher *dispatcher = new SocketDispatcher(this);
if (dispatcher->Create(family, type)) {
return dispatcher;
} else {
delete dispatcher;
return nullptr;
}
}
Socket *
PhysicalSocketServer::WrapSocket(SOCKET s)
{
SocketDispatcher *dispatcher = new SocketDispatcher(s, this);
if (dispatcher->Initialize()) {
return dispatcher;
} else {
delete dispatcher;
return nullptr;
}
}
void
PhysicalSocketServer::Add(Dispatcher *pdispatcher)
{
RecursiveMutexLock lock(&lock_);
if (key_by_dispatcher_.count(pdispatcher)) { return; }
uint64_t key = next_dispatcher_key_++;
dispatcher_by_key_.emplace(key, pdispatcher);
key_by_dispatcher_.emplace(pdispatcher, key);
}
void
PhysicalSocketServer::Remove(Dispatcher *pdispatcher)
{
RecursiveMutexLock lock(&lock_);
if (!key_by_dispatcher_.count(pdispatcher)) { return; }
uint64_t key = key_by_dispatcher_.at(pdispatcher);
key_by_dispatcher_.erase(pdispatcher);
dispatcher_by_key_.erase(key);
}
void
PhysicalSocketServer::Update(Dispatcher *pdispatcher)
{
return;
/*
MutexLock lock(&lock_);
if (!key_by_dispatcher_.count(pdispatcher)) { return; }
UpdateEpoll();
*/
}
int
PhysicalSocketServer::ToCmsWait(TimeDelta max_wait_duration)
{
return max_wait_duration == Event::kForever
? kForeverMs
: max_wait_duration.RoundUpTo(TimeDelta::Millis(1)).ms();
}
bool
PhysicalSocketServer::Wait(TimeDelta max_wait_duration, bool process_io)
{
ScopedSetTrue s(&waiting_);
const int cmsWait = ToCmsWait(max_wait_duration);
return WaitSelect(cmsWait, process_io);
}
static void
ProcessEvents(Dispatcher *pdispatcher,
bool readable,
bool writable,
bool error_event,
bool check_error)
{
int errcode = 0;
if (check_error) {
socklen_t len = sizeof(errcode);
int res = ::getsockopt(pdispatcher->GetDescriptor(), SOL_SOCKET,
SO_ERROR, &errcode, &len);
if (res < 0) {
if (error_event || errno != ENOTSOCK) { errcode = EBADF; }
}
}
const uint32_t requested_events = pdispatcher->GetRequestedEvents();
uint32_t ff = 0;
if (readable) {
if (errcode || pdispatcher->IsDescriptorClosed()) {
ff |= DE_CLOSE;
} else if (requested_events & DE_ACCEPT) {
ff |= DE_ACCEPT;
} else {
ff |= DE_READ;
}
}
if (writable) {
if (requested_events & DE_CONNECT) {
if (!errcode) { ff |= DE_CONNECT; }
} else {
ff |= DE_WRITE;
}
}
if (errcode) { ff |= DE_CLOSE; }
if (ff != 0) { pdispatcher->OnEvent(ff, errcode); }
}
bool
PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io)
{
struct timeval *ptvWait = nullptr;
struct timeval tvWait;
int64_t stop_us;
if (cmsWait != kForeverMs) {
tvWait.tv_sec = cmsWait / 1000;
tvWait.tv_usec = (cmsWait % 1000) * 1000;
ptvWait = &tvWait;
stop_us = TimeMicros() + cmsWait * 1000;
}
fd_set fdsRead;
fd_set fdsWrite;
fWait_ = true;
while (fWait_) {
FD_ZERO(&fdsRead);
FD_ZERO(&fdsWrite);
int fdmax = -1;
{
RecursiveMutexLock lock(&lock_);
current_dispatcher_keys_.clear();
for (auto const &kv : dispatcher_by_key_) {
uint64_t key = kv.first;
Dispatcher *pdispatcher = kv.second;
if (!process_io && (pdispatcher != signal_wakeup_)) {
continue;
}
current_dispatcher_keys_.push_back(key);
int fd = pdispatcher->GetDescriptor();
if (fd > fdmax) { fdmax = fd; }
uint32_t ff = pdispatcher->GetRequestedEvents();
if (ff & (DE_READ | DE_ACCEPT)) { FD_SET(fd, &fdsRead); }
if (ff & (DE_WRITE | DE_CONNECT)) { FD_SET(fd, &fdsWrite); }
}
}
int n = select(fdmax + 1, &fdsRead, &fdsWrite, nullptr, ptvWait);
if (n < 0) {
if (errno != EINTR) { return false; }
} else if (n == 0) {
return true;
} else {
RecursiveMutexLock lock(&lock_);
for (uint64_t key : current_dispatcher_keys_) {
// skip if the dispatcher is removed
if (!dispatcher_by_key_.count(key)) { continue; }
Dispatcher *pdispatcher = dispatcher_by_key_.at(key);
int fd = pdispatcher->GetDescriptor();
bool readable = FD_ISSET(fd, &fdsRead);
if (readable) { FD_CLR(fd, &fdsRead); }
bool writable = FD_ISSET(fd, &fdsWrite);
if (writable) { FD_CLR(fd, &fdsWrite); }
ProcessEvents(pdispatcher, readable, writable, false,
readable || writable);
}
}
if (ptvWait) {
ptvWait->tv_sec = 0;
ptvWait->tv_usec = 0;
int64_t time_left_us = stop_us - TimeMicros();
if (time_left_us > 0) {
ptvWait->tv_sec = time_left_us / kNumMicrosecsPerSec;
ptvWait->tv_usec = time_left_us % kNumMicrosecsPerSec;
} else {
break;
}
}
}
return true;
}
PhysicalSocket::PhysicalSocket(PhysicalSocketServer *ss, SOCKET s)
: ss_(ss),
s_(s),
error_(0),
state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
resolver_(nullptr)
{
if (s != INVALID_SOCKET) {
SetEnabledEvents(DE_READ | DE_WRITE);
int type = SOCK_STREAM;
socklen_t len = sizeof(type);
const int res =
getsockopt(s_, SOL_SOCKET, SO_TYPE, (void *) &type, &len);
udp_ = (SOCK_DGRAM == type);
}
}
PhysicalSocket::~PhysicalSocket() { Close(); }
bool
PhysicalSocket::Create(int family, int type)
{
Close();
s_ = ::socket(family, type, 0);
udp_ = (SOCK_DGRAM == type);
family_ = family;
UpdateLastError();
if (udp_) { SetEnabledEvents(DE_READ | DE_WRITE); }
return s_ != INVALID_SOCKET;
}
SocketAddress
PhysicalSocket::GetLocalAddress() const
{
sockaddr_storage addr_storage = {};
socklen_t addrlen = sizeof(addr_storage);
sockaddr *addr = reinterpret_cast<sockaddr *>(&addr_storage);
int result = ::getsockname(s_, addr, &addrlen);
SocketAddress address;
if (result >= 0) {
} else {
}
return address;
}
SocketAddress
PhysicalSocket::GetRemoteAddress() const
{
sockaddr_storage addr_storage = {};
socklen_t addrlen = sizeof(addr_storage);
sockaddr *addr = reinterpret_cast<sockaddr *>(&addr_storage);
int result = ::getpeername(s_, addr, &addrlen);
SocketAddress address;
if (result >= 0) {
} else {
}
return address;
}
int
PhysicalSocket::Bind(const SocketAddress &bind_addr)
{
SocketAddress copied_bind_addr = bind_addr;
sockaddr_storage addr_storage;
size_t len = copied_bind_addr.ToSockAddrStorage(&addr_storage);
sockaddr *addr = reinterpret_cast<sockaddr *>(&addr_storage);
int err = ::bind(s_, addr, static_cast<int>(len));
UpdateLastError();
return err;
}
int
PhysicalSocket::Connect(const SocketAddress &addr)
{
if (state_ != CS_CLOSED) {
SetError(EALREADY);
return SOCKET_ERROR;
}
if (addr.IsUnresolvedIP()) {
resolver_ = new AsyncResolver();
resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
resolver_->Start(addr);
state_ = CS_CONNECTING;
return 0;
}
return DoConnect(addr);
}
int
PhysicalSocket::GetError() const
{
MutexLock lock(&mutex_);
return error_;
}
void
PhysicalSocket::SetError(int error)
{
// MutexLock lock(&mutex_);
LockGuard<Mutex> lock(&mutex_);
error_ = error;
}
int
PhysicalSocket::GetOption(Option opt, int *value)
{
int slevel;
int sopt;
if (TranslateOption(opt, &slevel, &sopt) == -1) { return -1; }
socklen_t optlen = sizeof(*value);
int ret = ::getsockopt(s_, slevel, sopt, (void *) value, &optlen);
if (ret == -1) { return -1; }
return ret;
}
int
PhysicalSocket::SetOption(Option opt, int value)
{
int slevel;
int sopt;
if (TranslateOption(opt, &slevel, &sopt) == -1) { return -1; }
int result = ::setsockopt(s_, slevel, sopt, (void *) &value, sizeof(value));
if (result != 0) { UpdateLastError(); }
return result;
}
int
PhysicalSocket::Send(const void *pv, size_t cb)
{
int sent = DoSend(s_, reinterpret_cast<const char *>(pv),
static_cast<int>(cb), MSG_NOSIGNAL);
UpdateLastError();
if ((sent > 0 && sent < static_cast<int>(cb))
|| (sent < 0 && IsBlockingError(GetError()))) {
EnableEvents(DE_WRITE);
}
return sent;
}
int
PhysicalSocket::SendTo(const void *buffer,
size_t length,
const SocketAddress &addr)
{
sockaddr_storage saddr;
size_t len = addr.ToSockAddrStorage(&saddr);
int sent =
DoSendTo(s_, static_cast<const char *>(buffer),
static_cast<int>(length), MSG_NOSIGNAL,
reinterpret_cast<sockaddr *>(&saddr), static_cast<int>(len));
UpdateLastError();
if ((sent > 0 && sent < static_cast<int>(length))
|| (sent < 0 && IsBlockingError(GetError()))) {
EnableEvents(DE_WRITE);
}
return sent;
}
int
PhysicalSocket::Recv(void *buffer, size_t length, int64_t *timestamp)
{
int received = DoReadFromSocket(buffer, length, nullptr, timestamp);
if ((received == 0) && (length != 0)) {
EnableEvents(DE_READ);
SetError(EWOULDBLOCK);
return SOCKET_ERROR;
}
UpdateLastError();
int error = GetError();
bool success = (received >= 0) || IsBlockingError(GetError());
if (udp_ || success) { EnableEvents(DE_READ); }
if (!success) {
// TODO: add log here
}
return received;
}
int
PhysicalSocket::RecvFrom(void *buffer,
size_t length,
SocketAddress *out_addr,
int64_t *timestamp)
{
int received = DoReadFromSocket(buffer, length, out_addr, timestamp);
UpdateLastError();
int error = GetError();
bool success = (received >= 0) || IsBlockingError(error);
if (udp_ || success) { EnableEvents(DE_READ); }
if (!success) {
// TODO: add log here
}
return received;
}
int64_t
GetSocketRecvTimestamp(int socket)
{
struct timeval tv_ioctl;
#if defined(SIOCGSTAMP_OLD)
int ret = ioctl(socket, SIOCGSTAMP_OLD, &tv_ioctl);
#elif defined(SIOCGSTAMP)
int ret = ioctl(socket, SIOCGSTAMP, &tv_ioctl);
#else
int ret = -1;
#endif
if (ret != 0) { return -1; }
int64_t timestamp =
static_cast<int64_t>(tv_ioctl.tv_sec) * kNumMicrosecsPerSec
+ tv_ioctl.tv_usec;
return timestamp;
}
int
PhysicalSocket::DoReadFromSocket(void *buffer,
size_t length,
SocketAddress *out_addr,
int64_t *timestamp)
{
sockaddr_storage addr_storage;
socklen_t addr_len = sizeof(addr_storage);
sockaddr *addr = reinterpret_cast<sockaddr *>(&addr_storage);
int received = 0;
if (out_addr) {
received = ::recvfrom(s_, static_cast<char *>(buffer),
static_cast<int>(length), 0, addr, &addr_len);
SocketAddressFromSockAddrStorage(addr_storage, out_addr);
} else {
received = ::recv(s_, static_cast<char *>(buffer),
static_cast<int>(length), 0);
}
if (timestamp) { *timestamp = GetSocketRecvTimestamp(s_); }
return received;
}
int
PhysicalSocket::Listen(int backlog)
{
int err = ::listen(s_, backlog);
UpdateLastError();
if (err == 0) {
state_ = CS_CONNECTING;
EnableEvents(DE_ACCEPT);
}
return err;
}
Socket *
PhysicalSocket::Accept(SocketAddress *out_addr)
{
EnableEvents(DE_ACCEPT);
sockaddr_storage addr_storage;
socklen_t addr_len = sizeof(addr_storage);
sockaddr *addr = reinterpret_cast<sockaddr *>(&addr_storage);
SOCKET s = DoAccept(s_, addr, &addr_len);
UpdateLastError();
if (s == INVALID_SOCKET) { return nullptr; }
if (out_addr) { SocketAddressFromSockAddrStorage(addr_storage, out_addr); }
return ss_->WrapSocket(s);
}
int
PhysicalSocket::Close()
{
if (s_ == INVALID_SOCKET) { return 0; }
int err = ::close(s_);
UpdateLastError();
s_ = INVALID_SOCKET;
state_ = CS_CLOSED;
SetEnabledEvents(0);
if (resolver_) {
resolver_->Destroy(false);
resolver_ = nullptr;
}
return err;
}
SOCKET
PhysicalSocket::DoAccept(SOCKET socket, sockaddr *addr, socklen_t *addrlen)
{
return ::accept(socket, addr, addrlen);
}
int
PhysicalSocket::DoSend(SOCKET socket, const char *buf, int len, int flags)
{
return ::send(socket, buf, len, flags);
}
int
PhysicalSocket::DoSendTo(SOCKET socket,
const char *buf,
int len,
int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen)
{
return ::sendto(socket, buf, len, flags, dest_addr, addrlen);
}
int
PhysicalSocket::DoConnect(const SocketAddress &connect_addr)
{
if ((s_ == INVALID_SOCKET) && !Create(connect_addr.family(), SOCK_STREAM)) {
return SOCKET_ERROR;
}
sockaddr_storage addr_storage;
size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
sockaddr *addr = reinterpret_cast<sockaddr *>(&addr_storage);
int err = ::connect(s_, addr, static_cast<int>(len));
UpdateLastError();
uint8_t events = DE_READ | DE_WRITE;
if (err == 0) {
state_ = CS_CONNECTED;
} else if (IsBlockingError(GetError())) {
state_ = CS_CONNECTING;
events |= DE_CONNECT;
} else {
return SOCKET_ERROR;
}
EnableEvents(events);
return 0;
}
void
PhysicalSocket::OnResolveResult(AsyncResolverInterface *resolver)
{
if (resolver != resolver_) { return; }
int error = resolver_->GetError();
if (error == 0) {
error = DoConnect(resolver_->address());
} else {
// get error from resolver
Close();
SetError(error);
SignalCloseEvent(this, error);
}
}
void
PhysicalSocket::UpdateLastError()
{
SetError(errno);
}
void
PhysicalSocket::SetEnabledEvents(uint8_t events)
{
enabled_events_ = events;
}
void
PhysicalSocket::EnableEvents(uint8_t events)
{
enabled_events_ |= events;
}
void
PhysicalSocket::DisableEvents(uint8_t events)
{
enabled_events_ &= ~events;
}
int
PhysicalSocket::TranslateOption(Option opt, int *slevel, int *sopt)
{
switch (opt) {
case OPT_RCVBUF:
*slevel = SOL_SOCKET;
*sopt = SO_RCVBUF;
break;
case OPT_SNDBUF:
*slevel = SOL_SOCKET;
*sopt = SO_SNDBUF;
break;
case OPT_NODELAY:
*slevel = IPPROTO_TCP;
*sopt = TCP_NODELAY;
break;
default:
return -1;
}
return 0;
}
SocketDispatcher::SocketDispatcher(PhysicalSocketServer *ss)
: PhysicalSocket(ss)
{}
SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer *ss)
: PhysicalSocket(ss, s)
{}
SocketDispatcher::~SocketDispatcher() { Close(); }
bool
SocketDispatcher::Initialize()
{
// must be a non-blocking
fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
ss_->Add(this);
return true;
}
bool
SocketDispatcher::Create(int type)
{
return Create(AF_INET, type);
}
bool
SocketDispatcher::Create(int family, int type)
{
if (!PhysicalSocket::Create(family, type)) { return false; }
if (!Initialize()) { return false; }
return true;
}
int
SocketDispatcher::GetDescriptor()
{
return s_;
}
bool
SocketDispatcher::IsDescriptorClosed()
{
if (udp_) { return s_ == INVALID_SOCKET; }
char ch;
ssize_t res;
do {
res = ::recv(s_, &ch, 1, MSG_PEEK);
} while (res < 0 && errno == EINTR);
if (res > 0) {
return false;
} else if (res == 0) {
return true;
} else {
switch (errno) {
case EBADF:
return true;
case ECONNRESET:
return true;
case ECONNABORTED:
return true;
case EPIPE:
return true;
case EWOULDBLOCK:
return false;
default:
// Assuming benign blocking error
return false;
}
}
}
uint32_t
SocketDispatcher::GetRequestedEvents()
{
return enabled_events();
}
void
SocketDispatcher::OnEvent(uint32_t ff, int err)
{
if ((ff & DE_CONNECT) != 0) { state_ = CS_CONNECTED; }
if ((ff & DE_CLOSE) != 0) { state_ = CS_CLOSED; }
if ((ff & DE_CONNECT) != 0) {
DisableEvents(DE_CONNECT);
SignalConnectEvent(this);
}
if ((ff & DE_ACCEPT) != 0) {
DisableEvents(DE_ACCEPT);
SignalReadEvent(this);
}
if ((ff & DE_READ) != 0) {
DisableEvents(DE_READ);
SignalReadEvent(this);
}
if ((ff & DE_WRITE) != 0) {
DisableEvents(DE_WRITE);
SignalWriteEvent(this);
}
if ((ff & DE_CLOSE) != 0) {
SetEnabledEvents(0);
SignalCloseEvent(this, err);
}
}
int
SocketDispatcher::Close()
{
if (s_ == INVALID_SOCKET) { return 0; }
ss_->Remove(this);
return PhysicalSocket::Close();
}
}// namespace sled

View File

@@ -0,0 +1,235 @@
#include "sled/network/socket_address.h"
#include "sled/network/ip_address.h"
namespace sled {
SocketAddress::SocketAddress() { Clear(); }
SocketAddress::SocketAddress(const std::string &hostname, int port)
{
SetIP(hostname);
SetPort(port);
}
SocketAddress::SocketAddress(uint32_t ip_as_host_order_integer, int port)
{
SetIP(IPAddress(ip_as_host_order_integer));
SetPort(port);
}
SocketAddress::SocketAddress(const IPAddress &ip, int port)
{
SetIP(ip);
SetPort(port);
}
SocketAddress::SocketAddress(const SocketAddress &addr)
{
this->operator=(addr);
}
void
SocketAddress::Clear()
{
hostname_.clear();
literal_ = false;
ip_ = IPAddress();
port_ = 0;
scope_id_ = 0;
}
bool
SocketAddress::IsNil() const
{
return hostname_.empty() && IPIsUnspec(ip_) && 0 == port_;
}
bool
SocketAddress::IsComplete() const
{
return (!IPIsAny(ip_)) && (0 != port_);
}
SocketAddress &
SocketAddress::operator=(const SocketAddress &addr)
{
hostname_ = addr.hostname_;
ip_ = addr.ip_;
port_ = addr.port_;
scope_id_ = addr.scope_id_;
literal_ = addr.literal_;
return *this;
}
void
SocketAddress::SetIP(uint32_t ip_as_host_order_integer)
{
hostname_.clear();
literal_ = false;
ip_ = IPAddress(ip_as_host_order_integer);
scope_id_ = 0;
}
void
SocketAddress::SetIP(const IPAddress &ip)
{
hostname_.clear();
literal_ = false;
ip_ = ip;
scope_id_ = 0;
}
void
SocketAddress::SetIP(const std::string &hostname)
{
hostname_ = hostname;
literal_ = IPFromString(hostname, &ip_);
if (!literal_) { ip_ = IPAddress(); }
scope_id_ = 0;
}
void
SocketAddress::SetResolvedIP(uint32_t ip_as_host_order_integer)
{
SetIP(ip_as_host_order_integer);
scope_id_ = 0;
}
void
SocketAddress::SetResolvedIP(const IPAddress &ip)
{
ip_ = ip;
scope_id_ = 0;
}
void
SocketAddress::SetPort(int port)
{
port_ = static_cast<uint16_t>(port);
}
uint32_t
SocketAddress::ip() const
{
return ip_.v4AddressAsHostOrderInteger();
}
const IPAddress &
SocketAddress::ipaddr() const
{
return ip_;
}
uint16_t
SocketAddress::port() const
{
return port_;
}
bool
SocketAddress::IsAnyIP() const
{
return IPIsAny(ip_);
}
bool
SocketAddress::IsLoopbackIP() const
{
return IPIsLoopback(ip_)
|| (IPIsAny(ip_) && 0 == strcmp(hostname_.c_str(), "localhost"));
}
bool
SocketAddress::IsPrivateIP() const
{
return IPIsPrivate(ip_);
}
bool
SocketAddress::IsUnresolvedIP() const
{
return IPIsUnspec(ip_) && !literal_ && !hostname_.empty();
}
void
SocketAddress::ToSockAddr(sockaddr_in *saddr) const
{
::memset(saddr, 0, sizeof(*saddr));
if (ip_.family() != AF_INET) {
saddr->sin_family = AF_UNSPEC;
return;
}
saddr->sin_family = AF_INET;
saddr->sin_port = HostToNetwork16(port_);
if (IPIsAny(ip_)) {
saddr->sin_addr.s_addr = INADDR_ANY;
} else {
saddr->sin_addr = ip_.ipv4_address();
}
}
bool
SocketAddress::FromSockAddr(const sockaddr_in &saddr)
{
if (saddr.sin_family != AF_INET) { return false; }
SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
SetPort(NetworkToHost16(saddr.sin_port));
literal_ = false;
return true;
}
static size_t
ToSocketAddrStorageHelper(sockaddr_storage *addr,
const IPAddress &ip,
uint16_t port,
int scope_id)
{
::memset(addr, 0, sizeof(sockaddr_storage));
addr->ss_family = static_cast<sa_family_t>(ip.family());
if (addr->ss_family == AF_INET6) {
sockaddr_in6 *saddr = reinterpret_cast<sockaddr_in6 *>(addr);
saddr->sin6_addr = ip.ipv6_address();
saddr->sin6_port = HostToNetwork16(port);
saddr->sin6_scope_id = scope_id;
return sizeof(sockaddr_in6);
} else if (addr->ss_family == AF_INET) {
sockaddr_in *saddr = reinterpret_cast<sockaddr_in *>(addr);
saddr->sin_addr = ip.ipv4_address();
saddr->sin_port = HostToNetwork16(port);
return sizeof(sockaddr_in);
}
return 0;
}
size_t
SocketAddress::ToSockAddrStorage(sockaddr_storage *saddr) const
{
return ToSocketAddrStorageHelper(saddr, ip_, port_, scope_id_);
}
bool
SocketAddressFromSockAddrStorage(const sockaddr_storage &addr,
SocketAddress *out)
{
if (!out) { return false; }
if (addr.ss_family == AF_INET) {
const sockaddr_in *saddr = reinterpret_cast<const sockaddr_in *>(&addr);
*out = SocketAddress(IPAddress(saddr->sin_addr),
NetworkToHost16(saddr->sin_port));
return true;
} else if (addr.ss_family == AF_INET6) {
const sockaddr_in6 *saddr =
reinterpret_cast<const sockaddr_in6 *>(&addr);
*out = SocketAddress(IPAddress(saddr->sin6_addr),
NetworkToHost16(saddr->sin6_port));
return true;
}
return false;
}
}// namespace sled

View File

@@ -0,0 +1,16 @@
/**
* @author : {{NAME}} ({{EMAIL}})
* @file : {{FILE}}
* @created : {{TIMESTAMP}}
*/
#include "sled/network/socket_server.h"
#include "sled/network/physical_socket_server.h"
namespace sled {
std::unique_ptr<sled::SocketServer>
CreateDefaultSocketServer()
{
return std::unique_ptr<sled::SocketServer>(new PhysicalSocketServer());
}
}// namespace sled