diff --git a/include/Nazara/Core/Stream.hpp b/include/Nazara/Core/Stream.hpp index ff41958026..63d7e781b8 100644 --- a/include/Nazara/Core/Stream.hpp +++ b/include/Nazara/Core/Stream.hpp @@ -55,7 +55,7 @@ namespace Nz Stream& operator=(Stream&&) = default; protected: - inline Stream(UInt32 openMode); + inline Stream(UInt32 streamOptions = StreamOption_None, UInt32 openMode = OpenMode_NotOpen); virtual void FlushStream() = 0; virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0; diff --git a/include/Nazara/Core/Stream.inl b/include/Nazara/Core/Stream.inl index 6c50980605..104d5e3009 100644 --- a/include/Nazara/Core/Stream.inl +++ b/include/Nazara/Core/Stream.inl @@ -7,9 +7,9 @@ namespace Nz { - inline Stream::Stream(UInt32 openMode) : + inline Stream::Stream(UInt32 streamOptions, UInt32 openMode) : m_openMode(openMode), - m_streamOptions(0) + m_streamOptions(streamOptions) { } diff --git a/include/Nazara/Network/TcpClient.hpp b/include/Nazara/Network/TcpClient.hpp index ef696fac30..f06a438360 100644 --- a/include/Nazara/Network/TcpClient.hpp +++ b/include/Nazara/Network/TcpClient.hpp @@ -9,12 +9,13 @@ #include #include +#include #include #include namespace Nz { - class NAZARA_NETWORK_API TcpClient : public AbstractSocket + class NAZARA_NETWORK_API TcpClient : public AbstractSocket, public Stream { friend class TcpServer; @@ -30,9 +31,13 @@ namespace Nz void EnableLowDelay(bool lowDelay); void EnableKeepAlive(bool keepAlive, UInt64 msTime = 10000, UInt64 msInterval = 1000); + bool EndOfStream() const override; + + UInt64 GetCursorPos() const override; inline UInt64 GetKeepAliveInterval() const; inline UInt64 GetKeepAliveTime() const; inline IpAddress GetRemoteAddress() const; + UInt64 GetSize() const override; inline bool IsLowDelayEnabled() 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 SetCursorPos(UInt64 offset) override; + bool WaitForConnected(UInt64 msTimeout = 3000); private: + void FlushStream() override; + void OnClose() override; void OnOpened() override; + std::size_t ReadBlock(void* buffer, std::size_t size) override; void Reset(SocketHandle handle, const IpAddress& peerAddress); + std::size_t WriteBlock(const void* buffer, std::size_t size) override; IpAddress m_peerAddress; UInt64 m_keepAliveInterval; diff --git a/include/Nazara/Network/TcpClient.inl b/include/Nazara/Network/TcpClient.inl index 60c879497a..5348d2152e 100644 --- a/include/Nazara/Network/TcpClient.inl +++ b/include/Nazara/Network/TcpClient.inl @@ -9,6 +9,7 @@ namespace Nz { inline TcpClient::TcpClient() : AbstractSocket(SocketType_TCP), + Stream(StreamOption_Sequential), m_keepAliveInterval(1000), //TODO: Query OS default value m_keepAliveTime(7'200'000), //TODO: Query OS default value m_isKeepAliveEnabled(false), //TODO: Query OS default value @@ -18,6 +19,7 @@ namespace Nz inline TcpClient::TcpClient(TcpClient&& tcpClient) : AbstractSocket(std::move(tcpClient)), + Stream(std::move(tcpClient)), m_peerAddress(std::move(tcpClient.m_peerAddress)), m_keepAliveInterval(tcpClient.m_keepAliveInterval), m_keepAliveTime(tcpClient.m_keepAliveTime), diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index c21073efe7..db71f2d953 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -31,7 +31,6 @@ namespace Nz { File::File() : - Stream(OpenMode_NotOpen), m_impl(nullptr) { } @@ -75,6 +74,8 @@ namespace Nz m_impl->Close(); delete m_impl; m_impl = nullptr; + + m_openMode = OpenMode_NotOpen; } } @@ -208,20 +209,18 @@ namespace Nz if (m_filePath.IsEmpty()) return false; - if (openMode != 0) - m_openMode = openMode; - - if (m_openMode == 0) + if (openMode == OpenMode_NotOpen) return false; std::unique_ptr 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 NazaraError("Failed to open \"" + m_filePath + "\": " + Error::GetLastSystemError()); return false; } + m_openMode = openMode; m_impl = impl.release(); if (m_openMode & OpenMode_Text) diff --git a/src/Nazara/Network/TcpClient.cpp b/src/Nazara/Network/TcpClient.cpp index 4c13c5c03a..b91dfaffd9 100644 --- a/src/Nazara/Network/TcpClient.cpp +++ b/src/Nazara/Network/TcpClient.cpp @@ -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) { NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle"); @@ -165,6 +181,12 @@ namespace Nz return true; } + bool TcpClient::SetCursorPos(UInt64 offset) + { + NazaraError("SetCursorPos() cannot be used on sequential streams"); + return false; + } + bool TcpClient::WaitForConnected(UInt64 msTimeout) { switch (m_state) @@ -209,10 +231,15 @@ namespace Nz return false; } + void TcpClient::FlushStream() + { + } + void TcpClient::OnClose() { AbstractSocket::OnClose(); + m_openMode = OpenMode_NotOpen; m_peerAddress = IpAddress::Invalid; } @@ -229,12 +256,56 @@ namespace Nz NazaraWarning("Failed to set socket keep alive mode (0x" + String::Number(errorCode, 16) + ')'); 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) { Open(handle); m_peerAddress = peerAddress; + m_openMode = OpenMode_ReadWrite; 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; + } }