mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-10-13 22:51:39 +00:00
Added processor parameter for some methods in SocketApiClient to allow specific overriding behavior
This commit is contained in:
@@ -286,7 +286,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Get a new or existing socket connection
|
// Get a new or existing socket connection
|
||||||
var socketResult = await GetSocketConnection(url, subscription.Authenticated, false, ct, subscription.Topic, subscription.IndividualSubscriptionCount).ConfigureAwait(false);
|
var socketResult = await GetSocketConnection(url, subscription.Authenticated, false, ct, subscription, subscription.Topic, subscription.IndividualSubscriptionCount).ConfigureAwait(false);
|
||||||
if (!socketResult.Success)
|
if (!socketResult.Success)
|
||||||
return WebSocketResult.Fail<UpdateSubscription>(Exchange, socketResult.Error);
|
return WebSocketResult.Fail<UpdateSubscription>(Exchange, socketResult.Error);
|
||||||
|
|
||||||
@@ -309,7 +309,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
|
|
||||||
var needsConnecting = !socketConnection.Connected;
|
var needsConnecting = !socketConnection.Connected;
|
||||||
|
|
||||||
var connectResult = await ConnectIfNeededAsync(socketConnection, subscription.Authenticated, ct).ConfigureAwait(false);
|
var connectResult = await ConnectIfNeededAsync(socketConnection, subscription.Authenticated, ct, subscription).ConfigureAwait(false);
|
||||||
if (!connectResult.Success)
|
if (!connectResult.Success)
|
||||||
return WebSocketResult.Fail<UpdateSubscription>(Exchange, connectResult.Error!);
|
return WebSocketResult.Fail<UpdateSubscription>(Exchange, connectResult.Error!);
|
||||||
|
|
||||||
@@ -482,7 +482,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
await semaphoreSlim.WaitAsync().ConfigureAwait(false);
|
await semaphoreSlim.WaitAsync().ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var socketResult = await GetSocketConnection(url, query.Authenticated, true, ct).ConfigureAwait(false);
|
var socketResult = await GetSocketConnection(url, query.Authenticated, true, ct, processor: query).ConfigureAwait(false);
|
||||||
if (!socketResult.Success)
|
if (!socketResult.Success)
|
||||||
return QueryResult.Fail<THandlerResponse>(Exchange, socketResult.Error);
|
return QueryResult.Fail<THandlerResponse>(Exchange, socketResult.Error);
|
||||||
|
|
||||||
@@ -495,7 +495,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
released = true;
|
released = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var connectResult = await ConnectIfNeededAsync(socketConnection, query.Authenticated, ct).ConfigureAwait(false);
|
var connectResult = await ConnectIfNeededAsync(socketConnection, query.Authenticated, ct, query).ConfigureAwait(false);
|
||||||
if (!connectResult.Success)
|
if (!connectResult.Success)
|
||||||
return QueryResult.Fail<THandlerResponse>(Exchange, connectResult.Error!);
|
return QueryResult.Fail<THandlerResponse>(Exchange, connectResult.Error!);
|
||||||
}
|
}
|
||||||
@@ -524,7 +524,18 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// <param name="authenticated">Whether the socket should authenticated</param>
|
/// <param name="authenticated">Whether the socket should authenticated</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual async Task<CallResult> ConnectIfNeededAsync(ISocketConnection socket, bool authenticated, CancellationToken ct)
|
protected virtual Task<CallResult> ConnectIfNeededAsync(ISocketConnection socket, bool authenticated, CancellationToken ct)
|
||||||
|
=> ConnectIfNeededAsync(socket, authenticated, ct, null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a socket needs to be connected and does so if needed. Also authenticates on the socket if needed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socket">The connection to check</param>
|
||||||
|
/// <param name="authenticated">Whether the socket should authenticated</param>
|
||||||
|
/// <param name="processor">The message processor requesting a connection</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected virtual async Task<CallResult> ConnectIfNeededAsync(ISocketConnection socket, bool authenticated, CancellationToken ct, IMessageProcessor? processor)
|
||||||
{
|
{
|
||||||
if (socket.Connected)
|
if (socket.Connected)
|
||||||
return CallResult.Ok();
|
return CallResult.Ok();
|
||||||
@@ -539,7 +550,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
if (socket is not SocketConnection sc)
|
if (socket is not SocketConnection sc)
|
||||||
throw new InvalidOperationException("HighPerfSocketConnection not supported for authentication");
|
throw new InvalidOperationException("HighPerfSocketConnection not supported for authentication");
|
||||||
|
|
||||||
var result = await AuthenticateSocketAsync(sc).ConfigureAwait(false);
|
var result = await AuthenticateSocketAsync(sc, processor).ConfigureAwait(false);
|
||||||
if (!result.Success)
|
if (!result.Success)
|
||||||
await socket.CloseAsync().ConfigureAwait(false);
|
await socket.CloseAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
@@ -551,13 +562,22 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="socket">Socket to authenticate</param>
|
/// <param name="socket">Socket to authenticate</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual async Task<CallResult> AuthenticateSocketAsync(SocketConnection socket)
|
public virtual Task<CallResult> AuthenticateSocketAsync(SocketConnection socket)
|
||||||
|
=> AuthenticateSocketAsync(socket, null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Authenticate a socket connection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socket">Socket to authenticate</param>
|
||||||
|
/// <param name="processor">The message processor requesting authentication</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual async Task<CallResult> AuthenticateSocketAsync(SocketConnection socket, IMessageProcessor? processor)
|
||||||
{
|
{
|
||||||
if (GetAuthenticationProvider() == null)
|
if (GetAuthenticationProvider() == null)
|
||||||
return CallResult.Fail(new NoApiCredentialsError());
|
return CallResult.Fail(new NoApiCredentialsError());
|
||||||
|
|
||||||
_logger.AttemptingToAuthenticate(socket.SocketId);
|
_logger.AttemptingToAuthenticate(socket.SocketId);
|
||||||
var authRequest = await GetAuthenticationRequestAsync(socket).ConfigureAwait(false);
|
var authRequest = await GetAuthenticationRequestAsync(socket, processor).ConfigureAwait(false);
|
||||||
if (authRequest != null)
|
if (authRequest != null)
|
||||||
{
|
{
|
||||||
var result = await socket.SendAndWaitQueryAsync(authRequest).ConfigureAwait(false);
|
var result = await socket.SendAndWaitQueryAsync(authRequest).ConfigureAwait(false);
|
||||||
@@ -578,6 +598,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
return CallResult.Ok();
|
return CallResult.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should return the request which can be used to authenticate a socket connection
|
/// Should return the request which can be used to authenticate a socket connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -585,6 +606,13 @@ namespace CryptoExchange.Net.Clients
|
|||||||
protected internal virtual Task<Query?> GetAuthenticationRequestAsync(SocketConnection connection) =>
|
protected internal virtual Task<Query?> GetAuthenticationRequestAsync(SocketConnection connection) =>
|
||||||
Task.FromResult(GetAuthenticationProvider()!.GetAuthenticationQuery(this, connection));
|
Task.FromResult(GetAuthenticationProvider()!.GetAuthenticationQuery(this, connection));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should return the request which can be used to authenticate a socket connection
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected internal virtual Task<Query?> GetAuthenticationRequestAsync(SocketConnection connection, IMessageProcessor? processor) =>
|
||||||
|
GetAuthenticationRequestAsync(connection);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a system subscription. Used for example to reply to ping requests
|
/// Adds a system subscription. Used for example to reply to ping requests
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -642,6 +670,18 @@ namespace CryptoExchange.Net.Clients
|
|||||||
&& (AllowTopicsOnTheSameConnection || !connection.Topics.Contains(topic));
|
&& (AllowTopicsOnTheSameConnection || !connection.Topics.Contains(topic));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the connection can be used for a new subscription or query with the provided parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection">The connection to check</param>
|
||||||
|
/// <param name="address">The address set by the request</param>
|
||||||
|
/// <param name="authenticated">Whether the request needs an authenticated connection</param>
|
||||||
|
/// <param name="processor">The processor requesting a connection</param>
|
||||||
|
/// <param name="topic">Topic of the request</param>
|
||||||
|
/// <returns>True if connection can be used</returns>
|
||||||
|
protected virtual bool ConnectionCanBeUsedFor(SocketConnection connection, string address, bool authenticated, IMessageProcessor? processor, string? topic = null)
|
||||||
|
=> ConnectionCanBeUsedFor(connection, address, authenticated, topic);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a connection for a new subscription or query. Can be an existing if there are open position or a new one.
|
/// Gets a connection for a new subscription or query. Can be an existing if there are open position or a new one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -652,15 +692,36 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// <param name="topic">The subscription topic, can be provided when multiple of the same topics are not allowed on a connection</param>
|
/// <param name="topic">The subscription topic, can be provided when multiple of the same topics are not allowed on a connection</param>
|
||||||
/// <param name="individualSubscriptionCount">The number of individual subscriptions in this subscribe request</param>
|
/// <param name="individualSubscriptionCount">The number of individual subscriptions in this subscribe request</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual async Task<CallResult<SocketConnection>> GetSocketConnection(
|
protected virtual Task<CallResult<SocketConnection>> GetSocketConnection(
|
||||||
string address,
|
string address,
|
||||||
bool authenticated,
|
bool authenticated,
|
||||||
bool dedicatedRequestConnection,
|
bool dedicatedRequestConnection,
|
||||||
CancellationToken ct,
|
CancellationToken ct,
|
||||||
string? topic = null,
|
string? topic = null,
|
||||||
int individualSubscriptionCount = 1)
|
int individualSubscriptionCount = 1)
|
||||||
|
=> GetSocketConnection(address, authenticated, dedicatedRequestConnection, ct, null, topic, individualSubscriptionCount);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a connection for a new subscription or query. Can be an existing if there are open position or a new one.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The address the socket is for</param>
|
||||||
|
/// <param name="authenticated">Whether the socket should be authenticated</param>
|
||||||
|
/// <param name="dedicatedRequestConnection">Whether a dedicated request connection should be returned</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
/// <param name="topic">The subscription topic, can be provided when multiple of the same topics are not allowed on a connection</param>
|
||||||
|
/// <param name="individualSubscriptionCount">The number of individual subscriptions in this subscribe request</param>
|
||||||
|
/// <param name="processor">The processor requesting a connection</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected virtual async Task<CallResult<SocketConnection>> GetSocketConnection(
|
||||||
|
string address,
|
||||||
|
bool authenticated,
|
||||||
|
bool dedicatedRequestConnection,
|
||||||
|
CancellationToken ct,
|
||||||
|
IMessageProcessor? processor,
|
||||||
|
string? topic = null,
|
||||||
|
int individualSubscriptionCount = 1)
|
||||||
{
|
{
|
||||||
var socketQuery = _socketConnections.Where(s => ConnectionCanBeUsedFor(s.Value, address, authenticated, topic)).Select(x => x.Value); // Don't ToList this so the query is executed again when called
|
var socketQuery = _socketConnections.Where(s => ConnectionCanBeUsedFor(s.Value, address, authenticated, processor, topic)).Select(x => x.Value); // Don't ToList this so the query is executed again when called
|
||||||
|
|
||||||
// If all current socket connections are reconnecting or resubscribing wait for that to finish as we can probably use the existing connection
|
// If all current socket connections are reconnecting or resubscribing wait for that to finish as we can probably use the existing connection
|
||||||
var delayStart = DateTime.UtcNow;
|
var delayStart = DateTime.UtcNow;
|
||||||
|
|||||||
Reference in New Issue
Block a user