1
// SPDX-License-Identifier: BSD-2-Clause
2
/*
3
 * event.rs - Event handling traits and logic for the libcoap Rust Wrapper.
4
 * This file is part of the libcoap-rs crate, see the README and LICENSE files for
5
 * more information and terms of use.
6
 * Copyright © 2021-2023 The NAMIB Project Developers, all rights reserved.
7
 * See the README as well as the LICENSE file for more information.
8
 */
9

            
10
//! Event handling-related code
11

            
12
use std::fmt::Debug;
13

            
14
use libcoap_sys::{coap_event_t, coap_session_get_context, coap_session_t};
15
use libcoap_sys::{coap_session_get_type, coap_session_type_t};
16

            
17
use crate::context::CoapContext;
18
use crate::session::CoapSession;
19

            
20
use crate::session::CoapServerSession;
21

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
150

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

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

            
159
    /// Handle a WebSocket layer closed event.
160

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

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

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

            
174
559
    let session: CoapSession = if event == coap_event_t::COAP_EVENT_SERVER_SESSION_NEW
175
326
        || (event == coap_event_t::COAP_EVENT_TCP_CONNECTED
176
70
            && raw_session_type == coap_session_type_t::COAP_SESSION_TYPE_SERVER)
177
    {
178
268
        CoapServerSession::initialize_raw(raw_session).into()
179
    } else {
180
291
        CoapSession::from_raw(raw_session)
181
    };
182

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