diff --git a/coapthon/client/coap.py b/coapthon/client/coap.py index 8627f8e..a9badd8 100644 --- a/coapthon/client/coap.py +++ b/coapthon/client/coap.py @@ -165,6 +165,13 @@ class CoAP(object): if not self._cb_ignore_write_exception(e, self): raise + # if you're explicitly setting that you don't want a response, don't wait for it + # https://tools.ietf.org/html/rfc7967#section-2.1 + for opt in message.options: + if opt.number == defines.OptionRegistry.NO_RESPONSE.number: + if opt.value == 26: + return + if self._receiver_thread is None or not self._receiver_thread.isAlive(): self._receiver_thread = threading.Thread(target=self.receive_datagram) self._receiver_thread.start() diff --git a/coapthon/client/helperclient.py b/coapthon/client/helperclient.py index 986be8b..dc2672b 100644 --- a/coapthon/client/helperclient.py +++ b/coapthon/client/helperclient.py @@ -134,7 +134,7 @@ class HelperClient(object): return self.send_request(request, callback, timeout) - def post(self, path, payload, callback=None, timeout=None, **kwargs): # pragma: no cover + def post(self, path, payload, callback=None, timeout=None, no_response=False, **kwargs): # pragma: no cover """ Perform a POST on a certain path. @@ -148,13 +148,17 @@ class HelperClient(object): request.token = generate_random_token(2) request.payload = payload + if no_response: + request.add_no_response() + request.type = defines.Types["NON"] + for k, v in kwargs.items(): if hasattr(request, k): setattr(request, k, v) - return self.send_request(request, callback, timeout) + return self.send_request(request, callback, timeout, no_response=no_response) - def put(self, path, payload, callback=None, timeout=None, **kwargs): # pragma: no cover + def put(self, path, payload, callback=None, timeout=None, no_response=False, **kwargs): # pragma: no cover """ Perform a PUT on a certain path. @@ -168,11 +172,15 @@ class HelperClient(object): request.token = generate_random_token(2) request.payload = payload + if no_response: + request.add_no_response() + request.type = defines.Types["NON"] + for k, v in kwargs.items(): if hasattr(request, k): setattr(request, k, v) - return self.send_request(request, callback, timeout) + return self.send_request(request, callback, timeout, no_response=no_response) def discover(self, callback=None, timeout=None, **kwargs): # pragma: no cover """ @@ -190,7 +198,7 @@ class HelperClient(object): return self.send_request(request, callback, timeout) - def send_request(self, request, callback=None, timeout=None): # pragma: no cover + def send_request(self, request, callback=None, timeout=None, no_response=False): # pragma: no cover """ Send a request to the remote server. @@ -204,6 +212,8 @@ class HelperClient(object): thread.start() else: self.protocol.send_message(request) + if no_response: + return try: response = self.queue.get(block=True, timeout=timeout) except Empty: diff --git a/coapthon/defines.py b/coapthon/defines.py index b786021..9b081ea 100644 --- a/coapthon/defines.py +++ b/coapthon/defines.py @@ -127,6 +127,7 @@ class OptionRegistry(object): PROXY_URI = OptionItem(35, "Proxy-Uri", STRING, False, None) PROXY_SCHEME = OptionItem(39, "Proxy-Schema", STRING, False, None) SIZE1 = OptionItem(60, "Size1", INTEGER, False, None) + NO_RESPONSE = OptionItem(258, "No-Response", INTEGER, False, None) RM_MESSAGE_SWITCHING = OptionItem(65524, "Routing", OPAQUE, False, None) LIST = { @@ -149,6 +150,7 @@ class OptionRegistry(object): 35: PROXY_URI, 39: PROXY_SCHEME, 60: SIZE1, + 258: NO_RESPONSE, 65524: RM_MESSAGE_SWITCHING } diff --git a/coapthon/messages/request.py b/coapthon/messages/request.py index 9eee41d..f6067d0 100644 --- a/coapthon/messages/request.py +++ b/coapthon/messages/request.py @@ -187,6 +187,16 @@ class Request(Message): option.value = None self.add_option(option) + 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) + @if_none_match.deleter def if_none_match(self): """