Exemplo n.º 1
0
        internal void AddHandler(ConnectingHandler handler)
        {
            handlers.TryAdd(handler.ID, handler);
            Interlocked.Increment(ref handlerCount);

            host.RaiseHostStateChange(this, ReasonChange.AddHandler, handler);
        }
        /// <summary>
        /// Начинает предобработку нового подключения.
        /// </summary>
        /// <param name="handlerFactory">Фабрика для создания обработчика данного подключения.</param>
        public async Task Start(Socket socket, Func <Connection, ConnectedClient, ConnectingHandler> handlerFactory)
        {
            ConnectingHandler handler    = null;
            ConnectedClient   client     = null;
            Connection        connection = new Connection(socket);

            try
            {
                Initialization init = new Initialization(connection);

                await init.ReceiveAsyncControlCommand().ConfigureAwait(false);

                Logger.Write(Source.Server, $"Начата предобработка нового подключения. Получен код команды: {init.CommandCode}");

                switch (init.CommandCode)
                {
                case NetSharpProtocol.Commands.NEW_CLIENT:
                {
                    #region ~Подключение нового клиента.~
                    client = host.ClientManager.CreateNewClient();

                    handler = handlerFactory(connection, client);
                    connection.InitializationOnServer(client.ID, handler.ID, handler.Name, client.ReconnectManager);
                    client.AddHandler(handler);

                    Logger.Write(Source.Server, $"Создан новый клиент. Удалённый адрес: {connection.RemoteEndPoint}",
                                 data: Data.Create().
                                 SetClientID(client.ID).
                                 SetHandlerData(handler.ID, handler.Name));

                    await init.SendAsyncClientAndHandlerID(NetSharpProtocol.Commands.ACCEPT, client.ID, handler.ID).ConfigureAwait(false);

                    await handler.StartService().ConfigureAwait(false);

                    #endregion
                }
                break;

                case NetSharpProtocol.Commands.NOT_NEW_CLIENT:
                {
                    #region ~Подключение от уже существующего клиента.~
                    Guid clientID = init.GetClientOrHandlerID();

                    client = host.ClientManager.GetClientByID(clientID);

                    if (client != null)
                    {
                        handler = handlerFactory(connection, client);
                        connection.InitializationOnServer(client.ID, handler.ID, handler.Name, client.ReconnectManager);
                        client.AddHandler(handler);

                        Logger.Write(Source.Server, "Добавлен обработчик.",
                                     data: Data.Create().
                                     SetClientID(client.ID).
                                     SetHandlerData(handler.ID, handler.Name));

                        await init.SendAsyncClientOrHandlerID(NetSharpProtocol.Commands.ACCEPT, handler.ID).ConfigureAwait(false);

                        await handler.StartService().ConfigureAwait(false);
                    }
                    else
                    {
                        Logger.Write(Source.Server, $"Новое подключение от уже подключённого клиента. Ошибка: клиент с указанным ID не найден на сервере.",
                                     data: Data.Create().SetClientID(clientID));

                        await init.SendAsyncControlCommand(NetSharpProtocol.Commands.DENY, NetSharpProtocol.Errors.CLIENT_NOT_FOUND).ConfigureAwait(false);
                    }
                    #endregion
                }
                break;

                case NetSharpProtocol.Commands.RECONNECT:
                {
                    #region ~Восстановление связи.~
                    Guid[] ids = init.GetClientAndHandlerID();

                    client = host.ClientManager.GetClientByID(ids[0]);

                    if (client != null)
                    {
                        if (client.ReconnectManager.ProcessNewConnection(ids[1], socket))
                        {
                            Logger.Write(Source.Server, $"Подключение для обработчика с ID {ids[1]} успешно восстановлено.");

                            await init.SendAsyncControlCommand(NetSharpProtocol.Commands.ACCEPT).ConfigureAwait(false);
                        }
                        else
                        {
                            Logger.Write(Source.Server, $"Запрос на восстановление подключения не может быть выполнен, т.к. обработчик с ID {ids[1]} не зарегистрирован как ожидающий восстановления подключения или был удалён по истечении временного интервала.");

                            await init.SendAsyncControlCommand(NetSharpProtocol.Commands.DENY,
                                                               NetSharpProtocol.Errors.HANDLER_NOT_FOUND).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        Logger.Write(Source.Server, $"Запрос на восстановление подключения не может быть выполнен, т.к. клиент с ID {ids[1]} не найден.");

                        await init.SendAsyncControlCommand(NetSharpProtocol.Commands.DENY,
                                                           NetSharpProtocol.Errors.CLIENT_NOT_FOUND).ConfigureAwait(false);
                    }
                    #endregion
                }
                break;

                default:
                {
                    await init.SendAsyncControlCommand(NetSharpProtocol.Commands.DENY, NetSharpProtocol.Errors.UNKNOWN_CODE).ConfigureAwait(false);
                }
                break;
                }
            }
            catch (Exception ex)
            {
                if (handler == null)
                {
                    Logger.Write(Source.Server, "Исключение в задаче обработчика. Обработчик не был запущен.", ex);
                    connection.Close();
                }
                else
                {
                    Type exType = ex.GetType();

                    if ((exType == typeof(ObjectDisposedException) || exType == typeof(CommunicationException)) && handler.HardStop)
                    {
                        Logger.Write(Source.Server, $"Обработчик завершил работу. Причина: выполнена жесткая остановка.",
                                     data: Data.Create().SetHandlerData(handler.ID, handler.Name));
                    }
                    else
                    {
                        Logger.Write(Source.Server, "Исключение в задаче обработчика. Обработчик завершил работу.", ex,
                                     Data.Create().SetHandlerData(handler.ID, handler.Name));
                    }

                    client.RemoveHandler(handler.ID);
                }

                return;
            }

            Logger.Write(Source.Server, $"Обработчик завершил работу. Причина: нормальное завершение.",
                         data: Data.Create().SetHandlerData(handler.ID, handler.Name));

            client.RemoveHandler(handler.ID);
        }