예제 #1
0
        public async void ConnectToId(SteamId hostId)
        {
            // Refuse to attempt another connection if one is active or in progress
            if (Active || Status == PeerStatus.CONNECTING)
            {
                Output.LogWarning($"{Name}: Attempted to connect while a previous connection is active or in progress");
                return;
            }

            // Set timeout start time, set client active, and set client status to Connecting
            DateTime timeoutStart = DateTime.Now;

            // Set status appropriately
            _active = true;
            _status = PeerStatus.CONNECTING;

            try
            {
                // Send a request to connect
                byte[] sendData = new byte[] { (byte)PacketType.CONNECT };
                SendPacket(hostId, sendData, sendData.Length);

                while (Status == PeerStatus.CONNECTING)
                {
                    // Wait for a packet to arrive
                    while (!IsPacketAvailable())
                    {
                        TimeSpan timeoutChk = DateTime.Now - timeoutStart;

                        if (timeoutChk.TotalMilliseconds >= MP_TIMEOUT)
                        {
                            throw new Exception("Timed out attempting to connect");
                        }

                        await Task.Delay(TimeSpan.FromMilliseconds(TickRate));
                    }

                    GetNextPacket(out P2Packet? packet);

                    if (packet == null)
                    {
                        throw new Exception("Null packet received");
                    }

                    // If the packet is not null, get data and sender SteamId
                    byte[]  data   = packet.Value.Data;
                    SteamId sender = packet.Value.SteamId;

                    if (data.Length < 1 || data == null)
                    {
                        throw new Exception("Null or zero-length data array received");
                    }

                    // Ignore packets sent by someone who isn't expected
                    if (sender != hostId)
                    {
                        continue;
                    }

                    if (data[0] != (byte)PacketType.CONNECTION_ACCEPTED)
                    {
                        throw new Exception($"Unexpected response ({data[0]})");
                    }

                    // Now connected to a new server, set status and refresh receive queue
                    _status = PeerStatus.CONNECTED;
                    _receiveQueue.Clear();

                    // Raise OnConnected event
                    OnConnected?.Invoke();
                }

                _host = hostId;
            }
            catch (Exception e)
            {
                Output.LogError($"{Name}: Error connecting to host ({e.Message})");

                // If we catch an exception, reset active and status
                ResetStatus();
            }
        }