1
0
Fork 0
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:
bytesnake 2017-08-13 20:56:11 +02:00
parent cb20bd1f5c
commit 966199b8c5
8 changed files with 65 additions and 41 deletions

View file

@ -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);

View file

@ -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)) })
}
}

View file

@ -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);

View file

@ -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());

View file

@ -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);
}
};

View file

@ -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) => {

View file

@ -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");
}
_ => {}
}
}

View file

@ -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(_) => {