Skip to content

Commit

Permalink
Merge pull request #1 from jiayihu/master
Browse files Browse the repository at this point in the history
Add CoapRequest and CoapResponse.
  • Loading branch information
martindisch committed Nov 25, 2020
2 parents 52511b1 + 3ca3380 commit 2788f41
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ pub mod error;

mod header;
mod packet;
mod request;
mod response;

pub use header::{
Header, HeaderRaw, MessageClass, MessageType, RequestType, ResponseType,
};
pub use packet::{CoapOption, ContentFormat, Packet};
pub use request::CoapRequest;
pub use response::CoapResponse;
83 changes: 83 additions & 0 deletions src/request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use super::header::{MessageClass, RequestType as Method};
use super::packet::{CoapOption, Packet};
use super::response::CoapResponse;
use alloc::string::{String, ToString};
use alloc::vec::Vec;

/// The CoAP request.
#[derive(Clone, Debug)]
pub struct CoapRequest<Endpoint> {
pub message: Packet,
pub response: Option<CoapResponse>,
pub source: Option<Endpoint>,
}

impl<Endpoint> CoapRequest<Endpoint> {
/// Creates a new request.
pub fn new() -> CoapRequest<Endpoint> {
CoapRequest {
response: None,
message: Packet::new(),
source: None,
}
}

/// Creates a request from a packet.
pub fn from_packet(
packet: Packet,
source: Endpoint,
) -> CoapRequest<Endpoint> {
CoapRequest {
response: CoapResponse::new(&packet),
message: packet,
source: Some(source),
}
}

/// Sets the method.
pub fn set_method(&mut self, method: Method) {
self.message.header.code = MessageClass::Request(method);
}

/// Returns the method.
pub fn get_method(&self) -> &Method {
match self.message.header.code {
MessageClass::Request(Method::Get) => &Method::Get,
MessageClass::Request(Method::Post) => &Method::Post,
MessageClass::Request(Method::Put) => &Method::Put,
MessageClass::Request(Method::Delete) => &Method::Delete,
_ => &Method::UnKnown,
}
}

/// Sets the path.
pub fn set_path(&mut self, path: &str) {
self.message.clear_option(CoapOption::UriPath);

let segs = path.split('/');
for (i, s) in segs.enumerate() {
if i == 0 && s.is_empty() {
continue;
}

self.message
.add_option(CoapOption::UriPath, s.as_bytes().to_vec());
}
}

/// Returns the path.
pub fn get_path(&self) -> String {
match self.message.get_option(CoapOption::UriPath) {
Some(options) => {
let mut vec = Vec::new();
for option in options.iter() {
if let Ok(seg) = core::str::from_utf8(option) {
vec.push(seg);
}
}
vec.join("/")
}
_ => "".to_string(),
}
}
}
87 changes: 87 additions & 0 deletions src/response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use super::header::{MessageClass, MessageType, ResponseType as Status};
use super::packet::Packet;

/// The CoAP response.
#[derive(Clone, Debug)]
pub struct CoapResponse {
pub message: Packet,
}

impl CoapResponse {
/// Creates a new response.
pub fn new(request: &Packet) -> Option<CoapResponse> {
let mut packet = Packet::new();

packet.header.set_version(1);
let response_type = match request.header.get_type() {
MessageType::Confirmable => MessageType::Acknowledgement,
MessageType::NonConfirmable => MessageType::NonConfirmable,
_ => return None,
};
packet.header.set_type(response_type);
packet.header.code = MessageClass::Response(Status::Content);
packet.header.message_id = request.header.message_id;
packet.set_token(request.get_token().clone());

packet.payload = request.payload.clone();

Some(CoapResponse { message: packet })
}

/// Sets the status.
pub fn set_status(&mut self, status: Status) {
self.message.header.code = MessageClass::Response(status);
}

/// Returns the status.
pub fn get_status(&self) -> &Status {
match self.message.header.code {
MessageClass::Response(Status::Created) => &Status::Created,
MessageClass::Response(Status::Deleted) => &Status::Deleted,
MessageClass::Response(Status::Valid) => &Status::Valid,
MessageClass::Response(Status::Changed) => &Status::Changed,
MessageClass::Response(Status::Content) => &Status::Content,

MessageClass::Response(Status::BadRequest) => &Status::BadRequest,
MessageClass::Response(Status::Unauthorized) => {
&Status::Unauthorized
}
MessageClass::Response(Status::BadOption) => &Status::BadOption,
MessageClass::Response(Status::Forbidden) => &Status::Forbidden,
MessageClass::Response(Status::NotFound) => &Status::NotFound,
MessageClass::Response(Status::MethodNotAllowed) => {
&Status::MethodNotAllowed
}
MessageClass::Response(Status::NotAcceptable) => {
&Status::NotAcceptable
}
MessageClass::Response(Status::PreconditionFailed) => {
&Status::PreconditionFailed
}
MessageClass::Response(Status::RequestEntityTooLarge) => {
&Status::RequestEntityTooLarge
}
MessageClass::Response(Status::UnsupportedContentFormat) => {
&Status::UnsupportedContentFormat
}

MessageClass::Response(Status::InternalServerError) => {
&Status::InternalServerError
}
MessageClass::Response(Status::NotImplemented) => {
&Status::NotImplemented
}
MessageClass::Response(Status::BadGateway) => &Status::BadGateway,
MessageClass::Response(Status::ServiceUnavailable) => {
&Status::ServiceUnavailable
}
MessageClass::Response(Status::GatewayTimeout) => {
&Status::GatewayTimeout
}
MessageClass::Response(Status::ProxyingNotSupported) => {
&Status::ProxyingNotSupported
}
_ => &Status::UnKnown,
}
}
}

0 comments on commit 2788f41

Please sign in to comment.