@@ -101,8 +101,40 @@ fn make_addr(_domain: Domain, sockaddr: &str) -> Result<UnixAddr> {
101
101
UnixAddr :: new ( sockaddr) . map_err ( err_to_others_err ! ( e, "" ) )
102
102
}
103
103
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 > ) > {
106
138
let ( domain, sockaddrv) = parse_sockaddr ( sockaddr) ?;
107
139
108
140
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
121
153
Domain :: Unix => get_sock_addr ( domain, sockaddrv) ?,
122
154
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
123
155
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) ?;
133
157
let fd = socket (
134
158
AddressFamily :: Vsock ,
135
159
SockType :: Stream ,
136
160
SockFlag :: SOCK_CLOEXEC ,
137
161
None ,
138
162
)
139
163
. map_err ( |e| Error :: Socket ( e. to_string ( ) ) ) ?;
140
- let cid = addr. 1 ;
141
164
let sockaddr = VsockAddr :: new ( cid, port) ;
142
165
( fd, Box :: new ( sockaddr) )
143
166
}
@@ -146,18 +169,8 @@ fn make_socket(addr: (&str, u32)) -> Result<(RawFd, Domain, Box<dyn SockaddrLike
146
169
Ok ( ( fd, domain, sockaddr) )
147
170
}
148
171
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
-
159
172
pub ( 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) ?;
161
174
162
175
setsockopt ( fd, sockopt:: ReusePort , & true ) ?;
163
176
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)> {
167
180
168
181
/// Creates a unix socket for client.
169
182
pub ( 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) ?;
171
184
172
185
connect ( fd, sockaddr. as_ref ( ) ) ?;
173
186
@@ -236,4 +249,20 @@ mod tests {
236
249
}
237
250
}
238
251
}
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
+ }
239
268
}
0 commit comments