/// <summary> /// Assigns request context to given easy handle. /// </summary> public void AssignContext(SafeEasyHandle easy, T context) { if (!_busy.TryAdd(easy, context)) { throw new Exception("Trying to assign request context to handle that already has its context."); } }
public HandleCompletedAction OnComplete(SafeEasyHandle easy, MyRequestContext context, CURLcode errorCode) { Console.WriteLine($"Request label: {context.Label}."); if (errorCode != CURLcode.OK) { Console.BackgroundColor = ConsoleColor.DarkRed; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine($"cURL error code: {errorCode}"); var pErrorMsg = CurlNative.Easy.StrError(errorCode); var errorMsg = Marshal.PtrToStringAnsi(pErrorMsg); Console.WriteLine($"cURL error message: {errorMsg}"); Console.ResetColor(); Console.WriteLine("--------"); Console.WriteLine(); context.Dispose(); return(HandleCompletedAction.ResetHandleAndNext); } // Get HTTP response code. CurlNative.Easy.GetInfo(easy, CURLINFO.RESPONSE_CODE, out int httpCode); if (httpCode != 200) { Console.BackgroundColor = ConsoleColor.DarkRed; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine($"Invalid HTTP response code: {httpCode}"); Console.ResetColor(); Console.WriteLine("--------"); Console.WriteLine(); context.Dispose(); return(HandleCompletedAction.ResetHandleAndNext); } Console.WriteLine($"Response code: {httpCode}"); // Get effective URL. IntPtr pDoneUrl; CurlNative.Easy.GetInfo(easy, CURLINFO.EFFECTIVE_URL, out pDoneUrl); var doneUrl = Marshal.PtrToStringAnsi(pDoneUrl); Console.WriteLine($"Effective URL: {doneUrl}"); // Get response body as string. var html = context.ContentData.ReadAsString(); // Scrape question from HTML source. var match = Regex.Match(html, "<title>(.+?)<\\/"); Console.WriteLine($"Question: {match.Groups[1].Value.Trim()}"); Console.WriteLine("--------"); Console.WriteLine(); context.Dispose(); return(HandleCompletedAction.ResetHandleAndNext); }
/// <summary> /// Unassigns request context for given easy handle. /// </summary> public void UnassignContext(SafeEasyHandle easy) { if (!_busy.TryRemove(easy, out T _)) { throw new Exception("Given handle doesn't have stored any request context."); } }
/// <summary> /// Retrieves request context for given easy handle. /// </summary> public void GetAssignedContext(SafeEasyHandle easy, out T context) { if (!_busy.TryGetValue(easy, out context)) { throw new Exception("Cannot find request context for given easy handle."); } }
public bool TryNext(SafeEasyHandle easy, out MyRequestContext context) { // If question ID is higher than maximum, return false. if (_currentQuestion > _maxQuestion) { context = null; return(false); } // Create request context. Assign it a label to easily recognize it later. var contextLocal = new MyRequestContext { Label = $"StackOverflow Question #{_currentQuestion}" }; // Copy response header (it contains HTTP code and response headers, for example // "Content-Type") to MemoryStream in our RequestContext. context = contextLocal; context.HeaderFunction = (data, size, nmemb, userdata) => { var length = (int)size * (int)nmemb; var buffer = new byte[length]; Marshal.Copy(data, buffer, 0, length); contextLocal.HeaderStream.Write(buffer, 0, length); return((UIntPtr)length); }; // Copy response body (it for example contains HTML source) to MemoryStream // in our RequestContext. context.ContentFunction = (data, size, nmemb, userdata) => { var length = (int)size * (int)nmemb; var buffer = new byte[length]; Marshal.Copy(data, buffer, 0, length); contextLocal.ContentStream.Write(buffer, 0, length); return((UIntPtr)length); }; // Set request URL. CurlNative.Easy.SetOpt(easy, CURLoption.URL, $"http://stackoverflow.com/questions/{_currentQuestion}/"); // Follow redirects. CurlNative.Easy.SetOpt(easy, CURLoption.FOLLOWLOCATION, 1); CurlNative.Easy.SetOpt(easy, CURLoption.HEADERFUNCTION, context.HeaderFunction); CurlNative.Easy.SetOpt(easy, CURLoption.WRITEFUNCTION, context.ContentFunction); _currentQuestion++; return(true); }
public ValueTask <bool> MoveNextAsync(SafeEasyHandle easy) { // If question ID is higher than maximum, return false. if (_currentQuestion > _maxQuestion) { Current = null; return(new ValueTask <bool>(false)); } // Create request context. Assign it a label to easily recognize it later. var context = new MyRequestContext($"StackOverflow Question #{_currentQuestion}"); // Set request URL. CurlNative.Easy.SetOpt(easy, CURLoption.URL, $"https://stackoverflow.com/questions/{_currentQuestion}/"); // Follow redirects. CurlNative.Easy.SetOpt(easy, CURLoption.FOLLOWLOCATION, 1); // Set request timeout. CurlNative.Easy.SetOpt(easy, CURLoption.TIMEOUT_MS, 3000); // Copy response header (it contains HTTP code and response headers, for example // "Content-Type") to MemoryStream in our RequestContext. CurlNative.Easy.SetOpt(easy, CURLoption.HEADERFUNCTION, context.HeaderData.DataHandler); // Copy response body (it for example contains HTML source) to MemoryStream // in our RequestContext. CurlNative.Easy.SetOpt(easy, CURLoption.WRITEFUNCTION, context.ContentData.DataHandler); // Point the certificate bundle file path to verify HTTPS certificates. //CurlNative.Easy.SetOpt(easy, CURLoption.CAINFO, CurlResources.CaBundlePath); _currentQuestion++; Current = context; return(new ValueTask <bool>(true)); }
public static extern CURLcode GetInfo(SafeEasyHandle handle, CURLINFO option, out double value);
public static extern CURLcode SetOpt(SafeEasyHandle handle, CURLoption option, DataHandler value);
public static extern CURLcode SetOpt(SafeEasyHandle handle, CURLoption option, string value);
public static extern void Reset(SafeEasyHandle handle);
public static extern CURLcode Perform(SafeEasyHandle handle);
public static CURLcode SetOpt(SafeEasyHandle handle, CURLoption option, CURLAUTH auth) { return(SetOpt(handle, option, (int)auth)); }
/// <summary> /// Change status of cURL easy handle from busy to free. /// </summary> public void Free(SafeEasyHandle easy) { _free.Add(easy); }
/// <summary> /// Try get unused cURL easy handle. /// </summary> /// <returns>TRUE if successful, FALSE if all handles are busy.</returns> public bool TryTakeFree(out SafeEasyHandle easy) { return(_free.TryTake(out easy)); }
public static extern CURLcode GetInfo(SafeEasyHandle handle, CURLINFO option, IntPtr value);
public static extern CURLMcode RemoveHandle(SafeMultiHandle multiHandle, SafeEasyHandle easyHandle);
public EasyHandleContext(SafeEasyHandle easy) { Easy = easy; }