Network/TcpClient: Make TcpClient a Stream

Former-commit-id: 2176748166ae84b609d5a336495e6ff3550a765d
This commit is contained in:
Lynix 2015-11-23 18:22:12 +01:00
parent 6829863d81
commit 4721bf80c3
6 changed files with 93 additions and 10 deletions

View File

@ -55,7 +55,7 @@ namespace Nz
Stream& operator=(Stream&&) = default; Stream& operator=(Stream&&) = default;
protected: protected:
inline Stream(UInt32 openMode); inline Stream(UInt32 streamOptions = StreamOption_None, UInt32 openMode = OpenMode_NotOpen);
virtual void FlushStream() = 0; virtual void FlushStream() = 0;
virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0; virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0;

View File

@ -7,9 +7,9 @@
namespace Nz namespace Nz
{ {
inline Stream::Stream(UInt32 openMode) : inline Stream::Stream(UInt32 streamOptions, UInt32 openMode) :
m_openMode(openMode), m_openMode(openMode),
m_streamOptions(0) m_streamOptions(streamOptions)
{ {
} }

View File

@ -9,12 +9,13 @@
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Signal.hpp> #include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Network/AbstractSocket.hpp> #include <Nazara/Network/AbstractSocket.hpp>
#include <Nazara/Network/IpAddress.hpp> #include <Nazara/Network/IpAddress.hpp>
namespace Nz namespace Nz
{ {
class NAZARA_NETWORK_API TcpClient : public AbstractSocket class NAZARA_NETWORK_API TcpClient : public AbstractSocket, public Stream
{ {
friend class TcpServer; friend class TcpServer;
@ -30,9 +31,13 @@ namespace Nz
void EnableLowDelay(bool lowDelay); void EnableLowDelay(bool lowDelay);
void EnableKeepAlive(bool keepAlive, UInt64 msTime = 10000, UInt64 msInterval = 1000); void EnableKeepAlive(bool keepAlive, UInt64 msTime = 10000, UInt64 msInterval = 1000);
bool EndOfStream() const override;
UInt64 GetCursorPos() const override;
inline UInt64 GetKeepAliveInterval() const; inline UInt64 GetKeepAliveInterval() const;
inline UInt64 GetKeepAliveTime() const; inline UInt64 GetKeepAliveTime() const;
inline IpAddress GetRemoteAddress() const; inline IpAddress GetRemoteAddress() const;
UInt64 GetSize() const override;
inline bool IsLowDelayEnabled() const; inline bool IsLowDelayEnabled() const;
inline bool IsKeepAliveEnabled() const; inline bool IsKeepAliveEnabled() const;
@ -41,13 +46,19 @@ namespace Nz
bool Send(const void* buffer, std::size_t size, std::size_t* sent); bool Send(const void* buffer, std::size_t size, std::size_t* sent);
bool SetCursorPos(UInt64 offset) override;
bool WaitForConnected(UInt64 msTimeout = 3000); bool WaitForConnected(UInt64 msTimeout = 3000);
private: private:
void FlushStream() override;
void OnClose() override; void OnClose() override;
void OnOpened() override; void OnOpened() override;
std::size_t ReadBlock(void* buffer, std::size_t size) override;
void Reset(SocketHandle handle, const IpAddress& peerAddress); void Reset(SocketHandle handle, const IpAddress& peerAddress);
std::size_t WriteBlock(const void* buffer, std::size_t size) override;
IpAddress m_peerAddress; IpAddress m_peerAddress;
UInt64 m_keepAliveInterval; UInt64 m_keepAliveInterval;

View File

@ -9,6 +9,7 @@ namespace Nz
{ {
inline TcpClient::TcpClient() : inline TcpClient::TcpClient() :
AbstractSocket(SocketType_TCP), AbstractSocket(SocketType_TCP),
Stream(StreamOption_Sequential),
m_keepAliveInterval(1000), //TODO: Query OS default value m_keepAliveInterval(1000), //TODO: Query OS default value
m_keepAliveTime(7'200'000), //TODO: Query OS default value m_keepAliveTime(7'200'000), //TODO: Query OS default value
m_isKeepAliveEnabled(false), //TODO: Query OS default value m_isKeepAliveEnabled(false), //TODO: Query OS default value
@ -18,6 +19,7 @@ namespace Nz
inline TcpClient::TcpClient(TcpClient&& tcpClient) : inline TcpClient::TcpClient(TcpClient&& tcpClient) :
AbstractSocket(std::move(tcpClient)), AbstractSocket(std::move(tcpClient)),
Stream(std::move(tcpClient)),
m_peerAddress(std::move(tcpClient.m_peerAddress)), m_peerAddress(std::move(tcpClient.m_peerAddress)),
m_keepAliveInterval(tcpClient.m_keepAliveInterval), m_keepAliveInterval(tcpClient.m_keepAliveInterval),
m_keepAliveTime(tcpClient.m_keepAliveTime), m_keepAliveTime(tcpClient.m_keepAliveTime),

View File

@ -31,7 +31,6 @@
namespace Nz namespace Nz
{ {
File::File() : File::File() :
Stream(OpenMode_NotOpen),
m_impl(nullptr) m_impl(nullptr)
{ {
} }
@ -75,6 +74,8 @@ namespace Nz
m_impl->Close(); m_impl->Close();
delete m_impl; delete m_impl;
m_impl = nullptr; m_impl = nullptr;
m_openMode = OpenMode_NotOpen;
} }
} }
@ -208,20 +209,18 @@ namespace Nz
if (m_filePath.IsEmpty()) if (m_filePath.IsEmpty())
return false; return false;
if (openMode != 0) if (openMode == OpenMode_NotOpen)
m_openMode = openMode;
if (m_openMode == 0)
return false; return false;
std::unique_ptr<FileImpl> impl(new FileImpl(this)); std::unique_ptr<FileImpl> impl(new FileImpl(this));
if (!impl->Open(m_filePath, m_openMode)) if (!impl->Open(m_filePath, openMode))
{ {
ErrorFlags flags(ErrorFlag_Silent); // Silencieux par défaut ErrorFlags flags(ErrorFlag_Silent); // Silencieux par défaut
NazaraError("Failed to open \"" + m_filePath + "\": " + Error::GetLastSystemError()); NazaraError("Failed to open \"" + m_filePath + "\": " + Error::GetLastSystemError());
return false; return false;
} }
m_openMode = openMode;
m_impl = impl.release(); m_impl = impl.release();
if (m_openMode & OpenMode_Text) if (m_openMode & OpenMode_Text)

View File

@ -94,6 +94,22 @@ namespace Nz
} }
} }
bool TcpClient::EndOfStream() const
{
return QueryAvailableBytes() == 0;
}
UInt64 TcpClient::GetCursorPos() const
{
NazaraError("GetCursorPos() cannot be used on sequential streams");
return 0;
}
UInt64 TcpClient::GetSize() const
{
return QueryAvailableBytes();
}
bool TcpClient::Receive(void* buffer, std::size_t size, std::size_t* received) bool TcpClient::Receive(void* buffer, std::size_t size, std::size_t* received)
{ {
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle"); NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
@ -165,6 +181,12 @@ namespace Nz
return true; return true;
} }
bool TcpClient::SetCursorPos(UInt64 offset)
{
NazaraError("SetCursorPos() cannot be used on sequential streams");
return false;
}
bool TcpClient::WaitForConnected(UInt64 msTimeout) bool TcpClient::WaitForConnected(UInt64 msTimeout)
{ {
switch (m_state) switch (m_state)
@ -209,10 +231,15 @@ namespace Nz
return false; return false;
} }
void TcpClient::FlushStream()
{
}
void TcpClient::OnClose() void TcpClient::OnClose()
{ {
AbstractSocket::OnClose(); AbstractSocket::OnClose();
m_openMode = OpenMode_NotOpen;
m_peerAddress = IpAddress::Invalid; m_peerAddress = IpAddress::Invalid;
} }
@ -229,12 +256,56 @@ namespace Nz
NazaraWarning("Failed to set socket keep alive mode (0x" + String::Number(errorCode, 16) + ')'); NazaraWarning("Failed to set socket keep alive mode (0x" + String::Number(errorCode, 16) + ')');
m_peerAddress = IpAddress::Invalid; m_peerAddress = IpAddress::Invalid;
m_openMode = OpenMode_ReadWrite;
}
std::size_t TcpClient::ReadBlock(void* buffer, std::size_t size)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
CallOnExit restoreBlocking;
if (!m_isBlockingEnabled)
{
SocketImpl::SetBlocking(m_handle, true);
restoreBlocking.Reset([this] ()
{
SocketImpl::SetBlocking(m_handle, false);
});
}
std::size_t received;
if (!Receive(buffer, size, &received))
received = 0;
return received;
} }
void TcpClient::Reset(SocketHandle handle, const IpAddress& peerAddress) void TcpClient::Reset(SocketHandle handle, const IpAddress& peerAddress)
{ {
Open(handle); Open(handle);
m_peerAddress = peerAddress; m_peerAddress = peerAddress;
m_openMode = OpenMode_ReadWrite;
UpdateState(SocketState_Connected); UpdateState(SocketState_Connected);
} }
std::size_t TcpClient::WriteBlock(const void* buffer, std::size_t size)
{
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
CallOnExit restoreBlocking;
if (!m_isBlockingEnabled)
{
SocketImpl::SetBlocking(m_handle, true);
restoreBlocking.Reset([this] ()
{
SocketImpl::SetBlocking(m_handle, false);
});
}
std::size_t sent;
if (!Send(buffer, size, &sent))
sent = 0;
return sent;
}
} }