mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
Assign a different tcp port to each qemu isle
This commit is contained in:
parent
cb20bd1f5c
commit
966199b8c5
8 changed files with 65 additions and 41 deletions
|
@ -89,6 +89,7 @@ impl Connection {
|
|||
|
||||
loop {
|
||||
match self.socket.read(&mut tmp) {
|
||||
Ok(0) => break,
|
||||
Ok(nread) => buf.extend_from_slice(&tmp[0..nread]),
|
||||
Err(err) => {
|
||||
if buf.len() > 0 {
|
||||
|
@ -141,7 +142,7 @@ pub enum ActionResult {
|
|||
CreateIsle(Result<u32>),
|
||||
StopIsle(Result<i32>),
|
||||
RemoveIsle(Result<i32>),
|
||||
Connect,
|
||||
Connect(Result<()>),
|
||||
Log(Vec<Log>),
|
||||
IsleLog(Result<String>),
|
||||
List(Vec<(Result<bool>, IsleParameter)>),
|
||||
|
@ -251,6 +252,9 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn exit_daemon_handler() {
|
||||
}
|
||||
|
||||
pub fn daemon_handler() {
|
||||
let mut state = State::new();
|
||||
let mut buf = vec![0; 256];
|
||||
|
@ -261,8 +265,6 @@ pub fn daemon_handler() {
|
|||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(mut stream) => {
|
||||
//let mut stream = Arc::new(Mutex::new(stream));
|
||||
|
||||
loop {
|
||||
let nread = stream.read(&mut buf);
|
||||
|
||||
|
@ -275,6 +277,11 @@ pub fn daemon_handler() {
|
|||
let ret = match action {
|
||||
Action::KillDaemon => {
|
||||
fs::remove_file("/tmp/hermit_daemon").unwrap();
|
||||
|
||||
let buf: Vec<u8> = serialize(&ActionResult::KillDaemon(Ok(())), Infinite).unwrap();
|
||||
stream.write(&buf);
|
||||
|
||||
process::exit(0);
|
||||
break;
|
||||
},
|
||||
Action::CreateIsle(path, specs) => {
|
||||
|
@ -289,7 +296,7 @@ pub fn daemon_handler() {
|
|||
},
|
||||
Action::List => ActionResult::List(state.list()),
|
||||
Action::Connect(id) => {
|
||||
let buf: Vec<u8> = serialize(&ActionResult::Connect, Infinite).unwrap();
|
||||
let buf: Vec<u8> = serialize(&ActionResult::Connect(state.exist_isle(id)), Infinite).unwrap();
|
||||
stream.write(&buf);
|
||||
|
||||
state.add_endpoint(id, stream);
|
||||
|
|
|
@ -51,7 +51,7 @@ impl Multi {
|
|||
return Err(Error::MultiIsleFailed);
|
||||
}
|
||||
|
||||
Ok(Multi { num: num, socket: Some(Socket::new()) })
|
||||
Ok(Multi { num: num, socket: Some(Socket::new(18766)) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,10 @@ pub enum Packet {
|
|||
|
||||
impl Packet {
|
||||
pub fn from_buf(obj: &PartialPacket, buf: &mut Cursor<Vec<u8>>) -> Packet {
|
||||
|
||||
//println!("{:?}", *obj);
|
||||
|
||||
|
||||
match *obj {
|
||||
PartialPacket::Write { fd, len } => {
|
||||
debug!("Read write packet with length {}", len);
|
||||
|
|
|
@ -19,6 +19,26 @@ use hermit::socket::{Socket, Console};
|
|||
const PIDNAME: &'static str = "/tmp/hpid-XXXXXX";
|
||||
const TMPNAME: &'static str = "/tmp/hermit-XXXXXX";
|
||||
|
||||
const BASE_PORT: u16 = 18766;
|
||||
static mut FREE_PORT: u64 = 0u64;
|
||||
|
||||
// there are 64 ports free
|
||||
fn get_free_port() -> Result<u16> {
|
||||
// assume single threading
|
||||
unsafe {
|
||||
if FREE_PORT == u64::max_value() {
|
||||
return Err(Error::InternalError);
|
||||
}
|
||||
|
||||
// find first bit set to zero
|
||||
let pos = (!FREE_PORT).trailing_zeros();
|
||||
|
||||
FREE_PORT |= (1 << pos);
|
||||
|
||||
Ok(BASE_PORT + pos as u16)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QEmu {
|
||||
socket: Option<Socket>,
|
||||
|
@ -34,12 +54,15 @@ impl QEmu {
|
|||
pub fn new(path: &str, mem_size: u64, num_cpus: u32, additional: IsleParameterQEmu) -> Result<QEmu> {
|
||||
let tmpf = utils::create_tmp_file(TMPNAME)?;
|
||||
let pidf = utils::create_tmp_file(PIDNAME)?;
|
||||
// get a new port number
|
||||
let port = get_free_port()?;
|
||||
|
||||
let mut child = QEmu::start_with(path, mem_size, num_cpus, additional, &tmpf, &pidf)?.spawn().expect("Couldn't find qemu binary!");
|
||||
debug!("new port number: {}", port);
|
||||
|
||||
let mut child = QEmu::start_with(path, port, mem_size, num_cpus, additional, &tmpf, &pidf)?.spawn().expect("Couldn't find qemu binary!");
|
||||
let stdout = child.stdout.take().unwrap();
|
||||
let stderr = child.stderr.take().unwrap();
|
||||
println!("{}", pidf);
|
||||
let socket = Socket::new();
|
||||
let socket = Socket::new(port);
|
||||
let console = socket.console();
|
||||
|
||||
Ok(QEmu {
|
||||
|
@ -53,8 +76,8 @@ impl QEmu {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn start_with(path: &str, mem_size: u64, num_cpus: u32, add: IsleParameterQEmu, tmp_file: &str, pid_file: &str) -> Result<Command> {
|
||||
let hostfwd = format!("user,hostfwd=tcp:127.0.0.1:{}-:{}", add.port, add.port);
|
||||
pub fn start_with(path: &str, port: u16, mem_size: u64, num_cpus: u32, add: IsleParameterQEmu, tmp_file: &str, pid_file: &str) -> Result<Command> {
|
||||
let hostfwd = format!("user,hostfwd=tcp:127.0.0.1:{}-:{}", port, 18766);
|
||||
let monitor_str = format!("unix:{}_monitor,server,nowait", pid_file);
|
||||
let chardev = format!("file,id=gnc0,path={}",&tmp_file);
|
||||
let freq = format!("\"-freq{} -proxy\"",(utils::cpufreq().unwrap()/1000).to_string());
|
||||
|
|
|
@ -26,17 +26,18 @@ pub type Console = Arc<Mutex<Vec<UnixStream>>>;
|
|||
#[derive(Debug)]
|
||||
pub struct Socket {
|
||||
stream: Option<TcpStream>,
|
||||
port: u16,
|
||||
console: Console
|
||||
}
|
||||
|
||||
impl Socket {
|
||||
pub fn new() -> Socket {
|
||||
Socket { stream: None, console: Arc::new(Mutex::new(Vec::new())) }
|
||||
pub fn new(port: u16) -> Socket {
|
||||
Socket { stream: None, port: port, console: Arc::new(Mutex::new(Vec::new())) }
|
||||
}
|
||||
|
||||
pub fn connect(&mut self) -> Result<()> {
|
||||
// prepare the initializing struct
|
||||
let length: usize = 4 + env::args().skip(2).map(|x| 4+x.len()).sum::<usize>() +
|
||||
let length: usize = 4 + 4 + env::args().skip(2).map(|x| 4+x.len()+1).sum::<usize>() +
|
||||
4 + env::vars().map(|(x,y)| 5 + x.len()+ y.len()).sum::<usize>();
|
||||
|
||||
let mut buf = Cursor::new(vec![0u8;length]);
|
||||
|
@ -46,8 +47,9 @@ impl Socket {
|
|||
// send all arguments (skip first)
|
||||
buf.write_u32::<LittleEndian>(env::args().count() as u32 - 2);
|
||||
for key in env::args().skip(2) {
|
||||
buf.write_u32::<LittleEndian>(key.len() as u32);
|
||||
buf.write_u32::<LittleEndian>(key.len() as u32 + 1);
|
||||
buf.write(key.as_bytes());
|
||||
buf.write_u8(b'\0');
|
||||
}
|
||||
|
||||
// send the environment
|
||||
|
@ -60,7 +62,7 @@ impl Socket {
|
|||
|
||||
let mut stream;
|
||||
loop {
|
||||
match TcpStream::connect(("127.0.0.1", 0x494E)) {
|
||||
match TcpStream::connect(("127.0.0.1", self.port)) {
|
||||
Ok(mut s) => {
|
||||
match s.write(buf.get_ref()) {
|
||||
Ok(_) => { stream = s; break; },
|
||||
|
@ -120,7 +122,7 @@ impl Socket {
|
|||
Packet::Write { fd, buf } => {
|
||||
let mut buf_ret: [u8; 8];
|
||||
if fd != 1 && fd != 2 {
|
||||
buf_ret = transmute(libc::write(fd as i32, buf.as_ptr() as *const libc::c_void, buf.len()).to_le());
|
||||
buf_ret = transmute(libc::write(fd, buf.as_ptr() as *const libc::c_void, buf.len()).to_le());
|
||||
} else {
|
||||
let res = match fd {
|
||||
1 => ActionResult::Output(String::from_utf8_unchecked(buf)),
|
||||
|
@ -129,9 +131,10 @@ impl Socket {
|
|||
};
|
||||
|
||||
let buf: Vec<u8> = serialize(&res, Infinite).unwrap();
|
||||
for stream in self.console.lock().unwrap().iter_mut() {
|
||||
stream.write(&buf).unwrap();
|
||||
}
|
||||
|
||||
// try to send the new console log to each endpoint and retain only
|
||||
// the successfully ones.
|
||||
self.console.lock().unwrap().retain(|mut x| x.write(&buf).is_ok());
|
||||
|
||||
buf_ret = transmute(buf.len());
|
||||
}
|
||||
|
@ -139,24 +142,19 @@ impl Socket {
|
|||
stream.write(&buf_ret);
|
||||
},
|
||||
Packet::Open { name, mode, flags } => {
|
||||
let buf: [u8; 4] = transmute(libc::open(name.as_ptr(), flags as i32, mode as i32).to_le());
|
||||
debug!("got {:?}", buf);
|
||||
|
||||
let mut buf: [u8; 4] = transmute(libc::open(name.as_ptr(), flags as i32, mode as i32).to_le());
|
||||
let written = stream.write(&buf).unwrap();
|
||||
|
||||
debug!("Written {}", written);
|
||||
},
|
||||
Packet::Close { fd } => {
|
||||
let buf: [u8; 4] = transmute(libc::close(fd as i32).to_le());
|
||||
let buf: [u8; 4] = transmute(libc::close(fd).to_le());
|
||||
stream.write(&buf);
|
||||
},
|
||||
Packet::Read { fd, len } => {
|
||||
let mut tmp: Vec<u8> = vec![0; len as usize];
|
||||
let got = libc::read(fd as i32, tmp.as_mut_ptr() as *mut libc::c_void, len as usize);
|
||||
let got = libc::read(fd, tmp.as_mut_ptr() as *mut libc::c_void, len as usize);
|
||||
let buf: [u8; 8] = transmute(got.to_le());
|
||||
|
||||
debug!("Read size {:?}", buf);
|
||||
|
||||
stream.write(&buf);
|
||||
|
||||
if got > 0 {
|
||||
|
@ -164,7 +162,7 @@ impl Socket {
|
|||
}
|
||||
},
|
||||
Packet::LSeek { fd, offset, whence } => {
|
||||
let buf: [u8; 8] = transmute(libc::lseek(fd as i32, offset, whence as i32).to_le());
|
||||
let buf: [u8; 8] = transmute(libc::lseek(fd, offset, whence as i32).to_le());
|
||||
stream.write(&buf);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -96,8 +96,6 @@ impl Syscall {
|
|||
}
|
||||
|
||||
pub unsafe fn run(&self, guest_mem: *mut u8, console: Console) -> Result<Return> {
|
||||
println!("{:?}", *self);
|
||||
|
||||
match *self {
|
||||
Syscall::Write(obj) => {
|
||||
use std::io::Write;
|
||||
|
@ -116,9 +114,7 @@ impl Syscall {
|
|||
|
||||
let buf: Vec<u8> = serialize(&ret, Infinite).unwrap();
|
||||
|
||||
for stream in console.lock().unwrap().iter_mut() {
|
||||
stream.write(&buf).unwrap();
|
||||
}
|
||||
console.lock().unwrap().retain(|mut x| x.write(&buf).is_ok());
|
||||
}
|
||||
},
|
||||
Syscall::Read(obj) => {
|
||||
|
|
|
@ -237,20 +237,14 @@ impl VirtualCPU {
|
|||
Ok(proto::Return::Exit(code)) => {
|
||||
state.running_state.store(false, Ordering::Relaxed);
|
||||
|
||||
println!("exit {}", code);
|
||||
|
||||
return ExitCode::Cause(Ok(code));
|
||||
},
|
||||
Err(err) => {
|
||||
state.running_state.store(false, Ordering::Relaxed);
|
||||
|
||||
println!("error {:?}", err);
|
||||
|
||||
return ExitCode::Cause(Err(err));
|
||||
},
|
||||
_ => {
|
||||
println!("RUN");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,8 +178,10 @@ fn main() {
|
|||
Ok(id) => {
|
||||
let res = daemon.send(Action::Connect(id));
|
||||
|
||||
if let ActionResult::Connect = res {
|
||||
if let ActionResult::Connect(Ok(())) = res {
|
||||
daemon.output();
|
||||
} else {
|
||||
println!("Invalid number!");
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
|
|
Loading…
Add table
Reference in a new issue