/// <summary>
 /// Deserialize request number 0
 /// </summary>
 /// <param name="chunks"></param>
 /// <param name="payload"></param>
 /// <param name="request"></param>
 /// <returns></returns>
 private byte[] DeserializeRequest0(byte[] payload,
                                    out HttpTunnelRequestModel request, out int chunks)
 {
     // Deserialize data
     using (var header = new MemoryStream(payload))
         using (var reader = new BinaryReader(header)) {
             var headerLen = reader.ReadInt32();
             if (headerLen > payload.Length - 8)
             {
                 throw new ArgumentException("Bad encoding length");
             }
             var headerBuf = reader.ReadBytes(headerLen);
             var bufferLen = reader.ReadInt32();
             if (bufferLen > payload.Length - (headerLen + 8))
             {
                 throw new ArgumentException("Bad encoding length");
             }
             var chunk0 = bufferLen > 0 ? reader.ReadBytes(bufferLen) : null;
             chunks = reader.ReadInt32();
             if (chunks > kMaxNumberOfChunks)
             {
                 throw new ArgumentException("Bad encoding length");
             }
             request = _serializer.Deserialize <HttpTunnelRequestModel>(
                 headerBuf.Unzip());
             return(chunk0);
         }
 }
예제 #2
0
 /// <summary>
 /// Create chunk
 /// </summary>
 /// <param name="outer"></param>
 /// <param name="deviceId"></param>
 /// <param name="moduleId"></param>
 /// <param name="requestId"></param>
 /// <param name="request"></param>
 /// <param name="timeout"></param>
 public HttpRequestProcessor(HttpTunnelServer outer, string deviceId,
                             string moduleId, string requestId, HttpTunnelRequestModel request,
                             TimeSpan?timeout)
 {
     RequestId = requestId ??
                 throw new ArgumentNullException(nameof(requestId));
     _outer = outer ??
              throw new ArgumentNullException(nameof(outer));
     _deviceId = deviceId;
     _moduleId = moduleId;
     _timeout  = timeout ?? TimeSpan.FromSeconds(20);
     _request  = request;
     _payload  = new List <byte[]>(request.Chunks);
 }
예제 #3
0
            /// <summary>
            /// Serialize request into buffer chunks
            /// </summary>
            /// <param name="tunnelRequest"></param>
            /// <param name="payload"></param>
            /// <returns></returns>
            private List <byte[]> SerializeRequest(HttpTunnelRequestModel tunnelRequest, byte[] payload)
            {
                // Serialize data
                var buffers       = new List <byte[]>();
                var remainingRoom = 0;

                using (var header = new MemoryStream())
                    using (var writer = new BinaryWriter(header)) {
                        // Serialize header (0)
                        var headerBuffer =
                            _outer._serializer.SerializeToBytes(tunnelRequest).ToArray().Zip();

                        writer.Write(headerBuffer.Length);
                        writer.Write(headerBuffer);

                        // Assume chunk size and payload size also written
                        remainingRoom = _maxSize - (int)(header.Position + 8);
                        if (remainingRoom < 0)
                        {
                            throw new ArgumentException("Header too large to sent");
                        }

                        // Create chunks from payload
                        if (payload != null && payload.Length > 0)
                        {
                            // Fill remaining room with payload
                            remainingRoom = Math.Min(remainingRoom, payload.Length);
                            writer.Write(remainingRoom);
                            writer.Write(payload, 0, remainingRoom);

                            // Create remaining chunks
                            for (; remainingRoom < payload.Length; remainingRoom += _maxSize)
                            {
                                var length = Math.Min(payload.Length - remainingRoom, _maxSize);
                                var chunk  = payload.AsSpan(remainingRoom, length).ToArray();
                                buffers.Add(chunk);
                            }
                            writer.Write(buffers.Count);
                        }
                        else
                        {
                            writer.Write(0);
                            writer.Write(0);
                        }
                        // Insert header as first buffer
                        buffers.Insert(0, header.ToArray());
                    }
                return(buffers);
            }
 /// <summary>
 /// Create chunk
 /// </summary>
 /// <param name="outer"></param>
 /// <param name="deviceId"></param>
 /// <param name="moduleId"></param>
 /// <param name="requestId"></param>
 /// <param name="request"></param>
 /// <param name="chunks"></param>
 /// <param name="chunk0"></param>
 /// <param name="timeout"></param>
 public HttpRequestProcessor(HttpTunnelServer outer, string deviceId,
                             string moduleId, string requestId, HttpTunnelRequestModel request,
                             int chunks, byte[] chunk0, TimeSpan?timeout)
 {
     RequestId = requestId ??
                 throw new ArgumentNullException(nameof(requestId));
     _outer = outer ??
              throw new ArgumentNullException(nameof(outer));
     _deviceId   = deviceId;
     _moduleId   = moduleId;
     _timeout    = timeout ?? TimeSpan.FromSeconds(20);
     _request    = request;
     _chunks     = chunks + 1;
     _payload    = new byte[_chunks][];
     _payload[0] = chunk0 ?? new byte[0];
 }
예제 #5
0
            /// <inheritdoc/>
            protected override async Task <HttpResponseMessage> SendAsync(
                HttpRequestMessage request, CancellationToken ct)
            {
                if (request.Headers.TryGetValues(HttpHeader.UdsPath, out var paths))
                {
                    // On edge we must still support unix sockets to talk to edgelet
                    return(await base.SendAsync(request, ct));
                }

                // Create tunnel request
                var tunnelRequest = new HttpTunnelRequestModel {
                    ResourceId     = null, // TODO - fill in somehow from outer handler
                    Uri            = request.RequestUri.ToString(),
                    RequestHeaders = request.Headers?
                                     .ToDictionary(h => h.Key, h => h.Value.ToList()),
                    Method = request.Method.ToString()
                };

                // Get content
                byte[] payload = null;
                if (request.Content != null)
                {
                    payload = await request.Content.ReadAsByteArrayAsync();

                    payload = payload.Zip();

                    tunnelRequest.ContentHeaders = request.Content.Headers?
                                                   .ToDictionary(h => h.Key, h => h.Value.ToList());
                }

                // Serialize
                var buffers = SerializeRequest(tunnelRequest, payload);

                var requestId   = Guid.NewGuid().ToString();
                var requestTask = new RequestTask(kDefaultTimeout, ct);

                if (!_outer._outstanding.TryAdd(requestId, requestTask))
                {
                    throw new InvalidOperationException("Could not add completion.");
                }

                // Send events
                for (var messageId = 0; messageId < buffers.Count; messageId++)
                {
                    await _outer._client.SendEventAsync(buffers[messageId],
                                                        requestId + "_" + messageId.ToString(),
                                                        HttpTunnelRequestModel.SchemaName, ContentMimeType.Binary);
                }

                // Wait for completion
                try {
                    return(await requestTask.Completion.Task);
                }
                catch {
                    // If thrown remove and dispose first
                    if (_outer._outstanding.TryRemove(requestId, out requestTask))
                    {
                        requestTask.Dispose();
                    }
                    throw;
                }
            }