/// <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);
        }
예제 #2
0
        /// <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);
        }