async_coap/
null.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16//! NULL CoAP backend
17//!
18//! This is a CoAP back end that does nothing. It is used primarily for testing.
19use super::*;
20use crate::message::NullMessageRead;
21use crate::remote_endpoint::RemoteEndpoint;
22use futures::future::BoxFuture;
23use std::net::{IpAddr, Ipv4Addr};
24
25/// Concrete instance of [`LocalEndpoint::RespondableInboundContext`] for [`NullLocalEndpoint`].
26#[derive(Debug)]
27pub struct NullRespondableInboundContext
28where
29    Self: Send + Sync;
30impl RespondableInboundContext for NullRespondableInboundContext {
31    fn is_multicast(&self) -> bool {
32        false
33    }
34
35    fn is_fake(&self) -> bool {
36        false
37    }
38
39    fn respond<F>(&self, _msg_gen: F) -> Result<(), Error>
40    where
41        F: Fn(&mut dyn MessageWrite) -> Result<(), Error>,
42    {
43        Ok(())
44    }
45}
46impl InboundContext for NullRespondableInboundContext {
47    type SocketAddr = std::net::SocketAddr;
48
49    fn remote_socket_addr(&self) -> Self::SocketAddr {
50        Self::SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0)
51    }
52
53    fn is_dupe(&self) -> bool {
54        false
55    }
56
57    fn message(&self) -> &dyn MessageRead {
58        &NullMessageRead
59    }
60}
61
62/// Concrete instance of [`LocalEndpoint::InboundContext`] for [`NullLocalEndpoint`].
63#[derive(Debug)]
64pub struct NullInboundContext
65where
66    Self: Send + Sync;
67impl InboundContext for NullInboundContext {
68    type SocketAddr = std::net::SocketAddr;
69
70    fn remote_socket_addr(&self) -> Self::SocketAddr {
71        Self::SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0)
72    }
73
74    fn is_dupe(&self) -> bool {
75        false
76    }
77
78    fn message(&self) -> &dyn MessageRead {
79        &NullMessageRead
80    }
81}
82
83/// Concrete instance of [`LocalEndpoint::RemoteEndpoint`] for [`NullLocalEndpoint`].
84#[derive(Debug)]
85pub struct NullRemoteEndpoint
86where
87    Self: Send + Sync;
88
89impl RemoteEndpoint for NullRemoteEndpoint {
90    type SocketAddr = std::net::SocketAddr;
91    type InboundContext = NullInboundContext;
92
93    fn scheme(&self) -> &'static str {
94        "null"
95    }
96
97    fn uri(&self) -> UriBuf {
98        uri!("null:///").to_owned()
99    }
100
101    fn send<'a, R, SD>(&'a self, _send_desc: SD) -> BoxFuture<'_, Result<R, Error>>
102    where
103        SD: SendDesc<Self::InboundContext, R>,
104        R: Send + 'a,
105    {
106        futures::future::ready(Err(Error::ResponseTimeout)).boxed()
107    }
108
109    fn send_to<'a, R, SD, UF>(
110        &'a self,
111        _path: UF,
112        _send_desc: SD,
113    ) -> BoxFuture<'_, Result<R, Error>>
114    where
115        SD: SendDesc<Self::InboundContext, R> + 'a,
116        R: Send + 'a,
117        UF: AsRef<RelRef>,
118    {
119        futures::future::ready(Err(Error::ResponseTimeout)).boxed()
120    }
121
122    fn remove_host_option(&mut self) {}
123
124    fn clone_using_rel_ref(&self, _uri: &RelRef) -> Self {
125        NullRemoteEndpoint
126    }
127}
128
129/// A dummy endpoint implementation that doesn't do anything. Useful for testing.
130#[derive(Debug)]
131pub struct NullLocalEndpoint
132where
133    Self: Send + Sync;
134
135impl LocalEndpoint for NullLocalEndpoint {
136    type SocketAddr = std::net::SocketAddr;
137    type SocketError = std::io::Error;
138    type DefaultTransParams = StandardCoapConstants;
139
140    fn scheme(&self) -> &'static str {
141        URI_SCHEME_NULL
142    }
143
144    fn default_port(&self) -> u16 {
145        // Zero means ports are ignored.
146        0
147    }
148
149    type RemoteEndpoint = NullRemoteEndpoint;
150
151    fn remote_endpoint<S, H, P>(&self, _addr: S, _host: Option<H>, _path: P) -> Self::RemoteEndpoint
152    where
153        S: ToSocketAddrs<SocketAddr = Self::SocketAddr, Error = Self::SocketError>,
154        H: Into<String>,
155        P: Into<RelRefBuf>,
156    {
157        NullRemoteEndpoint
158    }
159
160    fn remote_endpoint_from_uri(&self, _uri: &Uri) -> Result<Self::RemoteEndpoint, Error> {
161        Ok(NullRemoteEndpoint)
162    }
163
164    type LookupStream = futures::stream::Iter<std::vec::IntoIter<Self::SocketAddr>>;
165
166    fn lookup(&self, _hostname: &str, mut _port: u16) -> Result<Self::LookupStream, Error> {
167        let dummy_iter = "127.0.0.1:12345".to_socket_addrs().unwrap();
168        Ok(futures::stream::iter(dummy_iter))
169    }
170
171    type InboundContext = NullInboundContext;
172
173    fn send<'a, S, R, SD>(&'a self, _dest: S, _send_desc: SD) -> BoxFuture<'a, Result<R, Error>>
174    where
175        S: ToSocketAddrs<SocketAddr = Self::SocketAddr, Error = Self::SocketError> + 'a,
176        SD: SendDesc<Self::InboundContext, R> + 'a,
177        R: Send + 'a,
178    {
179        futures::future::ready(Err(Error::ResponseTimeout)).boxed()
180    }
181
182    type RespondableInboundContext = NullRespondableInboundContext;
183
184    fn receive<'a, F>(&'a self, _handler: F) -> BoxFuture<'a, Result<(), Error>>
185    where
186        F: FnMut(&Self::RespondableInboundContext) -> Result<(), Error> + 'a,
187    {
188        futures::future::pending::<Result<(), Error>>().boxed()
189    }
190}
191
192#[cfg(test)]
193mod tests {
194    use super::*;
195    use futures::executor::block_on;
196    use std::net::SocketAddr;
197
198    #[test]
199    fn ping() {
200        let local_endpoint = NullLocalEndpoint;
201
202        let future = local_endpoint.send(
203            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1234),
204            Ping::new(),
205        );
206
207        assert_eq!(Err(Error::ResponseTimeout), block_on(future));
208    }
209}