示例#1
0
 public async Task Process(SteamHostGameRequest args)
 {
     try
     {
         steam.PrepareToHostP2PGame(args);
     }
     catch (Exception ex)
     {
         Trace.TraceError("Error processing steamhostgamerequest: {0}", ex);
     }
 }
示例#2
0
        /// <summary>
        ///     chobby request p2p game to be created
        /// </summary>
        public void PrepareToHostP2PGame(SteamHostGameRequest request)
        {
            // clear old listeners
            DisposeExistingProxies();

            gameHostUdpPort = SteamP2PPortProxy.GetFreeUdpPort();

            // send channel numbers to players
            foreach (var player in request.Players)
            {
                ulong playerSteamID;
                ulong.TryParse(player.SteamID, out playerSteamID);

                p2pProxies[playerSteamID] = null;
                SendSteamMessage(playerSteamID, new SteamP2PRequestPrepareProxy()
                {
                    Channel = steamChannelCounter++
                });
            }

            // wait for response
            var startWait = DateTime.UtcNow;

            Task.Factory.StartNew(() =>
            {
                // wait 30s for all clients to respond
                while (p2pProxies.Any(x => x.Value == null))
                {
                    if (DateTime.UtcNow.Subtract(startWait).TotalSeconds > 30)
                    {
                        Listener.SendCommand(new SteamHostGameFailed()
                        {
                            CausedBySteamID = p2pProxies.Where(x => x.Value == null).Select(x => x.Key).FirstOrDefault().ToString(),
                            Reason          = "Client didn't send his confirmation"
                        });
                    }

                    Task.Delay(100);
                }

                // send command to start spring to all clients
                foreach (var cli in p2pProxies)
                {
                    var player = request.Players.First(x => x.SteamID == cli.Key.ToString());

                    // tell clients to connect to server's external port/IP
                    SendSteamMessage(cli.Key,
                                     new SteamP2PDirectConnectRequest()
                    {
                        Name           = player.Name,
                        Engine         = request.Engine,
                        Game           = request.Game,
                        Map            = request.Map,
                        ScriptPassword = player.ScriptPassword
                    });
                }

                // send command to start spring to self
                Listener.SendCommand(new SteamHostGameSuccess()
                {
                    HostPort = gameHostUdpPort
                });
            });
        }
示例#3
0
        /// <summary>
        ///     chobby request p2p game to be created
        /// </summary>
        public void PrepareToHostP2PGame(SteamHostGameRequest request)
        {
            var socket = new UdpClient(0);

            udpClient = socket;

            // send requests to clients to resolve their external IPs
            clientPorts.Clear();
            foreach (var player in request.Players)
            {
                ulong playerSteamID;
                ulong.TryParse(player.SteamID, out playerSteamID);

                clientPorts[playerSteamID] = null;
                SendSteamMessage(playerSteamID, new SteamP2PRequestClientPort());
            }

            // resolve my own address
            var hostResolve = StunUDP(udpClient);

            if ((hostResolve == null) || (hostResolve.NetType == STUN_NetType.UdpBlocked))
            {
                Listener.SendCommand(new SteamHostGameFailed()
                {
                    CausedBySteamID = GetSteamID().ToString(), Reason = "Host cannot open UDP port"
                });
                return;
            }

            var startWait = DateTime.UtcNow;

            Task.Factory.StartNew(() =>
            {
                // wait 30s for all clients to respond
                while (clientPorts.Any(x => x.Value == null))
                {
                    if (DateTime.UtcNow.Subtract(startWait).TotalSeconds > 30)
                    {
                        Listener.SendCommand(new SteamHostGameFailed()
                        {
                            CausedBySteamID = clientPorts.Where(x => x.Value == null).Select(x => x.Key).FirstOrDefault().ToString(),
                            Reason          = "Client didn't send his UDP port"
                        });
                    }

                    Task.Delay(100);
                }

                // any client without valid ip/port ?
                var failedClient = clientPorts.Where(x => (x.Value.IP == null) || (x.Value.Port == 0)).Select(x => x.Key).FirstOrDefault();
                if (failedClient != 0)
                {
                    Listener.SendCommand(new SteamHostGameFailed()
                    {
                        CausedBySteamID = failedClient.ToString(),
                        Reason          = "Client could not resolve his NAT/firewall"
                    });
                }

                var hostExtPort   = hostResolve.PublicEndPoint.Port;
                var hostExtIP     = hostResolve.PublicEndPoint.Address.ToString();
                var hostLocalPort = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port;

                var buffer = new byte[] { 1, 2, 3, 4, 5, 6 };
                foreach (var cli in clientPorts)
                {
                    var player = request.Players.First(x => x.SteamID == cli.Key.ToString());

                    // send some packets to each client's external IP/port to punch NAT
                    udpClient.Send(buffer, buffer.Length, cli.Value.IP, cli.Value.Port);
                    udpClient.Send(buffer, buffer.Length, cli.Value.IP, cli.Value.Port);
                    udpClient.Send(buffer, buffer.Length, cli.Value.IP, cli.Value.Port);

                    // tell clients to connect to server's external port/IP
                    SendSteamMessage(cli.Key,
                                     new SteamP2PDirectConnectRequest()
                    {
                        HostPort       = hostExtPort,
                        HostIP         = hostExtIP,
                        Name           = player.Name,
                        Engine         = request.Engine,
                        Game           = request.Game,
                        Map            = request.Map,
                        ScriptPassword = player.ScriptPassword
                    });
                }


                udpClient.Close(); // release socket

                Listener.SendCommand(new SteamHostGameSuccess()
                {
                    HostPort = hostLocalPort
                });
            });
        }