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 h2_hs_done : 1; 115 : uint window_update_pending : 1; /* SETTINGS window delta arrived mid-rx; continue tx after fd_h2_rx returns */ 116 : 117 : /* Inflight request 118 : Non-NULL until a gRPC request is fully written out. */ 119 : fd_grpc_h2_stream_t * request_stream; 120 : fd_h2_tx_op_t request_tx_op[1]; 121 : 122 : /* Stream pool */ 123 : fd_grpc_h2_stream_t * stream_pool; 124 : uchar * stream_bufs; 125 : 126 : /* Stream map */ 127 : /* FIXME pull this into a fd_map_tiny.c? */ 128 : uint stream_ids[ FD_GRPC_CLIENT_MAX_STREAMS ]; 129 : fd_grpc_h2_stream_t * streams [ FD_GRPC_CLIENT_MAX_STREAMS ]; 130 : ulong stream_cnt; 131 : 132 : /* Buffers */ 133 : uchar * nanopb_tx; 134 : ulong nanopb_tx_max; 135 : uchar * frame_scratch; 136 : ulong frame_scratch_max; 137 : 138 : /* Frame buffers */ 139 : uchar * frame_rx_buf; 140 : ulong frame_rx_buf_max; 141 : uchar * frame_tx_buf; 142 : ulong frame_tx_buf_max; 143 : 144 : fd_tlsrec_sock_t tls_sock[1]; 145 : 146 : /* Version string */ 147 : uchar version_len; 148 : char version[ FD_GRPC_CLIENT_VERSION_LEN_MAX ]; 149 : 150 : fd_grpc_client_metrics_t * metrics; 151 : }; 152 : 153 : FD_PROTOTYPES_BEGIN 154 : 155 : /* fd_grpc_client_stream_acquire grabs a new stream ID and a stream 156 : object. */ 157 : 158 : int 159 : fd_grpc_client_stream_acquire_is_safe( fd_grpc_client_t * client ); 160 : 161 : 162 : fd_grpc_h2_stream_t * 163 : fd_grpc_client_stream_acquire( fd_grpc_client_t * client, 164 : ulong request_ctx ); 165 : 166 : void 167 : fd_grpc_client_stream_release( fd_grpc_client_t * client, 168 : fd_grpc_h2_stream_t * stream ); 169 : 170 : /* fd_grpc_client_service_streams checks all streams for timeouts and 171 : optionally generates receive window updates. 172 : FIXME poor algorithmic inefficiency (O(n)). Consider using a service 173 : queue/heap */ 174 : 175 : void 176 : fd_grpc_client_service_streams( fd_grpc_client_t * client, 177 : long ts_nanos ); 178 : 179 : void 180 : fd_grpc_h2_cb_headers( 181 : fd_h2_conn_t * conn, 182 : fd_h2_stream_t * h2_stream, 183 : void const * data, 184 : ulong data_sz, 185 : ulong flags 186 : ); 187 : 188 : void 189 : fd_grpc_h2_cb_data( 190 : fd_h2_conn_t * conn, 191 : fd_h2_stream_t * h2_stream, 192 : void const * data, 193 : ulong data_sz, 194 : ulong flags 195 : ); 196 : 197 : void 198 : fd_grpc_h2_stream_window_update( fd_h2_conn_t * conn, 199 : fd_h2_stream_t * stream, 200 : uint increment ); 201 : 202 : void 203 : fd_grpc_h2_initial_window_update( fd_h2_conn_t * conn, 204 : long delta ); 205 : 206 : FD_PROTOTYPES_END 207 : 208 : #endif /* HEADER_fd_src_waltz_grpc_fd_grpc_client_private_h */