/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuNetSrvSockets.cpp Date: 2022-8-16 Author: Reece ***/ #include "Networking.hpp" #include "AuNetSrvSockets.hpp" #include "AuNetInterface.hpp" #include "AuNetWorker.hpp" #include "AuNetSocket.hpp" #include "AuNetSocketServer.hpp" #include "SocketOverDatagram/SocketOverDatagram.hpp" namespace Aurora::IO::Net { NetSrvSockets::NetSrvSockets(NetInterface *pParent) : pParent_(pParent) { } AuSPtr NetSrvSockets::Connect(const NetSocketConnect &netConnect) { auto pWorker = this->pParent_->TryScheduleEx(); if (!pWorker) { SysPushErrorNet("No Worker"); return {}; } AuSPtr pSocket; if (netConnect.endpoint) { if (netConnect.endpoint.Value().transportProtocol != ETransportProtocol::eProtocolTCP) { SysPushErrorNet("Invalid transport protocol. Hint: Use ConnectManyEx for UDP."); return {}; } pSocket = AuMakeShared(this->pParent_, pWorker.get(), netConnect.pDriver, netConnect.endpoint.value()); } else { if (!netConnect.byHost.netHostname) { SysPushErrorArg("Missing hostname or endpoint"); return {}; } if (!netConnect.byHost.protocol) { SysPushErrorArg("Missing protocol"); return {}; } if (!netConnect.byHost.uPort) { SysPushErrorArg("Missing port"); return {}; } pSocket = AuMakeShared(this->pParent_, pWorker.get(), netConnect.pDriver, AuMakePair(netConnect.byHost.netHostname.value(), netConnect.byHost.uPort.value()), netConnect.byHost.protocol.value()); } if (!pSocket) { SysPushErrorNet("No Memory"); return {}; } if (!pWorker->TryScheduleInternalTemplate([=](const AuSPtr> &info) { pSocket->FinishConstructAsync(); if (pSocket->bResolving_) { return; } if (!pSocket->IsValid()) { pSocket->SendErrorNoStream({}); return; } if (!pSocket->Connect(pSocket->GetRemoteEndpoint())) { SysPushErrorIO("An asynchronous connect failed [root level]"); } }, AuSPtr>{})) { return {}; } return pSocket; } AuSPtr NetSrvSockets::ConnectMany(const NetSocketConnectMany &netConnectMany) { if (netConnectMany.protocol != ETransportProtocol::eProtocolTCP) { SysPushErrorNet("Invalid transport protocol. Hint: Use ConnectManyEx for UDP."); return {}; } auto pWorker = this->pParent_->TryScheduleEx(); if (!pWorker) { SysPushErrorNet("No Worker"); return {}; } auto pSocket = AuMakeShared(this->pParent_, pWorker.get(), netConnectMany.pDriver, netConnectMany); if (!pSocket) { SysPushErrorNet("No Memory"); return {}; } if (!pWorker->TryScheduleInternalTemplate([=](const AuSPtr> &info) { pSocket->FinishConstructAsync(); if (!pSocket->IsValid()) { pSocket->SendErrorNoStream({}); return; } if (!pSocket->ConnectNext()) { SysPushErrorIO("An asynchronous connect failed [root level]"); } }, AuSPtr>{})) { return {}; } return pSocket; } AuSPtr NetSrvSockets::NewServer(const NetSocketBind &netBind) { auto uMaxSockets = netBind.uMaxConnections ? netBind.uMaxConnections : 512; auto pWorker = this->pParent_->TryScheduleEx(); if (!pWorker) { SysPushErrorNet("No Worker"); return {}; } if (netBind.protocol == ETransportProtocol::eProtocolUDP) { auto pSocket = AuMakeShared(this->pParent_, pWorker.get(), netBind.pDriver, netBind.pFactory, uMaxSockets, 0, AuSToMS(60), netBind.bMultiThreaded, false, kDefaultStreamSize); if (!pSocket) { SysPushErrorNet("No Memory"); return {}; } if (!pSocket->Init()) { SysPushErrorNested("no socket"); return {}; } if (!pWorker->TryScheduleInternalTemplate([=](const AuSPtr> &info) { NetEndpoint endpoint; endpoint.ip = netBind.ip; endpoint.uPort = netBind.uPort; endpoint.transportProtocol = netBind.protocol; pSocket->Start(endpoint); }, AuSPtr>{})) { return {}; } return pSocket->ToSocketServer(); } if (netBind.protocol != ETransportProtocol::eProtocolTCP) { SysPushErrorNet("Unknown transport protocol"); return {}; } auto pSocket = AuMakeShared(this->pParent_, pWorker.get(), netBind.pDriver, netBind.pFactory, uMaxSockets, netBind.uDefaultInputStreamSize, netBind.bMultiThreaded); if (!pSocket) { SysPushErrorNet("No Memory"); return {}; } if (!pWorker->TryScheduleInternalTemplate([=](const AuSPtr> &info) { pSocket->FinishConstructAsync(); NetEndpoint endpoint; endpoint.ip = netBind.ip; endpoint.uPort = netBind.uPort; endpoint.transportProtocol = netBind.protocol; pSocket->Init(endpoint); pSocket->Listen(endpoint); pSocket->Accept(); }, AuSPtr>{})) { return {}; } return pSocket; } AuSPtr NetSrvSockets::NewServerEx(const NetSocketBindEx &netBindEx) { auto uMaxSockets = netBindEx.uMaxConnections ? netBindEx.uMaxConnections : 512; auto pWorker = this->pParent_->TryScheduleEx(); if (!pWorker) { SysPushErrorNet("No Worker"); return {}; } if (netBindEx.protocol == ETransportProtocol::eProtocolUDP) { auto pSocket = AuMakeShared(this->pParent_, pWorker.get(), netBindEx.pDriver, netBindEx.pFactory, uMaxSockets, 0, AuSToMS(netBindEx.uUDPTimeoutMs), netBindEx.bMultiThreaded, false, kDefaultStreamSize); if (!pSocket) { SysPushErrorNet("No Memory"); return {}; } if (!pSocket->Init()) { SysPushErrorNested("no socket"); return {}; } if (!pWorker->TryScheduleInternalTemplate([=](const AuSPtr> &info) { NetEndpoint endpoint; endpoint.ip = netBindEx.ip; endpoint.uPort = netBindEx.uPort; endpoint.transportProtocol = netBindEx.protocol; pSocket->Start(endpoint); }, AuSPtr>{})) { return {}; } return pSocket->ToSocketServer(); } if (netBindEx.protocol == ETransportProtocol::eProtocolTCP) { return this->NewServer(netBindEx); } return {}; } }