WriteLine() 공개 정적인 메소드

Writes a line to the debug log, informing all listeners.
public static WriteLine ( string category, string msg ) : void
category string The category of the message.
msg string A composite format string.
리턴 void
예제 #1
0
        /// <summary>
        /// Sends the specified client net message.
        /// </summary>
        /// <param name="clientMsg">The client net message.</param>
        public override void Send(IClientMsg clientMsg)
        {
            byte[] data = clientMsg.Serialize();

            // encrypt outgoing traffic if we need to
            if (NetFilter != null)
            {
                data = NetFilter.ProcessOutgoing(data);
            }

            netLock.EnterReadLock();

            try
            {
                if (netStream == null)
                {
                    DebugLog.WriteLine("TcpConnection", "Attempting to send client message when not connected: {0}", clientMsg.MsgType);
                    return;
                }

                // need to ensure ordering between concurrent Sends
                lock ( netWriter )
                {
                    // write header
                    netWriter.Write((uint)data.Length);
                    netWriter.Write(TcpConnection.MAGIC);

                    netWriter.Write(data);
                }
            }
            finally
            {
                netLock.ExitReadLock();
            }
        }
예제 #2
0
        /// <summary>
        /// Connects to the specified end point.
        /// </summary>
        /// <param name="endPoint">The end point.</param>
        /// <param name="timeout">Timeout in milliseconds</param>
        public override void Connect(IPEndPoint endPoint, int timeout)
        {
            // if we're connected, disconnect
            Disconnect();

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            DebugLog.WriteLine("TcpConnection", "Connecting to {0}...", endPoint);

            var cts = new CancellationTokenSource();

            connectTokens.TryAdd(cts, true);

            ThreadPool.QueueUserWorkItem(sender =>
            {
                var asyncResult = socket.BeginConnect(endPoint, null, null);

                if (WaitHandle.WaitAny(new WaitHandle[] { asyncResult.AsyncWaitHandle, cts.Token.WaitHandle }, timeout) == 0)
                {
                    sock = socket;
                    ConnectCompleted(socket, asyncResult, cts);
                }
                else
                {
                    socket.Close();
                    ConnectCompleted(null, asyncResult, cts);
                }

                bool ignored;
                connectTokens.TryRemove(cts, out ignored);
                cts.Dispose();
            });
        }
예제 #3
0
        /// <summary>
        /// Sends a packet immediately.
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void SendPacket(UdpPacket packet)
        {
            packet.Header.SourceConnID = sourceConnId;
            packet.Header.DestConnID = remoteConnId;
            packet.Header.SeqAck = inSeqAcked = inSeq;

            DebugLog.WriteLine("UdpConnection", "Sent -> {0} Seq {1} Ack {2}; {3} bytes; Message: {4} bytes {5} packets",
                packet.Header.PacketType, packet.Header.SeqThis, packet.Header.SeqAck,
                packet.Header.PayloadSize, packet.Header.MsgSize, packet.Header.PacketsInMsg);

            byte[] data = packet.GetData();

            try
            {
                sock.SendTo(data, remoteEndPoint);
            }
            catch (SocketException e)
            {
                DebugLog.WriteLine("UdpConnection", "Critical socket failure: " + e.ErrorCode);

                state = State.Disconnected;
                return;
            }

            // If we've been idle but completely acked for more than two seconds, the next sent
            // packet will trip the resend detection. This fixes that.
            if (outSeqSent == outSeqAcked)
                nextResend = DateTime.Now.AddSeconds(RESEND_DELAY);

            // Sending should generally carry on from the packet most recently sent, even if it was a
            // resend (who knows what else was lost).
            if (packet.Header.SeqThis > 0)
                outSeqSent = packet.Header.SeqThis;
        }
예제 #4
0
        private void TryConnect(object sender)
        {
            int timeout = (int)sender;

            if (cancellationToken.IsCancellationRequested)
            {
                DebugLog.WriteLine("TcpConnection", "Connection to {0} cancelled by user", destination);
                Release(userRequestedDisconnect: true);
                return;
            }

            var asyncResult = socket.BeginConnect(destination, null, null);

            if (WaitHandle.WaitAny(new WaitHandle[] { asyncResult.AsyncWaitHandle, cancellationToken.Token.WaitHandle }, timeout) == 0)
            {
                try
                {
                    socket.EndConnect(asyncResult);
                    ConnectCompleted(true);
                }
                catch (Exception ex)
                {
                    DebugLog.WriteLine("TcpConnection", "Socket exception while completing connection request to {0}: {1}", destination, ex);
                    ConnectCompleted(false);
                }
            }
            else
            {
                ConnectCompleted(false);
            }
        }
예제 #5
0
            public async Task SendAsync(byte[] data)
            {
                var segment = new ArraySegment <byte>(data, 0, data.Length);
                await socket.SendAsync(segment, WebSocketMessageType.Binary, true, cts.Token).ConfigureAwait(false);

                DebugLog.WriteLine(nameof(WebSocketContext), "Sent {0} bytes.", data.Length);
            }
예제 #6
0
        void NetMsgReceived(object sender, NetMsgEventArgs e)
        {
            var packetMsg = CMClient.GetPacketMsg(e.Data);

            DebugLog.WriteLine("UFSClient", "<- Recv'd EMsg: {0} ({1}) {2}", packetMsg.MsgType, ( int )packetMsg.MsgType, packetMsg.IsProto ? "(Proto)" : "");

            var msgDispatch = new Dictionary <EMsg, Action <IPacketMsg> >
            {
                { EMsg.ChannelEncryptRequest, HandleEncryptRequest },
                { EMsg.ChannelEncryptResult, HandleEncryptResult },

                { EMsg.ClientUFSLoginResponse, HandleLoginResponse },
                { EMsg.ClientUFSUploadFileResponse, HandleUploadFileResponse },
                { EMsg.ClientUFSUploadFileFinished, HandleUploadFileFinished },
            };

            Action <IPacketMsg> handlerFunc;

            if (!msgDispatch.TryGetValue(packetMsg.MsgType, out handlerFunc))
            {
                return;
            }

            handlerFunc(packetMsg);
        }
예제 #7
0
        /// <summary>
        /// Dispatches up to one message to the rest of SteamKit
        /// </summary>
        /// <returns>True if a message was dispatched, false otherwise</returns>
        private bool DispatchMessage()
        {
            uint numPackets = ReadyMessageParts();

            if (numPackets == 0)
            {
                return(false);
            }

            MemoryStream payload = new MemoryStream();

            for (uint i = 0; i < numPackets; i++)
            {
                UdpPacket packet;

                inPackets.TryGetValue(++inSeqHandled, out packet);
                inPackets.Remove(inSeqHandled);

                packet.Payload.WriteTo(payload);
            }

            byte[] data = payload.ToArray();

            if (NetFilter != null)
            {
                data = NetFilter.ProcessIncoming(data);
            }

            DebugLog.WriteLine("UdpConnection", "Dispatching message; {0} bytes", data.Length);

            OnNetMsgReceived(new NetMsgEventArgs(data, remoteEndPoint));

            return(true);
        }
예제 #8
0
        void OnNetMsgReceived(object sender, NetMsgEventArgs e)
        {
            if (state == EncryptionState.Encrypted)
            {
                var plaintextData = encryption.ProcessIncoming(e.Data);
                NetMsgReceived?.Invoke(this, e.WithData(plaintextData));
                return;
            }

            var packetMsg = CMClient.GetPacketMsg(e.Data);

            if (!IsExpectedEMsg(packetMsg.MsgType))
            {
                DebugLog.WriteLine(nameof(EnvelopeEncryptedConnection), "Rejected EMsg: {0} during channel setup", packetMsg.MsgType);
                return;
            }

            switch (packetMsg.MsgType)
            {
            case EMsg.ChannelEncryptRequest:
                HandleEncryptRequest(packetMsg);
                break;

            case EMsg.ChannelEncryptResult:
                HandleEncryptResult(packetMsg);
                break;
            }
        }
예제 #9
0
        /// <summary>
        /// Connects to the specified end point.
        /// </summary>
        /// <param name="endPoint">The end point.</param>
        /// <param name="timeout">Timeout in milliseconds</param>
        public override void Connect(IPEndPoint endPoint, int timeout)
        {
            // if we're connected, disconnect
            Disconnect();

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            DebugLog.WriteLine("TcpConnection", "Connecting to {0}...", endPoint);

            ThreadPool.QueueUserWorkItem(sender =>
            {
                var asyncResult = socket.BeginConnect(endPoint, null, null);

                if (asyncResult.AsyncWaitHandle.WaitOne(timeout))
                {
                    sock = socket;
                    ConnectCompleted(socket);
                }
                else
                {
                    socket.Close();
                    ConnectCompleted(null);
                }
            });
        }
예제 #10
0
        /// <summary>
        /// Dispatches up to one message to the rest of SteamKit
        /// </summary>
        /// <returns>True if a message was dispatched, false otherwise</returns>
        private bool DispatchMessage()
        {
            uint numPackets = ReadyMessageParts();

            if (numPackets == 0)
            {
                return(false);
            }

            MemoryStream payload = new MemoryStream();

            for (uint i = 0; i < numPackets; i++)
            {
                UdpPacket packet;

                inPackets.TryGetValue(++inSeqHandled, out packet);
                inPackets.Remove(inSeqHandled);

                packet.Payload.WriteTo(payload);
            }

            byte[] data = payload.ToArray();

            DebugLog.WriteLine("UdpConnection", "Dispatching message; {0} bytes", data.Length);

            NetMsgReceived?.Invoke(this, new NetMsgEventArgs(data, CurrentEndPoint));

            return(true);
        }
예제 #11
0
        internal TcpPacket GetRawServerList(byte commandOrType, params object[] args)
        {
            try
            {
                if (!this.HandshakeServer(ESteam2ServerType.GeneralDirectoryServer))
                {
                    DebugLog.WriteLine("DSClient", "GetServerList failed handshake.");

                    Socket.Disconnect();
                    return(null);
                }

                bool bRet = this.SendCommand(commandOrType, args);

                if (!bRet)
                {
                    DebugLog.WriteLine("DSClient", "GetServerList failed sending EServerType command.");

                    Socket.Disconnect();
                    return(null);
                }

                TcpPacket packet = Socket.ReceivePacket();
                return(packet);
            }
            catch (Exception ex)
            {
                DebugLog.WriteLine("DSClient", "GetServerList threw an exception.\n{0}", ex.ToString());

                Socket.Disconnect();
                return(null);
            }
        }
예제 #12
0
        /// <summary>
        /// Sends the specified client message to the UFS server.
        /// This method will automatically assign the correct <see cref="IClientMsg.SteamID"/> of the message, as given by the parent <see cref="SteamClient"/>.
        /// </summary>
        /// <param name="msg">The client message to send.</param>
        public void Send(IClientMsg msg)
        {
            if (msg == null)
            {
                throw new ArgumentNullException(nameof(msg));
            }

            msg.SteamID = steamClient.SteamID;

            DebugLog.WriteLine(nameof(UFSClient), "Sent -> EMsg: {0} {1}", msg.MsgType, msg.IsProto ? "(Proto)" : "");

            // we'll swallow any network failures here because they will be thrown later
            // on the network thread, and that will lead to a disconnect callback
            // down the line

            try
            {
                connection.Send(msg.Serialize());
            }
            catch (IOException)
            {
            }
            catch (SocketException)
            {
            }
        }
예제 #13
0
 void DisconnectNonBlocking(bool userInitiated)
 => Task.Run(() => connection.DisconnectCore(userInitiated, this))
 .ContinueWith(t =>
 {
     var ex = t.Exception;
     DebugLog.WriteLine(nameof(WebSocketContext), "Unhandled {0} when disconnecting: {1}", ex.GetType().FullName, ex.Message);
 }, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
예제 #14
0
        public static byte[]? GetMachineID()
        {
            if (generateTask is null)
            {
                DebugLog.WriteLine(nameof(HardwareUtils), "GetMachineID() called before Init()");
                return(null);
            }

            bool didComplete = generateTask.Wait(TimeSpan.FromSeconds(30));

            if (!didComplete)
            {
                DebugLog.WriteLine(nameof(HardwareUtils), "Unable to generate machine_id in a timely fashion, logons may fail");
                return(null);
            }

            MachineID machineId = generateTask.Result;

            using (MemoryStream ms = new MemoryStream())
            {
                machineId.WriteToStream(ms);

                return(ms.ToArray());
            }
        }
예제 #15
0
        public static byte[]? GetMachineID(IMachineInfoProvider machineInfoProvider)
        {
            if (!generationTable.TryGetValue(machineInfoProvider, out var generateTask))
            {
                DebugLog.WriteLine(nameof(HardwareUtils), "GetMachineID() called before Init()");
                return(null);
            }

            DebugLog.Assert(generateTask != null, nameof(HardwareUtils), "GetMachineID() found null task - should be impossible.");

            try
            {
                bool didComplete = generateTask.Wait(TimeSpan.FromSeconds(30));

                if (!didComplete)
                {
                    DebugLog.WriteLine(nameof(HardwareUtils), "Unable to generate machine_id in a timely fashion, logons may fail");
                    return(null);
                }
            }
            catch (AggregateException ex) when(ex.InnerException != null && generateTask.IsFaulted)
            {
                // Rethrow the original exception rather than a wrapped AggregateException.
                ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
            }

            MachineID machineId = generateTask.Result;

            using MemoryStream ms = new MemoryStream();
            machineId.WriteToStream(ms);
            return(ms.ToArray());
        }
예제 #16
0
        /// <summary>
        /// Sends or resends sequenced messages, if necessary. Also responsible for throttling
        /// the rate at which they are sent.
        /// </summary>
        private void SendPendingMessages()
        {
            lock ( outPackets )
            {
                if (DateTime.Now > nextResend && outSeqSent > outSeqAcked)
                {
                    // If we can't clear the send queue during a Disconnect, clear out the pending messages
                    if (state == ( int )State.Disconnecting)
                    {
                        outPackets.Clear();
                    }

                    DebugLog.WriteLine("UdpConnection", "Sequenced packet resend required");

                    // Don't send more than 3 (Steam behavior?)
                    for (int i = 0; i < RESEND_COUNT && i < outPackets.Count; i++)
                    {
                        SendPacket(outPackets[i]);
                    }

                    nextResend = DateTime.Now.AddSeconds(RESEND_DELAY);
                }
                else if (outSeqSent < outSeqAcked + AHEAD_COUNT)
                {
                    // I've never seen Steam send more than 4 packets before it gets an Ack, so this limits the
                    // number of sequenced packets that can be sent out at one time.
                    for (int i = ( int )(outSeqSent - outSeqAcked); i < AHEAD_COUNT && i < outPackets.Count; i++)
                    {
                        SendPacket(outPackets[i]);
                    }
                }
            }
        }
예제 #17
0
        public override void Send(IClientMsg clientMsg)
        {
            lock (netLock)
            {
                if (socket == null || netStream == null)
                {
                    DebugLog.WriteLine("TcpConnection", "Attempting to send client message when not connected: {0}", clientMsg.MsgType);
                    return;
                }

                byte[] data = clientMsg.Serialize();

                if (netFilter != null)
                {
                    data = netFilter.ProcessOutgoing(data);
                }

                try
                {
                    netWriter.Write((uint)data.Length);
                    netWriter.Write(TcpConnection.MAGIC);
                    netWriter.Write(data);
                }
                catch (IOException ex)
                {
                    DebugLog.WriteLine("TcpConnection", "Socket exception while writing data: {0}", ex);
                }
            }
        }
예제 #18
0
        /// <summary>
        /// Sends the specified client net message.
        /// </summary>
        /// <param name="clientMsg">The client net message.</param>
        public override void Send(IClientMsg clientMsg)
        {
            if (!isConnected)
            {
                DebugLog.WriteLine("TcpConnection", "Attempting to send client message when not connected: {0}", clientMsg.MsgType);
                return;
            }

            byte[] data = clientMsg.Serialize();

            // encrypt outgoing traffic if we need to
            if (NetFilter != null)
            {
                data = NetFilter.ProcessOutgoing(data);
            }

            lock ( sock )
            {
                // write header
                netWriter.Write(( uint )data.Length);
                netWriter.Write(TcpConnection.MAGIC);

                netWriter.Write(data);
            }
        }
예제 #19
0
        void NetMsgReceived(object sender, NetMsgEventArgs e)
        {
            var packetMsg = CMClient.GetPacketMsg(e.Data);

            if (packetMsg == null)
            {
                DebugLog.WriteLine(nameof(UFSClient), "Packet message failed to parse, shutting down connection");
                Disconnect(userInitiated: false);
                return;
            }

            DebugLog.WriteLine(nameof(UFSClient), "<- Recv'd EMsg: {0} ({1}) {2}", packetMsg.MsgType, ( int )packetMsg.MsgType, packetMsg.IsProto ? "(Proto)" : "");

            var msgDispatch = new Dictionary <EMsg, Action <IPacketMsg> >
            {
                { EMsg.ClientUFSLoginResponse, HandleLoginResponse },
                { EMsg.ClientUFSUploadFileResponse, HandleUploadFileResponse },
                { EMsg.ClientUFSUploadFileFinished, HandleUploadFileFinished },
            };

            if (!msgDispatch.TryGetValue(packetMsg.MsgType, out var handlerFunc))
            {
                return;
            }

            handlerFunc(packetMsg);
        }
예제 #20
0
        async Task <byte[]> DoRawCommandAsync(Server server, HttpMethod method, string command, string data = null, bool doAuth = false, string args = "", string authtoken = null)
        {
            var url     = BuildCommand(server, command, args, authtoken);
            var request = new HttpRequestMessage(method, url);

            if (doAuth && server.Type == "CS")
            {
                var req = Interlocked.Increment(ref reqCounter);

                byte[] shaHash;

                using (var ms = new MemoryStream())
                    using (var bw = new BinaryWriter(ms))
                    {
                        var uri = new Uri(url);

                        bw.Write(sessionId);
                        bw.Write(req);
                        bw.Write(sessionKey);
                        bw.Write(Encoding.UTF8.GetBytes(uri.AbsolutePath));

                        shaHash = CryptoHelper.SHAHash(ms.ToArray());
                    }

                string hexHash    = Utils.EncodeHexString(shaHash);
                string authHeader = string.Format("sessionid={0};req-counter={1};hash={2};", sessionId, req, hexHash);

                request.Headers.Add("x-steam-auth", authHeader);
            }

            if (HttpMethod.Post.Equals(method))
            {
                request.Content = new StringContent(data, Encoding.UTF8);
                request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            }

            using (var cts = new CancellationTokenSource())
            {
                cts.CancelAfter(RequestTimeout);

                try
                {
                    var response = await httpClient.SendAsync(request, cts.Token).ConfigureAwait(false);

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new SteamKitWebRequestException($"Response status code does not indicate success: {response.StatusCode} ({response.ReasonPhrase}).", response);
                    }

                    var responseData = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

                    return(responseData);
                }
                catch (Exception ex)
                {
                    DebugLog.WriteLine("CDNClient", "Failed to complete web request to {0}: {1}", url, ex.Message);
                    throw;
                }
            }
        }
예제 #21
0
        /// <summary>
        /// Connects this client to a UFS server.
        /// This begins the process of connecting and encrypting the data channel between the client and the UFS server.
        /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>.
        /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead.
        /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay.
        /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server.
        /// </summary>
        /// <param name="ufsServer">
        /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to.
        /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers.
        /// </param>
        public void Connect(IPEndPoint ufsServer = null)
        {
            DebugLog.Assert(steamClient.IsConnected, nameof(UFSClient), "CMClient is not connected!");

            Disconnect();
            Debug.Assert(connection == null);

            if (ufsServer == null)
            {
                var serverList = steamClient.GetServersOfType(EServerType.UFS);

                if (serverList.Count == 0)
                {
                    DebugLog.WriteLine(nameof(UFSClient), "No UFS server addresses were provided yet.");
                    Disconnected(this, new DisconnectedEventArgs(userInitiated: false));
                    return;
                }

                var random = new Random();
                ufsServer = serverList[random.Next(serverList.Count)];
            }

            // steamclient has the connection type hardcoded as TCP
            // todo: determine if UFS supports UDP and if we want to support it
            connection = new EnvelopeEncryptedConnection(new TcpConnection(), steamClient.Universe);

            connection.NetMsgReceived += NetMsgReceived;
            connection.Connected      += Connected;
            connection.Disconnected   += Disconnected;

            connection.Connect(ufsServer, ( int )ConnectionTimeout.TotalMilliseconds);
        }
예제 #22
0
        void ConnectCompleted(Socket sock)
        {
            if (sock == null)
            {
                OnDisconnected(EventArgs.Empty);
                return;
            }

            if (!sock.Connected)
            {
                DebugLog.WriteLine("TcpConnection", "Unable to connect");
                OnDisconnected(EventArgs.Empty);
                return;
            }

            DebugLog.WriteLine("TcpConnection", "Connected!");

            isConnected = true;

            netStream = new NetworkStream(sock, false);

            netReader = new BinaryReader(netStream);
            netWriter = new BinaryWriter(netStream);

            // initialize our network thread
            netThread      = new Thread(NetLoop);
            netThread.Name = "TcpConnection Thread";
            netThread.Start();

            OnConnected(EventArgs.Empty);
        }
예제 #23
0
        void ConnectCompleted(object sender, SocketAsyncEventArgs e)
        {
            sock = sender as Socket;

            if (sock == null)
            {
                OnDisconnected(EventArgs.Empty);
                return;
            }

            if (e.SocketError != SocketError.Success)
            {
                DebugLog.WriteLine("TcpConnection", "Unable to connect: {0}", e.SocketError);
                OnDisconnected(EventArgs.Empty);
                return;
            }

            DebugLog.WriteLine("TcpConnection", "Connected!");

            isConnected = true;

            netStream = new NetworkStream(sock, false);

            netReader = new BinaryReader(netStream);
            netWriter = new BinaryWriter(netStream);

            // initialize our network thread
            netThread      = new Thread(NetLoop);
            netThread.Name = "TcpConnection Thread";
            netThread.Start();

            OnConnected(EventArgs.Empty);
        }
예제 #24
0
        async Task <byte[]> DoRawCommandAsync(Server server, string command, string?args)
        {
            var url = BuildCommand(server, command, args ?? string.Empty);

            using var request = new HttpRequestMessage(HttpMethod.Get, url);

            using (var cts = new CancellationTokenSource())
            {
                cts.CancelAfter(RequestTimeout);

                try
                {
                    var response = await httpClient.SendAsync(request, cts.Token).ConfigureAwait(false);

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new SteamKitWebRequestException($"Response status code does not indicate success: {response.StatusCode:D} ({response.ReasonPhrase}).", response);
                    }

                    var responseData = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

                    return(responseData);
                }
                catch (Exception ex)
                {
                    DebugLog.WriteLine("CDNClient", "Failed to complete web request to {0}: {1}", url, ex.Message);
                    throw;
                }
            }
        }
예제 #25
0
        void ConnectCompleted(Socket sock, IAsyncResult asyncResult, CancellationTokenSource connectToken)
        {
            if (connectToken.IsCancellationRequested)
            {
                DebugLog.WriteLine("TcpConnection", "Connect request was cancelled");
                return;
            }
            else if (sock == null)
            {
                DebugLog.WriteLine("TcpConnection", "Timed out while connecting");
                OnDisconnected(EventArgs.Empty);
                return;
            }

            try
            {
                sock.EndConnect(asyncResult);
            }
            catch (Exception ex)
            {
                DebugLog.WriteLine("TcpConnection", "Socket exception while connecting: {0}", ex);
                OnDisconnected(EventArgs.Empty);
                return;
            }

            netLock.EnterWriteLock();

            try
            {
                if (!sock.Connected)
                {
                    DebugLog.WriteLine("TcpConnection", "Unable to connect");
                    OnDisconnected(EventArgs.Empty);
                    return;
                }

                DebugLog.WriteLine("TcpConnection", "Connected!");

                filter           = null;
                wantsNetShutdown = false;
                netStream        = new NetworkStream(sock, false);

                netReader = new BinaryReader(netStream);
                netWriter = new BinaryWriter(netStream);

                // initialize our network thread
                netThread      = new Thread(NetLoop);
                netThread.Name = "TcpConnection Thread";
                netThread.Start(sock);
            }
            finally
            {
                netLock.ExitWriteLock();
            }

            OnConnected(EventArgs.Empty);
        }
예제 #26
0
        // this is now a steamkit meme
        /// <summary>
        /// Nets the loop.
        /// </summary>
        void NetLoop()
        {
            // poll for readable data every 100ms
            const int POLL_MS = 100;

            while (!cancellationToken.IsCancellationRequested)
            {
                bool canRead = false;

                try
                {
                    canRead = socket.Poll(POLL_MS * 1000, SelectMode.SelectRead);
                }
                catch (SocketException ex)
                {
                    DebugLog.WriteLine("TcpConnection", "Socket exception while polling: {0}", ex);
                    break;
                }

                if (!canRead)
                {
                    // nothing to read yet
                    continue;
                }

                byte[] packData = null;

                try
                {
                    // read the packet off the network
                    packData = ReadPacket();
                }
                catch (IOException ex)
                {
                    DebugLog.WriteLine("TcpConnection", "Socket exception occurred while reading packet: {0}", ex);
                    break;
                }

                try
                {
                    NetMsgReceived?.Invoke(this, new NetMsgEventArgs(packData, destination));
                }
                catch (Exception ex)
                {
                    DebugLog.WriteLine("TcpConnection", "Unexpected exception propogated back to NetLoop: {0}", ex);
                }
            }

            // Thread is shutting down, ensure socket is shut down and disposed
            bool userShutdown = cancellationToken.IsCancellationRequested;

            if (userShutdown)
            {
                Shutdown();
            }
            Release(userShutdown);
        }
예제 #27
0
        void ReadPacket()
        {
            // the tcp packet header is considerably less complex than the udp one
            // it only consists of the packet length, followed by the "VT01" magic
            uint packetLen   = 0;
            uint packetMagic = 0;

            byte[] packData = null;

            try
            {
                try
                {
                    packetLen   = netReader.ReadUInt32();
                    packetMagic = netReader.ReadUInt32();
                }
                catch (IOException ex)
                {
                    throw new IOException("Connection lost while reading packet header.", ex);
                }

                if (packetMagic != TcpConnection.MAGIC)
                {
                    throw new IOException("Got a packet with invalid magic!");
                }

                // rest of the packet is the physical data
                packData = netReader.ReadBytes(( int )packetLen);

                if (packData.Length != packetLen)
                {
                    throw new IOException("Connection lost while reading packet payload");
                }

                // decrypt the data off the wire if needed
                if (NetFilter != null)
                {
                    packData = NetFilter.ProcessIncoming(packData);
                }
            }
            catch (IOException ex)
            {
                DebugLog.WriteLine("TcpConnection", "Socket exception occurred while reading packet: {0}", ex);

                // signal that our connection is dead
                isConnected = false;

                Cleanup();

                OnDisconnected(EventArgs.Empty);
                return;
            }

            OnNetMsgReceived(new NetMsgEventArgs(packData, sock.RemoteEndPoint as IPEndPoint));
        }
예제 #28
0
        // this is now a steamkit meme
        /// <summary>
        /// Nets the loop.
        /// </summary>
        void NetLoop(object param)
        {
            // poll for readable data every 100ms
            const int POLL_MS = 100;
            Socket    socket  = param as Socket;

            while (!wantsNetShutdown)
            {
                bool canRead = socket.Poll(POLL_MS * 1000, SelectMode.SelectRead);

                if (!canRead)
                {
                    // nothing to read yet
                    continue;
                }

                netLock.EnterUpgradeableReadLock();
                byte[] packData = null;

                if (netStream == null)
                {
                    break;
                }

                try
                {
                    // read the packet off the network
                    packData = ReadPacket();
                }
                catch (IOException ex)
                {
                    DebugLog.WriteLine("TcpConnection", "Socket exception occurred while reading packet: {0}", ex);

                    // signal that our connection is dead
                    Cleanup();

                    OnDisconnected(EventArgs.Empty);
                    return;
                }
                finally
                {
                    netLock.ExitUpgradeableReadLock();
                }

                // decrypt the data off the wire if needed
                if (NetFilter != null)
                {
                    packData = NetFilter.ProcessIncoming(packData);
                }

                OnNetMsgReceived(new NetMsgEventArgs(packData, socket.RemoteEndPoint as IPEndPoint));
            }
        }
예제 #29
0
            async Task RunCore(CancellationToken cancellationToken, TimeSpan connectionTimeout)
            {
                var uri = new Uri(FormattableString.Invariant($"wss://{hostAndPort}/cmsocket/"));

                using (var timeout = new CancellationTokenSource())
                    using (var combinedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeout.Token))
                    {
                        timeout.CancelAfter(connectionTimeout);

                        try
                        {
                            await socket.ConnectAsync(uri, combinedCancellation.Token).ConfigureAwait(false);
                        }
                        catch (TaskCanceledException) when(timeout.IsCancellationRequested)
                        {
                            DebugLog.WriteLine(nameof(WebSocketContext), "Time out connecting websocket {0} after {1}", uri, connectionTimeout);
                            connection.DisconnectCore(userInitiated: false, specificContext: this);
                            return;
                        }
                        catch (Exception ex)
                        {
                            DebugLog.WriteLine(nameof(WebSocketContext), "Exception connecting websocket: {0} - {1}", ex.GetType().FullName, ex.Message);
                            connection.DisconnectCore(userInitiated: false, specificContext: this);
                            return;
                        }
                    }

                DebugLog.WriteLine(nameof(WebSocketContext), "Connected to {0}", uri);
                connection.Connected?.Invoke(connection, EventArgs.Empty);

                while (!cancellationToken.IsCancellationRequested && socket.State == WebSocketState.Open)
                {
                    var packet = await ReadMessageAsync(cancellationToken).ConfigureAwait(false);

                    if (packet != null && packet.Length > 0)
                    {
                        connection.NetMsgReceived?.Invoke(connection, new NetMsgEventArgs(packet, EndPoint));
                    }
                }

                if (socket.State == WebSocketState.Open)
                {
                    DebugLog.WriteLine(nameof(WebSocketContext), "Closing connection...");
                    try
                    {
                        await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, default(CancellationToken)).ConfigureAwait(false);
                    }
                    catch (Win32Exception ex)
                    {
                        DebugLog.WriteLine(nameof(WebSocketContext), "Error closing connection: {0}", ex.Message);
                    }
                }
            }
예제 #30
0
 public void Send(byte[] data)
 {
     try
     {
         currentContext?.SendAsync(data).GetAwaiter().GetResult();
     }
     catch (Exception ex)
     {
         DebugLog.WriteLine(nameof(WebSocketConnection), "Exception while sending data: {0} - {1}", ex.GetType().FullName, ex.Message);
         DisconnectCore(userInitiated: false, specificContext: null);
     }
 }