Ejemplo n.º 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;
        }
Ejemplo n.º 2
0
 private static ClusterConnection CreateClusterConnection(ServiceHostConfig config, ISerializer serializer)
 {
     return(new ClusterConnection(config.KnownHosts, new ClusterConnectionSettings {
         ReconnectionDelay = TimeSpan.FromSeconds(config.ClusterConnectionSettings.ReconnectionDelay),
         MaxRequestHoldTime = TimeSpan.FromSeconds(config.ClusterConnectionSettings.MaxRequestHoldTime),
         Serializer = serializer,
         TlsSettings =
         {
             AllowSelfSignedCertificates = config.TlsSettings?.AllowSelfSignedCertificates ?? false
         }
     }));
 }
Ejemplo n.º 3
0
        private static async Task ConnectCluster(ServiceHostConfig config, ClusterConnection clusterConnection)
        {
            _logger.Info("Connecting cluster after {0} sec.", config.ClusterConnectionSettings.ConnectionDelay);

            try
            {
                await clusterConnection.Connect(TimeSpan.FromSeconds(config.ClusterConnectionSettings.ConnectionDelay));

                _logger.Info("Cluster connected.");
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Failed to connect cluster. Interservice communication is not available.");
            }
        }
Ejemplo n.º 4
0
        private async Task UpdateClusterConnection(ServiceHostConfig config, ClusterConnection clusterConnection)
        {
            try
            {
                while (_updateClusterConnection)
                {
                    clusterConnection.Update();

                    await Task.Delay(TimeSpan.FromMilliseconds(config.ClusterConnectionSettings.UpdatePeriodMs));
                }
            }
            catch (Exception ex)
            {
                // Server callbacks are just async completions. They are not expected to throw exceptions.
                _logger.Fatal(ex, "Callbacks invocation faulted. No more callbacks will be invoked.");
            }
        }
Ejemplo n.º 5
0
        private static async Task <X509Certificate?> LoadCertificate(ServiceHostConfig config)
        {
            if (config.TlsSettings == null || string.IsNullOrEmpty(config.TlsSettings.CertificateFile) || string.IsNullOrEmpty(config.TlsSettings.PasswordFile))
            {
                return(null);
            }

            byte[] certificateData = await File.ReadAllBytesAsync(config.TlsSettings.CertificateFile);

            string password = await File.ReadAllTextAsync(config.TlsSettings.PasswordFile);

            var certificate = new X509Certificate(certificateData, password);

            _logger.Info("Loaded TLS certificate issued by '{0}' for '{1}' SN:'{2}' expires: {3}",
                         certificate.Issuer,
                         certificate.Subject,
                         certificate.GetSerialNumberString(),
                         certificate.GetExpirationDateString()
                         );

            return(certificate);
        }
Ejemplo n.º 6
0
        private async void ServeConnection(ServerConnection connection, ServiceHostConfig config, Session session, int connectionId)
        {
            var clientRemoteAddress = ((IPEndPoint)connection.Socket.RemoteEndPoint).Address;

            try
            {
                session.SetData(new Session.Data {
                    InstanceId          = config.InstanceId,
                    ClientRemoteAddress = clientRemoteAddress,
                    ConnectionId        = connectionId
                });

                await connection.Serve(session);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Connection {0} faulted.", clientRemoteAddress);
            }
            finally
            {
                _logger.Info("Client disconnected {0}.", clientRemoteAddress);
                connection.Dispose();
            }
        }
Ejemplo n.º 7
0
 private void ConfigureLogger(ServiceHostConfig config)
 {
     LogManager.Configuration = new XmlLoggingConfiguration(config.NLogConfigFile);
     LogManager.Configuration.Variables["instanceId"] = config.InstanceId.ToString();
 }
Ejemplo n.º 8
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();
            }
        }
Ejemplo n.º 9
0
        private IContainer BuildContainer(ServiceHostConfig config, ClusterConnection clusterConnection, ISession session)
        {
            var containerBuilder       = new ContainerBuilder();
            var serviceConfigsProvider = new ServiceConfigsProvider(config.ServiceConfigs);

            containerBuilder
            .RegisterTypes(_serviceTypes.ToArray())
            .SingleInstance();
            containerBuilder
            .RegisterInstance(serviceConfigsProvider)
            .As <IConfig>();
            containerBuilder
            .RegisterInstance(clusterConnection)
            .As <ICluster>()
            .ExternallyOwned();
            containerBuilder
            .RegisterInstance(session)
            .As <ISession>();

            var containerBuilderWrapper = new ContainerBuilderWrapper(containerBuilder);

            foreach (Type serviceType in _serviceTypes)
            {
                try
                {
                    serviceType
                    .GetMethods()
                    .FirstOrDefault(IsContainerSetupMethod)
                    ?.Invoke(null, new object[] { containerBuilderWrapper, serviceConfigsProvider });
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "Service {0} container setup faulted.", serviceType.FullName);
                }
            }

            return(containerBuilder.Build());

            bool IsContainerSetupMethod(MethodInfo methodInfo)
            {
                if (!(methodInfo.IsStatic && methodInfo.IsPublic))
                {
                    return(false);
                }

                ParameterInfo[] methodParams = methodInfo.GetParameters();
                if (methodParams.Length != 2)
                {
                    return(false);
                }

                if (methodParams[0].ParameterType != typeof(IContainerBuilder))
                {
                    return(false);
                }

                if (methodParams[1].ParameterType != typeof(IConfig))
                {
                    return(false);
                }

                return(true);
            }
        }