예제 #1
0
        /// <summary>
        /// Gateway lobby logic is done on a separate thread so that it's not blocking the main thread.
        /// </summary>

        void ThreadDiscover(object obj)
        {
            string request = "M-SEARCH * HTTP/1.1\r\n" +
                             "HOST: 239.255.255.250:1900\r\n" +
                             "ST:upnp:rootdevice\r\n" +
                             "MAN:\"ssdp:discover\"\r\n" +
                             "MX:3\r\n\r\n";

            byte[]           requestBytes   = Encoding.ASCII.GetBytes(request);
            List <IPAddress> ips            = Tools.localAddresses;
            IPEndPoint       searchEndpoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);

            // UPnP discovery should happen on all network interfaces
            for (int i = 0; i < ips.size; ++i)
            {
                IPAddress ip     = ips[i];
                UdpClient sender = null;

                try
                {
#if STANDALONE
                    Tools.Print("Checking UPnP status on " + ip + "...");
#endif
                    sender = new UdpClient(new IPEndPoint(ip, 0));
                    sender.Client.ReceiveTimeout = 3000;

                    // Send several requests due to the unreliable nature of UDP
                    for (int b = 0; b < 3; ++b)
                    {
                        sender.Send(requestBytes, requestBytes.Length, searchEndpoint);
                    }

                    for (; ;)
                    {
                        IPEndPoint sourceAddress = new IPEndPoint(IPAddress.Any, 0);
                        byte[]     data          = sender.Receive(ref sourceAddress);

                        if (ParseResponse(Encoding.ASCII.GetString(data, 0, data.Length)))
                        {
                            sender.Close();
                            sender = null;

                            mGatewayAddress = sourceAddress.Address;
#if STANDALONE
                            Tools.Print("UPnP Gateway: " + mGatewayAddress);
#endif
                            mStatus   = Status.Success;
                            mDiscover = null;
                            return;
                        }
                    }
                }
                catch (System.Exception) { if (sender != null)
                                           {
                                               sender.Close();
                                           }
                }

                mStatus = Status.Failure;
#if STANDALONE
                Tools.Print("UPnP Gateway: Not found");
#endif
                // If we found one, we're done
                if (mStatus == Status.Success)
                {
                    break;
                }
            }
            mDiscover = null;
        }
예제 #2
0
        public bool Start(int port)
        {
            Stop();

            mPort   = port;
            mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
#if !UNITY_WEBPLAYER
            // Web player doesn't seem to support broadcasts
            mSocket.MulticastLoopback = true;
            mMulticast = useMulticasting;

            try
            {
                if (useMulticasting)
                {
                    List <IPAddress> ips = Tools.localAddresses;

                    foreach (IPAddress ip in ips)
                    {
                        MulticastOption opt = new MulticastOption(multicastIP, ip);
                        mSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, opt);
                    }
                }
                else
                {
                    mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
                }
            }
            catch (System.Exception) { }
#endif
            // Port zero means we will be able to send, but not receive
            if (mPort == 0)
            {
                return(true);
            }

            try
            {
                // Use the default network interface if one wasn't explicitly chosen
 #if (UNITY_IPHONE && !UNITY_EDITOR) //|| UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
                IPAddress networkInterface = useMulticasting ? multicastIP : (defaultNetworkInterface ?? IPAddress.Any);
 #else
                IPAddress networkInterface = defaultNetworkInterface ?? IPAddress.Any;
 #endif
                mEndPoint        = new IPEndPoint(networkInterface, 0);
                mDefaultEndPoint = new IPEndPoint(networkInterface, 0);

                // Bind the socket to the specific network interface and start listening for incoming packets
                mSocket.Bind(new IPEndPoint(networkInterface, mPort));
                mSocket.BeginReceiveFrom(mTemp, 0, mTemp.Length, SocketFlags.None, ref mEndPoint, OnReceive, null);
            }
#if UNITY_EDITOR
            catch (System.Exception ex)
            {
                UnityEngine.Debug.LogError("[TNet] Udp.Start: " + ex.Message);
                Stop();
                return(false);
            }
#elif DEBUG
            catch (System.Exception ex) { Tools.Print("Udp.Start: " + ex.Message); Stop(); return(false); }
#else
            catch (System.Exception) { Stop(); return(false); }
#endif
            return(true);
        }
        /// <summary>
        /// Send periodic updates.
        /// </summary>

        void ThreadFunction()
        {
            mInternal = new IPEndPoint(Tools.localAddress, mGameServer.tcpPort);
            mExternal = new IPEndPoint(Tools.externalAddress, mGameServer.tcpPort);

            for (; ;)
            {
                long time = DateTime.UtcNow.Ticks / 10000;

                if (mShutdown)
                {
                    mTcp.Disconnect();
                    mThread = null;
#if STANDALONE
                    Tools.Print("TcpLobbyLink shut down");
#endif
                    break;
                }

#if !STANDALONE
                if (TNManager.isPaused)
                {
                    Thread.Sleep(500);
                    continue;
                }
#endif
                Buffer buffer;

                // Try to establish a connection
                if (mGameServer != null && !mTcp.isConnected && !mTcp.isTryingToConnect && mNextConnect < time)
                {
#if STANDALONE
                    Tools.Print("TcpLobbyLink is connecting to " + mRemoteAddress + "...");
#endif
                    mUpdateNeeded = true;
                    mNextConnect  = time + 15000;
                    mTcp.Connect(mRemoteAddress);
                }

                while (mTcp.ReceivePacket(out buffer))
                {
                    BinaryReader reader   = buffer.BeginReading();
                    Packet       response = (Packet)reader.ReadByte();

                    if (mTcp.stage == TcpProtocol.Stage.Verifying)
                    {
                        if (mTcp.VerifyResponseID(response, reader))
                        {
                            mTimeDifference = reader.ReadInt64() - (System.DateTime.UtcNow.Ticks / 10000);
                            mWasConnected   = true;
#if STANDALONE
                            Tools.Print("TcpLobbyLink connection established");
#endif
                        }
                        else
                        {
#if STANDALONE
                            Tools.Print("TcpLobbyLink Error: Protocol version mismatch");
#endif
                            mThread = null;
                            return;
                        }
                    }
                    else if (response == Packet.RequestPing)
                    {
                    }
#if STANDALONE
                    else if (response == Packet.Error)
                    {
                        Tools.Print("TcpLobbyLink Error: " + reader.ReadString());
                    }
                    else if (response == Packet.Disconnect)
                    {
                        Tools.Print("TcpLobbyLink disconnected");
                    }
                    else
                    {
                        Tools.Print("TcpLobbyLink can't handle this packet: " + response);
                    }
#endif
                    buffer.Recycle();
                }


                // Automatically try to re-establish a connection on disconnect
                if (mWasConnected && !mTcp.isConnected && !mTcp.isTryingToConnect)
                {
                    mNextConnect  = time + 5000;
                    mWasConnected = false;
                }
                else if (mGameServer != null && mTcp.isConnected && (mUpdateNeeded || mNextSend < time))
                {
                    mUpdateNeeded = false;
                    mNextSend     = time + 5000;

                    Buffer       buff   = Buffer.Create();
                    BinaryWriter writer = buff.BeginPacket(Packet.RequestAddServer);
                    writer.Write(GameServer.gameID);
                    writer.Write(mGameServer.name);
                    writer.Write((short)mGameServer.playerCount);
                    Tools.Serialize(writer, mInternal);
                    Tools.Serialize(writer, mExternal);
                    buff.EndPacket();
                    mTcp.SendTcpPacket(buff);
                    buff.Recycle();
                }

                try { Thread.Sleep(10); }
                catch (System.Threading.ThreadInterruptedException) { return; }
            }
        }
예제 #4
0
        /// <summary>
        /// Process an incoming packet.
        /// </summary>

        bool ProcessPacket(Buffer buffer, IPEndPoint ip)
        {
            BinaryReader reader  = buffer.BeginReading();
            Packet       request = (Packet)reader.ReadByte();

            switch (request)
            {
            case Packet.RequestPing:
            {
                BeginSend(Packet.ResponsePing);
                EndSend(ip);
                break;
            }

            case Packet.RequestAddServer:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                ServerList.Entry ent = new ServerList.Entry();
                ent.ReadFrom(reader);

                if (ent.externalAddress.Address.Equals(IPAddress.None))
                {
                    ent.externalAddress = ip;
                }

                mList.Add(ent, mTime);
#if STANDALONE
                Tools.Print(ip + " added a server (" + ent.internalAddress + ", " + ent.externalAddress + ")");
#endif
                return(true);
            }

            case Packet.RequestRemoveServer:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                IPEndPoint internalAddress, externalAddress;
                Tools.Serialize(reader, out internalAddress);
                Tools.Serialize(reader, out externalAddress);

                if (externalAddress.Address.Equals(IPAddress.None))
                {
                    externalAddress = ip;
                }

                RemoveServer(internalAddress, externalAddress);
#if STANDALONE
                Tools.Print(ip + " removed a server (" + internalAddress + ", " + externalAddress + ")");
#endif
                return(true);
            }

            case Packet.RequestServerList:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                mList.WriteTo(BeginSend(Packet.ResponseServerList));
                EndSend(ip);
                return(true);
            }
            }
            return(false);
        }
예제 #5
0
        /// <summary>
        /// Load a previously saved ban list.
        /// </summary>

        public void LoadBanList()
        {
            Tools.Print("Bans: " + (Tools.LoadList(string.IsNullOrEmpty(rootDirectory) ? banFilePath : Path.Combine(rootDirectory, banFilePath), mBan) ? mBan.Count.ToString() : "file not found"));
        }
예제 #6
0
        /// <summary>
        /// Process an incoming packet.
        /// </summary>

        bool ProcessPacket(Buffer buffer, IPEndPoint ip)
        {
            if (mBan.Count != 0 && mBan.Contains(ip.Address.ToString()))
            {
                return(false);
            }

            var reader  = buffer.BeginReading();
            var request = (Packet)reader.ReadByte();

            switch (request)
            {
            case Packet.RequestPing:
            {
                var writer = BeginSend(Packet.ResponsePing);
                writer.Write(mTime);
                writer.Write((ushort)mList.list.size);
                EndSend(ip);
                break;
            }

            case Packet.RequestAddServer:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }

                var ent = new ServerList.Entry();
                ent.ReadFrom(reader);

                if (mBan.Count != 0 && (mBan.Contains(ent.externalAddress.Address.ToString()) || IsBanned(ent.name)))
                {
                    return(false);
                }

                if (ent.externalAddress.Address.Equals(IPAddress.None) ||
                    ent.externalAddress.Address.Equals(IPAddress.IPv6None))
                {
                    ent.externalAddress = ip;
                }

                mList.Add(ent, mTime);
#if STANDALONE
                Tools.Print(ip + " added a server (" + ent.internalAddress + ", " + ent.externalAddress + ")");
#endif
                return(true);
            }

            case Packet.RequestRemoveServer:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                IPEndPoint internalAddress, externalAddress;
                Tools.Serialize(reader, out internalAddress);
                Tools.Serialize(reader, out externalAddress);

                if (externalAddress.Address.Equals(IPAddress.None) ||
                    externalAddress.Address.Equals(IPAddress.IPv6None))
                {
                    externalAddress = ip;
                }

                RemoveServer(internalAddress, externalAddress);
#if STANDALONE
                Tools.Print(ip + " removed a server (" + internalAddress + ", " + externalAddress + ")");
#endif
                return(true);
            }

            case Packet.RequestServerList:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                mList.WriteTo(BeginSend(Packet.ResponseServerList));
                EndSend(ip);
                return(true);
            }
            }
            return(false);
        }