Branch data Line data Source code
1 : : /* SPDX-FileCopyrightText: Copyright 2026 Cozens Software Solutions Limited
2 : : * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0 OR LicenseRef-COSOSO-Commercial
3 : : */
4 : :
5 : : #include "FreeRTOS_IP.h"
6 : :
7 : : /* This component requires FreeRTOS-Plus-TCP built with TCP. */
8 : : #if (ipconfigUSE_TCP == 1)
9 : :
10 : : // NOLINTBEGIN(performance-no-int-to-ptr) -- FREERTOS_INVALID_SOCKET is ((Socket_t)~0U) from FreeRTOS-Plus-TCP; the int-to-ptr cast is intrinsic to the upstream
11 : : // sentinel and unavoidable.
12 : :
13 : : #include "SolidSyslogPlusTcpTcpStream.h"
14 : :
15 : : #include <stdbool.h>
16 : : #include <stddef.h>
17 : : #include <stdint.h>
18 : :
19 : : #include "FreeRTOS.h"
20 : : #include "FreeRTOS_ARP.h"
21 : : #include "FreeRTOS_Sockets.h"
22 : : #include "SolidSyslogError.h"
23 : : #include "SolidSyslogErrorCategory.h"
24 : : #include "SolidSyslogNullStream.h"
25 : : #include "SolidSyslogPlusTcpAddressPrivate.h"
26 : : #include "SolidSyslogPlusTcpTcpStreamErrors.h"
27 : : #include "SolidSyslogPlusTcpTcpStreamPrivate.h"
28 : : #include "SolidSyslogStream.h"
29 : : #include "SolidSyslogStreamCategories.h"
30 : : #include "SolidSyslogTunables.h"
31 : : #include "task.h"
32 : :
33 : : const struct SolidSyslogErrorSource SolidSyslogPlusTcpTcpStreamErrorSource = {
34 : : "PlusTcpTcpStream",
35 : : SolidSyslogTcpStreamErrors_Name
36 : : };
37 : :
38 : : struct SolidSyslogAddress;
39 : :
40 : : /* SolidSyslogStream_Read returns < 0 to signal EOF/error (socket closed
41 : : * internally); -1 is the in-tree convention across the Stream adapters. */
42 : : static const SolidSyslogSsize READ_FAILED = -1;
43 : :
44 : : enum
45 : : {
46 : : /* FreeRTOS-Plus-TCP's setsockopt ignores the level argument (no
47 : : * SOL_SOCKET vs IPPROTO_TCP split; option codes are flat); pass 0 by
48 : : * convention. */
49 : : SETSOCKOPT_LEVEL_DEFAULT = 0,
50 : : /* No MSG_PEEK / MSG_DONTWAIT / zero-copy - the timeouts cleared after
51 : : * connect already give us the non-blocking single-call behaviour
52 : : * SolidSyslogStream requires. */
53 : : SEND_RECV_FLAGS_DEFAULT = 0
54 : : };
55 : :
56 : : static uint32_t PlusTcpTcpStream_NullConnectTimeoutGetter(void* context);
57 : :
58 : : static bool PlusTcpTcpStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr);
59 : : static bool PlusTcpTcpStream_Send(struct SolidSyslogStream* base, const void* buffer, size_t size);
60 : : static SolidSyslogSsize PlusTcpTcpStream_Read(struct SolidSyslogStream* base, void* buffer, size_t size);
61 : : static void PlusTcpTcpStream_Close(struct SolidSyslogStream* base);
62 : : static uint32_t PlusTcpTcpStream_Version(struct SolidSyslogStream* base);
63 : :
64 : : static inline struct SolidSyslogPlusTcpTcpStream* PlusTcpTcpStream_SelfFromBase(struct SolidSyslogStream* base);
65 : : static inline bool PlusTcpTcpStream_ConfigProvidesGetter(const struct SolidSyslogPlusTcpTcpStreamConfig* config);
66 : : static inline bool PlusTcpTcpStream_IsOpen(const struct SolidSyslogPlusTcpTcpStream* self);
67 : : static void PlusTcpTcpStream_OpenSocket(struct SolidSyslogPlusTcpTcpStream* self);
68 : : static void PlusTcpTcpStream_ConnectOrCloseOnFailure(
69 : : struct SolidSyslogPlusTcpTcpStream* self,
70 : : const struct SolidSyslogAddress* addr
71 : : );
72 : : static BaseType_t PlusTcpTcpStream_TryConnect(
73 : : struct SolidSyslogPlusTcpTcpStream* self,
74 : : const struct SolidSyslogAddress* addr
75 : : );
76 : : static void PlusTcpTcpStream_ReportConnectFailure(
77 : : struct SolidSyslogPlusTcpTcpStream* self,
78 : : enum SolidSyslogSeverity severity,
79 : : enum SolidSyslogTcpStreamErrors detail
80 : : );
81 : : static void PlusTcpTcpStream_ReportConnectFailureWithCode(
82 : : struct SolidSyslogPlusTcpTcpStream* self,
83 : : enum SolidSyslogSeverity severity,
84 : : enum SolidSyslogTcpStreamErrors detail,
85 : : BaseType_t connectResult
86 : : );
87 : : static void PlusTcpTcpStream_ReportFailedAttempt(struct SolidSyslogPlusTcpTcpStream* self, BaseType_t connectResult);
88 : : static inline void PlusTcpTcpStream_PrimeArpIfMissing(uint32_t ip);
89 : : static void PlusTcpTcpStream_ClearTimeouts(Socket_t socket);
90 : : static void PlusTcpTcpStream_SetSendTimeout(Socket_t socket, TickType_t ticks);
91 : : static void PlusTcpTcpStream_SetRecvTimeout(Socket_t socket, TickType_t ticks);
92 : : static uint32_t PlusTcpTcpStream_ResolveConnectTimeoutMs(struct SolidSyslogPlusTcpTcpStream* self);
93 : : static bool PlusTcpTcpStream_SendOrCloseOnFailure(
94 : : struct SolidSyslogPlusTcpTcpStream* self,
95 : : const void* buffer,
96 : : size_t size
97 : : );
98 : : static bool PlusTcpTcpStream_TrySend(struct SolidSyslogPlusTcpTcpStream* self, const void* buffer, size_t size);
99 : : static bool PlusTcpTcpStream_AllBytesSent(BaseType_t sentCount, size_t expected);
100 : : static SolidSyslogSsize PlusTcpTcpStream_ReceiveOrCloseOnFailure(
101 : : struct SolidSyslogPlusTcpTcpStream* self,
102 : : void* buffer,
103 : : size_t size
104 : : );
105 : : static void PlusTcpTcpStream_CloseSocket(struct SolidSyslogPlusTcpTcpStream* self);
106 : :
107 : 68 : void SolidSyslogPlusTcpTcpStream_Initialise(
108 : : struct SolidSyslogStream* base,
109 : : const struct SolidSyslogPlusTcpTcpStreamConfig* config
110 : : )
111 : : {
112 : : static const struct SolidSyslogPlusTcpTcpStream DefaultPlusTcpTcpStream = {
113 : : .Base =
114 : : {.Open = PlusTcpTcpStream_Open,
115 : : .Send = PlusTcpTcpStream_Send,
116 : : .Read = PlusTcpTcpStream_Read,
117 : : .Close = PlusTcpTcpStream_Close,
118 : : .Version = PlusTcpTcpStream_Version},
119 : : .Config = {.GetConnectTimeoutMs = PlusTcpTcpStream_NullConnectTimeoutGetter, .ConnectTimeoutContext = NULL},
120 : : .Socket = FREERTOS_INVALID_SOCKET,
121 : : };
122 : :
123 : 68 : struct SolidSyslogPlusTcpTcpStream* self = PlusTcpTcpStream_SelfFromBase(base);
124 : 68 : *self = DefaultPlusTcpTcpStream;
125 [ + + ]: 68 : if (PlusTcpTcpStream_ConfigProvidesGetter(config) == true)
126 : : {
127 : 4 : self->Config = *config;
128 : : }
129 : 68 : }
130 : :
131 : 68 : static inline bool PlusTcpTcpStream_ConfigProvidesGetter(const struct SolidSyslogPlusTcpTcpStreamConfig* config)
132 : : {
133 [ + + + + ]: 68 : return (config != NULL) && (config->GetConnectTimeoutMs != NULL);
134 : : }
135 : :
136 : : /* Null Object substituted when the integrator does not install a getter -
137 : : * returns the compile-time tunable so the bounded-wait path has a single
138 : : * code path regardless of whether the integrator wired runtime tuning. */
139 : 44 : static uint32_t PlusTcpTcpStream_NullConnectTimeoutGetter(void* context)
140 : : {
141 : : (void) context;
142 : 44 : return (uint32_t) SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS;
143 : : }
144 : :
145 : 208 : static inline struct SolidSyslogPlusTcpTcpStream* PlusTcpTcpStream_SelfFromBase(struct SolidSyslogStream* base)
146 : : {
147 : 208 : return (struct SolidSyslogPlusTcpTcpStream*) base;
148 : : }
149 : :
150 : 68 : void SolidSyslogPlusTcpTcpStream_Cleanup(struct SolidSyslogStream* base)
151 : : {
152 : 68 : struct SolidSyslogPlusTcpTcpStream* self = PlusTcpTcpStream_SelfFromBase(base);
153 : 68 : PlusTcpTcpStream_CloseSocket(self);
154 : : /* Overwrite the abstract base with the shared NullStream vtable so
155 : : * use-after-destroy is a safe no-op rather than a NULL-fn-pointer crash. */
156 : 68 : *base = *SolidSyslogNullStream_Get();
157 : 68 : }
158 : :
159 : 91 : static void PlusTcpTcpStream_CloseSocket(struct SolidSyslogPlusTcpTcpStream* self)
160 : : {
161 [ + + ]: 91 : if (PlusTcpTcpStream_IsOpen(self))
162 : : {
163 : 48 : (void) FreeRTOS_closesocket(self->Socket);
164 : 48 : self->Socket = FREERTOS_INVALID_SOCKET;
165 : : }
166 : 91 : }
167 : :
168 : 52 : static bool PlusTcpTcpStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr)
169 : : {
170 : 52 : struct SolidSyslogPlusTcpTcpStream* self = PlusTcpTcpStream_SelfFromBase(base);
171 : 52 : bool opened = false;
172 [ + + ]: 52 : if (PlusTcpTcpStream_IsOpen(self))
173 : : {
174 : : /* Refused by contract, not reconnected: what is held stays as it is. */
175 : 2 : PlusTcpTcpStream_Report(
176 : : SOLIDSYSLOG_BAD_ARGUMENT_SEVERITY,
177 : : SOLIDSYSLOG_CAT_BAD_ARGUMENT,
178 : : SOLIDSYSLOG_TCP_STREAM_ERROR_ALREADY_OPEN
179 : : );
180 : : }
181 : : else
182 : : {
183 : 50 : PlusTcpTcpStream_OpenSocket(self);
184 [ + + ]: 50 : if (PlusTcpTcpStream_IsOpen(self))
185 : : {
186 : 48 : PlusTcpTcpStream_ConnectOrCloseOnFailure(self, addr);
187 : : }
188 : : else
189 : : {
190 : 2 : PlusTcpTcpStream_ReportConnectFailure(
191 : : self,
192 : : SOLIDSYSLOG_STREAM_CONNECT_LOCAL_SEVERITY,
193 : : SOLIDSYSLOG_TCP_STREAM_ERROR_ENDPOINT_UNAVAILABLE
194 : : );
195 : : }
196 : 50 : opened = PlusTcpTcpStream_IsOpen(self);
197 [ + + ]: 50 : if (opened)
198 : : {
199 : 37 : SolidSyslogStreamOpenHealth_Opened(&self->OpenHealth);
200 : : }
201 : : }
202 : 52 : return opened;
203 : : }
204 : :
205 : 257 : static inline bool PlusTcpTcpStream_IsOpen(const struct SolidSyslogPlusTcpTcpStream* self)
206 : : {
207 : 257 : return self->Socket != FREERTOS_INVALID_SOCKET;
208 : : }
209 : :
210 : 50 : static void PlusTcpTcpStream_OpenSocket(struct SolidSyslogPlusTcpTcpStream* self)
211 : : {
212 : 50 : self->Socket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP);
213 : 50 : }
214 : :
215 : 48 : static void PlusTcpTcpStream_ConnectOrCloseOnFailure(
216 : : struct SolidSyslogPlusTcpTcpStream* self,
217 : : const struct SolidSyslogAddress* addr
218 : : )
219 : : {
220 : 48 : BaseType_t connectResult = PlusTcpTcpStream_TryConnect(self, addr);
221 [ + + ]: 48 : if (connectResult == 0)
222 : : {
223 : 37 : PlusTcpTcpStream_ClearTimeouts(self->Socket);
224 : : }
225 : : else
226 : : {
227 : 11 : PlusTcpTcpStream_ReportFailedAttempt(self, connectResult);
228 : 11 : PlusTcpTcpStream_CloseSocket(self);
229 : : }
230 : 48 : }
231 : :
232 : : /* Every connect failure is one category with the detail naming which step
233 : : * failed, so a portable handler reacts to "no connection" without knowing
234 : : * FreeRTOS-Plus-TCP. Reported once per run of the same detail, as the Open
235 : : * contract requires: the sender retries every service pass. */
236 : 2 : static void PlusTcpTcpStream_ReportConnectFailure(
237 : : struct SolidSyslogPlusTcpTcpStream* self,
238 : : enum SolidSyslogSeverity severity,
239 : : enum SolidSyslogTcpStreamErrors detail
240 : : )
241 : : {
242 : 2 : SolidSyslogStreamOpenHealth_ReportFailure(
243 : : &self->OpenHealth,
244 : : &SolidSyslogPlusTcpTcpStreamErrorSource,
245 : : severity,
246 : : SOLIDSYSLOG_CAT_STREAM_CONNECT_FAILED,
247 : : (int32_t) detail
248 : : );
249 : 2 : }
250 : :
251 : : /* The fault, with the value FreeRTOS_connect answered behind it: the negated
252 : : * FreeRTOS errno, as the stack returns it. */
253 : 11 : static void PlusTcpTcpStream_ReportConnectFailureWithCode(
254 : : struct SolidSyslogPlusTcpTcpStream* self,
255 : : enum SolidSyslogSeverity severity,
256 : : enum SolidSyslogTcpStreamErrors detail,
257 : : BaseType_t connectResult
258 : : )
259 : : {
260 : 11 : SolidSyslogStreamOpenHealth_ReportFailureWithNativeCode(
261 : : &self->OpenHealth,
262 : : &SolidSyslogPlusTcpTcpStreamErrorSource,
263 : : severity,
264 : : SOLIDSYSLOG_CAT_STREAM_CONNECT_FAILED,
265 : : (int32_t) detail,
266 : : (int32_t) connectResult
267 : : );
268 : 11 : }
269 : :
270 : : /* FreeRTOS_connect distinguishes three outcomes in its return: ETIMEDOUT is
271 : : * the bounded wait expiring, ENOTCONN is the socket being closed under it -
272 : : * the destination answering with something other than a connection - and any
273 : : * other error comes from prvTCPConnectStart, which means the stack declined
274 : : * to begin and no SYN was sent. Each carries that return as its code. */
275 : 11 : static void PlusTcpTcpStream_ReportFailedAttempt(struct SolidSyslogPlusTcpTcpStream* self, BaseType_t connectResult)
276 : : {
277 [ + + ]: 11 : if (connectResult == -pdFREERTOS_ERRNO_ETIMEDOUT)
278 : : {
279 : 1 : PlusTcpTcpStream_ReportConnectFailureWithCode(
280 : : self,
281 : : SOLIDSYSLOG_STREAM_CONNECT_REMOTE_SEVERITY,
282 : : SOLIDSYSLOG_TCP_STREAM_ERROR_CONNECT_TIMED_OUT,
283 : : connectResult
284 : : );
285 : : }
286 [ + + ]: 10 : else if (connectResult == -pdFREERTOS_ERRNO_ENOTCONN)
287 : : {
288 : 8 : PlusTcpTcpStream_ReportConnectFailureWithCode(
289 : : self,
290 : : SOLIDSYSLOG_STREAM_CONNECT_REMOTE_SEVERITY,
291 : : SOLIDSYSLOG_TCP_STREAM_ERROR_CONNECT_REFUSED,
292 : : connectResult
293 : : );
294 : : }
295 : : else
296 : : {
297 : 2 : PlusTcpTcpStream_ReportConnectFailureWithCode(
298 : : self,
299 : : SOLIDSYSLOG_STREAM_CONNECT_LOCAL_SEVERITY,
300 : : SOLIDSYSLOG_TCP_STREAM_ERROR_CONNECT_NOT_STARTED,
301 : : connectResult
302 : : );
303 : : }
304 : 11 : }
305 : :
306 : 48 : static BaseType_t PlusTcpTcpStream_TryConnect(
307 : : struct SolidSyslogPlusTcpTcpStream* self,
308 : : const struct SolidSyslogAddress* addr
309 : : )
310 : : {
311 : : /* Both SO_SNDTIMEO and SO_RCVTIMEO are set before FreeRTOS_connect -
312 : : * upstream gates connect on SO_RCVTIMEO, but we set both as belt-and-
313 : : * braces against an upstream change. After connect both timeouts go
314 : : * back to 0 so subsequent Send/Read follow the non-blocking single-
315 : : * call contract from SolidSyslogStream. The default
316 : : * SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS = 200 is short enough that the
317 : : * Service task keeps draining predictably during an outage, long
318 : : * enough for a healthy peer to ACK over slirp/LAN. */
319 : 48 : const TickType_t connectTimeoutTicks = pdMS_TO_TICKS(PlusTcpTcpStream_ResolveConnectTimeoutMs(self));
320 : :
321 : 48 : const struct freertos_sockaddr* dest = SolidSyslogPlusTcpAddress_AsConstFreertosSockaddr(addr);
322 : 48 : PlusTcpTcpStream_PrimeArpIfMissing(dest->sin_address.ulIP_IPv4);
323 : 48 : PlusTcpTcpStream_SetSendTimeout(self->Socket, connectTimeoutTicks);
324 : 48 : PlusTcpTcpStream_SetRecvTimeout(self->Socket, connectTimeoutTicks);
325 : 48 : return FreeRTOS_connect(self->Socket, dest, sizeof(*dest));
326 : : }
327 : :
328 : : /* Bridges the integrator-installed getter (or the Null Object substituted in
329 : : * Initialise) to the bounded SO_*TIMEO deadline. Invoked on every connect
330 : : * attempt so a runtime-tunable value takes effect on the next reconnect. */
331 : 48 : static uint32_t PlusTcpTcpStream_ResolveConnectTimeoutMs(struct SolidSyslogPlusTcpTcpStream* self)
332 : : {
333 : 48 : uint32_t ms = self->Config.GetConnectTimeoutMs(self->Config.ConnectTimeoutContext);
334 : 48 : return (ms > SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS_MAX) ? SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS_MAX : ms;
335 : : }
336 : :
337 : : /* On ARP cache miss issue a probe and yield once for the reply to land
338 : : * before FreeRTOS_connect runs. Without this, the cold-start SYN is dropped
339 : : * at the IP layer (FreeRTOS-Plus-TCP does not queue while ARP resolves) and
340 : : * the bounded 200 ms connect timeout expires before the SYN-and-resend
341 : : * cycle completes. */
342 : 48 : static inline void PlusTcpTcpStream_PrimeArpIfMissing(uint32_t ip)
343 : : {
344 : : /* Yield window for the IP task to receive an ARP reply and populate
345 : : * the cache before we attempt FreeRTOS_connect. */
346 : : static const TickType_t ARP_RESOLUTION_WAIT_TICKS = pdMS_TO_TICKS(50);
347 : :
348 [ + + ]: 48 : if (xIsIPInARPCache(ip) == pdFALSE)
349 : : {
350 : 47 : FreeRTOS_OutputARPRequest(ip);
351 : 47 : vTaskDelay(ARP_RESOLUTION_WAIT_TICKS);
352 : : }
353 : 48 : }
354 : :
355 : 37 : static void PlusTcpTcpStream_ClearTimeouts(Socket_t socket)
356 : : {
357 : : static const TickType_t NO_TIMEOUT_TICKS = 0U;
358 : :
359 : 37 : PlusTcpTcpStream_SetSendTimeout(socket, NO_TIMEOUT_TICKS);
360 : 37 : PlusTcpTcpStream_SetRecvTimeout(socket, NO_TIMEOUT_TICKS);
361 : 37 : }
362 : :
363 : 85 : static void PlusTcpTcpStream_SetSendTimeout(Socket_t socket, TickType_t ticks)
364 : : {
365 : 85 : (void) FreeRTOS_setsockopt(socket, SETSOCKOPT_LEVEL_DEFAULT, FREERTOS_SO_SNDTIMEO, &ticks, sizeof(ticks));
366 : 85 : }
367 : :
368 : 85 : static void PlusTcpTcpStream_SetRecvTimeout(Socket_t socket, TickType_t ticks)
369 : : {
370 : 85 : (void) FreeRTOS_setsockopt(socket, SETSOCKOPT_LEVEL_DEFAULT, FREERTOS_SO_RCVTIMEO, &ticks, sizeof(ticks));
371 : 85 : }
372 : :
373 : 8 : static bool PlusTcpTcpStream_Send(struct SolidSyslogStream* base, const void* buffer, size_t size)
374 : : {
375 : 8 : struct SolidSyslogPlusTcpTcpStream* self = PlusTcpTcpStream_SelfFromBase(base);
376 : 8 : bool sent = false;
377 [ + + ]: 8 : if (PlusTcpTcpStream_IsOpen(self))
378 : : {
379 : 7 : sent = PlusTcpTcpStream_SendOrCloseOnFailure(self, buffer, size);
380 : : }
381 : 8 : return sent;
382 : : }
383 : :
384 : 7 : static bool PlusTcpTcpStream_SendOrCloseOnFailure(
385 : : struct SolidSyslogPlusTcpTcpStream* self,
386 : : const void* buffer,
387 : : size_t size
388 : : )
389 : : {
390 : 7 : bool sent = PlusTcpTcpStream_TrySend(self, buffer, size);
391 [ + + ]: 7 : if (!sent)
392 : : {
393 : 5 : PlusTcpTcpStream_CloseSocket(self);
394 : : }
395 : 7 : return sent;
396 : : }
397 : :
398 : 7 : static bool PlusTcpTcpStream_TrySend(struct SolidSyslogPlusTcpTcpStream* self, const void* buffer, size_t size)
399 : : {
400 : 7 : BaseType_t sentCount = FreeRTOS_send(self->Socket, buffer, size, SEND_RECV_FLAGS_DEFAULT);
401 : 7 : return PlusTcpTcpStream_AllBytesSent(sentCount, size);
402 : : }
403 : :
404 : 7 : static bool PlusTcpTcpStream_AllBytesSent(BaseType_t sentCount, size_t expected)
405 : : {
406 [ + + + + ]: 7 : return (sentCount >= 0) && ((size_t) sentCount == expected);
407 : : }
408 : :
409 : : /* FreeRTOS_recv with RCVTIMEO=0 returns 0 when no data is available (would
410 : : * block); the Service thread treats that as "nothing to read right now".
411 : : * Negative returns are real errors - close the socket and surface failure. */
412 : 6 : static SolidSyslogSsize PlusTcpTcpStream_Read(struct SolidSyslogStream* base, void* buffer, size_t size)
413 : : {
414 : 6 : struct SolidSyslogPlusTcpTcpStream* self = PlusTcpTcpStream_SelfFromBase(base);
415 : 6 : SolidSyslogSsize result = READ_FAILED;
416 [ + + ]: 6 : if (PlusTcpTcpStream_IsOpen(self))
417 : : {
418 : 5 : result = PlusTcpTcpStream_ReceiveOrCloseOnFailure(self, buffer, size);
419 : : }
420 : 6 : return result;
421 : : }
422 : :
423 : 5 : static SolidSyslogSsize PlusTcpTcpStream_ReceiveOrCloseOnFailure(
424 : : struct SolidSyslogPlusTcpTcpStream* self,
425 : : void* buffer,
426 : : size_t size
427 : : )
428 : : {
429 : 5 : BaseType_t receivedCount = FreeRTOS_recv(self->Socket, buffer, size, SEND_RECV_FLAGS_DEFAULT);
430 : 5 : SolidSyslogSsize result = READ_FAILED;
431 [ + + ]: 5 : if (receivedCount >= 0)
432 : : {
433 : 4 : result = (SolidSyslogSsize) receivedCount;
434 : : }
435 : : else
436 : : {
437 : 1 : PlusTcpTcpStream_CloseSocket(self);
438 : : }
439 : 5 : return result;
440 : : }
441 : :
442 : 6 : static void PlusTcpTcpStream_Close(struct SolidSyslogStream* base)
443 : : {
444 : 6 : PlusTcpTcpStream_CloseSocket(PlusTcpTcpStream_SelfFromBase(base));
445 : 6 : }
446 : :
447 : 1 : static uint32_t PlusTcpTcpStream_Version(struct SolidSyslogStream* base)
448 : : {
449 : : (void) base;
450 : 1 : return 0U;
451 : : }
452 : :
453 : : // NOLINTEND(performance-no-int-to-ptr)
454 : :
455 : : #else
456 : :
457 : : /* ISO C forbids an empty translation unit. */
458 : : typedef int PlusTcpTcpStream_EmptyTranslationUnit;
459 : :
460 : : #endif /* ipconfigUSE_TCP */
|