Line data Source code
1 : #include "fd_http_resolver.h"
2 : #include "fd_ssresolve.h"
3 :
4 : #include "../../../util/log/fd_log.h"
5 : #include "../../../util/fd_util.h"
6 :
7 : #include <poll.h>
8 : #include <errno.h>
9 : #include <unistd.h>
10 : #include <sys/socket.h>
11 : #include <netinet/in.h>
12 : #include <netinet/tcp.h>
13 :
14 : #if FD_HAS_OPENSSL
15 : #include <openssl/ssl.h>
16 : #include "../../../waltz/openssl/fd_openssl_tile.h"
17 : #endif
18 :
19 0 : #define PEER_STATE_UNRESOLVED (0)
20 0 : #define PEER_STATE_REFRESHING (1)
21 0 : #define PEER_STATE_VALID (2)
22 0 : #define PEER_STATE_INVALID (3)
23 :
24 0 : #define PEER_DEADLINE_NANOS_VALID (5L*1000L*1000L*1000L) /* 5 seconds */
25 0 : #define PEER_DEADLINE_NANOS_RESOLVE (2L*1000L*1000L*1000L) /* 2 seconds */
26 0 : #define PEER_DEADLINE_NANOS_INVALID (5L*1000L*1000L*1000L) /* 5 seconds */
27 :
28 : /* FIXME: The fds/fds_len/idx logic is fragile, replace with something
29 : that duplicates less state / etc. */
30 :
31 : struct fd_ssresolve_peer {
32 : fd_ip4_port_t addr;
33 : char const * hostname;
34 : int is_https;
35 : fd_ssinfo_t ssinfo;
36 :
37 : fd_ssresolve_t * full_ssresolve;
38 : fd_ssresolve_t * inc_ssresolve;
39 :
40 : struct {
41 : ulong next;
42 : } pool;
43 :
44 : struct {
45 : ulong next;
46 : ulong prev;
47 : } deadline;
48 :
49 : struct {
50 : ulong idx;
51 : } fd;
52 :
53 : int state;
54 : long deadline_nanos;
55 : };
56 : typedef struct fd_ssresolve_peer fd_ssresolve_peer_t;
57 :
58 : #define POOL_NAME peer_pool
59 0 : #define POOL_T fd_ssresolve_peer_t
60 : #define POOL_IDX_T ulong
61 0 : #define POOL_NEXT pool.next
62 : #include "../../../util/tmpl/fd_pool.c"
63 :
64 : #define DLIST_NAME deadline_list
65 : #define DLIST_ELE_T fd_ssresolve_peer_t
66 0 : #define DLIST_PREV deadline.prev
67 0 : #define DLIST_NEXT deadline.next
68 : #include "../../../util/tmpl/fd_dlist.c"
69 :
70 : struct fd_http_resolver_private {
71 : fd_ssresolve_peer_t * pool;
72 : deadline_list_t * unresolved;
73 : deadline_list_t * resolving;
74 : deadline_list_t * valid;
75 : deadline_list_t * invalid;
76 :
77 : ulong fds_len;
78 : struct pollfd * fds;
79 : ulong * fds_idx;
80 :
81 : int incremental_snapshot_fetch;
82 :
83 : void * cb_arg;
84 : fd_http_resolver_on_resolve_fn_t on_resolve_cb;
85 :
86 : #if FD_HAS_OPENSSL
87 : SSL_CTX * ssl_ctx;
88 : #endif
89 :
90 : ulong magic; /* ==FD_HTTP_RESOLVER_MAGIC */
91 : };
92 :
93 : FD_FN_CONST ulong
94 0 : fd_http_resolver_align( void ) {
95 0 : return fd_ulong_max( alignof(fd_http_resolver_t), fd_ulong_max( peer_pool_align(), fd_ulong_max( deadline_list_align(), fd_ulong_max( alignof(struct pollfd), alignof(ulong) ) ) ) );
96 0 : }
97 :
98 : FD_FN_CONST ulong
99 0 : fd_http_resolver_footprint( ulong peers_cnt ) {
100 0 : ulong l;
101 0 : l = FD_LAYOUT_INIT;
102 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_http_resolver_t), sizeof(fd_http_resolver_t) );
103 0 : l = FD_LAYOUT_APPEND( l, peer_pool_align(), peer_pool_footprint( peers_cnt ) );
104 0 : l = FD_LAYOUT_APPEND( l, deadline_list_align(), deadline_list_footprint() );
105 0 : l = FD_LAYOUT_APPEND( l, deadline_list_align(), deadline_list_footprint() );
106 0 : l = FD_LAYOUT_APPEND( l, deadline_list_align(), deadline_list_footprint() );
107 0 : l = FD_LAYOUT_APPEND( l, deadline_list_align(), deadline_list_footprint() );
108 0 : l = FD_LAYOUT_APPEND( l, alignof(struct pollfd), 2UL*peers_cnt*sizeof(struct pollfd) );
109 0 : l = FD_LAYOUT_APPEND( l, alignof(ulong), 2UL*peers_cnt*sizeof(ulong) );
110 :
111 0 : for( ulong i=0UL; i<peers_cnt*2UL; i++ ) {
112 0 : l = FD_LAYOUT_APPEND( l, fd_ssresolve_align(), fd_ssresolve_footprint() );
113 0 : }
114 0 : return FD_LAYOUT_FINI( l, fd_http_resolver_align() );
115 0 : }
116 :
117 : void *
118 : fd_http_resolver_new( void * shmem,
119 : ulong peers_cnt,
120 : int incremental_snapshot_fetch,
121 : fd_http_resolver_on_resolve_fn_t on_resolve_cb,
122 0 : void * cb_arg ) {
123 0 : if( FD_UNLIKELY( !shmem ) ) {
124 0 : FD_LOG_WARNING(( "NULL shmem" ));
125 0 : return NULL;
126 0 : }
127 :
128 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_http_resolver_align() ) ) ) {
129 0 : FD_LOG_WARNING(( "unaligned shmem" ));
130 0 : return NULL;
131 0 : }
132 :
133 0 : if( FD_UNLIKELY( peers_cnt<1UL ) ) {
134 0 : FD_LOG_WARNING(( "max_peers must be at least 1" ));
135 0 : return NULL;
136 0 : }
137 :
138 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
139 0 : fd_http_resolver_t * resolver = FD_SCRATCH_ALLOC_APPEND( l, fd_http_resolver_align(), sizeof(fd_http_resolver_t) );
140 0 : void * _pool = FD_SCRATCH_ALLOC_APPEND( l, peer_pool_align(), peer_pool_footprint( peers_cnt ) );
141 0 : void * _unresolved = FD_SCRATCH_ALLOC_APPEND( l, deadline_list_align(), deadline_list_footprint() );
142 0 : void * _resolving = FD_SCRATCH_ALLOC_APPEND( l, deadline_list_align(), deadline_list_footprint() );
143 0 : void * _invalid = FD_SCRATCH_ALLOC_APPEND( l, deadline_list_align(), deadline_list_footprint() );
144 0 : void * _valid = FD_SCRATCH_ALLOC_APPEND( l, deadline_list_align(), deadline_list_footprint() );
145 0 : struct pollfd * fds = FD_SCRATCH_ALLOC_APPEND( l, alignof(struct pollfd), 2UL*peers_cnt*sizeof(struct pollfd) );
146 0 : ulong * fds_idx = FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong), 2UL*peers_cnt*sizeof(ulong) );
147 :
148 0 : resolver->pool = peer_pool_join( peer_pool_new( _pool, peers_cnt ) );
149 0 : resolver->unresolved = deadline_list_join( deadline_list_new( _unresolved ) );
150 0 : resolver->resolving = deadline_list_join( deadline_list_new( _resolving ) );
151 0 : resolver->invalid = deadline_list_join( deadline_list_new( _invalid ) );
152 0 : resolver->valid = deadline_list_join( deadline_list_new( _valid ) );
153 :
154 0 : resolver->fds_len = 0UL;
155 0 : resolver->fds = fds;
156 0 : resolver->fds_idx = fds_idx;
157 :
158 0 : for( ulong i=0UL; i<peer_pool_max( resolver->pool ); i++ ) {
159 0 : void * _full_ssresolve = FD_SCRATCH_ALLOC_APPEND( l, fd_ssresolve_align(), fd_ssresolve_footprint() );
160 0 : void * _inc_ssresolve = FD_SCRATCH_ALLOC_APPEND( l, fd_ssresolve_align(), fd_ssresolve_footprint() );
161 0 : resolver->pool[ i ].full_ssresolve = fd_ssresolve_join( fd_ssresolve_new( _full_ssresolve ) );
162 0 : resolver->pool[ i ].inc_ssresolve = fd_ssresolve_join( fd_ssresolve_new( _inc_ssresolve ) );
163 0 : }
164 :
165 0 : resolver->incremental_snapshot_fetch = incremental_snapshot_fetch;
166 0 : resolver->cb_arg = cb_arg;
167 0 : resolver->on_resolve_cb = on_resolve_cb;
168 :
169 0 : #if FD_HAS_OPENSSL
170 0 : SSL_CTX * ssl_ctx = SSL_CTX_new( TLS_client_method() );
171 0 : if( FD_UNLIKELY( !ssl_ctx ) ) {
172 0 : FD_LOG_ERR(( "SSL_CTX_new failed" ));
173 0 : }
174 :
175 0 : if( FD_UNLIKELY( !SSL_CTX_set_min_proto_version( ssl_ctx, TLS1_3_VERSION ) ) ) {
176 0 : FD_LOG_ERR(( "SSL_CTX_set_min_proto_version(ssl_ctx,TLS1_3_VERSION) failed" ));
177 0 : }
178 :
179 : /* transfering ownership of ssl_ctx by assignment */
180 0 : resolver->ssl_ctx = ssl_ctx;
181 :
182 0 : fd_ossl_load_certs( resolver->ssl_ctx );
183 0 : #endif
184 :
185 0 : FD_COMPILER_MFENCE();
186 0 : FD_VOLATILE( resolver->magic ) = FD_HTTP_RESOLVER_MAGIC;
187 0 : FD_COMPILER_MFENCE();
188 :
189 0 : return (void *)resolver;
190 0 : }
191 :
192 : fd_http_resolver_t *
193 0 : fd_http_resolver_join( void * shresolver ) {
194 0 : if( FD_UNLIKELY( !shresolver ) ) {
195 0 : FD_LOG_WARNING(( "NULL shresolver" ));
196 0 : return NULL;
197 0 : }
198 :
199 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shresolver, fd_http_resolver_align() ) ) ) {
200 0 : FD_LOG_WARNING(( "misaligned shresolver" ));
201 0 : return NULL;
202 0 : }
203 :
204 0 : fd_http_resolver_t * resolver = (fd_http_resolver_t *)shresolver;
205 :
206 0 : if( FD_UNLIKELY( resolver->magic!=FD_HTTP_RESOLVER_MAGIC ) ) {
207 0 : FD_LOG_WARNING(( "bad magic" ));
208 0 : return NULL;
209 0 : }
210 :
211 0 : return resolver;
212 0 : }
213 :
214 : void
215 : fd_http_resolver_add( fd_http_resolver_t * resolver,
216 : fd_ip4_port_t addr,
217 : char const * hostname,
218 0 : int is_https ) {
219 0 : if( !peer_pool_free( resolver->pool ) ) {
220 0 : FD_LOG_ERR(( "peer pool exhausted" ));
221 0 : }
222 0 : fd_ssresolve_peer_t * peer = peer_pool_ele_acquire( resolver->pool );
223 0 : peer->state = PEER_STATE_UNRESOLVED;
224 0 : peer->addr = addr;
225 0 : peer->hostname = hostname;
226 0 : peer->is_https = is_https;
227 0 : peer->fd.idx = ULONG_MAX;
228 0 : peer->ssinfo.full.slot = ULONG_MAX;
229 0 : peer->ssinfo.incremental.base_slot = ULONG_MAX;
230 0 : peer->ssinfo.incremental.slot = ULONG_MAX;
231 0 : deadline_list_ele_push_tail( resolver->unresolved, peer, resolver->pool );
232 0 : }
233 :
234 : static int
235 : create_socket( fd_http_resolver_t * resolver,
236 0 : fd_ssresolve_peer_t * peer ) {
237 0 : int sockfd = socket( AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0 );
238 0 : if( FD_UNLIKELY( -1==sockfd ) ) FD_LOG_ERR(( "socket failed (%i-%s)", errno, strerror( errno ) ));
239 :
240 0 : int optval = 1;
241 0 : if( FD_UNLIKELY( -1==setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int) ) ) ) {
242 0 : FD_LOG_ERR(( "setsockopt() failed (%d-%s)", errno, fd_io_strerror( errno ) ));
243 0 : }
244 :
245 0 : struct sockaddr_in addr = {
246 0 : .sin_family = AF_INET,
247 0 : .sin_port = peer->addr.port,
248 0 : .sin_addr = { .s_addr = peer->addr.addr }
249 0 : };
250 :
251 0 : if( FD_UNLIKELY( -1==connect( sockfd, fd_type_pun( &addr ), sizeof(addr) ) && errno!=EINPROGRESS ) ) {
252 0 : if( FD_UNLIKELY( -1==close( sockfd ) ) ) FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
253 0 : return -1;
254 0 : }
255 :
256 0 : resolver->fds[ resolver->fds_len ] = (struct pollfd){
257 0 : .fd = sockfd,
258 0 : .events = POLLIN|POLLOUT,
259 0 : .revents = 0
260 0 : };
261 :
262 0 : return 0;
263 0 : }
264 :
265 : static int
266 : peer_connect( fd_http_resolver_t * resolver,
267 0 : fd_ssresolve_peer_t * peer ) {
268 0 : int err;
269 0 : err = create_socket( resolver, peer ); /* full */
270 0 : if( FD_UNLIKELY( err ) ) return err;
271 0 : resolver->fds_idx[ resolver->fds_len ] = peer_pool_idx( resolver->pool, peer );
272 0 : peer->fd.idx = resolver->fds_len;
273 0 : resolver->fds_len++;
274 :
275 0 : if( FD_UNLIKELY( peer->is_https ) ) {
276 0 : #if FD_HAS_OPENSSL
277 0 : fd_ssresolve_init_https( peer->full_ssresolve, peer->addr, resolver->fds[ peer->fd.idx ].fd, 1, peer->hostname, resolver->ssl_ctx );
278 : #else
279 : FD_LOG_ERR(( "peer %s requires https but firedancer is built without openssl support. Please remove this peer from your validator config.", peer->hostname ));
280 : #endif
281 0 : } else {
282 0 : fd_ssresolve_init( peer->full_ssresolve, peer->addr, resolver->fds[ peer->fd.idx ].fd, 1 );
283 0 : }
284 :
285 0 : if( FD_LIKELY( resolver->incremental_snapshot_fetch ) ) {
286 0 : err = create_socket( resolver, peer ); /* incremental */
287 0 : if( FD_UNLIKELY( err ) ) return err;
288 0 : resolver->fds_idx[ resolver->fds_len ] = peer_pool_idx( resolver->pool, peer );
289 0 : resolver->fds_len++;
290 0 : if( FD_UNLIKELY( peer->is_https ) ) {
291 0 : #if FD_HAS_OPENSSL
292 0 : fd_ssresolve_init_https( peer->inc_ssresolve, peer->addr, resolver->fds[ peer->fd.idx+1UL ].fd, 0, peer->hostname, resolver->ssl_ctx );
293 : #else
294 : FD_LOG_ERR(( "peer requires https but firedancer is built without openssl support" ));
295 : #endif
296 0 : } else {
297 0 : fd_ssresolve_init( peer->inc_ssresolve, peer->addr, resolver->fds[ peer->fd.idx+1UL ].fd, 0 );
298 0 : }
299 0 : } else {
300 0 : resolver->fds[ resolver->fds_len ] = (struct pollfd) {
301 0 : .fd = -1,
302 0 : .events = 0,
303 0 : .revents = 0
304 0 : };
305 0 : resolver->fds_idx[ resolver->fds_len ] = ULONG_MAX;
306 0 : resolver->fds_len++;
307 0 : }
308 :
309 0 : return 0;
310 0 : }
311 :
312 : static inline void
313 : remove_peer( fd_http_resolver_t * resolver,
314 0 : ulong idx ) {
315 0 : FD_TEST( idx<resolver->fds_len );
316 :
317 0 : fd_ssresolve_peer_t * cur_peer = peer_pool_ele( resolver->pool, resolver->fds_idx[ idx ] );
318 0 : fd_ssresolve_cancel( cur_peer->full_ssresolve );
319 0 : fd_ssresolve_cancel( cur_peer->inc_ssresolve );
320 :
321 0 : if( FD_UNLIKELY( resolver->fds_len==2UL ) ) {
322 0 : resolver->fds_len = 0UL;
323 0 : return;
324 0 : }
325 :
326 0 : resolver->fds[ idx ] = resolver->fds[ resolver->fds_len-2UL ];
327 0 : resolver->fds_idx[ idx ] = resolver->fds_idx[ resolver->fds_len-2UL ];
328 :
329 0 : resolver->fds[ idx+1UL ] = resolver->fds[ resolver->fds_len-1UL ];
330 0 : resolver->fds_idx[ idx+1UL ] = resolver->fds_idx[ resolver->fds_len-1UL ];
331 :
332 0 : fd_ssresolve_peer_t * peer = peer_pool_ele( resolver->pool, resolver->fds_idx[ idx ] );
333 0 : peer->fd.idx = idx;
334 :
335 0 : resolver->fds_len -= 2UL;
336 0 : }
337 :
338 : static inline void
339 : unresolve_peer( fd_http_resolver_t * resolver,
340 : fd_ssresolve_peer_t * peer,
341 0 : long now ) {
342 0 : FD_TEST( peer->state==PEER_STATE_UNRESOLVED || peer->state==PEER_STATE_REFRESHING );
343 0 : remove_peer( resolver, peer->fd.idx );
344 0 : deadline_list_ele_remove( resolver->resolving, peer, resolver->pool );
345 0 : peer->state = PEER_STATE_INVALID;
346 0 : peer->deadline_nanos = now + PEER_DEADLINE_NANOS_INVALID;
347 0 : deadline_list_ele_push_tail( resolver->invalid, peer, resolver->pool );
348 0 : }
349 :
350 : static inline int
351 : poll_resolve( fd_http_resolver_t * resolver,
352 : struct pollfd * pfd,
353 : fd_ssresolve_peer_t * peer,
354 : fd_ssresolve_t * ssresolve,
355 : ulong idx,
356 0 : long now ) {
357 0 : FD_TEST( !fd_ssresolve_is_done( ssresolve ) );
358 0 : if( FD_LIKELY( pfd->revents & POLLOUT ) ) {
359 0 : int res = fd_ssresolve_advance_poll_out( ssresolve );
360 :
361 0 : if( FD_UNLIKELY( res==FD_SSRESOLVE_ADVANCE_ERROR ) ) {
362 0 : unresolve_peer( resolver, peer_pool_ele( resolver->pool, resolver->fds_idx[ idx ] ), now );
363 0 : return -1;
364 0 : }
365 0 : }
366 :
367 0 : if( FD_LIKELY( pfd->revents & POLLIN ) ) {
368 0 : fd_ssresolve_result_t resolve_result;
369 0 : int res = fd_ssresolve_advance_poll_in( ssresolve, &resolve_result );
370 :
371 0 : if( FD_UNLIKELY( res==FD_SSRESOLVE_ADVANCE_ERROR ) ) {
372 0 : unresolve_peer( resolver, peer_pool_ele( resolver->pool, resolver->fds_idx[ idx ] ), now );
373 0 : return -1;
374 0 : } else if( FD_UNLIKELY( res==FD_SSRESOLVE_ADVANCE_AGAIN ) ) {
375 0 : return -1;
376 0 : } else if( FD_LIKELY( res==FD_SSRESOLVE_ADVANCE_RESULT ) ) {
377 0 : FD_TEST( peer->deadline_nanos>now );
378 :
379 0 : if( resolve_result.base_slot==ULONG_MAX ) {
380 0 : peer->ssinfo.full.slot = resolve_result.slot;
381 0 : } else {
382 0 : peer->ssinfo.incremental.base_slot = resolve_result.base_slot;
383 0 : peer->ssinfo.incremental.slot = resolve_result.slot;
384 0 : }
385 0 : }
386 0 : }
387 :
388 0 : return 0;
389 0 : }
390 :
391 : static inline void
392 : poll_advance( fd_http_resolver_t * resolver,
393 0 : long now ) {
394 0 : if( FD_LIKELY( !resolver->fds_len ) ) return;
395 :
396 0 : int nfds = fd_syscall_poll( resolver->fds, (uint)resolver->fds_len, 0 );
397 0 : if( FD_LIKELY( !nfds ) ) return;
398 0 : else if( FD_UNLIKELY( -1==nfds && errno==EINTR ) ) return;
399 0 : else if( FD_UNLIKELY( -1==nfds ) ) FD_LOG_ERR(( "poll failed (%i-%s)", errno, strerror( errno ) ));
400 :
401 0 : for( ulong i=0UL; i<resolver->fds_len; i++) {
402 :
403 0 : struct pollfd * pfd = &resolver->fds[ i ];
404 0 : if( FD_UNLIKELY( pfd->fd==-1 ) ) continue;
405 0 : if( FD_UNLIKELY( pfd->revents & (POLLERR|POLLHUP) ) ) {
406 0 : unresolve_peer( resolver, peer_pool_ele( resolver->pool, resolver->fds_idx[ i ] ), now );
407 0 : continue;
408 0 : }
409 :
410 0 : fd_ssresolve_peer_t * peer = peer_pool_ele( resolver->pool, resolver->fds_idx[ i ] );
411 0 : int full = i&1UL ? 0 : 1; /* even indices are full, odd indices are incremental */
412 0 : fd_ssresolve_t * ssresolve = full ? peer->full_ssresolve : peer->inc_ssresolve;
413 :
414 0 : if( FD_LIKELY( !fd_ssresolve_is_done( ssresolve ) ) ) {
415 0 : int res = poll_resolve( resolver, pfd, peer, ssresolve, i, now );
416 0 : if( FD_UNLIKELY( res ) ) continue;
417 0 : }
418 :
419 : /* Once both the full and incremental snapshots are resolved, we can
420 : mark the peer valid and remove the peer from the list of peers to
421 : ping. */
422 0 : if( FD_LIKELY( fd_ssresolve_is_done( peer->full_ssresolve ) &&
423 0 : (!resolver->incremental_snapshot_fetch || fd_ssresolve_is_done( peer->inc_ssresolve ) ) ) ) {
424 0 : peer->state = PEER_STATE_VALID;
425 0 : peer->deadline_nanos = now + PEER_DEADLINE_NANOS_VALID;
426 :
427 0 : deadline_list_ele_remove( resolver->resolving, peer, resolver->pool );
428 0 : deadline_list_ele_push_tail( resolver->valid, peer, resolver->pool );
429 0 : remove_peer( resolver, peer->fd.idx );
430 :
431 0 : resolver->on_resolve_cb( resolver->cb_arg, peer->addr, &peer->ssinfo );
432 0 : }
433 0 : }
434 0 : }
435 :
436 : void
437 : fd_http_resolver_advance( fd_http_resolver_t * resolver,
438 : long now,
439 0 : fd_sspeer_selector_t * selector ) {
440 0 : while( !deadline_list_is_empty( resolver->unresolved, resolver->pool ) ) {
441 0 : fd_ssresolve_peer_t * peer = deadline_list_ele_pop_head( resolver->unresolved, resolver->pool );
442 :
443 0 : FD_LOG_INFO(( "resolving " FD_IP4_ADDR_FMT ":%hu", FD_IP4_ADDR_FMT_ARGS( peer->addr.addr ), fd_ushort_bswap( peer->addr.port ) ));
444 0 : int result = peer_connect( resolver, peer );
445 0 : if( FD_UNLIKELY( -1==result ) ) {
446 0 : peer->state = PEER_STATE_INVALID;
447 0 : peer->deadline_nanos = now + PEER_DEADLINE_NANOS_INVALID;
448 0 : deadline_list_ele_push_tail( resolver->invalid, peer, resolver->pool );
449 0 : } else {
450 0 : peer->state = PEER_STATE_REFRESHING;
451 0 : peer->deadline_nanos = now + PEER_DEADLINE_NANOS_RESOLVE;
452 0 : deadline_list_ele_push_tail( resolver->resolving, peer, resolver->pool );
453 0 : }
454 0 : }
455 :
456 0 : while( !deadline_list_is_empty( resolver->resolving, resolver->pool ) ) {
457 0 : fd_ssresolve_peer_t * peer = deadline_list_ele_peek_head( resolver->resolving, resolver->pool );
458 0 : if( FD_LIKELY( peer->deadline_nanos>now ) ) break;
459 :
460 0 : deadline_list_ele_pop_head( resolver->resolving, resolver->pool );
461 0 : peer->state = PEER_STATE_INVALID;
462 0 : peer->deadline_nanos = now + PEER_DEADLINE_NANOS_INVALID;
463 0 : deadline_list_ele_push_tail( resolver->invalid, peer, resolver->pool );
464 0 : remove_peer( resolver, peer->fd.idx );
465 :
466 0 : fd_sspeer_selector_remove( selector, peer->addr );
467 0 : }
468 :
469 0 : while( !deadline_list_is_empty( resolver->invalid, resolver->pool ) ) {
470 0 : fd_ssresolve_peer_t * peer = deadline_list_ele_peek_head( resolver->invalid, resolver->pool );
471 0 : if( FD_LIKELY( peer->deadline_nanos>now ) ) break;
472 :
473 0 : deadline_list_ele_pop_head( resolver->invalid, resolver->pool );
474 :
475 0 : peer->state = PEER_STATE_UNRESOLVED;
476 0 : peer->deadline_nanos = 0L;
477 0 : deadline_list_ele_push_tail( resolver->unresolved, peer, resolver->pool );
478 0 : }
479 :
480 0 : while( !deadline_list_is_empty( resolver->valid, resolver->pool ) ) {
481 0 : fd_ssresolve_peer_t * peer = deadline_list_ele_peek_head( resolver->valid, resolver->pool );
482 0 : if( FD_LIKELY( peer->deadline_nanos>now ) ) break;
483 :
484 0 : deadline_list_ele_pop_head( resolver->valid, resolver->pool );
485 :
486 0 : int result = peer_connect( resolver, peer );
487 0 : if( FD_UNLIKELY( -1==result ) ) {
488 0 : peer->state = PEER_STATE_INVALID;
489 0 : peer->deadline_nanos = now + PEER_DEADLINE_NANOS_INVALID;
490 0 : deadline_list_ele_push_tail( resolver->invalid, peer, resolver->pool );
491 0 : fd_sspeer_selector_remove( selector, peer->addr );
492 0 : } else {
493 0 : peer->state = PEER_STATE_REFRESHING;
494 0 : peer->deadline_nanos = now + PEER_DEADLINE_NANOS_RESOLVE;
495 0 : deadline_list_ele_push_tail( resolver->resolving, peer, resolver->pool );
496 0 : }
497 0 : }
498 :
499 0 : poll_advance( resolver, now );
500 0 : }
|