1
// SPDX-License-Identifier: BSD-2-Clause
2
/*
3
 * error.rs - CoAP error types.
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
//! Error types
11

            
12
use std::ffi::NulError;
13
use std::string::FromUtf8Error;
14
use std::sync::PoisonError;
15

            
16
use thiserror::Error;
17

            
18
use crate::protocol::{CoapMessageType, CoapOptionType};
19

            
20
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
21
pub enum EndpointCreationError {
22
    /// Unknown error inside of libcoap
23
    #[error("CoAP endpoint creation error: unknown error in call to libcoap")]
24
    Unknown,
25
}
26

            
27
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
28
pub enum ContextConfigurationError {
29
    /// Unknown error inside of libcoap
30
    #[error("CoAP context configuration error: unknown error in call to libcoap")]
31
    Unknown,
32
    #[error(
33
        "CoAP context configuration error: attempted to set encryption context while one has already been configured for this encryption variant"
34
    )]
35
    CryptoContextAlreadySet,
36
}
37

            
38
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
39
pub enum MessageCreationError {
40
    /// Unknown error inside of libcoap
41
    #[error("CoAP message creation error: unknown error in call to libcoap")]
42
    Unknown,
43
}
44

            
45
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
46
pub enum IoProcessError {
47
    /// Unknown error inside of libcoap
48
    #[error("CoAP IO error: unknown error in call to libcoap")]
49
    Unknown,
50
}
51

            
52
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
53
pub enum SessionGetAppDataError {
54
    /// Stored application data type differs from requested type
55
    #[error("CoAP application data retrieval error: wrong type")]
56
    WrongType,
57
}
58

            
59
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
60
pub enum OptionCreationError {
61
    /// Unknown error inside of libcoap
62
    #[error("CoAP option creation error: unknown error in call to libcoap")]
63
    Unknown,
64
}
65

            
66
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
67
pub enum SessionCreationError {
68
    /// Unknown error inside of libcoap
69
    #[error("CoAP session creation error: unknown error in call to libcoap")]
70
    Unknown,
71
}
72

            
73
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
74
pub enum UnknownOptionError {
75
    /// Unknown error inside of libcoap
76
    #[error("CoAP option conversion error: unknown option")]
77
    Unknown,
78
}
79

            
80
#[derive(Error, Debug)]
81
pub enum RngError {
82
    /// Unknown error inside of libcoap
83
    #[error("CoAP RNG error: unknown error in call to libcoap")]
84
    Unknown,
85
    /// RNG mutex is poisoned (panic in another thread while calling RNG function).
86
    #[error("CoAP RNG configuration error: global RNG mutex is poisoned")]
87
    GlobalMutexPoisonError,
88
}
89

            
90
impl<T> From<PoisonError<T>> for RngError {
91
    fn from(_value: PoisonError<T>) -> Self {
92
        RngError::GlobalMutexPoisonError
93
    }
94
}
95

            
96
#[derive(Error, Debug, Clone, Eq, PartialEq)]
97
pub enum OptionValueError {
98
    /// Provided value for option is too short.
99
    #[error("CoAP option has invalid value: too short")]
100
    TooShort,
101
    /// Provided value for option is too long.
102
    #[error("CoAP option has invalid value: too long")]
103
    TooLong,
104
    /// A string value could not be converted to UTF-8.
105
    #[error("CoAP option has invalid value: invalid string")]
106
    StringConversion(#[from] FromUtf8Error),
107
    /// URI encoded in message could not be parsed.
108
    #[error("CoAP option has invalid value: invalid URI")]
109
    UriParsing(#[from] UriParsingError),
110
    /// Option has an illegal value.
111
    #[error("CoAP option has invalid value")]
112
    IllegalValue,
113
}
114

            
115
#[derive(Error, Debug, Clone, Eq, PartialEq)]
116
pub enum UriParsingError {
117
    /// Unknown error inside of libcoap
118
    #[error("CoAP option creation error: unknown error in call to libcoap")]
119
    Unknown,
120
    /// URI does not have a valid scheme for libcoap (coap, coaps, coap+tcp, coaps+tcp, http, https).
121
    #[error("URI scheme {} is not a valid CoAP scheme known to libcoap", .0)]
122
    NotACoapScheme(String),
123
    /// Provided URI contains a null byte.
124
    #[error("Provided URI contains a null byte")]
125
    ContainsNullByte(#[from] NulError),
126
}
127

            
128
#[derive(Error, Debug, Clone, Eq, PartialEq)]
129
pub enum MessageConversionError {
130
    /// Value of an option is invalid.
131
    #[error("CoAP message conversion error: invalid option value for {:?}", .0)]
132
    InvalidOptionValue(Option<CoapOptionType>, #[source] OptionValueError),
133
    /// Message has an option that is specific for another message type (i.e., request option in
134
    /// response message).
135
    #[error("CoAP message conversion error: option of type {:?} invalid for message type", .0)]
136
    InvalidOptionForMessageType(CoapOptionType),
137
    /// Non-repeatable option was repeated.
138
    #[error("CoAP message conversion error: non-repeatable option of type {:?} repeated", .0)]
139
    NonRepeatableOptionRepeated(CoapOptionType),
140
    /// Provided URI has invalid scheme.
141
    #[error("CoAP message conversion error: provided uri does not have scheme valid for CoAP")]
142
    NotACoapUri(UriParsingError),
143
    /// Invalid message code.
144
    #[error("CoAP message conversion error: invalid message code")]
145
    InvalidMessageCode(#[from] MessageCodeError),
146
    /// A message with code 0.00 (Empty) contains data.
147
    #[error("CoAP message conversion error: empty message contains data")]
148
    DataInEmptyMessage,
149
    /// Message has no token.
150
    #[error("CoAP message conversion error: token missing")]
151
    MissingToken,
152
    /// Message has no ID.
153
    #[error("CoAP message conversion error: message id missing")]
154
    MissingMessageId,
155
    /// Two (or more) options were combined which must not be combined (e.g., Proxy-Scheme and
156
    /// Proxy-URI).
157
    #[error("CoAP message conversion error: options {:?} and {:?} cannot be combined", .0, .1)]
158
    InvalidOptionCombination(CoapOptionType, CoapOptionType),
159
    /// A critical option (as defined in [RFC 7252](https://datatracker.ietf.org/doc/html/rfc7252#section-5.4.1)
160
    /// was not recognized).
161
    #[error("CoAP option identified as critical but not recognized")]
162
    CriticalOptionUnrecognized,
163
    /// Unknown error inside of libcoap.
164
    #[error("unknown CoAP message conversion error")]
165
    Unknown,
166
}
167

            
168
impl From<UriParsingError> for MessageConversionError {
169
    fn from(v: UriParsingError) -> Self {
170
        MessageConversionError::NotACoapUri(v)
171
    }
172
}
173

            
174
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
175
pub enum MessageCodeError {
176
    /// Provided message code for request was not a request code.
177
    #[error("CoAP message code conversion error: not a request code")]
178
    NotARequestCode,
179
    /// Provided message code for response was not a response code.
180
    #[error("CoAP message code conversion error: not a response code")]
181
    NotAResponseCode,
182
}
183

            
184
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
185
pub enum MessageTypeError {
186
    /// Message type cannot be used for this message code (e.g., ACK for request).
187
    #[error("message type {:?} cannot be used for this message code", .0)]
188
    InvalidForMessageCode(CoapMessageType),
189
}