예제 #1
0
        public void TestIsAncestor()
        {
            Setup();

            var messageAllocation = new Span <byte>(new byte[IsAncestor.SizeInBytes]);

            var isAncestorReq = new IsAncestor(1, 5, _3, _1);

            // Serialize message to put it into the inbox
            MessageSerializers.ClientSerializeIsAncestor(isAncestorReq, messageAllocation);

            _inbox.TryWrite(messageAllocation);

            _controller.DoWork();

            var result = _outbox.Peek();

            Assert.Equal(MessageType.AncestorResponse, ClientServerMessage.GetMessageType(result));
            Assert.True(ClientServerMessage.TryGetLength(result, out int responseSize));
            Assert.Equal(AncestorResponse.SizeInBytes, responseSize);

            var response = MessageSerializers.ClientDeserializeAncestorResponse(result);

            Assert.Equal(1U, response.RequestId);
            Assert.Equal(5U, response.ClientId);
            Assert.True(response.Answer);

            // get a wrong ancestor
            isAncestorReq = new IsAncestor(1, 5, _3, _5);
            // Serialize message to put it into the inbox
            MessageSerializers.ClientSerializeIsAncestor(isAncestorReq, messageAllocation);

            _inbox.TryWrite(messageAllocation);

            _controller.DoWork();

            _outbox.Next();
            result = _outbox.Peek();
            var response2 = MessageSerializers.ClientDeserializeAncestorResponse(result);

            Assert.Equal(1U, response2.RequestId);
            Assert.Equal(5U, response2.ClientId);
            Assert.Equal(MessageType.AncestorResponse, response2.ResponseType);

            Assert.False(response2.Answer);
        }
예제 #2
0
        // TODO: [vermorel] Should probably be renamed 'GetInputMessageLenght()'.
        private int InputMessageLength()
        {
            if (_endIn < sizeof(int))
            {
                return(0);
            }

            if (!ClientServerMessage.TryGetLength(_bufferIn, out var length))
            {
                // TODO: [vermorel] Pattern below is bizarelly written, to be rewritten.
                new Span <byte>(_errorSpan).EmitRequestTooShort(_bufferIn);

                if (_socket.Connected())
                {
                    _socket.Send(_errorSpan);
                    _socket.Close();
                }

                return(0);
            }

            if (length > ClientServerMessage.MaxSizeInBytes || length < ClientServerMessage.MinSizeInBytes)
            {
                // TODO: [vermorel] Pattern below is bizarelly written, to be rewritten.
                new Span <byte>(_errorSpan).EmitRequestTooLong(_bufferIn);

                if (_socket.Connected())
                {
                    _socket.Send(_errorSpan);
                    _socket.Close();
                }

                return(0);
            }

            // TODO: [vermorel] Clarify what is the edge-case here. Unclear.
            if (_endIn < length)
            {
                return(0);
            }

            return(length);
        }
예제 #3
0
 public void TestLengthField()
 {
     ClientServerMessage.TryGetLength(_bytes, out var length);
     Assert.Equal(0x14131211, length);
     Assert.False(ClientServerMessage.TryGetLength(new Span <byte>(_bytes, 0, 3), out length));
 }
예제 #4
0
        // TODO: [vermorel] The condition for not succeeding to write should be clarified.
        public bool TryWrite(Span <byte> message)
        {
            // TODO: [vermorel] If we are not even connected, we should throw an 'InvalidOperationException'.
            if (!IsConnected)
            {
                return(false);
            }

            if (message.Length > ClientServerMessage.MaxSizeInBytes)
            {
                throw new ArgumentException(
                          $"Message size {message.Length} exceeds max size {ClientServerMessage.MaxSizeInBytes}.");
            }

            ClientServerMessage.TryGetLength(message, out var announcedMessageLength);

            if (announcedMessageLength != message.Length)
            {
                throw new ArgumentException(
                          $"Message size {announcedMessageLength} in span of size {message.Length}.");
            }

            // TODO: [vermorel] This operation should be moving within the 'ClientServerMessage'
            // delete client ID which is just for internal purposes
            BitConverter.TryWriteBytes(message.Slice(8), 0U);

            // Try to send message only if buffer is empty, to not corrupt the message stream
            if (_endOut > 0)
            {
                if (message.Length > _bufferOut.Length - _endOut)
                {
                    // No room in buffer for this message, close connection.
                    // This behaviour may change in future versions.
                    _socket.Close();
                    return(false);
                }

                if (!message.TryCopyTo(new Span <byte>(_bufferOut).Slice(_endOut)))
                {
                    // Should really replace this with a span copy function
                    throw new NotImplementedException("No handling for case when byte copy fails");
                }

                _endOut += message.Length;

                return(true);
            }

            // Nothing in buffer, so the socket is free for sending
            var bytesSent = _socket.Send(message);

            if (bytesSent == message.Length)
            {
                return(true);
            }

            var bytesNotSent = message.Length - bytesSent;

            if (!message.Slice(bytesSent).TryCopyTo(_bufferOut))
            {
                // TODO: Should really replace this with a span copy function
                throw new NotImplementedException("No handling for case when byte copy fails");
            }

            _endOut += bytesNotSent;
            return(true);
        }