Example #1
0
        public async Task StartHttpService(CancellationTokenSource ctsHttp, int WebManagementPort)
        {
            try
            {
                HttpListener listener = new HttpListener();
                //缓存所有文件
                var dir   = new DirectoryInfo(BASE_FILE_PATH);
                var files = dir.GetFiles("*.*");
                foreach (var file in files)
                {
                    using (var fs = file.OpenRead())
                    {
                        var mms = new MemoryStream();
                        fs.CopyTo(mms);
                        FilesCache.Add(file.Name, mms);
                    }
                }
                Logger.Debug($"{files.Length} files cached.");

                listener.Prefixes.Add($"http://+:{WebManagementPort}/");
                Logger.Debug("Listening HTTP request on port " + WebManagementPort.ToString() + "...");
                await AcceptHttpRequest(listener, ctsHttp);
            }
            catch (HttpListenerException ex)
            {
                Logger.Debug("Please run this program in administrator mode." + ex);
                Server.Logger.Error(ex.ToString(), ex);
            }
            catch (Exception ex)
            {
                Logger.Debug(ex);
                Server.Logger.Error(ex.ToString(), ex);
            }
            Logger.Debug("Http服务结束。");
        }
Example #2
0
        /// <summary>
        /// 重要:连接服务端
        /// </summary>
        /// <returns></returns>
        public async Task ConnectToProvider()
        {
            var appIdIpPortConfig = ClientConfig.Clients;

            ConnnectionManager = ServerConnnectionManager.Create();
            ConnnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected;
            var clientModel = await ConnnectionManager.InitConfig();

            int counter = 0;

            //appid为0时说明没有分配appid,所以需要分配一个
            foreach (var app in appIdIpPortConfig)
            {
                if (app.AppId == 0)
                {
                    app.AppId = clientModel.AppList[counter].AppId;
                    counter++;
                }
            }
            Logger.Debug("****************port list*************");

            foreach (var ap in clientModel.AppList)
            {
                var cApp = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId);
                Logger.Debug(ap.AppId.ToString() + ":  " + ClientConfig.ProviderAddress + ":" + ap.Port.ToString() + "=>" +
                             cApp.IP + ":" + cApp.TargetServicePort);
            }
            Logger.Debug("**************************************");
            Task pollingTask = ConnnectionManager.PollingToProvider();

            try
            {
                await pollingTask;
            }
            catch (Exception ex)
            {
                Logger.Error("Thread:" + Thread.CurrentThread.ManagedThreadId + " crashed.\n", ex);
                throw;
            }

            await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.Token);
        }
Example #3
0
 public async Task StartHttpService(CancellationTokenSource ctsHttp, int WebManagementPort)
 {
     try
     {
         HttpListener listener = new HttpListener();
         listener.Prefixes.Add($"http://+:{WebManagementPort}/");
         //TcpListener listenerConfigService = new TcpListener(IPAddress.Any, WebManagementPort);
         Logger.Debug("Listening HTTP request on port " + WebManagementPort.ToString() + "...");
         await AcceptHttpRequest(listener, ctsHttp);
     }
     catch (HttpListenerException ex)
     {
         Logger.Debug("Please run this program in administrator mode." + ex);
         Server.Logger.Error(ex.ToString(), ex);
     }
     catch (Exception ex)
     {
         Logger.Debug(ex);
         Server.Logger.Error(ex.ToString(), ex);
     }
 }
Example #4
0
        //public static X509Certificate2 TestCert;

        public async Task Start()
        {
            DbOp = new LiteDbOperator(USER_DB_PATH);//加载数据库
            //从配置文件加载服务端配置
            InitSecureKey();
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            CancellationTokenSource ctsConfig   = new CancellationTokenSource();
            CancellationTokenSource ctsHttp     = new CancellationTokenSource();
            CancellationTokenSource ctsConsumer = new CancellationTokenSource();

            //1.反向连接池配置
            ConnectionManager = ClientConnectionManager.GetInstance().SetServerContext(ServerContext);
            //注册客户端发生连接时的事件
            ConnectionManager.AppTcpClientMapConfigConnected += ConnectionManager_AppAdded;
            _ = ConnectionManager.ListenServiceClient(DbOp);
            Logger.Debug("NSmart server started");

            //2.开启http服务
            if (ServerContext.ServerConfig.WebAPIPort > 0)
            {
                var httpServer = new HttpServer(Logger, DbOp, ServerContext);
                _ = httpServer.StartHttpService(ctsHttp, ServerContext.ServerConfig.WebAPIPort);
            }

            //3.开启心跳检测线程
            _ = ProcessHeartbeatsCheck(Global.HeartbeatCheckInterval, ctsConsumer);

            //3.5 加载SSL证书
            Logger.Debug("SSL CA Generating...");
            ServerContext.InitCertificates();
            Logger.Debug("SSL CA Generated.");
            //4.开启配置服务(常开)
            try
            {
                await StartConfigService(ctsConfig);
            }
            catch (Exception ex)
            {
                Logger.Debug(ex.Message);
            }
            finally
            {
                Logger.Debug("all closed");
                ctsConfig.Cancel(); ctsHttp.Cancel(); ctsConsumer.Cancel();
                DbOp.Close();
            }
        }
Example #5
0
        /// <summary>
        /// 重要:连接服务端,一般做为入口方法
        /// 该方法主要操作一些配置和心跳
        /// AlwaysReconnect:始终重试,开启此选项,无论何时,一旦程序在连接不上时都会进行重试,否则只在连接成功后的异常中断时才重试。
        /// </summary>
        /// <returns></returns>
        public async Task Start(bool AlwaysReconnect = false)
        {
            if (AlwaysReconnect)
            {
                IsStarted = true;
            }
            var oneLiveToken = ONE_LIVE_TOKEN_SRC.Token;
            //登录功能
            string arrangedToken = Global.NO_TOKEN_STRING;

            while (!oneLiveToken.IsCancellationRequested)
            {
                CANCEL_TOKEN_SRC      = new CancellationTokenSource();
                TRANSFERING_TOKEN_SRC = new CancellationTokenSource();
                HEARTBEAT_TOKEN_SRC   = new CancellationTokenSource();
                _waiter          = new TaskCompletionSource <object>();
                Router.TimeStamp = Guid.NewGuid();

                var appIdIpPortConfig = ClientConfig.Clients;
                int clientId          = 0;

                //0 获取服务器端口配置
                try
                {
                    await InitServerPorts();
                }
                catch (Exception ex)//出错 重连
                {
                    if (IsStarted == false)
                    {
                        StatusChanged(ClientStatus.LoginError, null); return;
                    }
                    else
                    {
                        Logger.Error("获取服务器端口失败:" + ex.Message, ex);

                        await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token);

                        continue;
                    }
                }

                //0.5 处理登录/重登录/匿名登录逻辑
                try
                {
                    //登录
                    if (CurrentLoginInfo != null)
                    {
                        var loginResult = await Login();

                        arrangedToken = loginResult.Item1;
                        clientId      = loginResult.Item2;
                    }
                    else if (File.Exists(NspClientCachePath))
                    { //登录缓存
                        arrangedToken = File.ReadAllText(NspClientCachePath);
                        //TODO 这个token的合法性无法保证,如果服务端删除了用户,而这里缓存还存在,会导致无法登录
                        //TODO ***** 这是个trick:防止匿名用户被服务端踢了之后无限申请新账号
                        //TODO 待解决 版本号无法显示的问题
                        CurrentLoginInfo = null;
                    }
                    else
                    {
                        //匿名登录,未提供登录信息时,使用空用户名密码自动注册并尝试匿名登录
                        Router.Logger.Debug("未提供登录信息,尝试匿名登录");
                        CurrentLoginInfo = new LoginInfo()
                        {
                            UserName = "", UserPwd = ""
                        };
                        var loginResult = await Login();

                        arrangedToken = loginResult.Item1;
                        clientId      = loginResult.Item2;
                        //保存缓存到磁盘
                        File.WriteAllText(NspClientCachePath, arrangedToken);
                    }
                }
                catch (Exception ex)//出错 重连
                {
                    if (IsStarted == false)
                    {
                        StatusChanged(ClientStatus.LoginError, null); return;
                    }
                    else
                    {
                        Logger.Error("启动失败:" + ex.Message, ex);
                        await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token);

                        continue;
                    }
                }
                //1.获取配置
                ConnectionManager = ServerConnectionManager.Create(clientId);
                ConnectionManager.CurrentToken          = arrangedToken;
                ConnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected;
                ConnectionManager.ServerNoResponse      = DoServerNoResponse; //下钻事件
                ClientModel clientModel = null;                               //
                try
                {
                    //从服务端初始化客户端配置
                    clientModel = await ConnectionManager.InitConfig(this.ClientConfig).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    //TODO 状态码:连接失败
                    Router.Logger.Error("连接失败:" + ex.Message, ex);
                    //throw;
                }

                //HasConnected = true;
                if (clientModel != null)
                {
                    int counter = 0;

                    //2.分配配置:appid为0时说明没有分配appid,所以需要分配一个
                    foreach (var app in appIdIpPortConfig)
                    {
                        if (app.AppId == 0)
                        {
                            app.AppId = clientModel.AppList[counter].AppId;
                            counter++;
                        }
                    }
                    Logger.Debug("****************port list*************");
                    List <string> tunnelstrs = new List <string>();
                    foreach (var ap in clientModel.AppList)
                    {
                        var cApp      = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId);
                        var tunnelStr = ap.AppId.ToString() + ":  " + ClientConfig.ProviderAddress + ":" +
                                        ap.Port.ToString() + "=>" +
                                        cApp.IP + ":" + cApp.TargetServicePort;
                        Logger.Debug(tunnelStr);
                        tunnelstrs.Add(tunnelStr);
                    }
                    Logger.Debug("**************************************");
                    _ = ConnectionManager.PollingToProvider(StatusChanged, tunnelstrs);
                    //3.创建心跳连接
                    _ = ConnectionManager.StartHeartBeats(Global.HeartbeatInterval, HEARTBEAT_TOKEN_SRC.Token, _waiter);

                    IsStarted = true;
                    if (await _waiter.Task.ConfigureAwait(false) is Exception exception)
                    {
                        Router.Logger.Debug($"程序异常终止:{exception.Message}。");
                    }
                    else
                    {
                        Router.Logger.Debug($"未知异常。");
                    }
                }
                else
                {
                    Router.Logger.Debug($"程序启动失败。");
                    //如果程序从未启动过就出错,则终止程序,否则重试。
                    if (IsStarted == false)
                    {
                        StatusChanged(ClientStatus.Stopped, null); return;
                    }
                }

                Router.Logger.Debug($"连接故障,尝试关闭连接并重试");
                if (ConnectionManager != null)
                {
                    ConnectionManager.CloseAllConnections();//关闭所有连接
                }
                //出错重试
                await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token);

                //TODO 返回错误码
                //await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.CurrentToken).ConfigureAwait(false);
                Router.Logger.Debug($"连接关闭,开启重试");
            }
            //正常终止
            Router.Logger.Debug($"停止重试,循环终止。");
        }
Example #6
0
        /// <summary>
        /// 重要:连接服务端,一般做为入口方法
        /// 该方法主要操作一些配置和心跳
        /// </summary>
        /// <returns></returns>
        public async Task Start()
        {
            var oneLiveToken = ONE_LIVE_TOKEN_SRC.Token;

            while (!oneLiveToken.IsCancellationRequested)
            {
                CANCEL_TOKEN_SRC      = new CancellationTokenSource();
                TRANSFERING_TOKEN_SRC = new CancellationTokenSource();
                HEARTBEAT_TOKEN_SRC   = new CancellationTokenSource();
                _waiter = new TaskCompletionSource <object>();
                var appIdIpPortConfig = ClientConfig.Clients;
                int clientId          = 0;

                //0.5 如果有文件,取出缓存中的clientid
                try
                {
                    if (File.Exists(NSMART_CLIENT_CACHE_PATH))
                    {
                        using (var stream = File.OpenRead(NSMART_CLIENT_CACHE_PATH))
                        {
                            byte[] bytes = new byte[2];
                            stream.Read(bytes, 0, bytes.Length);
                            clientId = StringUtil.DoubleBytesToInt(bytes);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.Message, ex);
                }
                //1.获取配置
                ConnectionManager = ServerConnnectionManager.Create(clientId);
                ConnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected;
                ConnectionManager.ServerNoResponse      = DoServerNoResponse; //下钻事件
                ClientModel clientModel = null;                               //
                try
                {
                    //非第一次则算作重连,发送clientid过去
                    clientModel = await ConnectionManager.InitConfig(this.ClientConfig).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    //TODO 状态码:连接失败
                    Router.Logger.Error("连接失败:" + ex.Message, ex);
                    //throw;
                }

                //HasConnected = true;
                if (clientModel != null)
                {
                    int counter = 0;

                    //1.5 写入缓存
                    File.WriteAllBytes(NSMART_CLIENT_CACHE_PATH, StringUtil.IntTo2Bytes(clientModel.ClientId));
                    //2.分配配置:appid为0时说明没有分配appid,所以需要分配一个
                    foreach (var app in appIdIpPortConfig)
                    {
                        if (app.AppId == 0)
                        {
                            app.AppId = clientModel.AppList[counter].AppId;
                            counter++;
                        }
                    }
                    Logger.Debug("****************port list*************");
                    List <string> tunnelstrs = new List <string>();
                    foreach (var ap in clientModel.AppList)
                    {
                        var cApp      = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId);
                        var tunnelStr = ap.AppId.ToString() + ":  " + ClientConfig.ProviderAddress + ":" +
                                        ap.Port.ToString() + "=>" +
                                        cApp.IP + ":" + cApp.TargetServicePort;
                        Logger.Debug(tunnelStr);
                        tunnelstrs.Add(tunnelStr);
                    }
                    Logger.Debug("**************************************");
                    ConnectionManager.PollingToProvider(StatusChanged, tunnelstrs);
                    //3.创建心跳连接
                    ConnectionManager.StartHeartBeats(Global.HeartbeatInterval, HEARTBEAT_TOKEN_SRC.Token);

                    //try
                    //{
                    //    await pollingTask.ConfigureAwait(false);
                    //}
                    //catch (Exception ex)
                    //{
                    //    Logger.Error("Thread:" + Thread.CurrentThread.ManagedThreadId + " crashed.\n", ex);
                    //    throw;
                    //}
                    IsStarted = true;
                    Exception exception = await _waiter.Task.ConfigureAwait(false) as Exception;

                    Router.Logger.Debug($"程序异常终止:{exception.Message}。");
                }
                else
                {
                    Router.Logger.Debug($"程序启动失败。");
                    //如果程序从未启动过就出错,则终止程序,否则重试。
                    if (IsStarted == false)
                    {
                        StatusChanged(ClientStatus.Stopped, null); return;
                    }
                }
                //出错重试
                await Task.Delay(3000, ONE_LIVE_TOKEN_SRC.Token);

                //TODO 返回错误码
                //await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.Token).ConfigureAwait(false);
            }
            //正常终止
        }
Example #7
0
        /// <summary>
        /// 重要:连接服务端,一般做为入口方法
        /// 该方法主要操作一些配置和心跳
        /// AlwaysReconnect:始终重试,开启此选项,无论何时,一旦程序在连接不上时都会进行重试,否则只在连接成功后的断线时才重试。
        /// </summary>
        /// <returns></returns>
        public async Task Start(bool AlwaysReconnect = false)
        {
            if (AlwaysReconnect)
            {
                IsStarted = true;
            }
            var oneLiveToken = ONE_LIVE_TOKEN_SRC.Token;
            //登陆功能
            string arrangedToken = Global.NO_TOKEN_STRING;

            while (!oneLiveToken.IsCancellationRequested)
            {
                CANCEL_TOKEN_SRC      = new CancellationTokenSource();
                TRANSFERING_TOKEN_SRC = new CancellationTokenSource();
                HEARTBEAT_TOKEN_SRC   = new CancellationTokenSource();
                _waiter = new TaskCompletionSource <object>();
                var appIdIpPortConfig = ClientConfig.Clients;
                int clientId          = 0;

                //0.5 如果有文件,取出缓存中的clientid
                try
                {
                    //登陆缓存
                    if (File.Exists(NSMART_CLIENT_CACHE_PATH))
                    {
                        using (var stream = File.OpenRead(NSMART_CLIENT_CACHE_PATH))
                        {
                            byte[] bytes = new byte[2];
                            stream.Read(bytes, 0, bytes.Length);
                            clientId = StringUtil.DoubleBytesToInt(bytes);
                        }
                    }
                    //登陆
                    if (CurrentLoginInfo != null)
                    {
                        NSPDispatcher disp   = new NSPDispatcher();
                        var           result = await disp.LoginFromClient(CurrentLoginInfo.UserName, CurrentLoginInfo.UserPwd);

                        if (result.State == 1)
                        {
                            Router.Logger.Debug("登陆成功");
                            var data = result.Data;
                            arrangedToken = data.Token;
                            Router.Logger.Debug($"服务端版本号:{data.Version},当前适配版本号{Global.NSmartProxyServerName}");
                            clientId = int.Parse(data.Userid);
                        }
                        else
                        {
                            throw new Exception("登陆失败,服务端返回错误如下:" + result.Msg);
                        }
                    }
                    else
                    {
                        Router.Logger.Debug("为提供登陆信息,尝试匿名登陆");
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.Message, ex);
                }
                //1.获取配置
                ConnectionManager = ServerConnectionManager.Create(clientId);
                ConnectionManager.CurrentToken          = arrangedToken;
                ConnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected;
                ConnectionManager.ServerNoResponse      = DoServerNoResponse; //下钻事件
                ClientModel clientModel = null;                               //
                try
                {
                    //非第一次则算作重连,发送clientid过去
                    clientModel = await ConnectionManager.InitConfig(this.ClientConfig).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    //TODO 状态码:连接失败
                    Router.Logger.Error("连接失败:" + ex.Message, ex);
                    //throw;
                }

                //HasConnected = true;
                if (clientModel != null)
                {
                    int counter = 0;

                    //1.5 写入缓存
                    File.WriteAllBytes(NSMART_CLIENT_CACHE_PATH, StringUtil.IntTo2Bytes(clientModel.ClientId));
                    //2.分配配置:appid为0时说明没有分配appid,所以需要分配一个
                    foreach (var app in appIdIpPortConfig)
                    {
                        if (app.AppId == 0)
                        {
                            app.AppId = clientModel.AppList[counter].AppId;
                            counter++;
                        }
                    }
                    Logger.Debug("****************port list*************");
                    List <string> tunnelstrs = new List <string>();
                    foreach (var ap in clientModel.AppList)
                    {
                        var cApp      = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId);
                        var tunnelStr = ap.AppId.ToString() + ":  " + ClientConfig.ProviderAddress + ":" +
                                        ap.Port.ToString() + "=>" +
                                        cApp.IP + ":" + cApp.TargetServicePort;
                        Logger.Debug(tunnelStr);
                        tunnelstrs.Add(tunnelStr);
                    }
                    Logger.Debug("**************************************");
                    ConnectionManager.PollingToProvider(StatusChanged, tunnelstrs);
                    //3.创建心跳连接
                    ConnectionManager.StartHeartBeats(Global.HeartbeatInterval, HEARTBEAT_TOKEN_SRC.Token);

                    IsStarted = true;
                    Exception exception = await _waiter.Task.ConfigureAwait(false) as Exception;

                    if (exception != null)
                    {
                        Router.Logger.Debug($"程序异常终止:{exception.Message}。");
                    }
                    else
                    {
                        Router.Logger.Debug($"未知异常。");
                    }
                }
                else
                {
                    Router.Logger.Debug($"程序启动失败。");
                    //如果程序从未启动过就出错,则终止程序,否则重试。
                    if (IsStarted == false)
                    {
                        StatusChanged(ClientStatus.Stopped, null); return;
                    }
                }

                Router.Logger.Debug($"连接故障,尝试关闭连接并重试");
                if (ConnectionManager != null)
                {
                    ConnectionManager.CloseAllConnections();//关闭所有连接
                }
                //出错重试
                await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token);

                //TODO 返回错误码
                //await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.CurrentToken).ConfigureAwait(false);
                Router.Logger.Debug($"连接关闭,开启重试");
            }
            //正常终止
            Router.Logger.Debug($"停止重试,循环终止。");
        }
Example #8
0
        public async Task Start()
        {
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            CancellationTokenSource ctsConfig   = new CancellationTokenSource();
            CancellationTokenSource ctsHttp     = new CancellationTokenSource();
            CancellationTokenSource ctsConsumer = new CancellationTokenSource();

            //1.反向连接池配置
            ConnectionManager = ClientConnectionManager.GetInstance();
            //注册客户端发生连接时的事件
            ConnectionManager.AppTcpClientMapConfigConnected += ConnectionManager_AppAdded;
            Logger.Debug("NSmart server started");

            //2.开启http服务
            if (WebManagementPort > 0)
            {
                var httpServer = new HttpServer(Logger);
                httpServer.StartHttpService(ctsHttp, WebManagementPort);
            }

            //3.开启心跳检测线程
            ProcessHeartbeatsCheck(Global.HeartbeatCheckInterval, ctsConsumer);

            //4.开启配置服务(常开)
            try
            {
                await StartConfigService(ctsConfig);
            }
            catch (Exception ex)
            {
                Logger.Debug(ex.Message);
            }
            finally
            {
                Logger.Debug("all closed");
                ctsConfig.Cancel(); ctsHttp.Cancel(); ctsConsumer.Cancel();
            }
        }
Example #9
0
        public async Task Start()
        {
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            CancellationTokenSource ctsConfig   = new CancellationTokenSource();
            CancellationTokenSource ctsHttp     = new CancellationTokenSource();
            CancellationTokenSource ctsConsumer = new CancellationTokenSource();

            //1.反向连接池配置
            ConnectionManager = ClientConnectionManager.GetInstance();
            //注册客户端发生连接时的事件
            ConnectionManager.AppTcpClientMapConfigConnected += ConnectionManager_AppAdded;
            Logger.Debug("NSmart server started");

            //2.开启http服务
            if (WebManagementPort > 0)
            {
                StartHttpService(ctsHttp);
            }

            //3.开启配置服务

            try
            {
                await StartConfigService(ctsConfig);
            }
            catch (Exception ex)
            {
                Logger.Debug(ex.Message);
            }
            finally
            {
                Logger.Debug("all closed");
                ctsConfig.Cancel();
                //listenerConsumer.Stop();
            }
            ////4.通过已配置的端口集合开启侦听
            //foreach (var kv in ConnectionManager.PortAppMap)
            //{
            //    ListenConsumeAsync(kv.Key, ctsConsumer.Token);
            //}
        }