public void TestClientIdField() { Span <byte> expectedAsHex = stackalloc byte[] { 0x21, 0x22, 0x23, 0x24 }; ClientId expected = ClientId.ReadFrom(expectedAsHex); Assert.Equal(expected, ClientServerMessage.GetClientId(_bytes)); Assert.Throws <ArgumentException>(() => ClientServerMessage.GetClientId(new Span <byte>(_bytes, 0, 11))); }
// TODO: [vermorel] Almost but not quite like other 'Iterator' in solution. Align designs. /// <summary> /// Provides the next unread message. /// </summary> /// <remarks> /// Returned span is only valid until the next call to /// <see cref="ReceiveNext"/>. /// </remarks> public Span <byte> ReceiveNext() { // Delete first message and copy everything else to the beginning var length = InputMessageLength(); if (length > 0) { Array.Copy(_bufferIn, length, _bufferIn, 0, _endIn - length); _endIn -= length; } // Try to receive more data from socket if (IsConnected && 0 != _socket.Available() && _bufferIn.Length != _endIn) { _endIn += _socket.Receive(new Span <byte>(_bufferIn).Slice(_endIn)); } length = InputMessageLength(); if (length > 0) { var message = new Span <byte>(_bufferIn, 0, length); var messageStatus = PassesVerifications(message); if (messageStatus != MessageType.EverythingOk) { switch (messageStatus) { case MessageType.ClientIdFieldNotEmpty: new Span <byte>(_errorSpan).EmitClientIdFieldNotEmpty(message); _socket.Send(_errorSpan); // see whether a valid message is waiting in the inbox return(ReceiveNext()); } } else // write client ID into message { ConnectionId.WriteTo(message.Slice(8)); } return(new Span <byte>(_bufferIn, 0, length)); } else { return(Span <byte> .Empty); } // TODO: [vermorel] The intent of this method must be clarified. MessageType PassesVerifications(Span <byte> message) { // Maybe other verifications are going to be added over time if (message.Length >= ClientServerMessage.PayloadStart && ClientServerMessage.GetClientId(message).IsSpecified) { return(MessageType.ClientIdFieldNotEmpty); } return(MessageType.EverythingOk); } }
public void SendResponses() { var toSend = _outbox.Peek(); while (toSend.Length != 0) { if (_activeConnections.TryGetValue(ClientServerMessage.GetClientId(toSend), out var client)) { client.TryWrite(toSend); } _outbox.Next(); toSend = _outbox.Peek(); } }