osb/source/core/StarUdp.cpp
2023-06-20 14:33:09 +10:00

85 lines
2.3 KiB
C++

#include "StarUdp.hpp"
#include "StarLogging.hpp"
#include "StarNetImpl.hpp"
namespace Star {
UdpSocket::UdpSocket(NetworkMode networkMode) : Socket(SocketType::Udp, networkMode) {}
size_t UdpSocket::receive(HostAddressWithPort* address, char* data, size_t datasize) {
ReadLocker locker(m_mutex);
checkOpen("UdpSocket::receive");
int flags = 0;
int len;
struct sockaddr_storage sockAddr;
socklen_t sockAddrLen = sizeof(sockAddr);
len = ::recvfrom(m_impl->socketDesc, data, datasize, flags, (struct sockaddr*)&sockAddr, &sockAddrLen);
if (len < 0) {
if (!isActive())
throw SocketClosedException("Connection closed");
else if (netErrorInterrupt())
len = 0;
else
throw NetworkException(strf("udp recv error: %s", netErrorString()));
}
if (address)
setAddressFromNative(*address, m_localAddress.address().mode(), &sockAddr);
return len;
}
size_t UdpSocket::send(HostAddressWithPort const& address, char const* data, size_t size) {
ReadLocker locker(m_mutex);
checkOpen("UdpSocket::send");
struct sockaddr_storage sockAddr;
socklen_t sockAddrLen;
setNativeFromAddress(address, &sockAddr, &sockAddrLen);
int len = ::sendto(m_impl->socketDesc, data, size, 0, (struct sockaddr*)&sockAddr, sockAddrLen);
if (len < 0) {
if (!isActive())
throw SocketClosedException("Connection closed");
else if (netErrorInterrupt())
len = 0;
else
throw NetworkException(strf("udp send error: %s", netErrorString()));
}
return len;
}
UdpServer::UdpServer(HostAddressWithPort const& address)
: m_hostAddress(address), m_listenSocket(make_shared<UdpSocket>(m_hostAddress.address().mode())) {
m_listenSocket->setNonBlocking(true);
m_listenSocket->bind(m_hostAddress);
Logger::debug("UdpServer listening on: %s", m_hostAddress);
}
UdpServer::~UdpServer() {
close();
}
size_t UdpServer::receive(HostAddressWithPort* address, char* data, size_t bufsize, unsigned timeout) {
Socket::poll({{m_listenSocket, {true, false}}}, timeout);
return m_listenSocket->receive(address, data, bufsize);
}
size_t UdpServer::send(HostAddressWithPort const& address, char const* data, size_t len) {
return m_listenSocket->send(address, data, len);
}
void UdpServer::close() {
m_listenSocket->close();
}
bool UdpServer::isListening() const {
return m_listenSocket->isActive();
}
}