/// <inheritdoc/>
        public async Task <MethodChunkModel> ProcessAsync(MethodChunkModel request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            ChunkProcessor processor;

            if (request.Handle != null)
            {
                if (!_requests.TryGetValue(request.Handle, out processor))
                {
                    throw new MethodCallStatusException(
                              (int)HttpStatusCode.RequestTimeout);
                }
            }
            else
            {
                var handle = Interlocked.Increment(ref _requestCounter).ToString();
                processor = new ChunkProcessor(this, handle, request.MethodName,
                                               request.ContentType, request.ContentLength, request.MaxChunkLength,
                                               request.Timeout);
                if (!_requests.TryAdd(handle, processor))
                {
                    throw new MethodCallStatusException(
                              (int)HttpStatusCode.InternalServerError);
                }
            }
            return(await processor.ProcessAsync(request));
        }
            /// <summary>
            /// Process request and return response
            /// </summary>
            /// <param name="request"></param>
            /// <returns></returns>
            public async Task <MethodChunkModel> ProcessAsync(MethodChunkModel request)
            {
                var status = 200;

                if (_sent == -1)
                {
                    // Receiving
                    Buffer.BlockCopy(request.Payload, 0, _payload, _received,
                                     request.Payload.Length);
                    _received += request.Payload.Length;
                    if (_received < _payload.Length)
                    {
                        // Continue upload
                        _lastActivity = DateTime.UtcNow;
                        return(new MethodChunkModel {
                            Handle = Handle
                        });
                    }
                    try {
                        // Process
                        var result = await _outer._handler.InvokeAsync(_method,
                                                                       _payload.Unzip(), _contentType);

                        // Set response payload
                        _payload = result.Zip();
                    }
                    catch (MethodCallStatusException mex) {
                        _payload = mex.Payload.Zip();
                        status   = mex.Result;
                    }
                    catch (Exception ex) {
                        // Unexpected
                        status = (int)HttpStatusCode.InternalServerError;
                        _outer._logger.Error(ex,
                                             "Processing message resulted in unexpected error");
                    }
                    _sent = 0;
                }

                // Sending
                var length = Math.Min(_payload.Length - _sent, _maxChunkLength);
                var buffer = new byte[length];

                Buffer.BlockCopy(_payload, _sent, buffer, 0, buffer.Length);
                var response = new MethodChunkModel {
                    ContentLength = _sent == 0 ? _payload.Length : (int?)null,
                    Status        = _sent == 0 && status != 200 ? status : (int?)null,
                    Payload       = buffer
                };

                _sent += length;
                if (_sent == _payload.Length)
                {
                    // Done - remove ourselves
                    _outer._requests.TryRemove(Handle, out var tmp);
                }
                else
                {
                    response.Handle = Handle;
                    _lastActivity   = DateTime.UtcNow;
                }
                return(response);
            }