public InheritedEntityAvro DeserializeAvro(byte[] bytes) { using (var ms = new MemoryStream(bytes)) { var dec = new BinaryDecoder(ms); var reader = new SpecificDefaultReader(InheritedEntityAvro._SCHEMA, InheritedEntityAvro._SCHEMA); var regenAvroMsg = new InheritedEntityAvro(); reader.Read(regenAvroMsg, dec); return regenAvroMsg; } }
/// <summary> /// Reads the schema information from a XML document. /// </summary> public void LoadFromBinary(ISystemContext context, Stream istrm, bool updateTables) { ServiceMessageContext messageContext = new ServiceMessageContext(); messageContext.NamespaceUris = context.NamespaceUris; messageContext.ServerUris = context.ServerUris; messageContext.Factory = context.EncodeableFactory; using (BinaryDecoder decoder = new BinaryDecoder(istrm, messageContext)) { // check if a namespace table was provided. NamespaceTable namespaceUris = new NamespaceTable(); if (!decoder.LoadStringTable(namespaceUris)) { namespaceUris = null; } // update namespace table. if (updateTables) { if (namespaceUris != null && context.NamespaceUris != null) { for (int ii = 0; ii < namespaceUris.Count; ii++) { context.NamespaceUris.GetIndexOrAppend(namespaceUris.GetString((uint)ii)); } } } // check if a server uri table was provided. StringTable serverUris = new StringTable(); if (namespaceUris != null && namespaceUris.Count > 1) { serverUris.Append(namespaceUris.GetString(1)); } if (!decoder.LoadStringTable(serverUris)) { serverUris = null; } // update server table. if (updateTables) { if (serverUris != null && context.ServerUris != null) { for (int ii = 0; ii < serverUris.Count; ii++) { context.ServerUris.GetIndexOrAppend(serverUris.GetString((uint)ii)); } } } // setup the mappings to use during decoding. decoder.SetMappingTables(namespaceUris, serverUris); int count = decoder.ReadInt32(null); for (int ii = 0; ii < count; ii++) { NodeState state = NodeState.LoadNode(context, decoder); this.Add(state); } } }
protected void ReadAsymmetricMessageHeader( BinaryDecoder decoder, X509Certificate2 receiverCertificate, out uint secureChannelId, out X509Certificate2 senderCertificate, out string securityPolicyUri) { senderCertificate = null; uint messageType = decoder.ReadUInt32(null); uint messageSize = decoder.ReadUInt32(null); // decode security header. byte[] certificateData = null; byte[] thumbprintData = null; try { secureChannelId = decoder.ReadUInt32(null); securityPolicyUri = decoder.ReadString(null, TcpMessageLimits.MaxSecurityPolicyUriSize); certificateData = decoder.ReadByteString(null, TcpMessageLimits.MaxCertificateSize); thumbprintData = decoder.ReadByteString(null, TcpMessageLimits.CertificateThumbprintSize); } catch (Exception e) { throw ServiceResultException.Create( StatusCodes.BadSecurityChecksFailed, e, "The asymmetric security header could not be parsed."); } // verify sender certificate. if (certificateData != null && certificateData.Length > 0) { senderCertificate = CertificateFactory.Create(certificateData, true); try { string thumbprint = senderCertificate.Thumbprint; if (thumbprint == null) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "Invalid certificate thumbprint."); } } catch (Exception e) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, e, "The sender's certificate could not be parsed."); } } else { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The sender's certificate was not specified."); } } // verify receiver thumbprint. if (thumbprintData != null && thumbprintData.Length > 0) { if (receiverCertificate.Thumbprint.ToUpperInvariant() != GetThumbprintString(thumbprintData)) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint is not valid."); } } else { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint was not specified."); } } }
/// <summary> /// Processes a request message. /// </summary> private bool ProcessRequestMessage(uint messageType, ArraySegment <byte> messageChunk) { // validate the channel state. if (State != TcpChannelState.Open) { ForceChannelFault(StatusCodes.BadTcpMessageTypeInvalid, "Client sent an unexpected request message."); return(false); } // validate security on the message. TcpChannelToken token = null; uint requestId = 0; uint sequenceNumber = 0; ArraySegment <byte> messageBody; try { messageBody = ReadSymmetricMessage(messageChunk, true, out token, out requestId, out sequenceNumber); // check for replay attacks. if (!VerifySequenceNumber(sequenceNumber, "ProcessRequestMessage")) { throw new ServiceResultException(StatusCodes.BadSequenceNumberInvalid); } if (token == CurrentToken && PreviousToken != null && !PreviousToken.Expired) { Utils.Trace("Server Revoked Token. ChannelId={1}, TokenId={0}", PreviousToken.TokenId, PreviousToken.ChannelId, DateTime.UtcNow); PreviousToken.Lifetime = 0; } } catch (Exception e) { Utils.Trace("Could not verify security on incoming request."); ForceChannelFault(e, StatusCodes.BadSecurityChecksFailed, "Could not verify security on incoming request."); return(false); } BufferCollection chunksToProcess = null; try { // check for an abort. if (TcpMessageType.IsAbort(messageType)) { Utils.Trace("Request was aborted."); chunksToProcess = GetSavedChunks(requestId, messageBody); return(true); } // check if it is necessary to wait for more chunks. if (!TcpMessageType.IsFinal(messageType)) { SaveIntermediateChunk(requestId, messageBody); return(true); } Utils.Trace("Channel {0}: ProcessRequestMessage {1}", ChannelId, requestId); // get the chunks to process. chunksToProcess = GetSavedChunks(requestId, messageBody); // decode the request. IServiceRequest request = BinaryDecoder.DecodeMessage(new ArraySegmentStream(chunksToProcess), null, Quotas.MessageContext) as IServiceRequest; if (request == null) { SendServiceFault(token, requestId, ServiceResult.Create(StatusCodes.BadStructureMissing, "Could not parse request body.")); return(true); } // ensure that only discovery requests come through unsecured. if (DiscoveryOnly) { if (!(request is GetEndpointsRequest || request is FindServersRequest)) { SendServiceFault(token, requestId, ServiceResult.Create(StatusCodes.BadSecurityPolicyRejected, "Channel can only be used for discovery.")); return(true); } } // hand the request to the server. if (m_RequestReceived != null) { m_RequestReceived(this, requestId, request); } return(true); } catch (Exception e) { Utils.Trace(e, "Unexpected error processing request."); SendServiceFault(token, requestId, ServiceResult.Create(e, StatusCodes.BadTcpInternalError, "Unexpected error processing request.")); return(false); } finally { if (chunksToProcess != null) { chunksToProcess.Release(BufferManager, "ProcessRequestMessage"); } } }
public Response(Requestor requestor, RpcRequest request, BinaryDecoder input) { this.requestor = requestor; this.request = request; this.input = input; }
protected ArraySegment<byte> ReadSymmetricMessage( ArraySegment<byte> buffer, bool isRequest, out TcpChannelToken token, out uint requestId, out uint sequenceNumber) { BinaryDecoder decoder = new BinaryDecoder(buffer.Array, buffer.Offset, buffer.Count, Quotas.MessageContext); uint messageType = decoder.ReadUInt32(null); uint messageSize = decoder.ReadUInt32(null); uint channelId = decoder.ReadUInt32(null); uint tokenId = decoder.ReadUInt32(null); // ensure the channel is valid. if (channelId != ChannelId) { throw ServiceResultException.Create( StatusCodes.BadTcpSecureChannelUnknown, "SecureChannelId is not known. ChanneId={0}, CurrentChannelId={1}", channelId, ChannelId); } // check for a message secured with the new token. if (RenewedToken != null && RenewedToken.TokenId == tokenId) { ActivateToken(RenewedToken); } // check if activation of the new token should be forced. if (RenewedToken != null && CurrentToken.ActivationRequired) { ActivateToken(RenewedToken); Utils.Trace("Token #{0} activated forced.", CurrentToken.TokenId); } // check for valid token. TcpChannelToken currentToken = CurrentToken; if (currentToken == null) { throw new ServiceResultException(StatusCodes.BadSecureChannelClosed); } // find the token. if (currentToken.TokenId != tokenId && PreviousToken != null && PreviousToken.TokenId != tokenId) { throw ServiceResultException.Create( StatusCodes.BadTcpSecureChannelUnknown, "TokenId is not known. ChanneId={0}, TokenId={1}, CurrentTokenId={2}, PreviousTokenId={3}", channelId, tokenId, currentToken.TokenId, (PreviousToken != null)?(int)PreviousToken.TokenId:-1); } token = currentToken; // check for a message secured with the token before it expired. if (PreviousToken != null && PreviousToken.TokenId == tokenId) { token = PreviousToken; } // check if token has expired. if (token.Expired) { throw ServiceResultException.Create(StatusCodes.BadTcpSecureChannelUnknown, "Token #{0} has expired. CreatedAt = {1:HH:mm:ss.fff} . Lifetime = {2}", token.TokenId, token.CreatedAt, token.Lifetime); } int headerSize = decoder.Position; if (SecurityMode == MessageSecurityMode.SignAndEncrypt) { // decrypt the message. Decrypt(token, new ArraySegment<byte>(buffer.Array, buffer.Offset + headerSize, buffer.Count - headerSize), isRequest); } if (SecurityMode != MessageSecurityMode.None) { // extract signature. byte[] signature = new byte[SymmetricSignatureSize]; for (int ii = 0; ii < SymmetricSignatureSize; ii++) { signature[ii] = buffer.Array[buffer.Offset+buffer.Count-SymmetricSignatureSize+ii]; } // verify the signature. if (!Verify(token, signature, new ArraySegment<byte>(buffer.Array, buffer.Offset, buffer.Count - SymmetricSignatureSize), isRequest)) { Utils.Trace("Could not verify signature on message."); throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the signature on the message."); } } int paddingCount = 0; if (SecurityMode == MessageSecurityMode.SignAndEncrypt) { // verify padding. int paddingStart = buffer.Offset + buffer.Count - SymmetricSignatureSize - 1; paddingCount = buffer.Array[paddingStart]; for (int ii = paddingStart - paddingCount; ii < paddingStart; ii++) { if (buffer.Array[ii] != paddingCount) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } // add byte for size. paddingCount++; } // extract request id and sequence number. sequenceNumber = decoder.ReadUInt32(null); requestId = decoder.ReadUInt32(null); // return an the data contained in the message. int startOfBody = buffer.Offset + TcpMessageLimits.SymmetricHeaderSize + TcpMessageLimits.SequenceHeaderSize; int sizeOfBody = buffer.Count - TcpMessageLimits.SymmetricHeaderSize - TcpMessageLimits.SequenceHeaderSize - paddingCount - SymmetricSignatureSize; return new ArraySegment<byte>(buffer.Array, startOfBody, sizeOfBody); }
/// <summary> /// Processes an Error message received over the socket. /// </summary> protected bool ProcessErrorMessage(uint messageType, ArraySegment<byte> messageChunk) { // Utils.Trace("Channel {0}: ProcessErrorMessage()", ChannelId); // read request buffer sizes. MemoryStream istrm = new MemoryStream(messageChunk.Array, messageChunk.Offset, messageChunk.Count, false); BinaryDecoder decoder = new BinaryDecoder(istrm, Quotas.MessageContext); istrm.Seek(TcpMessageLimits.MessageTypeAndSize, SeekOrigin.Current); try { ServiceResult error = ReadErrorMessageBody(decoder); // check if a handshake is in progress if (m_handshakeOperation != null) { m_handshakeOperation.Fault(error); return false; } // handle the fatal error. ForceReconnect(error); return false; } finally { decoder.Close(); } }
/// <summary> /// Processes an OpenSecureChannel request message. /// </summary> protected ArraySegment<byte> ReadAsymmetricMessage( ArraySegment<byte> buffer, X509Certificate2 receiverCertificate, out uint channelId, out X509Certificate2 senderCertificate, out uint requestId, out uint sequenceNumber) { BinaryDecoder decoder = new BinaryDecoder(buffer.Array, buffer.Offset, buffer.Count, Quotas.MessageContext); string securityPolicyUri = null; //X509Certificate2Collection senderCertificateChain; // parse the security header. ReadAsymmetricMessageHeader( decoder, receiverCertificate, out channelId, out senderCertificate, out securityPolicyUri); /*senderCertificate = null; if (senderCertificateChain != null && senderCertificateChain.Count > 0) { senderCertificate = senderCertificateChain[0]; }*/ // validate the sender certificate. if (senderCertificate != null && Quotas.CertificateValidator != null && securityPolicyUri != SecurityPolicies.None) { //(Quotas.CertificateValidator as Opc.Ua.CertificateValidator.WcfValidatorWrapper).Validate(senderCertificateChain); Quotas.CertificateValidator.Validate(senderCertificate); } // check if this is the first open secure channel request. if (!m_uninitialized) { if (securityPolicyUri != m_securityPolicyUri) { throw ServiceResultException.Create(StatusCodes.BadSecurityPolicyRejected, "Cannot change the security policy after creating the channnel."); } } else { // find a matching endpoint description. if (m_endpoints != null) { foreach (EndpointDescription endpoint in m_endpoints) { // There may be multiple endpoints with the same securityPolicyUri. // Just choose the first one that matches. This choice will be re-examined // When the OpenSecureChannel request body is processed. if (endpoint.SecurityPolicyUri == securityPolicyUri || (securityPolicyUri == SecurityPolicies.None && endpoint.SecurityMode == MessageSecurityMode.None)) { m_securityMode = endpoint.SecurityMode; m_securityPolicyUri = securityPolicyUri; m_discoveryOnly = false; m_uninitialized = false; m_selectedEndpoint = endpoint; // recalculate the key sizes. CalculateSymmetricKeySizes(); break; } } } // allow a discovery only channel with no security if policy not suppported if (m_uninitialized) { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadSecurityPolicyRejected, "The security policy is not supported."); } m_securityMode = MessageSecurityMode.None; m_securityPolicyUri = SecurityPolicies.None; m_discoveryOnly = true; m_uninitialized = false; m_selectedEndpoint = null; } } int headerSize = decoder.Position; // decrypt the body. ArraySegment<byte> plainText = Decrypt( new ArraySegment<byte>(buffer.Array, buffer.Offset + headerSize, buffer.Count - headerSize), new ArraySegment<byte>(buffer.Array, buffer.Offset, headerSize), receiverCertificate); // extract signature. int signatureSize = GetAsymmetricSignatureSize(senderCertificate); byte[] signature = new byte[signatureSize]; for (int ii = 0; ii < signatureSize; ii++) { signature[ii] = plainText.Array[plainText.Offset+plainText.Count-signatureSize+ii]; } // verify the signature. ArraySegment<byte> dataToVerify = new ArraySegment<byte>(plainText.Array, plainText.Offset, plainText.Count-signatureSize); if (!Verify(dataToVerify, signature, senderCertificate)) { Utils.Trace("Could not verify signature on message."); throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the signature on the message."); } // verify padding. int paddingCount = 0; if (SecurityMode != MessageSecurityMode.None) { int paddingEnd = -1; if (receiverCertificate.PublicKey.Key.KeySize > TcpMessageLimits.KeySizeExtraPadding) { paddingEnd = plainText.Offset + plainText.Count - signatureSize - 1; paddingCount = plainText.Array[paddingEnd - 1] + plainText.Array[paddingEnd] * 256; //parse until paddingStart-1; the last one is actually the extrapaddingsize for (int ii = paddingEnd - paddingCount; ii < paddingEnd; ii++) { if (plainText.Array[ii] != plainText.Array[paddingEnd - 1]) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } } else { paddingEnd = plainText.Offset + plainText.Count - signatureSize - 1; paddingCount = plainText.Array[paddingEnd]; for (int ii = paddingEnd - paddingCount; ii < paddingEnd; ii++) { if (plainText.Array[ii] != plainText.Array[paddingEnd]) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } } paddingCount++; } // decode message. decoder = new BinaryDecoder( plainText.Array, plainText.Offset + headerSize, plainText.Count - headerSize, Quotas.MessageContext); sequenceNumber = decoder.ReadUInt32(null); requestId = decoder.ReadUInt32(null); headerSize += decoder.Position; decoder.Close(); // Utils.Trace("Security Policy: {0}", SecurityPolicyUri); // Utils.Trace("Sender Certificate: {0}", (senderCertificate != null)?senderCertificate.Subject:"(none)"); // return the body. return new ArraySegment<byte>( plainText.Array, plainText.Offset + headerSize, plainText.Count - headerSize - signatureSize - paddingCount); }
private async Task<IServiceResponse> ReceiveResponseAsync(CancellationToken token = default(CancellationToken)) { await this.receivingSemaphore.WaitAsync(token).ConfigureAwait(false); try { token.ThrowIfCancellationRequested(); this.ThrowIfClosedOrNotOpening(); uint sequenceNumber; uint requestId; int paddingHeaderSize; int plainHeaderSize; int bodySize; int paddingSize; var bodyStream = SerializableBytes.CreateWritableStream(); var bodyDecoder = new BinaryDecoder(bodyStream, this); try { // read chunks int chunkCount = 0; bool isFinal = false; do { chunkCount++; if (this.LocalMaxChunkCount > 0 && chunkCount > this.LocalMaxChunkCount) { throw new ServiceResultException(StatusCodes.BadEncodingLimitsExceeded); } var count = await this.ReceiveAsync(this.receiveBuffer, 0, (int)this.LocalReceiveBufferSize, token).ConfigureAwait(false); if (count == 0) { return null; } var stream = new MemoryStream(this.receiveBuffer, 0, count, true, true); var decoder = new BinaryDecoder(stream, this); try { uint channelId; uint messageType = decoder.ReadUInt32(null); int messageLength = (int)decoder.ReadUInt32(null); Debug.Assert(count == messageLength, "Bytes received not equal to encoded Message length"); switch (messageType) { case UaTcpMessageTypes.MSGF: case UaTcpMessageTypes.MSGC: // header channelId = decoder.ReadUInt32(null); if (channelId != this.ChannelId) { throw new ServiceResultException(StatusCodes.BadTcpSecureChannelUnknown); } // symmetric security header var tokenId = decoder.ReadUInt32(null); // detect new token if (tokenId != this.currentServerTokenId) { this.currentServerTokenId = tokenId; // update with new keys if (this.symIsSigned) { this.symVerifier.Key = this.serverSigningKey; if (this.symIsEncrypted) { this.currentServerEncryptingKey = this.serverEncryptingKey; this.currentServerInitializationVector = this.serverInitializationVector; this.symDecryptor = this.symEncryptionAlgorithm.CreateDecryptor(this.currentServerEncryptingKey, this.currentServerInitializationVector); } } } plainHeaderSize = decoder.Position; // decrypt if (this.symIsEncrypted) { using (var symDecryptor = this.symEncryptionAlgorithm.CreateDecryptor(this.currentServerEncryptingKey, this.currentServerInitializationVector)) { int inputCount = messageLength - plainHeaderSize; Debug.Assert(inputCount % symDecryptor.InputBlockSize == 0, "Input data is not an even number of encryption blocks."); symDecryptor.TransformBlock(this.receiveBuffer, plainHeaderSize, inputCount, this.receiveBuffer, plainHeaderSize); symDecryptor.TransformFinalBlock(this.receiveBuffer, messageLength, 0); } } // verify if (this.symIsSigned) { var datalen = messageLength - this.symSignatureSize; byte[] signature = this.symVerifier.ComputeHash(this.receiveBuffer, 0, datalen); if (!signature.SequenceEqual(this.receiveBuffer.AsArraySegment(datalen, this.symSignatureSize))) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed); } } // read sequence header sequenceNumber = decoder.ReadUInt32(null); requestId = decoder.ReadUInt32(null); // body if (this.symIsEncrypted) { if (this.symEncryptionBlockSize > 256) { paddingHeaderSize = 2; paddingSize = BitConverter.ToInt16(this.receiveBuffer, messageLength - this.symSignatureSize - paddingHeaderSize); } else { paddingHeaderSize = 1; paddingSize = this.receiveBuffer[messageLength - this.symSignatureSize - paddingHeaderSize]; } bodySize = messageLength - plainHeaderSize - SequenceHeaderSize - paddingSize - paddingHeaderSize - this.symSignatureSize; } else { bodySize = messageLength - plainHeaderSize - SequenceHeaderSize - this.symSignatureSize; } bodyStream.Write(this.receiveBuffer, plainHeaderSize + SequenceHeaderSize, bodySize); isFinal = messageType == UaTcpMessageTypes.MSGF; break; case UaTcpMessageTypes.OPNF: case UaTcpMessageTypes.OPNC: // header channelId = decoder.ReadUInt32(null); // asymmetric header var securityPolicyUri = decoder.ReadString(null); var serverCertificateByteString = decoder.ReadByteString(null); var clientThumbprint = decoder.ReadByteString(null); plainHeaderSize = decoder.Position; // decrypt if (this.asymIsEncrypted) { byte[] cipherTextBlock = new byte[this.asymLocalCipherTextBlockSize]; int jj = plainHeaderSize; for (int ii = plainHeaderSize; ii < messageLength; ii += this.asymLocalCipherTextBlockSize) { Buffer.BlockCopy(this.receiveBuffer, ii, cipherTextBlock, 0, this.asymLocalCipherTextBlockSize); // decrypt with local private key. byte[] plainTextBlock = this.LocalPrivateKey.Decrypt(cipherTextBlock, this.asymEncryptionPadding); Debug.Assert(plainTextBlock.Length == this.asymLocalPlainTextBlockSize, "Decrypted block length was not as expected."); Buffer.BlockCopy(plainTextBlock, 0, this.receiveBuffer, jj, this.asymLocalPlainTextBlockSize); jj += this.asymLocalPlainTextBlockSize; } messageLength = jj; decoder.Position = plainHeaderSize; } // verify if (this.asymIsSigned) { // verify with remote public key. var datalen = messageLength - this.asymRemoteSignatureSize; if (!this.RemotePublicKey.VerifyData(this.receiveBuffer, 0, datalen, this.receiveBuffer.AsArraySegment(datalen, this.asymRemoteSignatureSize).ToArray(), this.asymSignatureHashAlgorithmName, RSASignaturePadding.Pkcs1)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed); } } // sequence header sequenceNumber = decoder.ReadUInt32(null); requestId = decoder.ReadUInt32(null); // body if (this.asymIsEncrypted) { if (this.asymLocalCipherTextBlockSize > 256) { paddingHeaderSize = 2; paddingSize = BitConverter.ToInt16(this.receiveBuffer, messageLength - this.asymRemoteSignatureSize - paddingHeaderSize); } else { paddingHeaderSize = 1; paddingSize = this.receiveBuffer[messageLength - this.asymRemoteSignatureSize - paddingHeaderSize]; } bodySize = messageLength - plainHeaderSize - SequenceHeaderSize - paddingSize - paddingHeaderSize - this.asymRemoteSignatureSize; } else { bodySize = messageLength - plainHeaderSize - SequenceHeaderSize - this.asymRemoteSignatureSize; } bodyStream.Write(this.receiveBuffer, plainHeaderSize + SequenceHeaderSize, bodySize); isFinal = messageType == UaTcpMessageTypes.OPNF; break; case UaTcpMessageTypes.ERRF: case UaTcpMessageTypes.MSGA: case UaTcpMessageTypes.OPNA: case UaTcpMessageTypes.CLOA: var code = (StatusCode)decoder.ReadUInt32(null); var message = decoder.ReadString(null); throw new ServiceResultException(code, message); default: throw new ServiceResultException(StatusCodes.BadUnknownResponse); } if (this.LocalMaxMessageSize > 0 && bodyStream.Position > this.LocalMaxMessageSize) { throw new ServiceResultException(StatusCodes.BadEncodingLimitsExceeded); } } finally { decoder.Dispose(); } } while (!isFinal); bodyStream.Seek(0L, SeekOrigin.Begin); var nodeId = bodyDecoder.ReadNodeId(null); IServiceResponse response; // fast path if (nodeId == PublishResponseNodeId) { response = new PublishResponse(); } else if (nodeId == ReadResponseNodeId) { response = new ReadResponse(); } else { // find node in dictionary Type type2; if (!BinaryEncodingIdToTypeDictionary.TryGetValue(NodeId.ToExpandedNodeId(nodeId, this.NamespaceUris), out type2)) { throw new ServiceResultException(StatusCodes.BadEncodingError, "NodeId not registered in dictionary."); } // create response response = (IServiceResponse)Activator.CreateInstance(type2); } // set properties from message stream response.Decode(bodyDecoder); return response; } finally { bodyDecoder.Dispose(); } } finally { this.receivingSemaphore.Release(); } }
public IGenericRecord Read(Stream inputStream) { try { var decoder = new BinaryDecoder(inputStream); var avroRecord = _reader.Read(default, decoder);
public static int AvroDecodeInt(BinaryReader stream) { BinaryDecoder _e = new BinaryDecoder(stream.BaseStream); return(_e.ReadInt()); }
public bool Decode(BinaryDecoder decoder) { if (!BinaryCodec.Decode(decoder, out _id)) { return(false); } if (!BinaryCodec.Decode(decoder, out _name)) { return(false); } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _tileMaterial = (E_TileMaterial)enumValue; } if (!BinaryCodec.Decode(decoder, out _isMove)) { return(false); } if (!BinaryCodec.Decode(decoder, out _groupname)) { return(false); } if (!BinaryCodec.Decode(decoder, out _randomCount)) { return(false); } if (!BinaryCodec.Decode(decoder, out _isAutoTile)) { return(false); } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _autoTileType = (E_AutoTile)enumValue; } if (!BinaryCodec.Decode(decoder, out _subPath)) { return(false); } if (!BinaryCodec.Decode(decoder, out _spritePack)) { return(false); } { ushort _size = 0; if (!BinaryCodec.Decode(decoder, out _size)) { return(false); } sprites.Capacity = _size; for (int i = 0; i < _size; ++i) { string item = null; if (!BinaryCodec.Decode(decoder, out item)) { return(false); } sprites.Add(item); } } return(true); }
public bool Decode(BinaryDecoder decoder) { if (!BinaryCodec.Decode(decoder, out _id)) { return(false); } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _tileMapType = (E_TileMap)enumValue; } if (!BinaryCodec.Decode(decoder, out _name)) { return(false); } if (!BinaryCodec.DecodeUnicodeString(decoder, out _displayName)) { return(false); } if (!BinaryCodec.Decode(decoder, out _sizeX)) { return(false); } if (!BinaryCodec.Decode(decoder, out _sizeY)) { return(false); } if (!BinaryCodec.Decode(decoder, out _isFog)) { return(false); } if (!BinaryCodec.Decode(decoder, out _groupname)) { return(false); } { ushort _size = 0; if (!BinaryCodec.Decode(decoder, out _size)) { return(false); } bgTileSets.Capacity = _size; for (int i = 0; i < _size; ++i) { string item = null; if (!BinaryCodec.Decode(decoder, out item)) { return(false); } bgTileSets.Add(item); } } { ushort _size = 0; if (!BinaryCodec.Decode(decoder, out _size)) { return(false); } objectTileSets.Capacity = _size; for (int i = 0; i < _size; ++i) { string item = null; if (!BinaryCodec.Decode(decoder, out item)) { return(false); } objectTileSets.Add(item); } } return(true); }
/// <summary> /// Decode a scalar type /// </summary> /// <param name="binaryDecoder"></param> /// <param name="builtInType"></param> /// <returns>The decoded object</returns> private object DecodeRawScalar(BinaryDecoder binaryDecoder, byte builtInType) { switch ((BuiltInType)builtInType) { case BuiltInType.Boolean: return(binaryDecoder.ReadBoolean(null)); case BuiltInType.SByte: return(binaryDecoder.ReadSByte(null)); case BuiltInType.Byte: return(binaryDecoder.ReadByte(null)); case BuiltInType.Int16: return(binaryDecoder.ReadInt16(null)); case BuiltInType.UInt16: return(binaryDecoder.ReadUInt16(null)); case BuiltInType.Int32: return(binaryDecoder.ReadInt32(null)); case BuiltInType.UInt32: return(binaryDecoder.ReadUInt32(null)); case BuiltInType.Int64: return(binaryDecoder.ReadInt64(null)); case BuiltInType.UInt64: return(binaryDecoder.ReadUInt64(null)); case BuiltInType.Float: return(binaryDecoder.ReadFloat(null)); case BuiltInType.Double: return(binaryDecoder.ReadDouble(null)); case BuiltInType.String: return(binaryDecoder.ReadString(null)); case BuiltInType.DateTime: return(binaryDecoder.ReadDateTime(null)); case BuiltInType.Guid: return(binaryDecoder.ReadGuid(null)); case BuiltInType.ByteString: return(binaryDecoder.ReadByteString(null)); case BuiltInType.XmlElement: return(binaryDecoder.ReadXmlElement(null)); case BuiltInType.NodeId: return(binaryDecoder.ReadNodeId(null)); case BuiltInType.ExpandedNodeId: return(binaryDecoder.ReadExpandedNodeId(null)); case BuiltInType.StatusCode: return(binaryDecoder.ReadStatusCode(null)); case BuiltInType.QualifiedName: return(binaryDecoder.ReadQualifiedName(null)); case BuiltInType.LocalizedText: return(binaryDecoder.ReadLocalizedText(null)); case BuiltInType.DataValue: return(binaryDecoder.ReadDataValue(null)); case BuiltInType.Enumeration: return(binaryDecoder.ReadInt32(null)); case BuiltInType.Variant: return(binaryDecoder.ReadVariant(null)); case BuiltInType.ExtensionObject: return(binaryDecoder.ReadExtensionObject(null)); default: return(null); } }
/// <summary> /// Handles requests arriving from a channel. /// </summary> public async Task SendAsync(HttpContext context) { string message = string.Empty; CancellationToken ct = context.RequestAborted; try { if (m_callback == null) { await WriteResponseAsync(context.Response, message, HttpStatusCode.NotImplemented).ConfigureAwait(false); return; } if (context.Request.ContentType != kApplicationContentType) { message = "HTTPSLISTENER - Unsupported content type."; await WriteResponseAsync(context.Response, message, HttpStatusCode.BadRequest).ConfigureAwait(false); return; } int length = (int)context.Request.ContentLength; byte[] buffer = await ReadBodyAsync(context.Request).ConfigureAwait(false); if (buffer.Length != length) { message = "HTTPSLISTENER - Invalid buffer."; await WriteResponseAsync(context.Response, message, HttpStatusCode.BadRequest).ConfigureAwait(false); return; } IServiceRequest input = (IServiceRequest)BinaryDecoder.DecodeMessage(buffer, null, m_quotas.MessageContext); // extract the JWT token from the HTTP headers. if (input.RequestHeader == null) { input.RequestHeader = new RequestHeader(); } if (NodeId.IsNull(input.RequestHeader.AuthenticationToken) && input.TypeId != DataTypeIds.CreateSessionRequest) { if (context.Request.Headers.ContainsKey(kAuthorizationKey)) { foreach (string value in context.Request.Headers[kAuthorizationKey]) { if (value.StartsWith(kBearerKey, StringComparison.OrdinalIgnoreCase)) { // note: use NodeId(string, uint) to avoid the NodeId.Parse call. input.RequestHeader.AuthenticationToken = new NodeId(value.Substring(kBearerKey.Length + 1).Trim(), 0); } } } } if (!context.Request.Headers.TryGetValue(Profiles.HttpsSecurityPolicyHeader, out var header)) { header = SecurityPolicies.None; } EndpointDescription endpoint = null; foreach (var ep in m_descriptions) { if (ep.EndpointUrl.StartsWith(Utils.UriSchemeHttps, StringComparison.Ordinal)) { if (!string.IsNullOrEmpty(header)) { if (!string.Equals(ep.SecurityPolicyUri, header, StringComparison.Ordinal)) { continue; } } endpoint = ep; break; } } if (endpoint == null && input.TypeId != DataTypeIds.GetEndpointsRequest && input.TypeId != DataTypeIds.FindServersRequest) { message = "Connection refused, invalid security policy."; Utils.LogError(message); await WriteResponseAsync(context.Response, message, HttpStatusCode.Unauthorized).ConfigureAwait(false); return; } // note: do not use Task.Factory.FromAsync here var result = m_callback.BeginProcessRequest( m_listenerId, endpoint, input as IServiceRequest, null, null); IServiceResponse output = m_callback.EndProcessRequest(result); byte[] response = BinaryEncoder.EncodeMessage(output, m_quotas.MessageContext); context.Response.ContentLength = response.Length; context.Response.ContentType = context.Request.ContentType; context.Response.StatusCode = (int)HttpStatusCode.OK; #if NETSTANDARD2_1 || NET5_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER await context.Response.Body.WriteAsync(response.AsMemory(0, response.Length), ct).ConfigureAwait(false); #else await context.Response.Body.WriteAsync(response, 0, response.Length, ct).ConfigureAwait(false); #endif return; } catch (Exception e) { message = "HTTPSLISTENER - Unexpected error processing request."; Utils.LogError(e, message); } await WriteResponseAsync(context.Response, message, HttpStatusCode.InternalServerError).ConfigureAwait(false); }
private bool ProcessHelloMessage(ArraySegment <byte> messageChunk) { // validate the channel state. if (State != TcpChannelState.Connecting) { ForceChannelFault(StatusCodes.BadTcpMessageTypeInvalid, "Client sent an unexpected Hello message."); return(false); } try { MemoryStream istrm = new MemoryStream(messageChunk.Array, messageChunk.Offset, messageChunk.Count, false); BinaryDecoder decoder = new BinaryDecoder(istrm, Quotas.MessageContext); istrm.Seek(TcpMessageLimits.MessageTypeAndSize, SeekOrigin.Current); // read requested buffer sizes. uint protocolVersion = decoder.ReadUInt32(null); uint receiveBufferSize = decoder.ReadUInt32(null); uint sendBufferSize = decoder.ReadUInt32(null); uint maxMessageSize = decoder.ReadUInt32(null); uint maxChunkCount = decoder.ReadUInt32(null); // read the endpoint url. int length = decoder.ReadInt32(null); if (length > 0) { if (length > TcpMessageLimits.MaxEndpointUrlLength) { ForceChannelFault(StatusCodes.BadTcpEndpointUrlInvalid); return(false); } byte[] endpointUrl = new byte[length]; for (int ii = 0; ii < endpointUrl.Length; ii++) { endpointUrl[ii] = decoder.ReadByte(null); } if (!SetEndpointUrl(new UTF8Encoding().GetString(endpointUrl, 0, endpointUrl.Length))) { ForceChannelFault(StatusCodes.BadTcpEndpointUrlInvalid); return(false); } } decoder.Close(); // update receive buffer size. if (receiveBufferSize < ReceiveBufferSize) { ReceiveBufferSize = (int)receiveBufferSize; } if (ReceiveBufferSize < TcpMessageLimits.MinBufferSize) { ReceiveBufferSize = TcpMessageLimits.MinBufferSize; } // update send buffer size. if (sendBufferSize < SendBufferSize) { SendBufferSize = (int)sendBufferSize; } if (SendBufferSize < TcpMessageLimits.MinBufferSize) { SendBufferSize = TcpMessageLimits.MinBufferSize; } // update the max message size. if (maxMessageSize > 0 && maxMessageSize < MaxResponseMessageSize) { MaxResponseMessageSize = (int)maxMessageSize; } if (MaxResponseMessageSize < SendBufferSize) { MaxResponseMessageSize = SendBufferSize; } // update the max chunk count. if (maxChunkCount > 0 && maxChunkCount < MaxResponseChunkCount) { MaxResponseChunkCount = (int)maxChunkCount; } // send acknowledge. byte[] buffer = BufferManager.TakeBuffer(SendBufferSize, "ProcessHelloMessage"); try { MemoryStream ostrm = new MemoryStream(buffer, 0, SendBufferSize); BinaryEncoder encoder = new BinaryEncoder(ostrm, Quotas.MessageContext); encoder.WriteUInt32(null, TcpMessageType.Acknowledge); encoder.WriteUInt32(null, 0); encoder.WriteUInt32(null, 0); // ProtocolVersion encoder.WriteUInt32(null, (uint)ReceiveBufferSize); encoder.WriteUInt32(null, (uint)SendBufferSize); encoder.WriteUInt32(null, (uint)MaxRequestMessageSize); encoder.WriteUInt32(null, (uint)MaxRequestChunkCount); int size = encoder.Close(); UpdateMessageSize(buffer, 0, size); // now ready for the open or bind request. State = TcpChannelState.Opening; BeginWriteMessage(new ArraySegment <byte>(buffer, 0, size), null); buffer = null; } finally { if (buffer != null) { BufferManager.ReturnBuffer(buffer, "ProcessHelloMessage"); } } } catch (Exception e) { ForceChannelFault(e, StatusCodes.BadTcpInternalError, "Unexpected error while processing a Hello message."); } return(false); }
public static void TestSpecific(string str, object[] result) { Protocol protocol = Protocol.Parse(str); var codegen = new CodeGen(); codegen.AddProtocol(protocol); var compileUnit = codegen.GenerateCode(); // add a constructor to the main class using the passed assignment statements CodeTypeDeclaration ctd = compileUnit.Namespaces[0].Types[(int)result[0]]; CodeConstructor constructor = new CodeConstructor(); constructor.Attributes = MemberAttributes.Public; CodeSnippetExpression snippet = new CodeSnippetExpression((string)result[2]); constructor.Statements.Add(snippet); ctd.Members.Add(constructor); // compile var comparam = new CompilerParameters(new string[] { "mscorlib.dll" }); comparam.ReferencedAssemblies.Add("System.dll"); comparam.ReferencedAssemblies.Add("System.Core.dll"); comparam.ReferencedAssemblies.Add(Type.GetType("Mono.Runtime") != null ? "Mono.CSharp.dll" : "Microsoft.CSharp.dll"); comparam.ReferencedAssemblies.Add("Avro.dll"); comparam.GenerateInMemory = true; var ccp = new Microsoft.CSharp.CSharpCodeProvider(); var units = new CodeCompileUnit[] { compileUnit }; var compres = ccp.CompileAssemblyFromDom(comparam, units); if (compres == null || compres.Errors.Count > 0) { for (int i = 0; i < compres.Errors.Count; i++) Console.WriteLine(compres.Errors[i]); } if (null != compres) Assert.IsTrue(compres.Errors.Count == 0); // create record ISpecificRecord rec = compres.CompiledAssembly.CreateInstance((string)result[1]) as ISpecificRecord; Assert.IsFalse(rec == null); // serialize var stream = new MemoryStream(); var binEncoder = new BinaryEncoder(stream); var writer = new SpecificDefaultWriter(rec.Schema); writer.Write(rec.Schema, rec, binEncoder); // deserialize stream.Position = 0; var decoder = new BinaryDecoder(stream); var reader = new SpecificDefaultReader(rec.Schema, rec.Schema); var rec2 = (ISpecificRecord)reader.Read(null, rec.Schema, rec.Schema, decoder); Assert.IsFalse(rec2 == null); }
public static void TestSpecific(string str, object[] result) { Protocol protocol = Protocol.Parse(str); var codegen = new CodeGen(); codegen.AddProtocol(protocol); var compileUnit = codegen.GenerateCode(); // add a constructor to the main class using the passed assignment statements CodeTypeDeclaration ctd = compileUnit.Namespaces[0].Types[(int)result[0]]; CodeConstructor constructor = new CodeConstructor(); constructor.Attributes = MemberAttributes.Public; CodeSnippetExpression snippet = new CodeSnippetExpression((string)result[2]); constructor.Statements.Add(snippet); ctd.Members.Add(constructor); // add a function to the main class to populate the data // This has been moved from constructor, as it was causing some tests to pass that shouldn't when referencing a blank object on READ. CodeMemberMethod method = new CodeMemberMethod(); method.Attributes = MemberAttributes.Public; method.Name = "Populate"; CodeSnippetExpression snippet2 = new CodeSnippetExpression((string)result[3]); method.Statements.Add(snippet2); ctd.Members.Add(method); // compile var comparam = new CompilerParameters(new string[] { "mscorlib.dll" }); comparam.ReferencedAssemblies.Add("System.dll"); comparam.ReferencedAssemblies.Add("Avro.dll"); comparam.GenerateInMemory = true; var ccp = new Microsoft.CSharp.CSharpCodeProvider(); var units = new CodeCompileUnit[] { compileUnit }; var compres = ccp.CompileAssemblyFromDom(comparam, units); if (compres == null || compres.Errors.Count > 0) { for (int i = 0; i < compres.Errors.Count; i++) Console.WriteLine(compres.Errors[i]); } if (null != compres) Assert.IsTrue(compres.Errors.Count == 0); // create record ISpecificRecord rec = compres.CompiledAssembly.CreateInstance((string)result[1]) as ISpecificRecord; // Call populate to put some data in it. Type recType = rec.GetType(); ; MethodInfo methodInfo = recType.GetMethod("Populate"); methodInfo.Invoke(rec, null); var x1 = compres.CompiledAssembly.FullName; Assert.IsFalse(rec == null); // serialize var stream = new MemoryStream(); var binEncoder = new BinaryEncoder(stream); var writer = new SpecificDefaultWriter(rec.Schema); writer.Write(rec.Schema, rec, binEncoder); // deserialize stream.Position = 0; var decoder = new BinaryDecoder(stream); var reader = new SpecificDefaultReader(rec.Schema, rec.Schema); var rec2 = (ISpecificRecord)reader.Read(null, rec.Schema, rec.Schema, decoder); Assert.IsFalse(rec2 == null); }
/// <summary> /// Handles requests arriving from a channel. /// </summary> public async void SendAsync(HttpContext context) { IAsyncResult result = null; try { if (m_callback == null) { context.Response.ContentLength = 0; context.Response.ContentType = "text/plain"; context.Response.StatusCode = (int)HttpStatusCode.NotImplemented; await context.Response.WriteAsync(string.Empty); return; } byte[] buffer = new byte[(int)context.Request.ContentLength]; lock (m_lock) { Task <int> task = context.Request.Body.ReadAsync(buffer, 0, (int)context.Request.ContentLength); task.Wait(); } IServiceRequest input = (IServiceRequest)BinaryDecoder.DecodeMessage(buffer, null, m_quotas.MessageContext); // extract the JWT token from the HTTP headers. if (input.RequestHeader == null) { input.RequestHeader = new RequestHeader(); } if (NodeId.IsNull(input.RequestHeader.AuthenticationToken) && input.TypeId != DataTypeIds.CreateSessionRequest) { if (context.Request.Headers.Keys.Contains("Authorization")) { foreach (string value in context.Request.Headers["Authorization"]) { if (value.StartsWith("Bearer")) { input.RequestHeader.AuthenticationToken = new NodeId(value.Substring("Bearer ".Length).Trim()); } } } } EndpointDescription endpoint = null; foreach (var ep in m_descriptions) { if (ep.EndpointUrl.StartsWith(Utils.UriSchemeHttps)) { endpoint = ep; break; } } result = m_callback.BeginProcessRequest( m_listenerId, endpoint, input as IServiceRequest, null, null); IServiceResponse output = m_callback.EndProcessRequest(result); byte[] response = BinaryEncoder.EncodeMessage(output, m_quotas.MessageContext); context.Response.ContentLength = response.Length; context.Response.ContentType = context.Request.ContentType; context.Response.StatusCode = (int)HttpStatusCode.OK; await context.Response.Body.WriteAsync(response, 0, response.Length); } catch (Exception e) { Utils.Trace(e, "HTTPSLISTENER - Unexpected error processing request."); context.Response.ContentLength = e.Message.Length; context.Response.ContentType = "text/plain"; context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; await context.Response.WriteAsync(e.Message); } }
private bool ProcessAcknowledgeMessage(ArraySegment<byte> messageChunk) { // Utils.Trace("Channel {0}: ProcessAcknowledgeMessage()", ChannelId); // check state. if (State != TcpChannelState.Connecting) { ForceReconnect(ServiceResult.Create(StatusCodes.BadTcpMessageTypeInvalid, "Server sent an unexpected acknowledge message.")); return false; } // check if operation was abandoned. if (m_handshakeOperation == null) { return false; } // read buffer sizes. MemoryStream istrm = new MemoryStream(messageChunk.Array, messageChunk.Offset, messageChunk.Count); BinaryDecoder decoder = new BinaryDecoder(istrm, Quotas.MessageContext); istrm.Seek(TcpMessageLimits.MessageTypeAndSize, SeekOrigin.Current); try { uint protocolVersion = decoder.ReadUInt32(null); SendBufferSize = (int)decoder.ReadUInt32(null); ReceiveBufferSize = (int)decoder.ReadUInt32(null); int maxMessageSize = (int)decoder.ReadUInt32(null); int maxChunkCount = (int)decoder.ReadUInt32(null); // update the max message size. if (maxMessageSize > 0 && maxMessageSize < MaxRequestMessageSize) { MaxRequestMessageSize = (int)maxMessageSize; } if (MaxRequestMessageSize < SendBufferSize) { MaxRequestMessageSize = SendBufferSize; } // update the max chunk count. if (maxChunkCount > 0 && maxChunkCount < MaxRequestChunkCount) { MaxRequestChunkCount = (int)maxChunkCount; } } finally { decoder.Close(); } // valdiate buffer sizes. if (ReceiveBufferSize < TcpMessageLimits.MinBufferSize) { m_handshakeOperation.Fault(StatusCodes.BadTcpNotEnoughResources, "Server receive buffer size is too small ({0} bytes).", ReceiveBufferSize); return false; } if (SendBufferSize < TcpMessageLimits.MinBufferSize) { m_handshakeOperation.Fault(StatusCodes.BadTcpNotEnoughResources, "Server send buffer size is too small ({0} bytes).", SendBufferSize); return false; } // ready to open the channel. State = TcpChannelState.Opening; try { // check if reconnecting after a socket failure. if (CurrentToken != null) { SendOpenSecureChannelRequest(true); return false; } // open a new connection. SendOpenSecureChannelRequest(false); } catch (Exception e) { m_handshakeOperation.Fault(e, StatusCodes.BadTcpInternalError, "Could not send an Open Secure Channel request."); } return false; }
protected void Decode(byte[] data) { var receivedTime = DateTime.UtcNow; using (var inputStream = new MemoryStream(data)) { // create avro binary decoder to read from memory stream var decoder = new BinaryDecoder(inputStream); var record = Activator.CreateInstance <MessageHeader>(); var reader = new SpecificReader <MessageHeader>(new EtpSpecificReader(record.Schema, record.Schema)); MessageHeader header = reader.Read(record, decoder); // string message = Encoding.UTF8.GetString(inputStream.ToArray()); if (header.Protocol == 0 && header.MessageType == 2) { lock (m_ConnectionLock) { m_HasConnected = true; } var recordSession = Activator.CreateInstance <OpenSession>(); var readerSession = new SpecificReader <OpenSession>(new EtpSpecificReader(recordSession.Schema, recordSession.Schema)); readerSession.Read(recordSession, decoder); string message = ToString(recordSession); var timediff = receivedTime - m_Time; Message?.Invoke(message, timediff.TotalMilliseconds, TraceLevel.Info); } else if (header.Protocol == 3 && header.MessageType == 2) { var responce = Activator.CreateInstance <GetResourcesResponse>(); var bodyreader = new SpecificReader <GetResourcesResponse>(new EtpSpecificReader(responce.Schema, responce.Schema)); GetResourcesResponse bodyheader = bodyreader.Read(responce, decoder); RequestInformation parent; lock (m_RequestInformation) { parent = m_RequestInformation[header.CorrelationId]; } var timediff = receivedTime - parent.RequestTime; string message = ToString(responce); Message?.Invoke(message, timediff.TotalMilliseconds, TraceLevel.Info); if (parent.ChannelItem == null) { ChannelItem channelItem = new ChannelItem() { Name = responce.Resource.Name, Uid = responce.Resource.Uuid, Eml = responce.Resource.Uri, Level = 0, ChildrensCount = responce.Resource.HasChildren }; ChannelItemsReceived?.Invoke(channelItem); } else { ChannelItem channelItem = new ChannelItem() { Name = responce.Resource.Name, Uid = responce.Resource.Uuid, Eml = responce.Resource.Uri, Level = parent.ChannelItem.Level + 1, ChildrensCount = responce.Resource.HasChildren }; ChannelChildrensReceived?.Invoke(channelItem, parent.ChannelItem); } } else if (header.Protocol == 1 && header.MessageType == 2) { var timediff = receivedTime - m_Time; string message = "Channels received: ["; var recordMetadata = Activator.CreateInstance <ChannelMetadata>(); var readerMetadata = new SpecificReader <ChannelMetadata>(new EtpSpecificReader(recordMetadata.Schema, recordMetadata.Schema)); readerMetadata.Read(recordMetadata, decoder); ChannelMetadata metadata = new ChannelMetadata(); metadata.Channels = new List <ChannelMetadataRecord>(); lock (m_ChannelStreamingInfo) { foreach (var channel in recordMetadata.Channels) { if (m_LogCurveEml.Contains(channel.ChannelUri, StringComparer.InvariantCultureIgnoreCase)) { metadata.Channels.Add(channel); ChannelStreamingInfo channelStreamingInfo = new ChannelStreamingInfo() { ChannelId = channel.ChannelId, StartIndex = new StreamingStartIndex() { Item = null }, ReceiveChangeNotification = true }; m_ChannelStreamingInfo.Add(channelStreamingInfo); message = message + $"\n{channel.ChannelId} {channel.ChannelName}"; ChannelMetaDataVM channelMetaData_VM = ETPMapper.Instance().Map <ChannelMetaDataVM>(channel); string json = JsonConvert.SerializeObject(channelMetaData_VM, Formatting.Indented); Message?.Invoke(json, timediff.TotalMilliseconds, TraceLevel.Info); } } ChannelInfoReceived?.Invoke(metadata); } message = message + "\n]"; Message?.Invoke(message, timediff.TotalMilliseconds, TraceLevel.Info); HasDescribing = false; } else if (header.Protocol == 1 && header.MessageType == 3) { var recordData = Activator.CreateInstance <ChannelData>(); var readerdata = new SpecificReader <ChannelData>(new EtpSpecificReader(recordData.Schema, recordData.Schema)); readerdata.Read(recordData, decoder); ChannelDataReceived?.Invoke(recordData.Data); } else if (header.MessageType == 1000) { var timediff = receivedTime - m_Time; var bodyrecord = Activator.CreateInstance <ProtocolException>(); var bodyreader = new SpecificReader <ProtocolException>(new EtpSpecificReader(bodyrecord.Schema, bodyrecord.Schema)); ProtocolException bodyheader = bodyreader.Read(bodyrecord, decoder); string message = $"Error Received ({bodyrecord.ErrorCode}): {bodyrecord.ErrorMessage}"; Message?.Invoke(message, timediff.TotalMilliseconds, TraceLevel.Error); HasDescribing = false; } else { HasDescribing = false; } } }
/// <summary> /// Converts a local value to a remote value. /// </summary> /// <param name="srcValue">The local value.</param> /// <param name="srcType">The data type of the local value.</param> /// <param name="dstType">The data type of the remote value.</param> /// <returns>The remote value.</returns> private object ConvertLocalToRemote(object srcValue, BuiltInType srcType, BuiltInType dstType) { // must determine the type from the source if the containing array is a variant. if (srcType == BuiltInType.Variant) { TypeInfo typeInfo = TypeInfo.Construct(srcValue); srcType = typeInfo.BuiltInType; } // no conversion by default. object dstValue = srcValue; // apply different conversions depending on the data type. switch (dstType) { case BuiltInType.Guid: { dstValue = new Uuid((string)srcValue); break; } case BuiltInType.XmlElement: { XmlDocument document = new XmlDocument(); document.InnerXml = (string)srcValue; dstValue = document.DocumentElement; break; } case BuiltInType.NodeId: { dstValue = GetRemoteNodeId((string)srcValue); break; } case BuiltInType.ExpandedNodeId: { ExpandedNodeId nodeId = ExpandedNodeId.Parse((string)srcValue); dstValue = GetRemoteExpandedNodeId(nodeId); break; } case BuiltInType.QualifiedName: { dstValue = GetRemoteBrowseName((string)srcValue); break; } case BuiltInType.LocalizedText: { dstValue = new LocalizedText((string)srcValue); break; } case BuiltInType.StatusCode: { dstValue = new StatusCode((uint)srcValue); break; } case BuiltInType.ExtensionObject: { BinaryDecoder decoder = new BinaryDecoder((byte[])srcValue, m_localMessageContext); dstValue = decoder.ReadExtensionObject(null); decoder.Close(); break; } default: { if (dstType != srcType && dstType != BuiltInType.Variant && dstType != BuiltInType.Null) { throw ComUtils.CreateComException(ResultIds.E_BADTYPE); } break; } } // all done. return dstValue; }
protected abstract bool ReadData(BinaryDecoder decoder);
protected ArraySegment <byte> ReadSymmetricMessage( ArraySegment <byte> buffer, bool isRequest, out TcpChannelToken token, out uint requestId, out uint sequenceNumber) { BinaryDecoder decoder = new BinaryDecoder(buffer.Array, buffer.Offset, buffer.Count, Quotas.MessageContext); uint messageType = decoder.ReadUInt32(null); uint messageSize = decoder.ReadUInt32(null); uint channelId = decoder.ReadUInt32(null); uint tokenId = decoder.ReadUInt32(null); // ensure the channel is valid. if (channelId != ChannelId) { throw ServiceResultException.Create( StatusCodes.BadTcpSecureChannelUnknown, "SecureChannelId is not known. ChanneId={0}, CurrentChannelId={1}", channelId, ChannelId); } // check for valid token. TcpChannelToken currentToken = CurrentToken; if (currentToken == null) { throw new ServiceResultException(StatusCodes.BadSecureChannelClosed); } // find the token. if (currentToken.TokenId != tokenId && PreviousToken != null && PreviousToken.TokenId != tokenId) { throw ServiceResultException.Create( StatusCodes.BadTcpSecureChannelUnknown, "TokenId is not known. ChanneId={0}, TokenId={1}, CurrentTokenId={2}, PreviousTokenId={3}", channelId, tokenId, currentToken.TokenId, (PreviousToken != null)?(int)PreviousToken.TokenId:-1); } token = currentToken; // check for a message secured with the token before it expired. if (PreviousToken != null && PreviousToken.TokenId == tokenId) { token = PreviousToken; } // check if token has expired. if (token.Expired) { throw ServiceResultException.Create(StatusCodes.BadTcpSecureChannelUnknown, "Token #{0} has expired. Lifetime={1:HH:mm:ss.fff}", token.TokenId, token.CreatedAt); } int headerSize = decoder.Position; if (SecurityMode == MessageSecurityMode.SignAndEncrypt) { // decrypt the message. Decrypt(token, new ArraySegment <byte>(buffer.Array, buffer.Offset + headerSize, buffer.Count - headerSize), isRequest); } if (SecurityMode != MessageSecurityMode.None) { // extract signature. byte[] signature = new byte[SymmetricSignatureSize]; for (int ii = 0; ii < SymmetricSignatureSize; ii++) { signature[ii] = buffer.Array[buffer.Offset + buffer.Count - SymmetricSignatureSize + ii]; } // verify the signature. if (!Verify(token, signature, new ArraySegment <byte>(buffer.Array, buffer.Offset, buffer.Count - SymmetricSignatureSize), isRequest)) { Utils.Trace("Could not verify signature on message."); throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the signature on the message."); } } int paddingCount = 0; if (SecurityMode == MessageSecurityMode.SignAndEncrypt) { // verify padding. int paddingStart = buffer.Offset + buffer.Count - SymmetricSignatureSize - 1; paddingCount = buffer.Array[paddingStart]; for (int ii = paddingStart - paddingCount; ii < paddingStart; ii++) { if (buffer.Array[ii] != paddingCount) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } // add byte for size. paddingCount++; } // extract request id and sequence number. sequenceNumber = decoder.ReadUInt32(null); requestId = decoder.ReadUInt32(null); // return an the data contained in the message. int startOfBody = buffer.Offset + TcpMessageLimits.SymmetricHeaderSize + TcpMessageLimits.SequenceHeaderSize; int sizeOfBody = buffer.Count - TcpMessageLimits.SymmetricHeaderSize - TcpMessageLimits.SequenceHeaderSize - paddingCount - SymmetricSignatureSize; return(new ArraySegment <byte>(buffer.Array, startOfBody, sizeOfBody)); }
/// <summary cref="IClientMessageInspector.AfterReceiveReply" /> public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { // check for fault. if (reply.IsFault) { return; } // parse request parameters. object[] parameters = correlationState as object[]; if (parameters == null || parameters.Length != 3) { throw new InvalidOperationException("Cannot decode request because the IClientMessageInspector not configured properly."); } // extract request parameters. MessageVersion messageVersion = parameters[0] as MessageVersion; string action = parameters[1] as string; IServiceMessage request = parameters[2] as IServiceMessage; object encodeable = null; if (!reply.Properties.TryGetValue(MessageProperties.UnencodedBody, out encodeable)) { // extract binary encoded response from body. XmlDictionaryReader reader = reply.GetReaderAtBodyContents(); reader.MoveToStartElement("InvokeServiceResponse", Namespaces.OpcUaXsd); byte[] response = reader.ReadElementContentAsBase64(); // decode body. try { encodeable = BinaryDecoder.DecodeMessage(response, null, m_messageContext); } catch (Exception e) { ServiceResult error = ServiceResult.Create( e, StatusCodes.BadDecodingError, "Could not decoding incoming response message."); ServiceFault fault = new ServiceFault(); fault.ResponseHeader.RequestHandle = request.GetRequest().RequestHeader.RequestHandle; fault.ResponseHeader.Timestamp = DateTime.UtcNow; fault.ResponseHeader.ServiceResult = error.Code; StringTable stringTable = new StringTable(); fault.ResponseHeader.ServiceDiagnostics = new DiagnosticInfo( error, DiagnosticsMasks.NoInnerStatus, true, stringTable); fault.ResponseHeader.StringTable = stringTable.ToArray(); encodeable = fault; } } object unencodedBody = request.CreateResponse((IServiceResponse)encodeable); // create the unencoded reply message. Message unencodedReply = Message.CreateMessage( messageVersion, action + "Response", unencodedBody); unencodedReply.Headers.MessageId = reply.Headers.MessageId; unencodedReply.Headers.RelatesTo = reply.Headers.RelatesTo; unencodedReply.Properties.Add(MessageProperties.UnencodedBody, unencodedBody); // replace the incoming message. reply = unencodedReply; }
/// <summary> /// Processes an CloseSecureChannel request message. /// </summary> private bool ProcessCloseSecureChannelRequest(uint messageType, ArraySegment <byte> messageChunk) { // validate security on the message. TcpChannelToken token = null; uint requestId = 0; uint sequenceNumber = 0; ArraySegment <byte> messageBody; try { messageBody = ReadSymmetricMessage(messageChunk, true, out token, out requestId, out sequenceNumber); // check for replay attacks. if (!VerifySequenceNumber(sequenceNumber, "ProcessCloseSecureChannelRequest")) { throw new ServiceResultException(StatusCodes.BadSequenceNumberInvalid); } } catch (Exception e) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, e, "Could not verify security on CloseSecureChannel request."); } BufferCollection chunksToProcess = null; try { // check if it is necessary to wait for more chunks. if (!TcpMessageType.IsFinal(messageType)) { SaveIntermediateChunk(requestId, messageBody); return(false); } // get the chunks to process. chunksToProcess = GetSavedChunks(requestId, messageBody); CloseSecureChannelRequest request = BinaryDecoder.DecodeMessage( new ArraySegmentStream(chunksToProcess), typeof(CloseSecureChannelRequest), Quotas.MessageContext) as CloseSecureChannelRequest; if (request == null) { throw ServiceResultException.Create(StatusCodes.BadStructureMissing, "Could not parse CloseSecureChannel request body."); } // send the response. // SendCloseSecureChannelResponse(requestId, token, request); } catch (Exception e) { Utils.Trace(e, "Unexpected error processing OpenSecureChannel request."); } finally { if (chunksToProcess != null) { chunksToProcess.Release(BufferManager, "ProcessCloseSecureChannelRequest"); } Utils.Trace( "TCPSERVERCHANNEL ProcessCloseSecureChannelRequest Socket={0:X8}, ChannelId={1}, TokenId={2}", (Socket != null)?Socket.Handle:0, (CurrentToken != null)?CurrentToken.ChannelId:0, (CurrentToken != null)?CurrentToken.TokenId:0); // close the channel. ChannelClosed(); } return(true); }
/// <summary> /// Reads the trust list. /// </summary> public TrustListDataType ReadTrustList(NodeId trustListId) { if (!IsConnected) { Connect(); } var outputArguments = Session.Call( trustListId, Opc.Ua.MethodIds.FileType_Open, (byte)OpenFileMode.Read); uint fileHandle = (uint)outputArguments[0]; MemoryStream ostrm = new MemoryStream(); try { while (true) { int length = 4096; outputArguments = Session.Call( trustListId, Opc.Ua.MethodIds.FileType_Read, fileHandle, length); byte[] bytes = (byte[])outputArguments[0]; ostrm.Write(bytes, 0, bytes.Length); if (length != bytes.Length) { break; } } } catch (Exception) { throw; } finally { if (IsConnected) { Session.Call( trustListId, Opc.Ua.MethodIds.FileType_Close, fileHandle); } } ostrm.Position = 0; BinaryDecoder decoder = new BinaryDecoder(ostrm, Session.MessageContext); TrustListDataType trustList = new TrustListDataType(); trustList.Decode(decoder); decoder.Close(); ostrm.Close(); return(trustList); }
/// <summary> /// Processes an OpenSecureChannel request message. /// </summary> protected ArraySegment <byte> ReadAsymmetricMessage( ArraySegment <byte> buffer, X509Certificate2 receiverCertificate, out uint channelId, out X509Certificate2 senderCertificate, out uint requestId, out uint sequenceNumber) { BinaryDecoder decoder = new BinaryDecoder(buffer.Array, buffer.Offset, buffer.Count, Quotas.MessageContext); string securityPolicyUri = null; // parse the security header. ReadAsymmetricMessageHeader( decoder, receiverCertificate, out channelId, out senderCertificate, out securityPolicyUri); // validate the sender certificate. if (senderCertificate != null && Quotas.CertificateValidator != null && securityPolicyUri != SecurityPolicies.None) { Quotas.CertificateValidator.Validate(senderCertificate); } // check if this is the first open secure channel request. if (!m_uninitialized) { if (securityPolicyUri != m_securityPolicyUri) { throw ServiceResultException.Create(StatusCodes.BadSecurityPolicyRejected, "Cannot change the security policy after creating the channnel."); } } else { // find a matching endpoint description. if (m_endpoints != null) { foreach (EndpointDescription endpoint in m_endpoints) { // There may be multiple endpoints with the same securityPolicyUri. // Just choose the first one that matches. This choice will be re-examined // When the OpenSecureChannel request body is processed. if (endpoint.SecurityPolicyUri == securityPolicyUri || (securityPolicyUri == SecurityPolicies.None && endpoint.SecurityMode == MessageSecurityMode.None)) { m_securityMode = endpoint.SecurityMode; m_securityPolicyUri = securityPolicyUri; m_discoveryOnly = false; m_uninitialized = false; m_selectedEndpoint = endpoint; // recalculate the key sizes. CalculateSymmetricKeySizes(); break; } } } // allow a discovery only channel with no security if policy not suppported if (m_uninitialized) { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadSecurityPolicyRejected, "The security policy is not supported."); } m_securityMode = MessageSecurityMode.None; m_securityPolicyUri = SecurityPolicies.None; m_discoveryOnly = true; m_uninitialized = false; m_selectedEndpoint = null; } } int headerSize = decoder.Position; // decrypt the body. ArraySegment <byte> plainText = Decrypt( new ArraySegment <byte>(buffer.Array, buffer.Offset + headerSize, buffer.Count - headerSize), new ArraySegment <byte>(buffer.Array, buffer.Offset, headerSize), receiverCertificate); // extract signature. int signatureSize = GetAsymmetricSignatureSize(senderCertificate); byte[] signature = new byte[signatureSize]; for (int ii = 0; ii < signatureSize; ii++) { signature[ii] = plainText.Array[plainText.Offset + plainText.Count - signatureSize + ii]; } // verify the signature. ArraySegment <byte> dataToVerify = new ArraySegment <byte>(plainText.Array, plainText.Offset, plainText.Count - signatureSize); if (!Verify(dataToVerify, signature, senderCertificate)) { Utils.Trace("Could not verify signature on message."); throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the signature on the message."); } // verify padding. int paddingCount = 0; if (SecurityMode != MessageSecurityMode.None) { int paddingEnd = -1; if (receiverCertificate.GetRSAPublicKey().KeySize > TcpMessageLimits.KeySizeExtraPadding) { paddingEnd = plainText.Offset + plainText.Count - signatureSize - 1; paddingCount = plainText.Array[paddingEnd - 1] + plainText.Array[paddingEnd] * 256; //parse until paddingStart-1; the last one is actually the extrapaddingsize for (int ii = paddingEnd - paddingCount; ii < paddingEnd; ii++) { if (plainText.Array[ii] != plainText.Array[paddingEnd - 1]) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } } else { paddingEnd = plainText.Offset + plainText.Count - signatureSize - 1; paddingCount = plainText.Array[paddingEnd]; for (int ii = paddingEnd - paddingCount; ii < paddingEnd; ii++) { if (plainText.Array[ii] != plainText.Array[paddingEnd]) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } } paddingCount++; } // decode message. decoder = new BinaryDecoder( plainText.Array, plainText.Offset + headerSize, plainText.Count - headerSize, Quotas.MessageContext); sequenceNumber = decoder.ReadUInt32(null); requestId = decoder.ReadUInt32(null); headerSize += decoder.Position; decoder.Close(); Utils.Trace("Security Policy: {0}", SecurityPolicyUri); Utils.Trace("Sender Certificate: {0}", (senderCertificate != null)?senderCertificate.Subject:"(none)"); // return the body. return(new ArraySegment <byte>( plainText.Array, plainText.Offset + headerSize, plainText.Count - headerSize - signatureSize - paddingCount)); }
/// <summary> /// Converts a local value to a remote value. /// </summary> /// <param name="srcValue">The local value.</param> /// <param name="srcType">The data type of the local value.</param> /// <param name="dstType">The data type of the remote value.</param> /// <returns>The remote value.</returns> private object ConvertLocalToRemote(object srcValue, BuiltInType srcType, BuiltInType dstType) { // must determine the type from the source if the containing array is a variant. if (srcType == BuiltInType.Variant) { TypeInfo typeInfo = TypeInfo.Construct(srcValue); srcType = typeInfo.BuiltInType; } // no conversion by default. object dstValue = srcValue; // apply different conversions depending on the data type. switch (dstType) { case BuiltInType.Guid: { dstValue = new Uuid((string)srcValue); break; } case BuiltInType.XmlElement: { XmlDocument document = new XmlDocument(); document.InnerXml = (string)srcValue; dstValue = document.DocumentElement; break; } case BuiltInType.NodeId: { dstValue = GetRemoteNodeId((string)srcValue); break; } case BuiltInType.ExpandedNodeId: { ExpandedNodeId nodeId = ExpandedNodeId.Parse((string)srcValue); dstValue = GetRemoteExpandedNodeId(nodeId); break; } case BuiltInType.QualifiedName: { dstValue = GetRemoteBrowseName((string)srcValue); break; } case BuiltInType.LocalizedText: { dstValue = new LocalizedText((string)srcValue); break; } case BuiltInType.StatusCode: { dstValue = new StatusCode((uint)srcValue); break; } case BuiltInType.ExtensionObject: { BinaryDecoder decoder = new BinaryDecoder((byte[])srcValue, m_localMessageContext); dstValue = decoder.ReadExtensionObject(null); decoder.Close(); break; } default: { if (dstType != srcType && dstType != BuiltInType.Variant && dstType != BuiltInType.Null) { throw ComUtils.CreateComException(ResultIds.E_BADTYPE); } break; } } // all done. return(dstValue); }
/// <summary> /// Handles requests arriving from a channel. /// </summary> public async Task SendAsync(HttpContext context) { IAsyncResult result = null; try { if (m_callback == null) { context.Response.ContentLength = 0; context.Response.ContentType = "text/plain"; context.Response.StatusCode = (int)HttpStatusCode.NotImplemented; await context.Response.WriteAsync(string.Empty); return; } if (context.Request.ContentType != "application/octet-stream") { context.Response.ContentLength = 0; context.Response.ContentType = "text/plain"; context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync("HTTPSLISTENER - Unsupported content type."); return; } int length = (int)context.Request.ContentLength; byte[] buffer = await ReadBodyAsync(context.Request); if (buffer.Length != length) { context.Response.ContentLength = 0; context.Response.ContentType = "text/plain"; context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync("HTTPSLISTENER - Couldn't decode buffer."); return; } IServiceRequest input = (IServiceRequest)BinaryDecoder.DecodeMessage(buffer, null, m_quotas.MessageContext); // extract the JWT token from the HTTP headers. if (input.RequestHeader == null) { input.RequestHeader = new RequestHeader(); } if (NodeId.IsNull(input.RequestHeader.AuthenticationToken) && input.TypeId != DataTypeIds.CreateSessionRequest) { if (context.Request.Headers.Keys.Contains("Authorization")) { foreach (string value in context.Request.Headers["Authorization"]) { if (value.StartsWith("Bearer")) { input.RequestHeader.AuthenticationToken = new NodeId(value.Substring("Bearer ".Length).Trim()); } } } } EndpointDescription endpoint = null; foreach (var ep in m_descriptions) { if (ep.EndpointUrl.StartsWith(Utils.UriSchemeHttps)) { endpoint = ep; break; } } IPAddress remoteIP = (context.Connection == null ? null : context.Connection.RemoteIpAddress); int remotePort = (context.Connection == null ? 0 : context.Connection.RemotePort); result = m_callback.BeginProcessRequest( m_listenerId, endpoint, input as IServiceRequest, null, null, remoteIP, // HONEYPOT - pass the remote IP address as an additional parameter. remotePort); // HONEYPOT - pass the remote port as an additional parameter. IServiceResponse output = m_callback.EndProcessRequest(result); byte[] response = BinaryEncoder.EncodeMessage(output, m_quotas.MessageContext); context.Response.ContentLength = response.Length; context.Response.ContentType = context.Request.ContentType; context.Response.StatusCode = (int)HttpStatusCode.OK; await context.Response.Body.WriteAsync(response, 0, response.Length); } catch (Exception e) { Utils.Trace(e, "HTTPSLISTENER - Unexpected error processing request."); context.Response.ContentLength = e.Message.Length; context.Response.ContentType = "text/plain"; context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; await context.Response.WriteAsync(e.Message); } }
public static async Task Run( [EventHubTrigger("table-update", Connection = "eventHubConnection")] EventData[] events, [CosmosDB( databaseName: "Temenos", collectionName: "Events", ConnectionStringSetting = "CosmosDBConnection")] IAsyncCollector <JObject> eventsOut, ILogger log) { log.LogInformation($"ProcessAvroEvent triggered with {events.Count()} events"); var exceptions = new List <Exception>(); foreach (EventData eventData in events) { try { // convert messageBody of this event to a stream MemoryStream stream = new MemoryStream(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count); // skip the first 2 bytes stream.Position = 3; // decode the stream and get the schema number BinaryDecoder decoder = new BinaryDecoder(stream); var magicCode = (decoder.ReadBoolean() == false); var schemaNumber = decoder.ReadLong(); // get the appropriate schema Schema schema = null; switch (schemaNumber) { case 23: schema = Schema.Parse(File.ReadAllText(@"SerializationID-46-CUSTOMER.avsc")); break; case -21: schema = Schema.Parse(File.ReadAllText(@"SerializationID-41-DE_ADDRESS.avsc")); break; default: throw new Exception("Unknown schema nuumber: " + schemaNumber); } // read the avro message using the identified schema var reader = new DefaultReader(schema, schema); GenericRecord record = reader.Read(null, schema, schema, decoder) as GenericRecord; // convert to JSON and return JObject outputData = ConvertToJson(record); eventsOut.AddAsync(outputData).Wait(); // Replace these two lines with your processing logic. await Task.Yield(); } catch (Exception e) { // We need to keep processing the rest of the batch - capture this exception and continue. // TODO: consider capturing details of the message that failed processing so it can be processed again later. exceptions.Add(e); } } // Once processing of the batch is complete, if any messages in the batch failed processing throw an exception so that there is a record of the failure. if (exceptions.Count > 1) { throw new AggregateException(exceptions); } if (exceptions.Count == 1) { throw exceptions.Single(); } }
/// <summary> /// Handles requests arriving from a channel. /// </summary> private IAsyncResult BeginProcessRequest(Stream istrm, string action, string securityPolicyUri, object callbackData) { IAsyncResult result = null; try { if (m_callback != null) { string contentType = WebOperationContext.Current.IncomingRequest.ContentType; Uri uri = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri; string scheme = uri.Scheme + ":"; EndpointDescription endpoint = null; for (int ii = 0; ii < m_descriptions.Count; ii++) { if (m_descriptions[ii].EndpointUrl.StartsWith(scheme)) { if (endpoint == null) { endpoint = m_descriptions[ii]; } if (m_descriptions[ii].SecurityPolicyUri == securityPolicyUri) { endpoint = m_descriptions[ii]; break; } } } IEncodeable request = null; if (String.IsNullOrEmpty(action)) { request = BinaryDecoder.DecodeMessage(istrm, null, this.m_quotas.MessageContext); } else { string requestType = "Opc.Ua." + action + "Request"; request = HttpsTransportChannel.ReadSoapMessage( istrm, action + "Request", Type.GetType(requestType), this.m_quotas.MessageContext); } result = m_callback.BeginProcessRequest( m_listenerId, endpoint, request as IServiceRequest, null, callbackData); } } catch (Exception e) { Utils.Trace(e, "HTTPSLISTENER - Unexpected error processing request."); } return(result); }
// Just a simple unit test, non-exhaustive! Encodes/Decodes 100 1's and 100 0's. private static void UnitTest() { System.IO.MemoryStream output = new System.IO.MemoryStream(); BinaryCoder coder = new BinaryCoder((Stream)output); BinShiftModel adaptiveModel = new BinShiftModel(); adaptiveModel.Inertia = 1; // NB: Skipping try/catch here! for (int i = 0; i < 100; ++i) { adaptiveModel.Encode(coder, 1); } for (int i = 0; i < 100; ++i) { adaptiveModel.Encode(coder, 0); } coder.Flush(); output.Seek(0, SeekOrigin.Begin); BinaryDecoder decoder = new BinaryDecoder(output); BinShiftModel adaptiveDecodeModel = new BinShiftModel(); adaptiveDecodeModel.Inertia = 1; bool works = true; //for (int j = 0; j < 10; ++j) //{ for (int i = 0; i < 100; ++i) { int val = adaptiveDecodeModel.Decode(decoder); if (val != 1) { Console.WriteLine("Decomp (1) error at " + i); works = false; } } for (int i = 0; i < 100; ++i) { int val = adaptiveDecodeModel.Decode(decoder); if (val != 0) { Console.WriteLine("Decomp (0) error at " + i); works = false; } } //} if (!works) { Console.WriteLine("Compression test had an error"); } else { Console.WriteLine("Compression test worked"); } coder.Flush(); // Console.WriteLine("Size of compressed data = " + output.Length); }
/// <summary> /// Processes an OpenSecureChannel request message. /// </summary> private bool ProcessOpenSecureChannelRequest(uint messageType, ArraySegment <byte> messageChunk) { // validate the channel state. if (State != TcpChannelState.Opening && State != TcpChannelState.Open) { ForceChannelFault(StatusCodes.BadTcpMessageTypeInvalid, "Client sent an unexpected OpenSecureChannel message."); return(false); } // parse the security header. uint channelId = 0; X509Certificate2 clientCertificate = null; uint requestId = 0; uint sequenceNumber = 0; ArraySegment <byte> messageBody; try { messageBody = ReadAsymmetricMessage( messageChunk, ServerCertificate, out channelId, out clientCertificate, out requestId, out sequenceNumber); // check for replay attacks. if (!VerifySequenceNumber(sequenceNumber, "ProcessOpenSecureChannelRequest")) { throw new ServiceResultException(StatusCodes.BadSequenceNumberInvalid); } } catch (Exception e) { ServiceResultException innerException = e.InnerException as ServiceResultException; // If the certificate structre, signature and trust list checks pass, we return the other specific validation errors instead of BadSecurityChecksFailed if (innerException != null) { if (innerException.StatusCode == StatusCodes.BadCertificateUntrusted || innerException.StatusCode == StatusCodes.BadCertificateChainIncomplete || innerException.StatusCode == StatusCodes.BadCertificateRevoked || innerException.StatusCode == StatusCodes.BadCertificateInvalid || (innerException.InnerResult != null && innerException.InnerResult.StatusCode == StatusCodes.BadCertificateUntrusted)) { ForceChannelFault(StatusCodes.BadSecurityChecksFailed, e.Message); return(false); } else if (innerException.StatusCode == StatusCodes.BadCertificateTimeInvalid || innerException.StatusCode == StatusCodes.BadCertificateIssuerTimeInvalid || innerException.StatusCode == StatusCodes.BadCertificateHostNameInvalid || innerException.StatusCode == StatusCodes.BadCertificateUriInvalid || innerException.StatusCode == StatusCodes.BadCertificateUseNotAllowed || innerException.StatusCode == StatusCodes.BadCertificateIssuerUseNotAllowed || innerException.StatusCode == StatusCodes.BadCertificateRevocationUnknown || innerException.StatusCode == StatusCodes.BadCertificateIssuerRevocationUnknown || innerException.StatusCode == StatusCodes.BadCertificateIssuerRevoked) { ForceChannelFault(innerException, innerException.StatusCode, e.Message); return(false); } } ForceChannelFault(e, StatusCodes.BadSecurityChecksFailed, "Could not verify security on OpenSecureChannel request."); return(false); } BufferCollection chunksToProcess = null; try { bool firstCall = ClientCertificate == null; // must ensure the same certificate was used. if (ClientCertificate != null) { CompareCertificates(ClientCertificate, clientCertificate, false); } else { ClientCertificate = clientCertificate; } // check if it is necessary to wait for more chunks. if (!TcpMessageType.IsFinal(messageType)) { SaveIntermediateChunk(requestId, messageBody); return(false); } // create a new token. ChannelToken token = CreateToken(); token.TokenId = GetNewTokenId(); token.ServerNonce = CreateNonce(); // get the chunks to process. chunksToProcess = GetSavedChunks(requestId, messageBody); OpenSecureChannelRequest request = (OpenSecureChannelRequest)BinaryDecoder.DecodeMessage( new ArraySegmentStream(chunksToProcess), typeof(OpenSecureChannelRequest), Quotas.MessageContext); if (request == null) { throw ServiceResultException.Create(StatusCodes.BadStructureMissing, "Could not parse OpenSecureChannel request body."); } // check the security mode. if (request.SecurityMode != SecurityMode) { ReviseSecurityMode(firstCall, request.SecurityMode); } // check the client nonce. token.ClientNonce = request.ClientNonce; if (!ValidateNonce(token.ClientNonce)) { throw ServiceResultException.Create(StatusCodes.BadNonceInvalid, "Client nonce is not the correct length or not random enough."); } // choose the lifetime. int lifetime = (int)request.RequestedLifetime; if (lifetime < TcpMessageLimits.MinSecurityTokenLifeTime) { lifetime = TcpMessageLimits.MinSecurityTokenLifeTime; } if (lifetime > 0 && lifetime < token.Lifetime) { token.Lifetime = lifetime; } // check the request type. SecurityTokenRequestType requestType = request.RequestType; if (requestType == SecurityTokenRequestType.Issue && State != TcpChannelState.Opening) { throw ServiceResultException.Create(StatusCodes.BadRequestTypeInvalid, "Cannot request a new token for an open channel."); } if (requestType == SecurityTokenRequestType.Renew && State != TcpChannelState.Open) { // may be reconnecting to a dropped channel. if (State == TcpChannelState.Opening) { // tell the listener to find the channel that can process the request. Listener.ReconnectToExistingChannel( Socket, requestId, sequenceNumber, channelId, ClientCertificate, token, request); Utils.Trace( "{0} ReconnectToExistingChannel Socket={0:X8}, ChannelId={1}, TokenId={2}", ChannelName, (Socket != null) ? Socket.Handle : 0, (CurrentToken != null) ? CurrentToken.ChannelId : 0, (CurrentToken != null) ? CurrentToken.TokenId : 0); // close the channel. ChannelClosed(); // nothing more to do. return(false); } throw ServiceResultException.Create(StatusCodes.BadRequestTypeInvalid, "Cannot request to renew a token for a channel that has not been opened."); } // check the channel id. if (requestType == SecurityTokenRequestType.Renew && channelId != ChannelId) { throw ServiceResultException.Create(StatusCodes.BadTcpSecureChannelUnknown, "Do not recognize the secure channel id provided."); } // log security information. if (requestType == SecurityTokenRequestType.Issue) { Opc.Ua.Security.Audit.SecureChannelCreated( m_ImplementationString, Listener.EndpointUrl.ToString(), Utils.Format("{0}", ChannelId), EndpointDescription, ClientCertificate, ServerCertificate, BinaryEncodingSupport.Required); } else { Opc.Ua.Security.Audit.SecureChannelRenewed( m_ImplementationString, Utils.Format("{0}", ChannelId)); } if (requestType == SecurityTokenRequestType.Renew) { SetRenewedToken(token); } else { ActivateToken(token); } State = TcpChannelState.Open; // send the response. SendOpenSecureChannelResponse(requestId, token, request); // notify reverse CompleteReverseHello(null); // notify any monitors. NotifyMonitors(ServiceResult.Good, false); return(false); } catch (Exception e) { SendServiceFault(requestId, ServiceResult.Create(e, StatusCodes.BadTcpInternalError, "Unexpected error processing OpenSecureChannel request.")); CompleteReverseHello(e); return(false); } finally { if (chunksToProcess != null) { chunksToProcess.Release(BufferManager, "ProcessOpenSecureChannelRequest"); } } }
static void SimpleExample() { // let's construct some data consisting of runs of 0's and 1's. byte[] simpleSampleData = { 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xe0, 0x0c, 0xf0 }; // Naiive adaptive example { System.IO.MemoryStream output = new System.IO.MemoryStream(); BinaryCoder coder = new BinaryCoder((Stream)output); BinShiftModel adaptiveModel = new BinShiftModel(); // the lower the number, the faster it adapts adaptiveModel.Inertia = 1; foreach (byte b in simpleSampleData) { for (int bitpos = 7; bitpos >= 0; --bitpos) { int bit = (int)(b >> bitpos) & 1; // NB: Skipping try/catch here! adaptiveModel.Encode(coder, bit); } } coder.Flush(); Console.WriteLine("Adaptive Output size is " + output.Length); } // Context-switching example { // encode System.IO.MemoryStream output2 = new System.IO.MemoryStream(); BinaryCoder coder2 = new BinaryCoder((Stream)output2); SimpleStaticModel model0 = new SimpleStaticModel(); SimpleStaticModel model1 = new SimpleStaticModel(); model0.SetProb(10f / 128f); model1.SetProb(1f - (10f / 128f)); bool use0Context = true; // 0 bits come first, use the correct model! foreach (byte b in simpleSampleData) { for (int bitpos = 7; bitpos >= 0; --bitpos) { int bit = (int)(b >> bitpos) & 1; // encode using the correct context // NB: Skipping try/catch here! if (use0Context) { model0.Encode(coder2, bit); } else { model1.Encode(coder2, bit); } // switch context AFTER the bit state changes use0Context = (bit == 0 ? true : false); } } coder2.Flush(); Console.WriteLine("Ideal static model with context switch size is " + output2.Length); // The decoder looks much like the encoder. Notice how the context switch occurs only // after a symbol is decoded, exactly as the encoder does it. output2.Seek(0, SeekOrigin.Begin); // decode BinaryDecoder decoder2 = new BinaryDecoder((Stream)output2); SimpleStaticModel staticModel0dec = new SimpleStaticModel(); SimpleStaticModel staticModel1dec = new SimpleStaticModel(); staticModel0dec.SetProb(10f / 128f); staticModel1dec.SetProb(1f - (10f / 128f)); bool use0ContextDec = true; // 0 bits come first, use the correct model! foreach (byte b in simpleSampleData) { for (int bitpos = 7; bitpos >= 0; --bitpos) { int bit = (int)(b >> bitpos) & 1; int decBit; // decode using the correct context! // NB: Skipping try/catch here! if (use0ContextDec) { decBit = staticModel0dec.Decode(decoder2); } else { decBit = staticModel1dec.Decode(decoder2); } // the decoded bit should match the source bit for the decoder to have worked if (decBit != bit) { Console.WriteLine("Error, static example 1 did not decode properly!"); } // switch context when the bit state changes use0ContextDec = (decBit == 0 ? true : false); } } } }
protected void ReadAsymmetricMessageHeader( BinaryDecoder decoder, X509Certificate2 receiverCertificate, out uint secureChannelId, out X509Certificate2 senderCertificate, out string securityPolicyUri) { senderCertificate = null; uint messageType = decoder.ReadUInt32(null); uint messageSize = decoder.ReadUInt32(null); // decode security header. byte[] certificateData = null; byte[] thumbprintData = null; try { secureChannelId = decoder.ReadUInt32(null); securityPolicyUri = decoder.ReadString(null, TcpMessageLimits.MaxSecurityPolicyUriSize); certificateData = decoder.ReadByteString(null, TcpMessageLimits.MaxCertificateSize); thumbprintData = decoder.ReadByteString(null, TcpMessageLimits.CertificateThumbprintSize); } catch (Exception e) { throw ServiceResultException.Create( StatusCodes.BadSecurityChecksFailed, e, "The asymmetric security header could not be parsed."); } // verify sender certificate. if (certificateData != null && certificateData.Length > 0) { senderCertificate = CertificateFactory.Create(certificateData, true); try { string thumbprint = senderCertificate.Thumbprint; if (thumbprint == null) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "Invalid certificate thumbprint."); } } catch (Exception e) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, e, "The sender's certificate could not be parsed."); } } else { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The sender's certificate was not specified."); } } // verify receiver thumbprint. if (thumbprintData != null && thumbprintData.Length > 0) { if (receiverCertificate.Thumbprint.ToUpperInvariant() != GetThumbprintString(thumbprintData)) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint is not valid."); } } else { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint was not specified."); } } }
/// <summary> /// Called whenever socket operation completes /// </summary> /// <param name="index"></param> /// <param name="arg"></param> /// <param name="ok"></param> /// <param name="timeout"></param> /// <returns>true if completed, false to be called again</returns> public bool CompleteAsync(int index, SocketAsyncEventArgs arg, out bool ok, out int timeout) { ok = false; timeout = _timeout; if (arg.SocketError != SocketError.Success) { _logger.Debug("Probe {index} : {remoteEp} found no opc server. {error}", index, _socket?.RemoteEndPoint, arg.SocketError); _state = State.BeginProbe; return(true); } while (true) { switch (_state) { case State.BeginProbe: if (arg.ConnectSocket == null) { _logger.Error("Probe {index} : Called without connected socket!", index); return(true); } _socket = arg.ConnectSocket; var ep = _socket.RemoteEndPoint.TryResolve(); using (var ostrm = new MemoryStream(_buffer, 0, _buffer.Length)) using (var encoder = new BinaryEncoder(ostrm, ServiceMessageContext.GlobalContext)) { encoder.WriteUInt32(null, TcpMessageType.Hello); encoder.WriteUInt32(null, 0); encoder.WriteUInt32(null, 0); // ProtocolVersion encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteByteString(null, Encoding.UTF8.GetBytes("opc.tcp://" + ep)); _size = encoder.Close(); } _buffer[4] = (byte)(_size & 0x000000FF); _buffer[5] = (byte)((_size & 0x0000FF00) >> 8); _buffer[6] = (byte)((_size & 0x00FF0000) >> 16); _buffer[7] = (byte)((_size & 0xFF000000) >> 24); arg.SetBuffer(_buffer, 0, _size); _len = 0; _logger.Debug("Probe {index} : {ep} ({remoteEp})...", index, "opc.tcp://" + ep, _socket.RemoteEndPoint); _state = State.SendHello; if (!_socket.SendAsync(arg)) { break; } return(false); case State.SendHello: _len += arg.Count; if (_len >= _size) { _len = 0; _size = TcpMessageLimits.MessageTypeAndSize; _state = State.ReceiveSize; arg.SetBuffer(0, _size); // Start read size if (!_socket.ReceiveAsync(arg)) { break; } return(false); } // Continue to send reset arg.SetBuffer(_len, _size - _len); if (!_socket.SendAsync(arg)) { break; } return(false); case State.ReceiveSize: _len += arg.Count; if (_len >= _size) { var type = BitConverter.ToUInt32(_buffer, 0); if (type != TcpMessageType.Acknowledge) { if (TcpMessageType.IsValid(type)) { _logger.Debug("Probe {index} : {remoteEp} " + "returned message type {type} != Ack.", index, _socket.RemoteEndPoint, type); } else { _logger.Verbose("Probe {index} : {remoteEp} " + "returned invalid message type {type}.", index, _socket.RemoteEndPoint, type); } _state = State.BeginProbe; return(true); } _size = (int)BitConverter.ToUInt32(_buffer, 4); if (_size > _buffer.Length) { _logger.Debug("Probe {index} : {remoteEp} " + "returned invalid message length {size}.", index, _socket.RemoteEndPoint, _size); _state = State.BeginProbe; return(true); } _len = 0; // Start receive message _state = State.ReceiveAck; } // Continue to read rest of type and size arg.SetBuffer(_len, _size - _len); if (!_socket.ReceiveAsync(arg)) { break; } return(false); case State.ReceiveAck: _len += arg.Count; if (_len >= _size) { _state = State.BeginProbe; // Validate message using (var istrm = new MemoryStream(_buffer, 0, _size)) using (var decoder = new BinaryDecoder(istrm, ServiceMessageContext.GlobalContext)) { var protocolVersion = decoder.ReadUInt32(null); var sendBufferSize = (int)decoder.ReadUInt32(null); var receiveBufferSize = (int)decoder.ReadUInt32(null); var maxMessageSize = (int)decoder.ReadUInt32(null); var maxChunkCount = (int)decoder.ReadUInt32(null); _logger.Information("Probe {index} : found OPC UA " + "server at {remoteEp} (protocol:{protocolVersion}) ...", index, _socket.RemoteEndPoint, protocolVersion); if (sendBufferSize < TcpMessageLimits.MinBufferSize || receiveBufferSize < TcpMessageLimits.MinBufferSize) { _logger.Warning("Probe {index} : Bad size value read " + "{sendBufferSize} or {receiveBufferSize} from opc " + "server at {_socket.RemoteEndPoint}.", index, sendBufferSize, receiveBufferSize, _socket.RemoteEndPoint); } } ok = true; return(true); } // Continue to read rest arg.SetBuffer(_len, _size - _len); if (!_socket.ReceiveAsync(arg)) { break; } return(false); default: throw new SystemException("Bad state"); } } }
public void TestEnumResolution() { Schema writerSchema = Schema.Parse("{\"type\":\"record\",\"name\":\"EnumRecord\",\"namespace\":\"Avro.Test\"," + "\"fields\":[{\"name\":\"enumType\",\"type\": { \"type\": \"enum\", \"name\": \"EnumType\", \"symbols\": [\"FIRST\", \"SECOND\"]} }]}"); Schema readerSchema = Schema.Parse("{\"type\":\"record\",\"name\":\"EnumRecord\",\"namespace\":\"Avro.Test\"," + "\"fields\":[{\"name\":\"enumType\",\"type\": { \"type\": \"enum\", \"name\": \"EnumType\", \"symbols\": [\"THIRD\", \"FIRST\", \"SECOND\"]} }]}"); EnumRecord testRecord = new EnumRecord(); testRecord.enumType = EnumType.SECOND; // serialize var stream = new MemoryStream(); var binEncoder = new BinaryEncoder(stream); var writer = new SpecificWriter<EnumRecord>(writerSchema); writer.Write(testRecord, binEncoder); // deserialize stream.Position = 0; var decoder = new BinaryDecoder(stream); var reader = new SpecificReader<EnumRecord>(writerSchema, readerSchema); var rec2 = reader.Read(null, decoder); Assert.AreEqual( EnumType.SECOND, rec2.enumType ); }
/// <summary> /// Reads the trust list. /// </summary> public TrustListDataType ReadTrustList(TrustListMasks masks = TrustListMasks.All) { if (!IsConnected) { Connect(); } IUserIdentity oldUser = ElevatePermissions(); try { var outputArguments = m_session.Call( ExpandedNodeId.ToNodeId(Opc.Ua.ObjectIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList, m_session.NamespaceUris), ExpandedNodeId.ToNodeId(Opc.Ua.MethodIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList_OpenWithMasks, m_session.NamespaceUris), (uint)masks); uint fileHandle = (uint)outputArguments[0]; MemoryStream ostrm = new MemoryStream(); try { while (true) { int length = 256; outputArguments = m_session.Call( ExpandedNodeId.ToNodeId(Opc.Ua.ObjectIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList, m_session.NamespaceUris), ExpandedNodeId.ToNodeId(Opc.Ua.MethodIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList_Read, m_session.NamespaceUris), fileHandle, length); byte[] bytes = (byte[])outputArguments[0]; ostrm.Write(bytes, 0, bytes.Length); if (length != bytes.Length) { break; } } m_session.Call( ExpandedNodeId.ToNodeId(Opc.Ua.ObjectIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList, m_session.NamespaceUris), ExpandedNodeId.ToNodeId(Opc.Ua.MethodIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList_Close, m_session.NamespaceUris), fileHandle); } catch (Exception) { if (IsConnected) { m_session.Call( ExpandedNodeId.ToNodeId(Opc.Ua.ObjectIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList, m_session.NamespaceUris), ExpandedNodeId.ToNodeId(Opc.Ua.MethodIds.ServerConfiguration_CertificateGroups_DefaultApplicationGroup_TrustList_Close, m_session.NamespaceUris), fileHandle); } throw; } ostrm.Position = 0; BinaryDecoder decoder = new BinaryDecoder(ostrm, m_session.MessageContext); TrustListDataType trustList = new TrustListDataType(); trustList.Decode(decoder); decoder.Close(); ostrm.Close(); return(trustList); } finally { RevertPermissions(oldUser); } }
/// <summary> /// Processes a response message. /// </summary> private bool ProcessResponseMessage(uint messageType, ArraySegment<byte> messageChunk) { // Utils.Trace("Channel {0}: ProcessResponseMessage()", ChannelId); // validate security on the message. TcpChannelToken token = null; uint requestId = 0; uint sequenceNumber = 0; ArraySegment<byte> messageBody; try { messageBody = ReadSymmetricMessage(messageChunk, false, out token, out requestId, out sequenceNumber); } catch (Exception e) { ForceReconnect(ServiceResult.Create(e, StatusCodes.BadSecurityChecksFailed, "Could not verify security on response.")); return false; } // check if operation is still available. WriteOperation operation = null; if (!m_requests.TryGetValue(requestId, out operation)) { return false; } BufferCollection chunksToProcess = null; // check for replay attacks. if (!VerifySequenceNumber(sequenceNumber, "ProcessResponseMessage")) { throw new ServiceResultException(StatusCodes.BadSequenceNumberInvalid); } try { // check for an abort. if (TcpMessageType.IsAbort(messageType)) { // get the chunks to process. chunksToProcess = GetSavedChunks(requestId, messageBody); // decoder reason. MemoryStream istrm = new MemoryStream(messageBody.Array, messageBody.Offset, messageBody.Count, false); BinaryDecoder decoder = new BinaryDecoder(istrm, Quotas.MessageContext); ServiceResult error = ReadErrorMessageBody(decoder); decoder.Close(); // report a fault. operation.Fault(true, error); return true; } // check if it is necessary to wait for more chunks. if (!TcpMessageType.IsFinal(messageType)) { SaveIntermediateChunk(requestId, messageBody); return true; } // get the chunks to process. chunksToProcess = GetSavedChunks(requestId, messageBody); // get response. operation.MessageBody = ParseResponse(chunksToProcess); if (operation.MessageBody == null) { operation.Fault(true, StatusCodes.BadStructureMissing, "Could not parse response body."); return true; } // is complete. operation.Complete(true, 0); return true; } catch (Exception e) { operation.Fault(true, e, StatusCodes.BadUnknownResponse, "Unexpected error processing response."); return true; } finally { if (chunksToProcess != null) { chunksToProcess.Release(BufferManager, "ProcessResponseMessage"); } } }
public bool Decode(BinaryDecoder decoder) { if (!BinaryCodec.Decode(decoder, out _itemID)) { return(false); } if (!BinaryCodec.DecodeUnicodeString(decoder, out _itemName)) { return(false); } if (!BinaryCodec.DecodeUnicodeString(decoder, out _itemDesc)) { return(false); } if (!BinaryCodec.Decode(decoder, out _iconName)) { return(false); } if (!BinaryCodec.Decode(decoder, out _price)) { return(false); } if (!BinaryCodec.Decode(decoder, out _option)) { return(false); } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _itemType = (E_ItemType)enumValue; } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _itemKindType = (E_ItemKindType)enumValue; } if (!BinaryCodec.Decode(decoder, out _isConsume)) { return(false); } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _scopeType = (E_ScopeType)enumValue; } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _occasionType = (E_OccasionType)enumValue; } return(true); }
/// <summary> /// Parses the response return from the server. /// </summary> private IServiceResponse ParseResponse(BufferCollection chunksToProcess) { BinaryDecoder decoder = new BinaryDecoder(new ArraySegmentStream(chunksToProcess), Quotas.MessageContext); try { IServiceResponse response = BinaryDecoder.DecodeMessage(new ArraySegmentStream(chunksToProcess), null, Quotas.MessageContext) as IServiceResponse; if (response == null) { throw ServiceResultException.Create(StatusCodes.BadStructureMissing, "Could not parse response body."); } return response; } finally { decoder.Close(); } }
public bool Decode(BinaryDecoder decoder) { if (!BinaryCodec.Decode(decoder, out _itemID)) { return(false); } if (!BinaryCodec.DecodeUnicodeString(decoder, out _itemName)) { return(false); } if (!BinaryCodec.DecodeUnicodeString(decoder, out _itemDesc)) { return(false); } if (!BinaryCodec.Decode(decoder, out _iconName)) { return(false); } if (!BinaryCodec.Decode(decoder, out _price)) { return(false); } if (!BinaryCodec.Decode(decoder, out _option)) { return(false); } { int enumValue = 0; if (!BinaryCodec.Decode(decoder, out enumValue)) { return(false); } _armorType = (E_ArmorType)enumValue; } if (!BinaryCodec.Decode(decoder, out _health)) { return(false); } if (!BinaryCodec.Decode(decoder, out _energy)) { return(false); } if (!BinaryCodec.Decode(decoder, out _healthRecover)) { return(false); } if (!BinaryCodec.Decode(decoder, out _energyRecover)) { return(false); } if (!BinaryCodec.Decode(decoder, out _physicalArmor)) { return(false); } if (!BinaryCodec.Decode(decoder, out _elementalArmor)) { return(false); } if (!BinaryCodec.Decode(decoder, out _physicalAvoid)) { return(false); } if (!BinaryCodec.Decode(decoder, out _elementalAvoid)) { return(false); } if (!BinaryCodec.Decode(decoder, out _physicalResistance)) { return(false); } if (!BinaryCodec.Decode(decoder, out _elementalResistance)) { return(false); } return(true); }
private bool ProcessHelloMessage(uint messageType, ArraySegment<byte> messageChunk) { // validate the channel state. if (State != TcpChannelState.Connecting) { ForceChannelFault(StatusCodes.BadTcpMessageTypeInvalid, "Client sent an unexpected Hello message."); return false; } try { MemoryStream istrm = new MemoryStream(messageChunk.Array, messageChunk.Offset, messageChunk.Count, false); BinaryDecoder decoder = new BinaryDecoder(istrm, Quotas.MessageContext); istrm.Seek(TcpMessageLimits.MessageTypeAndSize, SeekOrigin.Current); // read requested buffer sizes. uint protocolVersion = decoder.ReadUInt32(null); uint receiveBufferSize = decoder.ReadUInt32(null); uint sendBufferSize = decoder.ReadUInt32(null); uint maxMessageSize = decoder.ReadUInt32(null); uint maxChunkCount = decoder.ReadUInt32(null); // read the endpoint url. int length = decoder.ReadInt32(null); if (length > 0) { if (length > TcpMessageLimits.MaxEndpointUrlLength) { ForceChannelFault(StatusCodes.BadTcpEndpointUrlInvalid); return false; } byte[] endpointUrl = new byte[length]; for (int ii = 0; ii < endpointUrl.Length; ii++) { endpointUrl[ii] = decoder.ReadByte(null); } if (!SetEndpointUrl(new UTF8Encoding().GetString(endpointUrl))) { ForceChannelFault(StatusCodes.BadTcpEndpointUrlInvalid); return false; } } decoder.Close(); // update receive buffer size. if (receiveBufferSize < ReceiveBufferSize) { ReceiveBufferSize = (int)receiveBufferSize; } if (ReceiveBufferSize < TcpMessageLimits.MinBufferSize) { ReceiveBufferSize = TcpMessageLimits.MinBufferSize; } // update send buffer size. if (sendBufferSize < SendBufferSize) { SendBufferSize = (int)sendBufferSize; } if (SendBufferSize < TcpMessageLimits.MinBufferSize) { SendBufferSize = TcpMessageLimits.MinBufferSize; } // update the max message size. if (maxMessageSize > 0 && maxMessageSize < MaxResponseMessageSize) { MaxResponseMessageSize = (int)maxMessageSize; } if (MaxResponseMessageSize < SendBufferSize) { MaxResponseMessageSize = SendBufferSize; } // update the max chunk count. if (maxChunkCount > 0 && maxChunkCount < MaxResponseChunkCount) { MaxResponseChunkCount = (int)maxChunkCount; } // send acknowledge. byte[] buffer = BufferManager.TakeBuffer(SendBufferSize, "ProcessHelloMessage"); try { MemoryStream ostrm = new MemoryStream(buffer, 0, SendBufferSize); BinaryEncoder encoder = new BinaryEncoder(ostrm, Quotas.MessageContext); encoder.WriteUInt32(null, TcpMessageType.Acknowledge); encoder.WriteUInt32(null, 0); encoder.WriteUInt32(null, 0); // ProtocolVersion encoder.WriteUInt32(null, (uint)ReceiveBufferSize); encoder.WriteUInt32(null, (uint)SendBufferSize); encoder.WriteUInt32(null, (uint)MaxRequestMessageSize); encoder.WriteUInt32(null, (uint)MaxRequestChunkCount); int size = encoder.Close(); UpdateMessageSize(buffer, 0, size); // now ready for the open or bind request. State = TcpChannelState.Opening; BeginWriteMessage(new ArraySegment<byte>(buffer, 0, size), Int32.MaxValue, null); buffer = null; } finally { if (buffer != null) { BufferManager.ReturnBuffer(buffer, "ProcessHelloMessage"); } } } catch (Exception e) { ForceChannelFault(e, StatusCodes.BadTcpInternalError, "Unexpected error while processing a Hello message."); } return false; }
protected override async Task OnOpenAsync(CancellationToken token) { token.ThrowIfCancellationRequested(); this.sendBuffer = new byte[MinBufferSize]; this.receiveBuffer = new byte[MinBufferSize]; this.tcpClient = new System.Net.Sockets.TcpClient { NoDelay = true }; var uri = new UriBuilder(this.RemoteEndpoint.EndpointUrl); await this.tcpClient.ConnectAsync(uri.Host, uri.Port).ConfigureAwait(false); this.instream = this.outstream = this.tcpClient.GetStream(); // send 'hello'. int count; var encoder = new BinaryEncoder(new MemoryStream(this.sendBuffer, 0, MinBufferSize, true, false)); try { encoder.WriteUInt32(null, UaTcpMessageTypes.HELF); encoder.WriteUInt32(null, 0u); encoder.WriteUInt32(null, ProtocolVersion); encoder.WriteUInt32(null, this.LocalReceiveBufferSize); encoder.WriteUInt32(null, this.LocalSendBufferSize); encoder.WriteUInt32(null, this.LocalMaxMessageSize); encoder.WriteUInt32(null, this.LocalMaxChunkCount); encoder.WriteString(null, uri.ToString()); count = encoder.Position; encoder.Position = 4; encoder.WriteUInt32(null, (uint)count); encoder.Position = count; await this.SendAsync(this.sendBuffer, 0, count, token).ConfigureAwait(false); } finally { encoder.Dispose(); } // receive response count = await this.ReceiveAsync(this.receiveBuffer, 0, MinBufferSize, token).ConfigureAwait(false); if (count == 0) { throw new ObjectDisposedException("socket"); } // decode 'ack' or 'err'. var decoder = new BinaryDecoder(new MemoryStream(this.receiveBuffer, 0, count, false, false)); try { var type = decoder.ReadUInt32(null); var len = decoder.ReadUInt32(null); if (type == UaTcpMessageTypes.ACKF) { var remoteProtocolVersion = decoder.ReadUInt32(null); if (remoteProtocolVersion < ProtocolVersion) { throw new ServiceResultException(StatusCodes.BadProtocolVersionUnsupported); } this.RemoteSendBufferSize = decoder.ReadUInt32(null); this.RemoteReceiveBufferSize = decoder.ReadUInt32(null); this.RemoteMaxMessageSize = decoder.ReadUInt32(null); this.RemoteMaxChunkCount = decoder.ReadUInt32(null); return; } else if (type == UaTcpMessageTypes.ERRF) { var statusCode = decoder.ReadUInt32(null); var message = decoder.ReadString(null); throw new ServiceResultException(statusCode, message); } throw new InvalidOperationException("UaTcpTransportChannel.OnOpenAsync received unexpected message type."); } finally { decoder.Dispose(); } }