summary refs log tree commit diff
path: root/devices/src/proxy.rs
diff options
context:
space:
mode:
authorJingkui Wang <jkwang@google.com>2018-11-02 17:00:31 +0000
committerchrome-bot <chrome-bot@chromium.org>2018-11-19 07:09:20 -0800
commitb23c091c8bfd37cab8be15c0912d684187969c63 (patch)
treed3d93db5e5001649be4df69528e4ce7751c7145f /devices/src/proxy.rs
parentac2e50a6ced9f6cf7885a6d8a9ce3edde8a755d6 (diff)
downloadcrosvm-b23c091c8bfd37cab8be15c0912d684187969c63.tar
crosvm-b23c091c8bfd37cab8be15c0912d684187969c63.tar.gz
crosvm-b23c091c8bfd37cab8be15c0912d684187969c63.tar.bz2
crosvm-b23c091c8bfd37cab8be15c0912d684187969c63.tar.lz
crosvm-b23c091c8bfd37cab8be15c0912d684187969c63.tar.xz
crosvm-b23c091c8bfd37cab8be15c0912d684187969c63.tar.zst
crosvm-b23c091c8bfd37cab8be15c0912d684187969c63.zip
Reland "devices: refactor proxy to use msg_socket"
This reverts commit 9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.

Reason for revert: msg_socket was fixed to not call sendmsg/recvmsg

BUG=None
TEST=local build

Original change's description:
> Revert "devices: refactor proxy to use msg_socket"
>
> This reverts commit 142ce3efd9c6a20efb4685fa632ad522509441f2.
>
> Reason for revert: <INSERT REASONING HERE>
>
> Original change's description:
> > devices: refactor proxy to use msg_socket
> >
> > Use msg socket in proxy.
> >
> > BUG=None
> > TEST=None
> >
> > Change-Id: Ia5ebc4410918a261fe525abc1051ebbbdc66a876
> > Reviewed-on: https://chromium-review.googlesource.com/1260259
> > Commit-Ready: Jingkui Wang <jkwang@google.com>
> > Tested-by: Jingkui Wang <jkwang@google.com>
> > Reviewed-by: Zach Reizner <zachr@chromium.org>
>
> Bug: None
> Change-Id: Ic7827969e9ad508cd1b65cb7b8747e81e0cd02d0
> Reviewed-on: https://chromium-review.googlesource.com/c/1313014
> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
> Commit-Queue: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
> Tested-by: Jingkui Wang <jkwang@google.com>

Bug: None
Change-Id: I27822d7572cab028ec6ed1f0f686fface0858a9a
Reviewed-on: https://chromium-review.googlesource.com/1315511
Commit-Ready: Jingkui Wang <jkwang@google.com>
Tested-by: Jingkui Wang <jkwang@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'devices/src/proxy.rs')
-rw-r--r--devices/src/proxy.rs229
1 files changed, 107 insertions, 122 deletions
diff --git a/devices/src/proxy.rs b/devices/src/proxy.rs
index 5b79d31..c7c28bb 100644
--- a/devices/src/proxy.rs
+++ b/devices/src/proxy.rs
@@ -12,7 +12,7 @@ use std::process;
 use std::time::Duration;
 use std::{self, fmt, io};
 
-use byteorder::{ByteOrder, LittleEndian, NativeEndian};
+use msg_socket::{MsgOnSocket, MsgReceiver, MsgSender, MsgSocket};
 
 use io_jail::{self, Minijail};
 use BusDevice;
@@ -35,74 +35,80 @@ impl fmt::Display for Error {
 }
 
 const SOCKET_TIMEOUT_MS: u64 = 2000;
-const MSG_SIZE: usize = 24;
 
+#[derive(MsgOnSocket)]
 enum Command {
-    Read = 0,
-    Write = 1,
-    ReadConfig = 2,
-    WriteConfig = 3,
-    Shutdown = 4,
+    Read {
+        len: u32,
+        offset: u64,
+    },
+    Write {
+        len: u32,
+        offset: u64,
+        data: [u8; 8],
+    },
+    ReadConfig(u32),
+    WriteConfig {
+        reg_idx: u32,
+        offset: u32,
+        len: u32,
+        data: [u8; 4],
+    },
+    Shutdown,
+}
+
+#[derive(MsgOnSocket)]
+enum CommandResult {
+    Ok,
+    ReadResult([u8; 8]),
+    ReadConfigResult(u32),
 }
 
 fn child_proc(sock: UnixDatagram, device: &mut BusDevice) {
     let mut running = true;
+    let sock = MsgSocket::<CommandResult, Command>::new(sock);
 
     while running {
-        let mut buf = [0; MSG_SIZE];
-        match handle_eintr!(sock.recv(&mut buf)) {
-            Ok(c) if c != buf.len() => {
-                error!(
-                    "child device process incorrect recv size: got {}, expected {}",
-                    c,
-                    buf.len()
-                );
-                break;
-            }
-            Err(e) => {
-                error!("child device process failed recv: {}", e);
+        let cmd = match sock.recv() {
+            Ok(cmd) => cmd,
+            Err(err) => {
+                error!("child device process failed recv: {:?}", err);
                 break;
             }
-            _ => {}
-        }
-
-        let cmd = NativeEndian::read_u32(&buf[0..]);
-
-        let res = if cmd == Command::Read as u32 {
-            let len = NativeEndian::read_u32(&buf[4..]) as usize;
-            let offset = NativeEndian::read_u64(&buf[8..]);
-            device.read(offset, &mut buf[16..16 + len]);
-            handle_eintr!(sock.send(&buf))
-        } else if cmd == Command::Write as u32 {
-            let len = NativeEndian::read_u32(&buf[4..]) as usize;
-            let offset = NativeEndian::read_u64(&buf[8..]);
-            device.write(offset, &buf[16..16 + len]);
-            handle_eintr!(sock.send(&buf))
-        } else if cmd == Command::ReadConfig as u32 {
-            let reg_idx = NativeEndian::read_u32(&buf[4..]) as usize;
-            let val = device.config_register_read(reg_idx);
-            buf[16] = val as u8;
-            buf[17] = (val >> 8) as u8;
-            buf[18] = (val >> 16) as u8;
-            buf[19] = (val >> 24) as u8;
-            handle_eintr!(sock.send(&buf))
-        } else if cmd == Command::WriteConfig as u32 {
-            let reg_idx = NativeEndian::read_u32(&buf[4..]) as usize;
-            let offset = u64::from(NativeEndian::read_u32(&buf[8..]));
-            let len = u64::from(NativeEndian::read_u32(&buf[16..]));
-            device.config_register_write(reg_idx, offset, &buf[20..(20 + len as usize)]);
-            handle_eintr!(sock.send(&buf))
-        } else if cmd == Command::Shutdown as u32 {
-            running = false;
-            handle_eintr!(sock.send(&buf))
-        } else {
-            error!("child device process unknown command: {}", cmd);
-            break;
         };
 
+        let res = match cmd {
+            Command::Read { len, offset } => {
+                let mut buffer = [0u8; 8];
+                device.read(offset, &mut buffer[0..len as usize]);
+                sock.send(&CommandResult::ReadResult(buffer))
+            }
+            Command::Write { len, offset, data } => {
+                let len = len as usize;
+                device.write(offset, &data[0..len]);
+                sock.send(&CommandResult::Ok)
+            }
+            Command::ReadConfig(idx) => {
+                let val = device.config_register_read(idx as usize);
+                sock.send(&CommandResult::ReadConfigResult(val))
+            }
+            Command::WriteConfig {
+                reg_idx,
+                offset,
+                len,
+                data,
+            } => {
+                let len = len as usize;
+                device.config_register_write(reg_idx as usize, offset as u64, &data[0..len]);
+                sock.send(&CommandResult::Ok)
+            }
+            Command::Shutdown => {
+                running = false;
+                sock.send(&CommandResult::Ok)
+            }
+        };
         if let Err(e) = res {
-            error!("error: child device process failed send: {}", e);
-            break;
+            error!("child device process failed send: {:?}", e);
         }
     }
 }
@@ -112,7 +118,7 @@ fn child_proc(sock: UnixDatagram, device: &mut BusDevice) {
 /// Because forks are very unfriendly to destructors and all memory mappings and file descriptors
 /// are inherited, this should be used as early as possible in the main process.
 pub struct ProxyDevice {
-    sock: UnixDatagram,
+    sock: MsgSocket<Command, CommandResult>,
     pid: pid_t,
 }
 
@@ -152,7 +158,7 @@ impl ProxyDevice {
             .set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
             .map_err(Error::Io)?;
         Ok(ProxyDevice {
-            sock: parent_sock,
+            sock: MsgSocket::<Command, CommandResult>::new(parent_sock),
             pid,
         })
     }
@@ -161,90 +167,69 @@ impl ProxyDevice {
         self.pid
     }
 
-    fn send_cmd(&self, cmd: Command, offset: u64, len: u32, data: &[u8]) -> Result<()> {
-        let mut buf = [0; MSG_SIZE];
-        NativeEndian::write_u32(&mut buf[0..], cmd as u32);
-        NativeEndian::write_u32(&mut buf[4..], len);
-        NativeEndian::write_u64(&mut buf[8..], offset);
-        buf[16..16 + data.len()].clone_from_slice(data);
-        handle_eintr!(self.sock.send(&buf))
-            .map(|_| ())
-            .map_err(Error::Io)
-    }
-
-    fn send_config_cmd(&self, cmd: Command, reg_idx: u32, offset: u64, data: &[u8]) -> Result<()> {
-        let mut buf = [0; MSG_SIZE];
-        NativeEndian::write_u32(&mut buf[0..], cmd as u32);
-        NativeEndian::write_u32(&mut buf[4..], reg_idx);
-        NativeEndian::write_u64(&mut buf[8..], offset);
-        NativeEndian::write_u32(&mut buf[16..], data.len() as u32);
-        buf[20..20 + data.len()].clone_from_slice(data);
-        handle_eintr!(self.sock.send(&buf))
-            .map(|_| ())
-            .map_err(Error::Io)
-    }
-
-    fn recv_resp(&self, data: &mut [u8]) -> Result<()> {
-        let mut buf = [0; MSG_SIZE];
-        handle_eintr!(self.sock.recv(&mut buf)).map_err(Error::Io)?;
-        let len = data.len();
-        data.clone_from_slice(&buf[16..16 + len]);
-        Ok(())
-    }
-
-    fn wait(&self) -> Result<()> {
-        let mut buf = [0; MSG_SIZE];
-        handle_eintr!(self.sock.recv(&mut buf))
-            .map(|_| ())
-            .map_err(Error::Io)
+    fn sync_send(&self, cmd: Command) -> Option<CommandResult> {
+        let res = self.sock.send(&cmd);
+        if let Err(e) = res {
+            error!("failed write to child device process: {:?}", e);
+        };
+        match self.sock.recv() {
+            Err(e) => {
+                error!("failed read from child device process: {:?}", e);
+                None
+            }
+            Ok(r) => Some(r),
+        }
     }
 }
 
 impl BusDevice for ProxyDevice {
     fn config_register_write(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
-        let res = self
-            .send_config_cmd(Command::WriteConfig, reg_idx as u32, offset, data)
-            .and_then(|_| self.wait());
-        if let Err(e) = res {
-            error!("failed write to child device process: {}", e);
-        }
+        let len = data.len() as u32;
+        let mut buffer = [0u8; 4];
+        buffer[0..data.len()].clone_from_slice(data);
+        let reg_idx = reg_idx as u32;
+        let offset = offset as u32;
+        self.sync_send(Command::WriteConfig {
+            reg_idx,
+            offset,
+            len,
+            data: buffer,
+        });
     }
 
     fn config_register_read(&self, reg_idx: usize) -> u32 {
-        let mut data = [0u8; 4];
-        let res = self
-            .send_config_cmd(Command::ReadConfig, reg_idx as u32, 0, &[])
-            .and_then(|_| self.recv_resp(&mut data));
-        if let Err(e) = res {
-            error!("failed write to child device process: {}", e);
+        let res = self.sync_send(Command::ReadConfig(reg_idx as u32));
+        if let Some(CommandResult::ReadConfigResult(val)) = res {
+            val
+        } else {
+            0
         }
-        LittleEndian::read_u32(&data)
     }
 
     fn read(&mut self, offset: u64, data: &mut [u8]) {
-        let res = self
-            .send_cmd(Command::Read, offset, data.len() as u32, &[])
-            .and_then(|_| self.recv_resp(data));
-        if let Err(e) = res {
-            error!("failed read from child device process: {}", e);
+        let len = data.len() as u32;
+        if let Some(CommandResult::ReadResult(buffer)) =
+            self.sync_send(Command::Read { len, offset })
+        {
+            let len = data.len();
+            data.clone_from_slice(&buffer[0..len]);
         }
     }
 
     fn write(&mut self, offset: u64, data: &[u8]) {
-        let res = self
-            .send_cmd(Command::Write, offset, data.len() as u32, data)
-            .and_then(|_| self.wait());
-        if let Err(e) = res {
-            error!("failed write to child device process: {}", e);
-        }
+        let mut buffer = [0u8; 8];
+        let len = data.len() as u32;
+        buffer[0..data.len()].clone_from_slice(data);
+        self.sync_send(Command::Write {
+            len,
+            offset,
+            data: buffer,
+        });
     }
 }
 
 impl Drop for ProxyDevice {
     fn drop(&mut self) {
-        let res = self.send_cmd(Command::Shutdown, 0, 0, &[]);
-        if let Err(e) = res {
-            error!("failed to shutdown child device process: {}", e);
-        }
+        self.sync_send(Command::Shutdown);
     }
 }