Select Git revision
client.rs 6.25 KiB
use std::io::{Result, Error, ErrorKind};
use std::net::{ToSocketAddrs, SocketAddr, UdpSocket};
use std::time::Duration;
use url::{UrlParser, SchemeType};
use num;
use rand::{thread_rng, random, Rng};
use packet::{Packet, PacketType, OptionType};
const DEFAULT_RECEIVE_TIMEOUT: u64 = 5; // 5s
pub struct CoAPClient {
socket: UdpSocket,
peer_addr: SocketAddr,
}
impl CoAPClient {
/// Create a CoAP client with the peer address.
pub fn new<A: ToSocketAddrs>(addr: A) -> Result<CoAPClient> {
addr.to_socket_addrs().and_then(|mut iter| {
match iter.next() {
Some(SocketAddr::V4(a)) => {
UdpSocket::bind("0.0.0.0:0").and_then(|s| {
s.set_read_timeout(Some(Duration::new(DEFAULT_RECEIVE_TIMEOUT, 0)))
.and_then(|_| {
Ok(CoAPClient {
socket: s,
peer_addr: SocketAddr::V4(a),
})
})
})
}
Some(SocketAddr::V6(a)) => {
UdpSocket::bind(":::0").and_then(|s| {
s.set_read_timeout(Some(Duration::new(DEFAULT_RECEIVE_TIMEOUT, 0)))
.and_then(|_| {
Ok(CoAPClient {
socket: s,
peer_addr: SocketAddr::V6(a),
})
})
})
}
None => Err(Error::new(ErrorKind::Other, "no address")),
}
})
}
/// Execute a request with the coap url and a specific timeout. Default timeout is 5s.
pub fn request_with_timeout(url: &str, timeout: Option<Duration>) -> 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,