1
// SPDX-License-Identifier: BSD-2-Clause
2
/*
3
 * Copyright © The libcoap-rs Contributors, all rights reserved.
4
 * This file is part of the libcoap-rs project, see the README file for
5
 * general information on this project and the NOTICE.md and LICENSE files
6
 * for information regarding copyright ownership and terms of use.
7
 *
8
 * event.rs - Event handling traits and logic for the libcoap Rust wrapper.
9
 */
10

            
11
//! Event handling-related code
12

            
13
use std::fmt::Debug;
14

            
15
use libcoap_sys::{
16
    coap_event_t, coap_event_t_COAP_EVENT_SERVER_SESSION_NEW, coap_event_t_COAP_EVENT_TCP_CONNECTED,
17
    coap_session_get_context, coap_session_get_type, coap_session_t, coap_session_type_t_COAP_SESSION_TYPE_SERVER,
18
};
19

            
20
use crate::{
21
    context::CoapContext,
22
    session::{CoapServerSession, CoapSession},
23
};
24

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
161
    /// Handle a WebSocket layer closed event.
162

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

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

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

            
176
559
    let session: CoapSession = if event == coap_event_t_COAP_EVENT_SERVER_SESSION_NEW
177
326
        || (event == coap_event_t_COAP_EVENT_TCP_CONNECTED
178
70
            && raw_session_type == coap_session_type_t_COAP_SESSION_TYPE_SERVER)
179
    {
180
268
        CoapServerSession::initialize_raw(raw_session).into()
181
    } else {
182
291
        CoapSession::from_raw(raw_session)
183
    };
184

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