LCOV - code coverage report
Current view: top level - utils - s2n_socket.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 91 125 72.8 %
Date: 2026-07-04 07:27:58 Functions: 8 10 80.0 %
Branches: 32 126 25.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License").
       5                 :            :  * You may not use this file except in compliance with the License.
       6                 :            :  * A copy of the License is located at
       7                 :            :  *
       8                 :            :  *  http://aws.amazon.com/apache2.0
       9                 :            :  *
      10                 :            :  * or in the "license" file accompanying this file. This file is distributed
      11                 :            :  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
      12                 :            :  * express or implied. See the License for the specific language governing
      13                 :            :  * permissions and limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : /* On Windows, s2n-tls does not provide built-in socket I/O.
      17                 :            :  * This file compiles to an empty translation unit on Windows.
      18                 :            :  */
      19                 :            : #ifndef _WIN32
      20                 :            : 
      21                 :            :     #include "utils/s2n_socket.h"
      22                 :            : 
      23                 :            :     #include <netinet/in.h>
      24                 :            :     #include <netinet/tcp.h>
      25                 :            :     #include <sys/socket.h>
      26                 :            :     #include <unistd.h>
      27                 :            : 
      28                 :            :     #include "tls/s2n_connection.h"
      29                 :            :     #include "utils/s2n_safety.h"
      30                 :            : 
      31                 :            :     #if TCP_CORK
      32                 :       7099 :         #define S2N_CORK     TCP_CORK
      33                 :         62 :         #define S2N_CORK_ON  1
      34                 :         72 :         #define S2N_CORK_OFF 0
      35                 :            :     #elif TCP_NOPUSH
      36                 :            :         #define S2N_CORK     TCP_NOPUSH
      37                 :            :         #define S2N_CORK_ON  1
      38                 :            :         #define S2N_CORK_OFF 0
      39                 :            :     #elif TCP_NODELAY
      40                 :            :         #define S2N_CORK     TCP_NODELAY
      41                 :            :         #define S2N_CORK_ON  0
      42                 :            :         #define S2N_CORK_OFF 1
      43                 :            :     #endif
      44                 :            : 
      45                 :            : int s2n_socket_quickack(struct s2n_connection *conn)
      46                 :     101245 : {
      47                 :     101245 :     #ifdef TCP_QUICKACK
      48 [ -  + ][ #  # ]:     101245 :     POSIX_ENSURE_REF(conn);
      49         [ +  + ]:     101245 :     if (!conn->managed_recv_io) {
      50                 :      41675 :         return 0;
      51                 :      41675 :     }
      52                 :            : 
      53                 :      59570 :     struct s2n_socket_read_io_context *r_io_ctx = (struct s2n_socket_read_io_context *) conn->recv_io_context;
      54 [ #  # ][ -  + ]:      59570 :     POSIX_ENSURE_REF(r_io_ctx);
      55         [ +  + ]:      59570 :     if (r_io_ctx->tcp_quickack_set) {
      56                 :          9 :         return 0;
      57                 :          9 :     }
      58                 :            : 
      59                 :            :     /* Ignore the return value, if it fails it fails */
      60                 :      59561 :     int optval = 1;
      61         [ +  + ]:      59561 :     if (setsockopt(r_io_ctx->fd, IPPROTO_TCP, TCP_QUICKACK, &optval, sizeof(optval)) == 0) {
      62                 :         11 :         r_io_ctx->tcp_quickack_set = 1;
      63                 :         11 :     }
      64                 :      59561 :     #endif
      65                 :            : 
      66                 :      59561 :     return 0;
      67                 :      59570 : }
      68                 :            : 
      69                 :            : int s2n_socket_write_snapshot(struct s2n_connection *conn)
      70                 :       6965 : {
      71                 :       6965 :     #ifdef S2N_CORK
      72                 :       6965 :     socklen_t corklen = sizeof(int);
      73 [ -  + ][ #  # ]:       6965 :     POSIX_ENSURE_REF(conn);
      74                 :       6965 :     struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
      75 [ #  # ][ -  + ]:       6965 :     POSIX_ENSURE_REF(w_io_ctx);
      76                 :            : 
      77                 :       6965 :     getsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &w_io_ctx->original_cork_val, &corklen);
      78 [ -  + ][ #  # ]:       6965 :     POSIX_ENSURE_EQ(corklen, sizeof(int));
      79                 :       6965 :     w_io_ctx->original_cork_is_set = 1;
      80                 :       6965 :     #endif
      81                 :            : 
      82                 :       6965 :     return 0;
      83                 :       6965 : }
      84                 :            : 
      85                 :            : int s2n_socket_read_snapshot(struct s2n_connection *conn)
      86                 :       6960 : {
      87                 :       6960 :     #ifdef SO_RCVLOWAT
      88                 :       6960 :     socklen_t watlen = sizeof(int);
      89 [ #  # ][ -  + ]:       6960 :     POSIX_ENSURE_REF(conn);
      90                 :       6960 :     struct s2n_socket_read_io_context *r_io_ctx = (struct s2n_socket_read_io_context *) conn->recv_io_context;
      91 [ -  + ][ #  # ]:       6960 :     POSIX_ENSURE_REF(r_io_ctx);
      92                 :            : 
      93                 :       6960 :     getsockopt(r_io_ctx->fd, SOL_SOCKET, SO_RCVLOWAT, &r_io_ctx->original_rcvlowat_val, &watlen);
      94 [ #  # ][ -  + ]:       6960 :     POSIX_ENSURE_EQ(watlen, sizeof(int));
      95                 :       6960 :     r_io_ctx->original_rcvlowat_is_set = 1;
      96                 :       6960 :     #endif
      97                 :            : 
      98                 :       6960 :     return 0;
      99                 :       6960 : }
     100                 :            : 
     101                 :            : int s2n_socket_write_restore(struct s2n_connection *conn)
     102                 :          0 : {
     103                 :          0 :     #ifdef S2N_CORK
     104 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(conn);
     105                 :          0 :     struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
     106 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(w_io_ctx);
     107                 :            : 
     108         [ #  # ]:          0 :     if (!w_io_ctx->original_cork_is_set) {
     109                 :          0 :         return 0;
     110                 :          0 :     }
     111                 :          0 :     setsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &w_io_ctx->original_cork_val, sizeof(w_io_ctx->original_cork_val));
     112                 :          0 :     w_io_ctx->original_cork_is_set = 0;
     113                 :          0 :     #endif
     114                 :            : 
     115                 :          0 :     return 0;
     116                 :          0 : }
     117                 :            : 
     118                 :            : int s2n_socket_read_restore(struct s2n_connection *conn)
     119                 :          0 : {
     120                 :          0 :     #ifdef SO_RCVLOWAT
     121 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(conn);
     122                 :          0 :     struct s2n_socket_read_io_context *r_io_ctx = (struct s2n_socket_read_io_context *) conn->recv_io_context;
     123 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(r_io_ctx);
     124                 :            : 
     125         [ #  # ]:          0 :     if (!r_io_ctx->original_rcvlowat_is_set) {
     126                 :          0 :         return 0;
     127                 :          0 :     }
     128                 :          0 :     setsockopt(r_io_ctx->fd, SOL_SOCKET, SO_RCVLOWAT, &r_io_ctx->original_rcvlowat_val, sizeof(r_io_ctx->original_rcvlowat_val));
     129                 :          0 :     r_io_ctx->original_rcvlowat_is_set = 0;
     130                 :          0 :     #endif
     131                 :            : 
     132                 :          0 :     return 0;
     133                 :          0 : }
     134                 :            : 
     135                 :            : int s2n_socket_was_corked(struct s2n_connection *conn)
     136                 :        340 : {
     137 [ -  + ][ #  # ]:        340 :     POSIX_ENSURE_REF(conn);
     138                 :            :     /* If we're not using custom I/O and a send fd has not been set yet, return false*/
     139 [ -  + ][ -  + ]:        340 :     if (!conn->managed_send_io || !conn->send) {
     140                 :          0 :         return 0;
     141                 :          0 :     }
     142                 :            : 
     143                 :        340 :     struct s2n_socket_write_io_context *io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
     144 [ -  + ][ #  # ]:        340 :     POSIX_ENSURE_REF(io_ctx);
     145                 :            : 
     146                 :        340 :     return io_ctx->original_cork_val;
     147                 :        340 : }
     148                 :            : 
     149                 :            : int s2n_socket_write_cork(struct s2n_connection *conn)
     150                 :         62 : {
     151                 :         62 :     #ifdef S2N_CORK
     152 [ #  # ][ -  + ]:         62 :     POSIX_ENSURE_REF(conn);
     153                 :         62 :     int optval = S2N_CORK_ON;
     154                 :            : 
     155                 :         62 :     struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
     156 [ -  + ][ #  # ]:         62 :     POSIX_ENSURE_REF(w_io_ctx);
     157                 :            : 
     158                 :            :     /* Ignore the return value, if it fails it fails */
     159                 :         62 :     setsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &optval, sizeof(optval));
     160                 :         62 :     #endif
     161                 :            : 
     162                 :         62 :     return 0;
     163                 :         62 : }
     164                 :            : 
     165                 :            : int s2n_socket_write_uncork(struct s2n_connection *conn)
     166                 :         72 : {
     167                 :         72 :     #ifdef S2N_CORK
     168 [ #  # ][ -  + ]:         72 :     POSIX_ENSURE_REF(conn);
     169                 :         72 :     int optval = S2N_CORK_OFF;
     170                 :            : 
     171                 :         72 :     struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
     172 [ #  # ][ -  + ]:         72 :     POSIX_ENSURE_REF(w_io_ctx);
     173                 :            : 
     174                 :            :     /* Ignore the return value, if it fails it fails */
     175                 :         72 :     setsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &optval, sizeof(optval));
     176                 :         72 :     #endif
     177                 :            : 
     178                 :         72 :     return 0;
     179                 :         72 : }
     180                 :            : 
     181                 :            : int s2n_socket_read(void *io_context, uint8_t *buf, uint32_t len)
     182                 :     467589 : {
     183 [ -  + ][ #  # ]:     467589 :     POSIX_ENSURE_REF(io_context);
     184 [ -  + ][ #  # ]:     467589 :     POSIX_ENSURE_REF(buf);
     185                 :     467589 :     int rfd = ((struct s2n_socket_read_io_context *) io_context)->fd;
     186         [ -  + ]:     467589 :     if (rfd < 0) {
     187                 :          0 :         errno = EBADF;
     188         [ #  # ]:          0 :         POSIX_BAIL(S2N_ERR_BAD_FD);
     189                 :          0 :     }
     190                 :            : 
     191                 :            :     /* Clear the quickack flag so we know to reset it */
     192                 :     467589 :     ((struct s2n_socket_read_io_context *) io_context)->tcp_quickack_set = 0;
     193                 :            : 
     194                 :            :     /* On success, the number of bytes read is returned. On failure, -1 is
     195                 :            :      * returned and errno is set appropriately. */
     196                 :     467589 :     ssize_t result = read(rfd, buf, len);
     197 [ #  # ][ -  + ]:     467589 :     POSIX_ENSURE_INCLUSIVE_RANGE(INT_MIN, result, INT_MAX);
         [ #  # ][ -  + ]
     198                 :     467589 :     return result;
     199                 :     467589 : }
     200                 :            : 
     201                 :            : int s2n_socket_write(void *io_context, const uint8_t *buf, uint32_t len)
     202                 :     368603 : {
     203 [ #  # ][ -  + ]:     368603 :     POSIX_ENSURE_REF(io_context);
     204 [ -  + ][ #  # ]:     368603 :     POSIX_ENSURE_REF(buf);
     205                 :     368603 :     int wfd = ((struct s2n_socket_write_io_context *) io_context)->fd;
     206         [ -  + ]:     368603 :     if (wfd < 0) {
     207                 :          0 :         errno = EBADF;
     208         [ #  # ]:          0 :         POSIX_BAIL(S2N_ERR_BAD_FD);
     209                 :          0 :     }
     210                 :            : 
     211                 :            :     /* On success, the number of bytes written is returned. On failure, -1 is
     212                 :            :      * returned and errno is set appropriately. */
     213                 :     368603 :     ssize_t result = write(wfd, buf, len);
     214 [ #  # ][ -  + ]:     368603 :     POSIX_ENSURE_INCLUSIVE_RANGE(INT_MIN, result, INT_MAX);
         [ #  # ][ -  + ]
     215                 :     368603 :     return result;
     216                 :     368603 : }
     217                 :            : 
     218                 :            : #endif
     219                 :            : 
     220                 :            : /* Suppress empty translation unit warning when compiled on Windows. */
     221                 :            : #pragma clang diagnostic ignored "-Wempty-translation-unit"

Generated by: LCOV version 1.14