예제 #1
0
        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();
        }
예제 #2
0
        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;
            }
        }
예제 #3
0
        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);
        }