25
25
* takes care of the serializing and de-serializing DHT packets
26
26
*/
27
27
28
- use nom:: { le_u8, be_u64, rest} ;
28
+ use nom:: { le_u8, be_u32 , be_u64, rest} ;
29
29
30
30
use std:: io:: { Error , ErrorKind } ;
31
31
@@ -78,7 +78,8 @@ pub enum DhtPacket {
78
78
OnionResponse2 ( OnionResponse2 ) ,
79
79
/// [`OnionResponse1`](../onion/struct.OnionResponse1.html) structure.
80
80
OnionResponse1 ( OnionResponse1 ) ,
81
- // TODO: BootstrapInfo
81
+ /// [`BootstrapInfo`](./struct.BootstrapInfo.html) structure.
82
+ BootstrapInfo ( BootstrapInfo )
82
83
}
83
84
84
85
impl ToBytes for DhtPacket {
@@ -100,6 +101,7 @@ impl ToBytes for DhtPacket {
100
101
DhtPacket :: OnionResponse3 ( ref p) => p. to_bytes ( buf) ,
101
102
DhtPacket :: OnionResponse2 ( ref p) => p. to_bytes ( buf) ,
102
103
DhtPacket :: OnionResponse1 ( ref p) => p. to_bytes ( buf) ,
104
+ DhtPacket :: BootstrapInfo ( ref p) => p. to_bytes ( buf)
103
105
}
104
106
}
105
107
}
@@ -121,7 +123,8 @@ impl FromBytes for DhtPacket {
121
123
map!( OnionDataResponse :: from_bytes, DhtPacket :: OnionDataResponse ) |
122
124
map!( OnionResponse3 :: from_bytes, DhtPacket :: OnionResponse3 ) |
123
125
map!( OnionResponse2 :: from_bytes, DhtPacket :: OnionResponse2 ) |
124
- map!( OnionResponse1 :: from_bytes, DhtPacket :: OnionResponse1 )
126
+ map!( OnionResponse1 :: from_bytes, DhtPacket :: OnionResponse1 ) |
127
+ map!( BootstrapInfo :: from_bytes, DhtPacket :: BootstrapInfo )
125
128
) ) ;
126
129
}
127
130
@@ -804,6 +807,62 @@ impl FromBytes for LanDiscovery {
804
807
) ) ;
805
808
}
806
809
810
+ /** Sent by both client and server, only server will respond.
811
+ When server receives this packet it may respond with the version of the library
812
+ plus MoTD (message of the day). The max length of MoTD is 256 bytes so the max packet
813
+ lenght of server BootstrapInfo is 261=(1+4+256) bytes.
814
+
815
+ Client must send a BootstrapInfo of exactly 78 bytes, the only 1 field is required: `packet type`
816
+ which is filled automatically. So version may be filled with any value, so does MoTD, but
817
+ it has to be exactly 73=(78-1-4) bytes long. The server should check that the size of the
818
+ packet is exactly 78 bytes long (or MoTD=73 bytes filled with any values). Frankly speaking,
819
+ there should be neither `version` nor `motd` fields in the request version, the serialized form
820
+ should be 1 byte with packet type + (78-1) bytes of trash, but this implementation is simplified.
821
+
822
+ Serialized form:
823
+
824
+ Length | Contents
825
+ ----------- | --------
826
+ `1` | `0xF0`
827
+ `4` | Version in BigEndian
828
+ variable | MoTD, must not longer than 256 bytes
829
+
830
+ */
831
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
832
+ pub struct BootstrapInfo {
833
+ /// The version of DHT server
834
+ pub version : u32 ,
835
+ /// Message of the day
836
+ pub motd : Vec < u8 > ,
837
+ }
838
+
839
+ /// Length of in bytes of MoTD field of [`BootstrapInfo`](./struct.BootstrapInfo.html)
840
+ /// when server responds with info.
841
+ pub const BOOSTRAP_SERVER_MAX_MOTD_LENGTH : usize = 256 ;
842
+ /// Length of in bytes of MoTD field of [`BootstrapInfo`](./struct.BootstrapInfo.html)
843
+ /// when client requests info. 73 = 78 (max client request len) - 1 (type) - 4 (version)
844
+ pub const BOOSTRAP_CLIENT_MAX_MOTD_LENGTH : usize = 73 ;
845
+
846
+ impl ToBytes for BootstrapInfo {
847
+ fn to_bytes < ' a > ( & self , buf : ( & ' a mut [ u8 ] , usize ) ) -> Result < ( & ' a mut [ u8 ] , usize ) , GenError > {
848
+ do_gen ! ( buf,
849
+ gen_be_u8!( 0xf0 ) >>
850
+ gen_be_u32!( self . version) >>
851
+ gen_slice!( self . motd. as_slice( ) )
852
+ )
853
+ }
854
+ }
855
+
856
+ impl FromBytes for BootstrapInfo {
857
+ named ! ( from_bytes<BootstrapInfo >, do_parse!(
858
+ tag!( & [ 0xf0 ] [ ..] ) >>
859
+ version: be_u32 >>
860
+ motd: verify!( rest, |motd: & [ u8 ] | motd. len( ) <= BOOSTRAP_SERVER_MAX_MOTD_LENGTH ) >>
861
+ ( BootstrapInfo { version, motd: motd. to_vec( ) } )
862
+ ) ) ;
863
+ }
864
+
865
+
807
866
#[ cfg( test) ]
808
867
mod tests {
809
868
use super :: * ;
@@ -1295,6 +1354,14 @@ mod tests {
1295
1354
} )
1296
1355
) ;
1297
1356
1357
+ encode_decode_test ! (
1358
+ bootstrap_info_encode_decode,
1359
+ DhtPacket :: BootstrapInfo ( BootstrapInfo {
1360
+ version: 42 ,
1361
+ motd: vec![ 1 , 2 , 3 , 4 ]
1362
+ } )
1363
+ ) ;
1364
+
1298
1365
macro_rules! dht_packet_encrypt_decrypt (
1299
1366
( $test: ident, $packet: ident, $payload: expr) => (
1300
1367
#[ test]
0 commit comments