4#ifndef _Stroika_Foundation_IO_Network_Socket_Private_h_
5#define _Stroika_Foundation_IO_Network_Socket_Private_h_ 1
7#include "Stroika/Foundation/StroikaPreComp.h"
14#if qStroika_Platform_POSIX
18#include <sys/socket.h>
20#elif qStroika_Platform_Windows
28#if qStroika_Platform_Linux
29#include <netinet/in.h>
30#include <netinet/tcp.h>
35#include "Stroika/Foundation/Execution/OperationNotSupportedException.h"
36#if qStroika_Platform_Windows
37#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
38#include "Stroika/Foundation/IO/Network/Platform/Windows/WinSock.h"
54 using namespace Stroika::Foundation::Memory;
55 using namespace Stroika::Foundation::IO;
60#if qStroika_Platform_POSIX
66#elif qStroika_Platform_Windows
71 void BreakWriteIntoParts_ (span<const T> data,
size_t maxSendAtATime,
const function<
size_t (span<const T>)>& writeFunc)
73#if USE_NOISY_TRACE_IN_THIS_MODULE_
76 ptrdiff_t amountToSend = data.size ();
77 ptrdiff_t amountRemainingToSend = amountToSend;
78 const T* remainingSendFrom = data.data ();
79 while (amountRemainingToSend > 0) {
80 size_t amountToSendThisIteration = min<size_t> (maxSendAtATime, amountRemainingToSend);
81 size_t amountSent = writeFunc (span{remainingSendFrom, amountToSendThisIteration});
82 Assert (amountSent <= amountToSendThisIteration);
83 Assert (
static_cast<size_t> (amountRemainingToSend) >= amountSent);
84 amountRemainingToSend -= amountSent;
85 remainingSendFrom += amountSent;
86#if USE_NOISY_TRACE_IN_THIS_MODULE_
87 if (amountSent < amountToSendThisIteration) {
89 L
"write broken into parts - amountSent=%lld out of amountToSendThisIteration=%lld, amountRemainingToSend=%lld",
90 static_cast<long long> (amountSent),
static_cast<long long> (amountToSendThisIteration),
91 static_cast<long long> (amountRemainingToSend));
97 template <
typename BASE_REP>
98 struct BackSocketImpl_ :
public BASE_REP {
106 if (fSD_ != kINVALID_NATIVE_HANDLE_) {
114 fSD_ = kINVALID_NATIVE_HANDLE_;
117 virtual void Shutdown (Socket::ShutdownTarget shutdownTarget)
override
120 if (fSD_ != kINVALID_NATIVE_HANDLE_) {
122 switch (shutdownTarget) {
123 case Socket::ShutdownTarget::eReads:
124#if qStroika_Platform_POSIX
125 ::shutdown (fSD_, SHUT_RD);
126#elif qStroika_Platform_Windows
127 ::shutdown (fSD_, SD_RECEIVE);
130 case Socket::ShutdownTarget::eWrites:
132#if qStroika_Platform_POSIX
133 ::shutdown (fSD_, SHUT_WR);
134#elif qStroika_Platform_Windows
135 ::shutdown (fSD_, SD_SEND);
138 case Socket::ShutdownTarget::eBoth:
139#if qStroika_Platform_POSIX
140 ::shutdown (fSD_, SHUT_RDWR);
141#elif qStroika_Platform_Windows
142 ::shutdown (fSD_, SD_BOTH);
150 virtual void Close ()
override
153 if (fSD_ != kINVALID_NATIVE_HANDLE_) {
154#if qStroika_Platform_POSIX
156#elif qStroika_Platform_Windows
157 ::closesocket (fSD_);
161 fSD_ = kINVALID_NATIVE_HANDLE_;
164 virtual optional<IO::Network::SocketAddress> GetLocalAddress ()
const override
167 struct sockaddr_storage radr;
168 socklen_t len =
sizeof (radr);
169 if (::getsockname (fSD_,
reinterpret_cast<struct sockaddr*
> (&radr), &len) == 0) {
178#if defined(SO_DOMAIN)
180#elif qStroika_Platform_Windows
182 WSAPROTOCOL_INFOW info{};
183 socklen_t infoLen =
sizeof (info);
184 getsockopt (SOL_SOCKET, SO_PROTOCOL_INFOW, &info, &infoLen);
189 sockaddr_storage radr{};
190 socklen_t len =
sizeof (radr);
200 virtual void getsockopt (
int level,
int optname,
void* optval, socklen_t* optvallen)
const override
205#if qStroika_Platform_POSIX
207#elif qStroika_Platform_Windows
208 ThrowWSASystemErrorIfSOCKET_ERROR (::getsockopt (fSD_, level, optname,
reinterpret_cast<char*
> (optval), optvallen));
213 template <
typename RESULT_TYPE>
214 inline RESULT_TYPE getsockopt (
int level,
int optname)
const
218 socklen_t roptlen =
sizeof (r);
219 this->getsockopt (level, optname, &r, &roptlen);
222 virtual void setsockopt (
int level,
int optname,
const void* optval, socklen_t optvallen)
override
227#if qStroika_Platform_POSIX
229#elif qStroika_Platform_Windows
230 ThrowWSASystemErrorIfSOCKET_ERROR (::setsockopt (fSD_, level, optname,
reinterpret_cast<const char*
> (optval), optvallen));
235 template <
typename ARG_TYPE>
236 inline void setsockopt (
int level,
int optname, ARG_TYPE arg)
238 socklen_t optvallen =
sizeof (arg);
239 this->setsockopt (level, optname, &arg, optvallen);
#define AssertNotImplemented()
#define RequireNotReached()
#define RequireNotNull(p)
#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE
[[msvc::no_unique_address]] isn't always broken in MSVC. Annotate with this on things where its not b...
#define Stroika_Foundation_Debug_OptionalizeTraceArgs(...)
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
unique_lock< AssertExternallySynchronizedChecker > WriteContext
Instantiate AssertExternallySynchronizedChecker::WriteContext to designate an area of code where prot...
shared_lock< const AssertExternallySynchronizedChecker > ReadContext
Instantiate AssertExternallySynchronizedChecker::ReadContext to designate an area of code where prote...
FamilyType
Socket address family - also sometimes referred to as domain (argument to ::socket calls it domain)
INT_TYPE ThrowPOSIXErrNoIfNegative(INT_TYPE returnCode)