/// <summary> /// Sends ERROR_PROTOCOL_VIOLATION to client with message ID set to 0x0BADC0DE. /// </summary> /// <param name="Client">Client to send the error to.</param> public async Task SendProtocolViolation(ClientBase Client) { LocMessageBuilder mb = new LocMessageBuilder(0, new List <SemVer> { SemVer.V100 }); LocProtocolMessage response = mb.CreateErrorProtocolViolationResponse(new LocProtocolMessage(new Message() { Id = 0x0BADC0DE })); await Client.SendMessageAsync(response); }
/// <summary> /// Processing of a message received from a client. /// </summary> /// <param name="Client">TCP client.</param> /// <param name="MessageBuilder">Client's message builder.</param> /// <param name="IncomingMessage">Full ProtoBuf message to be processed.</param> /// <returns>true if the conversation with the client should continue, false if a protocol violation error occurred and the client should be disconnected.</returns> public async Task <bool> ProcessMessageAsync(TcpClient Client, LocMessageBuilder MessageBuilder, LocProtocolMessage IncomingMessage) { bool res = false; log.Debug("()"); try { log.Trace("Received message type is {0}, message ID is {1}.", IncomingMessage.MessageTypeCase, IncomingMessage.Id); switch (IncomingMessage.MessageTypeCase) { case Message.MessageTypeOneofCase.Request: { LocProtocolMessage responseMessage = MessageBuilder.CreateErrorProtocolViolationResponse(IncomingMessage); Request request = IncomingMessage.Request; bool setKeepAlive = false; SemVer version = new SemVer(request.Version); log.Trace("Request type is {0}, version is {1}.", request.RequestTypeCase, version); switch (request.RequestTypeCase) { case Request.RequestTypeOneofCase.LocalService: { log.Trace("Local service request type is {0}.", request.LocalService.LocalServiceRequestTypeCase); switch (request.LocalService.LocalServiceRequestTypeCase) { case LocalServiceRequest.LocalServiceRequestTypeOneofCase.RegisterService: responseMessage = ProcessMessageRegisterServiceRequest(Client, MessageBuilder, IncomingMessage); break; case LocalServiceRequest.LocalServiceRequestTypeOneofCase.DeregisterService: responseMessage = ProcessMessageDeregisterServiceRequest(Client, MessageBuilder, IncomingMessage); break; case LocalServiceRequest.LocalServiceRequestTypeOneofCase.GetNeighbourNodes: responseMessage = ProcessMessageGetNeighbourNodesByDistanceLocalRequest(Client, MessageBuilder, IncomingMessage, out setKeepAlive); break; default: log.Error("Invalid local service request type '{0}'.", request.LocalService.LocalServiceRequestTypeCase); break; } break; } default: log.Error("Invalid request type '{0}'.", request.RequestTypeCase); break; } if (responseMessage != null) { // Send response to client. res = await SendMessageAsync(Client, responseMessage); if (res) { // If the message was sent successfully to the target, we close the connection only in case of protocol violation error. if (responseMessage.MessageTypeCase == Message.MessageTypeOneofCase.Response) { res = responseMessage.Response.Status != Status.ErrorProtocolViolation; } } if (res && setKeepAlive) { connectedProfileServerWantsUpdates = true; log.Debug("Profile server '{0}' is now connected to its LOC server and waiting for updates.", profileServer.Name); } } else { // If there is no response to send immediately to the client, // we want to keep the connection open. res = true; } break; } case Message.MessageTypeOneofCase.Response: { Response response = IncomingMessage.Response; log.Trace("Response status is {0}, details are '{1}', response type is {2}.", response.Status, response.Details, response.ResponseTypeCase); switch (response.ResponseTypeCase) { case Response.ResponseTypeOneofCase.LocalService: { log.Trace("Local service response type is {0}.", response.LocalService.LocalServiceResponseTypeCase); switch (response.LocalService.LocalServiceResponseTypeCase) { case LocalServiceResponse.LocalServiceResponseTypeOneofCase.NeighbourhoodUpdated: // Nothing to be done here. res = true; break; default: log.Error("Invalid local service response type '{0}'.", response.LocalService.LocalServiceResponseTypeCase); break; } break; } default: log.Error("Unknown response type '{0}'.", response.ResponseTypeCase); // Connection will be closed in ReceiveMessageLoop. break; } break; } default: log.Error("Unknown message type '{0}', connection to the client will be closed.", IncomingMessage.MessageTypeCase); await SendProtocolViolation(Client); // Connection will be closed in ReceiveMessageLoop. break; } } catch (Exception e) { log.Error("Exception occurred, connection to the client will be closed: {0}", e.ToString()); await SendProtocolViolation(Client); // Connection will be closed in ReceiveMessageLoop. } log.Debug("(-):{0}", res); return(res); }