From 6cb4ee3d4188bb7a1db7eab23bfdb9830f02d266 Mon Sep 17 00:00:00 2001 From: Ronald Steinke Date: Fri, 5 Oct 2018 15:33:20 +0200 Subject: [PATCH] handles release version indicator and updates request/response attributes --- .../src/openmtc_onem2m/client/http.py | 7 +- .../src/openmtc_onem2m/client/mqtt.py | 20 ++- .../src/openmtc_onem2m/mapper/__init__.py | 10 +- .../src/openmtc_onem2m/transport.py | 133 ++++++++++++++++-- .../methoddomain/controller/__init__.py | 4 + .../plugins/transport_gevent_http/wsgi.py | 28 +++- 6 files changed, 180 insertions(+), 22 deletions(-) diff --git a/common/openmtc-onem2m/src/openmtc_onem2m/client/http.py b/common/openmtc-onem2m/src/openmtc_onem2m/client/http.py index efc59c6..dc5c66b 100644 --- a/common/openmtc-onem2m/src/openmtc_onem2m/client/http.py +++ b/common/openmtc-onem2m/src/openmtc_onem2m/client/http.py @@ -48,7 +48,7 @@ _method_map_to_http = { _clients = LRUCache(threadsafe=False) -_query_params = frozenset(['rt', 'rp', 'rcn', 'da', 'drt']) +_query_params = frozenset(['rt', 'rp', 'rcn', 'da', 'drt', 'rids', 'tids', 'ltids', 'tqi']) _header_to_field_map = { 'X-M2M-ORIGIN': 'originator', @@ -59,6 +59,8 @@ _header_to_field_map = { 'X-M2M-RET': 'rqet', 'X-M2M-OET': 'oet', 'X-M2M-EC': 'ec', + 'X-M2M-RVI': 'rvi', + 'X-M2M-VSI': 'vsi', } @@ -162,7 +164,8 @@ class OneM2MHTTPClient(OneM2MClient): content_type += '; ty=' + str(ResourceTypeE[onem2m_request.resource_type.typename]) headers = { - header: getattr(onem2m_request, field) for header, field in _header_to_field_map.iteritems() + header: getattr(onem2m_request, field) + for header, field in _header_to_field_map.iteritems() if getattr(onem2m_request, field) is not None } headers['content-type'] = content_type diff --git a/common/openmtc-onem2m/src/openmtc_onem2m/client/mqtt.py b/common/openmtc-onem2m/src/openmtc_onem2m/client/mqtt.py index 66cd272..d714abf 100644 --- a/common/openmtc-onem2m/src/openmtc_onem2m/client/mqtt.py +++ b/common/openmtc-onem2m/src/openmtc_onem2m/client/mqtt.py @@ -83,11 +83,12 @@ class OneM2MMQTTClient(OneM2MClient): __request_fields = frozenset([ 'op', + 'to', 'fr', 'rqi', 'ty', 'pc', - 'rol', + 'rids', 'ot', 'rqet', 'rset', @@ -98,17 +99,28 @@ class OneM2MMQTTClient(OneM2MClient): 'ec', 'da', 'gid', - 'drt', - 'to', 'fc', + 'drt', + 'tids', + 'ltids', + 'tqi', + 'rvi', + 'vsi', ]) __response_fields = frozenset([ 'rsc', 'rqi', 'pc', - 'fr', 'to', + 'fr', + 'ot', + 'rset', + 'ec', + 'cts', + 'cto', + 'rvi', + 'vsi', ]) @staticmethod diff --git a/common/openmtc-onem2m/src/openmtc_onem2m/mapper/__init__.py b/common/openmtc-onem2m/src/openmtc_onem2m/mapper/__init__.py index eb89c76..1c25072 100644 --- a/common/openmtc-onem2m/src/openmtc_onem2m/mapper/__init__.py +++ b/common/openmtc-onem2m/src/openmtc_onem2m/mapper/__init__.py @@ -49,7 +49,8 @@ class OneM2MMapper(BasicMapper): path, self.originator, ty=type(instance), - pc=instance + pc=instance, + rvi='2a' )).get() try: @@ -83,7 +84,8 @@ class OneM2MMapper(BasicMapper): OneM2MOperation.update, instance.path, self.originator, - pc=instance + pc=instance, + rvi='2a' )).get() try: @@ -105,6 +107,7 @@ class OneM2MMapper(BasicMapper): path, self.originator, filter_criteria=fc, + rvi='2a', rcn=5, **request_options )).get() @@ -113,7 +116,8 @@ class OneM2MMapper(BasicMapper): self._send_request(OneM2MRequest( OneM2MOperation.delete, getattr(instance, "path", instance), - self.originator + self.originator, + rvi='2a' )) # TODO(rst): check if this can be removed in parent class diff --git a/common/openmtc-onem2m/src/openmtc_onem2m/transport.py b/common/openmtc-onem2m/src/openmtc_onem2m/transport.py index 987d41c..4bc9394 100644 --- a/common/openmtc-onem2m/src/openmtc_onem2m/transport.py +++ b/common/openmtc-onem2m/src/openmtc_onem2m/transport.py @@ -201,10 +201,11 @@ class OneM2MRequest(object): """Class representing a OneM2M request""" - def __init__(self, op, to, fr=None, rqi=None, ty=None, pc=None, rol=None, + def __init__(self, op, to, fr=None, rqi=None, ty=None, pc=None, rids=None, ot=None, rqet=None, rset=None, oet=None, rt=None, rp=None, rcn=None, ec=None, da=None, gid=None, filter_criteria=None, - fc=None, drt=None): + fc=None, drt=None, tids=None, ltids=None, tqi=None, rvi=None, + vsi=None): # Operation self.operation = op # Target uri @@ -216,7 +217,7 @@ class OneM2MRequest(object): self.resource_type = ty # Resource content to be transferred. self.content = pc - self.role = rol + self.role_ids = rids self.originating_timestamp = ot self.request_expiration_timestamp = rqet self.result_expiration_timestamp = rset @@ -230,6 +231,11 @@ class OneM2MRequest(object): self.filter_criteria = filter_criteria or fc # Optional Discovery result type self.discovery_result_type = drt + self.token_ids = tids + self.local_token_ids = ltids + self.token_request_identifier = tqi + self.release_version_indicator = rvi + self.vendor_information = vsi @property def op(self): @@ -272,12 +278,12 @@ class OneM2MRequest(object): self.content = pc @property - def rol(self): - return self.role + def rids(self): + return self.role_ids - @rol.setter - def rol(self, rol): - self.role = rol + @rids.setter + def rids(self, rids): + self.role_ids = rids @property def ot(self): @@ -375,6 +381,46 @@ class OneM2MRequest(object): def drt(self, drt): self.discovery_result_type = drt + @property + def tids(self): + return self.token_ids + + @tids.setter + def tids(self, tids): + self.token_ids = tids + + @property + def ltids(self): + return self.local_token_ids + + @ltids.setter + def ltids(self, rvi): + self.local_token_ids = ltids + + @property + def tqi(self): + return self.token_request_identifier + + @tqi.setter + def tqi(self, tqi): + self.token_request_identifier = tqi + + @property + def rvi(self): + return self.release_version_indicator + + @rvi.setter + def rvi(self, rvi): + self.release_version_indicator = rvi + + @property + def vsi(self): + return self.vendor_information + + @vsi.setter + def vsi(self, vsi): + self.vendor_information = vsi + def __str__(self): return '%s: %s' % (self.__class__.__name__, ' | '.join([ '%s: %s' % (str(k), str(v)) for k, v in self.__dict__.iteritems() @@ -385,7 +431,8 @@ class OneM2MResponse(object): """Class representing a OneM2M response""" def __init__(self, status_code, request=None, rqi=None, pc=None, to=None, - fr=None, rsc=None, fields=None): + fr=None, rsc=None, ot=None, rset=None, ec=None, cts=None, + cto=None, rvi=None, vsi=None, fields=None): # Operation result if isinstance(status_code, STATUS): self.response_status_code = status_code @@ -397,14 +444,26 @@ class OneM2MResponse(object): self.to = request.to # Originator ID self.originator = request.fr + self.originating_timestamp = request.ot + self.result_expiration_timestamp = request.rset + self.event_category = request.ec + self.release_version_indicator = request.rvi + self.vendor_information = request.vsi else: self.request_identifier = rqi # Target uri self.to = to # Originator ID self.originator = fr + self.originating_timestamp = ot + self.release_version_indicator = rvi + self.vendor_information = vsi + self.result_expiration_timestamp = rset + self.event_category = ec # Resource content to be transferred. self.content = pc + self.content_status = cts + self.content_offset = cto self.fields = fields @property @@ -439,6 +498,62 @@ class OneM2MResponse(object): def fr(self, fr): self.originator = fr + @property + def ot(self): + return self.originating_timestamp + + @ot.setter + def ot(self, ot): + self.originating_timestamp = ot + + @property + def rset(self): + return self.result_expiration_timestamp + + @rset.setter + def rset(self, rset): + self.result_expiration_timestamp = rset + + @property + def ec(self): + return self.event_category + + @ec.setter + def ec(self, ec): + self.event_category = ec + + @property + def cts(self): + return self.content_status + + @cts.setter + def cts(self, cts): + self.content_status = cts + + @property + def cto(self): + return self.content_offset + + @cto.setter + def cto(self, cto): + self.content_offset = cto + + @property + def rvi(self): + return self.release_version_indicator + + @rvi.setter + def rvi(self, rvi): + self.release_version_indicator = rvi + + @property + def vsi(self): + return self.vendor_information + + @vsi.setter + def vsi(self, vsi): + self.vendor_information = vsi + def __str__(self): return '%s: %s' % (self.__class__.__name__, ' | '.join([ '%s: %s' % (str(k), str(v)) for k, v in self.__dict__.iteritems() diff --git a/server/openmtc-cse/src/openmtc_cse/methoddomain/controller/__init__.py b/server/openmtc-cse/src/openmtc_cse/methoddomain/controller/__init__.py index 553c679..4795c5e 100644 --- a/server/openmtc-cse/src/openmtc_cse/methoddomain/controller/__init__.py +++ b/server/openmtc-cse/src/openmtc_cse/methoddomain/controller/__init__.py @@ -106,6 +106,10 @@ class OneM2MDefaultController(LoggerMixin): self._dynamic_authorization_supported = dynamic_authorization.get('enabled', False) self._dynamic_authorization_poa = dynamic_authorization.get('poa', []) + # release version indicator + if not self.request.rvi: + self.request.rvi = '2a' + return self._handle_request() def _handle_request(self): diff --git a/server/openmtc-cse/src/openmtc_cse/plugins/transport_gevent_http/wsgi.py b/server/openmtc-cse/src/openmtc_cse/plugins/transport_gevent_http/wsgi.py index afe3bc4..d8711d3 100644 --- a/server/openmtc-cse/src/openmtc_cse/plugins/transport_gevent_http/wsgi.py +++ b/server/openmtc-cse/src/openmtc_cse/plugins/transport_gevent_http/wsgi.py @@ -249,11 +249,21 @@ class OpenMTCWSGIApplication(LoggerMixin): # request and response primitives, and vice versa, if applicable. ec = get_header("x-m2m-ec") + # The X-M2M-CTS header shall be mapped to the Content Status parameter + # of response primitives and vice versa, if applicable. + rvi = get_header("x-m2m-rvi") + + # The X-M2M-CTS header shall be mapped to the Content Status parameter + # of response primitives and vice versa, if applicable. + vsi = get_header("x-m2m-vsi") + onem2m_request = OneM2MRequest(op=op, to=to, fr=fr, rqi=rqi, ty=ty, pc=pc, ot=ot, rqet=rqet, rset=rset, - oet=oet, rt=rt, ec=ec, gid=gid) + oet=oet, rt=rt, ec=ec, gid=gid, rvi=rvi, + vsi=vsi) - not_filter_params = ('rt', 'rp', 'rcn', 'da', 'drt') + not_filter_params = ('rt', 'rp', 'rcn', 'da', 'drt', 'rids', 'tids', + 'ltids', 'tqi') multiple_params = ('lbl', 'ty', 'cty', 'atr') if http_request.query_string: @@ -315,9 +325,18 @@ class OpenMTCWSGIApplication(LoggerMixin): headers = { "x-m2m-ri": str(response.rqi), - "x-m2m-rsc": str(response.rsc) + "x-m2m-rsc": str(response.rsc), + 'x-m2m-rvi': str(response.rvi) } + if response.fr: + headers['x-m2m-origin'] = str(response.fr) + + response_fields = ['ot', 'rset', 'ec', 'cts', 'cto', 'vsi'] + for f in response_fields: + if getattr(response, f): + headers['x-m2m-%s' % f] = str(getattr(response, f)) + try: headers['Content-Location'] = (resource_id_pre + response.content.resourceID) except (AttributeError, TypeError): @@ -370,7 +389,8 @@ class OpenMTCWSGIApplication(LoggerMixin): headers = { "x-m2m-ri": str(response.rqi), - "x-m2m-rsc": str(response.rsc) + "x-m2m-rsc": str(response.rsc), + 'x-m2m-rvi': str(response.rvi) } except AttributeError: status_code = STATUS_INTERNAL_SERVER_ERROR.http_status_code