Line data Source code
1 : #include "../../disco/topo/fd_topo.h"
2 : #include <sys/socket.h>
3 : #include "generated/fd_rpcserv_tile_seccomp.h"
4 : #include "../rpcserver/fd_rpc_service.h"
5 : #include "../../disco/keyguard/fd_keyload.h"
6 : #include "../../disco/keyguard/fd_keyswitch.h"
7 :
8 : #include <fcntl.h>
9 : #include <unistd.h>
10 :
11 0 : #define IN_KIND_REPLAY_OUT (0)
12 0 : #define IN_KIND_STAKE_OUT (1)
13 0 : #define IN_KIND_SHRED_OUT (2)
14 :
15 : struct fd_rpcserv_in {
16 : fd_wksp_t * mem;
17 : ulong chunk0;
18 : ulong wmark;
19 : ulong mtu;
20 : };
21 :
22 : typedef struct fd_rpcserv_in fd_rpcserv_in_t;
23 :
24 : struct fd_rpcserv_tile {
25 : fd_rpcserver_args_t args;
26 :
27 : fd_rpc_ctx_t * ctx;
28 :
29 : fd_pubkey_t identity_key;
30 : fd_keyswitch_t * keyswitch;
31 :
32 : int in_kind[ 16UL ];
33 : fd_rpcserv_in_t in[ 16UL ];
34 : };
35 :
36 : typedef struct fd_rpcserv_tile fd_rpcserv_tile_t;
37 :
38 0 : #define FD_RPC_SCRATCH_MAX (1LU<<30)
39 :
40 : const fd_http_server_params_t RPCSERV_HTTP_PARAMS = {
41 : .max_connection_cnt = 10,
42 : .max_ws_connection_cnt = 10,
43 : .max_request_len = 1<<16,
44 : .max_ws_recv_frame_len = 1<<16,
45 : .max_ws_send_frame_cnt = 10,
46 : .outgoing_buffer_sz = 100<<20,
47 : };
48 :
49 : FD_FN_CONST static inline ulong
50 0 : scratch_align( void ) {
51 0 : return 128UL;
52 0 : }
53 :
54 : FD_FN_PURE static inline ulong
55 0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED) {
56 0 : ulong l = FD_LAYOUT_INIT;
57 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_rpcserv_tile_t), sizeof(fd_rpcserv_tile_t) );
58 0 : l = FD_LAYOUT_APPEND( l, fd_spad_align(), fd_spad_footprint( FD_RPC_SCRATCH_MAX ) );
59 0 : return FD_LAYOUT_FINI( l, scratch_align() );
60 0 : }
61 :
62 : FD_FN_PURE static inline ulong
63 0 : loose_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
64 0 : return 1UL * FD_SHMEM_GIGANTIC_PAGE_SZ;
65 0 : }
66 :
67 : static inline void
68 0 : during_housekeeping( fd_rpcserv_tile_t * ctx ) {
69 0 : if( FD_UNLIKELY( fd_keyswitch_state_query( ctx->keyswitch )==FD_KEYSWITCH_STATE_SWITCH_PENDING ) ) {
70 0 : memcpy( &ctx->identity_key, ctx->keyswitch->bytes, sizeof(fd_pubkey_t) );
71 0 : fd_keyswitch_state( ctx->keyswitch, FD_KEYSWITCH_STATE_COMPLETED );
72 0 : }
73 0 : }
74 :
75 : static inline void
76 : before_credit( fd_rpcserv_tile_t * ctx,
77 : fd_stem_context_t * stem,
78 0 : int * charge_busy ) {
79 0 : (void)stem;
80 0 : *charge_busy = fd_rpc_ws_poll( ctx->ctx );
81 0 : }
82 :
83 : static inline int
84 : returnable_frag( fd_rpcserv_tile_t * ctx,
85 : ulong in_idx,
86 : ulong seq,
87 : ulong sig,
88 : ulong chunk,
89 : ulong sz,
90 : ulong ctl,
91 : ulong tsorig,
92 : ulong tspub,
93 0 : fd_stem_context_t * stem ) {
94 0 : (void)seq;
95 0 : (void)tsorig;
96 0 : (void)tspub;
97 0 : (void)stem;
98 :
99 0 : if( FD_UNLIKELY( chunk<ctx->in[ in_idx ].chunk0 || chunk>ctx->in[ in_idx ].wmark || sz>ctx->in[ in_idx ].mtu ) ) {
100 0 : FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz, ctx->in[ in_idx ].chunk0, ctx->in[ in_idx ].wmark ));
101 0 : }
102 :
103 0 : switch( ctx->in_kind[ in_idx ] ) {
104 0 : case IN_KIND_REPLAY_OUT: {
105 0 : fd_rpc_replay_during_frag( ctx->ctx, fd_chunk_to_laddr_const( ctx->in[ in_idx ].mem, chunk ), sig, sz, ctl );
106 0 : fd_rpc_replay_after_frag( ctx->ctx, sig );
107 0 : break;
108 0 : }
109 0 : case IN_KIND_STAKE_OUT: {
110 0 : fd_rpc_stake_during_frag( ctx->ctx, fd_chunk_to_laddr_const( ctx->in[ in_idx ].mem, chunk ), sz );
111 0 : fd_rpc_stake_after_frag( ctx->ctx );
112 0 : break;
113 0 : }
114 0 : case IN_KIND_SHRED_OUT: {
115 0 : fd_rpc_repair_during_frag( ctx->ctx, fd_chunk_to_laddr_const( ctx->in[ in_idx ].mem, chunk ), sz );
116 0 : fd_rpc_repair_after_frag( ctx->ctx );
117 0 : break;
118 0 : }
119 0 : default: FD_LOG_ERR(( "unhandled kind %d", ctx->in_kind[ in_idx ] ));
120 0 : }
121 :
122 0 : return 0;
123 0 : }
124 :
125 : static void
126 : privileged_init( fd_topo_t * topo,
127 0 : fd_topo_tile_t * tile ) {
128 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
129 :
130 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
131 0 : fd_rpcserv_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_t), sizeof(fd_rpcserv_tile_t) );
132 0 : void * spad_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), fd_spad_footprint( FD_RPC_SCRATCH_MAX ) );
133 0 : FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
134 :
135 0 : if( FD_UNLIKELY( !strcmp( tile->rpcserv.identity_key_path, "" ) ) ) FD_LOG_ERR( ( "identity_key_path not set" ) );
136 0 : memcpy( &ctx->identity_key, fd_keyload_load( tile->rpcserv.identity_key_path, /* pubkey only: */ 1 ), sizeof(fd_pubkey_t) );
137 :
138 0 : fd_rpcserver_args_t * args = &ctx->args;
139 0 : fd_memset( args, 0, sizeof(fd_rpcserver_args_t) );
140 :
141 0 : args->offline = 0;
142 0 : args->params = RPCSERV_HTTP_PARAMS;
143 :
144 0 : args->port = tile->rpcserv.rpc_port;
145 :
146 0 : args->tpu_addr.sin_family = AF_INET;
147 0 : args->tpu_addr.sin_addr.s_addr = tile->rpcserv.tpu_ip_addr;
148 0 : args->tpu_addr.sin_port = htons( (ushort)tile->rpcserv.tpu_port );
149 :
150 0 : uchar * spad_mem_cur = spad_mem;
151 0 : args->spad = fd_spad_join( fd_spad_new( spad_mem_cur, FD_RPC_SCRATCH_MAX ) );
152 :
153 0 : args->block_index_max = tile->rpcserv.block_index_max;
154 0 : args->txn_index_max = tile->rpcserv.txn_index_max;
155 0 : args->acct_index_max = tile->rpcserv.acct_index_max;
156 0 : strncpy( args->history_file, tile->rpcserv.history_file, sizeof(args->history_file) );
157 0 : args->identity_key = ctx->identity_key;
158 :
159 0 : fd_spad_push( args->spad ); /* We close this out when we stop the server */
160 0 : fd_rpc_create_ctx( args, &ctx->ctx );
161 :
162 : /* Wait until after replay tile boots before starting service */
163 0 : }
164 :
165 : static void
166 : unprivileged_init( fd_topo_t * topo,
167 0 : fd_topo_tile_t * tile ) {
168 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
169 :
170 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
171 0 : fd_rpcserv_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_t), sizeof(fd_rpcserv_tile_t) );
172 0 : FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), fd_ulong_align_up( FD_RPC_SCRATCH_MAX, fd_spad_align() ) );
173 :
174 0 : ctx->keyswitch = fd_keyswitch_join( fd_topo_obj_laddr( topo, tile->keyswitch_obj_id ) );
175 0 : FD_TEST( ctx->keyswitch );
176 :
177 0 : fd_rpcserver_args_t * args = &ctx->args;
178 0 : FD_TEST( fd_funk_join( args->funk, fd_topo_obj_laddr( topo, tile->rpcserv.funk_obj_id ) ) );
179 :
180 0 : args->store = fd_store_join( fd_topo_obj_laddr( topo, tile->rpcserv.store_obj_id ) );
181 0 : FD_TEST( args->store );
182 :
183 0 : fd_rpc_start_service( args, ctx->ctx );
184 :
185 0 : for( uint in_idx=0U; in_idx<(tile->in_cnt); in_idx++ ) {
186 0 : fd_topo_link_t * link = &topo->links[ tile->in_link_id[ in_idx ] ];
187 :
188 0 : if( FD_LIKELY( !strcmp( link->name, "replay_out" ) ) ) ctx->in_kind[ in_idx ] = IN_KIND_REPLAY_OUT;
189 0 : else if( FD_LIKELY( !strcmp( link->name, "replay_stake" ) ) ) ctx->in_kind[ in_idx ] = IN_KIND_STAKE_OUT;
190 0 : else if( FD_LIKELY( !strcmp( link->name, "shred_out" ) ) ) ctx->in_kind[ in_idx ] = IN_KIND_SHRED_OUT;
191 0 : else FD_LOG_ERR(( "rpcserv tile has unexpected input link %s", link->name ));
192 :
193 0 : ctx->in[ in_idx ].mem = topo->workspaces[ topo->objs[ link->dcache_obj_id ].wksp_id ].wksp;
194 0 : ctx->in[ in_idx ].chunk0 = fd_dcache_compact_chunk0( ctx->in[ in_idx ].mem, link->dcache );
195 0 : ctx->in[ in_idx ].wmark = fd_dcache_compact_wmark ( ctx->in[ in_idx ].mem, link->dcache, link->mtu );
196 0 : ctx->in[ in_idx ].mtu = link->mtu;
197 0 : }
198 :
199 0 : ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
200 0 : if( FD_UNLIKELY( scratch_top > (ulong)scratch + scratch_footprint( tile ) ) )
201 0 : FD_LOG_ERR(( "scratch overflow %lu %lu %lu", scratch_top - (ulong)scratch - scratch_footprint( tile ), scratch_top, (ulong)scratch + scratch_footprint( tile ) ));
202 0 : }
203 :
204 : static ulong
205 : populate_allowed_seccomp( fd_topo_t const * topo,
206 : fd_topo_tile_t const * tile,
207 : ulong out_cnt,
208 0 : struct sock_filter * out ) {
209 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
210 :
211 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
212 0 : fd_rpcserv_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_t), sizeof(fd_rpcserv_tile_t) );
213 :
214 0 : populate_sock_filter_policy_fd_rpcserv_tile( out_cnt, out, (uint)fd_log_private_logfile_fd(), (uint)fd_rpc_ws_fd( ctx->ctx ) );
215 0 : return sock_filter_policy_fd_rpcserv_tile_instr_cnt;
216 0 : }
217 :
218 : static ulong
219 : populate_allowed_fds( fd_topo_t const * topo,
220 : fd_topo_tile_t const * tile,
221 : ulong out_fds_cnt,
222 0 : int * out_fds ) {
223 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
224 :
225 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
226 0 : fd_rpcserv_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rpcserv_tile_t), sizeof(fd_rpcserv_tile_t) );
227 :
228 0 : if( FD_UNLIKELY( out_fds_cnt<3UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
229 :
230 0 : ulong out_cnt = 0;
231 0 : out_fds[ out_cnt++ ] = 2; /* stderr */
232 0 : if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
233 0 : out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
234 0 : out_fds[ out_cnt++ ] = fd_rpc_ws_fd( ctx->ctx ); /* listen socket */
235 0 : return out_cnt;
236 0 : }
237 :
238 0 : #define STEM_BURST (1UL)
239 :
240 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_rpcserv_tile_t
241 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_rpcserv_tile_t)
242 :
243 0 : #define STEM_CALLBACK_BEFORE_CREDIT before_credit
244 0 : #define STEM_CALLBACK_DURING_HOUSEKEEPING during_housekeeping
245 0 : #define STEM_CALLBACK_RETURNABLE_FRAG returnable_frag
246 :
247 : #include "../../disco/stem/fd_stem.c"
248 :
249 : fd_topo_run_tile_t fd_tile_rpcserv = {
250 : .name = "rpcsrv",
251 : .loose_footprint = loose_footprint,
252 : .populate_allowed_seccomp = populate_allowed_seccomp,
253 : .populate_allowed_fds = populate_allowed_fds,
254 : .scratch_align = scratch_align,
255 : .scratch_footprint = scratch_footprint,
256 : .unprivileged_init = unprivileged_init,
257 : .privileged_init = privileged_init,
258 : .run = stem_run,
259 : };
|