btcpayserver/BTCPayServer/Services/SocketFactory.cs

121 lines
3.9 KiB
C#
Raw Normal View History

2020-03-13 15:10:26 +01:00
using System;
using System.Linq;
using NBitcoin;
using System.Net;
2020-01-06 13:57:32 +01:00
using System.Net.Http;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Configuration;
2020-01-06 13:57:32 +01:00
using com.LandonKey.SocksWebProxy;
using com.LandonKey.SocksWebProxy.Proxy;
2020-03-13 16:52:50 +01:00
using Microsoft.Extensions.Logging;
using NBitcoin.Logging;
using NBitcoin.Protocol.Connectors;
using NBitcoin.Protocol;
namespace BTCPayServer.Services
{
public class SocketFactory
{
private readonly BTCPayServerOptions _options;
2020-03-13 15:10:26 +01:00
public readonly Task<HttpClient> SocksClient;
public SocketFactory(BTCPayServerOptions options)
{
_options = options;
2020-01-06 13:57:32 +01:00
SocksClient = CreateHttpClientUsingSocks();
}
2020-03-13 15:10:26 +01:00
2019-03-31 13:16:05 +09:00
public async Task<Socket> ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
{
DefaultEndpointConnector connector = new DefaultEndpointConnector();
NodeConnectionParameters connectionParameters = new NodeConnectionParameters();
if (_options.SocksEndpoint != null)
{
connectionParameters.TemplateBehaviors.Add(new NBitcoin.Protocol.Behaviors.SocksSettingsBehavior()
{
SocksEndpoint = _options.SocksEndpoint
});
}
2020-03-13 15:10:26 +01:00
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
try
{
await connector.ConnectSocket(socket, endPoint, connectionParameters, cancellationToken);
}
catch
{
SafeCloseSocket(socket);
}
2020-03-13 15:10:26 +01:00
return socket;
}
internal static void SafeCloseSocket(System.Net.Sockets.Socket socket)
{
try
{
socket.Shutdown(SocketShutdown.Both);
}
catch
{
}
2020-03-13 15:10:26 +01:00
try
{
socket.Dispose();
}
catch
{
}
}
2020-01-06 13:57:32 +01:00
2020-03-13 15:10:26 +01:00
private Task<HttpClient> CreateHttpClientUsingSocks()
2020-01-06 13:57:32 +01:00
{
2020-03-13 15:10:26 +01:00
return Task.Run(() =>
2020-01-06 13:57:32 +01:00
{
2020-03-13 16:52:50 +01:00
try
2020-01-06 13:57:32 +01:00
{
2020-03-13 16:52:50 +01:00
var proxyConfig = new ProxyConfig() {Version = ProxyConfig.SocksVersion.Five};
switch (_options.SocksEndpoint)
{
case null:
return null;
case IPEndPoint ipEndPoint:
proxyConfig.SocksPort = ipEndPoint.Port;
proxyConfig.SocksAddress = ipEndPoint.Address;
break;
case DnsEndPoint dnsEndPoint:
2020-03-13 15:10:26 +01:00
proxyConfig.SocksPort = dnsEndPoint.Port;
var ip = Dns.GetHostEntry(dnsEndPoint.Host).AddressList
.SingleOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork);
if (ip == null)
{
2020-03-13 16:52:50 +01:00
Logs.Utils.LogWarning( $"Could not find ip for {dnsEndPoint.Host}");
2020-03-13 15:10:26 +01:00
return null;
}
proxyConfig.SocksAddress = ip;
break;
2020-03-13 16:52:50 +01:00
default:
2020-03-13 15:10:26 +01:00
return null;
2020-03-13 16:52:50 +01:00
}
Logs.Utils.LogWarning( $"Created socks proxied http client!");
return new HttpClient(new HttpClientHandler
{
Proxy = new SocksWebProxy(proxyConfig), UseProxy = true
});
}
catch (Exception e)
{
Logs.Utils.LogError(e, "Could not create Tor client");
return null;
2020-03-13 15:10:26 +01:00
}
2020-01-06 13:57:32 +01:00
});
}
}
}