예제 #1
0
        public ServerConnection(Socket socket, ServiceDispatcher dispatcher, ServiceHostConfig config, ServiceHostCounters counters, ISerializer serializer, X509Certificate?certificate)
        {
            _dispatcher    = dispatcher;
            _socket        = socket;
            _config        = config;
            _requestLogger = new RequestLogger(socket.GetRemoteAddressName(), dispatcher.MessageMap);

            Stream readerStream, writerStream;

            if (config.TlsSettings == null || certificate == null)
            {
                readerStream = new NetworkStream(socket, FileAccess.Read, false);
                writerStream = new NetworkStream(socket, FileAccess.Write, false);
            }
            else
            {
                var networkStream = new NetworkStream(socket, FileAccess.ReadWrite, false);
                var tlsStream     = new SslStream(networkStream, true);

                readerStream = writerStream = tlsStream;

                _tls = new TlsData(certificate, tlsStream);
            }

            _messageReader = new DelimitedMessageReader(socket.GetRemoteAddressName(), readerStream, serializer);
            _messageWriter = new DelimitedMessageWriter(socket.GetRemoteAddressName(), writerStream, serializer);

            _responsePropagatorTask = PropagateResponses();
            _counters = counters;
        }
예제 #2
0
        private static void LogDispatcher(ServiceDispatcher dispatcher)
        {
            _logger.Info("The following message handlers found:");
            foreach ((int requestId, int responseId) in dispatcher.GetRequestResponseMap())
            {
                Type requestType  = dispatcher.MessageMap.GetMessageTypeById(requestId);
                Type?responseType = responseId > 0 ? dispatcher.MessageMap.GetMessageTypeById(responseId) : null;

                if (responseType != null)
                {
                    _logger.Info("  {0} -> {1}", requestType.Name, responseType.Name);
                }
                else
                {
                    _logger.Info("  {0}", requestType.Name);
                }
            }
        }
예제 #3
0
        public async Task Start(ServiceHostConfig config)
        {
            if (_listeningSocket != null)
            {
                throw new InvalidOperationException("Service host is already started.");
            }

            try
            {
                ConfigureLogger(config);
                LoadMessageAssemblies(config.MessageAssemblies);
                LoadServiceAssemblies(config.ServiceAssemblies);

                var incomingSerializer = (ISerializer)Activator.CreateInstance(Type.GetType(config.Serializer));
                var outgoingSerializer = (ISerializer)Activator.CreateInstance(Type.GetType(config.ClusterConnectionSettings.Serializer));

                InitSignalHandlers();

                X509Certificate?certificate = await LoadCertificate(config);

                var session  = new Session();
                var counters = new ServiceHostCounters();

                using ClusterConnection clusterConnection = CreateClusterConnection(config, outgoingSerializer);
                using IContainer container = BuildContainer(config, clusterConnection, session);

                var dispatcher = new ServiceDispatcher(container, _serviceTypes, clusterConnection);

                _listeningSocket = new Socket(SocketType.Stream, ProtocolType.IP);
                _listeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                _listeningSocket.Bind(new IPEndPoint(IPAddress.Any, config.Port));
                _listeningSocket.Listen(128);

                if (config.Gateway)
                {
                    _logger.Info("Server started as gateway. Listening port {0}...", config.Port);
                }
                else
                {
                    _logger.Info("Server started. Listening port {0}...", config.Port);
                }

                Task clusterConnectionTask   = ConnectCluster(config, clusterConnection);
                Task callbacksInvocationTask = UpdateClusterConnection(config, clusterConnection);

                // If it is a gateway, the host waits for the cluster connection to obtain
                // message maps, initializes routes and only then accepts connections.
                //
                // The first connection attempt tries to connect only once, so it is assumed
                // that the cluster itself is completely up before all its gateways.
                if (config.Gateway)
                {
                    await clusterConnectionTask;
                    dispatcher.InitGatewayRouts();
                }

                LogDispatcher(dispatcher);

                int nextConnectionId = 1;

                while (true)
                {
                    Socket connectionSocket;
                    try
                    {
                        connectionSocket = await _listeningSocket.AcceptAsync();
                    }
                    catch (SocketException)
                    {
                        _logger.Info("The listening socket is closed. The host is going to shutdown.");
                        break;
                    }

                    _logger.Info("Client connected {0}.", connectionSocket.GetRemoteAddressName());

                    ServeConnection(
                        new ServerConnection(
                            connectionSocket,
                            dispatcher,
                            config,
                            counters,
                            incomingSerializer,
                            certificate
                            ),
                        config,
                        session,
                        nextConnectionId++
                        );
                }

                _updateClusterConnection = false;

                await clusterConnectionTask;
                await callbacksInvocationTask;
            }
            catch (Exception ex)
            {
                _logger.Fatal(ex, "Service host faulted.");
            }
            finally
            {
                _listeningSocket?.Dispose();
                _listeningSocket = null;

                _logger.Info("Service host stopped.");

                LogManager.Flush();

                _serviceHostStopped.Set();
            }
        }