public TCPRawClient(IPAddress remote_ip, ushort remote_port, PacketCalculateEvent calc_event, int header_size, int maxPacketSize = 64 * 1024, int outputStreamMultiply = 64, LatencyMode mode = LatencyMode.Normal) { remoteIp = remote_ip; remotePort = remote_port; _maxPacketSize = maxPacketSize; this.mode = mode; if (calc_event == null) { throw new ArgumentNullException(nameof(calc_event)); } packetHeaderSize = header_size; CalculatePacketSize = calc_event; workerStarted = 0; _outputStream = new ConcurrentMemoryStream(_maxPacketSize * outputStreamMultiply); rcvBuff = new byte[maxPacketSize]; }
// Methods overidden from WebRequest public override WebResponse GetResponse() { ConcurrentMemoryStream stream = new ConcurrentMemoryStream() { Blocking = true, ReadTimeout = Timeout }; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; Task curlTask = Task.Factory.StartNew(() => { // We shouldn't need to check if libcurl is initialized, because it's reference counted and can be called multiple times. // However, repeated calls to curl_global_cleanup are crashing my program, so for the time being I'm not pairing it with this. // It's up the user to call curl_global_cleanup once when they're done using it. if (!LibCurl.IsInitialized) // Check so ref count will not be increased (only one call to curl_global_cleanup required after multiple requests) { LibCurl.GlobalInit(); } try { using (CurlEasyHandle easyHandle = LibCurl.EasyInit()) using (SList headers = new SList()) using (MemoryStream postDataStream = new MemoryStream(GetRequestStream(validateMethod: false).ToArray())) { CurlDataCopier dataCopier = new CurlDataCopier(stream, postDataStream, cancellationToken); dataCopier.SetCallbacks(easyHandle); LibCurl.EasySetOpt(easyHandle, CurlOption.Url, RequestUri.AbsoluteUri); LibCurl.EasySetOpt(easyHandle, CurlOption.FollowLocation, AllowAutoRedirect ? 1 : 0); LibCurl.EasySetOpt(easyHandle, CurlOption.MaxRedirs, MaximumAutomaticRedirections); LibCurl.EasySetOpt(easyHandle, CurlOption.Timeout, Timeout); LibCurl.EasySetOpt(easyHandle, CurlOption.HttpVersion, (int)GetHttpVersion()); if (AutomaticDecompression != DecompressionMethods.None) { LibCurl.EasySetOpt(easyHandle, CurlOption.AcceptEncoding, GetAcceptEncoding()); } LibCurl.EasySetOpt(easyHandle, CurlOption.TcpKeepAlive, KeepAlive ? 1 : 0); if (File.Exists(LibCurl.CABundlePath)) { LibCurl.EasySetOpt(easyHandle, CurlOption.CaInfo, LibCurl.CABundlePath); } SetCookies(easyHandle); SetCredentials(easyHandle); SetHeaders(easyHandle, headers); SetMethod(easyHandle); SetProxy(easyHandle); // Execute the request. LibCurl.EasyPerform(easyHandle); } } finally { // Close the stream to indicate that we're done writing to it, unblocking readers. stream.Close(); //LibCurl.GlobalCleanup(); } }, cancellationToken); HaveResponse = true; return(new LibCurlHttpWebResponse(this, stream, cancellationTokenSource)); }