mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Remove warnings, replace BIP79 by Payjoin, Fix strange error in Accept loop
This commit is contained in:
@@ -101,7 +101,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Selenium", "Selenium")]
|
[Trait("Selenium", "Selenium")]
|
||||||
public async Task CanUseBIP79Client()
|
public async Task CanUsePayjoinViaUI()
|
||||||
{
|
{
|
||||||
using (var s = SeleniumTester.Create())
|
using (var s = SeleniumTester.Create())
|
||||||
{
|
{
|
||||||
@@ -223,7 +223,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanUseBIP79FeeCornerCase()
|
public async Task CanUsePayjoinFeeCornerCase()
|
||||||
{
|
{
|
||||||
using (var tester = ServerTester.Create())
|
using (var tester = ServerTester.Create())
|
||||||
{
|
{
|
||||||
@@ -392,7 +392,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = TestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanUseBIP79()
|
public async Task CanUsePayjoin()
|
||||||
{
|
{
|
||||||
using (var tester = ServerTester.Create())
|
using (var tester = ServerTester.Create())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ namespace BTCPayServer.Controllers
|
|||||||
.GetMetadataAsync<string>(derivationScheme.AccountDerivation,
|
.GetMetadataAsync<string>(derivationScheme.AccountDerivation,
|
||||||
WellknownMetadataKeys.MasterHDKey);
|
WellknownMetadataKeys.MasterHDKey);
|
||||||
|
|
||||||
return await SignWithSeed(walletId,
|
return SignWithSeed(walletId,
|
||||||
new SignWithSeedViewModel() {SeedOrKey = extKey, PSBT = psbt.ToBase64(), PayJoinEndpointUrl = vm.PayJoinEndpointUrl});
|
new SignWithSeedViewModel() {SeedOrKey = extKey, PSBT = psbt.ToBase64(), PayJoinEndpointUrl = vm.PayJoinEndpointUrl});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -611,7 +611,7 @@ namespace BTCPayServer.Controllers
|
|||||||
var extKey = await ExplorerClientProvider.GetExplorerClient(network)
|
var extKey = await ExplorerClientProvider.GetExplorerClient(network)
|
||||||
.GetMetadataAsync<string>(derivationScheme.AccountDerivation, WellknownMetadataKeys.MasterHDKey, cancellation);
|
.GetMetadataAsync<string>(derivationScheme.AccountDerivation, WellknownMetadataKeys.MasterHDKey, cancellation);
|
||||||
|
|
||||||
return await SignWithSeed(walletId, new SignWithSeedViewModel()
|
return SignWithSeed(walletId, new SignWithSeedViewModel()
|
||||||
{
|
{
|
||||||
PayJoinEndpointUrl = vm.PayJoinEndpointUrl,
|
PayJoinEndpointUrl = vm.PayJoinEndpointUrl,
|
||||||
SeedOrKey = extKey,
|
SeedOrKey = extKey,
|
||||||
@@ -701,7 +701,7 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("{walletId}/vault")]
|
[Route("{walletId}/vault")]
|
||||||
public async Task<IActionResult> WalletSendVault([ModelBinder(typeof(WalletIdModelBinder))]
|
public IActionResult WalletSendVault([ModelBinder(typeof(WalletIdModelBinder))]
|
||||||
WalletId walletId, WalletSendVaultModel model)
|
WalletId walletId, WalletSendVaultModel model)
|
||||||
{
|
{
|
||||||
return RedirectToWalletPSBTReady(model.PSBT, originalPsbt: model.OriginalPSBT, payJoinEndpointUrl: model.PayJoinEndpointUrl);
|
return RedirectToWalletPSBTReady(model.PSBT, originalPsbt: model.OriginalPSBT, payJoinEndpointUrl: model.PayJoinEndpointUrl);
|
||||||
@@ -777,7 +777,7 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("{walletId}/ledger")]
|
[Route("{walletId}/ledger")]
|
||||||
public async Task<IActionResult> SubmitLedger([ModelBinder(typeof(WalletIdModelBinder))]
|
public IActionResult SubmitLedger([ModelBinder(typeof(WalletIdModelBinder))]
|
||||||
WalletId walletId, WalletSendLedgerModel model)
|
WalletId walletId, WalletSendLedgerModel model)
|
||||||
{
|
{
|
||||||
return RedirectToWalletPSBTReady(model.PSBT);
|
return RedirectToWalletPSBTReady(model.PSBT);
|
||||||
@@ -795,7 +795,7 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("{walletId}/psbt/seed")]
|
[HttpPost("{walletId}/psbt/seed")]
|
||||||
public async Task<IActionResult> SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
|
public IActionResult SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
|
||||||
WalletId walletId, SignWithSeedViewModel viewModel)
|
WalletId walletId, SignWithSeedViewModel viewModel)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
{
|
{
|
||||||
class ProxyConnection
|
class ProxyConnection
|
||||||
{
|
{
|
||||||
|
public ServerContext ServerContext;
|
||||||
public Socket ClientSocket;
|
public Socket ClientSocket;
|
||||||
public Socket SocksSocket;
|
public Socket SocksSocket;
|
||||||
public CancellationToken CancellationToken;
|
public CancellationToken CancellationToken;
|
||||||
@@ -41,25 +42,41 @@ namespace BTCPayServer.HostedServices
|
|||||||
CancellationTokenSource.Dispose();
|
CancellationTokenSource.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ServerContext
|
||||||
|
{
|
||||||
|
public EndPoint SocksEndpoint;
|
||||||
|
public Socket ServerSocket;
|
||||||
|
public CancellationToken CancellationToken;
|
||||||
|
public int ConnectionCount;
|
||||||
|
}
|
||||||
private readonly BTCPayServerOptions _opts;
|
private readonly BTCPayServerOptions _opts;
|
||||||
|
|
||||||
public Socks5HttpProxyServer(Configuration.BTCPayServerOptions opts)
|
public Socks5HttpProxyServer(Configuration.BTCPayServerOptions opts)
|
||||||
{
|
{
|
||||||
_opts = opts;
|
_opts = opts;
|
||||||
}
|
}
|
||||||
private Socket _ServerSocket;
|
private ServerContext _ServerContext;
|
||||||
private CancellationTokenSource _Cts;
|
private CancellationTokenSource _Cts;
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_opts.SocksEndpoint is null)
|
if (_opts.SocksEndpoint is null || _ServerContext != null)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
_Cts = new CancellationTokenSource();
|
_Cts = new CancellationTokenSource();
|
||||||
_ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
_ServerSocket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
Port = ((IPEndPoint)(_ServerSocket.LocalEndPoint)).Port;
|
socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||||
|
Port = ((IPEndPoint)(socket.LocalEndPoint)).Port;
|
||||||
Uri = new Uri($"http://127.0.0.1:{Port}");
|
Uri = new Uri($"http://127.0.0.1:{Port}");
|
||||||
_ServerSocket.Listen(5);
|
socket.Listen(5);
|
||||||
_ServerSocket.BeginAccept(Accept, null);
|
_ServerContext = new ServerContext()
|
||||||
|
{
|
||||||
|
SocksEndpoint = _opts.SocksEndpoint,
|
||||||
|
ServerSocket = socket,
|
||||||
|
CancellationToken = _Cts.Token,
|
||||||
|
ConnectionCount = 0
|
||||||
|
};
|
||||||
|
socket.BeginAccept(Accept, _ServerContext);
|
||||||
Logs.PayServer.LogInformation($"Internal Socks HTTP Proxy listening at {Uri}");
|
Logs.PayServer.LogInformation($"Internal Socks HTTP Proxy listening at {Uri}");
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -67,47 +84,49 @@ namespace BTCPayServer.HostedServices
|
|||||||
public int Port { get; private set; }
|
public int Port { get; private set; }
|
||||||
public Uri Uri { get; private set; }
|
public Uri Uri { get; private set; }
|
||||||
|
|
||||||
void Accept(IAsyncResult ar)
|
static void Accept(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
|
var ctx = (ServerContext)ar.AsyncState;
|
||||||
Socket clientSocket = null;
|
Socket clientSocket = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
clientSocket = _ServerSocket.EndAccept(ar);
|
clientSocket = ctx.ServerSocket.EndAccept(ar);
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException e)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_Cts.IsCancellationRequested)
|
if (ctx.CancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Dispose(clientSocket);
|
Dispose(clientSocket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var toSocksProxy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
var toSocksProxy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
var connectionCts = CancellationTokenSource.CreateLinkedTokenSource(_Cts.Token);
|
var connectionCts = CancellationTokenSource.CreateLinkedTokenSource(ctx.CancellationToken);
|
||||||
toSocksProxy.BeginConnect(_opts.SocksEndpoint, ConnectToSocks, new ProxyConnection()
|
toSocksProxy.BeginConnect(ctx.SocksEndpoint, ConnectToSocks, new ProxyConnection()
|
||||||
{
|
{
|
||||||
|
ServerContext = ctx,
|
||||||
ClientSocket = clientSocket,
|
ClientSocket = clientSocket,
|
||||||
SocksSocket = toSocksProxy,
|
SocksSocket = toSocksProxy,
|
||||||
CancellationToken = connectionCts.Token,
|
CancellationToken = connectionCts.Token,
|
||||||
CancellationTokenSource = connectionCts
|
CancellationTokenSource = connectionCts
|
||||||
});
|
});
|
||||||
_ServerSocket.BeginAccept(Accept, null);
|
ctx.ServerSocket.BeginAccept(Accept, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectToSocks(IAsyncResult ar)
|
static void ConnectToSocks(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
var connection = (ProxyConnection)ar.AsyncState;
|
var connection = (ProxyConnection)ar.AsyncState;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
connection.SocksSocket.EndConnect(ar);
|
connection.SocksSocket.EndConnect(ar);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
connection.Dispose();
|
connection.Dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Interlocked.Increment(ref connectionCount);
|
Interlocked.Increment(ref connection.ServerContext.ConnectionCount);
|
||||||
var pipe = new Pipe(PipeOptions.Default);
|
var pipe = new Pipe(PipeOptions.Default);
|
||||||
CancellationTokenSource.CreateLinkedTokenSource(connection.CancellationToken);
|
CancellationTokenSource.CreateLinkedTokenSource(connection.CancellationToken);
|
||||||
var reading = FillPipeAsync(connection.ClientSocket, pipe.Writer, connection.CancellationToken)
|
var reading = FillPipeAsync(connection.ClientSocket, pipe.Writer, connection.CancellationToken)
|
||||||
@@ -118,12 +137,11 @@ namespace BTCPayServer.HostedServices
|
|||||||
.ContinueWith(_ =>
|
.ContinueWith(_ =>
|
||||||
{
|
{
|
||||||
connection.Dispose();
|
connection.Dispose();
|
||||||
Interlocked.Decrement(ref connectionCount);
|
Interlocked.Decrement(ref connection.ServerContext.ConnectionCount);
|
||||||
}, TaskScheduler.Default);
|
}, TaskScheduler.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int connectionCount = 0;
|
public int ConnectionCount => _ServerContext is ServerContext s ? s.ConnectionCount : 0;
|
||||||
public int ConnectionCount => connectionCount;
|
|
||||||
private static async Task ReadPipeAsync(Socket socksSocket, Socket clientSocket, PipeReader reader, CancellationToken cancellationToken)
|
private static async Task ReadPipeAsync(Socket socksSocket, Socket clientSocket, PipeReader reader, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
bool handshaked = false;
|
bool handshaked = false;
|
||||||
@@ -295,43 +313,28 @@ namespace BTCPayServer.HostedServices
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Allocate at least 512 bytes from the PipeWriter
|
|
||||||
Memory<byte> memory = writer.GetMemory(BufferSize);
|
Memory<byte> memory = writer.GetMemory(BufferSize);
|
||||||
try
|
int bytesRead = await socket.ReceiveAsync(memory, SocketFlags.None, cancellationToken);
|
||||||
|
if (bytesRead == 0)
|
||||||
{
|
{
|
||||||
int bytesRead = await socket.ReceiveAsync(memory, SocketFlags.None, cancellationToken);
|
|
||||||
if (bytesRead == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Tell the PipeWriter how much was read from the Socket
|
|
||||||
writer.Advance(bytesRead);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
//LogError(ex);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
writer.Advance(bytesRead);
|
||||||
// Make the data available to the PipeReader
|
|
||||||
FlushResult result = await writer.FlushAsync(cancellationToken);
|
FlushResult result = await writer.FlushAsync(cancellationToken);
|
||||||
|
|
||||||
if (result.IsCompleted)
|
if (result.IsCompleted)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the PipeReader that there's no more data coming
|
|
||||||
writer.Complete();
|
writer.Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_ServerSocket is Socket)
|
if (_ServerContext is ServerContext ctx)
|
||||||
{
|
{
|
||||||
_Cts.Cancel();
|
_Cts.Cancel();
|
||||||
Dispose(_ServerSocket);
|
Dispose(ctx.ServerSocket);
|
||||||
Logs.PayServer.LogInformation($"Internal Socks HTTP Proxy closed");
|
Logs.PayServer.LogInformation($"Internal Socks HTTP Proxy closed");
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|||||||
Reference in New Issue
Block a user