Esempio n. 1
0
        /// <summary>
        /// Connects to the game server with the given <see cref="ConnectArgs"/>.
        /// This should be called from the main Unity thread.
        /// </summary>
        /// <param name="connectArgs"></param>
        public void Connect(ConnectArgs connectArgs)
        {
            if (isConnecting || IsConnected)
            {
                return;
            }

            InitializeFields(connectArgs);

            userId = UnityEngine.Random.Range(0, int.MaxValue);

            isConnecting = true;
            RaiseConnecting();

            // Instantiating with new TcpClient(url, port) will immediately
            // try to connect and block. Simply instantiate and connect
            // in the receive background thread when it starts so the
            // main Unity thread doesn't hang.
            client        = new TcpClient();
            client.Client = null;

            // Clear the queues when connecting instead of disconnecting
            // in case you want to still process packets that were received.
            receivePacketsQueue.Clear();
            sendPacketsQueue.Clear();

            receivePacketsThread = new Thread(() => { ReceivePacketsThread(connectArgs); });
            receivePacketsThread.IsBackground = true;
            receivePacketsThread.Start();
        }
Esempio n. 2
0
        private void TryOpenTcpSocket(ConnectArgs connectArgs)
        {
            try
            {
                client.Connect(connectArgs.Url, (int)connectArgs.Port);
                isConnecting = false;

                client.NoDelay = true;
            }
            catch (Exception)
            {
                RaiseCouldNotOpenSocket();
                throw;
            }
        }
Esempio n. 3
0
        private void InitializeFields(ConnectArgs connectArgs)
        {
            broadcastCount = 0;

            abortingMatch = false;

            userId             = UnityEngine.Random.Range(0, int.MaxValue);
            connectArgs.UserId = userId;

            Debug.Log($"Your userId={userId}");

            matchId = connectArgs.MatchId;
            Debug.Log($"Connect with matchId={matchId}");

            // Can only get the main thread's context from the main thread
            mainThreadContext = SynchronizationContext.Current;
        }
Esempio n. 4
0
 private void TryHandshake(ConnectArgs connectArgs)
 {
     try
     {
         // Write directly to the SSL stream instead of enqueueing
         // to the send packets queue in order to know immediately
         // if the server closes the socket because of an invalid
         // match token.
         sslStream.Write(PacketFactory.MakeConnectBuffer(userId, connectArgs.MatchId, connectArgs.MatchToken));
     }
     catch (Exception)
     {
         // The server will close the socket if the client's match
         // token was either invalid or its encrypted timestamp
         // is expired.
         RaiseServerHandshakeFailed();
         throw;
     }
 }
Esempio n. 5
0
        private void ReceivePacketsThread(ConnectArgs connectArgs)
        {
            // Thread exceptions are silent, so
            // catching is absolutely required.
            try
            {
                TryOpenTcpSocket(connectArgs);
                TryOpenSslStream();
                TryValidateServer();
                TryHandshake(connectArgs);

                RaiseConnected();

                // Start the send packets thread now that there's a connection
                sendPacketsThread = new Thread(() => { SendPacketsThread(); });
                sendPacketsThread.IsBackground = true;
                sendPacketsThread.Start();

                while (true)
                {
                    byte[] content;
                    if (!ReadPacketBlocking(out content))
                    {
                        break;
                    }

                    receivePacketsQueue.Enqueue(content);
                }
            }
            catch (SocketException exception)
            {
                Debug.Log($"Failed to connect to url={connectArgs.Url} port={connectArgs.Port}\nReason:\n{exception}");
            }
            catch (ThreadInterruptedException)
            {
                // Expected if Disconnect() is called
            }
            catch (ThreadAbortException)
            {
                // Expected if Disconnect() is called
            }
            catch (TimeoutException)
            {
                RaiseReceiveTimedOut();
            }
            catch (Exception exception)
            {
                // something went wrong. probably important.
                Debug.LogError($"Receive packets thread exception:\n{exception}");
                RaiseUnknownError();
            }
            finally
            {
                // The send packets thread might be waiting on ManualResetEvent,
                // interrupt it to ensure that it is stopped.
                sendPacketsThread?.Interrupt();

                // Connect might have failed.
                isConnecting = false;

                sslStream?.Close();
                client?.Close();
            }
        }