def receive_from_header_and_body(self, header, body): """ Convert MessageHeader and binary body to OPC UA TCP message (see OPC UA specs Part 6, 7.1: Hello, Acknowledge or ErrorMessage), or a Message object, or None (if intermediate chunk is received) """ if header.MessageType == ua.MessageType.SecureOpen: data = body.copy(header.body_size) security_header = struct_from_binary(ua.AsymmetricAlgorithmHeader, data) self.select_policy(security_header.SecurityPolicyURI, security_header.SenderCertificate) if header.MessageType in (ua.MessageType.SecureMessage, ua.MessageType.SecureOpen, ua.MessageType.SecureClose): chunk = MessageChunk.from_header_and_body(self.security_policy, header, body) return self._receive(chunk) elif header.MessageType == ua.MessageType.Hello: msg = struct_from_binary(ua.Hello, body) self._max_chunk_size = msg.ReceiveBufferSize return msg elif header.MessageType == ua.MessageType.Acknowledge: msg = struct_from_binary(ua.Acknowledge, body) self._max_chunk_size = msg.SendBufferSize return msg elif header.MessageType == ua.MessageType.Error: msg = struct_from_binary(ua.ErrorMessage, body) logger.warning("Received an error: %s", msg) return msg else: raise ua.UaError("Unsupported message type {0}".format(header.MessageType))
def from_header_and_body(security_policy, header, buf): assert len(buf) >= header.body_size, 'Full body expected here' data = buf.copy(header.body_size) buf.skip(header.body_size) if header.MessageType in (ua.MessageType.SecureMessage, ua.MessageType.SecureClose): security_header = struct_from_binary(ua.SymmetricAlgorithmHeader, data) crypto = security_policy.symmetric_cryptography elif header.MessageType == ua.MessageType.SecureOpen: security_header = struct_from_binary(ua.AsymmetricAlgorithmHeader, data) crypto = security_policy.asymmetric_cryptography else: raise ua.UaError("Unsupported message type: {0}".format( header.MessageType)) obj = MessageChunk(crypto) obj.MessageHeader = header obj.SecurityHeader = security_header decrypted = crypto.decrypt(data.read(len(data))) signature_size = crypto.vsignature_size() if signature_size > 0: signature = decrypted[-signature_size:] decrypted = decrypted[:-signature_size] crypto.verify( header_to_binary(obj.MessageHeader) + struct_to_binary(obj.SecurityHeader) + decrypted, signature) data = ua.utils.Buffer(crypto.remove_padding(decrypted)) obj.SequenceHeader = struct_from_binary(ua.SequenceHeader, data) obj.Body = data.read(len(data)) return obj
def receive_from_header_and_body(self, header, body): """ Convert MessageHeader and binary body to OPC UA TCP message (see OPC UA specs Part 6, 7.1: Hello, Acknowledge or ErrorMessage), or a Message object, or None (if intermediate chunk is received) """ if header.MessageType == ua.MessageType.SecureOpen: data = body.copy(header.body_size) security_header = struct_from_binary(ua.AsymmetricAlgorithmHeader, data) self.select_policy(security_header.SecurityPolicyURI, security_header.SenderCertificate) if header.MessageType in (ua.MessageType.SecureMessage, ua.MessageType.SecureOpen, ua.MessageType.SecureClose): chunk = MessageChunk.from_header_and_body(self.security_policy, header, body) return self._receive(chunk) elif header.MessageType == ua.MessageType.Hello: msg = struct_from_binary(ua.Hello, body) self._max_chunk_size = msg.ReceiveBufferSize return msg elif header.MessageType == ua.MessageType.Acknowledge: msg = struct_from_binary(ua.Acknowledge, body) self._max_chunk_size = msg.SendBufferSize return msg elif header.MessageType == ua.MessageType.Error: msg = struct_from_binary(ua.ErrorMessage, body) logger.warning("Received an error: %s", msg) return msg else: raise ua.UaError("Unsupported message type {0}".format( header.MessageType))
def from_header_and_body(security_policy, header, buf): assert len(buf) >= header.body_size, 'Full body expected here' data = buf.copy(header.body_size) buf.skip(header.body_size) if header.MessageType in (ua.MessageType.SecureMessage, ua.MessageType.SecureClose): security_header = struct_from_binary(ua.SymmetricAlgorithmHeader, data) crypto = security_policy.symmetric_cryptography elif header.MessageType == ua.MessageType.SecureOpen: security_header = struct_from_binary(ua.AsymmetricAlgorithmHeader, data) crypto = security_policy.asymmetric_cryptography else: raise ua.UaError("Unsupported message type: {0}".format(header.MessageType)) obj = MessageChunk(crypto) obj.MessageHeader = header obj.SecurityHeader = security_header decrypted = crypto.decrypt(data.read(len(data))) signature_size = crypto.vsignature_size() if signature_size > 0: signature = decrypted[-signature_size:] decrypted = decrypted[:-signature_size] crypto.verify(header_to_binary(obj.MessageHeader) + struct_to_binary(obj.SecurityHeader) + decrypted, signature) data = ua.utils.Buffer(crypto.remove_padding(decrypted)) obj.SequenceHeader = struct_from_binary(ua.SequenceHeader, data) obj.Body = data.read(len(data)) return obj
def test_custom_structs_array(self): xmlpath = "tests/example.bsd" c = StructGenerator() c.make_model_from_file(xmlpath) c.save_to_file("tests/structures.py") import structures as s # test with default values v = s.ArrayValueDataType() data = struct_to_binary(v) v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data)) # set some values v = s.ArrayValueDataType() v.SbyteValue = [1] v.ByteValue = [2] v.Int16Value = [3] v.UInt16Value = [4] v.Int32Value = [5] v.UInt32Value = [6] v.Int64Value = [7] v.UInt64Value = [8] v.FloatValue = [9.0] v.DoubleValue = [10.0] v.StringValue = ["elleven"] v.DateTimeValue = [datetime.utcnow()] #self.GuidValue = uuid.uudib"14" v.ByteStringValue = [b"fifteen", b"sixteen"] v.XmlElementValue = [ua.XmlElement("<toto>titi</toto>")] v.NodeIdValue = [ ua.NodeId.from_string("ns=4;i=9999"), ua.NodeId.from_string("i=6") ] #self.ExpandedNodeIdValue = #self.QualifiedNameValue = #self.LocalizedTextValue = #self.StatusCodeValue = #self.VariantValue = #self.EnumerationValue = #self.StructureValue = #self.Number = #self.Integer = #self.UInteger = data = struct_to_binary(v) v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data)) self.assertEqual(v.NodeIdValue, v2.NodeIdValue) print(v2.NodeIdValue)
def test_custom_structs_array(self): xmlpath = "tests/example.bsd" c = StructGenerator() c.make_model_from_file(xmlpath) c.save_to_file("tests/structures.py") import structures as s # test with default values v = s.ArrayValueDataType() data = struct_to_binary(v) v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data)) # set some values v = s.ArrayValueDataType() v.SbyteValue = [1] v.ByteValue = [2] v.Int16Value = [3] v.UInt16Value = [4] v.Int32Value = [5] v.UInt32Value = [6] v.Int64Value = [7] v.UInt64Value = [8] v.FloatValue = [9.0] v.DoubleValue = [10.0] v.StringValue = ["elleven"] v.DateTimeValue = [datetime.utcnow()] #self.GuidValue = uuid.uudib"14" v.ByteStringValue = [b"fifteen", b"sixteen"] v.XmlElementValue = [ua.XmlElement("<toto>titi</toto>")] v.NodeIdValue = [ua.NodeId.from_string("ns=4;i=9999"), ua.NodeId.from_string("i=6")] #self.ExpandedNodeIdValue = #self.QualifiedNameValue = #self.LocalizedTextValue = #self.StatusCodeValue = #self.VariantValue = #self.EnumerationValue = #self.StructureValue = #self.Number = #self.Integer = #self.UInteger = data = struct_to_binary(v) v2 = struct_from_binary(s.ArrayValueDataType, ua.utils.Buffer(data)) self.assertEqual(v.NodeIdValue, v2.NodeIdValue) print(v2.NodeIdValue)
def register_server(self, registered_server): self.logger.info("register_server") request = ua.RegisterServerRequest() request.Server = registered_server data = self._uasocket.send_request(request) response = struct_from_binary(ua.RegisterServerResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check()
def test_custom_structs(self): xmlpath = "tests/example.bsd" c = StructGenerator() c.make_model_from_file(xmlpath) c.save_to_file("tests/structures.py") import structures as s # test with default values v = s.ScalarValueDataType() data = struct_to_binary(v) v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data)) # set some values v = s.ScalarValueDataType() v.SbyteValue = 1 v.ByteValue = 2 v.Int16Value = 3 v.UInt16Value = 4 v.Int32Value = 5 v.UInt32Value = 6 v.Int64Value = 7 v.UInt64Value = 8 v.FloatValue = 9.0 v.DoubleValue = 10.0 v.StringValue = "elleven" v.DateTimeValue = datetime.utcnow() #self.GuidValue = uuid.uudib"14" v.ByteStringValue = b"fifteen" v.XmlElementValue = ua.XmlElement("<toto>titi</toto>") v.NodeIdValue = ua.NodeId.from_string("ns=4;i=9999") #self.ExpandedNodeIdValue = #self.QualifiedNameValue = #self.LocalizedTextValue = #self.StatusCodeValue = #self.VariantValue = #self.EnumerationValue = #self.StructureValue = #self.Number = #self.Integer = #self.UInteger = data = struct_to_binary(v) v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data)) self.assertEqual(v.NodeIdValue, v2.NodeIdValue)
def test_text(self): t1 = ua.LocalizedText('Root') t2 = ua.LocalizedText('Root') t3 = ua.LocalizedText('root') self.assertEqual(t1, t2) self.assertNotEqual(t1, t3) t4 = struct_from_binary(ua.LocalizedText, ua.utils.Buffer(struct_to_binary(t1))) self.assertEqual(t1, t4)
def register_server(self, registered_server): self.logger.info("register_server") request = ua.RegisterServerRequest() request.Server = registered_server data = self._uasocket.send_request(request) response = struct_from_binary(ua.RegisterServerResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check()
def clb(future): response = struct_from_binary(ua.OpenSecureChannelResponse, future.result()) response.ResponseHeader.ServiceResult.check() self._connection.set_channel(response.Parameters, params.RequestType, params.ClientNonce) clb.future.set_result(response)
def unregister_nodes(self, nodes): self.logger.info("unregister_nodes") request = ua.UnregisterNodesRequest() request.Parameters.NodesToUnregister = nodes data = self._uasocket.send_request(request) response = struct_from_binary(ua.UnregisterNodesResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check()
def test_custom_structs(self): xmlpath = "tests/example.bsd" c = StructGenerator() c.make_model_from_file(xmlpath) c.save_to_file("tests/structures.py") import structures as s # test with default values v = s.ScalarValueDataType() data = struct_to_binary(v) v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data)) # set some values v = s.ScalarValueDataType() v.SbyteValue = 1 v.ByteValue = 2 v.Int16Value = 3 v.UInt16Value = 4 v.Int32Value = 5 v.UInt32Value = 6 v.Int64Value = 7 v.UInt64Value = 8 v.FloatValue = 9.0 v.DoubleValue = 10.0 v.StringValue = "elleven" v.DateTimeValue = datetime.utcnow() #self.GuidValue = uuid.uudib"14" v.ByteStringValue = b"fifteen" v.XmlElementValue = ua.XmlElement("<toto>titi</toto>") v.NodeIdValue = ua.NodeId.from_string("ns=4;i=9999") #self.ExpandedNodeIdValue = #self.QualifiedNameValue = #self.LocalizedTextValue = #self.StatusCodeValue = #self.VariantValue = #self.EnumerationValue = #self.StructureValue = #self.Number = #self.Integer = #self.UInteger = data = struct_to_binary(v) v2 = struct_from_binary(s.ScalarValueDataType, ua.utils.Buffer(data)) self.assertEqual(v.NodeIdValue, v2.NodeIdValue)
def test_text(self): t1 = ua.LocalizedText('Root') t2 = ua.LocalizedText('Root') t3 = ua.LocalizedText('root') self.assertEqual(t1, t2) self.assertNotEqual(t1, t3) t4 = struct_from_binary(ua.LocalizedText, ua.utils.Buffer(struct_to_binary(t1))) self.assertEqual(t1, t4)
def call(self, methodstocall): request = ua.CallRequest() request.Parameters.MethodsToCall = methodstocall data = self._uasocket.send_request(request) response = struct_from_binary(ua.CallResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def call(self, methodstocall): request = ua.CallRequest() request.Parameters.MethodsToCall = methodstocall data = self._uasocket.send_request(request) response = struct_from_binary(ua.CallResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def _create_subscription_callback(self, pub_callback, resp_fut, data_fut): self.logger.info("_create_subscription_callback") data = data_fut.result() response = struct_from_binary(ua.CreateSubscriptionResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() self._publishcallbacks[response.Parameters.SubscriptionId] = pub_callback resp_fut.set_result(response.Parameters)
def _call_publish_callback(self, future): self.logger.info("call_publish_callback") data = future.result() # check if answer looks ok try: self._uasocket.check_answer(data, "while waiting for publish response") except BadTimeout: # Spec Part 4, 7.28 self.publish() return except BadNoSubscription: # Spec Part 5, 13.8.1 # BadNoSubscription is expected after deleting the last subscription. # # We should therefore also check for len(self._publishcallbacks) == 0, but # this gets us into trouble if a Publish response arrives before the # DeleteSubscription response. # # We could remove the callback already when sending the DeleteSubscription request, # but there are some legitimate reasons to keep them around, such as when the server # responds with "BadTimeout" and we should try again later instead of just removing # the subscription client-side. # # There are a variety of ways to act correctly, but the most practical solution seems # to be to just ignore any BadNoSubscription responses. self.logger.info( "BadNoSubscription received, ignoring because it's probably valid." ) return # parse publish response try: response = struct_from_binary(ua.PublishResponse, data) self.logger.debug(response) except Exception: # INFO: catching the exception here might be obsolete because we already # catch BadTimeout above. However, it's not really clear what this code # does so it stays in, doesn't seem to hurt. self.logger.exception("Error parsing notificatipn from server") self.publish( [] ) # send publish request ot server so he does stop sending notifications return # look for callback try: callback = self._publishcallbacks[ response.Parameters.SubscriptionId] except KeyError: self.logger.warning("Received data for unknown subscription: %s ", response.Parameters.SubscriptionId) return # do callback try: callback(response.Parameters) except Exception: # we call client code, catch everything! self.logger.exception("Exception while calling user callback: %s")
def check_answer(self, data, context): data = data.copy() typeid = nodeid_from_binary(data) if typeid == ua.FourByteNodeId(ua.ObjectIds.ServiceFault_Encoding_DefaultBinary): self.logger.warning("ServiceFault from server received %s", context) hdr = struct_from_binary(ua.ResponseHeader, data) hdr.ServiceResult.check() return False return True
def modify_monitored_items(self, params): self.logger.info("modify_monitored_items") request = ua.ModifyMonitoredItemsRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.ModifyMonitoredItemsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def history_read(self, params): self.logger.info("history_read") request = ua.HistoryReadRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.HistoryReadResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def delete_nodes(self, params): self.logger.info("delete_nodes") request = ua.DeleteNodesRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.DeleteNodesResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def find_servers_on_network(self, params): self.logger.info("find_servers_on_network") request = ua.FindServersOnNetworkRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.FindServersOnNetworkResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters
def history_read(self, params): self.logger.info("history_read") request = ua.HistoryReadRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.HistoryReadResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def _delete_subscriptions_callback(self, subscriptionids, resp_fut, data_fut): self.logger.info("_delete_subscriptions_callback") data = data_fut.result() response = struct_from_binary(ua.DeleteSubscriptionsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() for sid in subscriptionids: self._publishcallbacks.pop(sid) resp_fut.set_result(response.Results)
def translate_browsepaths_to_nodeids(self, browsepaths): self.logger.info("translate_browsepath_to_nodeid") request = ua.TranslateBrowsePathsToNodeIdsRequest() request.Parameters.BrowsePaths = browsepaths data = self._uasocket.send_request(request) response = struct_from_binary(ua.TranslateBrowsePathsToNodeIdsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def check_answer(self, data, context): data = data.copy() typeid = nodeid_from_binary(data) if typeid == ua.FourByteNodeId(ua.ObjectIds.ServiceFault_Encoding_DefaultBinary): self.logger.warning("ServiceFault from server received %s", context) hdr = struct_from_binary(ua.ResponseHeader, data) hdr.ServiceResult.check() return False return True
def translate_browsepaths_to_nodeids(self, browsepaths): self.logger.info("translate_browsepath_to_nodeid") request = ua.TranslateBrowsePathsToNodeIdsRequest() request.Parameters.BrowsePaths = browsepaths data = self._uasocket.send_request(request) response = struct_from_binary(ua.TranslateBrowsePathsToNodeIdsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def browse_next(self, parameters): self.logger.info("browse next") request = ua.BrowseNextRequest() request.Parameters = parameters data = self._uasocket.send_request(request) response = struct_from_binary(ua.BrowseNextResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters.Results
def modify_monitored_items(self, params): self.logger.info("modify_monitored_items") request = ua.ModifyMonitoredItemsRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.ModifyMonitoredItemsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def get_endpoints(self, params): self.logger.info("get_endpoint") request = ua.GetEndpointsRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.GetEndpointsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Endpoints
def add_nodes(self, nodestoadd): self.logger.info("add_nodes") request = ua.AddNodesRequest() request.Parameters.NodesToAdd = nodestoadd data = self._uasocket.send_request(request) response = struct_from_binary(ua.AddNodesResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def activate_session(self, parameters): self.logger.info("activate_session") request = ua.ActivateSessionRequest() request.Parameters = parameters data = self._uasocket.send_request(request) response = struct_from_binary(ua.ActivateSessionResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters
def _delete_subscriptions_callback(self, subscriptionids, resp_fut, data_fut): self.logger.info("_delete_subscriptions_callback") data = data_fut.result() response = struct_from_binary(ua.DeleteSubscriptionsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() for sid in subscriptionids: self._publishcallbacks.pop(sid) resp_fut.set_result(response.Results)
def register_server2(self, params): self.logger.info("register_server2") request = ua.RegisterServer2Request() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.RegisterServer2Response, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.ConfigurationResults
def delete_nodes(self, params): self.logger.info("delete_nodes") request = ua.DeleteNodesRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.DeleteNodesResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def delete_references(self, refs): self.logger.info("delete") request = ua.DeleteReferencesRequest() request.Parameters.ReferencesToDelete = refs data = self._uasocket.send_request(request) response = struct_from_binary(ua.DeleteReferencesResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters.Results
def delete_references(self, refs): self.logger.info("delete") request = ua.DeleteReferencesRequest() request.Parameters.ReferencesToDelete = refs data = self._uasocket.send_request(request) response = struct_from_binary(ua.DeleteReferencesResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters.Results
def find_servers_on_network(self, params): self.logger.info("find_servers_on_network") request = ua.FindServersOnNetworkRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.FindServersOnNetworkResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters
def add_nodes(self, nodestoadd): self.logger.info("add_nodes") request = ua.AddNodesRequest() request.Parameters.NodesToAdd = nodestoadd data = self._uasocket.send_request(request) response = struct_from_binary(ua.AddNodesResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Results
def register_server2(self, params): self.logger.info("register_server2") request = ua.RegisterServer2Request() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.RegisterServer2Response, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.ConfigurationResults
def get_endpoints(self, params): self.logger.info("get_endpoint") request = ua.GetEndpointsRequest() request.Parameters = params data = self._uasocket.send_request(request) response = struct_from_binary(ua.GetEndpointsResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Endpoints
def browse_next(self, parameters): self.logger.info("browse next") request = ua.BrowseNextRequest() request.Parameters = parameters data = self._uasocket.send_request(request) response = struct_from_binary(ua.BrowseNextResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters.Results
def activate_session(self, parameters): self.logger.info("activate_session") request = ua.ActivateSessionRequest() request.Parameters = parameters data = self._uasocket.send_request(request) response = struct_from_binary(ua.ActivateSessionResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() return response.Parameters
def test_string_to_val_xml_element(self): string = "<p> titi toto </p>" obj = ua.XmlElement(string) self.assertEqual(string_to_val(string, ua.VariantType.XmlElement), obj) self.assertEqual(val_to_string(obj), string) b = struct_to_binary(obj) obj2 = struct_from_binary(ua.XmlElement, ua.utils.Buffer(b)) self.assertEqual(obj, obj2)
def create_session(self, parameters): self.logger.info("create_session") request = ua.CreateSessionRequest() request.Parameters = parameters data = self._uasocket.send_request(request) response = struct_from_binary(ua.CreateSessionResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() self._uasocket.authentication_token = response.Parameters.AuthenticationToken return response.Parameters
def create_session(self, parameters): self.logger.info("create_session") request = ua.CreateSessionRequest() request.Parameters = parameters data = self._uasocket.send_request(request) response = struct_from_binary(ua.CreateSessionResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() self._uasocket.authentication_token = response.Parameters.AuthenticationToken return response.Parameters
def test_string_to_val_xml_element(self): string = "<p> titi toto </p>" obj = ua.XmlElement(string) self.assertEqual(string_to_val(string, ua.VariantType.XmlElement), obj) self.assertEqual(val_to_string(obj), string) b = struct_to_binary(obj) obj2 = struct_from_binary(ua.XmlElement, ua.utils.Buffer(b)) self.assertEqual(obj, obj2)
def test_binary_struct_example(self): # Example test so that we can manually control the object that gets # generated and see how it gets serialized/deserialized original = ObjectWithOptionalFields() serialized = struct_to_binary(original) deserialized = struct_from_binary(ObjectWithOptionalFields, ua.utils.Buffer(serialized)) self.assertEqual(len(original.ua_switches), len(deserialized.ua_switches)) self.assertEqual(len(original.ua_types), len(deserialized.ua_types)) for field, _ in original.ua_types: self.assertEqual(getattr(original, field), getattr(deserialized, field))
def open_secure_channel(self, params): self.logger.info("open_secure_channel") request = ua.OpenSecureChannelRequest() request.Parameters = params future = self._send_request(request, message_type=ua.MessageType.SecureOpen) response = struct_from_binary(ua.OpenSecureChannelResponse, future.result(self.timeout)) response.ResponseHeader.ServiceResult.check() self._connection.set_channel(response.Parameters, params.RequestType, params.ClientNonce) return response.Parameters
def open_secure_channel(self, algohdr, seqhdr, body): request = struct_from_binary(ua.OpenSecureChannelRequest, body) self._connection.select_policy( algohdr.SecurityPolicyURI, algohdr.SenderCertificate, request.Parameters.SecurityMode) channel = self._connection.open(request.Parameters, self.iserver) # send response response = ua.OpenSecureChannelResponse() response.Parameters = channel self.send_response(request.RequestHeader.RequestHandle, None, seqhdr, response, ua.MessageType.SecureOpen)
def test_status_code_to_string(self): # serialize a status code and deserialize it, name and doc resolution should work just fine statuscode = ua.StatusCode(ua.StatusCodes.BadNotConnected) statuscode2 = struct_from_binary(ua.StatusCode, io.BytesIO(struct_to_binary(ua.StatusCode(ua.StatusCodes.BadNotConnected)))) self.assertEqual(statuscode, statuscode2) self.assertEqual(statuscode.value, statuscode2.value) # properties that are not serialized should still translate properly self.assertEqual(statuscode.name, statuscode2.name) self.assertEqual(statuscode.doc, statuscode2.doc)
def open_secure_channel(self, algohdr, seqhdr, body): request = struct_from_binary(ua.OpenSecureChannelRequest, body) self._connection.select_policy( algohdr.SecurityPolicyURI, algohdr.SenderCertificate, request.Parameters.SecurityMode) channel = self._connection.open(request.Parameters, self.iserver) # send response response = ua.OpenSecureChannelResponse() response.Parameters = channel self.send_response(request.RequestHeader.RequestHandle, None, seqhdr, response, ua.MessageType.SecureOpen)
def process_message(self, algohdr, seqhdr, body): typeid = nodeid_from_binary(body) requesthdr = struct_from_binary(ua.RequestHeader, body) try: return self._process_message(typeid, requesthdr, algohdr, seqhdr, body) except utils.ServiceError as e: status = ua.StatusCode(e.code) response = ua.ServiceFault() response.ResponseHeader.ServiceResult = status self.logger.info("sending service fault response: %s (%s)", status.doc, status.name) self.send_response(requesthdr.RequestHandle, algohdr, seqhdr, response) return True
def open_secure_channel(self, params): self.logger.info("open_secure_channel") request = ua.OpenSecureChannelRequest() request.Parameters = params future = self._send_request(request, message_type=ua.MessageType.SecureOpen) # FIXME: we have a race condition here # we can get a packet with the new token id before we reach to store it.. response = struct_from_binary(ua.OpenSecureChannelResponse, future.result(self.timeout)) response.ResponseHeader.ServiceResult.check() self._connection.set_channel(response.Parameters) return response.Parameters
def _call_publish_callback(self, future): self.logger.info("call_publish_callback") data = future.result() # check if answer looks ok try: self._uasocket.check_answer(data, "while waiting for publish response") except BadTimeout: # Spec Part 4, 7.28 self.publish() return except BadNoSubscription: # Spec Part 5, 13.8.1 # BadNoSubscription is expected after deleting the last subscription. # # We should therefore also check for len(self._publishcallbacks) == 0, but # this gets us into trouble if a Publish response arrives before the # DeleteSubscription response. # # We could remove the callback already when sending the DeleteSubscription request, # but there are some legitimate reasons to keep them around, such as when the server # responds with "BadTimeout" and we should try again later instead of just removing # the subscription client-side. # # There are a variety of ways to act correctly, but the most practical solution seems # to be to just ignore any BadNoSubscription responses. self.logger.info("BadNoSubscription received, ignoring because it's probably valid.") return # parse publish response try: response = struct_from_binary(ua.PublishResponse, data) self.logger.debug(response) except Exception: # INFO: catching the exception here might be obsolete because we already # catch BadTimeout above. However, it's not really clear what this code # does so it stays in, doesn't seem to hurt. self.logger.exception("Error parsing notificatipn from server") self.publish([]) # send publish request ot server so he does stop sending notifications return # look for callback try: callback = self._publishcallbacks[response.Parameters.SubscriptionId] except KeyError: self.logger.warning("Received data for unknown subscription: %s ", response.Parameters.SubscriptionId) return # do callback try: callback(response.Parameters) except Exception: # we call client code, catch everything! self.logger.exception("Exception while calling user callback: %s")
def close_session(self, deletesubscriptions): self.logger.info("close_session") request = ua.CloseSessionRequest() request.DeleteSubscriptions = deletesubscriptions data = self._uasocket.send_request(request) response = struct_from_binary(ua.CloseSessionResponse, data) try: response.ResponseHeader.ServiceResult.check() except BadSessionClosed: # Problem: closing the session with open publish requests leads to BadSessionClosed responses # we can just ignore it therefore. # Alternatively we could make sure that there are no publish requests in flight when # closing the session. pass
def _receive(self, msg): self._check_incoming_chunk(msg) self._incoming_parts.append(msg) if msg.MessageHeader.ChunkType == ua.ChunkType.Intermediate: return None if msg.MessageHeader.ChunkType == ua.ChunkType.Abort: err = struct_from_binary(ua.ErrorMessage, ua.utils.Buffer(msg.Body)) logger.warning("Message %s aborted: %s", msg, err) # specs Part 6, 6.7.3 say that aborted message shall be ignored # and SecureChannel should not be closed self._incoming_parts = [] return None elif msg.MessageHeader.ChunkType == ua.ChunkType.Single: message = ua.Message(self._incoming_parts) self._incoming_parts = [] return message else: raise ua.UaError("Unsupported chunk type: {0}".format(msg))
def read(self, parameters): self.logger.info("read") request = ua.ReadRequest() request.Parameters = parameters data = self._uasocket.send_request(request) response = struct_from_binary(ua.ReadResponse, data) self.logger.debug(response) response.ResponseHeader.ServiceResult.check() # cast to Enum attributes that need to for idx, rv in enumerate(parameters.NodesToRead): if rv.AttributeId == ua.AttributeIds.NodeClass: dv = response.Results[idx] if dv.StatusCode.is_good(): dv.Value.Value = ua.NodeClass(dv.Value.Value) elif rv.AttributeId == ua.AttributeIds.ValueRank: dv = response.Results[idx] if dv.StatusCode.is_good() and dv.Value.Value in (-3, -2, -1, 0, 1, 2, 3, 4): dv.Value.Value = ua.ValueRank(dv.Value.Value) return response.Results