Line data Source code
1 : #ifndef HEADER_fd_src_waltz_h2_fd_h2_rbuf_sock_h 2 : #define HEADER_fd_src_waltz_h2_fd_h2_rbuf_sock_h 3 : 4 : #include "fd_h2_rbuf.h" 5 : 6 : #if FD_H2_HAS_SOCKETS 7 : 8 : #include <errno.h> 9 : #include <sys/socket.h> 10 : 11 : static inline ulong 12 : fd_h2_rbuf_prepare_recvmsg( fd_h2_rbuf_t * rbuf, 13 27 : struct iovec iov[2] ) { 14 27 : uchar * buf0 = rbuf->buf0; 15 27 : uchar * buf1 = rbuf->buf1; 16 27 : uchar * lo = rbuf->lo; 17 27 : uchar * hi = rbuf->hi; 18 27 : ulong free_sz = fd_h2_rbuf_free_sz( rbuf ); 19 27 : if( FD_UNLIKELY( !free_sz ) ) return 0UL; 20 : 21 27 : if( lo<=hi ) { 22 : 23 27 : iov[ 0 ].iov_base = hi; 24 27 : iov[ 0 ].iov_len = fd_ulong_min( (ulong)( buf1-hi ), free_sz ); 25 27 : free_sz -= iov[ 0 ].iov_len; 26 27 : iov[ 1 ].iov_base = buf0; 27 27 : iov[ 1 ].iov_len = fd_ulong_min( (ulong)( lo-buf0 ), free_sz ); 28 27 : return 2UL; 29 : 30 27 : } else { 31 : 32 0 : iov[ 0 ].iov_base = hi; 33 0 : iov[ 0 ].iov_len = free_sz; 34 0 : iov[ 1 ].iov_base = NULL; 35 0 : iov[ 1 ].iov_len = 0UL; 36 0 : return 1uL; 37 : 38 0 : } 39 27 : } 40 : 41 : static inline void 42 : fd_h2_rbuf_commit_recvmsg( fd_h2_rbuf_t * rbuf, 43 : struct iovec const iovec[2], 44 0 : ulong sz ) { 45 0 : uchar * buf0 = rbuf->buf0; 46 0 : uchar * buf1 = rbuf->buf1; 47 0 : struct iovec iov0 = iovec[0]; 48 0 : struct iovec iov1 = iovec[1]; 49 0 : rbuf->hi_off += sz; 50 0 : if( sz > iov0.iov_len ) { 51 0 : rbuf->hi = (uchar *)iov1.iov_base + ( sz - iov0.iov_len ); 52 0 : } else { 53 0 : rbuf->hi = (uchar *)iov0.iov_base + sz; 54 0 : } 55 0 : if( rbuf->hi == buf1 ) rbuf->hi = buf0; /* cmov */ 56 0 : } 57 : 58 : static inline int 59 : fd_h2_rbuf_recvmsg( fd_h2_rbuf_t * rbuf, 60 : int sock, 61 27 : int flags ) { 62 27 : struct iovec iov[2]; 63 27 : ulong iov_cnt = fd_h2_rbuf_prepare_recvmsg( rbuf, iov ); 64 27 : if( FD_UNLIKELY( !iov_cnt ) ) return 0; 65 : 66 27 : struct msghdr msg = { 67 27 : .msg_iov = iov, 68 27 : .msg_iovlen = iov_cnt 69 27 : }; 70 27 : ssize_t sz = recvmsg( sock, &msg, flags ); 71 27 : if( sz<0 ) { 72 27 : if( FD_LIKELY( errno==EAGAIN ) ) return 0; 73 0 : return errno; 74 27 : } else if( FD_UNLIKELY( sz==0 ) ) { 75 0 : return EPIPE; 76 0 : } 77 : 78 0 : fd_h2_rbuf_commit_recvmsg( rbuf, iov, (ulong)sz ); 79 0 : return 0; 80 27 : } 81 : 82 : static inline ulong 83 : fd_h2_rbuf_prepare_sendmsg( fd_h2_rbuf_t * rbuf, 84 39 : struct iovec iov[2] ) { 85 39 : uchar * buf0 = rbuf->buf0; 86 39 : uchar * buf1 = rbuf->buf1; 87 39 : uchar * lo = rbuf->lo; 88 39 : uchar * hi = rbuf->hi; 89 39 : ulong used_sz = fd_h2_rbuf_used_sz( rbuf ); 90 39 : if( FD_UNLIKELY( !used_sz ) ) return 0UL; 91 : 92 12 : if( hi<=lo ) { 93 : 94 0 : iov[ 0 ].iov_base = lo; 95 0 : iov[ 0 ].iov_len = fd_ulong_min( (ulong)( buf1-lo ), used_sz ); 96 0 : used_sz -= iov[ 0 ].iov_len; 97 0 : iov[ 1 ].iov_base = buf0; 98 0 : iov[ 1 ].iov_len = fd_ulong_min( (ulong)( hi-buf0 ), used_sz ); 99 0 : return 2UL; 100 : 101 12 : } else { 102 : 103 12 : iov[ 0 ].iov_base = lo; 104 12 : iov[ 0 ].iov_len = used_sz; 105 12 : iov[ 1 ].iov_base = NULL; 106 12 : iov[ 1 ].iov_len = 0UL; 107 12 : return 1uL; 108 : 109 12 : } 110 12 : } 111 : 112 : static inline void 113 : fd_h2_rbuf_commit_sendmsg( fd_h2_rbuf_t * rbuf, 114 : struct iovec const iovec[2], 115 12 : ulong sz ) { 116 12 : uchar * buf0 = rbuf->buf0; 117 12 : uchar * buf1 = rbuf->buf1; 118 12 : struct iovec iov0 = iovec[0]; 119 12 : struct iovec iov1 = iovec[1]; 120 12 : rbuf->lo_off += sz; 121 12 : if( sz > iov0.iov_len ) { 122 0 : rbuf->lo = (uchar *)iov1.iov_base + ( sz - iov0.iov_len ); 123 12 : } else { 124 12 : rbuf->lo = (uchar *)iov0.iov_base + sz; 125 12 : } 126 12 : if( rbuf->lo == buf1 ) rbuf->lo = buf0; /* cmov */ 127 12 : } 128 : 129 : static inline int 130 : fd_h2_rbuf_sendmsg( fd_h2_rbuf_t * rbuf, 131 : int sock, 132 39 : int flags ) { 133 39 : struct iovec iov[2]; 134 39 : ulong iov_cnt = fd_h2_rbuf_prepare_sendmsg( rbuf, iov ); 135 39 : if( FD_UNLIKELY( !iov_cnt ) ) return 0; 136 : 137 12 : struct msghdr msg = { 138 12 : .msg_iov = iov, 139 12 : .msg_iovlen = iov_cnt 140 12 : }; 141 12 : ssize_t sz = sendmsg( sock, &msg, flags ); 142 12 : if( sz<0 ) { 143 0 : return errno; 144 0 : } 145 : 146 12 : fd_h2_rbuf_commit_sendmsg( rbuf, iov, (ulong)sz ); 147 12 : return 0; 148 12 : } 149 : 150 : #endif /* FD_H2_HAS_SOCKETS */ 151 : 152 : #endif /* HEADER_fd_src_waltz_h2_fd_h2_rbuf_sock_h */