//通过客户端的id请求,分配好服务端端口和appid交给客户端
        //arrange ConfigId from top 4 bytes which received from client.
        //response:
        //   2          1       1       1           1        ...N
        //  clientid    appid   port    appid2      port2
        //request:
        //   2          2
        //  clientid    count
        //  methodType  value = 0
        public byte[] ArrangeConfigIds(byte[] appRequestBytes, byte[] consumerPortBytes, int highPriorityClientId)
        {
            // byte[] arrangedBytes = new byte[256];
            ClientModel clientModel = new ClientModel();
            int         clientId;

            //apprequestbytes里本身有clientId,但是如果传了highPriorityClientId,那就用这个clientId
            if (highPriorityClientId != 0)
            {
                clientId = highPriorityClientId;
            }
            else
            {
                clientId = StringUtil.DoubleBytesToInt(appRequestBytes[0], appRequestBytes[1]);
            }


            //2.分配clientid //TODO 这一段可能不会再用到了
            int appCount = (int)appRequestBytes[2];

            if (clientId == 0)
            {
                lock (_lockObject)
                {
                    byte[] tempClientIdBytes = new byte[2];
                    //分配clientid
                    for (int i = 0; i < 10000; i++)
                    {
                        _rand.NextBytes(tempClientIdBytes);
                        int tempClientId = (tempClientIdBytes[0] << 8) + tempClientIdBytes[1];
                        if (!ServerContext.Clients.ContainsKey(tempClientId))
                        {
                            clientModel.ClientId = tempClientId;
                            clientId             = tempClientId;

                            break;
                        }
                    }
                }
            }
            else
            {
                clientModel.ClientId = clientId;
            }

            //注册客户端
            ServerContext.Clients.RegisterNewClient(clientModel.ClientId);
            lock (_lockObject2)
            {
                //注册app
                clientModel.AppList = new List <App>(appCount);
                for (int i = 0; i < appCount; i++)
                {
                    int startPort = StringUtil.DoubleBytesToInt(consumerPortBytes[2 * i], consumerPortBytes[2 * i + 1]);

                    int arrangedAppid = ServerContext.Clients[clientId].RegisterNewApp();
                    //查找port的起始端口如果未指定,则设置为20000
                    //TODO 如果端口是指定的并且是绑定的,则直接使用该端口即可
                    if (startPort == 0)
                    {
                        startPort = 20000;
                    }
                    int    port = NetworkUtil.FindOneAvailableTCPPort(startPort);
                    NSPApp app  = ServerContext.Clients[clientId].AppMap[arrangedAppid];
                    app.ClientId                   = clientId;
                    app.AppId                      = arrangedAppid;
                    app.ConsumePort                = port;
                    app.Tunnels                    = new List <TcpTunnel>();
                    app.ReverseClients             = new List <TcpClient>();
                    ServerContext.PortAppMap[port] = app;

                    clientModel.AppList.Add(new App
                    {
                        AppId = arrangedAppid,
                        Port  = port
                    });

                    Logger.Info(port);
                    //配置时触发
                    AppTcpClientMapConfigConnected(this, new AppChangedEventArgs()
                    {
                        App = app
                    });
                }
                Logger.Debug(" <=端口已分配。");
            }
            return(clientModel.ToBytes());
        }
Exemple #2
0
        /// <summary>
        /// 分配端口方法
        /// arrange ConfigId from top 4 bytes which received from client.
        /// response:
        ///   2          1       1       1           1        ...N
        ///  clientid    appid   port    appid2      port2
        /// request:
        ///   2          2
        ///  clientid    count
        ///  methodType  value = 0
        /// </summary>
        public byte[] ArrangeConfigIds(byte[] appRequestBytes, byte[] consumerPortBytes, int highPriorityClientId)
        {
            // byte[] arrangedBytes = new byte[256];
            ClientModel clientModel = new ClientModel();
            int         clientId;

            //apprequestbytes里本身有clientId,但是如果传了highPriorityClientId,那就用这个clientId
            if (highPriorityClientId != 0)
            {
                clientId = highPriorityClientId;
            }
            else
            {
                clientId = StringUtil.DoubleBytesToInt(appRequestBytes[0], appRequestBytes[1]);
            }

            //2.分配clientid //TODO 这一段可能不会再用到了
            int appCount = (int)appRequestBytes[2];

            if (clientId == 0)
            {
                lock (_lockObject)
                {
                    byte[] tempClientIdBytes = new byte[2];
                    //分配clientid
                    for (int i = 0; i < 10000; i++)
                    {
                        _rand.NextBytes(tempClientIdBytes);
                        int tempClientId = StringUtil.DoubleBytesToInt(tempClientIdBytes);
                        if (!ServerContext.Clients.ContainsKey(tempClientId))
                        {
                            clientModel.ClientId = tempClientId;
                            clientId             = tempClientId;

                            break;
                        }
                    }
                }
            }
            else
            {
                clientModel.ClientId = clientId;
            }

            //注册客户端
            ServerContext.Clients.RegisterNewClient(clientModel.ClientId);
            //port proto option(iscompress)  host         description
            //2    1     1                   1024         96
            int oneEndpointLength = 2 + 1 + 1 + 1024 + 96;

            lock (_lockObject2)
            {
                //注册app
                clientModel.AppList = new List <App>(appCount);
                for (int i = 0; i < appCount; i++)
                {
                    int      offset        = oneEndpointLength * i;
                    int      startPort     = StringUtil.DoubleBytesToInt(consumerPortBytes[offset], consumerPortBytes[offset + 1]);
                    int      arrangedAppid = ServerContext.Clients[clientId].RegisterNewApp();
                    Protocol protocol      = (Protocol)consumerPortBytes[offset + 2];
                    bool     isCompress    = consumerPortBytes[offset + 3] == 1 ? true : false;
                    string   host          = Encoding.ASCII.GetString(consumerPortBytes, offset + 4, 1024).TrimEnd('\0');
                    string   description   = Encoding.UTF8.GetString(consumerPortBytes, offset + 4 + 1024, 96).TrimEnd('\0');
                    //查找port的起始端口如果未指定,则设置为20000
                    if (startPort == 0)
                    {
                        startPort = Global.StartArrangedPort;
                    }
                    int port = 0;
                    //如果端口是指定的并且是绑定的,不加任何检测
                    bool hasListened = false;
                    if (IsBoundedByUser(clientId, startPort))
                    {
                        port = startPort;
                    }
                    else
                    {
                        if (protocol == Protocol.TCP)
                        {
                            int relocatedPort = NetworkUtil.FindOneAvailableTCPPort(startPort);
                            port = relocatedPort; //TODO 2 如果是共享端口协议,如果找不到端口则不进行侦听
                        }
                        else if (protocol == Protocol.HTTP)
                        {
                            int relocatedPort = NetworkUtil.FindOneAvailableTCPPort(startPort);
                            //兼容http侦听端口公用
                            if (port != relocatedPort)
                            {
                                //http协议下如果portappmap已经有值,说明已经发起过侦听,接下来不必再侦听
                                if (ServerContext.PortAppMap.ContainsKey(startPort))
                                {
                                    port        = startPort;
                                    hasListened = true;
                                }
                                else
                                {
                                    port = relocatedPort;
                                }
                            }
                        }
                        else if (protocol == Protocol.UDP)
                        {
                            int relocatedPort = NetworkUtil.FindOneAvailableUDPPort(startPort);
                            port = relocatedPort;
                        }
                    }
                    NSPApp app = ServerContext.Clients[clientId].AppMap[arrangedAppid];
                    app.ClientId       = clientId;
                    app.AppId          = arrangedAppid;
                    app.ConsumePort    = port;
                    app.AppProtocol    = protocol;
                    app.Host           = host;
                    app.Description    = description;
                    app.Tunnels        = new List <TcpTunnel>();
                    app.ReverseClients = new List <TcpClient>();
                    app.IsCompress     = isCompress;

                    if (protocol == Protocol.UDP)
                    {
                        if (!ServerContext.UDPPortAppMap.ContainsKey(port))
                        {
                            ServerContext.UDPPortAppMap[port] = new NSPAppGroup();
                        }
                        ServerContext.UDPPortAppMap[port][host] = app;
                    }
                    else
                    {
                        //TODO 设置app的host和protocoltype(TCP Only)
                        if (!ServerContext.PortAppMap.ContainsKey(port))
                        {
                            ServerContext.PortAppMap[port] = new NSPAppGroup();
                        }
                        ServerContext.PortAppMap[port][host] = app;
                    }

                    clientModel.AppList.Add(new App
                    {
                        AppId = arrangedAppid,
                        Port  = port
                    });

                    Logger.Info(port);
                    //配置时触发
                    if (!hasListened)
                    {
                        AppTcpClientMapConfigApplied(this, new AppChangedEventArgs()
                        {
                            App = app
                        });                                                                         //触发listener侦听
                    }
                }
                Logger.Debug(" <=端口已分配。");
            }
            return(clientModel.ToBytes());
        }