diff --git a/Cargo.toml b/Cargo.toml index 545e5b7..585c8c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,16 @@ version = "0.1.0" authors = ["Jur van den Berg "] [dependencies] + +[features] +default = ["bonus", "extra"] + +bonus = ["bonus:network"] +"bonus:network" = [] + +extra = ["extra:sleep"] +"extra:sleep" = [] + +debug = ["debug:instr", "debug:frame"] +"debug:instr" = [] +"debug:frame" = [] \ No newline at end of file diff --git a/src/ijvm/frame.rs b/src/ijvm/frame.rs index 30a3e0f..718f674 100644 --- a/src/ijvm/frame.rs +++ b/src/ijvm/frame.rs @@ -9,7 +9,9 @@ pub struct Frame { impl Frame { pub fn new(num_locals: usize) -> Frame { -// println!("Initializing frame of len {}", num_locals); + if cfg!(feature="debug:frame") { + println!("Initializing frame of len {}", num_locals); + } return Frame { stack: Stack::new(), locals: vec![0; num_locals+1], diff --git a/src/ijvm/machine.rs b/src/ijvm/machine.rs index 050fcd4..790cb78 100644 --- a/src/ijvm/machine.rs +++ b/src/ijvm/machine.rs @@ -7,6 +7,7 @@ use ijvm::binread::BinRead; use ijvm::frame::Frame; use ijvm::stack::Stack; use ijvm::pool::Pool; +use ijvm::netstack::NetStack; use ijvm::Result; const MAGIC_HEADER:u32 = 0x1deadfad; @@ -16,7 +17,8 @@ pub struct Machine { pub wide: bool, pub pool: Pool, pub block: Block, - pub frame: Vec + pub frame: Vec, + pub net: NetStack } impl Machine { @@ -26,6 +28,7 @@ impl Machine { pool: pool, block: block, frame: vec![Frame::new(ANTI_BS_SIZE)], + net: NetStack::new(), } } @@ -52,11 +55,15 @@ impl Machine { pub fn step(&mut self) -> Result<()> { match self.block.read_op() { Ok(Operation::Op(a, func)) => { -// println!("{}", a); -// println!("Stack: {:?}", self.cur_frame().stack.data); - let x = func(self); -// println!("Stack: {:?}", self.cur_frame().stack.data); - x + if cfg!(feature = "debug:instr") { + println!("{}", a); + println!("Stack: {:?}", self.cur_frame().stack.data); + let x = func(self); + println!("Stack: {:?}", self.cur_frame().stack.data); + x + } else { + func(self) + } }, Ok(Operation::Invalid(a)) => { println!("OP: {}", a); diff --git a/src/ijvm/mod.rs b/src/ijvm/mod.rs index 8a8fb8b..dded12f 100644 --- a/src/ijvm/mod.rs +++ b/src/ijvm/mod.rs @@ -6,5 +6,6 @@ pub mod machine; pub mod stack; pub mod pool; pub mod frame; +pub mod netstack; type Result = ::std::result::Result; diff --git a/src/ijvm/netstack.rs b/src/ijvm/netstack.rs new file mode 100644 index 0000000..b5d6686 --- /dev/null +++ b/src/ijvm/netstack.rs @@ -0,0 +1,86 @@ +use ijvm::Result; +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; + + +#[derive(Debug)] +pub struct NetStack { + pub stream: Option +} + +impl NetStack { + pub fn new() -> NetStack { + NetStack{ + stream: None, + } + } + + pub fn bind(&mut self, port: u16) -> Result<()> { + let listener = match TcpListener::bind(format!("0.0.0.0:{}", port)) { + Ok(a) => a, + Err(_) => return Err("Failed to open connection"), + }; + + return match listener.accept() { + Ok((sock, _)) => { + self.stream = Some(sock); + Ok(()) + } + Err(_) => Err("Could not accept connection") + } + } + + pub fn connect(&mut self, host: u32, port: u16) -> Result<()> { + let h1 = (host & (0xFF << 24)) >> 24 as u8; + let h2 = (host & (0xFF << 16)) >> 16 as u8; + let h3 = (host & (0xFF << 8)) >> 8 as u8; + let h4 = (host & (0xFF << 0)) >> 0 as u8; + let addr: String = format!("{}.{}.{}.{}:{}", h1, h2, h3, h4, port); + + if let Ok(stream) = TcpStream::connect(addr) { + self.stream = Some(stream); + return Ok(()) + } + Err("Could not connect to address") + } + + pub fn close(&mut self) -> Result<()> { + if let None = self.stream { + return Err("Cannot close a nonexistent socket") + } + + self.stream = None; + Ok(()) + } + + pub fn read_byte(&mut self) -> Result { + return match self.stream { + Some(ref mut stream) => { + match stream.bytes().next().and_then(|r| r.ok()) { + Some(i) => Ok(i as i8), + None => Err("Could not read a byte") + } + }, + None => Err("No connection") + } + } + + pub fn write_byte(&mut self, byte: u8) -> Result<()> { + return match self.stream { + Some(ref mut stream) => { + let buf = [byte]; + match stream.write(&buf) { + Ok(a) => { + if a > 0 { + Ok(()) + } else { + Err("Wrote zero bytes") + } + }, + Err(_) => Err("Could not write a byte") + } + }, + None => Err("No connection") + } + } +} \ No newline at end of file diff --git a/src/ijvm/ops.rs b/src/ijvm/ops.rs index 2252b82..c052d1d 100644 --- a/src/ijvm/ops.rs +++ b/src/ijvm/ops.rs @@ -40,7 +40,20 @@ pub fn num_to_op(op: u8) -> Operation { 0xFD => Operation::Op("OUT", out), 0xFF => Operation::Op("HALT", halt), + #[cfg(feature = "extra:sleep")] 0xF0 => Operation::Op("SLP", slp), + + #[cfg(feature = "bonus:network")] + 0xE1 => Operation::Op("NETBIND", netbind), + #[cfg(feature = "bonus:network")] + 0xE2 => Operation::Op("NETCONNECT", netconnect), + #[cfg(feature = "bonus:network")] + 0xE3 => Operation::Op("NETIN", netin), + #[cfg(feature = "bonus:network")] + 0xE4 => Operation::Op("NETOUT", netout), + #[cfg(feature = "bonus:network")] + 0xE5 => Operation::Op("NETCLOSE", netclose), + x => Operation::Invalid(x) } } @@ -232,6 +245,7 @@ fn ireturn(machine: &mut Machine) -> Result<()> { machine.block.seek(return_addr as usize) } +#[cfg(feature = "extra:sleep")] fn slp(machine: &mut Machine) -> Result<()> { use std::time; use std::thread; @@ -242,4 +256,35 @@ fn slp(machine: &mut Machine) -> Result<()> { let slpdur = time::Duration::from_millis(val*100); thread::sleep(slpdur); Ok(()) +} + +#[cfg(feature = "bonus:network")] +fn netbind(machine: &mut Machine) -> Result<()> { + let port = machine.cur_stack().pop()? as u16; + machine.net.bind(port) +} + +#[cfg(feature = "bonus:network")] +fn netconnect(machine: &mut Machine) -> Result<()> { + let port = machine.cur_stack().pop()? as u16; + let host = machine.cur_stack().pop()? as u32; + machine.net.connect(host, port) +} + +#[cfg(feature = "bonus:network")] +fn netin(machine: &mut Machine) -> Result<()> { + let byte = machine.net.read_byte()? as i32; + machine.cur_stack().push(byte); + Ok(()) +} + +#[cfg(feature = "bonus:network")] +fn netout(machine: &mut Machine) -> Result<()> { + let val = machine.cur_stack().pop()? as u8; + machine.net.write_byte(val) +} + +#[cfg(feature = "bonus:network")] +fn netclose(machine: &mut Machine) -> Result<()> { + machine.net.close() } \ No newline at end of file diff --git a/src/ijvm/stack.rs b/src/ijvm/stack.rs index 349c53b..dfb0af5 100644 --- a/src/ijvm/stack.rs +++ b/src/ijvm/stack.rs @@ -33,8 +33,4 @@ impl Stack { pub fn push(&mut self, val: i32) { self.data.push(val); } - - pub fn len(&self) -> usize { - self.data.len() - } } \ No newline at end of file