fix rcon issue
This commit is contained in:
parent
3ad4aa2196
commit
ff0d22c142
@ -456,7 +456,7 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
|
|
||||||
private void GetDvarAsync(Server server, string dvarName, Delegate onCompleted)
|
private void GetDvarAsync(Server server, string dvarName, Delegate onCompleted)
|
||||||
{
|
{
|
||||||
Task.Run<Task>(async () =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
var tokenSource = new CancellationTokenSource();
|
var tokenSource = new CancellationTokenSource();
|
||||||
tokenSource.CancelAfter(TimeSpan.FromSeconds(5));
|
tokenSource.CancelAfter(TimeSpan.FromSeconds(5));
|
||||||
@ -464,14 +464,14 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
var success = true;
|
var success = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = (await server.GetDvarAsync<string>(dvarName, token: tokenSource.Token)).Value;
|
result = server.GetDvarAsync<string>(dvarName, token: tokenSource.Token).GetAwaiter().GetResult().Value;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _onProcessing.WaitAsync();
|
_onProcessing.Wait();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
onCompleted.DynamicInvoke(JsValue.Undefined,
|
onCompleted.DynamicInvoke(JsValue.Undefined,
|
||||||
@ -495,7 +495,7 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
}
|
}
|
||||||
private void SetDvarAsync(Server server, string dvarName, string dvarValue, Delegate onCompleted)
|
private void SetDvarAsync(Server server, string dvarName, string dvarValue, Delegate onCompleted)
|
||||||
{
|
{
|
||||||
Task.Run<Task>(async () =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
var tokenSource = new CancellationTokenSource();
|
var tokenSource = new CancellationTokenSource();
|
||||||
tokenSource.CancelAfter(TimeSpan.FromSeconds(5));
|
tokenSource.CancelAfter(TimeSpan.FromSeconds(5));
|
||||||
@ -503,14 +503,14 @@ namespace IW4MAdmin.Application.Misc
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await server.SetDvarAsync(dvarName, dvarValue, tokenSource.Token);
|
server.SetDvarAsync(dvarName, dvarValue, tokenSource.Token).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _onProcessing.WaitAsync();
|
_onProcessing.Wait();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
onCompleted.DynamicInvoke(JsValue.Undefined,
|
onCompleted.DynamicInvoke(JsValue.Undefined,
|
||||||
|
@ -33,7 +33,8 @@ namespace Integrations.Cod
|
|||||||
private readonly Encoding _gameEncoding;
|
private readonly Encoding _gameEncoding;
|
||||||
private readonly int _retryAttempts;
|
private readonly int _retryAttempts;
|
||||||
|
|
||||||
public CodRConConnection(IPEndPoint ipEndpoint, string password, ILogger<CodRConConnection> log, Encoding gameEncoding, int retryAttempts)
|
public CodRConConnection(IPEndPoint ipEndpoint, string password, ILogger<CodRConConnection> log,
|
||||||
|
Encoding gameEncoding, int retryAttempts)
|
||||||
{
|
{
|
||||||
RConPassword = password;
|
RConPassword = password;
|
||||||
_gameEncoding = gameEncoding;
|
_gameEncoding = gameEncoding;
|
||||||
@ -66,21 +67,31 @@ namespace Integrations.Cod
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
using (LogContext.PushProperty("Server", Endpoint.ToString()))
|
||||||
|
{
|
||||||
|
_log.LogDebug("Releasing OnComplete {Count}", ActiveQueries[Endpoint].OnComplete.CurrentCount);
|
||||||
|
}
|
||||||
|
|
||||||
if (ActiveQueries[Endpoint].OnComplete.CurrentCount == 0)
|
if (ActiveQueries[Endpoint].OnComplete.CurrentCount == 0)
|
||||||
{
|
{
|
||||||
ActiveQueries[Endpoint].OnComplete.Release();
|
ActiveQueries[Endpoint].OnComplete.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string[]> SendQueryAsyncInternal(StaticHelpers.QueryType type, string parameters = "", CancellationToken token = default)
|
private async Task<string[]> SendQueryAsyncInternal(StaticHelpers.QueryType type, string parameters = "",
|
||||||
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (!ActiveQueries.ContainsKey(Endpoint))
|
if (!ActiveQueries.ContainsKey(Endpoint))
|
||||||
{
|
{
|
||||||
ActiveQueries.TryAdd(Endpoint, new ConnectionState());
|
ActiveQueries.TryAdd(Endpoint, new ConnectionState());
|
||||||
}
|
}
|
||||||
|
|
||||||
var connectionState = ActiveQueries[Endpoint];
|
if (!ActiveQueries.TryGetValue(Endpoint, out var connectionState))
|
||||||
|
{
|
||||||
|
_log.LogError("Could not retrieve connection state");
|
||||||
|
throw new InvalidOperationException("Could not get connection state");
|
||||||
|
}
|
||||||
|
|
||||||
_log.LogDebug("Waiting for semaphore to be released [{Endpoint}]", Endpoint);
|
_log.LogDebug("Waiting for semaphore to be released [{Endpoint}]", Endpoint);
|
||||||
|
|
||||||
@ -91,6 +102,8 @@ namespace Integrations.Cod
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
_log.LogDebug("OnComplete did not complete before timeout {Count}",
|
||||||
|
connectionState.OnComplete.CurrentCount);
|
||||||
throw new RConException("Timed out waiting for access to rcon socket");
|
throw new RConException("Timed out waiting for access to rcon socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,16 +113,20 @@ namespace Integrations.Cod
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Delay(_config.FloodProtectInterval - (int)timeSinceLastQuery, token);
|
var delay = _config.FloodProtectInterval - (int)timeSinceLastQuery;
|
||||||
|
_log.LogDebug("Delaying for {Delay}ms", delay);
|
||||||
|
await Task.Delay(delay, token);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
_log.LogDebug("Waiting for flood protect did not complete before timeout timeout {Count}",
|
||||||
|
connectionState.OnComplete.CurrentCount);
|
||||||
throw new RConException("Timed out waiting for flood protect to expire");
|
throw new RConException("Timed out waiting for flood protect to expire");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.LogDebug("Semaphore has been released [{Endpoint}]", Endpoint);
|
_log.LogDebug("Semaphore has been released [{Endpoint}]", Endpoint);
|
||||||
_log.LogDebug("Query {@QueryInfo}", new { endpoint=Endpoint.ToString(), type, parameters });
|
_log.LogDebug("Query {@QueryInfo}", new { endpoint = Endpoint.ToString(), type, parameters });
|
||||||
|
|
||||||
byte[] payload = null;
|
byte[] payload = null;
|
||||||
var waitForResponse = _config.WaitForResponse;
|
var waitForResponse = _config.WaitForResponse;
|
||||||
@ -163,7 +180,6 @@ namespace Integrations.Cod
|
|||||||
// e.g: emoji -> windows-1252
|
// e.g: emoji -> windows-1252
|
||||||
catch (OverflowException ex)
|
catch (OverflowException ex)
|
||||||
{
|
{
|
||||||
|
|
||||||
using (LogContext.PushProperty("Server", Endpoint.ToString()))
|
using (LogContext.PushProperty("Server", Endpoint.ToString()))
|
||||||
{
|
{
|
||||||
_log.LogError(ex, "Could not convert RCon data payload to desired encoding {Encoding} {Params}",
|
_log.LogError(ex, "Could not convert RCon data payload to desired encoding {Encoding} {Params}",
|
||||||
@ -181,8 +197,8 @@ namespace Integrations.Cod
|
|||||||
using (LogContext.PushProperty("Server", Endpoint.ToString()))
|
using (LogContext.PushProperty("Server", Endpoint.ToString()))
|
||||||
{
|
{
|
||||||
_log.LogInformation(
|
_log.LogInformation(
|
||||||
"Retrying RCon message ({ConnectionAttempts}/{AllowedConnectionFailures} attempts) with parameters {Payload}",
|
"Retrying RCon message ({ConnectionAttempts}/{AllowedConnectionFailures} attempts) with parameters {Payload}",
|
||||||
connectionState.ConnectionAttempts,
|
connectionState.ConnectionAttempts,
|
||||||
_retryAttempts, parameters);
|
_retryAttempts, parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,6 +217,7 @@ namespace Integrations.Cod
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
_log.LogDebug("OnSent did not complete in time");
|
||||||
throw new RConException("Timed out waiting for access to RCon send socket");
|
throw new RConException("Timed out waiting for access to RCon send socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,14 +228,13 @@ namespace Integrations.Cod
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
throw new RConException("Timed out waiting for access to RCon receive socket");
|
_log.LogDebug("OnReceived did not complete in time");
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (connectionState.OnSentData.CurrentCount == 0)
|
if (connectionState.OnSentData.CurrentCount == 0)
|
||||||
{
|
{
|
||||||
connectionState.OnSentData.Release();
|
connectionState.OnSentData.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new RConException("Timed out waiting for access to RCon receive socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionState.SendEventArgs.UserToken = new ConnectionUserToken
|
connectionState.SendEventArgs.UserToken = new ConnectionUserToken
|
||||||
@ -242,6 +258,7 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
if ((response?.Length == 0 || response[0].Length == 0) && waitForResponse)
|
if ((response?.Length == 0 || response[0].Length == 0) && waitForResponse)
|
||||||
{
|
{
|
||||||
|
_log.LogDebug("0 bytes received from rcon request");
|
||||||
throw new RConException("Expected response but got 0 bytes back");
|
throw new RConException("Expected response but got 0 bytes back");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +269,7 @@ namespace Integrations.Cod
|
|||||||
{
|
{
|
||||||
// if we timed out due to the cancellation token,
|
// if we timed out due to the cancellation token,
|
||||||
// we don't want to count that as an attempt
|
// we don't want to count that as an attempt
|
||||||
|
_log.LogDebug("OperationCanceledException when waiting for payload send to complete");
|
||||||
connectionState.ConnectionAttempts = 0;
|
connectionState.ConnectionAttempts = 0;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -265,7 +283,8 @@ namespace Integrations.Cod
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
return Array.Empty<string>();
|
_log.LogDebug("OperationCancelled while waiting for retry");
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto retrySend;
|
goto retrySend;
|
||||||
@ -311,11 +330,13 @@ namespace Integrations.Cod
|
|||||||
return Array.Empty<string>();
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var responseString = type == StaticHelpers.QueryType.COMMAND_STATUS ?
|
var responseString = type == StaticHelpers.QueryType.COMMAND_STATUS
|
||||||
ReassembleSegmentedStatus(response) : RecombineMessages(response);
|
? ReassembleSegmentedStatus(response)
|
||||||
|
: RecombineMessages(response);
|
||||||
|
|
||||||
// note: not all games respond if the password is wrong or not set
|
// note: not all games respond if the password is wrong or not set
|
||||||
if (responseString.Contains("Invalid password") || responseString.Contains("rconpassword"))
|
if (responseString.Contains("Invalid password", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
responseString.Contains("rconpassword"))
|
||||||
{
|
{
|
||||||
throw new RConException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_INVALID"]);
|
throw new RConException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_INVALID"]);
|
||||||
}
|
}
|
||||||
@ -327,11 +348,14 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
if (responseString.Contains(_config.ServerNotRunningResponse))
|
if (responseString.Contains(_config.ServerNotRunningResponse))
|
||||||
{
|
{
|
||||||
throw new ServerException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_NOT_RUNNING"].FormatExt(Endpoint.ToString()));
|
throw new ServerException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_NOT_RUNNING"]
|
||||||
|
.FormatExt(Endpoint.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var responseHeaderMatch = Regex.Match(responseString, _config.CommandPrefixes.RConResponse).Value;
|
var responseHeaderMatch = Regex.Match(responseString, _config.CommandPrefixes.RConResponse).Value;
|
||||||
var headerSplit = responseString.Split(type == StaticHelpers.QueryType.GET_INFO ? _config.CommandPrefixes.RconGetInfoResponseHeader : responseHeaderMatch);
|
var headerSplit = responseString.Split(type == StaticHelpers.QueryType.GET_INFO
|
||||||
|
? _config.CommandPrefixes.RconGetInfoResponseHeader
|
||||||
|
: responseHeaderMatch);
|
||||||
|
|
||||||
if (headerSplit.Length != 2)
|
if (headerSplit.Length != 2)
|
||||||
{
|
{
|
||||||
@ -369,7 +393,8 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
splitStatusStrings.Add(responseString.Replace(_config.CommandPrefixes.RConResponse, "").TrimEnd('\0'));
|
splitStatusStrings.Add(responseString.Replace(_config.CommandPrefixes.RConResponse, "")
|
||||||
|
.TrimEnd('\0'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,8 +421,10 @@ namespace Integrations.Cod
|
|||||||
{
|
{
|
||||||
message = message.Replace(_config.CommandPrefixes.RConResponse, "");
|
message = message.Replace(_config.CommandPrefixes.RConResponse, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append(message);
|
builder.Append(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append('\n');
|
builder.Append('\n');
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
@ -410,6 +437,7 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
if (rconSocket is null)
|
if (rconSocket is null)
|
||||||
{
|
{
|
||||||
|
_log.LogDebug("Invalid state");
|
||||||
throw new InvalidOperationException("State is not valid for socket operation");
|
throw new InvalidOperationException("State is not valid for socket operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +447,7 @@ namespace Integrations.Cod
|
|||||||
// setup the event handlers only once because we're reusing the event args
|
// setup the event handlers only once because we're reusing the event args
|
||||||
connectionState.SendEventArgs.Completed += OnDataSent;
|
connectionState.SendEventArgs.Completed += OnDataSent;
|
||||||
connectionState.ReceiveEventArgs.Completed += OnDataReceived;
|
connectionState.ReceiveEventArgs.Completed += OnDataReceived;
|
||||||
|
connectionState.ReceiveEventArgs.UserToken = connectionState.SendEventArgs.UserToken;
|
||||||
connectionState.SendEventArgs.RemoteEndPoint = Endpoint;
|
connectionState.SendEventArgs.RemoteEndPoint = Endpoint;
|
||||||
connectionState.ReceiveEventArgs.RemoteEndPoint = Endpoint;
|
connectionState.ReceiveEventArgs.RemoteEndPoint = Endpoint;
|
||||||
connectionState.ReceiveEventArgs.DisconnectReuseSocket = true;
|
connectionState.ReceiveEventArgs.DisconnectReuseSocket = true;
|
||||||
@ -435,15 +464,15 @@ namespace Integrations.Cod
|
|||||||
// the send has not been completed asynchronously
|
// the send has not been completed asynchronously
|
||||||
// this really shouldn't ever happen because it's UDP
|
// this really shouldn't ever happen because it's UDP
|
||||||
var complete = await connectionState.OnSentData.WaitAsync(StaticHelpers.SocketTimeout(4), token);
|
var complete = await connectionState.OnSentData.WaitAsync(StaticHelpers.SocketTimeout(4), token);
|
||||||
|
|
||||||
if (!complete)
|
if (!complete)
|
||||||
{
|
{
|
||||||
using(LogContext.PushProperty("Server", Endpoint.ToString()))
|
using (LogContext.PushProperty("Server", Endpoint.ToString()))
|
||||||
{
|
{
|
||||||
_log.LogWarning("Socket timed out while sending RCon data on attempt {Attempt}",
|
_log.LogWarning("Socket timed out while sending RCon data on attempt {Attempt}",
|
||||||
connectionState.ConnectionAttempts);
|
connectionState.ConnectionAttempts);
|
||||||
}
|
}
|
||||||
|
|
||||||
rconSocket.Close();
|
rconSocket.Close();
|
||||||
throw new NetworkException("Timed out sending RCon data", rconSocket);
|
throw new NetworkException("Timed out sending RCon data", rconSocket);
|
||||||
}
|
}
|
||||||
@ -461,7 +490,8 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
if (receiveDataPending)
|
if (receiveDataPending)
|
||||||
{
|
{
|
||||||
_log.LogDebug("Waiting to asynchronously receive data on attempt #{ConnectionAttempts}", connectionState.ConnectionAttempts);
|
_log.LogDebug("Waiting to asynchronously receive data on attempt #{ConnectionAttempts}",
|
||||||
|
connectionState.ConnectionAttempts);
|
||||||
|
|
||||||
var completed = false;
|
var completed = false;
|
||||||
|
|
||||||
@ -493,6 +523,7 @@ namespace Integrations.Cod
|
|||||||
}
|
}
|
||||||
|
|
||||||
rconSocket.Close();
|
rconSocket.Close();
|
||||||
|
_log.LogDebug("OnDataReceived did not complete in allocated time");
|
||||||
throw new NetworkException("Timed out receiving RCon response", rconSocket);
|
throw new NetworkException("Timed out receiving RCon response", rconSocket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -521,13 +552,14 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
private void OnDataReceived(object sender, SocketAsyncEventArgs e)
|
private void OnDataReceived(object sender, SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
_log.LogDebug("Read {BytesTransferred} bytes from {Endpoint}", e.BytesTransferred, e.RemoteEndPoint?.ToString());
|
_log.LogDebug("Read {BytesTransferred} bytes from {Endpoint}", e.BytesTransferred,
|
||||||
|
e.RemoteEndPoint?.ToString());
|
||||||
|
|
||||||
// this occurs when we close the socket
|
// this occurs when we close the socket
|
||||||
if (e.BytesTransferred == 0)
|
if (e.BytesTransferred == 0)
|
||||||
{
|
{
|
||||||
_log.LogDebug("No bytes were transmitted so the connection was probably closed");
|
_log.LogDebug("No bytes were transmitted so the connection was probably closed");
|
||||||
|
|
||||||
var semaphore = ActiveQueries[Endpoint].OnReceivedData;
|
var semaphore = ActiveQueries[Endpoint].OnReceivedData;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -545,7 +577,7 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var state = ActiveQueries[Endpoint];
|
var state = ActiveQueries[Endpoint];
|
||||||
var cancellationRequested = ((ConnectionUserToken)e.UserToken)?.CancellationToken.IsCancellationRequested ??
|
var cancellationRequested = ((ConnectionUserToken)e.UserToken)?.CancellationToken.IsCancellationRequested ??
|
||||||
false;
|
false;
|
||||||
@ -566,12 +598,12 @@ namespace Integrations.Cod
|
|||||||
// ignored because we can have the socket operation cancelled (which releases the semaphore) but
|
// ignored because we can have the socket operation cancelled (which releases the semaphore) but
|
||||||
// this thread is not notified because it's an event
|
// this thread is not notified because it's an event
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.BytesReadPerSegment.Add(e.BytesTransferred);
|
state.BytesReadPerSegment.Add(e.BytesTransferred);
|
||||||
|
|
||||||
// I don't even want to know why this works for getting more data from Cod4x
|
// I don't even want to know why this works for getting more data from Cod4x
|
||||||
// but I'm leaving it in here as long as it doesn't break anything.
|
// but I'm leaving it in here as long as it doesn't break anything.
|
||||||
// it's very stupid...
|
// it's very stupid...
|
||||||
@ -582,7 +614,7 @@ namespace Integrations.Cod
|
|||||||
var totalBytesTransferred = e.BytesTransferred;
|
var totalBytesTransferred = e.BytesTransferred;
|
||||||
_log.LogDebug("{Total} total bytes transferred with {Available} bytes remaining", totalBytesTransferred,
|
_log.LogDebug("{Total} total bytes transferred with {Available} bytes remaining", totalBytesTransferred,
|
||||||
sock.Available);
|
sock.Available);
|
||||||
|
|
||||||
// we still have available data so the payload was segmented
|
// we still have available data so the payload was segmented
|
||||||
while (sock.Available > 0)
|
while (sock.Available > 0)
|
||||||
{
|
{
|
||||||
@ -596,17 +628,17 @@ namespace Integrations.Cod
|
|||||||
bufferSpaceAvailable);
|
bufferSpaceAvailable);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, totalBytesTransferred, sock.Available);
|
state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, totalBytesTransferred, sock.Available);
|
||||||
if (sock.ReceiveAsync(state.ReceiveEventArgs))
|
if (sock.ReceiveAsync(state.ReceiveEventArgs))
|
||||||
{
|
{
|
||||||
_log.LogDebug("Remaining bytes are async");
|
_log.LogDebug("Remaining bytes are async");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.LogDebug("Read {BytesTransferred} synchronous bytes from {Endpoint}",
|
_log.LogDebug("Read {BytesTransferred} synchronous bytes from {Endpoint}",
|
||||||
state.ReceiveEventArgs.BytesTransferred, e.RemoteEndPoint?.ToString());
|
state.ReceiveEventArgs.BytesTransferred, e.RemoteEndPoint?.ToString());
|
||||||
|
|
||||||
// we need to increment this here because the callback isn't executed if there's no pending IO
|
// we need to increment this here because the callback isn't executed if there's no pending IO
|
||||||
state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred);
|
state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred);
|
||||||
totalBytesTransferred += state.ReceiveEventArgs.BytesTransferred;
|
totalBytesTransferred += state.ReceiveEventArgs.BytesTransferred;
|
||||||
@ -638,8 +670,9 @@ namespace Integrations.Cod
|
|||||||
|
|
||||||
private void OnDataSent(object sender, SocketAsyncEventArgs e)
|
private void OnDataSent(object sender, SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
_log.LogDebug("Sent {ByteCount} bytes to {Endpoint}", e.Buffer?.Length, e.ConnectSocket?.RemoteEndPoint?.ToString());
|
_log.LogDebug("Sent {ByteCount} bytes to {Endpoint}", e.Buffer?.Length,
|
||||||
|
e.ConnectSocket?.RemoteEndPoint?.ToString());
|
||||||
|
|
||||||
var semaphore = ActiveQueries[Endpoint].OnSentData;
|
var semaphore = ActiveQueries[Endpoint].OnSentData;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,7 @@ namespace Integrations.Cod
|
|||||||
public int ConnectionAttempts { get; set; }
|
public int ConnectionAttempts { get; set; }
|
||||||
private const int BufferSize = 16384;
|
private const int BufferSize = 16384;
|
||||||
public readonly byte[] ReceiveBuffer = new byte[BufferSize];
|
public readonly byte[] ReceiveBuffer = new byte[BufferSize];
|
||||||
public readonly SemaphoreSlim OnComplete = new SemaphoreSlim(1, 1);
|
public readonly SemaphoreSlim OnComplete = new(1, 1);
|
||||||
public readonly SemaphoreSlim OnSentData = new(1, 1);
|
public readonly SemaphoreSlim OnSentData = new(1, 1);
|
||||||
public readonly SemaphoreSlim OnReceivedData = new (1, 1);
|
public readonly SemaphoreSlim OnReceivedData = new (1, 1);
|
||||||
|
|
||||||
|
@ -482,7 +482,7 @@ const pollForEvents = server => {
|
|||||||
if (!state.waitingOnOutput) {
|
if (!state.waitingOnOutput) {
|
||||||
if (state.queuedMessages.length === 0) {
|
if (state.queuedMessages.length === 0) {
|
||||||
logger.WriteDebug('No messages in queue');
|
logger.WriteDebug('No messages in queue');
|
||||||
return;``
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.waitingOnOutput = true;
|
state.waitingOnOutput = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user