libcoap_rs/
event.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright © The libcoap-rs Contributors, all rights reserved.
 * This file is part of the libcoap-rs project, see the README file for
 * general information on this project and the NOTICE.md and LICENSE files
 * for information regarding copyright ownership and terms of use.
 *
 * event.rs - Event handling traits and logic for the libcoap Rust wrapper.
 */

//! Event handling-related code

use std::fmt::Debug;

use libcoap_sys::{
    coap_event_t, coap_event_t_COAP_EVENT_SERVER_SESSION_NEW, coap_event_t_COAP_EVENT_TCP_CONNECTED,
    coap_session_get_context, coap_session_get_type, coap_session_t, coap_session_type_t_COAP_SESSION_TYPE_SERVER,
};

use crate::{
    context::CoapContext,
    session::{CoapServerSession, CoapSession},
};

/// Trait for CoAP event handlers.
///
/// Implementations of this trait can be provided to a [CoapContext] to handle various events relating
/// to sessions.
///
/// This is the equivalent to the [libcoap `coap_event_handler_t` type](https://libcoap.net/doc/reference/develop/group__events.html#ga5d57fba7df54eae6f8cb3a47a4cb3569).
pub trait CoapEventHandler: Debug {
    /// Handle a DTLS connected event.
    ///
    /// This event is triggered when a DTLS session switches to the connected state.
    #[allow(unused_variables)]
    fn handle_dtls_connected(&mut self, session: &mut CoapSession) {}

    /// Handle a DTLS closed event.
    ///
    /// This event is triggered when a DTLS session is closed.
    #[allow(unused_variables)]
    fn handle_dtls_closed(&mut self, session: &mut CoapSession) {}

    /// Handle a DTLS renegotiation event.
    ///
    /// This event is triggered when a DTLS renegotiation occurs.
    #[allow(unused_variables)]
    fn handle_dtls_renegotiate(&mut self, session: &mut CoapSession) {}

    /// Handle a DTLS error event.
    ///
    /// This event is triggered when a DTLS error occurs.
    #[allow(unused_variables)]
    fn handle_dtls_error(&mut self, session: &mut CoapSession) {}

    /// Handle a TCP connected event.
    ///
    /// This event is triggered when a new TCP connection is established.
    #[allow(unused_variables)]
    fn handle_tcp_connected(&mut self, session: &mut CoapSession) {}

    /// Handle a TCP closed event.
    ///
    /// This event is triggered when a new TCP connection is closed.
    #[allow(unused_variables)]
    fn handle_tcp_closed(&mut self, session: &mut CoapSession) {}

    /// Handle a TCP failed event.
    #[allow(unused_variables)]
    fn handle_tcp_failed(&mut self, session: &mut CoapSession) {}

    /// Handle a session connected event.
    ///
    /// This event is triggered by CSM exchanges only when reliable protocols are used.
    #[allow(unused_variables)]
    fn handle_session_connected(&mut self, session: &mut CoapSession) {}

    /// Handle a session closed event.
    ///
    /// This event is triggered by CSM exchanges only when reliable protocols are used.
    #[allow(unused_variables)]
    fn handle_session_closed(&mut self, session: &mut CoapSession) {}

    /// Handle a session failed event.
    ///
    /// This event is triggered by CSM exchanges only when reliable protocols are used.
    #[allow(unused_variables)]
    fn handle_session_failed(&mut self, session: &mut CoapSession) {}

    /// Handle a partially received message.
    #[allow(unused_variables)]
    fn handle_partial_block(&mut self, session: &mut CoapSession) {}

    /// Handle a failure to transmit a block.
    #[allow(unused_variables)]
    fn handle_xmit_block_fail(&mut self, session: &mut CoapSession) {}

    /// Handle the creation of a new server-side session.
    ///
    /// This event is called inside the IO loop when a new server-side session is created.
    #[allow(unused_variables)]
    fn handle_server_session_new(&mut self, session: &mut CoapServerSession) {}

    /// Handle the deletion of a server-side session.
    ///
    /// This event is called inside of the IO loop when a server-side session is deleted.
    /// This can happen for a number of reasons:
    /// - The session has been idle for too long (see [CoapContext::session_timeout()] and
    ///   [CoapContext::set_session_timeout()])
    /// - The maximum number of handshaking sessions is exceeded (see
    ///   [CoapContext::max_handshake_sessions()] and [CoapContext::set_max_handshake_sessions()])
    /// - The maximum number of idle sessions is exceeded (see
    ///   [CoapContext::max_idle_sessions()] and [CoapContext::set_max_idle_sessions()])
    #[allow(unused_variables)]
    fn handle_server_session_del(&mut self, session: &mut CoapServerSession) {}

    /// Handle the receival of a badly formatted packet.
    ///
    /// Note that this only refers to packets that can't be parsed by libcoap, i.e. valid packets
    /// that have some semantic issues and therefore can't be parsed into a request or response
    /// object do not trigger this event.
    #[allow(unused_variables)]
    fn handle_bad_packet(&mut self, session: &mut CoapSession) {}

    /// Handle a retransmission event.
    #[allow(unused_variables)]
    fn handle_msg_retransmitted(&mut self, session: &mut CoapSession) {}

    /// Handle an OSCORE decryption failure event.
    #[allow(unused_variables)]
    fn handle_oscore_decryption_failure(&mut self, session: &mut CoapSession) {}

    /// Handle an OSCORE not enabled event.
    #[allow(unused_variables)]
    fn handle_oscore_not_enabled(&mut self, session: &mut CoapSession) {}

    /// Handle an OSCORE no protected payload provided event.
    #[allow(unused_variables)]
    fn handle_oscore_no_protected_payload(&mut self, session: &mut CoapSession) {}

    /// Handle an OSCORE no security definition found event.
    #[allow(unused_variables)]
    fn handle_oscore_no_security(&mut self, session: &mut CoapSession) {}

    /// Handle an OSCORE internal error.
    #[allow(unused_variables)]
    fn handle_oscore_internal_error(&mut self, session: &mut CoapSession) {}

    /// Handle a decoding error when parsing OSCORE options.
    #[allow(unused_variables)]
    fn handle_oscore_decode_error(&mut self, session: &mut CoapSession) {}

    /// Handle an oversized WebSocket packet event.
    #[allow(unused_variables)]
    fn handle_ws_packet_size(&mut self, session: &mut CoapSession) {}

    /// Handle a WebSocket layer up event.
    #[allow(unused_variables)]
    fn handle_ws_connected(&mut self, session: &mut CoapSession) {}

    /// Handle a WebSocket layer closed event.

    #[allow(unused_variables)]
    fn handle_ws_closed(&mut self, session: &mut CoapSession) {}

    /// Handle a failure to perform a keepalive (no response to keepalive packet)
    #[allow(unused_variables)]
    fn handle_keepalive_failure(&mut self, session: &mut CoapSession) {}
}

// This should be fine as we don't provide this type to an FFI function, we only read from it.
#[allow(improper_ctypes_definitions)]
pub(crate) unsafe extern "C" fn event_handler_callback(raw_session: *mut coap_session_t, event: coap_event_t) -> i32 {
    let raw_session_type = coap_session_get_type(raw_session);

    let session: CoapSession = if event == coap_event_t_COAP_EVENT_SERVER_SESSION_NEW
        || (event == coap_event_t_COAP_EVENT_TCP_CONNECTED
            && raw_session_type == coap_session_type_t_COAP_SESSION_TYPE_SERVER)
    {
        CoapServerSession::initialize_raw(raw_session).into()
    } else {
        CoapSession::from_raw(raw_session)
    };

    // SAFETY: Pointer is always valid as long as there is no bug in libcoap.
    let context = CoapContext::from_raw(coap_session_get_context(raw_session));
    context.handle_event(session, event);
    0
}