@@ -1175,6 +1175,8 @@ pub enum ClientError {
1175
1175
Io ( ChannelAddr , std:: io:: Error ) ,
1176
1176
#[ error( "send {0}: serialize: {1}" ) ]
1177
1177
Serialize ( ChannelAddr , bincode:: ErrorKind ) ,
1178
+ #[ error( "invalid address: {0}" ) ]
1179
+ InvalidAddress ( String ) ,
1178
1180
}
1179
1181
1180
1182
#[ derive( EnumAsInner ) ]
@@ -2175,14 +2177,23 @@ pub(crate) mod meta {
2175
2177
2176
2178
#[ allow( clippy:: result_large_err) ] // TODO: Consider reducing the size of `ChannelError`.
2177
2179
pub ( crate ) fn parse ( addr_string : & str ) -> Result < ChannelAddr , ChannelError > {
2180
+ // Try to parse as a socket address first
2181
+ if let Ok ( socket_addr) = addr_string. parse :: < SocketAddr > ( ) {
2182
+ return Ok ( ChannelAddr :: MetaTls ( MetaTlsAddr :: Socket ( socket_addr) ) ) ;
2183
+ }
2184
+
2185
+ // Otherwise, parse as hostname:port
2178
2186
// use right split to allow for ipv6 addresses where ":" is expected.
2179
2187
let parts = addr_string. rsplit_once ( ":" ) ;
2180
2188
match parts {
2181
2189
Some ( ( hostname, port_str) ) => {
2182
2190
let Ok ( port) = port_str. parse ( ) else {
2183
2191
return Err ( ChannelError :: InvalidAddress ( addr_string. to_string ( ) ) ) ;
2184
2192
} ;
2185
- Ok ( ChannelAddr :: MetaTls ( hostname. to_string ( ) , port) )
2193
+ Ok ( ChannelAddr :: MetaTls ( MetaTlsAddr :: Host {
2194
+ hostname : hostname. to_string ( ) ,
2195
+ port,
2196
+ } ) )
2186
2197
}
2187
2198
_ => Err ( ChannelError :: InvalidAddress ( addr_string. to_string ( ) ) ) ,
2188
2199
}
@@ -2314,7 +2325,10 @@ pub(crate) mod meta {
2314
2325
type Stream = TlsStream < TcpStream > ;
2315
2326
2316
2327
fn dest ( & self ) -> ChannelAddr {
2317
- ChannelAddr :: MetaTls ( self . hostname . clone ( ) , self . port )
2328
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Host {
2329
+ hostname : self . hostname . clone ( ) ,
2330
+ port : self . port ,
2331
+ } )
2318
2332
}
2319
2333
2320
2334
async fn connect ( & self ) -> Result < Self :: Stream , ClientError > {
@@ -2353,42 +2367,93 @@ pub(crate) mod meta {
2353
2367
}
2354
2368
}
2355
2369
2356
- pub fn dial < M : RemoteMessage > ( hostname : Hostname , port : Port ) -> NetTx < M > {
2357
- NetTx :: new ( MetaLink { hostname, port } )
2370
+ pub fn dial < M : RemoteMessage > ( addr : MetaTlsAddr ) -> Result < NetTx < M > , ClientError > {
2371
+ match addr {
2372
+ MetaTlsAddr :: Host { hostname, port } => Ok ( NetTx :: new ( MetaLink { hostname, port } ) ) ,
2373
+ MetaTlsAddr :: Socket ( _) => Err ( ClientError :: InvalidAddress (
2374
+ "MetaTls clients require hostname/port for host identity, not socket addresses"
2375
+ . to_string ( ) ,
2376
+ ) ) ,
2377
+ }
2358
2378
}
2359
2379
2360
- /// Serve the given address with hostname and port. If port 0 is provided,
2361
- /// dynamic port will be resolved and is available on the returned ServerHandle.
2380
+ /// Serve the given address. If port 0 is provided in a Host address,
2381
+ /// a dynamic port will be resolved and is available in the returned ChannelAddr.
2382
+ /// For Host addresses, binds to all resolved socket addresses.
2362
2383
pub fn serve < M : RemoteMessage > (
2363
- hostname : Hostname ,
2364
- port : Port ,
2384
+ addr : MetaTlsAddr ,
2365
2385
) -> Result < ( ChannelAddr , NetRx < M > ) , ServerError > {
2366
- let mut addrs = ( hostname. as_ref ( ) , port) . to_socket_addrs ( ) . map_err ( |err| {
2367
- ServerError :: Resolve ( ChannelAddr :: MetaTls ( hostname. clone ( ) , port) , err)
2368
- } ) ?;
2369
- let addr = addrs. next ( ) . ok_or ( ServerError :: Resolve (
2370
- ChannelAddr :: MetaTls ( hostname. clone ( ) , port) ,
2371
- io:: Error :: other ( "no available socket addr" ) ,
2372
- ) ) ?;
2373
- let channel_addr = ChannelAddr :: MetaTls ( hostname. clone ( ) , port) ;
2386
+ match addr {
2387
+ MetaTlsAddr :: Host { hostname, port } => {
2388
+ // Resolve all addresses for the hostname
2389
+ let addrs: Vec < SocketAddr > = ( hostname. as_ref ( ) , port)
2390
+ . to_socket_addrs ( )
2391
+ . map_err ( |err| {
2392
+ ServerError :: Resolve (
2393
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Host {
2394
+ hostname : hostname. clone ( ) ,
2395
+ port,
2396
+ } ) ,
2397
+ err,
2398
+ )
2399
+ } ) ?
2400
+ . collect ( ) ;
2401
+
2402
+ if addrs. is_empty ( ) {
2403
+ return Err ( ServerError :: Resolve (
2404
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Host { hostname, port } ) ,
2405
+ io:: Error :: other ( "no available socket addr" ) ,
2406
+ ) ) ;
2407
+ }
2374
2408
2375
- // Go by way of a std listener to avoid making this function async.
2376
- let std_listener = std:: net:: TcpListener :: bind ( addr)
2377
- . map_err ( |err| ServerError :: Listen ( channel_addr. clone ( ) , err) ) ?;
2378
- std_listener
2379
- . set_nonblocking ( true )
2380
- . map_err ( |e| ServerError :: Listen ( channel_addr. clone ( ) , e) ) ?;
2381
- let listener = TcpListener :: from_std ( std_listener)
2382
- . map_err ( |e| ServerError :: Listen ( channel_addr. clone ( ) , e) ) ?;
2409
+ let channel_addr = ChannelAddr :: MetaTls ( MetaTlsAddr :: Host {
2410
+ hostname : hostname. clone ( ) ,
2411
+ port,
2412
+ } ) ;
2383
2413
2384
- let local_addr = listener
2385
- . local_addr ( )
2386
- . map_err ( |err| ServerError :: Resolve ( channel_addr, err) ) ?;
2387
- super :: serve (
2388
- listener,
2389
- ChannelAddr :: MetaTls ( hostname, local_addr. port ( ) ) ,
2390
- true ,
2391
- )
2414
+ // Bind to all resolved addresses
2415
+ let std_listener = std:: net:: TcpListener :: bind ( & addrs[ ..] )
2416
+ . map_err ( |err| ServerError :: Listen ( channel_addr. clone ( ) , err) ) ?;
2417
+ std_listener
2418
+ . set_nonblocking ( true )
2419
+ . map_err ( |e| ServerError :: Listen ( channel_addr. clone ( ) , e) ) ?;
2420
+ let listener = TcpListener :: from_std ( std_listener)
2421
+ . map_err ( |e| ServerError :: Listen ( channel_addr. clone ( ) , e) ) ?;
2422
+
2423
+ let local_addr = listener
2424
+ . local_addr ( )
2425
+ . map_err ( |err| ServerError :: Resolve ( channel_addr, err) ) ?;
2426
+ super :: serve (
2427
+ listener,
2428
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Host {
2429
+ hostname,
2430
+ port : local_addr. port ( ) ,
2431
+ } ) ,
2432
+ true ,
2433
+ )
2434
+ }
2435
+ MetaTlsAddr :: Socket ( socket_addr) => {
2436
+ let channel_addr = ChannelAddr :: MetaTls ( MetaTlsAddr :: Socket ( socket_addr) ) ;
2437
+
2438
+ // Bind directly to the socket address
2439
+ let std_listener = std:: net:: TcpListener :: bind ( socket_addr)
2440
+ . map_err ( |err| ServerError :: Listen ( channel_addr. clone ( ) , err) ) ?;
2441
+ std_listener
2442
+ . set_nonblocking ( true )
2443
+ . map_err ( |e| ServerError :: Listen ( channel_addr. clone ( ) , e) ) ?;
2444
+ let listener = TcpListener :: from_std ( std_listener)
2445
+ . map_err ( |e| ServerError :: Listen ( channel_addr. clone ( ) , e) ) ?;
2446
+
2447
+ let local_addr = listener
2448
+ . local_addr ( )
2449
+ . map_err ( |err| ServerError :: Resolve ( channel_addr, err) ) ?;
2450
+ super :: serve (
2451
+ listener,
2452
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Socket ( local_addr) ) ,
2453
+ true ,
2454
+ )
2455
+ }
2456
+ }
2392
2457
}
2393
2458
}
2394
2459
@@ -2569,11 +2634,11 @@ mod tests {
2569
2634
#[ tokio:: test]
2570
2635
async fn test_meta_tls_basic ( ) {
2571
2636
let addr = ChannelAddr :: any ( ChannelTransport :: MetaTls ( TlsMode :: IpV6 ) ) ;
2572
- let ( hostname , port ) = match addr {
2573
- ChannelAddr :: MetaTls ( hostname , port ) => ( hostname , port ) ,
2574
- _ => ( "" . to_string ( ) , 0 ) ,
2637
+ let meta_addr = match addr {
2638
+ ChannelAddr :: MetaTls ( meta_addr ) => meta_addr ,
2639
+ _ => panic ! ( "expected MetaTls address" ) ,
2575
2640
} ;
2576
- let ( local_addr, mut rx) = net:: meta:: serve :: < u64 > ( hostname , port ) . unwrap ( ) ;
2641
+ let ( local_addr, mut rx) = net:: meta:: serve :: < u64 > ( meta_addr ) . unwrap ( ) ;
2577
2642
{
2578
2643
let tx = dial :: < u64 > ( local_addr. clone ( ) ) . unwrap ( ) ;
2579
2644
tx. try_post ( 123 , unused_return_channel ( ) ) . unwrap ( ) ;
@@ -3736,17 +3801,35 @@ mod tests {
3736
3801
fn test_metatls_parsing ( ) {
3737
3802
// host:port
3738
3803
let channel: ChannelAddr = "metatls!localhost:1234" . parse ( ) . unwrap ( ) ;
3739
- assert_eq ! ( channel, ChannelAddr :: MetaTls ( "localhost" . to_string( ) , 1234 ) ) ;
3740
- // ipv4:port
3804
+ assert_eq ! (
3805
+ channel,
3806
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Host {
3807
+ hostname: "localhost" . to_string( ) ,
3808
+ port: 1234
3809
+ } )
3810
+ ) ;
3811
+ // ipv4:port - can be parsed as hostname or socket address
3741
3812
let channel: ChannelAddr = "metatls!1.2.3.4:1234" . parse ( ) . unwrap ( ) ;
3742
- assert_eq ! ( channel, ChannelAddr :: MetaTls ( "1.2.3.4" . to_string( ) , 1234 ) ) ;
3813
+ assert_eq ! (
3814
+ channel,
3815
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Socket ( "1.2.3.4:1234" . parse( ) . unwrap( ) ) )
3816
+ ) ;
3743
3817
// ipv6:port
3744
3818
let channel: ChannelAddr = "metatls!2401:db00:33c:6902:face:0:2a2:0:1234"
3745
3819
. parse ( )
3746
3820
. unwrap ( ) ;
3747
3821
assert_eq ! (
3748
3822
channel,
3749
- ChannelAddr :: MetaTls ( "2401:db00:33c:6902:face:0:2a2:0" . to_string( ) , 1234 )
3823
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Host {
3824
+ hostname: "2401:db00:33c:6902:face:0:2a2:0" . to_string( ) ,
3825
+ port: 1234
3826
+ } )
3827
+ ) ;
3828
+
3829
+ let channel: ChannelAddr = "metatls![::]:1234" . parse ( ) . unwrap ( ) ;
3830
+ assert_eq ! (
3831
+ channel,
3832
+ ChannelAddr :: MetaTls ( MetaTlsAddr :: Socket ( "[::]:1234" . parse( ) . unwrap( ) ) )
3750
3833
) ;
3751
3834
}
3752
3835
0 commit comments