Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
carllerche committed Aug 20, 2014
0 parents commit 0e711c4
Show file tree
Hide file tree
Showing 13 changed files with 670 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Cargo.lock
target
libs
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]

name = "mio"
version = "0.0.1"
authors = ["Carl Lerche <[email protected]>"]

[dependencies.nix]

path = "libs/nix-rust"
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# MIO - Mini IO

A lightweight non-blocking IO library for Rust.

## Summary

Uses the reactor pattern.
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub struct ReactorConfig {
}
4 changes: 4 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use nix;

pub type MioResult<T> = Result<T, MioError>;
pub type MioError = nix::SysError;
12 changes: 12 additions & 0 deletions src/handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

pub trait Handler<T> {
fn accept(token: T) -> Option<T> {
None
}

fn readable(token: T) {
}

fn writable(token: T) {
}
}
21 changes: 21 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#![crate_name = "mio"]
#![feature(globs)]
#![feature(unsafe_destructor)]

extern crate alloc;
extern crate nix;

pub use handler::Handler;
pub use reactor::{Reactor, IoHandle};
pub use sock::{TcpSocket, SockAddr};

mod error;
mod handler;
mod reactor;
mod sock;
mod timer;
mod util;

#[cfg(target_os = "linux")]
#[path = "os_linux.rs"]
mod os;
54 changes: 54 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
extern crate nix;
extern crate mio;

use std::mem;
use nix::sys::utsname::uname;
use mio::{Reactor, Handler, IoHandle, TcpSocket, SockAddr};

/*
struct Proxy;
impl Handler for Proxy {
fn accept(token: Token) -> Option<Token> {
// foo
}
fn readable(token);
fn writable(token);
fn error(token);
}
*/

struct MyHandler;

impl Handler<()> for MyHandler {
}

pub fn main() {
println!("ZOMG; {}", uname().release());

let mut reactor = Reactor::<()>::new().unwrap();
let addr = SockAddr::parse("74.125.28.103:80").expect("could not parse InetAddr");
let sock = TcpSocket::v4().unwrap();

// Configure options

reactor.connect(sock, addr, ()).unwrap();
reactor.run(MyHandler);

/*
// set sock options
// reactor.connect();
reactor.run(MyHandler);
let proxy = Proxy::new();
let sock = TcpSocket::v4();
let reactor = Reactor::new();
reactor.connect(sock, 1);
reactor.run();
*/
}
147 changes: 147 additions & 0 deletions src/os_linux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
use std::mem;
use nix::errno::EINPROGRESS;
use nix::fcntl::Fd;
use error::MioResult;
use sock::{Socket, SockAddr, InetAddr, IpV4Addr};
use reactor::{IoHandle, IoEventKind, IoEvent, IoReadable, IoWritable, IoError};

mod nix {
pub use nix::sys::epoll::*;
pub use nix::sys::socket::*;
pub use nix::unistd::*;
}

pub fn connect(io: IoHandle, addr: SockAddr) -> MioResult<bool> {
match nix::connect(io.ident(), &from_sockaddr(addr)) {
Ok(_) => Ok(true),
Err(e) => {
match e.kind {
EINPROGRESS => Ok(false),
_ => Err(e)
}
}
}
}

pub fn read(io: &IoHandle, dst: &mut [u8]) -> MioResult<uint> {
nix::read(io.ident(), dst)
}

pub struct Selector {
epfd: Fd
}

impl Selector {
pub fn new() -> MioResult<Selector> {
Ok(Selector {
epfd: try!(nix::epoll_create())
})
}

/// Wait for events from the OS
pub fn select(&mut self, evts: &mut Events, timeout_ms: uint) -> MioResult<()> {
let cnt = try!(nix::epoll_wait(
self.epfd,
evts.events.as_mut_slice(),
timeout_ms));

println!("select: {}", cnt);

evts.len = cnt;
Ok(())
}

/// Register event interests for the given IO handle with the OS
pub fn register(&mut self, handle: IoHandle) -> MioResult<()> {
let interests = nix::EPOLLIN | nix::EPOLLOUT | nix::EPOLLERR;

let info = nix::EpollEvent {
events: interests | nix::EPOLLET,
data: unsafe { mem::transmute(handle) }
};

nix::epoll_ctl(self.epfd, nix::EpollCtlAdd, handle.ident(), &info)
}
}

pub struct Events {
len: uint,
events: [nix::EpollEvent, ..256]
}

impl Events {
pub fn new() -> Events {
Events {
len: 0,
events: unsafe { mem::uninitialized() }
}
}

#[inline]
pub fn len(&self) -> uint {
self.len
}

#[inline]
pub fn get(&self, idx: uint) -> IoEvent {
if idx >= self.len {
fail!("invalid index");
}

let epoll = self.events[idx].events;
let mut kind = IoEventKind::empty();

if epoll.contains(nix::EPOLLIN) {
kind = kind | IoReadable;
}

if epoll.contains(nix::EPOLLOUT) {
kind = kind | IoWritable;
}

if epoll.contains(nix::EPOLLERR) {
kind = kind | IoError;
}

let handle = unsafe { mem::transmute(self.events[idx].data) };

IoEvent::new(kind, handle)
}
}

fn from_sockaddr(addr: SockAddr) -> nix::SockAddr {
use std::mem;

println!("addr: {}", addr);

match addr {
InetAddr(ip, port) => {
match ip {
IpV4Addr(a, b, c, d) => {
let addr = nix::sockaddr_in {
sin_family: nix::AF_INET as nix::sa_family_t,
sin_port: port.to_be(),
sin_addr: ip4_to_inaddr(a, b, c, d),
sin_zero: unsafe { mem::zeroed() }

};

nix::SockIpV4(addr)
}
_ => unimplemented!()
}
}
_ => unimplemented!()
}
}

fn ip4_to_inaddr(a: u8, b: u8, c: u8, d: u8) -> nix::in_addr {
let ip = (a as u32 << 24) |
(b as u32 << 16) |
(c as u32 << 8) |
(d as u32 << 0);

nix::in_addr {
s_addr: Int::from_be(ip)
}
}
Loading

0 comments on commit 0e711c4

Please sign in to comment.