// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Net; using System.Net.Sockets; using MQTTnet.Channel; namespace MQTTnet.Extensions.Socks5; /// /// Wraps a opened by the SOCKS5 stream provider so /// MqttTcpChannel can read the original socket's endpoints via /// while the rest of the I/O delegates to the /// underlying stream. /// sealed class Socks5NetworkStream : Stream, IMqttClientStreamEndPoints { readonly NetworkStream _inner; public Socks5NetworkStream(NetworkStream inner, EndPoint localEndPoint, EndPoint remoteEndPoint) { _inner = inner ?? throw new ArgumentNullException(nameof(inner)); LocalEndPoint = localEndPoint; RemoteEndPoint = remoteEndPoint; } public EndPoint LocalEndPoint { get; } public EndPoint RemoteEndPoint { get; } public override bool CanRead => _inner.CanRead; public override bool CanSeek => _inner.CanSeek; public override bool CanWrite => _inner.CanWrite; public override bool CanTimeout => _inner.CanTimeout; public override long Length => _inner.Length; public override long Position { get => _inner.Position; set => _inner.Position = value; } public override int ReadTimeout { get => _inner.ReadTimeout; set => _inner.ReadTimeout = value; } public override int WriteTimeout { get => _inner.WriteTimeout; set => _inner.WriteTimeout = value; } public override void Flush() => _inner.Flush(); public override Task FlushAsync(CancellationToken cancellationToken) => _inner.FlushAsync(cancellationToken); public override int Read(byte[] buffer, int offset, int count) => _inner.Read(buffer, offset, count); public override int Read(Span buffer) => _inner.Read(buffer); public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => _inner.ReadAsync(buffer, offset, count, cancellationToken); public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) => _inner.ReadAsync(buffer, cancellationToken); public override long Seek(long offset, SeekOrigin origin) => _inner.Seek(offset, origin); public override void SetLength(long value) => _inner.SetLength(value); public override void Write(byte[] buffer, int offset, int count) => _inner.Write(buffer, offset, count); public override void Write(ReadOnlySpan buffer) => _inner.Write(buffer); public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => _inner.WriteAsync(buffer, offset, count, cancellationToken); public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => _inner.WriteAsync(buffer, cancellationToken); public override void Close() { _inner.Close(); base.Close(); } protected override void Dispose(bool disposing) { if (disposing) { _inner.Dispose(); } base.Dispose(disposing); } public override async ValueTask DisposeAsync() { await _inner.DisposeAsync().ConfigureAwait(false); await base.DisposeAsync().ConfigureAwait(false); } }