Coverage for aiocoap/numbers/optionnumbers.py: 93%

94 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-16 16:09 +0000

1# SPDX-FileCopyrightText: Christian Amsüss and the aiocoap contributors 

2# 

3# SPDX-License-Identifier: MIT 

4 

5"""Known values for CoAP option numbers 

6 

7The values defined in `OptionNumber` correspond to the IANA registry "CoRE 

8Parameters", subregistries "CoAP Method Codes" and "CoAP Response Codes". 

9 

10The option numbers come with methods that can be used to evaluate their 

11properties, see the `OptionNumber` class for details. 

12""" 

13 

14from ..util import ExtensibleIntEnum 

15from .. import optiontypes 

16 

17class OptionNumber(ExtensibleIntEnum): 

18 """A CoAP option number. 

19 

20 As the option number contains information on whether the option is 

21 critical, and whether it is safe-to-forward, those properties can be 

22 queried using the `is_*` group of methods. 

23 

24 Note that whether an option may be repeated or not does not only depend on 

25 the option, but also on the context, and is thus handled in the `Options` 

26 object instead.""" 

27 IF_MATCH = 1 

28 URI_HOST = 3 

29 ETAG = 4 

30 IF_NONE_MATCH = 5 

31 OBSERVE = 6 

32 URI_PORT = 7 

33 LOCATION_PATH = 8 

34 # The OBJECT_SECURITY name is to be deprecated when Python 3.8 support is 

35 # dropped, and we can do that easily using a class property. 

36 OSCORE = OBJECT_SECURITY = 9 

37 URI_PATH = 11 

38 CONTENT_FORMAT = 12 

39 MAX_AGE = 14 

40 URI_QUERY = 15 

41 HOP_LIMIT = 16 

42 ACCEPT = 17 

43 Q_BLOCK1 = 19 

44 LOCATION_QUERY = 20 

45 EDHOC = 21 

46 BLOCK2 = 23 

47 BLOCK1 = 27 

48 SIZE2 = 28 

49 Q_BLOCK2 = 31 

50 PROXY_URI = 35 

51 PROXY_SCHEME = 39 

52 SIZE1 = 60 

53 ECHO = 252 

54 NO_RESPONSE = 258 

55 REQUEST_TAG = 292 

56 

57 # experimental for draft-amsuess-core-cachable-oscore 

58 # 

59 # Using the number suggested there (rather than a high one) as this is 

60 # going to be used in overhead comparisons. 

61 REQUEST_HASH = 548 

62 

63 def __add__(self, delta): 

64 """Addition makes sense on these due to the delta encoding in CoAP 

65 serialization""" 

66 return type(self)(int(self) + delta) 

67 

68 def is_critical(self): 

69 return self & 0x01 == 0x01 

70 

71 def is_elective(self): 

72 return not self.is_critical() 

73 

74 def is_unsafe(self): 

75 return self & 0x02 == 0x02 

76 

77 def is_safetoforward(self): 

78 return not self.is_unsafe() 

79 

80 def is_nocachekey(self): 

81 if self.is_unsafe(): 

82 raise ValueError("NoCacheKey is only meaningful for safe options") 

83 return self & 0x1e == 0x1c 

84 

85 def is_cachekey(self): 

86 return not self.is_nocachekey() 

87 

88 def _get_format(self): 

89 if hasattr(self, "_format"): 

90 return self._format 

91 else: 

92 return optiontypes.OpaqueOption 

93 

94 def _set_format(self, value): 

95 self._format = value 

96 

97 format = property(_get_format, _set_format) 

98 

99 def create_option(self, decode=None, value=None): 

100 """Return an Option element of the appropriate class from this option 

101 number. 

102 

103 An initial value may be set using the decode or value options, and will 

104 be fed to the resulting object's decode method or value property, 

105 respectively.""" 

106 option = self.format(self) 

107 if decode is not None: 

108 option.decode(decode) 

109 if value is not None: 

110 option.value = value 

111 return option 

112 

113 def _repr_html_(self): 

114 import html 

115 properties = f"{'critical' if self.is_critical() else 'elective'}, {'safe-to-forward' if self.is_safetoforward() else 'proxy unsafe'}" 

116 if self.is_safetoforward(): 

117 properties += ", part of the cache key" if self.is_cachekey() else ", not part of the cache key" 

118 if hasattr(self, "name"): 

119 return f'<abbr title="option {int(self)}: {properties}">{html.escape(self.name)}</abbr>' 

120 else: 

121 return f'<abbr title="{properties}">Option {int(self)}</abbr>' 

122 

123# OpaqueOption is set on formats where it is known to be used even though it is 

124# the default. This allows developers to rely on those interfaces to be stable 

125# (or at least to be notified visibly in the release notes). 

126 

127# RFC 7252 

128 

129OptionNumber.IF_MATCH.format = optiontypes.OpaqueOption 

130OptionNumber.URI_HOST.format = optiontypes.StringOption 

131OptionNumber.ETAG.format = optiontypes.OpaqueOption 

132OptionNumber.URI_PORT.format = optiontypes.UintOption 

133OptionNumber.LOCATION_PATH.format = optiontypes.StringOption 

134OptionNumber.URI_PATH.format = optiontypes.StringOption 

135OptionNumber.CONTENT_FORMAT.format = optiontypes.ContentFormatOption 

136OptionNumber.MAX_AGE.format = optiontypes.UintOption 

137OptionNumber.URI_QUERY.format = optiontypes.StringOption 

138OptionNumber.ACCEPT.format = optiontypes.ContentFormatOption 

139OptionNumber.LOCATION_QUERY.format = optiontypes.StringOption 

140OptionNumber.PROXY_URI.format = optiontypes.StringOption 

141OptionNumber.PROXY_SCHEME.format = optiontypes.StringOption 

142OptionNumber.SIZE1.format = optiontypes.UintOption 

143 

144# RFC 7959 

145 

146OptionNumber.BLOCK2.format = optiontypes.BlockOption 

147OptionNumber.BLOCK1.format = optiontypes.BlockOption 

148OptionNumber.SIZE2.format = optiontypes.UintOption 

149 

150# RFC 7641 

151 

152OptionNumber.OBSERVE.format = optiontypes.UintOption 

153 

154# RFC 7967 

155 

156OptionNumber.NO_RESPONSE.format = optiontypes.UintOption 

157 

158# RFC 8613 

159 

160OptionNumber.OSCORE.format = optiontypes.OpaqueOption 

161 

162# RFC 9175 

163 

164OptionNumber.ECHO.format = optiontypes.OpaqueOption 

165OptionNumber.REQUEST_TAG.format = optiontypes.OpaqueOption 

166 

167# RFC 8768 

168 

169OptionNumber.HOP_LIMIT.format = optiontypes.UintOption 

170 

171# experimental for draft-amsuess-core-cachable-oscore 

172 

173OptionNumber.REQUEST_HASH.format = optiontypes.OpaqueOption