def block2(self, value): """ Set the Block2 option. :param value: the Block2 value """ option = Option() option.number = defines.OptionRegistry.BLOCK2.number num, m, size = value if size > 512: szx = 6 elif 256 < size <= 512: szx = 5 elif 128 < size <= 256: szx = 4 elif 64 < size <= 128: szx = 3 elif 32 < size <= 64: szx = 2 elif 16 < size <= 32: szx = 1 else: szx = 0 value = (num << 4) value |= (m << 3) value |= szx option.value = value self.add_option(option)
def add_if_none_match(self): """ Add the if-none-match option to the request. """ option = Option() option.number = defines.OptionRegistry.IF_NONE_MATCH.number option.value = None self.add_option(option)
def test_create_options(self): m = Message() o = Options() o.accept = 10000 # setattr(o, 'accept', 10000) option = Option() option.number = defines.OptionRegistry.ACCEPT.number option.value = 10000
def add_no_response(self): """ Add the no-response option to the request # https://tools.ietf.org/html/rfc7967#section-2.1 """ option = Option() option.number = defines.OptionRegistry.NO_RESPONSE.number option.value = 26 self.add_option(option)
def proxy_schema(self, value): """ Set the Proxy-Schema option of a request. :param value: the Proxy-Schema value """ option = Option() option.number = defines.OptionRegistry.PROXY_SCHEME.number option.value = str(value) self.add_option(option)
def proxy_uri(self, value): """ Set the Proxy-Uri option of a request. :param value: the Proxy-Uri value """ option = Option() option.number = defines.OptionRegistry.PROXY_URI.number option.value = str(value) self.add_option(option)
def size2(self, value): """ Set the Size2 option. :param value: the Block2 value """ option = Option() option.number = defines.OptionRegistry.SIZE2.number option.value = value self.add_option(option)
def content_type(self, content_type): """ Set the Content-Type option of a response. :type content_type: int :param content_type: the Content-Type """ option = Option() option.number = defines.OptionRegistry.CONTENT_TYPE.number option.value = int(content_type) self.add_option(option)
def accept(self, value): """ Add an Accept option to a request. :param value: the Accept value """ if value in list(defines.Content_types.values()): option = Option() option.number = defines.OptionRegistry.ACCEPT.number option.value = value self.add_option(option)
def observe(self, ob): """ Add the Observe option. :param ob: observe count """ option = Option() option.number = defines.OptionRegistry.OBSERVE.number option.value = ob self.del_option_by_number(defines.OptionRegistry.OBSERVE.number) self.add_option(option)
def max_age(self, value): """ Set the MaxAge of the response. :type value: int :param value: the MaxAge option """ option = Option() option.number = defines.OptionRegistry.MAX_AGE.number option.value = int(value) self.del_option_by_number(defines.OptionRegistry.MAX_AGE.number) self.add_option(option)
def if_none_match(self, value): """ Set the If-Match option of a request. :param value: True/False :type values : bool """ assert isinstance(value, bool) option = Option() option.number = defines.OptionRegistry.IF_NONE_MATCH.number option.value = None self.add_option(option)
def if_match(self, values): """ Set the If-Match option of a request. :param values: the If-Match values :type values : list """ assert isinstance(values, list) for v in values: option = Option() option.number = defines.OptionRegistry.IF_MATCH.number option.value = v self.add_option(option)
def uri_query(self, value): """ Adds a query. :param value: the query """ del self.uri_query queries = value.split("&") for q in queries: option = Option() option.number = defines.OptionRegistry.URI_QUERY.number option.value = str(q) self.add_option(option)
def location_query(self, value): """ Set the Location-Query of the response. :type path: String :param path: the Location-Query as a string """ del self.location_query queries = value.split("&") for q in queries: option = Option() option.number = defines.OptionRegistry.LOCATION_QUERY.number option.value = str(q) self.add_option(option)
def encode_to_coap(self): # try: # parsed = urllib.parse.urlparse(self.to.get_endpoint(), allow_fragments=False) # address = (parsed.hostname, parsed.port) # except KeyError: # address = None # return msg2, address request = Request() request.type = NON # request.token = generate_random_token(2) request.destination = destination # request.destination = (sender, 5683) request.multicast = self.multicast request.source = (sender, None) request.code = self.code request.uri_path = self.to.href option = Option() option.number = defines.OptionRegistry.CONTENT_TYPE.number option.value = 10000 request.add_option(option) option = Option() option.number = defines.OptionRegistry.URI_QUERY.number option.value = self.encode_query( self.query) # todo разобраться что тут надо request.add_option(option)
def query(self, value): """ Adds a query. :param value: the query """ del self.uri_query for key in value: if not isinstance(value[key], list): raise Exception('value query param must be only list') for elem in value[key]: option = Option() option.number = defines.OptionRegistry.URI_QUERY.number option.value = str(f'{key}={elem}') self.add_option(option)
def etag(self, etag): """ Add an ETag option to the message. :param etag: the etag """ if not isinstance(etag, list): etag = [etag] for e in etag: option = Option() option.number = defines.OptionRegistry.ETAG.number if not isinstance(e, bytes): e = bytes(e, "utf-8") option.value = e self.add_option(option)
def location_path(self, path): """ Set the Location-Path of the response. :type path: String :param path: the Location-Path as a string """ path = path.strip("/") tmp = path.split("?") path = tmp[0] paths = path.split("/") for p in paths: option = Option() option.number = defines.OptionRegistry.LOCATION_PATH.number option.value = p self.add_option(option)
def uri_path(self, path): """ Set the Uri-Path of a request. :param path: the Uri-Path """ path = path.strip("/") tmp = path.split("?") path = tmp[0] paths = path.split("/") for p in paths: option = Option() option.number = defines.OptionRegistry.URI_PATH.number option.value = p self.add_option(option) if len(tmp) > 1: query = tmp[1] self.uri_query = query
def _prepare_request(self, operation, to, data=None, *, secure=False, multicast=False, query=None, **kwargs): # secure = kwargs.get('secure', False) # multicast = kwargs.get('multicast', False) scheme = 'coaps' if secure else 'coap' family = to['family'] request = Request() request.type = NON request.scheme = scheme request.multicast = multicast request.family = family request.source = (to['net_interface'], None) if multicast: request.destination = (self.coap_discovery[family][0], self.coap_discovery_port) else: request.destination = to[scheme] request.code = self.map_crudn_to_coap_code(operation) request.uri_path = to.get('href', '') option = Option() option.number = defines.OptionRegistry.CONTENT_TYPE.number option.value = 10000 request.add_option(option) # request.accept = 10000 # query = kwargs.get('query') if query: request.query = query if data: request.encode_payload(data) return request
async def discover(): timeout = kwargs.get('timeout') _protocol = [] if self.ipv4: _protocol.append(self.eps_coap_ipv4) if self.ipv6: _protocol.append(self.eps_coap_ipv6) _res = None _token = self.coap.message_layer.fetch_token() _mid = self.coap.message_layer.fetch_mid() for elem in _protocol: for ip in elem: for port in elem[ip]: ep = elem[ip][port] request = Request() request.token = _token request.query = { 'owned': ['TRUE'] if kwargs.get('owned') else ['FALSE'] } request.mid = _mid request.type = NON request.code = Code.GET request.uri_path = '/oic/sec/doxm' # request.content_type = 10000 request.accept = 10000 request.source = ep.address request.multicast = True request.family = ep.family request.scheme = ep.scheme option = Option() option.number = defines.OptionRegistry.OCF_ACCEPT_CONTENT_FORMAT_VERSION.number option.value = 2048 request.add_option(option) request.destination = ( self.coap_discovery[ep.family][0], self.coap_discovery_port) _res = asyncio.create_task( self.coap.send_message(request, timeout=timeout)) # _res.append(self.coap.send_message(request)) return await _res # все вернется одновременно потому что токен один
async def render_GET_advanced(self, request, response): data = { "rt": ["oic.r.doxm"], "if": ["oic.if.rw", "oic.if.baseline"], "p": { "bm": 1 }, "oxms": [0], "oxmsel": 0, "sct": 1, "owned": False, "devowneruuid": "00000000-0000-0000-0000-000000000000", "deviceuuid": "10000000-0000-0000-0000-000000000001", "rowneruuid": "00000000-0000-0000-0000-000000000000" } option = Option() option.number = defines.OptionRegistry.ACCEPT.number option.value = 10000 response.add_option(option) response.payload = (10000, cbor2.dumps(data) if data else b'') return self, response
def create_request_get_doxm(sender, destination): request = Request() request.type = NON # request.token = generate_random_token(2) request.destination = destination # request.destination = (sender, 5683) request.multicast = True request.source = (sender, None) request.code = Code.GET request.uri_path = '/oic/sec/doxm' option = Option() option.number = defines.OptionRegistry.CONTENT_TYPE.number option.value = 10000 request.add_option(option) option = Option() option.number = defines.OptionRegistry.URI_QUERY.number option.value = '' request.add_option(option) return request
def size1(self, value): option = Option() option.number = defines.OptionRegistry.SIZE1.number option.value = value self.add_option(option)
def deserialize(datagram, source): """ De-serialize a stream of byte to a message. :param datagram: the incoming udp message :param source: the source address and port (ip, port) :return: the message :rtype: Message """ try: fmt = "!BBH" pos = struct.calcsize(fmt) s = struct.Struct(fmt) values = s.unpack_from(datagram) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if Serializer.is_response(code): message = Response() message.code = code elif Serializer.is_request(code): message = Request() message.code = code else: message = Message() message.source = source message.destination = None message.version = version message.type = message_type message.mid = mid if token_length > 0: message.token = datagram[pos:pos + token_length] else: message.token = None pos += token_length current_option = 0 values = datagram[pos:] length_packet = len(values) pos = 0 while pos < length_packet: next_byte = struct.unpack("B", values[pos].to_bytes(1, "big"))[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint num, option_length, pos = Serializer.read_option_value_len_from_byte(next_byte, pos, values) # logger.debug("option value (delta): %d len: %d", num, option_length) current_option += num # read option try: option_item = defines.OptionRegistry.LIST[current_option] except KeyError: (opt_critical, _, _) = defines.OptionRegistry.get_option_flags(current_option) if opt_critical: raise AttributeError("Critical option %s unknown" % current_option) else: # If the non-critical option is unknown # (vendor-specific, proprietary) - just skip it logger.warning("unrecognized option %d", current_option) else: if option_length == 0: value = None elif option_item.value_type == defines.INTEGER: tmp = values[pos: pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b.to_bytes(1, "big"))[0] elif option_item.value_type == defines.OPAQUE: tmp = values[pos: pos + option_length] value = tmp else: value = values[pos: pos + option_length] option = Option() option.number = current_option option.value = Serializer.convert_to_raw(current_option, value, option_length) message.add_option(option) if option.number == defines.OptionRegistry.CONTENT_TYPE.number: message.payload_type = option.value finally: pos += option_length else: if length_packet <= pos: # log.err("Payload Marker with no payload") raise AttributeError("Packet length %s, pos %s" % (length_packet, pos)) message.payload = "" payload = values[pos:] message.payload = payload pos += len(payload) return message except AttributeError: return defines.Codes.BAD_REQUEST.number except struct.error: return defines.Codes.BAD_REQUEST.number except UnicodeDecodeError as e: logger.debug(e) return defines.Codes.BAD_REQUEST.number