use super::*;
mod request;
pub use request::*;
mod observe;
pub use observe::*;
mod unicast_block2;
pub use unicast_block2::*;
mod handler;
pub use handler::*;
mod inspect;
pub use inspect::*;
mod payload;
pub use payload::*;
mod ping;
pub use ping::Ping;
mod add_option;
pub use add_option::*;
mod nonconfirmable;
pub use nonconfirmable::*;
mod multicast;
pub use multicast::*;
mod emit;
pub use emit::*;
mod include_socket_addr;
pub use include_socket_addr::*;
mod uri_host_path;
pub use uri_host_path::UriHostPath;
use std::iter::{once, Once};
use std::marker::PhantomData;
use std::ops::Bound;
use std::time::Duration;
pub trait SendDesc<IC, R = (), TP = StandardCoapConstants>: Send
where
IC: InboundContext,
R: Send,
TP: TransParams,
{
fn trans_params(&self) -> Option<TP> {
None
}
fn supports_option(&self, option: OptionNumber) -> bool {
!option.is_critical()
}
fn delay_to_retransmit(&self, retransmits_sent: u32) -> Option<Duration> {
if retransmits_sent > TP::COAP_MAX_RETRANSMIT {
return None;
}
let ret = (TP::COAP_ACK_TIMEOUT.as_millis() as u64) << retransmits_sent as u64;
const JDIV: u64 = 512u64;
let rmod: u64 = (JDIV as f32 * (TP::COAP_ACK_RANDOM_FACTOR - 1.0)) as u64;
let jmul = JDIV + rand::random::<u64>() % rmod;
Some(Duration::from_millis(ret * jmul / JDIV))
}
fn delay_to_restart(&self) -> Option<Duration> {
None
}
fn max_rtt(&self) -> Duration {
TP::COAP_MAX_RTT
}
fn transmit_wait_duration(&self) -> Duration {
TP::COAP_MAX_TRANSMIT_WAIT
}
fn write_options(
&self,
msg: &mut dyn OptionInsert,
socket_addr: &IC::SocketAddr,
start: Bound<OptionNumber>,
end: Bound<OptionNumber>,
) -> Result<(), Error>;
fn write_payload(
&self,
msg: &mut dyn MessageWrite,
socket_addr: &IC::SocketAddr,
) -> Result<(), Error>;
fn handler(&mut self, context: Result<&IC, Error>) -> Result<ResponseStatus<R>, Error>;
}
pub trait SendDescUnicast {
fn block2<IC, R, TP>(self, block2: Option<BlockInfo>) -> UnicastBlock2<Self, IC>
where
IC: InboundContext,
R: Send,
TP: TransParams,
Self: SendDesc<IC, R, TP> + Sized,
{
UnicastBlock2::new(self, block2)
}
}
pub trait SendDescMulticast {}
pub trait SendDescExt<IC, R, TP>: SendDesc<IC, R, TP> + Sized
where
IC: InboundContext,
R: Send,
TP: TransParams,
{
fn add_option_iter<K, I>(self, key: OptionKey<K>, viter: I) -> AddOption<Self, K, I, IC>
where
I: IntoIterator<Item = K> + Send + Clone,
K: Send + Clone,
{
AddOption {
inner: self,
key,
viter,
phantom: PhantomData,
}
}
fn add_option<K>(self, key: OptionKey<K>, value: K) -> AddOption<Self, K, Once<K>, IC>
where
K: Send + Clone,
{
self.add_option_iter(key, once(value))
}
fn accept(
self,
accept: ContentFormat,
) -> AddOption<Self, ContentFormat, Once<ContentFormat>, IC> {
self.add_option(option::ACCEPT, accept)
}
fn content_format(
self,
content_format: ContentFormat,
) -> AddOption<Self, ContentFormat, Once<ContentFormat>, IC> {
self.add_option(option::CONTENT_FORMAT, content_format)
}
fn use_handler<F, FR>(self, handler: F) -> Handler<Self, F>
where
F: FnMut(
Result<&dyn InboundContext<SocketAddr = IC::SocketAddr>, Error>,
) -> Result<ResponseStatus<FR>, Error>
+ Send,
FR: Send,
{
Handler {
inner: self,
handler,
}
}
fn emit_any_response(self) -> EmitAnyResponse<Self> {
EmitAnyResponse::new(self)
}
fn emit_successful_response(self) -> EmitSuccessfulResponse<Self> {
EmitSuccessfulResponse::new(self)
}
fn emit_msg_code(self) -> EmitMsgCode<Self> {
EmitMsgCode::new(self)
}
fn include_socket_addr(self) -> IncludeSocketAddr<Self> {
IncludeSocketAddr::new(self)
}
fn inspect<F>(self, inspect: F) -> Inspect<Self, F>
where
F: FnMut(&dyn InboundContext<SocketAddr = IC::SocketAddr>) + Send,
{
Inspect {
inner: self,
inspect,
}
}
fn payload_writer<F>(self, writer: F) -> PayloadWriter<Self, F>
where
F: Fn(&mut dyn MessageWrite) -> Result<(), Error> + Send,
{
PayloadWriter {
inner: self,
writer,
}
}
fn uri_host_path<T: Into<RelRefBuf>>(
self,
host: Option<String>,
uri_path: T,
) -> UriHostPath<Self, IC> {
UriHostPath {
inner: self,
host,
path_and_query: uri_path.into(),
phantom: PhantomData,
}
}
}
impl<T, IC, R, TP> SendDescExt<IC, R, TP> for T
where
T: SendDesc<IC, R, TP>,
IC: InboundContext,
R: Send,
TP: TransParams,
{
}
#[macro_export]
macro_rules! write_options {
(($msg:expr, $socket_addr:expr, $start:expr, $end:expr, $inner:expr) { $($key:expr => $viter:expr),* }) => {{
let mut start = $start;
let end = $end;
let inner = &$inner;
let msg = $msg;
let socket_addr = $socket_addr;
#[allow(unused)]
use $crate::option::*;
#[allow(unused)]
use std::iter::once;
$( write_options!(_internal $key, $viter, start, end, msg, socket_addr, inner); )*
inner.write_options(msg, socket_addr, start, end)
}};
(($msg:expr, $socket_addr:expr, $start:expr, $end:expr) { $($key:expr => $viter:expr),* }) => {{
let mut start = $start;
let end = $end;
let msg = $msg;
let _socket_addr = $socket_addr;
#[allow(unused)]
use $crate::option::*;
#[allow(unused)]
use std::iter::once;
$( write_options!(_internal $key, $viter, start, end, msg, socket_addr); )*
let _ = start;
Ok(())
}};
(($msg:ident, $socket_addr:ident, $start:ident, $end:ident, $inner:expr) { $($key:expr => $viter:expr),* ,}) => {
write_options!(($msg,$socket_addr,$start,$end,$inner){$($key=>$viter),*})
};
(($msg:ident, $socket_addr:ident, $start:ident, $end:ident) { $($key:expr => $viter:expr),* ,}) => {
write_options!(($msg,$socket_addr,$start,$end){$($key=>$viter),*})
};
( _internal $key:expr, $viter:expr, $start:ident, $end:ident, $msg:ident, $socket_addr:ident, $inner:expr) => {{
let key = $key;
let mut value_iter = $viter.into_iter().peekable();
if value_iter.peek().is_some()
&& match $start {
Bound::Included(b) => b <= key.0,
Bound::Excluded(b) => b < key.0,
Bound::Unbounded => true,
}
{
if match $end {
Bound::Included(b) => key.0 <= b,
Bound::Excluded(b) => key.0 < b,
Bound::Unbounded => true,
} {
$inner.write_options($msg, $socket_addr, $start, Bound::Included(key.0))?;
for value in value_iter {
$msg.insert_option(key, value)?;
}
$start = Bound::Excluded(key.0)
}
}
}};
( _internal $key:expr, $viter:expr, $start:ident, $end:ident, $msg:ident, $socket_addr:ident) => {{
let key = $key;
let mut value_iter = $viter.into_iter().peekable();
if value_iter.peek().is_some()
&& match $start {
Bound::Included(b) => b <= key.0,
Bound::Excluded(b) => b < key.0,
Bound::Unbounded => true,
}
{
if match $end {
Bound::Included(b) => key.0 <= b,
Bound::Excluded(b) => key.0 < b,
Bound::Unbounded => true,
} {
for value in value_iter {
$msg.insert_option(key, value)?;
}
$start = Bound::Excluded(key.0)
}
}
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! send_desc_passthru_timing {
($inner:tt) => {
fn delay_to_retransmit(&self, retransmits_sent: u32) -> Option<::core::time::Duration> {
self.$inner.delay_to_retransmit(retransmits_sent)
}
fn delay_to_restart(&self) -> Option<::core::time::Duration> {
self.$inner.delay_to_restart()
}
fn max_rtt(&self) -> ::core::time::Duration {
self.$inner.max_rtt()
}
fn transmit_wait_duration(&self) -> ::core::time::Duration {
self.$inner.transmit_wait_duration()
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! send_desc_passthru_options {
($inner:tt) => {
fn write_options(
&self,
msg: &mut dyn OptionInsert,
socket_addr: &IC::SocketAddr,
start: Bound<OptionNumber>,
end: Bound<OptionNumber>,
) -> Result<(), Error> {
self.$inner.write_options(msg, socket_addr, start, end)
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! send_desc_passthru_handler {
($inner:tt, $rt:ty) => {
fn supports_option(&self, option: OptionNumber) -> bool {
self.$inner.supports_option(option)
}
fn handler(&mut self, context: Result<&IC, Error>) -> Result<ResponseStatus<$rt>, Error> {
self.$inner.handler(context)
}
};
($inner:tt) => {
send_desc_passthru_handler!($inner, ());
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! send_desc_passthru_supports_option {
($inner:tt) => {
fn supports_option(&self, option: OptionNumber) -> bool {
self.$inner.supports_option(option)
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! send_desc_passthru_payload {
($inner:tt) => {
fn write_payload(
&self,
msg: &mut dyn MessageWrite,
socket_addr: &IC::SocketAddr,
) -> Result<(), Error> {
self.$inner.write_payload(msg, socket_addr)
}
}
}