Skip to content

Commit 87f33b8

Browse files
committed
start of gcoap rework
1 parent 96467a7 commit 87f33b8

File tree

1 file changed

+100
-4
lines changed

1 file changed

+100
-4
lines changed

src/gcoap.rs

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,109 @@
1-
use riot_sys::libc::{c_uint, c_void, CStr};
1+
// There is some questionably scoped code in the lower half of this module (it made requirements on
2+
// data staying in a place that was not justified from the type system). This is being changed.
3+
4+
use riot_sys::{coap_resource_t, gcoap_listener_t, coap_pkt_t};
5+
use riot_sys::libc::{CStr, c_void};
6+
use core::marker::PhantomData;
7+
8+
/// Give the caller a way of registering Gcoap handlers into the global Gcoap registry inside a
9+
/// callback. When the callback terminates, the registered handlers are deregistered again,
10+
/// theoretically allowing the registration of non-'static handlers.
11+
///
12+
/// As there is currently no way to unregister handlers, this function panics when the callback
13+
/// terminates.
14+
pub fn scope<F>(callback: F)
15+
where
16+
F: FnOnce(&mut RegistrationScope)
17+
{
18+
let mut r = RegistrationScope { _private: () };
19+
20+
callback(&mut r);
21+
22+
r.deregister_all();
23+
}
24+
25+
// Could we allow users the creation of 'static RegistrationScopes? Like thread::spawn.
26+
pub struct RegistrationScope {
27+
_private: ()
28+
}
29+
30+
impl RegistrationScope {
31+
// FIXME: Generalize SingleHandlerListener::get_listener into a trait
32+
pub fn register<'scope, 'handler: 'scope, H: Handler>(&'scope mut self, handler: &'handler mut SingleHandlerListener<'handler, H>) {
33+
// Unsafe: Moving in a pointer to an internal structure to which we were given an exclusive
34+
// reference that outlives self -- and whoever can create a Self guarantees that
35+
// deregister_all() will be called before the end of this self's lifetime.
36+
unsafe { gcoap_register_listener(handler.get_listener()) };
37+
}
38+
39+
fn deregister_all(&mut self) {
40+
panic!("Registration callback returned, but Gcoap does not allow deregistration.");
41+
}
42+
}
43+
44+
pub struct SingleHandlerListener<'a, H> {
45+
_phantom: PhantomData<&'a H>,
46+
resource: coap_resource_t,
47+
listener: gcoap_listener_t,
48+
}
49+
50+
impl<'a, H> SingleHandlerListener<'a, H>
51+
where
52+
H: 'a + Handler
53+
{
54+
pub fn new(path: &'a CStr, handler: &'a mut H) -> Self
55+
{
56+
SingleHandlerListener {
57+
_phantom: PhantomData,
58+
resource: coap_resource_t {
59+
path: path.as_ptr(),
60+
handler: Some(Self::call_handler),
61+
methods: 0xff, // A good handler checks anyway
62+
context: handler as *mut _ as *mut c_void,
63+
},
64+
listener: gcoap_listener_t {
65+
resources: 0 as *const _,
66+
resources_len: 0,
67+
next: 0 as *mut _,
68+
}
69+
}
70+
}
71+
72+
pub fn get_listener(&mut self) -> *mut gcoap_listener_t {
73+
self.listener.resources = &self.resource;
74+
self.listener.resources_len = 1;
75+
self.listener.next = 0 as *mut _;
76+
77+
&mut self.listener as *mut _
78+
}
79+
80+
81+
unsafe extern "C" fn call_handler(
82+
pkt: *mut coap_pkt_t,
83+
buf: *mut u8,
84+
len: usize,
85+
context: *mut c_void,
86+
) -> isize {
87+
let h = context as *mut H;
88+
let h = &mut *h;
89+
let mut pb = PacketBuffer { pkt, buf, len };
90+
H::handle(h, &mut pb)
91+
}
92+
}
93+
94+
pub trait Handler {
95+
fn handle(&mut self, pkt: &mut PacketBuffer) -> isize;
96+
}
97+
98+
// Questionable code starts here
99+
100+
use riot_sys::libc::{c_uint};
2101
use riot_sys::{
3102
coap_get_blockopt,
4103
coap_hdr_t,
5104
coap_opt_add_uint,
6105
coap_opt_finish,
7-
coap_pkt_t,
8-
coap_resource_t,
9106
gcoap_finish,
10-
gcoap_listener_t,
11107
gcoap_register_listener,
12108
gcoap_resp_init,
13109
memmove,

0 commit comments

Comments
 (0)