@@ -2009,6 +2009,280 @@ async fn dialer_fallback_protocol_works(transport1: Transport, transport2: Trans
2009
2009
) ;
2010
2010
}
2011
2011
2012
+ #[ tokio:: test]
2013
+ async fn zero_byte_handshake_tcp ( ) {
2014
+ // Full node role.
2015
+ zero_byte_handshake (
2016
+ Transport :: Tcp ( TcpConfig {
2017
+ listen_addresses : vec ! [ "/ip6/::1/tcp/0" . parse( ) . unwrap( ) ] ,
2018
+ ..Default :: default ( )
2019
+ } ) ,
2020
+ Transport :: Tcp ( TcpConfig {
2021
+ listen_addresses : vec ! [ "/ip6/::1/tcp/0" . parse( ) . unwrap( ) ] ,
2022
+ ..Default :: default ( )
2023
+ } ) ,
2024
+ vec ! [ 1 ] ,
2025
+ )
2026
+ . await ;
2027
+
2028
+ // Invalid role set as `ObservedRole::NONE`.
2029
+ zero_byte_handshake (
2030
+ Transport :: Tcp ( TcpConfig {
2031
+ listen_addresses : vec ! [ "/ip6/::1/tcp/0" . parse( ) . unwrap( ) ] ,
2032
+ ..Default :: default ( )
2033
+ } ) ,
2034
+ Transport :: Tcp ( TcpConfig {
2035
+ listen_addresses : vec ! [ "/ip6/::1/tcp/0" . parse( ) . unwrap( ) ] ,
2036
+ ..Default :: default ( )
2037
+ } ) ,
2038
+ vec ! [ 0 ] ,
2039
+ )
2040
+ . await ;
2041
+
2042
+ // Light client role provided by smoldot.
2043
+ zero_byte_handshake (
2044
+ Transport :: Tcp ( TcpConfig {
2045
+ listen_addresses : vec ! [ "/ip6/::1/tcp/0" . parse( ) . unwrap( ) ] ,
2046
+ ..Default :: default ( )
2047
+ } ) ,
2048
+ Transport :: Tcp ( TcpConfig {
2049
+ listen_addresses : vec ! [ "/ip6/::1/tcp/0" . parse( ) . unwrap( ) ] ,
2050
+ ..Default :: default ( )
2051
+ } ) ,
2052
+ vec ! [ ] ,
2053
+ )
2054
+ . await ;
2055
+ }
2056
+
2057
+ #[ cfg( feature = "quic" ) ]
2058
+ #[ tokio:: test]
2059
+ async fn zero_byte_handshake_quic ( ) {
2060
+ zero_byte_handshake (
2061
+ Transport :: Quic ( Default :: default ( ) ) ,
2062
+ Transport :: Quic ( Default :: default ( ) ) ,
2063
+ vec ! [ 1 ] ,
2064
+ )
2065
+ . await ;
2066
+
2067
+ zero_byte_handshake (
2068
+ Transport :: Quic ( Default :: default ( ) ) ,
2069
+ Transport :: Quic ( Default :: default ( ) ) ,
2070
+ vec ! [ 0 ] ,
2071
+ )
2072
+ . await ;
2073
+
2074
+ zero_byte_handshake (
2075
+ Transport :: Quic ( Default :: default ( ) ) ,
2076
+ Transport :: Quic ( Default :: default ( ) ) ,
2077
+ vec ! [ ] ,
2078
+ )
2079
+ . await ;
2080
+ }
2081
+
2082
+ #[ cfg( feature = "websocket" ) ]
2083
+ #[ tokio:: test]
2084
+ async fn zero_byte_handshake_websocket ( ) {
2085
+ // Full node role.
2086
+ zero_byte_handshake (
2087
+ Transport :: WebSocket ( WebSocketConfig {
2088
+ listen_addresses : vec ! [ "/ip4/127.0.0.1/tcp/0/ws" . parse( ) . unwrap( ) ] ,
2089
+ ..Default :: default ( )
2090
+ } ) ,
2091
+ Transport :: WebSocket ( WebSocketConfig {
2092
+ listen_addresses : vec ! [ "/ip4/127.0.0.1/tcp/0/ws" . parse( ) . unwrap( ) ] ,
2093
+ ..Default :: default ( )
2094
+ } ) ,
2095
+ vec ! [ 1 ] ,
2096
+ )
2097
+ . await ;
2098
+
2099
+ // Invalid role set as `ObservedRole::NONE`.
2100
+ zero_byte_handshake (
2101
+ Transport :: WebSocket ( WebSocketConfig {
2102
+ listen_addresses : vec ! [ "/ip4/127.0.0.1/tcp/0/ws" . parse( ) . unwrap( ) ] ,
2103
+ ..Default :: default ( )
2104
+ } ) ,
2105
+ Transport :: WebSocket ( WebSocketConfig {
2106
+ listen_addresses : vec ! [ "/ip4/127.0.0.1/tcp/0/ws" . parse( ) . unwrap( ) ] ,
2107
+ ..Default :: default ( )
2108
+ } ) ,
2109
+ vec ! [ 0 ] ,
2110
+ )
2111
+ . await ;
2112
+
2113
+ // Light client role provided by smoldot.
2114
+ zero_byte_handshake (
2115
+ Transport :: WebSocket ( WebSocketConfig {
2116
+ listen_addresses : vec ! [ "/ip4/127.0.0.1/tcp/0/ws" . parse( ) . unwrap( ) ] ,
2117
+ ..Default :: default ( )
2118
+ } ) ,
2119
+ Transport :: WebSocket ( WebSocketConfig {
2120
+ listen_addresses : vec ! [ "/ip4/127.0.0.1/tcp/0/ws" . parse( ) . unwrap( ) ] ,
2121
+ ..Default :: default ( )
2122
+ } ) ,
2123
+ vec ! [ ] ,
2124
+ )
2125
+ . await ;
2126
+ }
2127
+
2128
+ async fn zero_byte_handshake ( transport1 : Transport , transport2 : Transport , handshake : Vec < u8 > ) {
2129
+ let _ = tracing_subscriber:: fmt ( )
2130
+ . with_env_filter ( tracing_subscriber:: EnvFilter :: from_default_env ( ) )
2131
+ . try_init ( ) ;
2132
+
2133
+ let ( notif_config1, mut handle1) = ConfigBuilder :: new ( ProtocolName :: from ( "/notif/1" ) )
2134
+ . with_max_size ( 1024usize )
2135
+ . with_handshake ( handshake. clone ( ) )
2136
+ . build ( ) ;
2137
+
2138
+ let config1 = Litep2pConfigBuilder :: new ( )
2139
+ . with_keypair ( Keypair :: generate ( ) )
2140
+ . with_notification_protocol ( notif_config1) ;
2141
+
2142
+ let config1 = add_transport ( config1, transport1) . build ( ) ;
2143
+
2144
+ let ( notif_config2, mut handle2) = ConfigBuilder :: new ( ProtocolName :: from ( "/notif/1" ) )
2145
+ . with_max_size ( 1024usize )
2146
+ . with_handshake ( handshake. clone ( ) )
2147
+ . build ( ) ;
2148
+ let config2 = Litep2pConfigBuilder :: new ( )
2149
+ . with_keypair ( Keypair :: generate ( ) )
2150
+ . with_notification_protocol ( notif_config2) ;
2151
+
2152
+ let config2 = add_transport ( config2, transport2) . build ( ) ;
2153
+
2154
+ let mut litep2p1 = Litep2p :: new ( config1) . unwrap ( ) ;
2155
+ let mut litep2p2 = Litep2p :: new ( config2) . unwrap ( ) ;
2156
+
2157
+ let peer1 = * litep2p1. local_peer_id ( ) ;
2158
+ let peer2 = * litep2p2. local_peer_id ( ) ;
2159
+
2160
+ // wait until peers have connected and spawn the litep2p objects in the background
2161
+ connect_peers ( & mut litep2p1, & mut litep2p2) . await ;
2162
+ tokio:: spawn ( async move {
2163
+ loop {
2164
+ tokio:: select! {
2165
+ _ = litep2p1. next_event( ) => { } ,
2166
+ _ = litep2p2. next_event( ) => { } ,
2167
+ }
2168
+ }
2169
+ } ) ;
2170
+
2171
+ // open substream for `peer2` and accept it
2172
+ tracing:: info!( "Opening substream handle1 => handle2" ) ;
2173
+ handle1. open_substream ( peer2) . await . unwrap ( ) ;
2174
+
2175
+ tracing:: info!( "Expecting validate substream event..." ) ;
2176
+ assert_eq ! (
2177
+ handle2. next( ) . await . unwrap( ) ,
2178
+ NotificationEvent :: ValidateSubstream {
2179
+ protocol: ProtocolName :: from( "/notif/1" ) ,
2180
+ fallback: None ,
2181
+ peer: peer1,
2182
+ handshake: handshake. clone( ) ,
2183
+ }
2184
+ ) ;
2185
+
2186
+ tracing:: info!( "Send validation result... peer2 => peer1" ) ;
2187
+ handle2. send_validation_result ( peer1, ValidationResult :: Accept ) ;
2188
+ assert_eq ! (
2189
+ handle1. next( ) . await . unwrap( ) ,
2190
+ NotificationEvent :: ValidateSubstream {
2191
+ protocol: ProtocolName :: from( "/notif/1" ) ,
2192
+ fallback: None ,
2193
+ peer: peer2,
2194
+ handshake: handshake. clone( ) ,
2195
+ }
2196
+ ) ;
2197
+
2198
+ tracing:: info!( "Send validation result... peer1 => peer2" ) ;
2199
+ handle1. send_validation_result ( peer2, ValidationResult :: Accept ) ;
2200
+
2201
+ tracing:: info!( "Handle2 expecting notification stream opened event..." ) ;
2202
+ assert_eq ! (
2203
+ handle2. next( ) . await . unwrap( ) ,
2204
+ NotificationEvent :: NotificationStreamOpened {
2205
+ protocol: ProtocolName :: from( "/notif/1" ) ,
2206
+ fallback: None ,
2207
+ direction: Direction :: Inbound ,
2208
+ peer: peer1,
2209
+ handshake: handshake. clone( ) ,
2210
+ }
2211
+ ) ;
2212
+
2213
+ tracing:: info!( "Handle1 expecting notification stream opened event..." ) ;
2214
+ assert_eq ! (
2215
+ handle1. next( ) . await . unwrap( ) ,
2216
+ NotificationEvent :: NotificationStreamOpened {
2217
+ protocol: ProtocolName :: from( "/notif/1" ) ,
2218
+ fallback: None ,
2219
+ direction: Direction :: Outbound ,
2220
+ peer: peer2,
2221
+ handshake: handshake,
2222
+ }
2223
+ ) ;
2224
+
2225
+ // This step ensures we have not messed with the notification frames.
2226
+ tracing:: info!( "Send sync notification..." ) ;
2227
+ handle1. send_sync_notification ( peer2, vec ! [ 1 , 3 , 3 , 7 ] ) . unwrap ( ) ;
2228
+ handle2. send_sync_notification ( peer1, vec ! [ 1 , 3 , 3 , 8 ] ) . unwrap ( ) ;
2229
+
2230
+ assert_eq ! (
2231
+ handle2. next( ) . await . unwrap( ) ,
2232
+ NotificationEvent :: NotificationReceived {
2233
+ peer: peer1,
2234
+ notification: BytesMut :: from( & [ 1 , 3 , 3 , 7 ] [ ..] ) ,
2235
+ }
2236
+ ) ;
2237
+ assert_eq ! (
2238
+ handle1. next( ) . await . unwrap( ) ,
2239
+ NotificationEvent :: NotificationReceived {
2240
+ peer: peer2,
2241
+ notification: BytesMut :: from( & [ 1 , 3 , 3 , 8 ] [ ..] ) ,
2242
+ }
2243
+ ) ;
2244
+
2245
+ // Ensure the handle can send empty notifications.
2246
+ tracing:: info!( "Send empty sync notification..." ) ;
2247
+ handle1. send_sync_notification ( peer2, vec ! [ ] ) . unwrap ( ) ;
2248
+ handle2. send_sync_notification ( peer1, vec ! [ ] ) . unwrap ( ) ;
2249
+
2250
+ assert_eq ! (
2251
+ handle2. next( ) . await . unwrap( ) ,
2252
+ NotificationEvent :: NotificationReceived {
2253
+ peer: peer1,
2254
+ notification: BytesMut :: from( & [ ] [ ..] ) ,
2255
+ }
2256
+ ) ;
2257
+ assert_eq ! (
2258
+ handle1. next( ) . await . unwrap( ) ,
2259
+ NotificationEvent :: NotificationReceived {
2260
+ peer: peer2,
2261
+ notification: BytesMut :: from( & [ ] [ ..] ) ,
2262
+ }
2263
+ ) ;
2264
+
2265
+ // Double check non-empty notifications.
2266
+ tracing:: info!( "Send sync notification..." ) ;
2267
+ handle1. send_sync_notification ( peer2, vec ! [ 1 , 3 , 3 , 9 ] ) . unwrap ( ) ;
2268
+ handle2. send_sync_notification ( peer1, vec ! [ 1 , 3 , 3 , 4 ] ) . unwrap ( ) ;
2269
+
2270
+ assert_eq ! (
2271
+ handle2. next( ) . await . unwrap( ) ,
2272
+ NotificationEvent :: NotificationReceived {
2273
+ peer: peer1,
2274
+ notification: BytesMut :: from( & [ 1 , 3 , 3 , 9 ] [ ..] ) ,
2275
+ }
2276
+ ) ;
2277
+ assert_eq ! (
2278
+ handle1. next( ) . await . unwrap( ) ,
2279
+ NotificationEvent :: NotificationReceived {
2280
+ peer: peer2,
2281
+ notification: BytesMut :: from( & [ 1 , 3 , 3 , 4 ] [ ..] ) ,
2282
+ }
2283
+ ) ;
2284
+ }
2285
+
2012
2286
#[ tokio:: test]
2013
2287
async fn listener_fallback_protocol_works_tcp ( ) {
2014
2288
listener_fallback_protocol_works (
0 commit comments