Line data Source code
1 : #if FD_HAS_HOSTED 2 : 3 : #include "fd_tlsrec_sock.h" 4 : 5 : #include <errno.h> 6 : #include <sys/socket.h> 7 : 8 : int 9 : fd_tlsrec_sock_flush( fd_tlsrec_sock_t * sock, 10 3 : int fd ) { 11 6 : while( sock->tx_off<sock->tx_sz ) { 12 3 : long sent = send( fd, sock->tx_buf+sock->tx_off, sock->tx_sz-sock->tx_off, MSG_NOSIGNAL|MSG_DONTWAIT ); 13 3 : if( FD_UNLIKELY( sent<0L ) ) { 14 0 : if( errno==EINTR ) continue; 15 0 : if( errno==EAGAIN || errno==EWOULDBLOCK ) return 1; 16 0 : return FD_TLSREC_SOCK_ERR_SEND; 17 0 : } 18 3 : sock->tx_off += (ulong)sent; 19 3 : } 20 3 : sock->tx_off = 0UL; 21 3 : sock->tx_sz = 0UL; 22 3 : return 0; 23 3 : } 24 : 25 : int 26 : fd_tlsrec_sock_rx( fd_tlsrec_sock_t * sock, 27 : fd_tlsrec_conn_t * conn, 28 : int fd, 29 15 : ulong * opt_rx_sz ) { 30 15 : if( opt_rx_sz ) *opt_rx_sz = 0UL; 31 : 32 15 : ulong tx_free = sizeof(sock->tx_buf) - sock->tx_sz; 33 15 : if( FD_UNLIKELY( fd_tlsrec_sock_rx_avail( sock ) || tx_free<FD_TLSREC_SOCK_TX_RESERVE ) ) return 0; 34 12 : if( FD_UNLIKELY( conn->rx_closed ) ) return FD_TLSREC_SOCK_ERR_EOF; 35 : 36 9 : uchar tcp_rx_buf[ FD_TLSREC_SOCK_RX_MTU ]; 37 9 : long tcp_rx_sz; 38 9 : do { 39 9 : tcp_rx_sz = recv( fd, tcp_rx_buf, sizeof(tcp_rx_buf), MSG_NOSIGNAL|MSG_DONTWAIT ); 40 9 : } while( FD_UNLIKELY( tcp_rx_sz<0L && errno==EINTR ) ); 41 9 : if( tcp_rx_sz<0L ) { 42 0 : if( errno==EAGAIN || errno==EWOULDBLOCK ) tcp_rx_sz = 0L; 43 0 : else return FD_TLSREC_SOCK_ERR_RECV; 44 9 : } else if( FD_UNLIKELY( !tcp_rx_sz ) ) { 45 0 : return FD_TLSREC_SOCK_ERR_EOF; 46 0 : } 47 : 48 9 : fd_tlsrec_slice_t tcp_rx[1]; 49 9 : fd_tlsrec_slice_init( tcp_rx, tcp_rx_buf, (ulong)tcp_rx_sz ); 50 9 : ulong tcp_tx_sz = tx_free; 51 9 : ulong app_rx_sz = sizeof(sock->rx_buf); 52 9 : int err = fd_tlsrec_conn_rx( conn, tcp_rx_sz ? tcp_rx : NULL, 53 9 : sock->tx_buf+sock->tx_sz, &tcp_tx_sz, 54 9 : sock->rx_buf, &app_rx_sz ); 55 9 : sock->rx_off = 0UL; 56 9 : sock->rx_sz = app_rx_sz; 57 9 : sock->tx_sz += tcp_tx_sz; 58 : 59 : /* Send before reporting a TLS error so an alert reaches the peer */ 60 9 : if( tcp_tx_sz && FD_UNLIKELY( fd_tlsrec_sock_flush( sock, fd )<0 ) ) return FD_TLSREC_SOCK_ERR_SEND; 61 9 : if( FD_UNLIKELY( err ) ) return err; 62 9 : if( FD_UNLIKELY( conn->rx_closed && !app_rx_sz ) ) return FD_TLSREC_SOCK_ERR_EOF; 63 : 64 3 : if( opt_rx_sz ) *opt_rx_sz = (ulong)tcp_rx_sz; 65 3 : return 0; 66 9 : } 67 : 68 : int 69 : fd_tlsrec_sock_close( fd_tlsrec_sock_t * sock, 70 : fd_tlsrec_conn_t * conn, 71 6 : int fd ) { 72 6 : ulong tcp_tx_sz = sizeof(sock->tx_buf) - sock->tx_sz; 73 6 : int err = fd_tlsrec_conn_close( conn, sock->tx_buf+sock->tx_sz, &tcp_tx_sz ); 74 6 : if( FD_UNLIKELY( err ) ) return err; 75 3 : sock->tx_sz += tcp_tx_sz; 76 3 : return fd_tlsrec_sock_flush( sock, fd ); 77 6 : } 78 : 79 : int 80 : fd_tlsrec_sock_tx( fd_tlsrec_sock_t * sock, 81 : fd_tlsrec_conn_t * conn, 82 : int fd, 83 : void const * app, 84 : ulong app_sz, 85 0 : ulong * opt_consumed ) { 86 0 : if( opt_consumed ) *opt_consumed = 0UL; 87 0 : if( FD_UNLIKELY( sock->tx_sz ) ) return 0; 88 : 89 0 : fd_tlsrec_slice_t app_tx[1]; 90 0 : fd_tlsrec_slice_init( app_tx, (uchar *)app, app_sz ); 91 0 : ulong tcp_tx_sz = sizeof(sock->tx_buf); 92 0 : int err = fd_tlsrec_conn_tx( conn, sock->tx_buf, &tcp_tx_sz, app_tx ); 93 0 : if( FD_UNLIKELY( err ) ) return err; 94 0 : sock->tx_off = 0UL; 95 0 : sock->tx_sz = tcp_tx_sz; 96 0 : if( opt_consumed ) *opt_consumed = app_sz - fd_tlsrec_slice_sz( app_tx ); 97 : 98 0 : if( FD_UNLIKELY( fd_tlsrec_sock_flush( sock, fd )<0 ) ) return FD_TLSREC_SOCK_ERR_SEND; 99 0 : return 0; 100 0 : } 101 : 102 : char const * 103 0 : fd_tlsrec_sock_strerror( int err ) { 104 0 : switch( err ) { 105 0 : case 0: return "success"; 106 0 : case FD_TLSREC_SOCK_ERR_RECV: return "recv failed"; 107 0 : case FD_TLSREC_SOCK_ERR_SEND: return "send failed"; 108 0 : case FD_TLSREC_SOCK_ERR_EOF: return "peer closed connection"; 109 0 : default: return err>0 ? fd_tlsrec_strerror( err ) : "unknown"; 110 0 : } 111 0 : } 112 : 113 : #endif /* FD_HAS_HOSTED */