Skip to content

Commit 443ff99

Browse files
committed
gcoap PacketBuffer: expose more gcoap/nanocoap functionality
This depends on RIOT-OS/RIOT#11386, and should receive some simplification when stepping up to current riot master.
1 parent ba135d4 commit 443ff99

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

src/gcoap.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ use riot_sys::{
137137
coap_get_blockopt,
138138
coap_hdr_t,
139139
coap_opt_add_uint,
140+
coap_opt_add_opaque,
140141
coap_opt_finish,
141142
gcoap_finish,
142143
gcoap_register_listener,
@@ -242,13 +243,97 @@ impl<'a> ::core::fmt::Write for BlockWriter<'a> {
242243
/// A representation of the incoming or outgoing data on the server side of a request. This
243244
/// includes the coap_pkt_t pre-parsed header and option pointers as well as the memory area
244245
/// dedicated to returning the packet.
246+
#[derive(Debug)]
245247
pub struct PacketBuffer {
246248
pkt: *mut coap_pkt_t,
247249
buf: *mut u8,
248250
len: usize,
249251
}
250252

251253
impl PacketBuffer {
254+
pub fn get_code_raw(&self) -> u8 {
255+
// FIXME inlining static coap_get_code_detail
256+
unsafe { (*(*self.pkt).hdr).code }
257+
}
258+
259+
fn get_total_hdr_len(&self) -> usize {
260+
unsafe { coap_get_total_hdr_len(&*self.pkt) }
261+
}
262+
263+
/// Take a message that came in as a request and configure it such that options and payload can
264+
/// be added. The response code is set to 5.00 Internal Server Error as a precaution.
265+
///
266+
/// This is similar to gcoap_resp_init, but does not try to reserve any space for options.
267+
///
268+
/// The options list is set to empty, and the available payload is configured to span the
269+
/// complete available buffer right after the header. Subsequent opt_add_* invocations can then
270+
/// push back the buffer.
271+
pub fn prepare_response(&mut self) {
272+
unsafe {
273+
let hdr: &mut coap_hdr_t = &mut *(*self.pkt).hdr;
274+
if (hdr.ver_t_tkl & 0x30) >> 4 == COAP_TYPE_CON as u8 {
275+
hdr.ver_t_tkl = hdr.ver_t_tkl & 0xcf | ((COAP_TYPE_ACK as u8) << 4);
276+
}
277+
hdr.code = 5 << 5;
278+
}
279+
280+
let hdrlen = self.get_total_hdr_len();
281+
unsafe {
282+
(*self.pkt).payload = self.buf.offset(hdrlen as isize);
283+
(*self.pkt).payload_len = self.len.saturating_sub(hdrlen) as u16;
284+
(*self.pkt).options_len = 0;
285+
}
286+
}
287+
288+
pub fn set_code_raw(&mut self, code: u8) {
289+
unsafe { (*(*self.pkt).hdr).code = code };
290+
}
291+
292+
/// Return the total number of bytes in the message, given that `payload_used` bytes were
293+
/// written at the payload pointer. Note that those bytes have to include the payload marker.
294+
///
295+
/// This measures the distance between the payload pointer in the pkt and the start of the
296+
/// buffer. It is the header length after `prepare_response`, and grows as options are added.
297+
pub fn get_length(&self, payload_used: usize) -> usize {
298+
let own_length = unsafe { (*self.pkt).payload.offset_from(self.buf) };
299+
assert!(own_length >= 0);
300+
let total_length = own_length as usize + payload_used;
301+
assert!(total_length <= self.len);
302+
total_length
303+
}
304+
305+
/// A view of the current message payload
306+
pub fn payload(&self) -> &[u8] {
307+
unsafe {
308+
core::slice::from_raw_parts((*self.pkt).payload, (*self.pkt).payload_len as usize)
309+
}
310+
}
311+
312+
/// A view of the current message payload
313+
pub fn payload_mut(&mut self) -> &mut [u8] {
314+
unsafe {
315+
core::slice::from_raw_parts_mut((*self.pkt).payload, (*self.pkt).payload_len as usize)
316+
}
317+
}
318+
319+
/// Add an integer value as an option
320+
pub fn opt_add_uint(&mut self, optnum: u16, value: u32) -> Result<(), ()> {
321+
if unsafe { coap_opt_add_uint(self.pkt, optnum, value) } < 0 {
322+
Err(())
323+
} else {
324+
Ok(())
325+
}
326+
}
327+
328+
/// Add a binary value as an option
329+
pub fn opt_add_opaque(&mut self, optnum: u16, data: &[u8]) -> Result<(), ()> {
330+
if unsafe { coap_opt_add_opaque(self.pkt, optnum, data.as_ptr(), data.len()) } < 0 {
331+
Err(())
332+
} else {
333+
Ok(())
334+
}
335+
}
336+
252337
pub fn response(
253338
&mut self,
254339
code: u32,
@@ -304,7 +389,7 @@ impl PacketBuffer {
304389
}
305390
hdr.code = code as u8;
306391

307-
let headroom = coap_get_total_hdr_len(&*self.pkt) + 25 /* used to be 8 */;
392+
let headroom = self.get_total_hdr_len() + 25 /* used to be 8 */;
308393
(*self.pkt).payload = self.buf.offset(headroom as isize);
309394
(*self.pkt).payload_len = self.len as u16 - headroom as u16;
310395
}

0 commit comments

Comments
 (0)