public void TestGetUncommittedBlockInfo() { var uncommittedBlockId = TestOpenBlock(); var messageAllocation = new Span <byte>(new byte[GetBlockInformation.SizeInBytes]); var getInfo = new GetBlockInformation(1, 5, _9); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeGetBlockInformation(getInfo, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); _outbox.Next(); var result = _outbox.Peek(); Assert.Equal(MessageType.UncommittedBlockInfo, ClientServerMessage.GetMessageType(result)); var response = MessageSerializers.ClientDeserializeUncommittedBlockInfo(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.Equal(uncommittedBlockId, response.UncommittedBlockId); Assert.Equal(_9, response.Alias); Assert.Equal(_3, response.Parent); Assert.Equal(3, response.BlockHeight); }
public TempBlockId TestOpenBlock() { Setup(); var messageAllocation = new Span <byte>(new byte[OpenBlock.SizeInBytes]); var openBlock = new OpenBlock(1, 5, _3); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeOpenBlock(openBlock, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); var result = _outbox.Peek(); Assert.Equal(MessageType.OpenedBlock, ClientServerMessage.GetMessageType(result)); var response = MessageSerializers.ClientDeserializeOpenedBlock(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.Equal(_9, response.Alias); return(response.UncommittedBlockId); }
public void TestCommitBlock() { TestOpenBlock(); var messageAllocation = new Span <byte>(new byte[CommitBlock.SizeInBytes]); var commitBlock = new CommitBlock(1, 5, _9, new BlockId(new Hash256(0xFFFFFFFFUL, 0xEEEEEEEEUL, 0xDDDDDDDDUL, 0xCCCCCCCEUL))); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeCommitBlock(commitBlock, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); _outbox.Next(); var result = _outbox.Peek(); Assert.Equal(MessageType.EverythingOk, ClientServerMessage.GetMessageType(result)); var response = MessageSerializers.ClientDeserializeEverythingOk(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); }
public void TestGetCommittedBlockInfo() { Setup(); var messageAllocation = new Span <byte>(new byte[GetBlockInformation.SizeInBytes]); var getInfo = new GetBlockInformation(1, 5, _1); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeGetBlockInformation(getInfo, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); var result = _outbox.Peek(); Assert.Equal(MessageType.CommittedBlockInfo, ClientServerMessage.GetMessageType(result)); var response = MessageSerializers.ClientDeserializeCommittedBlockInfo(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.Equal(BlockId.Genesis, response.BlockId); Assert.Equal(_1, response.Alias); Assert.Equal(0u, response.Parent.Value); Assert.Equal(0, response.BlockHeight); }
public void TestGetCommittedBlockHandle() { Setup(); var messageAllocation = new Span <byte>(new byte[GetBlockHandle.SizeInBytes]); var getHandle = new GetBlockHandle(1, 5, new BlockId(new Hash256(0xFFFFFFFFUL, 0xEEEEEEEEUL, 0xDDDDDDDDUL, 0xCCCCCCCCUL))); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeGetBlockHandle(getHandle, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); var result = _outbox.Peek(); Assert.Equal(MessageType.BlockHandle, ClientServerMessage.GetMessageType(result)); var response = MessageSerializers.ClientDeserializeBlockHandleResponse(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.Equal(_3, response.BlockHandle); }
public void TestGetUncommittedBlockHandle() { var uncommitedBlockId = TestOpenBlock(); var messageAllocation = new Span <byte>(new byte[GetUncommittedBlockHandle.SizeInBytes]); var getHandle = new GetUncommittedBlockHandle(1, 5, uncommitedBlockId); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeGetUncommittedBlockHandle(getHandle, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); _outbox.Next(); // because we did the TestOpenBlock in the beginning var result = _outbox.Peek(); Assert.Equal(MessageType.BlockHandle, ClientServerMessage.GetMessageType(result)); var response = MessageSerializers.ClientDeserializeBlockHandleResponse(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.Equal(_9, response.BlockHandle); }
public void TestOpenFirstBlock() { _controller = new ControllerThread(_chain, default(OptimizedLineage), _inbox = BoundedInbox.Create(), _outbox = BoundedInbox.Create()); var messageAllocation = new Span <byte>(new byte[OpenBlock.SizeInBytes]); var openBlock = new OpenBlock(1, 5, BlockAlias.GenesisParent); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeOpenBlock(openBlock, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); var result = _outbox.Peek(); Assert.Equal(MessageType.OpenedBlock, ClientServerMessage.GetMessageType(result)); var response = MessageSerializers.ClientDeserializeOpenedBlock(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.Equal(_1, response.Alias); var tmpId = response.UncommittedBlockId; Console.WriteLine(tmpId); }
//Метод, вытягивающий информацию о мастерах из базы данных private static ClientServerMessage GetMasters(ClientServerMessage request) { var masterType = (WorkType)Int32.Parse(request.Arguments["master"]); var args = new Dictionary <string, string>(); args.Add("result", "success"); ClientServerMessage response; List <Employee> mastersToSend = new List <Employee>(); using (DbContext context = new DbContext(DbConnectionString)) { var masters = context.Masters; if (masters != null) { mastersToSend = masters.Where(x => x.Specialization == masterType).ToList(); } if (mastersToSend == null) { args["result"] = "failed"; } else { args.Add("masters", JsonConvert.SerializeObject(mastersToSend)); } } response = new ClientServerMessage(args); return(response); }
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 TestSharded() { _bytes[12] = 0x85; Assert.True(ClientServerMessage.IsSharded(_bytes)); _bytes[12] = 0x71; Assert.False(ClientServerMessage.IsSharded(_bytes)); Assert.Throws <ArgumentException>(() => ClientServerMessage.IsSharded(new Span <byte>(_bytes, 0, 11))); }
public static void EmitRequestTooShort(this Span <byte> buffer, ReadOnlySpan <byte> request) { if (buffer.Length < ClientServerMessage.PayloadStart) { throw new ArgumentException($"Output buffer length {buffer.Length} too short.", nameof(buffer)); } ClientServerMessage.SetHeader( buffer, length: ClientServerMessage.PayloadStart, id: UInt64.MaxValue, // TODO: [vermorel] Very odd. Why not 'GetId(request)'? isSharded: 0, response: MessageType.RequestTooShort); }
// TODO: [vermorel] Don't pass 'request', pass 'GetId(request)' instead public static void EmitOutBufferFull(this Span <byte> buffer, ReadOnlySpan <byte> request) { if (buffer.Length < ClientServerMessage.PayloadStart) { throw new ArgumentException($"Output buffer length {buffer.Length} too short.", nameof(buffer)); } ClientServerMessage.SetHeader( buffer, length: ClientServerMessage.PayloadStart, id: ClientServerMessage.GetId(request), isSharded: 0, response: MessageType.OutBufferFull); }
// TODO: [vermorel] Method named 'listen' but actually 'remove'?. Intent to be clarified. public void ListenToConnections() { // TODO: [vermorel] Directly initialize, it will remove two test conditions below, perf overhead should be insignificant. List <ClientId> toRemove = null; foreach (var kv in _activeConnections) { if (!kv.Value.IsConnected) { if (toRemove == null) { toRemove = new List <ClientId>(); } toRemove.Add(kv.Key); continue; } kv.Value.Send(); // TODO: [vermorel] Almost but not quite like an iterator. Design should be aligned with other iterators. var nextMessage = kv.Value.ReceiveNext(); while (nextMessage.Length != 0) { var toWriteInto = ClientServerMessage.IsSharded(nextMessage) ? _workerInboxes[ // TODO: [vermorel] Do not keep the shardling logic inline, isolate with a helper. ClientServerMessage.FirstKeyByte(nextMessage) % _workerInboxes.Length] : _controllerInbox; if (!toWriteInto.TryWrite(nextMessage)) { // TODO: [vermorel] Oddly written statement, to be rewritten. new Span <byte>(_errorBuffer).EmitWorkersBusy(nextMessage); kv.Value.TryWrite(_errorBuffer); } nextMessage = kv.Value.ReceiveNext(); } } // Delete connections that were found unconnected if (toRemove != null) { foreach (var clientId in toRemove) { _activeConnections.Remove(clientId); } } }
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(); } }
//Метод, добавляющий поступивший заказ в базу данных private static ClientServerMessage AddAppointment(ClientServerMessage request) { var appointment = JsonConvert.DeserializeObject <Appointment>(request.Arguments["appointment"]); var master = JsonConvert.DeserializeObject <Employee>(request.Arguments["master"]); using (DbContext context = new DbContext(DbConnectionString)) { int id = context.UploadAppointment(appointment); appointment.Id = id; master.Appointments.Add(appointment); context.UpdateMasterAppointments(master); } return(new ClientServerMessage("success;true")); }
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); }
// 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); }
public void TestIsPruneable() { Setup(); var messageAllocation = new Span <byte>(new byte[IsPruneable.SizeInBytes]); var isPruneableReq = new IsPruneable(1, 5, _3); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeIsPruneable(isPruneableReq, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); var result = _outbox.Peek(); var response = MessageSerializers.ClientDeserializePruneableResponse(result); Assert.Equal(MessageType.PruneableResponse, ClientServerMessage.GetMessageType(result)); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.False(response.Answer); _outbox.Next(); isPruneableReq = new IsPruneable(1, 5, _4); // Serialize message to put it into the inbox MessageSerializers.ClientSerializeIsPruneable(isPruneableReq, messageAllocation); _inbox.TryWrite(messageAllocation); _controller.DoWork(); result = _outbox.Peek(); Assert.Equal(MessageType.PruneableResponse, ClientServerMessage.GetMessageType(result)); var response2 = MessageSerializers.ClientDeserializePruneableResponse(result); Assert.Equal(1U, response.RequestId); Assert.Equal(5U, response.ClientId); Assert.True(response2.Answer); }
//Метод получения работ определенного типа с сервера public List <Work> GetWorks(WorkType masterType) { string masterJson = ((int)masterType).ToString(); string command = "GET_MASTER_WORKS"; Dictionary <string, string> args = new Dictionary <string, string>(); args.Add("cmd", command); args.Add("master", masterJson); ClientServerMessage receivedMessage = SendMessage(new ClientServerMessage(args)); if (CheckReceivedMessage(receivedMessage) && receivedMessage.Arguments.ContainsKey("works")) { return(JsonConvert.DeserializeObject <List <Work> >(receivedMessage.Arguments["works"])); } else { return(null); } }
//Метод, принимающий запрос и отдающий ответ public static string GetResponse(string request) { ClientServerMessage requestMessage = new ClientServerMessage(request); ClientServerMessage response = new ClientServerMessage(new Dictionary <string, string>() { { "result", "failed" } }); //Обработка запроса в зависимости от команды, прижедшей с клиента switch (requestMessage.Arguments["cmd"].ToUpper()) { case "GET_MASTER_WORKS": response = GetMasterWorks(requestMessage); break; case "GET_MASTERS": response = GetMasters(requestMessage); break; case "ADD_APPOINTMENT": response = AddAppointment(requestMessage); break; } return(response.Message); }
public void TestRequestTypes() { BitConverter.TryWriteBytes(new Span <byte>(_bytes, ClientServerMessage.MessageTypeStart, sizeof(int)), (int)MessageType.OpenBlock); Assert.Equal(MessageType.OpenBlock, ClientServerMessage.GetMessageType(_bytes)); BitConverter.TryWriteBytes(new Span <byte>(_bytes, ClientServerMessage.MessageTypeStart, sizeof(int)), (int)MessageType.CommitBlock); Assert.Equal(MessageType.CommitBlock, ClientServerMessage.GetMessageType(_bytes)); BitConverter.TryWriteBytes(new Span <byte>(_bytes, ClientServerMessage.MessageTypeStart, sizeof(int)), (int)MessageType.Authenticate); Assert.Equal(MessageType.Authenticate, ClientServerMessage.GetMessageType(_bytes)); BitConverter.TryWriteBytes(new Span <byte>(_bytes, ClientServerMessage.MessageTypeStart, sizeof(int)), (int)MessageType.GetBlockHandle); Assert.Equal(MessageType.GetBlockHandle, ClientServerMessage.GetMessageType(_bytes)); BitConverter.TryWriteBytes(new Span <byte>(_bytes, ClientServerMessage.MessageTypeStart, sizeof(int)), (int)MessageType.IsAncestor); Assert.Equal(MessageType.IsAncestor, ClientServerMessage.GetMessageType(_bytes)); BitConverter.TryWriteBytes(new Span <byte>(_bytes, ClientServerMessage.MessageTypeStart, sizeof(int)), (int)MessageType.IsPruneable); Assert.Equal(MessageType.IsPruneable, ClientServerMessage.GetMessageType(_bytes)); Assert.Throws <ArgumentException>(() => ClientServerMessage.GetMessageType(new Span <byte>(_bytes, 0, ClientServerMessage.PayloadStart - 1))); }
//Метод, вытягивающий информацию о работах, соответствующих данному типу мастера private static ClientServerMessage GetMasterWorks(ClientServerMessage request) { var masterType = (WorkType)Int32.Parse(request.Arguments["master"]); var args = new Dictionary <string, string>(); args.Add("result", "success"); ClientServerMessage response; using (DbContext context = new DbContext(DbConnectionString)) { List <Work> works = context.Works.Where(x => x.Type == masterType).ToList(); if (works == null) { args["result"] = "failed"; } else { args.Add("works", JsonConvert.SerializeObject(works)); } } response = new ClientServerMessage(args); return(response); }
//Метод отправки сообщения на сервер и ожидания ответа private ClientServerMessage SendMessage(ClientServerMessage message) { byte[] bytes = new byte[4096]; //Конфигурируем точку, к которой будем обращаться IPHostEntry ipHost = Dns.GetHostEntry(URL); IPAddress iPAddress = ipHost.AddressList[0]; IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, Port); //Открываем сокет в конечной точке и соединяемся с ним var sender = new Socket(iPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); sender.Connect(iPEndPoint); //Отправляем сообщение на сервер byte[] msg = Encoding.UTF8.GetBytes(message.Message); sender.Send(msg); //Принимаем сообщение с сервера int bytesReceived = sender.Receive(bytes); ClientServerMessage receivedMessage = new ClientServerMessage(Encoding.UTF8.GetString(bytes, 0, bytesReceived)); //Закрываем соединение sender.Shutdown(SocketShutdown.Both); sender.Close(); //Возвращаем сообщение, полученное с сервера return(receivedMessage); }
public void FillShardedInboxes() { var queue = new ConcurrentQueue <ClientConnection>(); var socket = new MockSocket(); var client1 = new ClientConnection(socket, ClientId.Next(), 100); var client2 = new ClientConnection(socket, ClientId.Next(), 100); BoundedInbox[] threadInboxes = { BoundedInbox.Create(), BoundedInbox.Create() }; var dispatcher = new Dispatcher(queue, 3, BoundedInbox.Create(), threadInboxes, BoundedInbox.Create()); // Client1 sharded message socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => LargeMessageSize); socket.ExpectReceive(data => { data.Clear(); BitConverter.GetBytes(LargeMessageSize).CopyTo(data); data[ClientServerMessage.ShardedIndStart] = 0xFF; // 0xFF: all bits set to one, so "sharded" is set to 1 for sure data[ClientServerMessage.PayloadStart] = 0x01; return(LargeMessageSize); }); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 0); // Client2 sharded message socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => LargeMessageSize); socket.ExpectReceive(data => { data.Clear(); BitConverter.GetBytes(LargeMessageSize).CopyTo(data); data[12] = 0xFF; return(LargeMessageSize); }); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 0); // Client1 sharded message, fills up first sharded inbox socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => LargeMessageSize); socket.ExpectReceive(data => { data.Clear(); BitConverter.GetBytes(LargeMessageSize).CopyTo(data); data[ClientServerMessage.ShardedIndStart] = 0xFF; // 0xFF: all bits set to one, so "sharded" is set to 1 for sure data[ClientServerMessage.PayloadStart] = 0x00; return(LargeMessageSize); }); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 0); // Client2 sharded message, fills up second sharded inbox socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => LargeMessageSize); socket.ExpectReceive(data => { data.Clear(); BitConverter.GetBytes(LargeMessageSize).CopyTo(data); data[ClientServerMessage.ShardedIndStart] = 0xFF; // 0xFF: all bits set to one, so "sharded" is set to 1 for sure data[ClientServerMessage.PayloadStart] = 0x01; return(LargeMessageSize); }); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 0); // Read and get error message server busy writing into second sharded inbox socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 20); socket.ExpectReceive(data => { data.Clear(); BitConverter.GetBytes(20).CopyTo(data); data[ClientServerMessage.ShardedIndStart] = 0xFF; data[ClientServerMessage.PayloadStart] = 0x01; return(20); }); socket.ExpectConnected(() => true); socket.ExpectSend(data => { Assert.Equal(ClientServerMessage.PayloadStart, data.Length); Assert.Equal(data[13], (byte)MessageType.ServerBusy); return(ClientServerMessage.PayloadStart); }); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 0); // Read and get error message server busy writing into first sharded inbox socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 20); socket.ExpectReceive(data => { data.Clear(); BitConverter.GetBytes(20).CopyTo(data); data[ClientServerMessage.ShardedIndStart] = 0xFF; // 0xFF: all bits set to one, so "sharded" is set to 1 for sure data[ClientServerMessage.PayloadStart] = 0x00; return(20); }); socket.ExpectConnected(() => true); socket.ExpectSend(data => { Assert.Equal(ClientServerMessage.PayloadStart, data.Length); Assert.Equal(MessageType.ServerBusy, ClientServerMessage.GetMessageType(data)); return(ClientServerMessage.PayloadStart); }); socket.ExpectConnected(() => true); socket.ExpectAvailable(() => 0); queue.Enqueue(client1); queue.Enqueue(client2); dispatcher.DequeueNewClients(); // Client1 into sharded inbox 1, Client2 into sharded inbox 2 dispatcher.ListenToConnections(); // Client1 filling up sharded inbox 2, Client2 filling up sharded inbox 1 dispatcher.ListenToConnections(); // Errors when trying to write into any inbox dispatcher.ListenToConnections(); socket.ExpectAllDone(); }
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)); }
public void TestRequestIdField() { Assert.Equal(0x18171615U, ClientServerMessage.GetRequestId(_bytes)); Assert.Throws <ArgumentException>(() => ClientServerMessage.GetRequestId(new Span <byte>(_bytes, 0, 7))); }
public void DoWork() // TODO: [vermorel] method should return 'true' if any work has been done { var nextMessage = _inbox.Peek(); if (nextMessage.Length != 0) { // get message type and deserialize accordingly var reqType = ClientServerMessage.GetMessageType(nextMessage); switch (reqType) { // TODO: [vermorel] I don't like to too much the code below, it's highly repetitive, factorization is needed. case MessageType.OpenBlock: var openBlock = MessageSerializers.DeserializeOpenBlock(nextMessage); UncommittedBlock block; if (openBlock.ParentHandle == BlockAlias.GenesisParent && _chain.BlockchainLength == 0) { block = _chain.OpenFirstBlock(); } else { block = _chain.OpenBlock(openBlock.ParentHandle); } var blockHandle = new OpenedBlock(openBlock.RequestId, openBlock.ClientId, block.BlockId, block.Alias); MessageSerializers.SerializeOpenedBlock(blockHandle, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, OpenedBlock.SizeInBytes)); break; case MessageType.GetBlockHandle: var getBlockHandle = MessageSerializers.DeserializeGetBlockHandle(nextMessage); var retrievedHandle = _chain.RetrieveAlias(getBlockHandle.BlockId); var returnMessage = new BlockHandleResponse(getBlockHandle.RequestId, getBlockHandle.ClientId, retrievedHandle); MessageSerializers.SerializeBlockHandleResponse(returnMessage, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, BlockHandleResponse.SizeInBytes)); break; case MessageType.GetUncommittedBlockHandle: var getUBlockHandle = MessageSerializers.DeserializeGetUncommittedBlockHandle(nextMessage); var retrievedUHandle = _chain.RetrieveAlias(getUBlockHandle.UncommittedBlockId); var returnMes = new BlockHandleResponse(getUBlockHandle.RequestId, getUBlockHandle.ClientId, retrievedUHandle); MessageSerializers.SerializeBlockHandleResponse(returnMes, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, BlockHandleResponse.SizeInBytes)); break; case MessageType.CommitBlock: var commitBlock = MessageSerializers.DeserializeCommitBlock(nextMessage); _chain.CommitBlock(commitBlock.BlockHandle, commitBlock.BlockId); var committedMessage = new EverythingOkResponse(commitBlock.RequestId, commitBlock.ClientId); MessageSerializers.SerializeEverythingOk(committedMessage, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, EverythingOkResponse.SizeInBytes)); break; case MessageType.IsAncestor: var isAncestor = MessageSerializers.DeserializeIsAncestor(nextMessage); var res = _opti.IsAncestor(isAncestor.BlockHandle, isAncestor.MaybeAncestorHandle); var isAncestorMessage = new AncestorResponse(isAncestor.RequestId, isAncestor.ClientId, res); MessageSerializers.SerializeAncestorResponse(isAncestorMessage, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, AncestorResponse.SizeInBytes)); break; case MessageType.IsPruneable: var isPruneable = MessageSerializers.DeserializeIsPruneable(nextMessage); var result = _opti.IsPruneable(isPruneable.BlockHandle); var isPruneableMessage = new PruneableResponse(isPruneable.RequestId, isPruneable.ClientId, result); MessageSerializers.SerializePruneableResponse(isPruneableMessage, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, PruneableResponse.SizeInBytes)); break; case MessageType.GetBlockInfo: var blockInfoReq = MessageSerializers.DeserializeGetBlockInfo(nextMessage); // TODO: [vermorel] clarify the purpose of this test, unclear if (_chain.RetrieveCommittedBlock(blockInfoReq.BlockHandle, out var blockInfoC)) { var blockInfo = new CommittedBlockInformation(blockInfoReq.RequestId, blockInfoReq.ClientId, blockInfoC.BlockId, blockInfoC.Alias, blockInfoC.BlockHeight, blockInfoC.Parent); MessageSerializers.SerializeCommittedBlockInfo(blockInfo, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, CommittedBlockInformation.SizeInBytes)); break; } else { _chain.RetrieveUncommittedBlock(blockInfoReq.BlockHandle, out var blockInfoU); var blockInfo = new UncommittedBlockInformation(blockInfoReq.RequestId, blockInfoReq.ClientId, blockInfoU.BlockId, blockInfoU.Alias, blockInfoU.BlockHeight, blockInfoU.Parent); MessageSerializers.SerializeUncommittedBlockInfo(blockInfo, _responseBuffer); _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, UncommittedBlockInformation.SizeInBytes)); break; } // TODO: [vermorel] the 'default:' case should be covered with an NotSupportedException. } _inbox.Next(); // TODO: errors are not yet handled. } }
public void TestFirstKeyByte() { Assert.Equal(_bytes[ClientServerMessage.PayloadStart], ClientServerMessage.FirstKeyByte(_bytes)); Assert.Throws <ArgumentException>(() => ClientServerMessage.FirstKeyByte(new Span <byte>(_bytes, 0, ClientServerMessage.PayloadStart))); }
//Проверка сообщения на присутствие аргумента result в значении success private bool CheckReceivedMessage(ClientServerMessage message) { return(message.Arguments.ContainsKey("result") && message.Arguments["result"] == "success"); }