coap_zero/endpoint/
connect.rs1use core::str::FromStr;
12
13use embedded_hal::blocking::rng;
14use embedded_nal::{AddrType, Dns, IpAddr, SocketAddr, UdpClientStack};
15use embedded_timers::clock::Clock;
16
17use super::{error::Error, CoapEndpoint, ConnectionLink, Uri};
18
19impl<
20 'a,
21 UDP,
22 RNG,
23 CLOCK,
24 const MAX_OPTION_COUNT: usize,
25 const MAX_OPTION_SIZE: usize,
26 const INCOMING_BUFFER_SIZE: usize,
27 const OUTGOING_BUFFER_SIZE: usize,
28 const RECEIVE_BUFFER_SIZE: usize,
29 >
30 CoapEndpoint<
31 'a,
32 UDP,
33 RNG,
34 CLOCK,
35 MAX_OPTION_COUNT,
36 MAX_OPTION_SIZE,
37 INCOMING_BUFFER_SIZE,
38 OUTGOING_BUFFER_SIZE,
39 RECEIVE_BUFFER_SIZE,
40 >
41where
42 UDP: UdpClientStack,
43 RNG: rng::Read,
44 CLOCK: Clock,
45{
46 pub fn connect_with_socket(
50 &mut self,
51 socket: UDP::UdpSocket,
52 addr: SocketAddr,
53 ) -> Result<(), Error<<UDP as UdpClientStack>::Error>> {
54 if self.connection_link.is_none() {
55 self.connection_link = Some(ConnectionLink { socket, addr });
56 Ok(())
57 } else {
58 Err(Error::AlreadyConnected)
59 }
60 }
61
62 pub fn connect_to_addr<'client>(
64 &mut self,
65 client: &'client mut UDP,
66 addr: SocketAddr,
67 ) -> Result<&'client mut UDP, Error<<UDP as UdpClientStack>::Error>> {
68 if self.connection_link.is_some() {
69 Err(Error::AlreadyConnected)
70 } else {
71 let mut socket = client.socket().map_err(Error::Network)?;
72 client.connect(&mut socket, addr).map_err(Error::Network)?;
73
74 self.connection_link = Some(ConnectionLink { socket, addr });
75
76 Ok(client)
77 }
78 }
79
80 pub fn close<'client>(
82 &mut self,
83 client: &'client mut UDP,
84 ) -> Result<&'client mut UDP, Error<<UDP as UdpClientStack>::Error>> {
85 if self.connection_link.is_none() {
86 Err(Error::NotConnected)
87 } else {
88 client
89 .close(self.connection_link.take().unwrap().socket)
90 .map_err(Error::Network)?;
91 self.connection_link = None;
92
93 Ok(client)
94 }
95 }
96}
97
98impl<
99 'a,
100 UDP,
101 RNG,
102 CLOCK,
103 const MAX_OPTION_COUNT: usize,
104 const MAX_OPTION_SIZE: usize,
105 const INCOMING_BUFFER_SIZE: usize,
106 const OUTGOING_BUFFER_SIZE: usize,
107 const RECEIVE_BUFFER_SIZE: usize,
108 >
109 CoapEndpoint<
110 'a,
111 UDP,
112 RNG,
113 CLOCK,
114 MAX_OPTION_COUNT,
115 MAX_OPTION_SIZE,
116 INCOMING_BUFFER_SIZE,
117 OUTGOING_BUFFER_SIZE,
118 RECEIVE_BUFFER_SIZE,
119 >
120where
121 UDP: UdpClientStack + Dns,
122 RNG: rng::Read,
123 CLOCK: Clock,
124{
125 pub fn connect_to_url(
132 &mut self,
133 client: &mut UDP,
134 url: &str,
135 ) -> Result<(), Error<<UDP as UdpClientStack>::Error>> {
136 if self.connection_link.is_some() {
137 return Err(Error::AlreadyConnected);
138 }
139
140 let uri = Uri::new(url).map_err(|_| Error::Uri)?;
141
142 let components = uri.authority_components().ok_or(Error::Uri)?;
143
144 let host = components.host();
145 let port = if let Some(port_str) = components.port() {
146 port_str.parse::<u16>().map_err(|_| Error::Uri)?
147 } else {
148 super::DEFAULT_COAP_PORT
149 };
150
151 let ip = if let Ok(ip) = IpAddr::from_str(host) {
152 ip
153 } else {
154 nb::block!(client.get_host_by_name(host, AddrType::Either)).unwrap()
155 };
156
157 let socket_addr = SocketAddr::new(ip, port);
158
159 self.connect_to_addr(client, socket_addr)?;
160
161 Ok(())
162 }
163}