Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SocketErrorFormatter.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include "../Common/ResultErrorFormatter.h"
6#include "SocketError.h"
7
8namespace SC
9{
10namespace detail
11{
12inline bool appendSocketErrorDetail(ResultErrorFormatter& formatter, SocketErrorDetail detail)
13{
14 switch (detail)
15 {
16 case SocketErrorDetail::None: return true;
17 case SocketErrorDetail::ParseIPv4Address: formatter.append("parse IPv4 address"); break;
18 case SocketErrorDetail::ParseIPv6Address: formatter.append("parse IPv6 address"); break;
19 case SocketErrorDetail::BuildUnixPathAddress: formatter.append("build Unix-domain path address"); break;
20 case SocketErrorDetail::BuildUnixAbstractAddress: formatter.append("build Unix-domain abstract address"); break;
21 case SocketErrorDetail::ExtractIPAddress: formatter.append("extract IP address"); break;
22 case SocketErrorDetail::ExtractUnixAddress: formatter.append("extract Unix-domain address"); break;
23 case SocketErrorDetail::CopyHostName: formatter.append("copy host name"); break;
24 case SocketErrorDetail::ResolveHostName: formatter.append("resolve host name"); break;
25 case SocketErrorDetail::CopyResolvedAddress: formatter.append("copy resolved address"); break;
26 case SocketErrorDetail::GetSocketAddress: formatter.append("query socket address"); break;
27 case SocketErrorDetail::PosixCloseDescriptor: formatter.append("POSIX close socket descriptor"); break;
28 case SocketErrorDetail::WindowsCloseSocket: formatter.append("Windows close socket"); break;
29 case SocketErrorDetail::PosixGetDescriptorFlags: formatter.append("POSIX query descriptor flags"); break;
30 case SocketErrorDetail::PosixSetDescriptorFlags: formatter.append("POSIX set descriptor flags"); break;
31 case SocketErrorDetail::WindowsGetHandleInformation: formatter.append("Windows query handle information"); break;
32 case SocketErrorDetail::WindowsSetHandleInformation: formatter.append("Windows set handle information"); break;
33 case SocketErrorDetail::WindowsSetBlocking: formatter.append("Windows set blocking mode"); break;
34 case SocketErrorDetail::CreateSocket: formatter.append("create socket"); break;
35 case SocketErrorDetail::SetTcpNoDelay: formatter.append("set TCP no-delay option"); break;
36 case SocketErrorDetail::SetBroadcast: formatter.append("set broadcast option"); break;
37 case SocketErrorDetail::JoinIPv4Multicast: formatter.append("join IPv4 multicast group"); break;
38 case SocketErrorDetail::JoinIPv6Multicast: formatter.append("join IPv6 multicast group"); break;
39 case SocketErrorDetail::LeaveIPv4Multicast: formatter.append("leave IPv4 multicast group"); break;
40 case SocketErrorDetail::LeaveIPv6Multicast: formatter.append("leave IPv6 multicast group"); break;
41 case SocketErrorDetail::SetIPv4MulticastLoopback: formatter.append("set IPv4 multicast loopback"); break;
42 case SocketErrorDetail::SetIPv6MulticastLoopback: formatter.append("set IPv6 multicast loopback"); break;
43 case SocketErrorDetail::SetIPv4MulticastHops: formatter.append("set IPv4 multicast hops"); break;
44 case SocketErrorDetail::SetIPv6MulticastHops: formatter.append("set IPv6 multicast hops"); break;
45 case SocketErrorDetail::SetIPv4MulticastInterface: formatter.append("set IPv4 multicast interface"); break;
46 case SocketErrorDetail::SetIPv6MulticastInterface: formatter.append("set IPv6 multicast interface"); break;
47 case SocketErrorDetail::ShutdownSocket: formatter.append("shut down socket"); break;
48 case SocketErrorDetail::SendDatagram: formatter.append("send datagram"); break;
49 case SocketErrorDetail::ReceiveDatagram: formatter.append("receive datagram"); break;
50 case SocketErrorDetail::BindSocket: formatter.append("bind socket"); break;
51 case SocketErrorDetail::ListenSocket: formatter.append("listen on socket"); break;
52 case SocketErrorDetail::AcceptConnection: formatter.append("accept connection"); break;
53 case SocketErrorDetail::ConnectSocket: formatter.append("connect socket"); break;
54 case SocketErrorDetail::SendStream: formatter.append("send stream data"); break;
55 case SocketErrorDetail::ReceiveStream: formatter.append("receive stream data"); break;
56 case SocketErrorDetail::WaitForRead: formatter.append("wait for readable socket"); break;
57 default: return false;
58 }
59 return true;
60}
61
62inline bool appendSocketError(ResultErrorFormatter& formatter, SocketError error)
63{
64 switch (error)
65 {
66 case SocketError::NetworkingNotInitialized: formatter.append("Networking is not initialized"); break;
67 case SocketError::UnsupportedTextEncoding: formatter.append("Text encoding is not supported"); break;
68 case SocketError::InputCapacityExceeded: formatter.append("Input capacity exceeded"); break;
69 case SocketError::InvalidIPAddress: formatter.append("IP address is invalid"); break;
70 case SocketError::InvalidAddress: formatter.append("Socket address is invalid"); break;
71 case SocketError::AddressTypeMismatch: formatter.append("Socket address type does not match"); break;
72 case SocketError::AddressFamilyMismatch: formatter.append("Socket address families do not match"); break;
73 case SocketError::OperationUnsupported: formatter.append("Socket operation is unsupported"); break;
74 case SocketError::InvalidSocket: formatter.append("Socket descriptor is invalid"); break;
75 case SocketError::DestinationSocketInUse: formatter.append("Destination socket is already in use"); break;
76 case SocketError::InvalidShutdownType: formatter.append("Shutdown type is invalid"); break;
77 case SocketError::SocketCreationFailed: formatter.append("Failed to create socket"); break;
78 case SocketError::SocketCloseFailed: formatter.append("Failed to close socket"); break;
79 case SocketError::DescriptorQueryFailed: formatter.append("Failed to query socket descriptor"); break;
80 case SocketError::DescriptorConfigurationFailed: formatter.append("Failed to configure socket descriptor"); break;
81 case SocketError::SocketOptionFailed: formatter.append("Failed to configure socket option"); break;
82 case SocketError::ShutdownFailed: formatter.append("Failed to shut down socket"); break;
83 case SocketError::BindFailed: formatter.append("Failed to bind socket"); break;
84 case SocketError::AddressInUse: formatter.append("Socket address is already in use"); break;
85 case SocketError::ListenFailed: formatter.append("Failed to listen on socket"); break;
86 case SocketError::AcceptFailed: formatter.append("Failed to accept connection"); break;
87 case SocketError::ConnectFailed: formatter.append("Failed to connect socket"); break;
88 case SocketError::SendFailed: formatter.append("Failed to send socket data"); break;
89 case SocketError::ReceiveFailed: formatter.append("Failed to receive socket data"); break;
90 case SocketError::IncompleteSend: formatter.append("Socket send was incomplete"); break;
91 case SocketError::DatagramTruncated: formatter.append("Datagram was truncated"); break;
92 case SocketError::WouldBlock: formatter.append("Socket operation would block"); break;
93 case SocketError::TimedOut: formatter.append("Socket operation timed out"); break;
94 case SocketError::DNSResolutionFailed: formatter.append("Failed to resolve host name"); break;
95 case SocketError::OutputCapacityExceeded: formatter.append("Output capacity exceeded"); break;
96 default: return false;
97 }
98 return true;
99}
100
101inline ResultErrorFormat formatSocketErrorWithContext(SocketError error, SocketErrorDetail detail,
102 SocketErrorContextKind contextKind, SocketErrorContext context,
103 Span<char> output)
104{
105 ResultErrorFormatter formatter(output);
106 if (not appendSocketError(formatter, error))
107 return ResultErrorFormatter::failure(ResultErrorFormatStatus::UnknownError, output);
108 if (detail != SocketErrorDetail::None)
109 {
110 formatter.append(" (detail: ");
111 if (not appendSocketErrorDetail(formatter, detail))
112 return ResultErrorFormatter::failure(ResultErrorFormatStatus::UnknownError, output);
113 formatter.append(")");
114 }
115 switch (contextKind)
116 {
117 case SocketErrorContextKind::None: break;
118 case SocketErrorContextKind::NativeError:
119 formatter.append(" (native error: ");
120 formatter.append(static_cast<uint64_t>(context.nativeError));
121 formatter.append(")");
122 break;
123 case SocketErrorContextKind::ResolverError:
124 formatter.append(" (resolver error: ");
125 if (context.resolverError < 0)
126 {
127 formatter.append("-");
128 formatter.append(static_cast<uint64_t>(-static_cast<int64_t>(context.resolverError)));
129 }
130 else
131 formatter.append(static_cast<uint64_t>(context.resolverError));
132 formatter.append(")");
133 break;
134 case SocketErrorContextKind::RequiredBytes:
135 formatter.append(" (required capacity: ");
136 formatter.append(static_cast<uint64_t>(context.requiredBytes));
137 formatter.append(" bytes)");
138 break;
139 case SocketErrorContextKind::ActualBytes:
140 formatter.append(" (actual bytes: ");
141 formatter.append(static_cast<uint64_t>(context.actualBytes));
142 formatter.append(")");
143 break;
144 default: return ResultErrorFormatter::failure(ResultErrorFormatStatus::UnknownError, output);
145 }
146 return formatter.finish();
147}
148} // namespace detail
149
150inline ResultErrorFormat formatSocketError(SocketError error, Span<char> output)
151{
152 return detail::formatSocketErrorWithContext(error, SocketErrorDetail::None, SocketErrorContextKind::None, {},
153 output);
154}
155
156inline ResultErrorFormat formatSocketError(Result result, Span<char> output)
157{
158 if (result)
159 return ResultErrorFormatter::failure(ResultErrorFormatStatus::NotAnError, output);
160 if (result.category() != SocketResultCategory)
161 return ResultErrorFormatter::failure(ResultErrorFormatStatus::ForeignCategory, output);
162 return formatSocketError(static_cast<SocketError>(result.errorValue()), output);
163}
164
165inline ResultErrorFormat formatSocketError(ResultSocket result, Span<char> output)
166{
167 if (result)
168 return ResultErrorFormatter::failure(ResultErrorFormatStatus::NotAnError, output);
169 if (result.result.category() != SocketResultCategory)
170 return ResultErrorFormatter::failure(ResultErrorFormatStatus::ForeignCategory, output);
171 return detail::formatSocketErrorWithContext(static_cast<SocketError>(result.result.errorValue()), result.detail,
172 result.contextKind, result.context, output);
173}
174} // namespace SC
SocketErrorDetail
Stable operation or backend stage retained for a Socket failure.
Definition SocketError.h:49
SocketError
Stable portable failures returned by the Socket library.
Definition SocketError.h:14
SocketErrorContextKind
Kind of the scalar diagnostic context stored in ResultSocket.
Definition SocketError.h:95