|
16 | 16 | */
|
17 | 17 |
|
18 | 18 | use crate::data_model::{core::DataModel, objects::*};
|
| 19 | +use crate::transport::packet::Packet; |
| 20 | +use crate::utils::writebuf::WriteBuf; |
19 | 21 | use crate::{
|
20 | 22 | acl::{AccessReq, Accessor},
|
21 | 23 | error::*,
|
@@ -104,12 +106,7 @@ impl<'a, 'b, 'c> Encoder for AttrReadEncoder<'a, 'b, 'c> {
|
104 | 106 | pub struct ResumeReadReq {
|
105 | 107 | /// The Read Request Attribute Path that caused chunking, and this is the path
|
106 | 108 | /// that needs to be resumed.
|
107 |
| - /// |
108 |
| - /// TODO: Ideally, the entire ReadRequest (with any subsequent AttrPaths) should also |
109 |
| - /// be maintained. But for now, we just store the AttrPath that caused the overflow |
110 |
| - /// and chunking. Hopefully, the other end requests any pending paths when it sees no |
111 |
| - /// more chunks. |
112 |
| - pending_path: GenericPath, |
| 109 | + pending_req: Option<Packet<'static>>, |
113 | 110 |
|
114 | 111 | /// The Attribute that couldn't be encoded because our buffer got full. The next chunk
|
115 | 112 | /// will start encoding from this attribute onwards.
|
@@ -198,7 +195,7 @@ impl DataModel {
|
198 | 195 | read_req: &ReadReq,
|
199 | 196 | trans: &mut Transaction,
|
200 | 197 | tw: &mut TLVWriter,
|
201 |
| - ) -> Result<bool, Error> { |
| 198 | + ) -> Result<Option<ResumeReadReq>, Error> { |
202 | 199 | let mut resume_read_req: ResumeReadReq = Default::default();
|
203 | 200 |
|
204 | 201 | let mut attr_encoder = AttrReadEncoder::new(tw);
|
@@ -226,19 +223,31 @@ impl DataModel {
|
226 | 223 | &mut attr_details,
|
227 | 224 | &mut resume_read_req.resume_encode,
|
228 | 225 | );
|
229 |
| - if result.is_err() { |
230 |
| - resume_read_req.pending_path = attr_path.to_gp(); |
231 |
| - break; |
232 |
| - } |
233 | 226 | }
|
234 | 227 | tw.end_container()?;
|
235 | 228 | if result.is_err() {
|
236 | 229 | // If there was an error, indicate chunking. The resume_read_req would have been
|
237 | 230 | // already populated from in the loop above.
|
238 | 231 | tw.bool(TagType::Context(MoreChunkedMsgs as u8), true)?;
|
239 |
| - return Ok(true); |
| 232 | + // Retain the entire request, because we need the data-filters, and subsequent attr-reads, if any |
| 233 | + // when we resume this read in the next hop |
| 234 | + resume_read_req.pending_req = Some(copy_read_req_to_packet(read_req)?); |
| 235 | + return Ok(Some(resume_read_req)); |
240 | 236 | }
|
241 | 237 | }
|
242 |
| - Ok(false) |
| 238 | + Ok(None) |
243 | 239 | }
|
244 | 240 | }
|
| 241 | + |
| 242 | +fn copy_read_req_to_packet(read_req: &ReadReq) -> Result<Packet<'static>, Error> { |
| 243 | + let mut packet = Packet::new_rx()?; |
| 244 | + let backup = packet.as_borrow_slice(); |
| 245 | + let backup_len = backup.len(); |
| 246 | + let mut wb = WriteBuf::new(backup, backup_len); |
| 247 | + let mut tw = TLVWriter::new(&mut wb); |
| 248 | + // TODO: This is unnecessarily wasteful, could directly copy &[u8] if accessible |
| 249 | + read_req.to_tlv(&mut tw, TagType::Anonymous)?; |
| 250 | + let data_len = wb.as_borrow_slice().len(); |
| 251 | + packet.get_parsebuf()?.set_len(data_len); |
| 252 | + Ok(packet) |
| 253 | +} |
0 commit comments