Stroika Library 3.0d22
 
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"
15#include "Stroika/Foundation/Streams/InternallySynchronizedInputOutputStream.h"
16
17#include "SocketStream.h"
18
19using namespace Stroika::Foundation;
20using namespace Stroika::Foundation::Streams;
21using namespace Stroika::Foundation::IO;
23
24using std::byte;
25
26namespace {
27 class Rep_ : public InputOutputStream::IRep<byte> {
28 public:
29 bool fOpenForRead_{true};
30 bool fOpenForWrite_{true};
31 SeekOffsetType fReadSeekOffset_{};
33 : fSD_{sd}
34 {
35 }
36 virtual bool IsSeekable () const override
37 {
38 return false;
39 }
40 virtual void CloseWrite () override
41 {
42 if (IsOpenWrite ()) {
43 fSD_.Shutdown (Socket::ShutdownTarget::eWrites);
44 if (not fOpenForRead_) { // if Both closed
45 fSD_.Close ();
46 fSD_.reset ();
47 }
48 fOpenForWrite_ = false;
49 }
50 Ensure (not IsOpenWrite ());
51 }
52 virtual bool IsOpenWrite () const override
53 {
54 return fOpenForWrite_;
55 }
56 virtual void CloseRead () override
57 {
58 if (fOpenForRead_) {
59 fSD_.Shutdown (Socket::ShutdownTarget::eReads);
60 if (not fOpenForWrite_) { // if Both closed
61 fSD_.Close ();
62 fSD_.reset ();
63 }
64 fOpenForRead_ = false;
65 }
66 Ensure (not IsOpenRead ());
67 }
68 virtual bool IsOpenRead () const override
69 {
70 return fOpenForRead_;
71 }
72 virtual SeekOffsetType GetReadOffset () const override
73 {
74 Require (IsOpenRead ());
75 return fReadSeekOffset_;
76 }
77 virtual optional<size_t> AvailableToRead () override
78 {
79 Require (IsOpenRead ());
80 return fSD_.AvailableToRead ();
81 }
82 virtual optional<SeekOffsetType> RemainingLength () override
83 {
84 Require (IsOpenRead ());
85 return nullopt; // maybe in some cases we can answer this like closed, but not generally
86 }
87 virtual optional<span<byte>> Read (span<byte> intoBuffer, NoDataAvailableHandling blockFlag) override
88 {
89 Require (IsOpenRead ());
90 optional<span<byte>> result;
91 switch (blockFlag) {
92 case NoDataAvailableHandling::eBlockIfNoDataAvailable:
93 result = fSD_.Read (intoBuffer);
94 break;
95 case NoDataAvailableHandling::eDontBlock: {
96 auto o = fSD_.ReadNonBlocking (intoBuffer);
97 if (o == nullopt) {
98 Execution::Throw (EWouldBlock::kThe);
99 }
100 result = *o;
101 } break;
102 default:
104 }
105 Assert (result);
106 fReadSeekOffset_ += result->size ();
107 return result;
108 }
109 virtual SeekOffsetType GetWriteOffset () const override
110 {
111 RequireNotReached (); // not seekable
112 Require (IsOpenWrite ());
113 return 0;
114 }
115 virtual SeekOffsetType SeekWrite (Whence /*whence*/, SignedSeekOffsetType /*offset*/) override
116 {
117 RequireNotReached (); // not seekable
118 Require (IsOpenWrite ());
119 return 0;
120 }
121 virtual void Write (span<const byte> elts) override
122 {
123 Require (IsOpenWrite ());
124 fSD_.Write (elts);
125 }
126 virtual void Flush () override
127 {
128 Require (IsOpenWrite ());
129 // socket has no flush API, so write must do the trick...
130 }
131
132 private:
134 };
135}
136
137/*
138 ********************************************************************************
139 **************************** IO::Network::SocketStream *************************
140 ********************************************************************************
141 */
142auto SocketStream::New (const ConnectionOrientedStreamSocket::Ptr& sd) -> Ptr
143{
144 return Ptr{Memory::MakeSharedPtr<Rep_> (sd)};
145}
146
147auto SocketStream::New (Execution::InternallySynchronized internallySynchronized, const ConnectionOrientedStreamSocket::Ptr& sd) -> Ptr
148{
149 switch (internallySynchronized) {
150 case Execution::eInternallySynchronized:
151 return InternallySynchronizedInputOutputStream::New<Rep_> ({}, sd);
152 case Execution::eNotKnownInternallySynchronized:
153 return New (sd);
154 default:
156 return nullptr;
157 }
158}
#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