internal bool GetFixedSize(ref int size) { if (size < 0) { return(false); } if (_data.Length == 0) { return(true); } // Sensible? size = ProtocolInformation.Padded(size, Alignment); if (_data.Length == 1) { int valueSize = GetSize(this[0]); if (valueSize == -1) { return(false); } size += valueSize; return(true); } if (IsStructlike) { foreach (Signature sig in GetParts()) { if (!sig.GetFixedSize(ref size)) { return(false); } } return(true); } if (IsArray || IsDict) { return(false); } if (IsStruct) { foreach (Signature sig in GetFieldSignatures()) { if (!sig.GetFixedSize(ref size)) { return(false); } } return(true); } // Any other cases? throw new Exception(); }
public async Task <Message> ReceiveMessageAsync() { try { int bytesRead = await ReadCountAsync(_headerReadBuffer, 0, 16, _fileDescriptors).ConfigureAwait(false); if (bytesRead == 0) { return(null); } if (bytesRead != 16) { throw new ProtocolException("Header read length mismatch: " + bytesRead + " of expected " + "16"); } EndianFlag endianness = (EndianFlag)_headerReadBuffer[0]; MessageReader reader = new MessageReader(endianness, new ArraySegment <byte>(_headerReadBuffer)); //discard endian byte, message type and flags, which we don't care about here reader.Seek(3); byte version = reader.ReadByte(); if (version != ProtocolInformation.Version) { throw new NotSupportedException("Protocol version '" + version.ToString() + "' is not supported"); } uint bodyLength = reader.ReadUInt32(); //discard _methodSerial reader.ReadUInt32(); uint headerLength = reader.ReadUInt32(); int bodyLen = (int)bodyLength; int toRead = (int)headerLength; //we fixup to include the padding following the header toRead = ProtocolInformation.Padded(toRead, 8); long msgLength = toRead + bodyLen; if (msgLength > ProtocolInformation.MaxMessageLength) { throw new ProtocolException("Message length " + msgLength + " exceeds maximum allowed " + ProtocolInformation.MaxMessageLength + " bytes"); } byte[] header = new byte[16 + toRead]; Array.Copy(_headerReadBuffer, header, 16); bytesRead = await ReadCountAsync(header, 16, toRead, _fileDescriptors).ConfigureAwait(false); if (bytesRead != toRead) { throw new ProtocolException("Message header length mismatch: " + bytesRead + " of expected " + toRead); } var messageHeader = Header.FromBytes(new ArraySegment <byte>(header)); byte[] body = null; //read the body if (bodyLen != 0) { body = new byte[bodyLen]; bytesRead = await ReadCountAsync(body, 0, bodyLen, _fileDescriptors).ConfigureAwait(false); if (bytesRead != bodyLen) { throw new ProtocolException("Message body length mismatch: " + bytesRead + " of expected " + bodyLen); } } if (_fileDescriptors.Count < messageHeader.NumberOfFds) { throw new ProtocolException("File descriptor length mismatch: " + _fileDescriptors.Count + " of expected " + messageHeader.NumberOfFds); } Message msg = new Message( messageHeader, body, messageHeader.NumberOfFds == 0 ? null : _fileDescriptors.Count == messageHeader.NumberOfFds ? _fileDescriptors.ToArray() : _fileDescriptors.Take((int)messageHeader.NumberOfFds).ToArray() ); _fileDescriptors.RemoveRange(0, (int)messageHeader.NumberOfFds); return(msg); } catch { foreach (var fd in _fileDescriptors) { CloseSafeHandle.close(fd.Handle); } throw; } }
Message ReadMessageReal() { byte[] header = null; byte[] body = null; UnixFDArray fdArray = Connection.UnixFDSupported ? new UnixFDArray() : null; int read; //16 bytes is the size of the fixed part of the header if (readBuffer == null) { readBuffer = new byte[16]; } byte[] hbuf = readBuffer; read = Read(hbuf, 0, 16, fdArray); if (read == 0) { return(null); } if (read != 16) { throw new Exception("Header read length mismatch: " + read + " of expected " + "16"); } EndianFlag endianness = (EndianFlag)hbuf[0]; MessageReader reader = new MessageReader(endianness, hbuf); //discard endian byte, message type and flags, which we don't care about here reader.Seek(3); byte version = reader.ReadByte(); if (version < ProtocolInformation.MinVersion || version > ProtocolInformation.MaxVersion) { throw new NotSupportedException("Protocol version '" + version.ToString() + "' is not supported"); } if (ProtocolInformation.Verbose) { if (version != ProtocolInformation.Version) { Console.Error.WriteLine("Warning: Protocol version '" + version.ToString() + "' is not explicitly supported but may be compatible"); } } uint bodyLength = reader.ReadUInt32(); //discard serial reader.ReadUInt32(); uint headerLength = reader.ReadUInt32(); int bodyLen = (int)bodyLength; int toRead = (int)headerLength; //we fixup to include the padding following the header toRead = ProtocolInformation.Padded(toRead, 8); long msgLength = toRead + bodyLen; if (msgLength > ProtocolInformation.MaxMessageLength) { throw new Exception("Message length " + msgLength + " exceeds maximum allowed " + ProtocolInformation.MaxMessageLength + " bytes"); } header = new byte[16 + toRead]; Array.Copy(hbuf, header, 16); read = Read(header, 16, toRead, fdArray); if (read != toRead) { throw new Exception("Message header length mismatch: " + read + " of expected " + toRead); } //read the body if (bodyLen != 0) { body = new byte[bodyLen]; read = Read(body, 0, bodyLen, fdArray); if (read != bodyLen) { throw new Exception("Message body length mismatch: " + read + " of expected " + bodyLen); } } Message msg = Message.FromReceivedBytes(Connection, header, body, fdArray); return(msg); }