SolidSyslog coverage report
Current view: top level - Platform/PlusTcp/Source - SolidSyslogPlusTcpTcpStream.c (source / functions) Coverage Total Hit
Test: SolidSyslog Lines: 100.0 % 119 119
Test Date: 2026-11-12 23:14:35 Functions: 100.0 % 27 27
Branches: 100.0 % 34 34

             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 */
        

Generated by: LCOV version 2.0-1