in iothub/device/src/InternalClient.cs [892:981]
internal async Task OnMethodCalledAsync(MethodRequestInternal methodRequestInternal)
{
Tuple<MethodCallback, object> callbackContextPair = null;
if (Logging.IsEnabled)
Logging.Enter(this, methodRequestInternal?.Name, methodRequestInternal, nameof(OnMethodCalledAsync));
if (methodRequestInternal == null)
{
return;
}
MethodResponseInternal methodResponseInternal = null;
byte[] requestData = methodRequestInternal.GetBytes();
await _methodsSemaphore.WaitAsync().ConfigureAwait(false);
try
{
Utils.ValidateDataIsEmptyOrJson(requestData);
if (!_deviceMethods.TryGetValue(methodRequestInternal.Name, out callbackContextPair))
{
callbackContextPair = _deviceDefaultMethodCallback;
}
}
catch (Exception ex) when (!ex.IsFatal())
{
if (Logging.IsEnabled)
Logging.Error(this, ex, nameof(OnMethodCalledAsync));
methodResponseInternal = new MethodResponseInternal(methodRequestInternal.RequestId, (int)MethodResponseStatusCode.BadRequest);
await SendMethodResponseAsync(methodResponseInternal, methodRequestInternal.CancellationToken).ConfigureAwait(false);
if (Logging.IsEnabled)
Logging.Error(this, ex, nameof(OnMethodCalledAsync));
return;
}
finally
{
try
{
methodResponseInternal?.Dispose();
}
finally
{
// Need to release this semaphore even if the above dispose call fails
_methodsSemaphore.Release();
}
}
if (callbackContextPair == null)
{
methodResponseInternal = new MethodResponseInternal(
methodRequestInternal.RequestId,
(int)MethodResponseStatusCode.MethodNotImplemented);
}
else
{
try
{
MethodResponse rv = await callbackContextPair
.Item1(new MethodRequest(methodRequestInternal.Name, requestData), callbackContextPair.Item2)
.ConfigureAwait(false);
methodResponseInternal = rv.Result == null
? new MethodResponseInternal(methodRequestInternal.RequestId, rv.Status)
: new MethodResponseInternal(rv.Result, methodRequestInternal.RequestId, rv.Status);
}
catch (Exception ex)
{
if (Logging.IsEnabled)
Logging.Error(this, ex, nameof(OnMethodCalledAsync));
methodResponseInternal = new MethodResponseInternal(methodRequestInternal.RequestId, (int)MethodResponseStatusCode.UserCodeException);
}
}
try
{
await SendMethodResponseAsync(methodResponseInternal, methodRequestInternal.CancellationToken).ConfigureAwait(false);
}
finally
{
methodResponseInternal?.Dispose();
}
if (Logging.IsEnabled)
Logging.Exit(this, methodRequestInternal.Name, methodRequestInternal, nameof(OnMethodCalledAsync));
}