public static WriteLine ( string category, string msg ) : void | ||
category | string | The category of the message. |
msg | string | A composite format string. |
리턴 | void |
/// <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(); } }
/// <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(); }); }
/// <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; }
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); } }
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); }
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); }
/// <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); }
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; } }
/// <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); } }); }
/// <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); }
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); } }
/// <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) { } }
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);
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()); } }
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()); }
/// <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]); } } } }
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); } } }
/// <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); } }
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); }
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; } } }
/// <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); }
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); }
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); }
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; } } }
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); }
// 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); }
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)); }
// 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)); } }
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); } } }
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); } }