Line data Source code
1 : #ifndef HEADER_fd_src_waltz_grpc_fd_grpc_client_private_h 2 : #define HEADER_fd_src_waltz_grpc_fd_grpc_client_private_h 3 : 4 : #include "fd_grpc_client.h" 5 : #include "../grpc/fd_grpc_codec.h" 6 : #include "../h2/fd_h2.h" 7 : #include "../tlsrec/fd_tlsrec_sock.h" 8 : 9 : /* fd_grpc_h2_stream_t holds the state of a gRPC request. */ 10 : 11 : struct fd_grpc_h2_stream { 12 : fd_h2_stream_t s; 13 : 14 : ulong request_ctx; 15 : uint next; 16 : 17 : /* Buffer response headers */ 18 : fd_grpc_resp_hdrs_t hdrs; 19 : 20 : /* Buffer an incoming gRPC message */ 21 : uchar * msg_buf; 22 : ulong msg_buf_max; 23 : uint hdrs_received : 1; 24 : ulong msg_buf_used; /* including header */ 25 : ulong msg_sz; /* size of next message */ 26 : 27 : long header_deadline_nanos; /* deadline to first resp header bit */ 28 : long rx_end_deadline_nanos; /* deadline to end of stream signal */ 29 : long tx_wnd_debt; /* send-window deficit from an initial-window shrink below consumed credit; repaid from WINDOW_UPDATEs before new credit counts */ 30 : uint has_header_deadline : 1; 31 : uint has_rx_end_deadline : 1; 32 : uint rst_pending : 1; /* timed out, RST_STREAM waits for frame_tx space */ 33 : }; 34 : 35 : /* Declare a pool of stream objects. 36 : 37 : While only one stream is used to write requests out to the wire at a 38 : time, a gRPC client might be waiting for multiple responses. */ 39 : 40 : #define POOL_NAME fd_grpc_h2_stream_pool 41 0 : #define POOL_T fd_grpc_h2_stream_t 42 : #define POOL_IDX_T uint 43 : #include "../../util/tmpl/fd_pool.c" 44 : 45 : static inline fd_grpc_h2_stream_t * 46 0 : fd_grpc_h2_stream_upcast( fd_h2_stream_t * stream ) { 47 0 : return (fd_grpc_h2_stream_t *)( (ulong)stream - offsetof(fd_grpc_h2_stream_t, s) ); 48 0 : } 49 : 50 : /* I/O paths 51 : 52 : RX path (TLS) 53 : - fd_grpc_client_rxtx_tls 54 : - calls fd_tlsrec_sock_rx to read and decrypt TCP ciphertext 55 : - pushes plaintext into fd_h2_rbuf 56 : 57 : TX path (TLS) 58 : - fd_grpc_client_rxtx_tls 59 : - pops plaintext from fd_h2_rbuf 60 : - calls fd_tlsrec_sock_tx to encrypt and write TCP ciphertext 61 : 62 : RX/TX path (plaintext sockets) 63 : - fd_grpc_client_rxtx_socket 64 : - calls fd_h2_rbuf_recvmsg / fd_h2_rbuf_sendmsg */ 65 : 66 : /* gRPC client internal state. Quick overview: 67 : 68 : - The client maintains exactly one gRPC connection. 69 : - This conn includes a TCP socket, fd_tlsrec handle, and a fd_h2 70 : conn (and accompanying buffers). 71 : - The client object dies when the connection dies. 72 : 73 : - The client manages a small pool of stream objects. 74 : - Each stream has one of 3 states: 75 : - IDLE: marked free in stream_pool 76 : - OPEN: sending request data. marked used in stream_pool, present 77 : in stream_ids/streams, referred to by request_stream, has 78 : associated tx_op object. 79 : - CLOSE_TX: request sent, waiting for response. marked used in 80 : stream_pool, present in stream_ids/streams. 81 : - Only 1 stream can be in OPEN state. 82 : 83 : Regular state transitions: 84 : 85 : - IDLE->OPEN: Client acquires a stream object and starts a tx_op 86 : See fd_grpc_client_request_start 87 : - OPEN->CLOSE_TX: tx_op finished writing request data and is now 88 : waiting for the response. tx_op object finalized. 89 : See fd_grpc_client_request_continue1 90 : - CLOSE_TX->IDLE: All response data arrived. Stream object 91 : deallocated. 92 : 93 : Irregular state transitions: 94 : 95 : - CLOSE_TX->IDLE: Server aborts stream before request is fully sent. 96 : - OPEN->IDLE: Server aborts stream before response is received. */ 97 : 98 : struct fd_grpc_client_private { 99 : fd_grpc_client_callbacks_t const * callbacks; 100 : void * ctx; 101 : 102 : fd_h2_hdr_matcher_t matcher[1]; 103 : 104 : /* HTTP/2 connection */ 105 : fd_h2_conn_t conn[1]; 106 : fd_h2_rbuf_t frame_rx[1]; /* unencrypted HTTP/2 RX frame buffer */ 107 : fd_h2_rbuf_t frame_tx[1]; /* unencrypted HTTP/2 TX frame buffer */ 108 : 109 : /* HTTP/2 authority */ 110 : char host[ FD_FQDN_BUF_MAX ]; 111 : ushort port; /* <=65535 */ 112 : uchar host_len; /* <FD_FQDN_BUF_MAX */ 113 : 114 : uint https : 1; 115 : uint h2_hs_done : 1; 116 : uint window_update_pending : 1; /* SETTINGS window delta arrived mid-rx; continue tx after fd_h2_rx returns */ 117 : 118 : /* Inflight request 119 : Non-NULL until a gRPC request is fully written out. */ 120 : fd_grpc_h2_stream_t * request_stream; 121 : fd_h2_tx_op_t request_tx_op[1]; 122 : 123 : /* Stream pool */ 124 : fd_grpc_h2_stream_t * stream_pool; 125 : uchar * stream_bufs; 126 : 127 : /* Stream map */ 128 : /* FIXME pull this into a fd_map_tiny.c? */ 129 : uint stream_ids[ FD_GRPC_CLIENT_MAX_STREAMS ]; 130 : fd_grpc_h2_stream_t * streams [ FD_GRPC_CLIENT_MAX_STREAMS ]; 131 : ulong stream_cnt; 132 : 133 : /* Buffers */ 134 : uchar * pb_tx; 135 : ulong pb_tx_max; 136 : uchar * frame_scratch; 137 : ulong frame_scratch_max; 138 : 139 : /* Frame buffers */ 140 : uchar * frame_rx_buf; 141 : ulong frame_rx_buf_max; 142 : uchar * frame_tx_buf; 143 : ulong frame_tx_buf_max; 144 : 145 : fd_tlsrec_sock_t tls_sock[1]; 146 : 147 : /* Version string */ 148 : uchar version_len; 149 : char version[ FD_GRPC_CLIENT_VERSION_LEN_MAX ]; 150 : 151 : fd_grpc_client_metrics_t * metrics; 152 : }; 153 : 154 : FD_PROTOTYPES_BEGIN 155 : 156 : /* fd_grpc_client_stream_acquire grabs a new stream ID and a stream 157 : object. */ 158 : 159 : int 160 : fd_grpc_client_stream_acquire_is_safe( fd_grpc_client_t * client ); 161 : 162 : 163 : fd_grpc_h2_stream_t * 164 : fd_grpc_client_stream_acquire( fd_grpc_client_t * client, 165 : ulong request_ctx ); 166 : 167 : void 168 : fd_grpc_client_stream_release( fd_grpc_client_t * client, 169 : fd_grpc_h2_stream_t * stream ); 170 : 171 : /* fd_grpc_client_service_streams checks all streams for timeouts and 172 : optionally generates receive window updates. 173 : FIXME poor algorithmic inefficiency (O(n)). Consider using a service 174 : queue/heap */ 175 : 176 : void 177 : fd_grpc_client_service_streams( fd_grpc_client_t * client, 178 : long ts_nanos ); 179 : 180 : void 181 : fd_grpc_h2_cb_headers( 182 : fd_h2_conn_t * conn, 183 : fd_h2_stream_t * h2_stream, 184 : void const * data, 185 : ulong data_sz, 186 : ulong flags 187 : ); 188 : 189 : void 190 : fd_grpc_h2_cb_data( 191 : fd_h2_conn_t * conn, 192 : fd_h2_stream_t * h2_stream, 193 : void const * data, 194 : ulong data_sz, 195 : ulong flags 196 : ); 197 : 198 : void 199 : fd_grpc_h2_stream_window_update( fd_h2_conn_t * conn, 200 : fd_h2_stream_t * stream, 201 : uint increment ); 202 : 203 : void 204 : fd_grpc_h2_initial_window_update( fd_h2_conn_t * conn, 205 : long delta ); 206 : 207 : FD_PROTOTYPES_END 208 : 209 : #endif /* HEADER_fd_src_waltz_grpc_fd_grpc_client_private_h */