public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var request = context.HttpContext.Request; if (!request.Body.CanSeek && !_options.SuppressReadBuffering) { BufferingHelper.EnableRewind(request); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } try { var result = MessagePackSerializer.NonGeneric.Deserialize(context.ModelType, request.Body, _options.FormatterResolver); var formatterResult = await InputFormatterResult.SuccessAsync(result); return(formatterResult); } catch (Exception e) { SystemLogger.Instance.LogDebug($"Could not deserialize object {e}"); throw; } }
private async void OnNetConnectionStatusUpdated(object sender, NetStatusUpdatedEventArgs args) { var ncs = args.NetStatusCode; if (ncs == NetStatusCodeType.NetConnectionConnectSuccess) { _Stream = new NetStream(); _Stream.Attached += OnAttached; _Stream.StatusUpdated += OnNetStreamStatusUpdated; _Stream.AudioStarted += OnAudioStarted; _Stream.VideoStarted += OnVideoStarted; _BufferingHelper = new BufferingHelper(_Stream); // createStream await _Stream.AttachAsync(_Connection); // nlPlayNotice(チャンネル/ユーザー生放送のライブ配信のみ) await _ConnectionImpl.PostConnectionProcess(_Connection); } else if ((ncs & NetStatusCodeType.Level2Mask) == NetStatusCodeType.NetConnectionConnect) { Close(); Stopped?.Invoke(new NicovideoRtmpClientStoppedEventArgs()); } }
public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var request = context.HttpContext.Request; if (!request.Body.CanSeek && !_options.SuppressReadBuffering) { BufferingHelper.EnableRewind(request); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } using (MemoryStream stream = new MemoryStream()) { await request.Body.CopyToAsync(stream); stream.Position = 0; var result = MessagePackSerializer.NonGeneric.Deserialize(context.ModelType, stream, _options.FormatterResolver); return(await InputFormatterResult.SuccessAsync(result)); } }
/// <inheritdoc /> public override async Task <InputFormatterResult> ReadRequestBodyAsync( InputFormatterContext context, Encoding encoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (encoding == null) { throw new ArgumentNullException(nameof(encoding)); } var request = context.HttpContext.Request; var suppressInputFormatterBuffering = _options?.SuppressInputFormatterBuffering ?? _suppressInputFormatterBuffering; if (!request.Body.CanSeek && !suppressInputFormatterBuffering) { // XmlSerializer does synchronous reads. In order to avoid blocking on the stream, we asynchronously // read everything into a buffer, and then seek back to the beginning. BufferingHelper.EnableRewind(request); Debug.Assert(request.Body.CanSeek); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } try { using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), encoding)) { var type = GetSerializableType(context.ModelType); var serializer = GetCachedSerializer(type); var deserializedObject = serializer.Deserialize(xmlReader); // Unwrap only if the original type was wrapped. if (type != context.ModelType) { if (deserializedObject is IUnwrappable unwrappable) { deserializedObject = unwrappable.Unwrap(declaredType: context.ModelType); } } return(InputFormatterResult.Success(deserializedObject)); } } // XmlSerializer wraps actual exceptions (like FormatException or XmlException) into an InvalidOperationException // https://github.com/dotnet/corefx/blob/master/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs#L652 catch (InvalidOperationException exception) when(exception.InnerException is FormatException || exception.InnerException is XmlException) { throw new InputFormatterException(Resources.ErrorDeserializingInputData, exception); } }
public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (encoding == null) { throw new ArgumentNullException(nameof(encoding)); } if (context.ModelType == typeof(RequestMessage)) { var request = context.HttpContext.Request; if (!request.Body.CanSeek) { BufferingHelper.EnableRewind(request); Debug.Assert(request.Body.CanSeek); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), encoding)) { var inputRequestMessage = RequestMessageFactory.CreateRequestMessage(xmlReader); if ((_messageMode == MessageMode.Cipher || _messageMode == MessageMode.Compatible) && inputRequestMessage is RequestEncryptMessage) { var encryptMessage = inputRequestMessage as RequestEncryptMessage; var plainMessage = String.Empty; var sMsgSignature = context.HttpContext.Request.Query["msg_signature"]; var sTimeStamp = context.HttpContext.Request.Query["timestamp"]; var sNonce = context.HttpContext.Request.Query["nonce"]; var ret = _crypt.DecryptMsg(sMsgSignature, sTimeStamp, sNonce, encryptMessage.EncryptMessage, ref plainMessage); if (ret == 0) { using (var stringStream = new MemoryStream(encoding.GetBytes(plainMessage))) using (var stringReader = CreateXmlReader(stringStream, encoding)) { inputRequestMessage = RequestMessageFactory.CreateRequestMessage(stringReader); } } } return(InputFormatterResult.Success(inputRequestMessage)); } } return(await base.ReadRequestBodyAsync(context, encoding)); }
/// <summary> /// Ensure we can read the <paramref name="request"/> body without messing up JSON etc. deserialization. Body /// will be read at least twice in most receivers. /// </summary> /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param> /// <returns>A <see cref="Task"/> that on completion will have prepared the request body.</returns> public async Task PrepareRequestBody(HttpRequest request) { if (!request.Body.CanSeek) { BufferingHelper.EnableRewind(request); Debug.Assert(request.Body.CanSeek); await request.Body.DrainAsync(CancellationToken.None); } // Always start at the beginning. request.Body.Seek(0L, SeekOrigin.Begin); }
/// <inheritdoc /> public override async Task <InputFormatterResult> ReadRequestBodyAsync( InputFormatterContext context, Encoding encoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (encoding == null) { throw new ArgumentNullException(nameof(encoding)); } var request = context.HttpContext.Request; if (!request.Body.CanSeek && !_suppressInputFormatterBuffering) { // XmlSerializer does synchronous reads. In order to avoid blocking on the stream, we asynchronously // read everything into a buffer, and then seek back to the beginning. BufferingHelper.EnableRewind(request); Debug.Assert(request.Body.CanSeek); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), encoding)) { var type = GetSerializableType(context.ModelType); var serializer = GetCachedSerializer(type); var deserializedObject = serializer.Deserialize(xmlReader); // Unwrap only if the original type was wrapped. if (type != context.ModelType) { if (deserializedObject is IUnwrappable unwrappable) { deserializedObject = unwrappable.Unwrap(declaredType: context.ModelType); } } return(InputFormatterResult.Success(deserializedObject)); } }
private void Close() { if (_MediaStreamSource != null) { _MediaStreamSource.Starting -= OnStarting; _MediaStreamSource.SampleRequested -= OnSampleRequested; _MediaStreamSource = null; } if (_Stream != null) { _Stream.Attached -= OnAttached; _Stream.StatusUpdated -= OnNetStreamStatusUpdated; _Stream.AudioStarted -= OnAudioStarted; _Stream.VideoStarted -= OnVideoStarted; _Stream = null; } if (_BufferingHelper != null) { _BufferingHelper.Stop(); _BufferingHelper = null; } if (_Connection != null) { _Connection.StatusUpdated -= OnNetConnectionStatusUpdated; try { _Connection.Close(); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } finally { _Connection = null; } } _IsClosed = true; Debug.WriteLine($"RTMP : {ClientId} closed."); }
/// <summary> /// Ensure we can read the <paramref name="request"/> body without messing up JSON etc. deserialization. Body /// will be read at least twice in most WebHook receivers. /// </summary> /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param> /// <returns>A <see cref="Task"/> that on completion will have prepared the request body.</returns> public static async Task PrepareRequestBody(HttpRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (!request.Body.CanSeek) { BufferingHelper.EnableRewind(request); Debug.Assert(request.Body.CanSeek); await request.Body.DrainAsync(CancellationToken.None); } // Always start at the beginning. request.Body.Seek(0L, SeekOrigin.Begin); }
public override async Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { EnsureArg.IsNotNull(context); var request = context.HttpContext.Request; if (!request.Body.CanSeek) { BufferingHelper.EnableRewind(request); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } var result = MessagePackSerializer.NonGeneric.Deserialize(context.ModelType, request.Body, _resolver); return(await InputFormatterResult.SuccessAsync(result)); }
/// <summary> /// Ensure the <paramref name="request"/> <see cref="HttpRequest.Body"/> can be read multiple times. Normally /// buffers request bodies in memory; writes requests larger than <paramref name="bufferThreshold"/> bytes to /// disk. /// </summary> /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param> /// <param name="bufferThreshold"> /// The maximum size in bytes of the in-memory <see cref="System.Buffers.ArrayPool{Byte}"/> used to buffer the /// stream. Larger request bodies are written to disk. /// </param> /// <param name="bufferLimit"> /// The maximum size in bytes of the request body. An attempt to read beyond this limit will cause an /// <see cref="System.IO.IOException"/>. /// </param> /// <remarks> /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c> /// environment variable, if any. If that environment variable is not defined, these files are written to the /// current user's temporary folder. Files are automatically deleted at the end of their associated requests. /// </remarks> public static void EnableBuffering(this HttpRequest request, int bufferThreshold, long bufferLimit) { BufferingHelper.EnableRewind(request, bufferThreshold, bufferLimit); }
/// <summary> /// Ensure the <paramref name="request"/> <see cref="HttpRequest.Body"/> can be read multiple times. Normally /// buffers request bodies in memory; writes requests larger than 30K bytes to disk. /// </summary> /// <param name="request">The <see cref="HttpRequest"/> to prepare.</param> /// <remarks> /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c> /// environment variable, if any. If that environment variable is not defined, these files are written to the /// current user's temporary folder. Files are automatically deleted at the end of their associated requests. /// </remarks> public static void EnableBuffering(this HttpRequest request) { BufferingHelper.EnableRewind(request); }
/// <inheritdoc /> public override async Task <InputFormatterResult> ReadRequestBodyAsync( InputFormatterContext context, Encoding encoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (encoding == null) { throw new ArgumentNullException(nameof(encoding)); } var request = context.HttpContext.Request; if (!request.Body.CanSeek && !_suppressInputFormatterBuffering) { // JSON.Net does synchronous reads. In order to avoid blocking on the stream, we asynchronously // read everything into a buffer, and then seek back to the beginning. BufferingHelper.EnableRewind(request); Debug.Assert(request.Body.CanSeek); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } using (var streamReader = context.ReaderFactory(request.Body, encoding)) { using (var jsonReader = new JsonTextReader(streamReader)) { jsonReader.ArrayPool = _charPool; jsonReader.CloseInput = false; var successful = true; Exception exception = null; void ErrorHandler(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs eventArgs) { successful = false; // Handle path combinations such as "" + "Property", "Parent" + "Property", or "Parent" + "[12]". var key = eventArgs.ErrorContext.Path; if (!string.IsNullOrEmpty(context.ModelName)) { if (string.IsNullOrEmpty(eventArgs.ErrorContext.Path)) { key = context.ModelName; } else if (eventArgs.ErrorContext.Path[0] == '[') { key = context.ModelName + eventArgs.ErrorContext.Path; } else { key = context.ModelName + "." + eventArgs.ErrorContext.Path; } } var metadata = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path); context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error, metadata); _logger.JsonInputException(eventArgs.ErrorContext.Error); exception = eventArgs.ErrorContext.Error; // Error must always be marked as handled // Failure to do so can cause the exception to be rethrown at every recursive level and // overflow the stack for x64 CLR processes eventArgs.ErrorContext.Handled = true; } var type = context.ModelType; var jsonSerializer = CreateJsonSerializer(); jsonSerializer.Error += ErrorHandler; object model; try { model = jsonSerializer.Deserialize(jsonReader, type); } finally { // Clean up the error handler since CreateJsonSerializer() pools instances. jsonSerializer.Error -= ErrorHandler; ReleaseJsonSerializer(jsonSerializer); } if (successful) { if (model == null && !context.TreatEmptyInputAsDefaultValue) { // Some nonempty inputs might deserialize as null, for example whitespace, // or the JSON-encoded value "null". The upstream BodyModelBinder needs to // be notified that we don't regard this as a real input so it can register // a model binding error. return(InputFormatterResult.NoValue()); } else { return(InputFormatterResult.Success(model)); } } if (!(exception is JsonException || exception is OverflowException)) { var exceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception); exceptionDispatchInfo.Throw(); } return(InputFormatterResult.Failure()); } } }
public async Task Invoke(HttpContext httpContext) { BufferingHelper.EnableRewind(httpContext.Request); if (!httpContext.Request.Headers.Keys.Contains("Signature") || !httpContext.Request.Headers.Keys.Contains("SignatureCertChainUrl")) { _logger.LogError(SignatureHeadersMissing); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(SignatureHeadersMissing); return; } var sigCertChainUrl = httpContext.Request.Headers["SignatureCertChainUrl"]; var certChainUrl = sigCertChainUrl.Any() ? sigCertChainUrl.First() : string.Empty; if (string.IsNullOrWhiteSpace(certChainUrl)) { _logger.LogError(SignatureChainUrlEmpty); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(SignatureChainUrlEmpty); return; } // https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem var certUri = new Uri(certChainUrl); if (!((certUri.Port == 443 || certUri.IsDefaultPort) && certUri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))) { _logger.LogError(MustUseHttps); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(MustUseHttps); return; } if (!certUri.Host.Equals(ValidHostName, StringComparison.OrdinalIgnoreCase)) { _logger.LogError(InvalidHostName); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(InvalidHostName); return; } if (!certUri.AbsolutePath.StartsWith("/echo.api/")) { _logger.LogError(InvalidCertificatePath); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(InvalidCertificatePath); return; } using (var client = new WebClient()) { var certData = client.DownloadData(certUri); var certificate = new X509Certificate2(certData); if (certificate.NotBefore > DateTime.UtcNow) { _logger.LogError(CertificateNotYetEffective); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(CertificateNotYetEffective); return; } if (certificate.NotAfter <= DateTime.UtcNow) { _logger.LogError(CertificateExpired); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(CertificateExpired); return; } if (!certificate.Subject.Contains("CN=echo-api.amazon.com")) { _logger.LogError(CertificateInvalidIssuer); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(CertificateInvalidIssuer); return; } // ToDo: All certificates in the chain combine to create a // chain of trust to a trusted root CA certificate var certificateChain = new X509Chain { ChainPolicy = { RevocationMode = X509RevocationMode.NoCheck } }; var hasChainToTrustedCA = certificateChain.Build(certificate); if (!hasChainToTrustedCA) { _logger.LogError(InvalidCertificateChain); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(InvalidCertificateChain); return; } try { var signature = httpContext.Request.Headers["Signature"]; var signatureString = signature.Any() ? signature.First() : string.Empty; _logger.LogInformation($"Sig = >>{signatureString}<<"); byte[] signatureDecoded = Convert.FromBase64String(signatureString); var hasher = SHA1.Create(); var body = await httpContext.Request.ReadHttpRequestBodyAsync(); httpContext.Request.Body.Position = 0; // Reset var hashedBody = hasher.ComputeHash(Encoding.UTF8.GetBytes(body)); using (var rsaPublicKey = certificate.GetRSAPublicKey()) { var isHashValid = rsaPublicKey.VerifyHash(hashedBody, signatureDecoded, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1); _logger.LogInformation($"Is Hash Valid Response: {isHashValid}"); if (rsaPublicKey == null || !isHashValid) { _logger.LogError(InvalidCertificateKey); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(InvalidCertificateKey); return; } } } catch (Exception ex) { _logger.LogError(ex.Message); httpContext.Response.StatusCode = 400; // Bad Request await httpContext.Response.WriteAsync(ex.Message); return; } } _logger.LogInformation("******************* VALIDATED *******************"); await _next(httpContext); }
/// <summary> /// Ensure the <paramref name="request"/> <see cref="ProtoRequest.Body"/> can be read multiple times. Normally /// buffers request bodies in memory; writes requests larger than 30K bytes to disk. /// </summary> /// <param name="request">The <see cref="ProtoRequest"/> to prepare.</param> /// <param name="bufferLimit"> /// The maximum size in bytes of the request body. An attempt to read beyond this limit will cause an /// <see cref="System.IO.IOException"/>. /// </param> /// <remarks> /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c> /// environment variable, if any. If that environment variable is not defined, these files are written to the /// current user's temporary folder. Files are automatically deleted at the end of their associated requests. /// </remarks> public static void EnableBuffering(this ProtoRequest request, long bufferLimit) { BufferingHelper.EnableRewind(request, bufferLimit: bufferLimit); }
/// <summary> /// Ensure the <paramref name="request"/> <see cref="ProtoRequest.Body"/> can be read multiple times. Normally /// buffers request bodies in memory; writes requests larger than <paramref name="bufferThreshold"/> bytes to /// disk. /// </summary> /// <param name="request">The <see cref="ProtoRequest"/> to prepare.</param> /// <param name="bufferThreshold"> /// The maximum size in bytes of the in-memory <see cref="System.Buffers.ArrayPool{Byte}"/> used to buffer the /// stream. Larger request bodies are written to disk. /// </param> /// <remarks> /// Temporary files for larger requests are written to the location named in the <c>ASPNETCORE_TEMP</c> /// environment variable, if any. If that environment variable is not defined, these files are written to the /// current user's temporary folder. Files are automatically deleted at the end of their associated requests. /// </remarks> public static void EnableBuffering(this ProtoRequest request, int bufferThreshold) { BufferingHelper.EnableRewind(request, bufferThreshold); }