Skip to content

Commit

Permalink
Genesis: Initial commit
Browse files Browse the repository at this point in the history
Implement i2p SAM handshake. The library uses nom to parse the response.
  • Loading branch information
igortoliveira committed Jul 18, 2016
0 parents commit b2e8e41
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
target
Cargo.lock

# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "i2p"
version = "0.1.0"
authors = ["Igor Oliveira <igor@work.co>"]

[dependencies]
nom = "^1.2.3"
38 changes: 38 additions & 0 deletions src/i2p.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use nom::IResult;
use parsers::{sam_hello};
use std::net::{TcpStream, ToSocketAddrs};
use std::io::{Error, Read, Write};

static SAM_MIN: &'static str = "3.0";
static SAM_MAX: &'static str = "3.1";

pub struct I2p {
stream: TcpStream
}

impl I2p {
fn handshake(&mut self) {
let hello_msg = format!("HELLO VERSION MIN={min} MAX={max} \n",
min = SAM_MIN,
max = SAM_MAX);
let _ = self.stream.write(&hello_msg.into_bytes());

let mut buffer = String::new();
let _ = self.stream.read_to_string(&mut buffer);

let res = sam_hello(&buffer);
match res {
IResult::Done(i, o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
}

pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<I2p, Error> {
let tcp_stream = try!(TcpStream::connect(addr));
let mut i2p = I2p { stream: tcp_stream };

i2p.handshake();

Ok(i2p)
}
}
19 changes: 19 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[macro_use]
extern crate nom;

pub use i2p::I2p;

mod i2p;
mod parsers;

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
use i2p::I2p;
match I2p::connect("127.0.0.1:7656") {
Ok(_) => println!("works"),
Err(err) => println!("An error occurred: {}", err),
}
}
}
53 changes: 53 additions & 0 deletions src/parsers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use std::collections::HashMap;
use nom::{IResult, space, alphanumeric};

fn is_space(chr: char) -> bool {
chr == ' ' || chr == '\t'
}

fn is_next_line(chr: char) -> bool {
chr == '\n'
}

fn is_space_or_next_line(chr: char) -> bool {
is_space(chr) || is_next_line(chr)
}

named!(key_value <&str, (&str, &str)>,
chain!(
space? ~
key: alphanumeric ~
space? ~
tag_s!("=") ~
space? ~
val: take_till_s!(is_space_or_next_line) ,
|| { (key, val) }
)
);

named!(keys_and_values<&str, Vec<(&str, &str)> >, many0!(key_value));

fn options(input: &str) -> IResult<&str, HashMap<&str, &str> > {
let mut h: HashMap<&str, &str> = HashMap::new();

match keys_and_values(input) {
IResult::Done(i, tuple_vec) => {
for &(k,v) in &tuple_vec {
h.insert(k, v);
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}

named!(pub sam_hello <&str, HashMap<&str, &str> >,
chain!(
tag_s!("HELLO") ~
space? ~
tag_s!("REPLY") ~
parse_options: options ,
|| { parse_options }
)
);

0 comments on commit b2e8e41

Please sign in to comment.