private async Task HandleAsync(Server server, ClientMessageConnection connection, ClientMessage requestMessage, Func <Server, ClientMessageConnection, ClientMessage, ValueTask> handler) { var correlationId = requestMessage.CorrelationId; async Task SendResponseAsync(ClientMessage response) { response.CorrelationId = requestMessage.CorrelationId; response.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await connection.SendAsync(response).CfAwait(); } async Task SendEventAsync(ClientMessage eventMessage, long correlationId) { eventMessage.CorrelationId = correlationId; eventMessage.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await connection.SendAsync(eventMessage).CfAwait(); } switch (requestMessage.MessageType) { // handle authentication case ClientAuthenticationServerCodec.RequestMessageType: { var request = ClientAuthenticationServerCodec.DecodeRequest(requestMessage); var responseMessage = ClientAuthenticationServerCodec.EncodeResponse( 0, server.Address, server.MemberId, SerializationService.SerializerVersion, "4.0", 1, server.ClusterId, false); await SendResponseAsync(responseMessage).CfAwait(); break; } // handle events case ClientAddClusterViewListenerServerCodec.RequestMessageType: { var request = ClientAddClusterViewListenerServerCodec.DecodeRequest(requestMessage); var responseMessage = ClientAddClusterViewListenerServerCodec.EncodeResponse(); await SendResponseAsync(responseMessage).CfAwait(); _ = Task.Run(async() => { await Task.Delay(500).CfAwait(); var eventMessage = ClientAddClusterViewListenerServerCodec.EncodeMembersViewEvent(1, new[] { new MemberInfo(server.MemberId, server.Address, new MemberVersion(4, 0, 0), false, new Dictionary <string, string>()), }); await SendEventAsync(eventMessage, correlationId).CfAwait(); }); break; } // handle others default: await handler(server, connection, requestMessage).CfAwait(); break; } }
private async ValueTask ReceiveMessage(Server server, ClientMessageConnection connection, ClientMessage message) { HConsole.WriteLine(this, "Respond"); var text = Encoding.UTF8.GetString(message.FirstFrame.Bytes); #if NETSTANDARD2_1 var responseText = text switch { "a" => "alpha", "b" => "bravo", _ => "??" }; #else var responseText = text == "a" ? "alpha" : text == "b" ? "bravo" : "??"; #endif // this is very basic stuff and does not respect HZ protocol // the 64-bytes header is nonsense etc var response = new ClientMessage() .Append(new Frame(new byte[64])) // header stuff .Append(new Frame(Encoding.UTF8.GetBytes(responseText))); response.CorrelationId = message.CorrelationId; response.MessageType = 0x1; // 0x00 means exception // send in one fragment, set flags response.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await connection.SendAsync(response).CfAwait(); HConsole.WriteLine(this, "Responded"); }
public void ArgumentExceptions() { var endpoint = NetworkAddress.Parse("127.0.0.1:11000").IPEndPoint; var s = new ClientSocketConnection(1, endpoint, new NetworkingOptions(), new SslOptions(), new NullLoggerFactory()); var c = new ClientMessageConnection(s, new NullLoggerFactory()); Assert.ThrowsAsync <ArgumentNullException>(async() => _ = await c.SendAsync(null)); }
private async ValueTask ServerHandler(Server s, ClientMessageConnection conn, ClientMessage msg) { async Task SendResponseAsync(ClientMessage response) { response.CorrelationId = msg.CorrelationId; response.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await conn.SendAsync(response).CfAwait(); } async Task SendEventAsync(ClientMessage eventMessage, long correlationId) { eventMessage.CorrelationId = correlationId; eventMessage.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await conn.SendAsync(eventMessage).CfAwait(); } async Task SendErrorAsync(RemoteError error, string message) { var errorHolders = new List <ErrorHolder> { new ErrorHolder(error, "?", message, Enumerable.Empty <StackTraceElement>()) }; var response = ErrorsServerCodec.EncodeResponse(errorHolders); await SendResponseAsync(response).CfAwait(); } var state = (ServerState)s.State; var address = s.Address; const int partitionsCount = 2; switch (msg.MessageType) { // must handle auth case ClientAuthenticationServerCodec.RequestMessageType: { HConsole.WriteLine(this, $"(server{state.Id}) Authentication"); var authRequest = ClientAuthenticationServerCodec.DecodeRequest(msg); var authResponse = ClientAuthenticationServerCodec.EncodeResponse( 0, address, s.MemberId, SerializationService.SerializerVersion, "4.0", partitionsCount, s.ClusterId, false); await SendResponseAsync(authResponse).CfAwait(); break; } // must handle events case ClientAddClusterViewListenerServerCodec.RequestMessageType: { HConsole.WriteLine(this, $"(server{state.Id}) AddClusterViewListener"); var addRequest = ClientAddClusterViewListenerServerCodec.DecodeRequest(msg); var addResponse = ClientAddClusterViewListenerServerCodec.EncodeResponse(); await SendResponseAsync(addResponse).CfAwait(); _ = Task.Run(async() => { await Task.Delay(500).CfAwait(); const int membersVersion = 1; var memberVersion = new MemberVersion(4, 0, 0); var memberAttributes = new Dictionary <string, string>(); var membersEventMessage = ClientAddClusterViewListenerServerCodec.EncodeMembersViewEvent(membersVersion, new[] { new MemberInfo(state.MemberIds[0], state.Addresses[0], memberVersion, false, memberAttributes), new MemberInfo(state.MemberIds[1], state.Addresses[1], memberVersion, false, memberAttributes), }); await SendEventAsync(membersEventMessage, msg.CorrelationId).CfAwait(); await Task.Delay(500).CfAwait(); const int partitionsVersion = 1; var partitionsEventMessage = ClientAddClusterViewListenerServerCodec.EncodePartitionsViewEvent(partitionsVersion, new[] { new KeyValuePair <Guid, IList <int> >(state.MemberIds[0], new List <int> { 0 }), new KeyValuePair <Guid, IList <int> >(state.MemberIds[1], new List <int> { 1 }), }); await SendEventAsync(partitionsEventMessage, msg.CorrelationId).CfAwait(); }); break; } // create object case ClientCreateProxyServerCodec.RequestMessageType: { HConsole.WriteLine(this, $"(server{state.Id}) CreateProxy"); var createRequest = ClientCreateProxyServerCodec.DecodeRequest(msg); var createResponse = ClientCreateProxiesServerCodec.EncodeResponse(); await SendResponseAsync(createResponse).CfAwait(); break; } // subscribe case MapAddEntryListenerServerCodec.RequestMessageType: { HConsole.WriteLine(this, $"(server{state.Id}) AddEntryListener"); var addRequest = MapAddEntryListenerServerCodec.DecodeRequest(msg); state.Subscribed = true; state.SubscriptionCorrelationId = msg.CorrelationId; var addResponse = MapAddEntryListenerServerCodec.EncodeResponse(state.SubscriptionId); await SendResponseAsync(addResponse).CfAwait(); break; } // unsubscribe // server 1 removes on first try, server 2 removes on later tries case MapRemoveEntryListenerServerCodec.RequestMessageType: { HConsole.WriteLine(this, $"(server{state.Id}) RemoveEntryListener"); var removeRequest = MapRemoveEntryListenerServerCodec.DecodeRequest(msg); var removed = state.Subscribed && removeRequest.RegistrationId == state.SubscriptionId; removed &= state.Id == 0 || state.UnsubscribeCount++ > 0; if (removed) { state.Subscribed = false; } HConsole.WriteLine(this, $"(server{state.Id}) Subscribed={state.Subscribed}"); var removeResponse = MapRemoveEntryListenerServerCodec.EncodeResponse(removed); await SendResponseAsync(removeResponse).CfAwait(); break; } // add to map & trigger event case MapSetServerCodec.RequestMessageType: { HConsole.WriteLine(this, $"(server{state.Id}) Set"); var setRequest = MapSetServerCodec.DecodeRequest(msg); var setResponse = MapSetServerCodec.EncodeResponse(); await SendResponseAsync(setResponse).CfAwait(); HConsole.WriteLine(this, $"(server{state.Id}) Subscribed={state.Subscribed}"); if (state.Subscribed) { HConsole.WriteLine(this, $"(server{state.Id}) Trigger event"); var key = setRequest.Key; var value = setRequest.Value; var addedEvent = MapAddEntryListenerServerCodec.EncodeEntryEvent(key, value, value, value, (int)MapEventTypes.Added, state.SubscriptionId, 1); await SendEventAsync(addedEvent, state.SubscriptionCorrelationId).CfAwait(); } break; } // unexpected message = error default: { // RemoteError.Hazelcast or RemoteError.RetryableHazelcast var messageName = MessageTypeConstants.GetMessageTypeName(msg.MessageType); await SendErrorAsync(RemoteError.Hazelcast, $"MessageType {messageName} (0x{msg.MessageType:X}) not implemented.").CfAwait(); break; } } }
protected async Task SendAsync(ClientMessageConnection connection, ClientMessage eventMessage, long correlationId) { eventMessage.CorrelationId = correlationId; eventMessage.Flags |= ClientMessageFlags.BeginFragment | ClientMessageFlags.EndFragment; await connection.SendAsync(eventMessage).CfAwait(); }