1
1
//! Reproduces the functionality of "adstool" from the Beckhoff ADS C++ library.
2
2
3
3
use std:: convert:: TryInto ;
4
- use std:: io:: { self , stdin, stdout, Read , Write } ;
4
+ use std:: io:: { stdin, stdout, Read , Write } ;
5
+ use std:: net:: { IpAddr , Ipv4Addr , TcpStream } ;
5
6
use std:: str:: FromStr ;
6
7
use std:: time:: Duration ;
7
8
@@ -61,8 +62,8 @@ impl Cli {
61
62
( username, password)
62
63
}
63
64
64
- pub fn timeout ( & self ) -> ads:: Timeouts {
65
- ads:: Timeouts { connect : Some ( Duration :: from_secs ( self . timeout ) ) , ..Default :: default ( ) }
65
+ pub const fn timeout ( & self ) -> ads:: Timeouts {
66
+ ads:: Timeouts { connect : Some ( Duration :: from_secs ( self . timeout ) ) , ..ads :: Timeouts :: none ( ) }
66
67
}
67
68
}
68
69
@@ -103,7 +104,7 @@ struct CredentialArgs {
103
104
104
105
/// password for logging into the system (defaults to `1`)
105
106
#[ clap( long) ]
106
- password : Option < String >
107
+ password : Option < String > ,
107
108
}
108
109
109
110
#[ derive( Parser , Debug ) ]
@@ -376,6 +377,40 @@ fn connect(port: ads::AmsPort, args: &Cli) -> ads::Result<(ads::Client, ads::Ams
376
377
let amsaddr = ads:: AmsAddr :: new ( target_netid, amsport) ;
377
378
let source = if matches ! ( target. host. as_str( ) , "127.0.0.1" | "localhost" ) {
378
379
ads:: Source :: Request
380
+ } else if args. autoroute {
381
+ // temp. connection to remote to get the corrent IP addr of the interface in use
382
+ let sock = TcpStream :: connect ( tcp_addr)
383
+ . map_err ( |e| ads:: Error :: Io ( "attempting to resolve local IP address" , e) ) ?;
384
+
385
+ let local_ip = sock. local_addr ( )
386
+ . map ( |addr| addr. ip ( ) )
387
+ . map_err ( |e| ads:: Error :: Io ( "attempting to resolve local IP address" , e) ) ?;
388
+
389
+ // if not using IPv4 address or IPv6 address with IPv4 mapping,
390
+ // create an arbitrary AMS NetID
391
+ let local_net_id = {
392
+ let [ a, b, c, d] = match local_ip {
393
+ IpAddr :: V4 ( ip) => ip. octets ( ) ,
394
+ IpAddr :: V6 ( ip) => ip. to_ipv4 ( ) . unwrap_or ( Ipv4Addr :: new ( 1 , 2 , 3 , 4 ) ) . octets ( )
395
+ } ;
396
+
397
+ ads:: AmsNetId :: new ( a, b, c, d, 1 , 1 )
398
+ } ;
399
+
400
+ let ( username, password) = args. credentials ( ) ;
401
+
402
+ // add the route using the collected IP information and derived AMS NetID
403
+ ads:: udp:: add_route (
404
+ ( target. host . as_str ( ) , ads:: UDP_PORT ) ,
405
+ local_net_id,
406
+ & local_ip. to_string ( ) ,
407
+ None ,
408
+ username,
409
+ password,
410
+ true ,
411
+ ) ?;
412
+
413
+ ads:: Source :: Addr ( ads:: AmsAddr :: new ( local_net_id, 58913 ) )
379
414
} else {
380
415
ads:: Source :: Any
381
416
} ;
@@ -384,34 +419,6 @@ fn connect(port: ads::AmsPort, args: &Cli) -> ads::Result<(ads::Client, ads::Ams
384
419
// (probably because of a bad route)
385
420
let client = ads:: Client :: new ( tcp_addr, args. timeout ( ) , source) ?;
386
421
387
- if args. autoroute {
388
- let ( username, password) = args. credentials ( ) ;
389
-
390
- match client. device ( amsaddr) . get_info ( ) {
391
- Err ( e) => {
392
- println ! ( "Error connecting to client: (error: '{e}')" ) ;
393
- println ! ( "Attempting to autoroute" ) ;
394
-
395
- let [ a, b, c, d, ..] = client. source ( ) . netid ( ) . 0 ;
396
- let ip = format ! ( "{a}.{b}.{c}.{d}" ) ;
397
-
398
- ads:: udp:: add_route (
399
- ( target. host . as_str ( ) , ads:: UDP_PORT ) ,
400
- client. source ( ) . netid ( ) ,
401
- & ip,
402
- None ,
403
- username,
404
- password,
405
- true ,
406
- ) ?;
407
-
408
- return connect ( port, args) ;
409
- }
410
-
411
- _ => ( )
412
- }
413
- }
414
-
415
422
Ok ( ( client, amsaddr) )
416
423
}
417
424
@@ -539,8 +546,7 @@ fn main_inner(args: Cli) -> Result<(), Error> {
539
546
}
540
547
541
548
FileAction :: Read { path } => {
542
- let mut file =
543
- file:: File :: open ( dev, path, file:: READ | file:: BINARY | file:: ENSURE_DIR ) ?;
549
+ let mut file = file:: File :: open ( dev, path, file:: READ | file:: BINARY | file:: ENSURE_DIR ) ?;
544
550
std:: io:: copy ( & mut file, & mut stdout ( ) ) ?;
545
551
}
546
552
@@ -657,7 +663,8 @@ fn main_inner(args: Cli) -> Result<(), Error> {
657
663
658
664
if let Some ( length) = length {
659
665
let mut read_data = vec ! [ 0 ; * length] ;
660
- let nread = dev. write_read ( * index_group, * index_offset, & write_data, & mut read_data) ?;
666
+ let nread =
667
+ dev. write_read ( * index_group, * index_offset, & write_data, & mut read_data) ?;
661
668
if * hex {
662
669
hexdump ( & read_data[ ..nread] ) ;
663
670
} else {
0 commit comments