Skip to content

Commit d12719a

Browse files
quanweiZhouquanwei.zqw
authored andcommitted
vsock: parse cid from vsock
Parse vsock cid and port from address("vsock://cid:port"). Fixes: #266 Signed-off-by: Quanwei Zhou <quanweiZhou@linux.alibaba.com>
1 parent d2a0ce1 commit d12719a

File tree

1 file changed

+53
-24
lines changed

1 file changed

+53
-24
lines changed

src/common.rs

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
159172
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)?;
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.
169182
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)?;
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

Comments
 (0)