async_coap/send_desc/
unicast_block2.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
16use super::*;
17use crate::message::{OwnedImmutableMessage, VecMessageEncoder};
18use std::marker::PhantomData;
19
20impl<SD: SendDescUnicast, IC> SendDescUnicast for UnicastBlock2<SD, IC> {}
21impl<SD: SendDescUnicast, IC> SendDescUnicast for UnicastBlock2Collect<SD, IC> {}
22
23/// Unicast Block2 Tracking combinator, created by [`SendDescUnicast::block2`].
24///
25#[derive(Debug)]
26pub struct UnicastBlock2<SD, IC> {
27    pub(super) inner: SD,
28    pub(super) block2_default: Option<BlockInfo>,
29    pub(super) reconstructor: Option<BlockReconstructor<VecMessageEncoder>>,
30    pub(super) etag: Option<ETag>,
31    pub(super) phantom: PhantomData<IC>,
32}
33
34impl<SD, IC> UnicastBlock2<SD, IC> {
35    pub(super) fn new(inner: SD, block2: Option<BlockInfo>) -> UnicastBlock2<SD, IC> {
36        UnicastBlock2 {
37            inner,
38            block2_default: block2,
39            reconstructor: None,
40            etag: None,
41            phantom: PhantomData,
42        }
43    }
44
45    /// Adds Block2 collection support to this [`SendDesc`] chain.
46    ///
47    /// This may only follow a [`UnicastBlock2`], and the prior return type
48    /// must be `()` (the default).
49    pub fn emit_successful_collected_response(self) -> UnicastBlock2Collect<SD, IC> {
50        UnicastBlock2Collect { inner: self }
51    }
52}
53
54impl<SD, IC, R> SendDesc<IC, R> for UnicastBlock2<SD, IC>
55where
56    SD: SendDesc<IC, R> + Send + SendDescUnicast,
57    IC: InboundContext,
58    R: Send,
59{
60    send_desc_passthru_timing!(inner);
61    send_desc_passthru_payload!(inner);
62
63    fn supports_option(&self, option: OptionNumber) -> bool {
64        self.inner.supports_option(option) || option == OptionNumber::BLOCK2
65    }
66
67    fn write_options(
68        &self,
69        msg: &mut dyn OptionInsert,
70        socket_addr: &IC::SocketAddr,
71        start: Bound<OptionNumber>,
72        end: Bound<OptionNumber>,
73    ) -> Result<(), Error> {
74        let block2 = self
75            .reconstructor
76            .as_ref()
77            .map(|r| r.next_block())
78            .or(self.block2_default);
79
80        write_options!((msg, socket_addr, start, end, self.inner) {
81        // Commenting this out for now because coap.me seems to be broken?
82        //            ETAG => self.etag.into_iter(),
83                    BLOCK2 => block2.into_iter(),
84                })
85    }
86
87    fn handler(&mut self, context: Result<&IC, Error>) -> Result<ResponseStatus<R>, Error> {
88        if let Some(context) = context.ok() {
89            if context.is_dupe() {
90                // Ignore dupes.
91                return Ok(ResponseStatus::Continue);
92            }
93            let msg = context.message();
94            let block2 = msg.block2();
95
96            if let Some(block2) = block2 {
97                let etag = msg.options().find_next_of(option::ETAG).transpose()?;
98
99                if etag != self.etag {
100                    if self.etag.is_none() && self.reconstructor.is_none() {
101                        self.etag = etag;
102                    } else {
103                        // Etag mismatch
104                        self.reconstructor = None;
105                        self.etag = None;
106                        return self.inner.handler(Err(Error::Reset));
107                    }
108                }
109
110                if self.reconstructor.is_none() {
111                    let mut encoder = VecMessageEncoder::default();
112                    msg.write_msg_to(&mut encoder)?;
113
114                    if !block2.more_flag() || block2.offset() != 0 {
115                        // Bad initial block2?
116                        return self.inner.handler(Ok(context));
117                    }
118
119                    let next_block = block2.next().unwrap();
120                    self.reconstructor = Some(BlockReconstructor::new(encoder, next_block));
121                }
122
123                match self
124                    .reconstructor
125                    .as_mut()
126                    .unwrap()
127                    .feed(block2, msg.payload())
128                {
129                    Ok(false) => {
130                        return self
131                            .inner
132                            .handler(Ok(context))
133                            .map(|_| ResponseStatus::SendNext)
134                    }
135                    Ok(true) => return self.inner.handler(Ok(context)),
136                    Err(_) => {
137                        self.reconstructor = None;
138                        self.etag = None;
139                        return self.inner.handler(Err(Error::Reset));
140                    }
141                };
142            } else {
143                self.reconstructor = None;
144                self.etag = None;
145            }
146        }
147
148        self.inner.handler(context)
149    }
150}
151
152/// Unicast Block2 Collecting combinator, created by [`UnicastBlock2::emit_successful_collected_response`].
153///
154/// This `SendDesc` will collect all of the various pieces and emit a single allocated
155/// [`MessageRead`] instance that contains the entire payload.
156#[derive(Debug)]
157pub struct UnicastBlock2Collect<SD, SA> {
158    inner: UnicastBlock2<SD, SA>,
159}
160
161impl<SD, IC> SendDesc<IC, OwnedImmutableMessage> for UnicastBlock2Collect<SD, IC>
162where
163    SD: SendDesc<IC, ()> + Send + SendDescUnicast,
164    IC: InboundContext,
165{
166    send_desc_passthru_timing!(inner);
167    send_desc_passthru_payload!(inner);
168    send_desc_passthru_options!(inner);
169    send_desc_passthru_supports_option!(inner);
170
171    fn handler(
172        &mut self,
173        context: Result<&IC, Error>,
174    ) -> Result<ResponseStatus<OwnedImmutableMessage>, Error> {
175        let ret = match self.inner.handler(context) {
176            Ok(rs) => {
177                if let Some(recons) = self.inner.reconstructor.as_ref() {
178                    if recons.is_finished() {
179                        self.inner.reconstructor.take().unwrap().into_inner().into()
180                    } else {
181                        return Ok(match rs {
182                            ResponseStatus::SendNext => ResponseStatus::SendNext,
183                            _ => ResponseStatus::Continue,
184                        });
185                    }
186                } else if let Some(context) = context.ok() {
187                    context.message().to_owned()
188                } else {
189                    return Ok(match rs {
190                        ResponseStatus::SendNext => ResponseStatus::SendNext,
191                        _ => ResponseStatus::Continue,
192                    });
193                }
194            }
195            Err(Error::ClientRequestError) if context.is_ok() => {
196                context.unwrap().message().to_owned()
197            }
198            Err(e) => return Err(e),
199        };
200
201        return Ok(ResponseStatus::Done(ret));
202    }
203}