Line data Source code
1 : #include "fd_ipecho_client.h"
2 : #include "fd_ipecho_server.h"
3 : #include "../../disco/topo/fd_topo.h"
4 : #include "../../disco/metrics/fd_metrics.h"
5 : #include "generated/fd_ipecho_tile_seccomp.h"
6 :
7 : struct fd_ipecho_tile_ctx {
8 : int retrieving;
9 :
10 : fd_ipecho_server_t * server;
11 : fd_ipecho_client_t * client;
12 :
13 : uint bind_address;
14 : ushort bind_port;
15 :
16 : ushort bootstrap_shred_version;
17 : ushort expected_shred_version;
18 : ushort shred_version;
19 : };
20 :
21 : typedef struct fd_ipecho_tile_ctx fd_ipecho_tile_ctx_t;
22 :
23 : FD_FN_CONST static inline ulong
24 0 : scratch_align( void ) {
25 0 : return alignof( fd_ipecho_tile_ctx_t );
26 0 : }
27 :
28 : FD_FN_PURE static inline ulong
29 0 : scratch_footprint( fd_topo_tile_t const * tile ) {
30 0 : (void)tile;
31 :
32 0 : ulong l = FD_LAYOUT_INIT;
33 0 : l = FD_LAYOUT_APPEND( l, alignof( fd_ipecho_tile_ctx_t ), sizeof( fd_ipecho_tile_ctx_t ) );
34 0 : l = FD_LAYOUT_APPEND( l, fd_ipecho_client_align(), fd_ipecho_client_footprint() );
35 0 : l = FD_LAYOUT_APPEND( l, fd_ipecho_server_align(), fd_ipecho_server_footprint( 1024UL ) );
36 0 : return FD_LAYOUT_FINI( l, scratch_align() );
37 0 : }
38 :
39 : static inline void
40 0 : metrics_write( fd_ipecho_tile_ctx_t * ctx ) {
41 0 : fd_ipecho_server_metrics_t * metrics = fd_ipecho_server_metrics( ctx->server );
42 :
43 0 : FD_MGAUGE_SET( IPECHO, CONNECTION_COUNT, metrics->connection_cnt );
44 0 : FD_MCNT_SET( IPECHO, BYTES_READ, metrics->bytes_read );
45 0 : FD_MCNT_SET( IPECHO, BYTES_WRITTEN, metrics->bytes_written );
46 0 : FD_MCNT_SET( IPECHO, CONNECTIONS_CLOSED_OK, metrics->connections_closed_ok );
47 0 : FD_MCNT_SET( IPECHO, CONNECTIONS_CLOSED_ERROR, metrics->connections_closed_error );
48 0 : }
49 :
50 : static inline void
51 : poll_client( fd_ipecho_tile_ctx_t * ctx,
52 : fd_stem_context_t * stem,
53 0 : int * charge_busy ) {
54 0 : if( FD_UNLIKELY( !ctx->client ) ) return;
55 :
56 0 : int result = fd_ipecho_client_poll( ctx->client, &ctx->shred_version, charge_busy );
57 0 : if( FD_UNLIKELY( !result ) ) {
58 0 : if( FD_UNLIKELY( ctx->expected_shred_version && ctx->expected_shred_version!=ctx->shred_version ) ) {
59 0 : FD_LOG_ERR(( "Expected shred version %hu but entrypoint returned %hu",
60 0 : ctx->expected_shred_version, ctx->shred_version ));
61 0 : }
62 :
63 0 : FD_LOG_INFO(( "retrieved shred version %hu from entrypoint", ctx->shred_version ));
64 0 : FD_MGAUGE_SET( IPECHO, SHRED_VERSION, ctx->shred_version );
65 0 : fd_stem_publish( stem, 0UL, ctx->shred_version, 0UL, 0UL, 0UL, 0UL, 0UL );
66 0 : fd_ipecho_server_init( ctx->server, ctx->bind_address, ctx->bind_port, ctx->shred_version );
67 0 : ctx->retrieving = 0;
68 0 : return;
69 0 : } else if( FD_UNLIKELY( -1==result ) ) {
70 0 : FD_LOG_ERR(( "Could not determine shred version from entrypoints. Please "
71 0 : "check you can connect to the entrypoints provided." ));
72 0 : }
73 0 : }
74 :
75 : static inline void
76 : after_credit( fd_ipecho_tile_ctx_t * ctx,
77 : fd_stem_context_t * stem,
78 : int * opt_poll_in,
79 0 : int * charge_busy ) {
80 0 : (void)opt_poll_in;
81 :
82 0 : int timeout = ctx->retrieving ? 0 : 10;
83 :
84 0 : if( FD_UNLIKELY( ctx->retrieving ) ) poll_client( ctx, stem, charge_busy );
85 0 : else fd_ipecho_server_poll( ctx->server, charge_busy, timeout );
86 0 : }
87 :
88 : static inline int
89 : returnable_frag( fd_ipecho_tile_ctx_t * ctx,
90 : ulong in_idx,
91 : ulong seq,
92 : ulong sig,
93 : ulong chunk,
94 : ulong sz,
95 : ulong ctl,
96 : ulong tsorig,
97 : ulong tspub,
98 0 : fd_stem_context_t * stem ) {
99 0 : (void)in_idx;
100 0 : (void)seq;
101 0 : (void)chunk;
102 0 : (void)sz;
103 0 : (void)ctl;
104 0 : (void)tsorig;
105 0 : (void)tspub;
106 :
107 0 : FD_TEST( sig && sig<=USHORT_MAX );
108 0 : ctx->shred_version = (ushort)sig;
109 0 : FD_TEST( !ctx->expected_shred_version || ctx->shred_version==ctx->expected_shred_version );
110 0 : FD_MGAUGE_SET( IPECHO, SHRED_VERSION, ctx->shred_version );
111 0 : fd_stem_publish( stem, 0UL, ctx->shred_version, 0UL, 0UL, 0UL, tsorig, fd_frag_meta_ts_comp( fd_tickcount() ) );
112 0 : ctx->retrieving = 0;
113 0 : fd_ipecho_server_init( ctx->server, ctx->bind_address, ctx->bind_port, ctx->shred_version );
114 :
115 0 : return 0;
116 0 : }
117 :
118 : static void
119 : unprivileged_init( fd_topo_t * topo,
120 0 : fd_topo_tile_t * tile ) {
121 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
122 :
123 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
124 0 : fd_ipecho_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_ipecho_tile_ctx_t ), sizeof( fd_ipecho_tile_ctx_t ) );
125 0 : void * _client = FD_SCRATCH_ALLOC_APPEND( l, fd_ipecho_client_align(), fd_ipecho_client_footprint() );
126 0 : void * _server = FD_SCRATCH_ALLOC_APPEND( l, fd_ipecho_server_align(), fd_ipecho_server_footprint( 1024UL ) );
127 :
128 0 : ctx->bind_address = tile->ipecho.bind_address;
129 0 : ctx->bind_port = tile->ipecho.bind_port;
130 :
131 0 : ctx->expected_shred_version = tile->ipecho.expected_shred_version;
132 0 : ctx->shred_version = 0U;
133 :
134 0 : ctx->retrieving = 1;
135 0 : if( FD_LIKELY( tile->ipecho.entrypoints_cnt ) ) {
136 0 : ctx->client = fd_ipecho_client_join( fd_ipecho_client_new( _client ) );
137 0 : FD_TEST( ctx->client );
138 0 : fd_ipecho_client_init( ctx->client, tile->ipecho.entrypoints, tile->ipecho.entrypoints_cnt );
139 0 : } else {
140 0 : ctx->client = NULL;
141 0 : }
142 :
143 0 : ctx->server = fd_ipecho_server_join( fd_ipecho_server_new( _server, 1024UL ) );
144 0 : FD_TEST( ctx->server );
145 :
146 0 : ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, 1UL );
147 0 : if( FD_UNLIKELY( scratch_top > (ulong)scratch + scratch_footprint( tile ) ) )
148 0 : FD_LOG_ERR(( "scratch overflow %lu %lu %lu", scratch_top - (ulong)scratch - scratch_footprint( tile ), scratch_top, (ulong)scratch + scratch_footprint( tile ) ));
149 0 : }
150 :
151 : static ulong
152 : populate_allowed_seccomp( fd_topo_t const * topo,
153 : fd_topo_tile_t const * tile,
154 : ulong out_cnt,
155 0 : struct sock_filter * out ) {
156 0 : (void)topo;
157 0 : (void)tile;
158 :
159 0 : populate_sock_filter_policy_fd_ipecho_tile( out_cnt, out, (uint)fd_log_private_logfile_fd() );
160 0 : return sock_filter_policy_fd_ipecho_tile_instr_cnt;
161 0 : }
162 :
163 : static ulong
164 : populate_allowed_fds( fd_topo_t const * topo,
165 : fd_topo_tile_t const * tile,
166 : ulong out_fds_cnt,
167 0 : int * out_fds ) {
168 0 : (void)topo;
169 0 : (void)tile;
170 :
171 0 : if( FD_UNLIKELY( out_fds_cnt<2UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
172 :
173 0 : ulong out_cnt = 0UL;
174 0 : out_fds[ out_cnt++ ] = 2; /* stderr */
175 0 : if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
176 0 : out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
177 0 : return out_cnt;
178 0 : }
179 :
180 0 : #define STEM_BURST (1UL)
181 0 : #define STEM_LAZY (50UL)
182 :
183 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_ipecho_tile_ctx_t
184 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_ipecho_tile_ctx_t)
185 :
186 0 : #define STEM_CALLBACK_METRICS_WRITE metrics_write
187 0 : #define STEM_CALLBACK_AFTER_CREDIT after_credit
188 0 : #define STEM_CALLBACK_RETURNABLE_FRAG returnable_frag
189 :
190 : #include "../../disco/stem/fd_stem.c"
191 :
192 : fd_topo_run_tile_t fd_tile_ipecho = {
193 : .name = "ipecho",
194 : .populate_allowed_seccomp = populate_allowed_seccomp,
195 : .populate_allowed_fds = populate_allowed_fds,
196 : .scratch_align = scratch_align,
197 : .scratch_footprint = scratch_footprint,
198 : .unprivileged_init = unprivileged_init,
199 : .run = stem_run,
200 : };
|