summary refs log tree commit diff
path: root/devices/src/proxy.rs
diff options
context:
space:
mode:
authorJingkui Wang <jkwang@google.com>2018-11-01 16:53:47 +0000
committerJingkui Wang <jkwang@google.com>2018-11-02 16:59:10 +0000
commit9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3 (patch)
tree9deab1b9ad8fc4724e5e68df672e4f9a2aad9dd6 /devices/src/proxy.rs
parent142ce3efd9c6a20efb4685fa632ad522509441f2 (diff)
downloadcrosvm-9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.tar
crosvm-9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.tar.gz
crosvm-9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.tar.bz2
crosvm-9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.tar.lz
crosvm-9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.tar.xz
crosvm-9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.tar.zst
crosvm-9d5e8f34ade78222a8a4ab0a6fb259e2c2d1faa3.zip
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>
Diffstat (limited to 'devices/src/proxy.rs')
-rw-r--r--devices/src/proxy.rs229
1 files changed, 122 insertions, 107 deletions
diff --git a/devices/src/proxy.rs b/devices/src/proxy.rs
index 86fcd33..5b79d31 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 msg_socket::{MsgError, MsgOnSocket, MsgReceiver, MsgResult, MsgSender, MsgSocket};
+use byteorder::{ByteOrder, LittleEndian, NativeEndian};
 
 use io_jail::{self, Minijail};
 use BusDevice;
@@ -35,80 +35,74 @@ impl fmt::Display for Error {
 }
 
 const SOCKET_TIMEOUT_MS: u64 = 2000;
+const MSG_SIZE: usize = 24;
 
-#[derive(MsgOnSocket)]
 enum Command {
-    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),
+    Read = 0,
+    Write = 1,
+    ReadConfig = 2,
+    WriteConfig = 3,
+    Shutdown = 4,
 }
 
 fn child_proc(sock: UnixDatagram, device: &mut BusDevice) {
     let mut running = true;
-    let sock = MsgSocket::<CommandResult, Command>::new(sock);
 
     while running {
-        let cmd = match sock.recv() {
-            Ok(cmd) => cmd,
-            Err(err) => {
-                error!("child device process failed recv: {:?}", err);
+        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;
             }
-        };
-
-        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)
+            Err(e) => {
+                error!("child device process failed recv: {}", e);
+                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;
         };
+
         if let Err(e) = res {
-            error!("child device process failed send: {:?}", e);
+            error!("error: child device process failed send: {}", e);
+            break;
         }
     }
 }
@@ -118,7 +112,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: MsgSocket<Command, CommandResult>,
+    sock: UnixDatagram,
     pid: pid_t,
 }
 
@@ -158,7 +152,7 @@ impl ProxyDevice {
             .set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
             .map_err(Error::Io)?;
         Ok(ProxyDevice {
-            sock: MsgSocket::<Command, CommandResult>::new(parent_sock),
+            sock: parent_sock,
             pid,
         })
     }
@@ -167,69 +161,90 @@ impl ProxyDevice {
         self.pid
     }
 
-    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),
-        }
+    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)
     }
 }
 
 impl BusDevice for ProxyDevice {
     fn config_register_write(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
-        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,
-        });
+        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);
+        }
     }
 
     fn config_register_read(&self, reg_idx: usize) -> u32 {
-        let res = self.sync_send(Command::ReadConfig(reg_idx as u32));
-        if let Some(CommandResult::ReadConfigResult(val)) = res {
-            val
-        } else {
-            0
+        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);
         }
+        LittleEndian::read_u32(&data)
     }
 
     fn read(&mut self, offset: u64, data: &mut [u8]) {
-        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]);
+        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);
         }
     }
 
     fn write(&mut self, offset: u64, data: &[u8]) {
-        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,
-        });
+        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);
+        }
     }
 }
 
 impl Drop for ProxyDevice {
     fn drop(&mut self) {
-        self.sync_send(Command::Shutdown);
+        let res = self.send_cmd(Command::Shutdown, 0, 0, &[]);
+        if let Err(e) = res {
+            error!("failed to shutdown child device process: {}", e);
+        }
     }
 }