SolidSyslog coverage report
Current view: top level - Platform/VxWorks64/Source - SolidSyslogVxWorks64TcpStream.c (source / functions) Coverage Total Hit
Test: SolidSyslog Lines: 100.0 % 133 133
Test Date: 2026-11-12 23:14:35 Functions: 100.0 % 26 26
Branches: 98.6 % 72 71

             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 "SolidSyslogVxWorks64TcpStream.h"
       6                 :             : 
       7                 :             : #include <errno.h>
       8                 :             : #include <limits.h>
       9                 :             : #include <stdbool.h>
      10                 :             : #include <stddef.h>
      11                 :             : #include <stdint.h>
      12                 :             : 
      13                 :             : #include "vxWorks.h"
      14                 :             : 
      15                 :             : #include <netinet/in.h>
      16                 :             : #include <netinet/tcp.h>
      17                 :             : #include <sys/socket.h>
      18                 :             : #include <sys/times.h>
      19                 :             : 
      20                 :             : #include "ioLib.h"
      21                 :             : #include "sockLib.h"
      22                 :             : 
      23                 :             : #include "SolidSyslogError.h"
      24                 :             : #include "SolidSyslogErrorCategory.h"
      25                 :             : #include "SolidSyslogNullStream.h"
      26                 :             : #include "SolidSyslogStreamCategories.h"
      27                 :             : #include "SolidSyslogStreamDefinition.h"
      28                 :             : #include "SolidSyslogTunables.h"
      29                 :             : #include "SolidSyslogVxWorks64AddressPrivate.h"
      30                 :             : #include "SolidSyslogVxWorks64TcpStreamErrors.h"
      31                 :             : #include "SolidSyslogVxWorks64TcpStreamPrivate.h"
      32                 :             : 
      33                 :             : const struct SolidSyslogErrorSource SolidSyslogVxWorks64TcpStreamErrorSource = {
      34                 :             :     "VxWorks64TcpStream",
      35                 :             :     SolidSyslogTcpStreamErrors_Name
      36                 :             : };
      37                 :             : 
      38                 :             : struct SolidSyslogAddress;
      39                 :             : 
      40                 :             : enum
      41                 :             : {
      42                 :             :     INVALID_SOCKET = -1,
      43                 :             :     MILLISECONDS_PER_SECOND = 1000,
      44                 :             :     MICROSECONDS_PER_MILLISECOND = 1000
      45                 :             : };
      46                 :             : 
      47                 :             : static uint32_t VxWorks64TcpStream_NullConnectTimeoutGetter(void* context);
      48                 :             : static inline bool VxWorks64TcpStream_ConfigProvidesGetter(const struct SolidSyslogVxWorks64TcpStreamConfig* config);
      49                 :             : 
      50                 :             : static bool VxWorks64TcpStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr);
      51                 :             : static bool VxWorks64TcpStream_TakeSocketAndConnect(
      52                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
      53                 :             :     const struct sockaddr_in* sin
      54                 :             : );
      55                 :             : static bool VxWorks64TcpStream_Send(struct SolidSyslogStream* base, const void* buffer, size_t size);
      56                 :             : static inline bool VxWorks64TcpStream_FitsTheStack(size_t size);
      57                 :             : static bool VxWorks64TcpStream_PeerIsStillThere(const struct SolidSyslogVxWorks64TcpStream* self);
      58                 :             : static inline bool VxWorks64TcpStream_WouldBlock(int err);
      59                 :             : static inline bool VxWorks64TcpStream_WroteAllBytes(int sent, size_t expected);
      60                 :             : static SolidSyslogSsize VxWorks64TcpStream_Read(struct SolidSyslogStream* base, void* buffer, size_t size);
      61                 :             : static inline int VxWorks64TcpStream_ClampToTheStack(size_t size);
      62                 :             : static void VxWorks64TcpStream_Close(struct SolidSyslogStream* base);
      63                 :             : static uint32_t VxWorks64TcpStream_Version(struct SolidSyslogStream* base);
      64                 :             : 
      65                 :             : static inline struct SolidSyslogVxWorks64TcpStream* VxWorks64TcpStream_SelfFromBase(struct SolidSyslogStream* base);
      66                 :             : static void VxWorks64TcpStream_CloseSocket(struct SolidSyslogVxWorks64TcpStream* self);
      67                 :             : static inline bool VxWorks64TcpStream_IsSocketValid(int fd);
      68                 :             : static void VxWorks64TcpStream_ReportConnectFailure(
      69                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
      70                 :             :     enum SolidSyslogSeverity severity,
      71                 :             :     enum SolidSyslogTcpStreamErrors detail
      72                 :             : );
      73                 :             : static void VxWorks64TcpStream_ReportConnectFailureWithErrno(
      74                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
      75                 :             :     enum SolidSyslogSeverity severity,
      76                 :             :     enum SolidSyslogTcpStreamErrors detail,
      77                 :             :     int nativeErrno
      78                 :             : );
      79                 :             : static bool VxWorks64TcpStream_ConnectOrCloseOnFailure(
      80                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
      81                 :             :     const struct sockaddr_in* sin
      82                 :             : );
      83                 :             : static bool VxWorks64TcpStream_Connect(struct SolidSyslogVxWorks64TcpStream* self, const struct sockaddr_in* sin);
      84                 :             : static struct timeval VxWorks64TcpStream_ResolveConnectTimeout(struct SolidSyslogVxWorks64TcpStream* self);
      85                 :             : static inline bool VxWorks64TcpStream_IsRemoteConnectError(int connectErrno);
      86                 :             : static void VxWorks64TcpStream_ApplySocketOptions(int fd);
      87                 :             : static void VxWorks64TcpStream_ReportOptionRefused(void);
      88                 :             : 
      89                 :         121 : void SolidSyslogVxWorks64TcpStream_Initialise(
      90                 :             :     struct SolidSyslogStream* base,
      91                 :             :     const struct SolidSyslogVxWorks64TcpStreamConfig* config
      92                 :             : )
      93                 :             : {
      94                 :         121 :     struct SolidSyslogVxWorks64TcpStream* self = VxWorks64TcpStream_SelfFromBase(base);
      95                 :         121 :     self->Base.Open = VxWorks64TcpStream_Open;
      96                 :         121 :     self->Base.Send = VxWorks64TcpStream_Send;
      97                 :         121 :     self->Base.Read = VxWorks64TcpStream_Read;
      98                 :         121 :     self->Base.Close = VxWorks64TcpStream_Close;
      99                 :         121 :     self->Base.Version = VxWorks64TcpStream_Version;
     100                 :         121 :     self->Fd = INVALID_SOCKET;
     101                 :         121 :     self->OpenHealth = (struct SolidSyslogStreamOpenHealth) {0};
     102                 :         121 :     self->Config.GetConnectTimeoutMs = VxWorks64TcpStream_NullConnectTimeoutGetter;
     103                 :         121 :     self->Config.ConnectTimeoutContext = NULL;
     104         [ +  + ]:         121 :     if (VxWorks64TcpStream_ConfigProvidesGetter(config) == true)
     105                 :             :     {
     106                 :           3 :         self->Config = *config;
     107                 :             :     }
     108                 :         121 : }
     109                 :             : 
     110                 :         121 : static inline bool VxWorks64TcpStream_ConfigProvidesGetter(const struct SolidSyslogVxWorks64TcpStreamConfig* config)
     111                 :             : {
     112   [ +  +  +  + ]:         121 :     return (config != NULL) && (config->GetConnectTimeoutMs != NULL);
     113                 :             : }
     114                 :             : 
     115                 :             : /* Substituted when no getter is installed, so the connect has one code path. */
     116                 :          54 : static uint32_t VxWorks64TcpStream_NullConnectTimeoutGetter(void* context)
     117                 :             : {
     118                 :             :     (void) context;
     119                 :          54 :     return (uint32_t) SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS;
     120                 :             : }
     121                 :             : 
     122                 :         336 : static inline struct SolidSyslogVxWorks64TcpStream* VxWorks64TcpStream_SelfFromBase(struct SolidSyslogStream* base)
     123                 :             : {
     124                 :         336 :     return (struct SolidSyslogVxWorks64TcpStream*) base;
     125                 :             : }
     126                 :             : 
     127                 :         121 : void SolidSyslogVxWorks64TcpStream_Cleanup(struct SolidSyslogStream* base)
     128                 :             : {
     129                 :         121 :     VxWorks64TcpStream_CloseSocket(VxWorks64TcpStream_SelfFromBase(base));
     130                 :             :     /* Use-after-destroy lands on the NullStream vtable. */
     131                 :         121 :     *base = *SolidSyslogNullStream_Get();
     132                 :         121 : }
     133                 :             : 
     134                 :          61 : static bool VxWorks64TcpStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr)
     135                 :             : {
     136                 :          61 :     struct SolidSyslogVxWorks64TcpStream* self = VxWorks64TcpStream_SelfFromBase(base);
     137                 :          61 :     bool connected = false;
     138         [ +  + ]:          61 :     if (VxWorks64TcpStream_IsSocketValid(self->Fd))
     139                 :             :     {
     140                 :             :         /* Refused by contract, not reconnected: what is held stays as it is. */
     141                 :           2 :         VxWorks64TcpStream_Report(
     142                 :             :             SOLIDSYSLOG_BAD_ARGUMENT_SEVERITY,
     143                 :             :             SOLIDSYSLOG_CAT_BAD_ARGUMENT,
     144                 :             :             SOLIDSYSLOG_TCP_STREAM_ERROR_ALREADY_OPEN
     145                 :             :         );
     146                 :             :     }
     147                 :             :     else
     148                 :             :     {
     149                 :          59 :         connected = VxWorks64TcpStream_TakeSocketAndConnect(self, SolidSyslogVxWorks64Address_AsConstSockaddrIn(addr));
     150                 :             :     }
     151                 :          61 :     return connected;
     152                 :             : }
     153                 :             : 
     154                 :          59 : static bool VxWorks64TcpStream_TakeSocketAndConnect(
     155                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
     156                 :             :     const struct sockaddr_in* sin
     157                 :             : )
     158                 :             : {
     159                 :          59 :     bool connected = false;
     160                 :          59 :     self->Fd = socket(AF_INET, SOCK_STREAM, 0);
     161                 :             :     /* Read errno straight after the call that set it, with nothing between
     162                 :             :      * (MISRA 22.10). */
     163         [ +  + ]:          59 :     int socketErrno = VxWorks64TcpStream_IsSocketValid(self->Fd) ? 0 : errno;
     164         [ +  + ]:          59 :     if (VxWorks64TcpStream_IsSocketValid(self->Fd))
     165                 :             :     {
     166                 :          57 :         connected = VxWorks64TcpStream_ConnectOrCloseOnFailure(self, sin);
     167                 :             :     }
     168                 :             :     else
     169                 :             :     {
     170                 :           2 :         VxWorks64TcpStream_ReportConnectFailureWithErrno(
     171                 :             :             self,
     172                 :             :             SOLIDSYSLOG_STREAM_CONNECT_LOCAL_SEVERITY,
     173                 :             :             SOLIDSYSLOG_TCP_STREAM_ERROR_ENDPOINT_UNAVAILABLE,
     174                 :             :             socketErrno
     175                 :             :         );
     176                 :             :     }
     177         [ +  + ]:          59 :     if (connected)
     178                 :             :     {
     179                 :          44 :         SolidSyslogStreamOpenHealth_Opened(&self->OpenHealth);
     180                 :             :     }
     181                 :          59 :     return connected;
     182                 :             : }
     183                 :             : 
     184                 :         151 : static void VxWorks64TcpStream_CloseSocket(struct SolidSyslogVxWorks64TcpStream* self)
     185                 :             : {
     186         [ +  + ]:         151 :     if (VxWorks64TcpStream_IsSocketValid(self->Fd))
     187                 :             :     {
     188                 :          57 :         (void) close(self->Fd);
     189                 :          57 :         self->Fd = INVALID_SOCKET;
     190                 :             :     }
     191                 :         151 : }
     192                 :             : 
     193                 :         330 : static inline bool VxWorks64TcpStream_IsSocketValid(int fd)
     194                 :             : {
     195                 :         330 :     return fd >= 0;
     196                 :             : }
     197                 :             : 
     198                 :             : /* One category for every connect failure; the detail names the step.
     199                 :             :  * Reported once per run of the same detail, as the Open contract requires:
     200                 :             :  * the sender retries every service pass. */
     201                 :           1 : static void VxWorks64TcpStream_ReportConnectFailure(
     202                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
     203                 :             :     enum SolidSyslogSeverity severity,
     204                 :             :     enum SolidSyslogTcpStreamErrors detail
     205                 :             : )
     206                 :             : {
     207                 :           1 :     SolidSyslogStreamOpenHealth_ReportFailure(
     208                 :             :         &self->OpenHealth,
     209                 :             :         &SolidSyslogVxWorks64TcpStreamErrorSource,
     210                 :             :         severity,
     211                 :             :         SOLIDSYSLOG_CAT_STREAM_CONNECT_FAILED,
     212                 :             :         (int32_t) detail
     213                 :             :     );
     214                 :           1 : }
     215                 :             : 
     216                 :             : /* The fault, with the errno behind it when the call left one. */
     217                 :          15 : static void VxWorks64TcpStream_ReportConnectFailureWithErrno(
     218                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
     219                 :             :     enum SolidSyslogSeverity severity,
     220                 :             :     enum SolidSyslogTcpStreamErrors detail,
     221                 :             :     int nativeErrno
     222                 :             : )
     223                 :             : {
     224         [ +  + ]:          15 :     if (nativeErrno != 0)
     225                 :             :     {
     226                 :          14 :         SolidSyslogStreamOpenHealth_ReportFailureWithNativeCode(
     227                 :             :             &self->OpenHealth,
     228                 :             :             &SolidSyslogVxWorks64TcpStreamErrorSource,
     229                 :             :             severity,
     230                 :             :             SOLIDSYSLOG_CAT_STREAM_CONNECT_FAILED,
     231                 :             :             (int32_t) detail,
     232                 :             :             (int32_t) nativeErrno
     233                 :             :         );
     234                 :             :     }
     235                 :             :     else
     236                 :             :     {
     237                 :           1 :         VxWorks64TcpStream_ReportConnectFailure(self, severity, detail);
     238                 :             :     }
     239                 :          15 : }
     240                 :             : 
     241                 :             : /* A failed connect closes its socket, which would otherwise be held until
     242                 :             :  * Destroy. */
     243                 :          57 : static bool VxWorks64TcpStream_ConnectOrCloseOnFailure(
     244                 :             :     struct SolidSyslogVxWorks64TcpStream* self,
     245                 :             :     const struct sockaddr_in* sin
     246                 :             : )
     247                 :             : {
     248                 :          57 :     bool connected = VxWorks64TcpStream_Connect(self, sin);
     249         [ +  + ]:          57 :     if (connected)
     250                 :             :     {
     251                 :          44 :         VxWorks64TcpStream_ApplySocketOptions(self->Fd);
     252                 :             :     }
     253                 :             :     else
     254                 :             :     {
     255                 :          13 :         VxWorks64TcpStream_CloseSocket(self);
     256                 :             :     }
     257                 :          57 :     return connected;
     258                 :             : }
     259                 :             : 
     260                 :             : /* connectWithTimeout reports the bound expiring as EINPROGRESS. An attempt
     261                 :             :  * still under way when it returns dies with the socket. */
     262                 :          57 : static bool VxWorks64TcpStream_Connect(struct SolidSyslogVxWorks64TcpStream* self, const struct sockaddr_in* sin)
     263                 :             : {
     264                 :          57 :     struct timeval timeout = VxWorks64TcpStream_ResolveConnectTimeout(self);
     265                 :             :     /* sockLib takes a non-const address that it only reads (D.006). */
     266                 :          57 :     STATUS status = connectWithTimeout(self->Fd, (struct sockaddr*) sin, (int) sizeof(*sin), &timeout);
     267                 :             :     /* Read errno straight after the call that set it, with nothing between
     268                 :             :      * (MISRA 22.10). */
     269         [ +  + ]:          57 :     int connectErrno = (status == ERROR) ? errno : 0;
     270                 :          57 :     bool connected = (status == OK);
     271                 :             :     /* Each failure carries the errno connectWithTimeout left, the bound
     272                 :             :      * expiring included: EINPROGRESS is how it says so. */
     273         [ +  + ]:          57 :     if (connectErrno == EINPROGRESS)
     274                 :             :     {
     275                 :           1 :         VxWorks64TcpStream_ReportConnectFailureWithErrno(
     276                 :             :             self,
     277                 :             :             SOLIDSYSLOG_STREAM_CONNECT_REMOTE_SEVERITY,
     278                 :             :             SOLIDSYSLOG_TCP_STREAM_ERROR_CONNECT_TIMED_OUT,
     279                 :             :             connectErrno
     280                 :             :         );
     281                 :             :     }
     282         [ +  + ]:          56 :     else if (VxWorks64TcpStream_IsRemoteConnectError(connectErrno))
     283                 :             :     {
     284                 :           9 :         VxWorks64TcpStream_ReportConnectFailureWithErrno(
     285                 :             :             self,
     286                 :             :             SOLIDSYSLOG_STREAM_CONNECT_REMOTE_SEVERITY,
     287                 :             :             SOLIDSYSLOG_TCP_STREAM_ERROR_CONNECT_REFUSED,
     288                 :             :             connectErrno
     289                 :             :         );
     290                 :             :     }
     291         [ +  + ]:          47 :     else if (!connected)
     292                 :             :     {
     293                 :           3 :         VxWorks64TcpStream_ReportConnectFailureWithErrno(
     294                 :             :             self,
     295                 :             :             SOLIDSYSLOG_STREAM_CONNECT_LOCAL_SEVERITY,
     296                 :             :             SOLIDSYSLOG_TCP_STREAM_ERROR_CONNECT_NOT_STARTED,
     297                 :             :             connectErrno
     298                 :             :         );
     299                 :             :     }
     300                 :             :     else
     301                 :             :     {
     302                 :             :         /* connected - nothing to report */
     303                 :             :     }
     304                 :          57 :     return connected;
     305                 :             : }
     306                 :             : 
     307                 :          57 : static struct timeval VxWorks64TcpStream_ResolveConnectTimeout(struct SolidSyslogVxWorks64TcpStream* self)
     308                 :             : {
     309                 :          57 :     uint32_t requestedMs = self->Config.GetConnectTimeoutMs(self->Config.ConnectTimeoutContext);
     310                 :          57 :     uint32_t ms =
     311                 :             :         (requestedMs > SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS_MAX) ? SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS_MAX : requestedMs;
     312                 :          57 :     uint32_t seconds = ms / (uint32_t) MILLISECONDS_PER_SECOND;
     313                 :          57 :     uint32_t microseconds = (ms % (uint32_t) MILLISECONDS_PER_SECOND) * (uint32_t) MICROSECONDS_PER_MILLISECOND;
     314                 :             :     struct timeval timeout;
     315                 :          57 :     timeout.tv_sec = (long) seconds;
     316                 :          57 :     timeout.tv_usec = (long) microseconds;
     317                 :          57 :     return timeout;
     318                 :             : }
     319                 :             : 
     320                 :             : /* Remote: a SYN was sent and drew a reset or nothing. Any other failure is
     321                 :             :  * local, and nothing left this device. */
     322                 :          56 : static inline bool VxWorks64TcpStream_IsRemoteConnectError(int connectErrno)
     323                 :             : {
     324   [ +  +  +  + ]:          56 :     return (connectErrno == ECONNREFUSED) || (connectErrno == ETIMEDOUT);
     325                 :             : }
     326                 :             : 
     327                 :             : /* NODELAY stops a small record waiting to coalesce; keepalive detects a peer
     328                 :             :  * lost while idle. Set after connecting, so a refusal is reported only on a
     329                 :             :  * connection that stands. */
     330                 :          44 : static void VxWorks64TcpStream_ApplySocketOptions(int fd)
     331                 :             : {
     332                 :          44 :     int enable = 1;
     333                 :          44 :     bool allAccepted = (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*) &enable, (int) sizeof(enable)) == OK);
     334                 :          44 :     allAccepted =
     335   [ +  +  +  + ]:          44 :         (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*) &enable, (int) sizeof(enable)) == OK) && allAccepted;
     336         [ +  + ]:          44 :     if (!allAccepted)
     337                 :             :     {
     338                 :           3 :         VxWorks64TcpStream_ReportOptionRefused();
     339                 :             :     }
     340                 :          44 : }
     341                 :             : 
     342                 :             : /* One event per attempt, however many options were refused. */
     343                 :           3 : static void VxWorks64TcpStream_ReportOptionRefused(void)
     344                 :             : {
     345                 :           3 :     VxWorks64TcpStream_Report(
     346                 :             :         SOLIDSYSLOG_SEVERITY_WARNING,
     347                 :             :         SOLIDSYSLOG_CAT_STREAM_OPTION_REFUSED,
     348                 :             :         SOLIDSYSLOG_TCP_STREAM_ERROR_SOCKET_OPTION_REFUSED
     349                 :             :     );
     350                 :           3 : }
     351                 :             : 
     352                 :          17 : static bool VxWorks64TcpStream_Send(struct SolidSyslogStream* base, const void* buffer, size_t size)
     353                 :             : {
     354                 :          17 :     struct SolidSyslogVxWorks64TcpStream* self = VxWorks64TcpStream_SelfFromBase(base);
     355   [ +  +  +  + ]:          17 :     bool ok = VxWorks64TcpStream_FitsTheStack(size) && VxWorks64TcpStream_PeerIsStillThere(self);
     356         [ +  + ]:          17 :     if (ok)
     357                 :             :     {
     358                 :          13 :         int sent = send(self->Fd, (const char*) buffer, (int) size, MSG_DONTWAIT);
     359                 :          13 :         ok = VxWorks64TcpStream_WroteAllBytes(sent, size);
     360                 :             :     }
     361         [ +  + ]:          17 :     if (!ok)
     362                 :             :     {
     363                 :           7 :         VxWorks64TcpStream_CloseSocket(self);
     364                 :             :     }
     365                 :          17 :     return ok;
     366                 :             : }
     367                 :             : 
     368                 :             : /* The stack takes a record's length as an int. */
     369                 :          26 : static inline bool VxWorks64TcpStream_FitsTheStack(size_t size)
     370                 :             : {
     371                 :          26 :     return size <= (size_t) INT_MAX;
     372                 :             : }
     373                 :             : 
     374                 :             : /* A peer's FIN leaves the socket writable, so peek first: send would accept a
     375                 :             :  * record that cannot arrive. Bytes the peer sent that nothing has read stand in
     376                 :             :  * front of its FIN, and the peek sees those instead; a syslog collector sends
     377                 :             :  * nothing back, so the queue is empty when the check runs. */
     378                 :          16 : static bool VxWorks64TcpStream_PeerIsStillThere(const struct SolidSyslogVxWorks64TcpStream* self)
     379                 :             : {
     380                 :          16 :     char discard = 0;
     381                 :          16 :     int peeked = recv(self->Fd, &discard, (int) sizeof(discard), MSG_PEEK | MSG_DONTWAIT);
     382         [ +  + ]:          16 :     int peekErrno = (peeked == ERROR) ? errno : 0;
     383   [ +  +  +  +  :          16 :     return (peeked > 0) || ((peeked == ERROR) && VxWorks64TcpStream_WouldBlock(peekErrno));
                   +  + ]
     384                 :             : }
     385                 :             : 
     386                 :             : /* EWOULDBLOCK and EAGAIN are distinct values in VxWorks 6.4. */
     387                 :          19 : static inline bool VxWorks64TcpStream_WouldBlock(int err)
     388                 :             : {
     389   [ +  +  -  + ]:          19 :     return (err == EWOULDBLOCK) || (err == EAGAIN);
     390                 :             : }
     391                 :             : 
     392                 :             : /* A short write or any error means the record did not go whole. */
     393                 :          13 : static inline bool VxWorks64TcpStream_WroteAllBytes(int sent, size_t expected)
     394                 :             : {
     395   [ +  +  +  + ]:          13 :     return (sent >= 0) && ((size_t) sent == expected);
     396                 :             : }
     397                 :             : 
     398                 :           9 : static SolidSyslogSsize VxWorks64TcpStream_Read(struct SolidSyslogStream* base, void* buffer, size_t size)
     399                 :             : {
     400                 :           9 :     struct SolidSyslogVxWorks64TcpStream* self = VxWorks64TcpStream_SelfFromBase(base);
     401                 :           9 :     int received = recv(self->Fd, (char*) buffer, VxWorks64TcpStream_ClampToTheStack(size), MSG_DONTWAIT);
     402         [ +  + ]:           9 :     int recvErrno = (received == ERROR) ? errno : 0;
     403                 :           9 :     SolidSyslogSsize result = -1;
     404         [ +  + ]:           9 :     if (received > 0)
     405                 :             :     {
     406                 :           1 :         result = (SolidSyslogSsize) received;
     407                 :             :     }
     408   [ +  +  +  + ]:           8 :     else if ((received == ERROR) && VxWorks64TcpStream_WouldBlock(recvErrno))
     409                 :             :     {
     410                 :           5 :         result = 0;
     411                 :             :     }
     412                 :             :     else
     413                 :             :     {
     414                 :             :         /* The peer closed, or the connection failed. Close before reporting
     415                 :             :          * it, as the Stream contract asks. */
     416                 :           3 :         VxWorks64TcpStream_CloseSocket(self);
     417                 :             :     }
     418                 :           9 :     return result;
     419                 :             : }
     420                 :             : 
     421                 :             : /* The stack takes a buffer's length as an int. */
     422                 :           9 : static inline int VxWorks64TcpStream_ClampToTheStack(size_t size)
     423                 :             : {
     424         [ +  + ]:           9 :     return VxWorks64TcpStream_FitsTheStack(size) ? (int) size : INT_MAX;
     425                 :             : }
     426                 :             : 
     427                 :           7 : static void VxWorks64TcpStream_Close(struct SolidSyslogStream* base)
     428                 :             : {
     429                 :           7 :     VxWorks64TcpStream_CloseSocket(VxWorks64TcpStream_SelfFromBase(base));
     430                 :           7 : }
     431                 :             : 
     432                 :             : /* No runtime-tunable configuration; the destination is versioned by the
     433                 :             :  * sender's endpoint. */
     434                 :           3 : static uint32_t VxWorks64TcpStream_Version(struct SolidSyslogStream* base)
     435                 :             : {
     436                 :             :     (void) base;
     437                 :           3 :     return 0U;
     438                 :             : }
        

Generated by: LCOV version 2.0-1