diff options
Diffstat (limited to 'source/core/StarUdp.cpp')
-rw-r--r-- | source/core/StarUdp.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/source/core/StarUdp.cpp b/source/core/StarUdp.cpp new file mode 100644 index 0000000..9ff7b48 --- /dev/null +++ b/source/core/StarUdp.cpp @@ -0,0 +1,84 @@ +#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(); +} + +} |