Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
IO/Network/SocketStream.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#if qStroika_Foundation_Common_Platform_Windows
7#include <io.h>
8#elif qStroika_Foundation_Common_Platform_POSIX
9#include <unistd.h>
10#endif
11#include <cstdlib>
12
13#include "Stroika/Foundation/Execution/OperationNotSupportedException.h"
14#include "Stroika/Foundation/Streams/InternallySynchronizedInputOutputStream.h"
15
16#include "SocketStream.h"
17
18using namespace Stroika::Foundation;
19using namespace Stroika::Foundation::Streams;
20using namespace Stroika::Foundation::IO;
22
23using std::byte;
24
25namespace {
26 class Rep_ : public InputOutputStream::IRep<byte> {
27 public:
28 bool fOpenForRead_{true};
29 bool fOpenForWrite_{true};
30 SeekOffsetType fReadSeekOffset_{};
32 : fSD_{sd}
33 {
34 }
35 virtual bool IsSeekable () const override
36 {
37 return false;
38 }
39 virtual void CloseWrite () override
40 {
41 if (IsOpenWrite ()) {
42 fSD_.Shutdown (Socket::ShutdownTarget::eWrites);
43 if (not fOpenForRead_) { // if Both closed
44 fSD_.Close ();
45 fSD_.reset ();
46 }
47 fOpenForWrite_ = false;
48 }
49 Ensure (not IsOpenWrite ());
50 }
51 virtual bool IsOpenWrite () const override
52 {
53 return fOpenForWrite_;
54 }
55 virtual void CloseRead () override
56 {
57 if (fOpenForRead_) {
58 fSD_.Shutdown (Socket::ShutdownTarget::eReads);
59 if (not fOpenForWrite_) { // if Both closed
60 fSD_.Close ();
61 fSD_.reset ();
62 }
63 fOpenForRead_ = false;
64 }
65 Ensure (not IsOpenRead ());
66 }
67 virtual bool IsOpenRead () const override
68 {
69 return fOpenForRead_;
70 }
71 virtual SeekOffsetType GetReadOffset () const override
72 {
73 Require (IsOpenRead ());
74 return fReadSeekOffset_;
75 }
76 virtual optional<size_t> AvailableToRead () override
77 {
78 Require (IsOpenRead ());
79 return fSD_.AvailableToRead ();
80 }
81 virtual optional<SeekOffsetType> RemainingLength () override
82 {
83 Require (IsOpenRead ());
84 return nullopt; // maybe in some cases we can answer this like closed, but not generally
85 }
86 virtual optional<span<byte>> Read (span<byte> intoBuffer, NoDataAvailableHandling blockFlag) override
87 {
88 Require (IsOpenRead ());
89 optional<span<byte>> result;
90 switch (blockFlag) {
91 case NoDataAvailableHandling::eBlockIfNoDataAvailable:
92 result = fSD_.Read (intoBuffer);
93 break;
94 case NoDataAvailableHandling::eDontBlock: {
95 auto o = fSD_.ReadNonBlocking (intoBuffer);
96 if (o == nullopt) {
97 Execution::Throw (EWouldBlock::kThe);
98 }
99 result = *o;
100 } break;
101 default:
103 }
104 Assert (result);
105 fReadSeekOffset_ += result->size ();
106 return result;
107 }
108 virtual SeekOffsetType GetWriteOffset () const override
109 {
110 RequireNotReached (); // not seekable
111 Require (IsOpenWrite ());
112 return 0;
113 }
114 virtual SeekOffsetType SeekWrite (Whence /*whence*/, SignedSeekOffsetType /*offset*/) override
115 {
116 RequireNotReached (); // not seekable
117 Require (IsOpenWrite ());
118 return 0;
119 }
120 virtual void Write (span<const byte> elts) override
121 {
122 Require (IsOpenWrite ());
123 fSD_.Write (elts);
124 }
125 virtual void Flush () override
126 {
127 Require (IsOpenWrite ());
128 // socket has no flush API, so write must do the trick...
129 }
130
131 private:
133 };
134}
135
136/*
137 ********************************************************************************
138 **************************** IO::Network::SocketStream *************************
139 ********************************************************************************
140 */
141auto SocketStream::New (const ConnectionOrientedStreamSocket::Ptr& sd) -> Ptr
142{
143 return Ptr{make_shared<Rep_> (sd)};
144}
145
146auto SocketStream::New (Execution::InternallySynchronized internallySynchronized, const ConnectionOrientedStreamSocket::Ptr& sd) -> Ptr
147{
148 switch (internallySynchronized) {
149 case Execution::eInternallySynchronized:
150 return InternallySynchronizedInputOutputStream::New<Rep_> ({}, sd);
151 case Execution::eNotKnownInternallySynchronized:
152 return New (sd);
153 default:
155 return nullptr;
156 }
157}
#define RequireNotReached()
Definition Assertions.h:385
NoDataAvailableHandling
If eDontBlock passed to most Stream APIs, then when the code would do a blocking read,...
Definition Stream.h:90
nonvirtual void Shutdown(ShutdownTarget shutdownTarget=ShutdownTarget::eDEFAULT)
Definition Socket.inl:67
InputOutputStream is single stream object that acts much as a InputStream::Ptr and an OutputStream::P...
A Streams::Ptr<ELEMENT_TYPE> is a smart-pointer to a stream of elements of type T.
Definition Stream.h:170