Example #1
0
        static void Main()
        {
            NTMinerConsole.SetIsMainUiOk(true);
            NTMinerConsole.DisbleQuickEditMode();
            DevMode.SetDevMode();

            Windows.ConsoleHandler.Register(Exit);

            string thisServerAddress = ServerRoot.HostConfig.ThisServerAddress;

            Console.Title = $"{ServerAppType.WsServer.GetName()}_{thisServerAddress}";
            // 通过WsServer的网络缓解对WebApiServer的外网流量的压力。WsServer调用WebApiServer的时候走内网调用节省外网带宽
            RpcRoot.SetOfficialServerAddress(ServerRoot.HostConfig.RpcServerLocalAddress);
            // 用本节点的地址作为队列名,消费消息时根据路由键区分消息类型
            string queue        = $"{ServerAppType.WsServer.GetName()}.{thisServerAddress}";
            string durableQueue = queue + MqKeyword.DurableQueueEndsWith;

            AbstractMqMessagePath[] mqMessagePaths = new AbstractMqMessagePath[] {
                new ReadOnlyUserMqMessagePath(durableQueue),
                new MinerSignMqMessagePath(durableQueue),
                new WsServerNodeMqMessagePath(queue),
                new OperationMqMessagePath(queue),
                new MinerClientMqMessagePath(queue, thisServerAddress)
            };
            if (!MqRedis.Create(ServerAppType.WsServer, mqMessagePaths, out IMqRedis mqRedis))
            {
                NTMinerConsole.UserError("启动失败,无法继续,因为服务器上下文创建失败");
                return;
            }
            MinerClientMqSender    = new MinerClientMqSender(mqRedis);
            SpeedDataRedis         = new SpeedDataRedis(mqRedis);
            WsServerNodeRedis      = new WsServerNodeRedis(mqRedis);
            OperationMqSender      = new OperationMqSender(mqRedis);
            UserMqSender           = new UserMqSender(mqRedis);
            _wsServerNodeMqSender  = new WsServerNodeMqSender(mqRedis);
            WsServerNodeAddressSet = new WsServerNodeAddressSet(WsServerNodeRedis, _wsServerNodeMqSender);
            var minerRedis = new ReadOnlyMinerRedis(mqRedis);
            var userRedis  = new ReadOnlyUserRedis(mqRedis);

            VirtualRoot.StartTimer();
            RpcRoot.SetRpcUser(new RpcUser(ServerRoot.HostConfig.RpcLoginName, HashUtil.Sha1(ServerRoot.HostConfig.RpcPassword)));
            RpcRoot.SetIsOuterNet(false);
            // 构造函数中异步访问redis初始化用户列表,因为是异步的所以提前构造
            UserSet               = new ReadOnlyUserSet(userRedis);
            MinerSignSet          = new MinerSignSet(minerRedis);
            _wsServer             = new SharpWsServerAdapter(ServerRoot.HostConfig);
            MinerClientSessionSet = new MinerClientSessionSet(_wsServer.MinerClientWsSessions);
            MinerStudioSessionSet = new MinerStudioSessionSet(_wsServer.MinerStudioWsSessions);
            _started              = _wsServer.Start();
            if (!_started)
            {
                NTMinerConsole.UserError("启动失败,无法继续,因为_wsServer启动失败");
                return;
            }
            VirtualRoot.RaiseEvent(new WebSocketServerStatedEvent());

            Console.ReadKey(true);
            Exit();
        }
Example #2
0
        public static void AddMinerClientSession(WsUserName wsUserName, UserData userData, IPEndPoint remoteEndPoint, IWsSessionAdapter session)
        {
            IMinerClientSession minerSession = MinerClientSession.Create(userData, wsUserName, remoteEndPoint, session.SessionId, WsServer.MinerClientWsSessions);

            MinerClientSessionSet.Add(minerSession);
            // 通知WebApiServer节点该矿机Ws连线了
            MinerClientMqSender.SendMinerClientWsOpened(minerSession.LoginName, minerSession.ClientId);
            bool isMinerSignChanged;

            if (!MinerSignSet.TryGetByClientId(wsUserName.ClientId, out MinerSign minerSign))
            {
                // 此时该矿机是第一次在服务端出现
                minerSign = new MinerSign {
                    Id            = LiteDB.ObjectId.NewObjectId().ToString(),
                    ClientId      = wsUserName.ClientId,
                    LoginName     = userData.LoginName,
                    OuterUserId   = wsUserName.UserId,
                    AESPassword   = string.Empty,
                    AESPasswordOn = Timestamp.UnixBaseTime
                };
                isMinerSignChanged = true;
            }
            else
            {
                isMinerSignChanged = minerSign.OuterUserId != wsUserName.UserId || minerSign.LoginName != userData.LoginName;
                if (isMinerSignChanged)
                {
                    minerSign.OuterUserId = wsUserName.UserId;
                    minerSign.LoginName   = userData.LoginName;
                }
            }
            // 通常执行不到,因为用户注册的时候已经生成了RSA公私钥对了
            if (string.IsNullOrEmpty(userData.PublicKey) || string.IsNullOrEmpty(userData.PrivateKey))
            {
                var key = Cryptography.RSAUtil.GetRASKey();
                userData.PublicKey  = key.PublicKey;
                userData.PrivateKey = key.PrivateKey;
                UserMqSender.SendUpdateUserRSAKey(userData.LoginName, key);
            }
            DateTime now = DateTime.Now;

            if (string.IsNullOrEmpty(minerSign.AESPassword) || minerSign.AESPasswordOn.AddDays(1) < now)
            {
                isMinerSignChanged      = true;
                minerSign.AESPassword   = Cryptography.AESUtil.GetRandomPassword();
                minerSign.AESPasswordOn = now;
            }
            session.SendAsync(new WsMessage(Guid.NewGuid(), WsMessage.UpdateAESPassword)
            {
                Data = new AESPassword {
                    PublicKey = userData.PublicKey,
                    Password  = Cryptography.RSAUtil.EncryptString(minerSign.AESPassword, userData.PrivateKey)
                }
            }.SignToJson(minerSign.AESPassword));
            if (isMinerSignChanged)
            {
                MinerClientMqSender.SendChangeMinerSign(minerSign);
            }
        }
Example #3
0
        static void Main()
        {
            VirtualRoot.SetOut(new ConsoleOut());
            NTMinerConsole.MainUiOk();
            NTMinerConsole.DisbleQuickEditMode();
            DevMode.SetDevMode();

            Windows.ConsoleHandler.Register(Exit);

            string thisServerAddress = ServerRoot.HostConfig.ThisServerAddress;

            Console.Title = $"{nameof(ServerAppType.WsServer)}_{thisServerAddress}";
            // 用本节点的地址作为队列名,消费消息时根据路由键区分消息类型
            string queue        = $"{nameof(ServerAppType.WsServer)}.{thisServerAddress}";
            string durableQueue = queue + MqKeyword.DurableQueueEndsWith;

            AbstractMqMessagePath[] mqMessagePaths = new AbstractMqMessagePath[] {
                new ReadOnlyUserMqMessagePath(durableQueue),
                new MinerSignMqMessagePath(queue),
                new WsServerNodeMqMessagePath(queue),
                new OperationMqMessagePath(queue),
                new MinerClientMqMessagePath(queue, thisServerAddress),
                new ClientTestIdMqMessagePath(queue)
            };
            if (!MqRedis.Create(ServerAppType.WsServer, mqMessagePaths, out IMqRedis mqRedis))
            {
                NTMinerConsole.UserError("启动失败,无法继续,因为服务器上下文创建失败");
                return;
            }
            MinerClientMqSender    = new MinerClientMqSender(mqRedis);
            SpeedDataRedis         = new SpeedDataRedis(mqRedis);
            WsServerNodeRedis      = new WsServerNodeRedis(mqRedis);
            OperationMqSender      = new OperationMqSender(mqRedis);
            UserMqSender           = new UserMqSender(mqRedis);
            _wsServerNodeMqSender  = new WsServerNodeMqSender(mqRedis);
            WsServerNodeAddressSet = new WsServerNodeAddressSet(WsServerNodeRedis, _wsServerNodeMqSender);
            var minerRedis = new MinerDataRedis(mqRedis);
            var userRedis  = new ReadOnlyUserDataRedis(mqRedis);

            VirtualRoot.StartTimer();
            // 构造函数中异步访问redis初始化用户列表,因为是异步的所以提前构造
            UserSet               = new ReadOnlyUserSet(userRedis);
            MinerSignSet          = new MinerSignSet(minerRedis);
            _wsServer             = new SharpWsServerAdapter(ServerRoot.HostConfig);
            MinerClientSessionSet = new MinerClientSessionSet(_wsServer.MinerClientWsSessions);
            MinerStudioSessionSet = new MinerStudioSessionSet(_wsServer.MinerStudioWsSessions);
            _started              = _wsServer.Start();
            if (!_started)
            {
                NTMinerConsole.UserError("启动失败,无法继续,因为_wsServer启动失败");
                return;
            }
            VirtualRoot.RaiseEvent(new WebSocketServerStatedEvent());

            Console.ReadKey(true);
            Exit();
        }
Example #4
0
        static void Main()
        {
            NTMinerConsole.DisbleQuickEditMode();
            HomePath.SetHomeDirFullName(AppDomain.CurrentDomain.BaseDirectory);
            try {
                bool mutexCreated;
                try {
                    // 锁名称上带上本节点的端口号,从而允许一个服务器上运行多个WebApiServer节点,这在软升级服务端程序时有用。
                    // 升级WebApiServer程序的时候步骤是:
                    // 1,在另一个端口启动新版本的程序;
                    // 2,让Widnows将来自旧端口的所有tcp请求转发到新端口;
                    // 3,退出旧版本的程序并更新到新版本;
                    // 4,删除第2步添加的Windows的端口转发;
                    // 5,退出第1步运行的节点;
                    // TODO:实现软升级策略
                    _sMutexApp = new Mutex(true, $"NTMinerServicesMutex{ServerRoot.HostConfig.GetServerPort().ToString()}", out mutexCreated);
                }
                catch {
                    mutexCreated = false;
                }
                if (mutexCreated)
                {
                    try {
                        // 用本节点的地址作为队列名,消费消息时根据路由键区分消息类型
                        string queue        = $"{ServerAppType.WebApiServer.GetName()}.{ServerRoot.HostConfig.ThisServerAddress}";
                        string durableQueue = queue + MqKeyword.DurableQueueEndsWith;
                        AbstractMqMessagePath[] mqMessagePaths = new AbstractMqMessagePath[] {
                            new UserMqMessagePath(durableQueue),
                            new MinerClientMqMessagePath(queue)
                        };
                        _serverContext = ServerContext.Create(mqClientTypeName: ServerAppType.WebApiServer.GetName(), mqMessagePaths);
                        if (_serverContext == null)
                        {
                            Write.UserError("启动失败,无法继续,因为服务器上下文创建失败");
                            return;
                        }
                        Console.Title = $"{ServerAppType.WebApiServer.GetName()}_{ServerRoot.HostConfig.ThisServerAddress}";
                        _ossClient    = new OssClient(ServerRoot.HostConfig.OssEndpoint, ServerRoot.HostConfig.OssAccessKeyId, ServerRoot.HostConfig.OssAccessKeySecret);
                        var minerClientMqSender  = new MinerClientMqSender(_serverContext.Channel);
                        var userMqSender         = new UserMqSender(_serverContext.Channel);
                        var wsServerNodeMqSender = new WsServerNodeMqSender(_serverContext.Channel);

                        var minerRedis     = new MinerRedis(_serverContext.RedisConn);
                        var speedDataRedis = new SpeedDataRedis(_serverContext.RedisConn);
                        var userRedis      = new UserRedis(_serverContext.RedisConn);
                        var captchaRedis   = new CaptchaRedis(_serverContext.RedisConn);

                        WsServerNodeSet   = new WsServerNodeSet(wsServerNodeMqSender);
                        UserSet           = new UserSet(userRedis, userMqSender);
                        UserAppSettingSet = new UserAppSettingSet();
                        CaptchaSet        = new CaptchaSet(captchaRedis);
                        CalcConfigSet     = new CalcConfigSet();
                        NTMinerWalletSet  = new NTMinerWalletSet();
                        ClientDataSet clientDataSet = new ClientDataSet(minerRedis, speedDataRedis, minerClientMqSender);
                        ClientDataSet          = clientDataSet;
                        CoinSnapshotSet        = new CoinSnapshotSet(clientDataSet);
                        MineWorkSet            = new UserMineWorkSet();
                        MinerGroupSet          = new UserMinerGroupSet();
                        NTMinerFileSet         = new NTMinerFileSet();
                        OverClockDataSet       = new OverClockDataSet();
                        KernelOutputKeywordSet = new KernelOutputKeywordSet(SpecialPath.LocalDbFileFullName, isServer: true);
                        ServerMessageSet       = new ServerMessageSet(SpecialPath.LocalDbFileFullName, isServer: true);
                        UpdateServerMessageTimestamp();
                        if (VirtualRoot.LocalAppSettingSet.TryGetAppSetting(nameof(KernelOutputKeywordTimestamp), out IAppSetting appSetting) && appSetting.Value is DateTime value)
                        {
                            KernelOutputKeywordTimestamp = value;
                        }
                        else
                        {
                            KernelOutputKeywordTimestamp = Timestamp.UnixBaseTime;
                        }
                    }
                    catch (Exception e) {
                        Write.UserError(e.Message);
                        Write.UserError(e.StackTrace);
                        Write.UserInfo("按任意键退出");
                        Console.ReadKey();
                        return;
                    }
                    VirtualRoot.StartTimer();
                    NTMinerRegistry.SetAutoBoot("NTMinerServices", true);
                    Type thisType = typeof(WebApiRoot);
                    Run();
                }
            }
            catch (Exception e) {
                Logger.ErrorDebugLine(e);
            }
        }
Example #5
0
        static void Main()
        {
            VirtualRoot.SetOut(new ConsoleOut());
            NTMinerConsole.MainUiOk();
            NTMinerConsole.DisbleQuickEditMode();
            DevMode.SetDevMode();

            Windows.ConsoleHandler.Register(Exit);

            try {
                bool mutexCreated;
                try {
                    // 锁名称上带上本节点的端口号,从而允许一个服务器上运行多个WebApiServer节点,这在软升级服务端程序时有用。
                    // 升级WebApiServer程序的时候步骤是:
                    // 1,在另一个端口启动新版本的程序;
                    // 2,让Widnows将来自旧端口的所有tcp请求转发到新端口;
                    // 3,退出旧版本的程序并更新到新版本;
                    // 4,删除第2步添加的Windows的端口转发;
                    // 5,退出第1步运行的节点;
                    // TODO:实现软升级策略
                    _sMutexApp = new Mutex(true, $"NTMinerServicesMutex{ServerRoot.HostConfig.GetServerPort().ToString()}", out mutexCreated);
                }
                catch {
                    mutexCreated = false;
                }
                if (mutexCreated)
                {
                    try {
                        // 用本节点的地址作为队列名,消费消息时根据路由键区分消息类型
                        string queue         = $"{nameof(ServerAppType.WebApiServer)}.{ServerRoot.HostConfig.ThisServerAddress}";
                        string durableQueue  = queue + MqKeyword.DurableQueueEndsWith;
                        string wsBreathQueue = queue + MqKeyword.WsBreathQueueEndsWith;
                        AbstractMqMessagePath[] mqMessagePaths = new AbstractMqMessagePath[] {
                            new UserMqMessagePath(durableQueue),
                            new CalcConfigMqMessagePath(queue),
                            new MinerClientMqMessagePath(queue),
                            new WsBreathMqMessagePath(wsBreathQueue),
                            new OperationMqMessagePath(queue),
                            new MqCountMqMessagePath(queue),
                            new ClientTestIdMqMessagePath(queue)
                        };
                        if (!MqRedis.Create(ServerAppType.WebApiServer, mqMessagePaths, out IMqRedis mqRedis))
                        {
                            NTMinerConsole.UserError("启动失败,无法继续,因为服务器上下文创建失败");
                            return;
                        }
                        Console.Title = $"{nameof(ServerAppType.WebApiServer)}_{ServerRoot.HostConfig.ThisServerAddress}";
                        // 阿里云OSS坑爹比七牛Kodo贵一半
                        CloudFileUrlGenerater = new AliCloudOSSFileUrlGenerater();
                        IRedis redis = mqRedis;
                        IMq    mq    = mqRedis;
                        AdminMqSender         = new AdminMqSender(mq);
                        ClientTestIdDataRedis = new ClientTestIdDataRedis(redis);
                        var minerClientMqSender = new MinerClientMqSender(mq);
                        var userMqSender        = new UserMqSender(mq);
                        var calcConfigMqSender  = new CalcConfigMqSender(mq);

                        var minerRedis          = new MinerDataRedis(redis);
                        var clientActiveOnRedis = new ClientActiveOnRedis(redis);
                        var speedDataRedis      = new SpeedDataRedis(redis);
                        var userRedis           = new UserDataRedis(redis);
                        var captchaRedis        = new CaptchaDataRedis(redis);
                        var calcConfigRedis     = new CalcConfigDataRedis(redis);

                        MqCountSet             = new MqCountSet();
                        WsServerNodeRedis      = new WsServerNodeRedis(redis);
                        WsServerNodeAddressSet = new WsServerNodeAddressSet(WsServerNodeRedis);
                        UserSet           = new UserSet(userRedis, userMqSender);
                        UserAppSettingSet = new UserAppSettingSet();
                        CaptchaSet        = new CaptchaSet(captchaRedis);
                        CalcConfigSet     = new CalcConfigSet(calcConfigRedis, calcConfigMqSender);
                        NTMinerWalletSet  = new NTMinerWalletSet();
                        GpuNameSet        = new GpuNameSet();
                        ClientDataSet clientDataSet = new ClientDataSet(minerRedis, clientActiveOnRedis, speedDataRedis, minerClientMqSender);
                        ClientDataSet = clientDataSet;
                        var operationMqSender = new OperationMqSender(mq);
                        MineWorkSet            = new UserMineWorkSet(operationMqSender);
                        MinerGroupSet          = new UserMinerGroupSet();
                        NTMinerFileSet         = new NTMinerFileSet();
                        OverClockDataSet       = new OverClockDataSet();
                        KernelOutputKeywordSet = new KernelOutputKeywordSet(SpecialPath.LocalDbFileFullName);
                        ServerMessageSet       = new ServerMessageSet(SpecialPath.LocalDbFileFullName);
                        if (VirtualRoot.LocalAppSettingSet.TryGetAppSetting(nameof(KernelOutputKeywordTimestamp), out IAppSetting appSetting) && appSetting.Value is DateTime value)
                        {
                            KernelOutputKeywordTimestamp = value;
                        }
                        else
                        {
                            KernelOutputKeywordTimestamp = Timestamp.UnixBaseTime;
                        }
                    }
                    catch (Exception e) {
                        NTMinerConsole.UserError(e.Message);
                        NTMinerConsole.UserError(e.StackTrace);
                        NTMinerConsole.UserInfo("按任意键退出");
                        Console.ReadKey();
                        return;
                    }
                    VirtualRoot.StartTimer();
                    NTMinerRegistry.SetAutoBoot("NTMinerServices", true);
                    Type thisType = typeof(AppRoot);
                    Run();
                }
            }
            catch (Exception e) {
                Logger.ErrorDebugLine(e);
            }
        }