public void TryParse_Returns_False_On_Code_Mismatch() { var msg = new List <byte>(); msg.AddRange(BitConverter.GetBytes(0)); // overall length, ignored for this test. msg.Add((byte)MessageCode.Initialization.PierceFirewall); var r = PeerInit.TryFromByteArray(msg.ToArray(), out var result); Assert.False(r); Assert.Null(result); }
public void TryParse_Returns_False_On_Missing_Data(string username, char type) { var msg = new List <byte>(); msg.AddRange(BitConverter.GetBytes(0)); // overall length, ignored for this test. msg.Add((byte)MessageCode.Initialization.PeerInit); msg.AddRange(BitConverter.GetBytes(3)); // name len msg.AddRange(Encoding.ASCII.GetBytes(username)); // name msg.AddRange(BitConverter.GetBytes(1)); // type len msg.AddRange(Encoding.ASCII.GetBytes(type.ToString(CultureInfo.InvariantCulture))); // type // omit token var r = PeerInit.TryFromByteArray(msg.ToArray(), out var result); Assert.False(r); Assert.Null(result); }
public void TryParse_Returns_Expected_Data(string username, char type, int token) { var msg = new List <byte>(); msg.AddRange(BitConverter.GetBytes(0)); // overall length, ignored for this test. msg.Add((byte)MessageCode.Initialization.PeerInit); msg.AddRange(BitConverter.GetBytes(username.Length)); // name len msg.AddRange(Encoding.ASCII.GetBytes(username)); // name msg.AddRange(BitConverter.GetBytes(1)); // type len msg.AddRange(Encoding.ASCII.GetBytes(type.ToString(CultureInfo.InvariantCulture))); // type msg.AddRange(BitConverter.GetBytes(token)); // omit token var r = PeerInit.TryFromByteArray(msg.ToArray(), out var result); Assert.True(r); Assert.NotNull(result); Assert.Equal(username, result.Username); Assert.Equal(type.ToString(CultureInfo.InvariantCulture), result.ConnectionType); Assert.Equal(token, result.Token); }
/// <summary> /// Handle <see cref="IListener.Accepted"/> events. /// </summary> /// <param name="sender">The originating <see cref="IListener"/> instance.</param> /// <param name="connection">The accepted connection.</param> public async void HandleConnection(object sender, IConnection connection) { Diagnostic.Debug($"Accepted incoming connection from {connection.IPEndPoint.Address}:{SoulseekClient.Listener.Port} (id: {connection.Id})"); try { var lengthBytes = await connection.ReadAsync(4).ConfigureAwait(false); var length = BitConverter.ToInt32(lengthBytes, 0); var bodyBytes = await connection.ReadAsync(length).ConfigureAwait(false); byte[] message = lengthBytes.Concat(bodyBytes).ToArray(); if (PeerInit.TryFromByteArray(message, out var peerInit)) { // this connection is the result of an unsolicited connection from the remote peer, either to request info or // browse, or to send a file. Diagnostic.Debug($"PeerInit for connection type {peerInit.ConnectionType} received from {peerInit.Username} ({connection.IPEndPoint.Address}:{SoulseekClient.Listener.Port}) (id: {connection.Id})"); if (peerInit.ConnectionType == Constants.ConnectionType.Peer) { await SoulseekClient.PeerConnectionManager.AddMessageConnectionAsync( peerInit.Username, connection).ConfigureAwait(false); } else if (peerInit.ConnectionType == Constants.ConnectionType.Transfer) { var(transferConnection, remoteToken) = await SoulseekClient.PeerConnectionManager.AddTransferConnectionAsync( peerInit.Username, peerInit.Token, connection).ConfigureAwait(false); SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.DirectTransfer, peerInit.Username, remoteToken), transferConnection); } else if (peerInit.ConnectionType == Constants.ConnectionType.Distributed) { await SoulseekClient.DistributedConnectionManager.AddChildConnectionAsync( peerInit.Username, connection).ConfigureAwait(false); } } else if (PierceFirewall.TryFromByteArray(message, out var pierceFirewall)) { // this connection is the result of a ConnectToPeer request sent to the user, and the incoming message will // contain the token that was provided in the request. Ensure this token is among those expected, and use it // to determine the username of the remote user. if (SoulseekClient.PeerConnectionManager.PendingSolicitations.TryGetValue(pierceFirewall.Token, out var peerUsername)) { Diagnostic.Debug($"Peer PierceFirewall with token {pierceFirewall.Token} received from {peerUsername} ({connection.IPEndPoint.Address}:{SoulseekClient.Listener.Port}) (id: {connection.Id})"); SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.SolicitedPeerConnection, peerUsername, pierceFirewall.Token), connection); } else if (SoulseekClient.DistributedConnectionManager.PendingSolicitations.TryGetValue(pierceFirewall.Token, out var distributedUsername)) { Diagnostic.Debug($"Distributed PierceFirewall with token {pierceFirewall.Token} received from {distributedUsername} ({connection.IPEndPoint.Address}:{SoulseekClient.Listener.Port}) (id: {connection.Id})"); SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.SolicitedDistributedConnection, distributedUsername, pierceFirewall.Token), connection); } else { throw new ConnectionException($"Unknown PierceFirewall attempt with token {pierceFirewall.Token} from {connection.IPEndPoint.Address}:{connection.IPEndPoint.Port} (id: {connection.Id})"); } } else { throw new ConnectionException($"Unrecognized initialization message: {BitConverter.ToString(message)} ({message.Length} bytes, id: {connection.Id})"); } } catch (Exception ex) { Diagnostic.Debug($"Failed to initialize direct connection from {connection.IPEndPoint.Address}:{connection.IPEndPoint.Port}: {ex.Message}"); connection.Disconnect(exception: ex); connection.Dispose(); } }