protected override byte[] CreateHttpContent() { using (var stream = new RequestBodyStream()) { stream.WritePu16((byte)Operation.AddFile); stream.WritePu16(Revision); stream.WriteString(_fullPath); stream.WritePu64(_size); stream.WritePu64(_dateTime.ToUnix()); stream.WritePu32(00); stream.Write(_hash); long mask = ConflictResolver.Rename == _conflictResolver // 1 = overwrite, 55 = don't add if not changed, add with rename if changed ? 55 : 1; stream.WritePu32(mask); if ((mask & 32) != 0) { stream.Write(_hash); stream.WritePu64(_size); } var body = stream.GetBytes(); return(body); } }
/// <summary> /// Decodes the request body into a string with the given encoding and returns it. /// </summary> /// <param name="encoding">The encoding to use. If null or omitted, Encoding.ASCII will be used.</param> /// <remarks> /// Will return incomplete data until FinishedRequestBody is true. /// </remarks> public string GetBody(Encoding encoding = null) { if (encoding == null) { encoding = Encoding.ASCII; } return(encoding.GetString(RequestBodyStream.ToArray())); }
protected override byte[] CreateHttpContent() { using (var stream = new RequestBodyStream()) { stream.WritePu16((byte)Operation.SharedFoldersList); var body = stream.GetBytes(); return(body); } }
protected override byte[] CreateHttpContent() { using (var stream = new RequestBodyStream()) { stream.WritePu16((byte)Operation.CreateFolder); stream.WritePu16(Revision); stream.WriteString(_fullPath); stream.WritePu32(0); var body = stream.GetBytes(); return(body); } }
public RequestBodyCopier(Stream requestBody, long contentLength) { ContentLength = contentLength; DataHandler = (data, size, nmemb, userdata) => { int length = (int)size * (int)nmemb; var buffer = new byte[length]; RequestBodyStream.Read(buffer, 0, length); Marshal.Copy(buffer, 0, data, length); return((UIntPtr)length); }; }
protected override byte[] CreateHttpContent() { using (var stream = new RequestBodyStream()) { stream.WritePu16((byte)Operation.FolderList); stream.WriteString(_fullPath); stream.WritePu32(Depth); stream.WritePu32((int)Options); stream.WriteWithLength(new byte[0]); var body = stream.GetBytes(); return(body); } }
protected override byte[] CreateHttpContent() { using (var stream = new RequestBodyStream()) { stream.WritePu16((byte)Operation.Rename); stream.WritePu32(00); // old revision stream.WriteString(_fromPath); stream.WritePu32(00); // new revision stream.WriteString(_toPath); stream.WritePu32(00); //dunno var body = stream.GetBytes(); return(body); } }
public HttpMessage(ArraySegment <byte> buffer, int maxHeadersLength) { if (maxHeadersLength > buffer.Count) { throw new ArgumentOutOfRangeException("maxHeadersLength"); } _buffer = buffer; _maxHeadersLength = maxHeadersLength; _parser = new HttpParser(HttpParserType.Response, new HttpMessageHandler(this)); _requestHeadersStream = new BufferStream(_buffer.Array, _buffer.Offset, maxHeadersLength, true); _requestBodyStream = new RequestBodyStream(_buffer.Array, _maxHeadersLength, _buffer.Count - maxHeadersLength, this); Recycle(); }
/// <summary> /// Used internally. Feeds a <see cref="Record">Record</see> to this request for processing. /// </summary> /// <param name="record">The record to feed.</param> /// <returns>Returns true iff the request is completely received.</returns> internal bool HandleRecord(Record record) { switch (record.Type) { case Record.RecordType.Params: // An empty parameter record specifies that all parameters have been transmitted if (record.ContentLength == 0) { ParamStream.Seek(0, SeekOrigin.Begin); Parameters = Record.ReadNameValuePairs(ParamStream); FinishedParameters = true; } else { // If the params are not yet finished, write the contents to the ParamStream. ParamStream.Write(record.ContentData, 0, record.ContentLength); } break; case Record.RecordType.Stdin: var oldPos = RequestBodyStream.Position; RequestBodyStream.Seek(0, SeekOrigin.End); RequestBodyStream.Write(record.ContentData, 0, record.ContentLength); RequestBodyStream.Position = oldPos; // Finished requests are indicated by an empty stdin record if (record.ContentLength == 0) { FinishedRequestBody = true; return(true); } break; } return(false); }
/// <summary> /// Writes the request body to a byte array and returns it. /// </summary> /// <remarks> /// Will return incomplete data until FinishedRequestBody is true. /// </remarks> public byte[] GetBody() { return(RequestBodyStream.ToArray()); }
/// <summary> /// Writes the request body to a byte array and returns it. /// </summary> /// <remarks> /// Will return incomplete data until FinishedRequestBody is true. /// </remarks> public byte[] GetBody() => RequestBodyStream.ToArray();
public static Stream ExecuteStreamRequest( this Request request) { byte[] postdata = request.RequestBody; if (postdata != null) { request.RequestContentLength = 0; if (request.IsCompressed || request.RequestContentType == "application/x-gzip") { using (var ms = new MemoryStream()) { using (var comp = new GZipStream(ms, CompressionMode.Compress)) { comp.Write(postdata, 0, postdata.Length); /* The GZIP stream has a CRC-32 and a EOF marker, so we close it first to have it completed */ } postdata = ms.ToArray(); } } request.RequestBodyDelegate = (Stream poststream) => poststream.Write(postdata, 0, postdata.Length); /* append request POST data */ request.RequestContentLength = postdata.Length; } string url = request.Url; if (request.GetValues != null) { url += "?" + BuildQueryString(request.GetValues); } var uri = new Uri(url); if (request.ConnectionMode == ConnectionModeEnum.Http2PriorKnowledge) { return(DoStreamRequestHttp2(request, uri)); } if (request.ConnectionMode == ConnectionModeEnum.UpgradeHttp2) { Http2Connection.Http2Stream h2stream = TryReuseStream(uri.Scheme, uri.Host, uri.Port); if (h2stream != null) { return(DoStreamRequestHttp2(request, uri, h2stream)); } } byte[] outdata; string method = request.Method; redoafter401: var reqdata = new StringBuilder(uri.IsDefaultPort ? $"{method} {uri.PathAndQuery} HTTP/1.1\r\nHost: {uri.Host}\r\n" : $"{method} {uri.PathAndQuery} HTTP/1.1\r\nHost: {uri.Host}:{uri.Port}\r\n"); bool doPost = false; bool doChunked = false; bool compressed = request.IsCompressed; int content_length = request.RequestContentLength; IDictionary <string, string> headers = request.Headers; bool haveAccept = false; if (headers != null) { var removal = new List <string>(); foreach (string k in headers.Keys) { if (string.Compare(k, "content-length", true) == 0 || string.Compare(k, "content-type", true) == 0 || string.Compare(k, "connection", true) == 0 || string.Compare(k, "expect", true) == 0 || string.Compare(k, "transfer-encoding", true) == 0) { removal.Add(k); } if (string.Compare(k, "accept", true) == 0) { haveAccept = true; } } if (removal.Count != 0) { foreach (string k in removal) { headers.Remove(k); } } } if (request.Authorization != null) { if (headers == null) { headers = new Dictionary <string, string>(); } if (request.Authorization.IsSchemeAllowed(uri.Scheme)) { request.Authorization.GetRequestHeaders(headers, request.Method, uri.PathAndQuery); } } if (headers != null) { foreach (KeyValuePair <string, string> kvp in headers) { reqdata.Append($"{kvp.Key}: {kvp.Value}\r\n"); } } if (request.UseChunkedEncoding) { reqdata.Append("Transfer-Encoding: chunked\r\n"); } string content_type = request.RequestContentType; bool expect100Continue = request.Expect100Continue; if (request.RequestBodyDelegate != null) { if (content_type != null) { reqdata.Append($"Content-Type: {content_type}\r\n"); } if (request.UseChunkedEncoding) { doPost = true; doChunked = true; reqdata.Append("Transfer-Encoding: chunked\r\n"); if (compressed && content_type != "application/x-gzip") { reqdata.Append("X-Content-Encoding: gzip\r\n"); } if (expect100Continue) { reqdata.Append("Expect: 100-continue\r\n"); } } else { doPost = true; if (content_length > request.Expect100ContinueMinSize) { expect100Continue = true; request.Expect100Continue = true; } reqdata.Append($"Content-Length: {content_length}\r\n"); if (compressed && content_type != "application/x-gzip") { reqdata.Append("X-Content-Encoding: gzip\r\n"); } if (expect100Continue) { reqdata.Append("Expect: 100-continue\r\n"); } } } if (method != "HEAD") { reqdata.Append("Accept-Encoding: gzip, deflate\r\n"); } if (!haveAccept) { reqdata.Append("Accept: */*\r\n"); } int retrycnt = 1; retry: AbstractHttpStream s = OpenStream(uri.Scheme, uri.Host, uri.Port, request.ClientCertificates, request.EnabledSslProtocols, request.CheckCertificateRevocation, request.ConnectionMode, request.RemoteCertificateValidationCallback, request.EnableIPv6 && OSSupportsIPv6); string finalreqdata = reqdata.ToString(); if (!s.IsReusable) { finalreqdata += "Connection: close\r\n"; } bool h2cUpgrade = request.ConnectionMode == ConnectionModeEnum.UpgradeHttp2; if (h2cUpgrade) { finalreqdata += "Upgrade: h2c\r\nHTTP2-Settings:\r\n"; } finalreqdata += "\r\n"; outdata = Encoding.ASCII.GetBytes(finalreqdata); try { s.Write(outdata, 0, outdata.Length); s.Flush(); } catch (ObjectDisposedException) { if (retrycnt-- > 0) { goto retry; } throw; } catch (SocketException) { if (retrycnt-- > 0) { goto retry; } throw; } catch (IOException) { if (retrycnt-- > 0) { goto retry; } throw; } s.ReadTimeout = 10000; string resline; string[] splits; if (doPost) { if (expect100Continue) { try { resline = s.ReadHeaderLine(); splits = resline.Split(new char[] { ' ' }, 3); if (splits.Length < 3) { throw new BadHttpResponseException("Not a HTTP response"); } if (!splits[0].StartsWith("HTTP/")) { throw new BadHttpResponseException("Missing HTTP version info"); } if (splits[1] == "101") { ReadHeaderLines(s, headers); headers.Clear(); var conn = new Http2Connection(s, false); Http2Connection.Http2Stream h2stream = conn.UpgradeClientStream(); AddH2Connection(conn, uri.Scheme, uri.Host, uri.Port); return(DoStreamRequestHttp2Response(h2stream, request, uri, doPost)); } if (splits[1] != "100") { int statusCode; headers.Clear(); ReadHeaderLines(s, headers); if (!int.TryParse(splits[1], out statusCode)) { statusCode = 500; } request.StatusCode = (HttpStatusCode)statusCode; if (statusCode == 401 && request.Authorization != null && request.Authorization.CanHandleUnauthorized(headers)) { using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } goto redoafter401; } if (statusCode == 401) { string data; if (headers.TryGetValue("www-authenticate", out data)) { string authtype; Dictionary <string, string> authpara = ParseWWWAuthenticate(data, out authtype); if (authpara == null) { using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } throw new BadHttpResponseException("Invalid WWW-Authenticate"); } else if (request.IsExceptionDisabled()) { return(GetResponseBodyStream(headers, uri, splits, method, s)); } else { string realm; if (!authpara.TryGetValue("realm", out realm)) { realm = string.Empty; } using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } throw new HttpUnauthorizedException(authtype, realm, authpara); } } } if (request.IsExceptionDisabled()) { return(GetResponseBodyStream(headers, uri, splits, method, s)); } else { using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } throw new HttpException(statusCode, statusCode == 404 ? splits[2] + " (" + url + ")" : splits[2]); } } while (s.ReadHeaderLine().Length != 0) { /* ReadHeaderLine() is all we have to do */ } } catch (HttpStream.TimeoutException) { /* keep caller from being exceptioned */ } catch (IOException) { /* keep caller from being exceptioned */ } catch (SocketException) { /* keep caller from being exceptioned */ } } if (doChunked) { /* append request POST data */ using (var reqbody = new HttpWriteChunkedBodyStream(s)) { request.RequestBodyDelegate(reqbody); } } else { /* append request POST data */ using (var reqbody = new RequestBodyStream(s, content_length)) { request.RequestBodyDelegate(reqbody); } } s.Flush(); } s.ReadTimeout = request.TimeoutMs; resline = s.ReadHeaderLine(); splits = resline.Split(new char[] { ' ' }, 3); if (splits.Length < 3) { throw new BadHttpResponseException("Not a HTTP response"); } if (!splits[0].StartsWith("HTTP/")) { throw new BadHttpResponseException("Missing HTTP version info"); } if (headers == null) { headers = new Dictionary <string, string>(); } else { headers.Clear(); } if (splits[1] == "101") { ReadHeaderLines(s, headers); headers.Clear(); var conn = new Http2Connection(s, false); Http2Connection.Http2Stream h2stream = conn.UpgradeClientStream(); AddH2Connection(conn, uri.Scheme, uri.Host, uri.Port); return(DoStreamRequestHttp2Response(h2stream, request, uri, doPost)); } if (!splits[1].StartsWith("2")) { ReadHeaderLines(s, headers); int statusCode; if (!int.TryParse(splits[1], out statusCode)) { statusCode = 500; } request.StatusCode = (HttpStatusCode)statusCode; if (statusCode == 401 && request.Authorization != null && request.Authorization.CanHandleUnauthorized(headers)) { using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } goto redoafter401; } if (statusCode == 401) { string data; if (headers.TryGetValue("www-authenticate", out data)) { string authtype; Dictionary <string, string> authpara = ParseWWWAuthenticate(data, out authtype); if (authpara == null) { using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } throw new BadHttpResponseException("Invalid WWW-Authenticate"); } else if (request.IsExceptionDisabled()) { return(GetResponseBodyStream(headers, uri, splits, method, s)); } else { string realm; if (!authpara.TryGetValue("realm", out realm)) { realm = string.Empty; } using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } throw new HttpUnauthorizedException(authtype, realm, authpara); } } } else { request.Authorization?.ProcessResponseHeaders(headers); } if (request.IsExceptionDisabled()) { return(GetResponseBodyStream(headers, uri, splits, method, s)); } else { using (GetResponseBodyStream(headers, uri, splits, method, s)) { /* just consume it */ } throw new HttpException(statusCode, statusCode == 404 ? splits[2] + " (" + url + ")" : splits[2]); } } else { request.StatusCode = (HttpStatusCode)int.Parse(splits[1]); } /* needs a little passthrough for not changing the API, this actually comes from HTTP/2 */ headers.Add(":status", splits[1]); ReadHeaderLines(s, headers); request.Authorization?.ProcessResponseHeaders(headers); return(GetResponseBodyStream(headers, uri, splits, method, s)); }