From b2e385e26897dc79b12357afcd5ffcc3d0b3ab83 Mon Sep 17 00:00:00 2001 From: Covertness <wuyingfengsui@gmail.com> Date: Fri, 7 Aug 2015 22:29:38 +0800 Subject: [PATCH] add request API for client --- Cargo.toml | 7 ++-- README.md | 21 +++--------- examples/client.rs | 12 +++++-- examples/client_and_server.rs | 19 +++-------- src/client.rs | 64 ++++++++++++++++++++++++++++++++++- src/lib.rs | 3 ++ src/server.rs | 1 + 7 files changed, 90 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 97ee07c..30a5083 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "coap" -version = "0.1.1" +version = "0.2.0" description = "A CoAP library" readme = "README.md" documentation = "http://covertness.github.io/coap-rs/coap/index.html" @@ -13,4 +13,7 @@ keywords = ["CoAP"] bincode = "0.3.0" rustc-serialize = "0.3" mio = "0.3.7" -threadpool = "0.1" \ No newline at end of file +threadpool = "0.1" +url = "0.2.36" +num = "0.1" +rand = "0.3" \ No newline at end of file diff --git a/README.md b/README.md index 28e0cd4..e7f3f11 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ First add this to your `Cargo.toml`: ```toml [dependencies] -coap = "0.1.1" +coap = "0.2.0" ``` Then, add this to your crate root: @@ -62,21 +62,10 @@ use coap::packet::*; use coap::CoAPClient; fn main() { - let addr = "127.0.0.1:5683"; - let request = "test"; - - let client = CoAPClient::new(addr).unwrap(); - let mut packet = Packet::new(); - packet.header.set_version(1); - packet.header.set_type(PacketType::Confirmable); - packet.header.set_code("0.01"); - packet.header.set_message_id(1); - packet.set_token(vec!(0x51, 0x55, 0x77, 0xE8)); - packet.add_option(OptionType::UriPath, request.to_string().into_bytes()); - client.send(&packet).unwrap(); - println!("Client request: coap://{}/{}", addr, request); - - let response = client.receive().unwrap(); + let url = "coap://127.0.0.1:5683/Rust"; + println!("Client request: {}", url); + + let response: Packet = CoAPClient::request(url).unwrap(); println!("Server reply: {}", String::from_utf8(response.payload).unwrap()); } ``` diff --git a/examples/client.rs b/examples/client.rs index 6eacffc..eb4bfe0 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -6,7 +6,7 @@ use coap::CoAPClient; fn main() { let addr = "127.0.0.1:5683"; let request = "test"; - + let client = CoAPClient::new(addr).unwrap(); let mut packet = Packet::new(); packet.header.set_version(1); @@ -18,6 +18,12 @@ fn main() { client.send(&packet).unwrap(); println!("Client request: coap://{}/{}", addr, request); - let response = client.receive().unwrap(); - println!("Server reply: {}", String::from_utf8(response.payload).unwrap()); + match client.receive() { + Ok(response) => { + println!("Server reply: {}", String::from_utf8(response.payload).unwrap()); + }, + Err(e) => { + println!("Request error: {:?}", e); + } + } } \ No newline at end of file diff --git a/examples/client_and_server.rs b/examples/client_and_server.rs index 2f69a92..cb4093b 100644 --- a/examples/client_and_server.rs +++ b/examples/client_and_server.rs @@ -19,23 +19,12 @@ fn request_handler(req: Packet, resp: CoAPClient) { } fn main() { - let addr = "127.0.0.1:5683"; - let request = "test"; - - let mut server = CoAPServer::new(addr).unwrap(); + let mut server = CoAPServer::new("127.0.0.1:5683").unwrap(); server.handle(request_handler).unwrap(); - let client = CoAPClient::new(addr).unwrap(); - let mut packet = Packet::new(); - packet.header.set_version(1); - packet.header.set_type(PacketType::Confirmable); - packet.header.set_code("0.01"); - packet.header.set_message_id(1); - packet.set_token(vec!(0x51, 0x55, 0x77, 0xE8)); - packet.add_option(OptionType::UriPath, request.to_string().into_bytes()); - client.send(&packet).unwrap(); - println!("Client request: coap://{}/{}", addr, request); + let url = "coap://127.0.0.1:5683/Rust"; + println!("Client request: {}", url); - let response = client.receive().unwrap(); + let response: Packet = CoAPClient::request(url).unwrap(); println!("Server reply: {}", String::from_utf8(response.payload).unwrap()); } \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 52fbbd5..152e08f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,9 @@ use std::io::{Result, Error, ErrorKind}; use std::net::{ToSocketAddrs, SocketAddr, UdpSocket}; -use packet::Packet; +use url::{UrlParser, SchemeType}; +use num; +use rand::{thread_rng, random, Rng}; +use packet::{Packet, PacketType, OptionType}; pub struct CoAPClient { socket: UdpSocket, @@ -33,6 +36,58 @@ impl CoAPClient { }) } + /// Execute a request with the coap url. + pub fn request(url: &str) -> Result<Packet> { + let mut url_parser = UrlParser::new(); + url_parser.scheme_type_mapper(Self::coap_scheme_type_mapper); + + match url_parser.parse(url) { + Ok(url_params) => { + let mut packet = Packet::new(); + packet.header.set_version(1); + packet.header.set_type(PacketType::Confirmable); + packet.header.set_code("0.01"); + + let message_id = thread_rng().gen_range(0, num::pow(2u32, 16)) as u16; + packet.header.set_message_id(message_id); + + let mut token: Vec<u8> = vec!(1, 1, 1, 1); + for x in token.iter_mut() { + *x = random() + } + packet.set_token(token.clone()); + + let domain = match url_params.domain() { + Some(d) => d, + None => return Err(Error::new(ErrorKind::InvalidInput, "domain error")) + }; + let port = url_params.port_or_default().unwrap(); + + if let Some(path) = url_params.path() { + for p in path.iter() { + packet.add_option(OptionType::UriPath, p.clone().into_bytes().to_vec()); + } + }; + + let client = try!(Self::new((domain, port))); + try!(client.send(&packet)); + + match client.receive() { + Ok(receive_packet) => { + if receive_packet.header.get_message_id() == message_id + && *receive_packet.get_token() == token { + return Ok(receive_packet) + } else { + return Err(Error::new(ErrorKind::Other, "receive invalid data")) + } + }, + Err(e) => Err(e) + } + }, + Err(_) => Err(Error::new(ErrorKind::InvalidInput, "url error")) + } + } + /// Execute a request. pub fn send(&self, packet: &Packet) -> Result<()> { match packet.to_bytes() { @@ -58,4 +113,11 @@ impl CoAPClient { Err(_) => Err(Error::new(ErrorKind::InvalidInput, "packet error")) } } + + fn coap_scheme_type_mapper(scheme: &str) -> SchemeType { + match scheme { + "coap" => SchemeType::Relative(5683), + _ => SchemeType::NonRelative, + } + } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index f758ae7..eca1f6d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,9 @@ extern crate bincode; extern crate rustc_serialize; extern crate mio; extern crate threadpool; +extern crate url; +extern crate num; +extern crate rand; pub use server::CoAPServer; pub use client::CoAPClient; diff --git a/src/server.rs b/src/server.rs index f32d3f2..ba291f8 100644 --- a/src/server.rs +++ b/src/server.rs @@ -123,6 +123,7 @@ impl CoAPServer { } } + /// Set the number of threads for handling requests pub fn set_worker_num(&mut self, worker_num: usize) { self.worker_num = worker_num; } -- GitLab