internal RealTimeHandler(StartPayload payload)
        {
            CurrentRoom = payload.Room;
            AuthHash    = payload.Area.Hash;

            _connGateway = new GsUdpClient(payload.Area);
            _connGateway.DataReceived += OnDataReceived;
            _connGateway.Error        += OnError;

            _observer        = new GsLiveSystemObserver(GSLiveType.RealTime);
            _dataObserver    = new RealtimeDataObserver();
            _keepAliveSender = new KeepAliveSender();

            _isDisposed = false;
            PlayerHash  = -1;

            // Set Internal Event Handlers
            RealTimeEventHandlers.Authorized               += OnAuth;
            RealTimeEventHandlers.MemberId                 += OnMemberId;
            RealTimeEventHandlers.GProtocolConnected       += OnConnected;
            RealTimeEventHandlers.LeftDispose              += OnLeftDispose;
            RealTimeEventHandlers.PeerConfig               += OnPeerConfig;
            ObserverCompacterUtil.SendObserverEventHandler += SendObserverEventHandler;
            RealtimeDataObserver.Caller += DataGetter;
            KeepAliveSender.Caller      += SendKeepAlive;


            InitRequestMessageHandlers();
            InitResponseMessageHandlers();

            DebugUtil.LogNormal <RealTimeHandler>(DebugLocation.RealTime, "Constructor", "RealTimeHandler init");
        }
Example #2
0
 public HostConnectHandle(int computerId, HttpProcessor p)
 {
     this.ComputerID  = computerId;
     this.p           = p;
     this.stream      = p.tcpStream;
     this.ConnectTime = DateTime.UtcNow;
     // Send KeepAlive packets every 120 seconds if no other packets have been sent.
     keepAlive = new KeepAliveSender("KeepAlive[" + computerId + "]", 120000, SendKeepalive, (ignoredArg) => Disconnect());
 }
Example #3
0
 /// <summary>
 /// If it is time to send a keepalive packet, sends a keepalive packet.
 /// </summary>
 private void SendKeepalive(KeepAliveSender keepAlive)
 {
     ProtectedSend(() =>
     {
         if (keepAlive.IsTimeToKeepalive())                 // Test timing after aquiring writeLock, to prevent unnecessary keepalive packets if another packet was sending while we were obtaining the lock.
         {
             keepAlive.NotifyPacketSending();
             stream.WriteByte((byte)Command.KeepAlive);
         }
     });
 }
Example #4
0
        private HostConnectResult FollowHostConnectProtocol()
        {
            State = HostConnectClientState.Connecting;
            StateChanged(this, new StateChangedEventArgs(null, State));

            Uri masterServerUri = ServiceWrapper.settings.GetMasterServerUri();

            // Ensure the certificate exists before we connect, because it can take a moment to create and we don't want the connection to time out.
            IdentityVerification.EnsureClientCertificateExists();

            tcpClient = new TcpClient();
            KeepAliveSender keepAlive = null;

            try
            {
                #region Get Connected
                tcpClient.NoDelay        = true;
                tcpClient.ReceiveTimeout = 30000;
                tcpClient.SendTimeout    = 30000;
                tcpClient.Connect(masterServerUri.DnsSafeHost, masterServerUri.Port);
                stream = tcpClient.GetStream();
                if (masterServerUri.Scheme == "https")
                {
                    try
                    {
                        RemoteCertificateValidationCallback certCallback = null;
                        if (!ServiceWrapper.settings.ValidateServerCertificate)
                        {
                            certCallback = (sender, certificate, chain, sslPolicyErrors) => true;
                        }
                        stream = new SslStream(stream, false, certCallback, null);
                        ((SslStream)stream).AuthenticateAsClient(masterServerUri.DnsSafeHost, null, System.Security.Authentication.SslProtocols.Tls12, ServiceWrapper.settings.ValidateServerCertificate);
                    }
                    catch (ThreadAbortException) { throw; }
                    catch (SocketException) { throw; }
                    catch (Exception ex)
                    {
                        Logger.Debug(ex);
                        return(new HostConnectResult(ProtocolErrors.HttpsNegotiationFailed));
                    }
                }
                State = HostConnectClientState.Authenticating;
                StateChanged(this, new StateChangedEventArgs(null, State));
                {
                    // Create HTTP request.
                    StringBuilder sb = new StringBuilder();
                    sb.Append("POST ").Append(masterServerUri.PathAndQuery).Append("hostconnect HTTP/1.1\r\n");
                    sb.Append("Host: ").Append(masterServerUri.Host).Append("\r\n");
                    sb.Append("Content-Length: 0\r\n");
                    sb.Append("\r\n");
                    byte[] buf = ByteUtil.Utf8NoBOM.GetBytes(sb.ToString());
                    stream.Write(buf, 0, buf.Length);
                }
                #endregion
                #region Authentication Protocol
                // Auth 0) Receive ClientAuthentication command code.
                Command command = (Command)ByteUtil.ReadNBytes(stream, 1)[0];
                if (command != Command.ClientAuthentication)
                {
                    return(new HostConnectResult(ProtocolErrors.AuthResponseCommand));
                }

                // Auth 1) Receive authentication challenge.  This is an array of 32 random bytes which the Host Service must sign with its private key.
                byte[] authChallenge = ByteUtil.ReadNBytes(stream, 32);

                // Auth 2) Build authentication reply.
                // Auth 2.1) Authentication type
                HostAuthenticationType authType = HostAuthenticationType.PermanentHost;

                // Auth 2.2) Encode security key
                byte[] securityKey = ByteUtil.Utf8NoBOM.GetBytes("NOT REAL");
                // TODO: Get the real security key from this exe's embedded settings.
                if (securityKey.Length > byte.MaxValue)
                {
                    return(new HostConnectResult(ProtocolErrors.SecurityKeyLength));
                }

                byte[] signature, publicKey;
                if (authType == HostAuthenticationType.PermanentHost)
                {
                    // Auth 2.3) Create signature
                    signature = IdentityVerification.SignAuthenticationChallenge(authChallenge);
                    // Auth 2.4) Encode public key
                    publicKey = ByteUtil.Utf8NoBOM.GetBytes(IdentityVerification.GetPublicKeyXML());
                }
                else
                {
                    signature = new byte[0];
                    publicKey = new byte[0];
                }
                // Auth 2.5) Encode computer name
                byte[] computerName = ByteUtil.Utf8NoBOM.GetBytes(Environment.MachineName);
                // Auth 2.6) Encode host version string
                byte[] appVersion = ByteUtil.Utf8NoBOM.GetBytes(AppVersion.VersionNumber);
                // Auth 2.7) Encode OS version string
                byte[] osVersion = ByteUtil.Utf8NoBOM.GetBytes(OSInfo.GetOSVersionInfo());

                // Build single buffer (not strictly necessary, but it helps us ensure we got the length calculated right).
                int calculatedLength = 1
                                       + 1 + securityKey.Length
                                       + 2 + signature.Length
                                       + 2 + publicKey.Length
                                       + 1 + computerName.Length
                                       + 1 + appVersion.Length
                                       + 1 + osVersion.Length;
                if (calculatedLength > ushort.MaxValue)
                {
                    return(new HostConnectResult(ProtocolErrors.AuthResponseTooLarge));
                }

                using (MemoryDataStream mds = new MemoryDataStream(calculatedLength))
                {
                    mds.WriteByte((byte)authType);
                    mds.WriteByte((byte)securityKey.Length);
                    mds.Write(securityKey);
                    mds.WriteUInt16((ushort)signature.Length);
                    mds.Write(signature);
                    mds.WriteUInt16((ushort)publicKey.Length);
                    mds.Write(publicKey);
                    mds.WriteByte((byte)computerName.Length);
                    mds.Write(computerName);
                    mds.WriteByte((byte)appVersion.Length);
                    mds.Write(appVersion);
                    mds.WriteByte((byte)osVersion.Length);
                    mds.Write(osVersion);
                    if (mds.Position != calculatedLength)
                    {
                        return(new HostConnectResult(ProtocolErrors.AuthResponseSizeError));
                    }
                    mds.Seek(0, SeekOrigin.Begin);

                    // Send authentication reply
                    stream.WriteByte((byte)Command.ClientAuthentication);
                    ByteUtil.WriteUInt16((ushort)calculatedLength, stream);
                    mds.CopyTo(stream);
                }
                #endregion
                // This is the Host Service, which is responsible for sending a KeepAlive packet after 60 seconds of sending inactivity.  The Master Server will do the same on a 120 second interval.
                tcpClient.ReceiveTimeout = 135000;                 // 120 seconds + 15 seconds for bad network conditions.
                tcpClient.SendTimeout    = 75000;

                State = HostConnectClientState.Connected;
                StateChanged(this, new StateChangedEventArgs(null, State));

                // Send KeepAlive packets every 60 seconds if no other packets have been sent.
                keepAlive = new KeepAliveSender("KeepAlive", 60000, SendKeepalive, (ignoredArg) => Disconnect());
                CommandLoop(tcpClient, stream);
            }
            finally
            {
                // Make local copies of these references so they can't become null after the null check.
                KeepAliveSender k = keepAlive;
                if (k != null)
                {
                    Try.Catch_RethrowThreadAbort(keepAlive.Stop);
                }
                TcpClient c = tcpClient;
                if (c != null)
                {
                    Try.Catch_RethrowThreadAbort(c.Close);
                }
            }
            return(new HostConnectResult());
        }