@@ -21,6 +21,7 @@ use super::{
21
21
types:: { ClientInfo , MeshKey , RateLimiter , ServerInfo } ,
22
22
} ;
23
23
24
+ use crate :: derp:: codec:: PkarrWirePacket ;
24
25
use crate :: key:: { PublicKey , SecretKey } ;
25
26
use crate :: util:: AbortingJoinHandle ;
26
27
@@ -76,6 +77,8 @@ pub struct InnerClient {
76
77
reader_task : AbortingJoinHandle < ( ) > ,
77
78
/// [`PublicKey`] of the server we are connected to
78
79
server_public_key : PublicKey ,
80
+ /// Whether the server supports publishing pkarr packets for us
81
+ can_pkarr_publish : bool ,
79
82
}
80
83
81
84
impl Client {
@@ -160,6 +163,21 @@ impl Client {
160
163
Ok ( ( ) )
161
164
}
162
165
166
+ /// Send a pkarr packet to the derper to publish for us.
167
+ ///
168
+ /// Must be signed by our secret key, otherwise the derper will reject it.
169
+ pub async fn pkarr_publish_packet ( & self , packet : pkarr:: SignedPacket ) -> Result < ( ) > {
170
+ if !self . inner . can_pkarr_publish {
171
+ bail ! ( "the server does not allow pkarr publishing" ) ;
172
+ }
173
+ // todo: check pkey
174
+ self . inner
175
+ . writer_channel
176
+ . send ( ClientWriterMessage :: PkarrPublish ( packet) )
177
+ . await ?;
178
+ Ok ( ( ) )
179
+ }
180
+
163
181
/// The local address that the [`Client`] is listening on.
164
182
pub fn local_addr ( & self ) -> Result < SocketAddr > {
165
183
Ok ( self . inner . local_addr )
@@ -253,6 +271,8 @@ enum ClientWriterMessage {
253
271
/// Asks the server to close the target's connection.
254
272
/// Should only be used for mesh clients.
255
273
ClosePeer ( PublicKey ) ,
274
+ /// Publish a pkarr signed packet about ourselves
275
+ PkarrPublish ( pkarr:: SignedPacket ) ,
256
276
/// Shutdown the writer
257
277
Shutdown ,
258
278
}
@@ -305,6 +325,11 @@ impl<W: AsyncWrite + Unpin + Send + 'static> ClientWriter<W> {
305
325
write_frame ( & mut self . writer , Frame :: ClosePeer { peer } , None ) . await ?;
306
326
self . writer . flush ( ) . await ?;
307
327
}
328
+ ClientWriterMessage :: PkarrPublish ( packet) => {
329
+ let packet = PkarrWirePacket :: V0 ( packet. as_bytes ( ) ) ;
330
+ write_frame ( & mut self . writer , Frame :: PkarrPublish { packet } , None ) . await ?;
331
+ self . writer . flush ( ) . await ?;
332
+ }
308
333
ClientWriterMessage :: Shutdown => {
309
334
return Ok ( ( ) ) ;
310
335
}
@@ -368,7 +393,7 @@ impl ClientBuilder {
368
393
self
369
394
}
370
395
371
- async fn server_handshake ( & mut self ) -> Result < ( PublicKey , Option < RateLimiter > ) > {
396
+ async fn server_handshake ( & mut self ) -> Result < ( PublicKey , Option < RateLimiter > , bool ) > {
372
397
debug ! ( "server_handshake: started" ) ;
373
398
let server_key = recv_server_key ( & mut self . reader )
374
399
. await
@@ -404,6 +429,8 @@ impl ClientBuilder {
404
429
} ;
405
430
let mut buf = encrypted_message. to_vec ( ) ;
406
431
shared_secret. open ( & mut buf) ?;
432
+
433
+ // TODO: Can we parse the server info from old derpers without pkarr support?
407
434
let info: ServerInfo = postcard:: from_bytes ( & buf) ?;
408
435
if info. version != PROTOCOL_VERSION {
409
436
bail ! (
@@ -417,12 +444,12 @@ impl ClientBuilder {
417
444
) ?;
418
445
419
446
debug ! ( "server_handshake: done" ) ;
420
- Ok ( ( server_key, rate_limiter) )
447
+ Ok ( ( server_key, rate_limiter, info . can_pkarr_publish ) )
421
448
}
422
449
423
450
pub async fn build ( mut self ) -> Result < ( Client , ClientReceiver ) > {
424
451
// exchange information with the server
425
- let ( server_public_key, rate_limiter) = self . server_handshake ( ) . await ?;
452
+ let ( server_public_key, rate_limiter, can_pkarr_publish ) = self . server_handshake ( ) . await ?;
426
453
427
454
// create task to handle writing to the server
428
455
let ( writer_sender, writer_recv) = mpsc:: channel ( PER_CLIENT_SEND_QUEUE_DEPTH ) ;
@@ -485,6 +512,7 @@ impl ClientBuilder {
485
512
writer_task : writer_task. into ( ) ,
486
513
reader_task : reader_task. into ( ) ,
487
514
server_public_key,
515
+ can_pkarr_publish,
488
516
} ) ,
489
517
} ;
490
518
0 commit comments