Example #1
0
        internal void AddClientOrSession(TcpMapServerClient client)
        {
            var list = client._is_client ? _clients : (client.SessionId != null ? _sessions : _presessions);

            lock (list)
                list.Add(client);
            if (list.Count > 1)
            {
                //TODO:shall test alive for other clients
                //When client switch IP , the socket will not timeout for read
                List <TcpMapServerClient> others = new List <TcpMapServerClient>();
                lock (list)
                {
                    others = new List <TcpMapServerClient>(list);
                }
                foreach (var other in others)
                {
                    if (other == client)
                    {
                        continue;
                    }
                    other.TestAlive();
                }
            }
        }
Example #2
0
        internal TcpMapServerClient FindClient()
        {
TryAgain:
            TcpMapServerClient sclient = null;

            lock (_clients)
            {
                if (_clients.Count == 1)
                {
                    sclient = _clients[0];
                }
                else if (_clients.Count != 0)
                {
                    sclient = _clients[Interlocked.Increment(ref nextclientindex) % _clients.Count];

                    if (DateTime.Now - sclient._lastPingTime > TimeSpan.FromSeconds(90))
                    {
                        //TODO:maybe the client socket has timeout
                        sclient.Stop();
                        //RemoveClientOrSession(sclient);
                        goto TryAgain;
                    }
                }
                else
                {
                    // no client
                }
            }

            return(sclient);
        }
Example #3
0
        internal void AddClientOrSession(TcpMapServerClient client)
        {
            var list = client._is_client ? _clients : (client.SessionId != null ? _sessions : _presessions);

            lock (list)
                list.Add(client);
        }
Example #4
0
        internal void RemoveClientOrSession(TcpMapServerClient client)
        {
            _lastDisconnectTime = DateTime.Now;
            var list = client._is_client ? _clients : (client.SessionId != null ? _sessions : _presessions);

            lock (list)
                list.Remove(client);
        }
Example #5
0
        static public async Task AcceptConnectAndWorkAsync(Socket socket, CommandMessage connmsg)
        {
            System.Diagnostics.Debug.Assert(connmsg.Name == "ClientConnect" || connmsg.Name == "SessionConnect");

            TcpMapServerClient client = new TcpMapServerClient();

            client._socket = socket;
            await client.WorkAsync(connmsg);
        }
        static async Task ProcesSocketAsync(Socket socket)
        {
            while (true)
            {
                var msg = await CommandMessage.ReadFromSocketAsync(socket);

                if (msg == null)
                {
                    //LogMessage("no message ? Connected:" + socket.Connected);
                    return;
                }

                //LogMessage("new msg : " + msg);

                switch (msg.Name)
                {
                case "ClientConnect":
                case "SessionConnect":
                    await TcpMapServerClient.AcceptConnectAndWorkAsync(socket, msg);

                    return;

                case "ConnectorConnect":
                    var    server    = FindServerWorkerByPort(int.Parse(msg.Args[1]));
                    string failedmsg = null;
                    if (server == null)
                    {
                        failedmsg = "NoPort";
                    }
                    else if (server.Server.IsDisabled)
                    {
                        failedmsg = "IsDisabled";
                    }
                    else if (!server.Server.AllowConnector)
                    {
                        failedmsg = "NotAllow";
                    }
                    else if (server.Server.ConnectorLicense == null)
                    {
                        failedmsg = "NotLicense";
                    }
                    else if (server.Server.ConnectorLicense.Key != msg.Args[0])
                    {
                        failedmsg = "LicenseNotMatch";
                    }
                    if (failedmsg != null)
                    {
                        var resmsg = new CommandMessage("ConnectFailed", failedmsg);
                        await socket.SendAsync(resmsg.Pack(), SocketFlags.None);
                    }
                    else
                    {
                        await server.AcceptConnectorAndWorkAsync(socket, msg);
                    }
                    break;

                case "":                        //other direct request..
                default:
                    throw new Exception("Invaild command " + msg.Name);
                }
            }
        }
Example #7
0
        internal async Task AcceptConnectorAndWorkAsync(Socket clientSock, CommandMessage connmsg)
        {
            bool supportEncrypt = _worker.Server.UseEncrypt;

            if (connmsg.Args[4] == "0")
            {
                supportEncrypt = false;
            }

            byte[] clientKeyIV;
            try
            {
                _worker.Server.ConnectorLicense.DescriptSourceKey(Convert.FromBase64String(connmsg.Args[2]), Convert.FromBase64String(connmsg.Args[3]), out clientKeyIV);
            }
            catch (Exception x)
            {
                _worker.OnError(x);
                var failedmsg = new CommandMessage("ConnectFailed", "InvalidSecureKey");
                await clientSock.SendAsync(failedmsg.Pack(), SocketFlags.None);

                return;
            }

            TcpMapServerClient sclient = _worker.FindClient();

            if (sclient == null)
            {
                var failedmsg = new CommandMessage("ConnectFailed", "NoClient");
                await clientSock.SendAsync(failedmsg.Pack(), SocketFlags.None);

                return;
            }

            string mode         = connmsg.Args[5];
            string connArgument = connmsg.Args[6];

            if (mode == "USB")            //use server bandwidth
            {
                var resmsg = new CommandMessage("ConnectOK", "ConnectOK", supportEncrypt ? "1" : "0");
                await clientSock.SendAsync(resmsg.Pack(), SocketFlags.None);

                Stream _sread, _swrite;
                if (supportEncrypt)
                {
                    _worker.Server.ConnectorLicense.OverrideStream(clientSock.CreateStream(), clientKeyIV, out _sread, out _swrite);
                }
                else
                {
                    _sread = _swrite = clientSock.CreateStream();
                }

                using Socket localsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                string ip = _worker.Server.ServerBind;
                if (ip == "0.0.0.0")
                {
                    ip = "127.0.0.1";
                }
                localsock.InitTcp();
                await localsock.ConnectAsync(ip, _worker.Server.ServerPort);

                TcpMapConnectorSession session = new TcpMapConnectorSession(new SimpleSocketStream(localsock));
                await session.DirectWorkAsync(_sread, _swrite);
            }
            else if (mode == "UDP")
            {
                if (_udpcache == null)
                {
                    lock (typeof(TcpMapServerConnector))
                    {
                        if (_udpcache == null)
                        {
                            var opt = new MemoryCacheOptions();
                            Microsoft.Extensions.Options.IOptions <MemoryCacheOptions> iopt = Microsoft.Extensions.Options.Options.Create(opt);
                            _udpcache = new MemoryCache(iopt);
                        }
                    }
                }

                UdpInfoItem natinfo;
                string      key = connArgument + ":" + sclient.SessionId;
                if (!_udpcache.TryGetValue(key, out natinfo) || natinfo.HasExpired())
                {
                    var udpmsg = await sclient.CreateUDPNatAsync(connArgument);

                    string[] pair = udpmsg.Args[1].Split(':');
                    string   addr = pair[0];
                    int      port = int.Parse(pair[1]);
                    natinfo = new UdpInfoItem(addr + ":" + port);
                    _udpcache.Set(key, natinfo);
                }



                var resmsg = new CommandMessage("ConnectOK", "ConnectOK", supportEncrypt ? "1" : "0", natinfo.NatInfo);
                await clientSock.SendAsync(resmsg.Pack(), SocketFlags.None);

                resmsg = await CommandMessage.ReadFromSocketAsync(clientSock);

                if (resmsg == null)
                {
                    return;
                }
                throw new NotImplementedException("work for " + resmsg);
            }
            else if (mode == "RCP")
            {
                var resmsg = new CommandMessage("ConnectOK", "ConnectOK", supportEncrypt ? "1" : "0"
                                                , ((IPEndPoint)sclient._socket.RemoteEndPoint).Address.ToString(), sclient.OptionRouterClientPort.ToString());
                await clientSock.SendAsync(resmsg.Pack(), SocketFlags.None);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Example #8
0
        async Task ProcessSocketAsync(Socket socket)
        {
            //LogMessage("new server conn : " + socket.LocalEndPoint + " , " + socket.RemoteEndPoint);

            string sessionid = Guid.NewGuid().ToString();

            int tryagainIndex = 0;

TryAgain:

            if (!socket.Connected)              //this property is not OK .. actually the client has disconnect
            {
                return;
            }

            tryagainIndex++;

            if (tryagainIndex > 3)              //only try 3 times.
            {
                return;
            }

            TcpMapServerClient sclient = FindClient();

            if (sclient == null)
            {
                if (DateTime.Now - _lastDisconnectTime < TimeSpan.FromSeconds(8))                //TODO:const connect wait sclient timeout
                {
                    await Task.Delay(500);

                    goto TryAgain;
                }
                throw new Exception("no sclient.");
            }


            TcpMapServerClient presession = null;

            try
            {
                lock (_presessions)
                {
                    if (_presessions.Count != 0)
                    {
                        presession = _presessions[0];
                        _presessions.RemoveAt(0);
                    }
                }

                if (presession != null)
                {
                    try
                    {
                        await presession.UpgradeSessionAsync(sessionid);
                    }
                    catch (Exception x)
                    {
                        OnError(x);
                        LogMessage("Error:ServerWorker presession upgrade failed @" + tryagainIndex + " , " + sessionid);
                        goto TryAgain;
                    }
                    lock (_sessions)
                        _sessions.Add(presession);

                    LogMessage("ServerWorker session upgraded @" + tryagainIndex + " , " + sessionid);
                }
                else
                {
                    await sclient.StartSessionAsync(sessionid);

                    LogMessage("ServerWorker session created @" + tryagainIndex + " , " + sessionid);
                }
            }
            catch (Exception x)
            {
                OnError(x);
                await Task.Delay(500);                //TODO:const...

                goto TryAgain;
            }


            try
            {
                TcpMapServerSession session = new TcpMapServerSession(socket.CreateStream(), sessionid);
                sessionMap.TryAdd(sessionid, session);
                LogMessage("Warning: TcpMapServerSession added:" + sessionid);
                try
                {
                    if (presession != null)
                    {
                        presession.AttachToSession(session);
                    }
                    await session.WorkAsync();
                }
                finally
                {
                    sessionMap.TryRemove(sessionid, out _);
                    LogMessage("Warning: TcpMapServerSession removed:" + sessionid);
                }
            }
            catch (Exception x)
            {
                OnError(x);
            }

            await sclient.CloseSessionAsync(sessionid);

            //LogMessage("ServerWorker session closed @" + tryagainIndex);
        }