@@ -101,8 +101,40 @@ fn make_addr(_domain: Domain, sockaddr: &str) -> Result<UnixAddr> {
101101 UnixAddr :: new ( sockaddr) . map_err ( err_to_others_err ! ( e, "" ) )
102102}
103103
104- fn make_socket ( addr : ( & str , u32 ) ) -> Result < ( RawFd , Domain , Box < dyn SockaddrLike > ) > {
105- let ( sockaddr, _) = addr;
104+ // addr: cid:port
105+ // return (cid, port)
106+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
107+ fn parse_vscok ( addr : & str ) -> Result < ( u32 , u32 ) > {
108+ // vsock://cid:port
109+ let sockaddr_port_v: Vec < & str > = addr. split ( ':' ) . collect ( ) ;
110+ if sockaddr_port_v. len ( ) != 2 {
111+ return Err ( Error :: Others ( format ! (
112+ "sockaddr {addr} is not right for vsock"
113+ ) ) ) ;
114+ }
115+
116+ // for -1 need trace to libc::VMADDR_CID_ANY
117+ let cid: u32 = if sockaddr_port_v[ 0 ] . trim ( ) . eq ( "-1" ) {
118+ libc:: VMADDR_CID_ANY
119+ } else {
120+ sockaddr_port_v[ 0 ] . parse ( ) . map_err ( |e| {
121+ Error :: Others ( format ! (
122+ "failed to parse cid from {:?} error: {:?}" ,
123+ sockaddr_port_v[ 0 ] , e
124+ ) )
125+ } ) ?
126+ } ;
127+
128+ let port: u32 = sockaddr_port_v[ 1 ] . parse ( ) . map_err ( |e| {
129+ Error :: Others ( format ! (
130+ "failed to parse port from {:?} error: {:?}" ,
131+ sockaddr_port_v[ 1 ] , e
132+ ) )
133+ } ) ?;
134+ Ok ( ( cid, port) )
135+ }
136+
137+ fn make_socket ( sockaddr : & str ) -> Result < ( RawFd , Domain , Box < dyn SockaddrLike > ) > {
106138 let ( domain, sockaddrv) = parse_sockaddr ( sockaddr) ?;
107139
108140 let get_sock_addr = |domain, sockaddr| -> Result < ( RawFd , Box < dyn SockaddrLike > ) > {
@@ -121,23 +153,14 @@ fn make_socket(addr: (&str, u32)) -> Result<(RawFd, Domain, Box<dyn SockaddrLike
121153 Domain :: Unix => get_sock_addr ( domain, sockaddrv) ?,
122154 #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
123155 Domain :: Vsock => {
124- let sockaddr_port_v: Vec < & str > = sockaddrv. split ( ':' ) . collect ( ) ;
125- if sockaddr_port_v. len ( ) != 2 {
126- return Err ( Error :: Others ( format ! (
127- "sockaddr {sockaddr} is not right for vsock"
128- ) ) ) ;
129- }
130- let port: u32 = sockaddr_port_v[ 1 ]
131- . parse ( )
132- . expect ( "the vsock port is not an number" ) ;
156+ let ( cid, port) = parse_vscok ( sockaddrv) ?;
133157 let fd = socket (
134158 AddressFamily :: Vsock ,
135159 SockType :: Stream ,
136160 SockFlag :: SOCK_CLOEXEC ,
137161 None ,
138162 )
139163 . map_err ( |e| Error :: Socket ( e. to_string ( ) ) ) ?;
140- let cid = addr. 1 ;
141164 let sockaddr = VsockAddr :: new ( cid, port) ;
142165 ( fd, Box :: new ( sockaddr) )
143166 }
@@ -146,18 +169,8 @@ fn make_socket(addr: (&str, u32)) -> Result<(RawFd, Domain, Box<dyn SockaddrLike
146169 Ok ( ( fd, domain, sockaddr) )
147170}
148171
149- // Vsock is not supported on non Linux.
150- #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
151- use libc:: VMADDR_CID_ANY ;
152- #[ cfg( not( any( target_os = "linux" , target_os = "android" ) ) ) ]
153- const VMADDR_CID_ANY : u32 = 0 ;
154- #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
155- use libc:: VMADDR_CID_HOST ;
156- #[ cfg( not( any( target_os = "linux" , target_os = "android" ) ) ) ]
157- const VMADDR_CID_HOST : u32 = 0 ;
158-
159172pub ( crate ) fn do_bind ( sockaddr : & str ) -> Result < ( RawFd , Domain ) > {
160- let ( fd, domain, sockaddr) = make_socket ( ( sockaddr, VMADDR_CID_ANY ) ) ?;
173+ let ( fd, domain, sockaddr) = make_socket ( sockaddr) ?;
161174
162175 setsockopt ( fd, sockopt:: ReusePort , & true ) ?;
163176 bind ( fd, sockaddr. as_ref ( ) ) . map_err ( err_to_others_err ! ( e, "" ) ) ?;
@@ -167,7 +180,7 @@ pub(crate) fn do_bind(sockaddr: &str) -> Result<(RawFd, Domain)> {
167180
168181/// Creates a unix socket for client.
169182pub ( crate ) unsafe fn client_connect ( sockaddr : & str ) -> Result < RawFd > {
170- let ( fd, _, sockaddr) = make_socket ( ( sockaddr, VMADDR_CID_HOST ) ) ?;
183+ let ( fd, _, sockaddr) = make_socket ( sockaddr) ?;
171184
172185 connect ( fd, sockaddr. as_ref ( ) ) ?;
173186
@@ -236,4 +249,20 @@ mod tests {
236249 }
237250 }
238251 }
252+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
253+ #[ test]
254+ fn test_parse_vscok ( ) {
255+ for i in & [
256+ ( "-1:1024" , ( libc:: VMADDR_CID_ANY , 1024 ) ) ,
257+ ( "0:1" , ( 0 , 1 ) ) ,
258+ ( "1:2" , ( 1 , 2 ) ) ,
259+ ( "4294967294:3" , ( 4294967294 , 3 ) ) ,
260+ // 4294967295 = 0xFFFFFFFF
261+ ( "4294967295:4" , ( libc:: VMADDR_CID_ANY , 4 ) ) ,
262+ ] {
263+ let ( input, ( cid, port) ) = ( i. 0 , i. 1 ) ;
264+ let r = parse_vscok ( input) ;
265+ assert_eq ! ( r. unwrap( ) , ( cid, port) , "parse {:?} failed" , i) ;
266+ }
267+ }
239268}
0 commit comments