Documentation for module: Network

Former-commit-id: 0563349542b717b602d5a6eb7728bd40b2af7e1f
This commit is contained in:
Gawaboumga
2016-05-30 14:22:31 +02:00
parent 2c941827ed
commit 36c1ef1b97
25 changed files with 1368 additions and 25 deletions

View File

@@ -17,6 +17,18 @@
namespace Nz
{
/*!
* \ingroup network
* \class Nz::AbstractSocket
* \brief Network class that represents the base of socket
*
* \remark This class is abstract
*/
/*!
* \brief Constructs a AbstractSocket object with a type
*/
AbstractSocket::AbstractSocket(SocketType type) :
m_lastError(SocketError_NoError),
m_handle(SocketImpl::InvalidHandle),
@@ -26,6 +38,12 @@ namespace Nz
{
}
/*!
* \brief Constructs a AbstractSocket object with another one by move semantic
*
* \param abstractSocket AbstractSocket to move into this
*/
AbstractSocket::AbstractSocket(AbstractSocket&& abstractSocket) :
m_protocol(abstractSocket.m_protocol),
m_lastError(abstractSocket.m_lastError),
@@ -37,11 +55,21 @@ namespace Nz
abstractSocket.m_handle = SocketImpl::InvalidHandle;
}
/*!
* \brief Destructs the object and calls Close
*
* \see Close
*/
AbstractSocket::~AbstractSocket()
{
Close();
}
/*!
* \brief Closes the socket
*/
void AbstractSocket::Close()
{
if (m_handle != SocketImpl::InvalidHandle)
@@ -53,6 +81,12 @@ namespace Nz
}
}
/*!
* \brief Enables blocking
*
* \param blocking Should the read block
*/
void AbstractSocket::EnableBlocking(bool blocking)
{
if (m_isBlockingEnabled != blocking)
@@ -64,6 +98,11 @@ namespace Nz
}
}
/*!
* \brief Queries the available bytes
* \return Number of bytes which can be read
*/
std::size_t AbstractSocket::QueryAvailableBytes() const
{
if (m_handle == SocketImpl::InvalidHandle)
@@ -72,11 +111,21 @@ namespace Nz
return SocketImpl::QueryAvailableBytes(m_handle);
}
/*!
* \brief Operation to do when closing socket
*/
void AbstractSocket::OnClose()
{
UpdateState(SocketState_NotConnected);
}
/*!
* \brief Operation to do when opening socket
*
* \remark Produces a NazaraWarning if blocking failed
*/
void AbstractSocket::OnOpened()
{
SocketError errorCode;
@@ -84,6 +133,11 @@ namespace Nz
NazaraWarning("Failed to set socket blocking mode (0x" + String::Number(errorCode, 16) + ')');
}
/*!
* \brief Opens the socket according to a net protocol
* \return true If successful
*/
bool AbstractSocket::Open(NetProtocol protocol)
{
if (m_handle == SocketImpl::InvalidHandle || m_protocol != protocol)
@@ -99,6 +153,13 @@ namespace Nz
return true;
}
/*!
* \brief Opens the socket according to a socket handle
* \return true If successful
*
* \remark Produces a NazaraAssert if handle is invalid
*/
void AbstractSocket::Open(SocketHandle handle)
{
NazaraAssert(handle != SocketImpl::InvalidHandle, "Invalid handle");
@@ -109,6 +170,13 @@ namespace Nz
OnOpened();
}
/*!
* \brief Moves the AbstractSocket into this
* \return A reference to this
*
* \param abstractSocket AbstractSocket to move in this
*/
AbstractSocket& AbstractSocket::operator=(AbstractSocket&& abstractSocket)
{
Close();

View File

@@ -11,6 +11,15 @@ namespace Nz
{
namespace Detail
{
/*!
* \brief Parses a decimal number
* \return true If successful
*
* \param str C-string symbolizing the string to parse
* \param number Optional argument to return the number parsed
* \param endOfRead Optional argument to determine where parsing stopped
*/
bool ParseDecimal(const char* str, unsigned int* number, const char** endOfRead)
{
const char* ptr = str;
@@ -35,6 +44,15 @@ namespace Nz
return true;
}
/*!
* \brief Parses a hexadecimal number
* \return true If successful
*
* \param str C-string symbolizing the string to parse
* \param number Optional argument to return the number parsed
* \param endOfRead Optional argument to determine where parsing stopped
*/
bool ParseHexadecimal(const char* str, unsigned int* number, const char** endOfRead)
{
const char* ptr = str;
@@ -60,10 +78,26 @@ namespace Nz
}
}
// From http://rosettacode.org/wiki/Parse_an_IP_Address
// Parse a textual IPv4 or IPv6 address, optionally with port, into a binary
// array (for the address, in host order), and an optionally provided port.
// Also, indicate which of those forms (4 or 6) was parsed.
/*!
* \ingroup network
* \brief Parse a textual IPv4 or IPv6 address
* \return true If successful
*
* From http://rosettacode.org/wiki/Parse_an_IP_Address
* Parse a textual IPv4 or IPv6 address, optionally with port, into a binary
* array (for the address, in host order), and an optionally provided port.
* Also, indicate which of those forms (4 or 6) was parsed.
*
* \param addressPtr C-string which symbolizes the ip adress
* \param result Byte array to return the result in
* \param port Optional argument to resolve according to a specific port
* \param isIPv6 Optional argument to determine if the address is IPv6
* \param endOfRead Optional argument to determine where parsing stopped
*
* \remark Produces a NazaraAssert if addressPtr is invalid
* \remark Produces a NazaraAssert if result is invalid
*/
bool ParseIPAddress(const char* addressPtr, UInt8 result[16], UInt16* port, bool* isIPv6, const char** endOfRead)
{
NazaraAssert(addressPtr, "Invalid address string");

View File

@@ -22,6 +22,19 @@
namespace Nz
{
/*!
* \ingroup network
* \class Nz::IpAddress
* \brief Network class that represents an IP address
*/
/*!
* \brief Builds the IP from a hostname
* \return true If successful
*
* \remark address C-string symbolizing the IP address or hostname
*/
bool IpAddress::BuildFromAddress(const char* address)
{
m_isValid = false;
@@ -50,6 +63,13 @@ namespace Nz
return true;
}
/*!
* \brief Checks whether the IP address is loopback
* \return true If it is the case
*
* \remark Produces a NazaraAssert if internal protocol is invalid (should never happen)
*/
bool IpAddress::IsLoopback() const
{
if (!m_isValid)
@@ -73,6 +93,13 @@ namespace Nz
return false;
}
/*!
* \brief Gives a string representation
* \return A string representation of the object
*
* \remark Produces a NazaraAssert if internal protocol is invalid (should never happen)
*/
String IpAddress::ToString() const
{
StringStream stream;
@@ -153,6 +180,17 @@ namespace Nz
return stream;
}
/*!
* \brief Resolves the address based on the IP
* \return Hostname of the address
*
* \param address IP address to resolve
* \param service Optional argument to specify the protocol used
* \param error Optional argument to get the error
*
* \remark Produces a NazaraAssert if address is invalid
*/
String IpAddress::ResolveAddress(const IpAddress& address, String* service, ResolveError* error)
{
NazaraAssert(address.IsValid(), "Invalid address");
@@ -163,6 +201,18 @@ namespace Nz
return hostname;
}
/*!
* \brief Resolves the address based on the hostname
* \return Informations about the host: IP(s) of the address, names, ...
*
* \param protocol Net protocol to use
* \param hostname Hostname to resolve
* \param service Specify the service used (http, ...)
* \param error Optional argument to get the error
*
* \remark Produces a NazaraAssert if net protocol is set to unknown
*/
std::vector<HostnameInfo> IpAddress::ResolveHostname(NetProtocol protocol, const String& hostname, const String& service, ResolveError* error)
{
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");

View File

@@ -9,11 +9,36 @@
namespace Nz
{
/*!
* \ingroup network
* \class Nz::NetPacket
* \brief Network class that represents a packet
*/
/*!
* \brief Operation to do when receiving data
*
* \param netCode Packet number
* \param data Raw memory
* \param size Size of the memory
*/
void NetPacket::OnReceive(UInt16 netCode, const void* data, std::size_t size)
{
Reset(netCode, data, size);
}
/*!
* \brief Operation to do when sending data
* \return Beggining of the raw memory
*
* \param newSize Size of the memory to send
*
* \remark Produces a NazaraAssert if newSize is invalid
* \remark Produces a NazaraAssert if net code is invalid
* \remark Produces a NazaraError if header could not be encoded
*/
const void* NetPacket::OnSend(std::size_t* newSize) const
{
NazaraAssert(newSize, "Invalid size pointer");
@@ -30,6 +55,15 @@ namespace Nz
return m_buffer->GetBuffer();
}
/*!
* \brief Decodes the header of the packet
* \return true If successful
*
* \param data Raw memory
* \param packetSize Size of the packet
* \param netCode Packet number
*/
bool NetPacket::DecodeHeader(const void* data, UInt16* packetSize, UInt16* netCode)
{
MemoryView stream(data, HeaderSize);
@@ -40,6 +74,15 @@ namespace Nz
return Unserialize(context, packetSize) && Unserialize(context, netCode);
}
/*!
* \brief Encodes the header of the packet
* \return true If successful
*
* \param data Raw memory
* \param packetSize Size of the packet
* \param netCode Packet number
*/
bool NetPacket::EncodeHeader(void* data, UInt16 packetSize, UInt16 netCode)
{
MemoryView stream(data, HeaderSize);
@@ -50,11 +93,19 @@ namespace Nz
return Serialize(context, packetSize) && Serialize(context, netCode);
}
/*!
* \brief Operation to do when stream is empty
*/
void NetPacket::OnEmptyStream()
{
Reset(0);
}
/*!
* \brief Frees the stream
*/
void NetPacket::FreeStream()
{
if (!m_buffer)
@@ -66,6 +117,16 @@ namespace Nz
s_availableBuffers.emplace_back(std::make_pair(size, std::move(m_buffer)));
}
/*!
* \brief Inits the internal stream
*
* \param minCapacity Minimal capacity of the stream
* \param cursorPos Position of the cursor in the stream
* \param openMode Flag of the stream
*
* \remark Produces a NazaraAssert if cursor position is greather than the capacity
*/
void NetPacket::InitStream(std::size_t minCapacity, UInt64 cursorPos, UInt32 openMode)
{
NazaraAssert(minCapacity >= cursorPos, "Cannot init stream with a smaller capacity than wanted cursor pos");
@@ -92,12 +153,21 @@ namespace Nz
SetStream(&m_memoryStream);
}
/*!
* \brief Initializes the NetPacket class
* \return true If initialization is successful
*/
bool NetPacket::Initialize()
{
s_availableBuffersMutex = std::make_unique<Mutex>();
return true;
}
/*!
* \brief Uninitializes the NetPacket class
*/
void NetPacket::Uninitialize()
{
s_availableBuffers.clear();

View File

@@ -24,9 +24,23 @@
namespace Nz
{
/*!
* \ingroup network
* \class Nz::Network
* \brief Network class that represents the module initializer of Network
*/
/*!
* \brief Initializes the Network module
* \return true if initialization is successful
*
* \remark Produces a NazaraNotice
* \remark Produces a NazaraError if one submodule failed
*/
bool Network::Initialize()
{
if (s_moduleReferenceCounter > 0)
if (IsInitialized())
{
s_moduleReferenceCounter++;
return true; // Already initialized
@@ -68,11 +82,22 @@ namespace Nz
return true;
}
/*!
* \brief Checks whether the module is initialized
* \return true if module is initialized
*/
bool Network::IsInitialized()
{
return s_moduleReferenceCounter != 0;
}
/*!
* \brief Uninitializes the Core module
*
* \remark Produces a NazaraNotice
*/
void Network::Uninitialize()
{
if (s_moduleReferenceCounter != 1)

View File

@@ -10,6 +10,16 @@
namespace Nz
{
/*!
* \ingroup network
* \class Nz::RUdpConnection
* \brief Network class that represents a reliable UDP connection
*/
/*!
* \brief Constructs a RUdpConnection object by default
*/
RUdpConnection::RUdpConnection() :
m_peerIterator(0),
m_forceAckSendTime(10'000), //< 10ms
@@ -23,9 +33,20 @@ namespace Nz
{
}
/*!
* \brief Connects to the IpAddress
* \return true
*
* \param remoteAddress Address to connect to
*
* \remark Produces a NazaraAssert if socket is not bound
* \remark Produces a NazaraAssert if remote is invalid
* \remark Produces a NazaraAssert if port is not specified
*/
bool RUdpConnection::Connect(const IpAddress& remoteAddress)
{
NazaraAssert(m_socket.GetState() != SocketState_Bound, "Socket must be bound first");
NazaraAssert(m_socket.GetState() == SocketState_Bound, "Socket must be bound first");
NazaraAssert(remoteAddress.IsValid(), "Invalid remote address");
NazaraAssert(remoteAddress.GetPort() != 0, "Remote address has no port");
@@ -39,6 +60,16 @@ namespace Nz
return true;
}
/*!
* \brief Connects to the hostname
* \return true If successful
*
* \param hostName Hostname of the remote
* \param protocol Net protocol to use
* \param service Specify the protocol used
* \param error Optional argument to get the error
*/
bool RUdpConnection::Connect(const String& hostName, NetProtocol protocol, const String& service, ResolveError* error)
{
std::vector<HostnameInfo> results = IpAddress::ResolveHostname(protocol, hostName, service, error);
@@ -64,6 +95,13 @@ namespace Nz
return Connect(hostnameAddress);
}
/*!
* \brief Listens to a socket
* \return true If successfully bound
*
* \param remoteAddress Address to listen to
*/
bool RUdpConnection::Listen(const IpAddress& address)
{
if (!InitSocket(address.GetProtocol()))
@@ -72,8 +110,19 @@ namespace Nz
return m_socket.Bind(address) == SocketState_Bound;
}
/*!
* \brief Polls the message
* \return true If there is a message
*
* \param message Message to poll
*
* \remark Produces a NazaraAssert if message is invalid
*/
bool RUdpConnection::PollMessage(RUdpMessage* message)
{
NazaraAssert(message, "Invalid message");
if (m_receivedMessages.empty())
return false;
@@ -82,6 +131,16 @@ namespace Nz
return true;
}
/*!
* \brief Sends the packet to a peer
* \return true If peer exists (false may result from disconnected client)
*
* \param peerIp IpAddress of the peer
* \param priority Priority of the packet
* \param reliability Policy of reliability of the packet
* \param packet Packet to send
*/
bool RUdpConnection::Send(const IpAddress& peerIp, PacketPriority priority, PacketReliability reliability, const NetPacket& packet)
{
auto it = m_peerByIP.find(peerIp);
@@ -92,6 +151,10 @@ namespace Nz
return true;
}
/*!
* \brief Updates the reliable connection
*/
void RUdpConnection::Update()
{
m_currentTime = m_clock.GetMicroseconds();
@@ -156,6 +219,14 @@ namespace Nz
//m_activeClients.Reset();
}
/*!
* \brief Disconnects a peer
*
* \param peerIndex Index of the peer
*
* \remark Produces a NazaraNotice
*/
void RUdpConnection::DisconnectPeer(std::size_t peerIndex)
{
PeerData& peer = m_peers[peerIndex];
@@ -193,6 +264,15 @@ namespace Nz
m_peers.pop_back();
}
/*!
* \brief Enqueues a packet in the sending list
*
* \param peer Data relative to the peer
* \param priority Priority of the packet
* \param reliability Policy of reliability of the packet
* \param packet Packet to send
*/
void RUdpConnection::EnqueuePacket(PeerData& peer, PacketPriority priority, PacketReliability reliability, const NetPacket& packet)
{
UInt16 protocolBegin = static_cast<UInt16>(m_protocol & 0xFFFF);
@@ -208,6 +288,15 @@ namespace Nz
EnqueuePacketInternal(peer, priority, reliability, std::move(data));
}
/*!
* \brief Enqueues internally a packet in the sending list
*
* \param peer Data relative to the peer
* \param priority Priority of the packet
* \param reliability Policy of reliability of the packet
* \param packet Packet to send
*/
void RUdpConnection::EnqueuePacketInternal(PeerData& peer, PacketPriority priority, PacketReliability reliability, NetPacket&& data)
{
PendingPacket pendingPacket;
@@ -219,6 +308,13 @@ namespace Nz
m_activeClients.UnboundedSet(peer.index);
}
/*!
* \brief Inits the internal socket
* \return true If successful
*
* \param protocol Net protocol to use
*/
bool RUdpConnection::InitSocket(NetProtocol protocol)
{
CallOnExit updateLastError([this]
@@ -233,6 +329,14 @@ namespace Nz
return true;
}
/*!
* \brief Processes the acks
*
* \param peer Data relative to the peer
* \param lastAck Last index of the ack
* \param ackBits Bits for acking
*/
void RUdpConnection::ProcessAcks(PeerData& peer, SequenceIndex lastAck, UInt32 ackBits)
{
auto it = peer.pendingAckQueue.begin();
@@ -257,6 +361,14 @@ namespace Nz
}
}
/*!
* \brief Registers a peer
* \return Data relative to the peer
*
* \param address Address of the peer
* \param state Status of the peer
*/
RUdpConnection::PeerData& RUdpConnection::RegisterPeer(const IpAddress& address, PeerState state)
{
PeerData data;
@@ -266,7 +378,7 @@ namespace Nz
data.index = m_peers.size();
data.lastPacketTime = m_currentTime;
data.lastPingTime = m_currentTime;
data.roundTripTime = 1000000; ///< Okay that's quite a lot
data.roundTripTime = 1'000'000; ///< Okay that's quite a lot
data.state = state;
m_activeClients.UnboundedSet(data.index);
@@ -276,6 +388,14 @@ namespace Nz
return m_peers.back();
}
/*!
* \brief Operation to do when client requests a connection
*
* \param address Address of the peer
* \param sequenceId Sequence index for the ack
* \param token Token for connection
*/
void RUdpConnection::OnClientRequestingConnection(const IpAddress& address, SequenceIndex sequenceId, UInt64 token)
{
// Call hook to check if client should be accepted or not
@@ -292,6 +412,13 @@ namespace Nz
EnqueuePacket(client, PacketPriority_Immediate, PacketReliability_Reliable, connectionAcceptedPacket);
}
/*!
* \brief Operation to do when a packet is lost
*
* \param peer Data relative to the peer
* \param packet Pending packet
*/
void RUdpConnection::OnPacketLost(PeerData& peer, PendingAckPacket&& packet)
{
//NazaraNotice(m_socket.GetBoundAddress().ToString() + ": Lost packet " + String::Number(packet.sequenceId));
@@ -300,6 +427,14 @@ namespace Nz
EnqueuePacketInternal(peer, packet.priority, packet.reliability, std::move(packet.data));
}
/*!
* \brief Operation to do when receiving a packet
*
* \param peerIndex Index of the peer
*
* \remark Produces a NazaraNotice
*/
void RUdpConnection::OnPacketReceived(const IpAddress& peerIp, NetPacket&& packet)
{
UInt16 protocolBegin;
@@ -436,6 +571,13 @@ namespace Nz
}
}
/*!
* \brief Sends a packet to a peer
*
* \param peer Data relative to the peer
* \param packet Pending packet
*/
void RUdpConnection::SendPacket(PeerData& peer, PendingPacket&& packet)
{
if (peer.state == PeerState_WillAck)
@@ -448,7 +590,7 @@ namespace Nz
{
if (ack == remoteSequence)
continue;
unsigned int difference = ComputeSequenceDifference(remoteSequence, ack);
if (difference <= 32U)
previousAcks |= (1U << (difference - 1));
@@ -473,6 +615,11 @@ namespace Nz
peer.pendingAckQueue.emplace_back(std::move(pendingAckPacket));
}
/*!
* \brief Initializes the RUdpConnection class
* \return true
*/
bool RUdpConnection::Initialize()
{
std::random_device device;
@@ -481,6 +628,10 @@ namespace Nz
return true;
}
/*!
* \brief Uninitializes the RUdpConnection class
*/
void RUdpConnection::Uninitialize()
{
}

View File

@@ -20,6 +20,22 @@
namespace Nz
{
/*!
* \ingroup network
* \class Nz::TcpClient
* \brief Network class that represents a client in a TCP connection
*/
/*!
* \brief Connects to the IpAddress
* \return State of the socket
*
* \param remoteAddress Address to connect to
*
* \remark Produces a NazaraAssert if remote is invalid
* \remark Produces a NazaraAssert if remote's port is not specified
*/
SocketState TcpClient::Connect(const IpAddress& remoteAddress)
{
NazaraAssert(remoteAddress.IsValid(), "Invalid remote address");
@@ -45,6 +61,17 @@ namespace Nz
return state;
}
/*!
* \brief Connects to the hostname
* \return State of the socket
*
* \param hostName Hostname of the remote
* \param protocol Net protocol to use
* \param service Specify the protocol used
* \param error Optional argument to get the error
*/
SocketState TcpClient::Connect(const String& hostName, NetProtocol protocol, const String& service, ResolveError* error)
{
UpdateState(SocketState_Resolving);
@@ -73,6 +100,14 @@ namespace Nz
return Connect(hostnameAddress);
}
/*!
* \brief Enables low delay in emitting
*
* \param lowDelay Should low delay be used
*
* \remark This may produce lag
*/
void TcpClient::EnableLowDelay(bool lowDelay)
{
if (m_isLowDelayEnabled != lowDelay)
@@ -84,6 +119,14 @@ namespace Nz
}
}
/*!
* \brief Enables the keep alive flag
*
* \param keepAlive Should the connection be kept alive
* \param msTime Time in milliseconds before expiration
* \param msInterval Interval in milliseconds between two pings
*/
void TcpClient::EnableKeepAlive(bool keepAlive, UInt64 msTime, UInt64 msInterval)
{
if (m_isKeepAliveEnabled != keepAlive || m_keepAliveTime != msTime || m_keepAliveInterval != msInterval)
@@ -97,22 +140,51 @@ namespace Nz
}
}
/*!
* \brief Checks whether the stream reached the end of the stream
* \return true if there is no more available bytes
*/
bool TcpClient::EndOfStream() const
{
return QueryAvailableBytes() == 0;
}
/*!
* \brief Gets the position of the cursor
* \return 0
*
* \remark Produces a NazaraError because it is a special stream
*/
UInt64 TcpClient::GetCursorPos() const
{
NazaraError("GetCursorPos() cannot be used on sequential streams");
return 0;
}
/*!
* \brief Gets the size of the raw memory available
* \return Size of the memory available
*/
UInt64 TcpClient::GetSize() const
{
return QueryAvailableBytes();
}
/*!
* \brief Receives the data available
* \return true If data received
*
* \param buffer Raw memory to write
* \param size Size of the buffer
* \param received Optional argument to get the number of bytes received
*
* \remark Produces a NazaraAssert if socket is invalid
* \remark Produces a NazaraAssert if buffer and its size is invalid
*/
bool TcpClient::Receive(void* buffer, std::size_t size, std::size_t* received)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
@@ -142,6 +214,17 @@ namespace Nz
return true;
}
/*!
* \brief Receives the packet available
* \return true If packet received
*
* \param packet Packet to receive
*
* \remark Produces a NazaraAssert if packet is invalid
* \remark Produces a NazaraAssert if packet size is inferior to the header size
* \remark Produces a NazaraWarning if packet's header is invalid
*/
bool TcpClient::ReceivePacket(NetPacket* packet)
{
//TODO: Every packet requires at least two Receive call, using an internal buffer of a fixed size would prevent this
@@ -157,6 +240,7 @@ namespace Nz
m_pendingPacket.received += received;
//TODO: Should never happen in production !
NazaraAssert(m_pendingPacket.received <= NetPacket::HeaderSize, "Received more data than header size");
if (m_pendingPacket.received >= NetPacket::HeaderSize)
{
@@ -185,6 +269,7 @@ namespace Nz
m_pendingPacket.received += received;
//TODO: Should never happen in production !
NazaraAssert(m_pendingPacket.received <= packetSize, "Received more data than packet size");
if (m_pendingPacket.received >= packetSize)
{
@@ -202,6 +287,19 @@ namespace Nz
return false;
}
/*!
* \brief Sends the data available
* \return true If data sended
*
* \param buffer Raw memory to read
* \param size Size of the buffer
* \param sent Optional argument to get the number of bytes sent
*
* \remark Large sending are handled, you do not need to call this multiple time
* \remark Produces a NazaraAssert if socket is invalid
* \remark Produces a NazaraAssert if buffer and its size is invalid
*/
bool TcpClient::Send(const void* buffer, std::size_t size, std::size_t* sent)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
@@ -244,6 +342,15 @@ namespace Nz
return true;
}
/*!
* \brief Sends the packet available
* \return true If packet sent
*
* \param packet Packet to send
*
* \remark Produces a NazaraError if packet could not be prepared for sending
*/
bool TcpClient::SendPacket(const NetPacket& packet)
{
std::size_t size = 0;
@@ -258,12 +365,30 @@ namespace Nz
return Send(ptr, size, nullptr);
}
/*!
* \brief Sets the position of the cursor
* \return false
*
* \param offset Offset according to the beginning of the stream
*
* \remark Produces a NazaraError because it is a special stream
*/
bool TcpClient::SetCursorPos(UInt64 offset)
{
NazaraError("SetCursorPos() cannot be used on sequential streams");
return false;
}
/*!
* \brief Waits for being connected before time out
* \return true If connection is successful
*
* \param msTimeout Time in milliseconds before time out
*
* \remark Produces a NazaraAssert if socket is invalid
*/
bool TcpClient::WaitForConnected(UInt64 msTimeout)
{
switch (m_state)
@@ -308,10 +433,18 @@ namespace Nz
return false;
}
/*!
* \brief Flushes the stream
*/
void TcpClient::FlushStream()
{
}
/*!
* \brief Operation to do when closing socket
*/
void TcpClient::OnClose()
{
AbstractSocket::OnClose();
@@ -320,6 +453,12 @@ namespace Nz
m_peerAddress = IpAddress::Invalid;
}
/*!
* \brief Operation to do when opening socket
*
* \remark Produces a NazaraWarning if delay mode or keep alive failed
*/
void TcpClient::OnOpened()
{
AbstractSocket::OnOpened();
@@ -336,6 +475,16 @@ namespace Nz
m_openMode = OpenMode_ReadWrite;
}
/*!
* \brief Reads blocks
* \return Number of blocks read
*
* \param buffer Preallocated buffer to contain information read
* \param size Size of the read and thus of the buffer
*
* \remark Produces a NazaraAssert if socket is invalid
*/
std::size_t TcpClient::ReadBlock(void* buffer, std::size_t size)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
@@ -357,6 +506,13 @@ namespace Nz
return received;
}
/*!
* \brief Resets the connection with a new socket and a peer address
*
* \param handle Socket to connect
* \param peerAddress Address to connect to
*/
void TcpClient::Reset(SocketHandle handle, const IpAddress& peerAddress)
{
Open(handle);
@@ -365,8 +521,20 @@ namespace Nz
UpdateState(SocketState_Connected);
}
/*!
* \brief Writes blocks
* \return Number of blocks written
*
* \param buffer Preallocated buffer containing information to write
* \param size Size of the writting and thus of the buffer
*
* \remark Produces a NazaraAssert if buffer is nullptr
* \remark Produces a NazaraAssert if socket is invalid
*/
std::size_t TcpClient::WriteBlock(const void* buffer, std::size_t size)
{
NazaraAssert(buffer, "Invalid buffer");
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
CallOnExit restoreBlocking;

View File

@@ -19,6 +19,22 @@
namespace Nz
{
/*!
* \ingroup network
* \class Nz::TcpServer
* \brief Network class that represents a server in a TCP connection
*/
/*!
* \brief Accepts a client
* \return true If client'socket is valid
*
* \param newClient Client connection
*
* \remark Produces a NazaraAssert if socket is invalid
* \remark Produces a NazaraAssert if newClient is invalid
*/
bool TcpServer::AcceptClient(TcpClient* newClient)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Server isn't listening");
@@ -35,6 +51,16 @@ namespace Nz
return false;
}
/*!
* \brief Listens to a socket
* \return State of the socket
*
* \param address Address to listen to
* \param queueSize Size of the queue
*
* \remark Produces a NazaraAssert if address is invalid
*/
SocketState TcpServer::Listen(const IpAddress& address, unsigned int queueSize)
{
NazaraAssert(address.IsValid(), "Invalid address");
@@ -49,6 +75,10 @@ namespace Nz
return state;
}
/*!
* \brief Operation to do when closing socket
*/
void TcpServer::OnClose()
{
AbstractSocket::OnClose();
@@ -56,6 +86,10 @@ namespace Nz
m_boundAddress = IpAddress::Invalid;
}
/*!
* \brief Operation to do when opening socket
*/
void TcpServer::OnOpened()
{
AbstractSocket::OnOpened();

View File

@@ -17,6 +17,16 @@
namespace Nz
{
/*!
* \brief Binds a specific IpAddress
* \return State of the socket
*
* \param address Address to bind
*
* \remark Produces a NazaraAssert if socket is invalid
* \remark Produces a NazaraAssert if address is invalid
*/
SocketState UdpSocket::Bind(const IpAddress& address)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket hasn't been created");
@@ -30,6 +40,14 @@ namespace Nz
return state;
}
/*!
* \brief Enables broadcasting
*
* \param broadcasting Should the UDP broadcast
*
* \remark Produces a NazaraAssert if socket is invalid
*/
void UdpSocket::EnableBroadcasting(bool broadcasting)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
@@ -41,6 +59,13 @@ namespace Nz
}
}
/*!
* \brief Gets the maximum datagram size allowed
* \return Number of bytes
*
* \remark Produces a NazaraAssert if socket is invalid
*/
std::size_t UdpSocket::QueryMaxDatagramSize()
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket hasn't been created");
@@ -48,8 +73,22 @@ namespace Nz
return SocketImpl::QueryMaxDatagramSize(m_handle, &m_lastError);
}
/*!
* \brief Receives the data available
* \return true If data received
*
* \param buffer Raw memory to write
* \param size Size of the buffer
* \param from IpAddress of the peer
* \param received Optional argument to get the number of bytes received
*
* \remark Produces a NazaraAssert if socket is invalid
* \remark Produces a NazaraAssert if buffer and its size is invalid
*/
bool UdpSocket::Receive(void* buffer, std::size_t size, IpAddress* from, std::size_t* received)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket hasn't been created");
NazaraAssert(buffer && size > 0, "Invalid buffer");
int read;
@@ -62,8 +101,21 @@ namespace Nz
return true;
}
/*!
* \brief Receives the packet available
* \return true If packet received
*
* \param packet Packet to receive
* \param from IpAddress of the peer
*
* \remark Produces a NazaraAssert if packet is invalid
* \remark Produces a NazaraWarning if packet's header is invalid
*/
bool UdpSocket::ReceivePacket(NetPacket* packet, IpAddress* from)
{
NazaraAssert(packet, "Invalid packet");
// I'm not sure what's the best between having a 65k bytes buffer ready for any datagram size
// or querying the next datagram size every time, for now I'll leave it as is
packet->Reset(NetCode_Invalid, std::numeric_limits<UInt16>::max());
@@ -97,6 +149,20 @@ namespace Nz
return true;
}
/*!
* \brief Sends the data available
* \return true If data sended
*
* \param to IpAddress of the peer
* \param buffer Raw memory to read
* \param size Size of the buffer
* \param sent Optional argument to get the number of bytes sent
*
* \remark Produces a NazaraAssert if peer address is invalid
* \remark Produces a NazaraAssert if protocol of communication is not the same than the peer
* \remark Produces a NazaraAssert if buffer and its size is invalid
*/
bool UdpSocket::Send(const IpAddress& to, const void* buffer, std::size_t size, std::size_t* sent)
{
NazaraAssert(to.IsValid(), "Invalid ip address");
@@ -113,6 +179,16 @@ namespace Nz
return true;
}
/*!
* \brief Sends the packet available
* \return true If packet sent
*
* \param to IpAddress of the peer
* \param packet Packet to send
*
* \remark Produces a NazaraError if packet could not be prepared for sending
*/
bool UdpSocket::SendPacket(const IpAddress& to, const NetPacket& packet)
{
std::size_t size = 0;
@@ -127,6 +203,10 @@ namespace Nz
return Send(to, ptr, size, nullptr);
}
/*!
* \brief Operation to do when closing socket
*/
void UdpSocket::OnClose()
{
AbstractSocket::OnClose();
@@ -134,6 +214,10 @@ namespace Nz
m_boundAddress = IpAddress::Invalid;
}
/*!
* \brief Operation to do when opening socket
*/
void UdpSocket::OnOpened()
{
AbstractSocket::OnOpened();