From fae7fac4c44c5ddeee55a2db1eadde96b2965cf9 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 11 Jun 2018 16:00:15 -0700 Subject: [PATCH] Progress on adding cURL Multi API --- lime/net/curl/CURLMulti.hx | 39 +++++++ lime/net/curl/CURLMultiCode.hx | 34 ++++++ project/src/net/curl/CURLBindings.cpp | 146 +++++++++++++++++++++++++- 3 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 lime/net/curl/CURLMulti.hx create mode 100644 lime/net/curl/CURLMultiCode.hx diff --git a/lime/net/curl/CURLMulti.hx b/lime/net/curl/CURLMulti.hx new file mode 100644 index 000000000..cd1d7783a --- /dev/null +++ b/lime/net/curl/CURLMulti.hx @@ -0,0 +1,39 @@ +package lime.net.curl; + + +import haxe.io.Bytes; +import lime._backend.native.NativeCFFI; +import lime.system.CFFIPointer; + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end + +@:access(lime._backend.native.NativeCFFI) + + +class CURLMulti { + + + private var handle:CFFIPointer; + + + public function new (handle:CFFIPointer = null) { + + if (handle != null) { + + this.handle = handle; + + } else { + + #if (lime_cffi && lime_curl && !macro) + this.handle = NativeCFFI.lime_curl_multi_init (); + #end + + } + + } + + +} \ No newline at end of file diff --git a/lime/net/curl/CURLMultiCode.hx b/lime/net/curl/CURLMultiCode.hx new file mode 100644 index 000000000..f262dae2c --- /dev/null +++ b/lime/net/curl/CURLMultiCode.hx @@ -0,0 +1,34 @@ +package lime.net.curl; + + +@:enum abstract CURLMultiCode(Int) from Int to Int from UInt /*to UInt*/ { + + /* please call curl_multi_perform() or curl_multi_socket*() soon */ + var CURLM_CALL_MULTI_PERFORM = -1; + + var CURLM_OK = 0; + + /* the passed-in handle is not a valid CURLM handle */ + var CURLM_BAD_HANDLE = 1; + + /* an easy handle was not good/valid */ + var CURLM_BAD_EASY_HANDLE = 2; + + /* if you ever get this, you're in trouble */ + var CURLM_OUT_OF_MEMORY = 3; + + /* this is a libcurl bug */ + var CURLM_INTERNAL_ERROR = 4; + + /* the passed in socket argument did not match */ + var CURLM_BAD_SOCKET = 5; + + /* curl_multi_setopt() with unsupported option */ + var CURLM_UNKNOWN_OPTION = 6; + + /* an easy handle already added to a multi handle was attempted to get added - again */ + var CURLM_ADDED_ALREADY = 7; + + //CURLM_LAST + +} \ No newline at end of file diff --git a/project/src/net/curl/CURLBindings.cpp b/project/src/net/curl/CURLBindings.cpp index 9632638b8..848b70f5c 100644 --- a/project/src/net/curl/CURLBindings.cpp +++ b/project/src/net/curl/CURLBindings.cpp @@ -10,6 +10,9 @@ namespace lime { + std::map curlMultiHandles; + std::map curlMultiRunningHandles; + std::map curlMultiValid; std::map curlValid; std::map headerCallbacks; std::map headerSLists; @@ -27,6 +30,14 @@ namespace lime { curl_gc_mutex.Lock (); + if (curlMultiHandles.find (handle) != curlMultiHandles.end ()) { + + CURLM* multi = curlMultiHandles[handle]; + curl_multi_remove_handle (multi, handle); + curlMultiHandles.erase (handle); + + } + if (curlValid.find (handle) != curlValid.end ()) { curlValid.erase (handle); @@ -112,6 +123,39 @@ namespace lime { } + void gc_curl_multi (value handle) { + + if (!val_is_null (handle)) { + + curl_gc_mutex.Lock (); + + if (curlMultiValid.find (handle) != curlMultiValid.end ()) { + + curlMultiValid.erase (handle); + curl_multi_cleanup ((CURL*)val_data(handle)); + + } + + for (std::map::iterator it = curlMultiHandles.begin (); it != curlMultiHandles.end (); ++it) { + + if (curlMultiHandles[it->first] == handle) { + + gc_curl (it->first); + + } + + } + + val_gc (handle, 0); + //handle = alloc_null (); + + curl_gc_mutex.Unlock (); + + } + + } + + void lime_curl_easy_cleanup (value handle) { // Disabled due to collision with GC-based cleanup @@ -335,7 +379,13 @@ namespace lime { int lime_curl_easy_perform (value easy_handle) { - return curl_easy_perform ((CURL*)val_data(easy_handle)); + int code; + gc_enter_blocking (); + + code = curl_easy_perform ((CURL*)val_data(easy_handle)); + + gc_exit_blocking (); + return code; } @@ -841,6 +891,96 @@ namespace lime { } + int lime_curl_multi_cleanup (value multi_handle) { + + curl_gc_mutex.Lock (); + + // CURLMcode result = curl_multi_cleanup ((CURLM*)val_data (multi_handle)); + gc_curl_multi (multi_handle); + + curl_gc_mutex.Unlock (); + + return CURLM_OK; + + } + + + value lime_curl_multi_init () { + + curl_gc_mutex.Lock (); + + value handle = CFFIPointer (curl_multi_init (), gc_curl_multi); + + if (curlMultiValid.find (handle) != curlMultiValid.end ()) { + + printf ("Error: Duplicate cURL Multi handle\n"); + + } + + curlMultiValid[handle] = true; + curlMultiRunningHandles[handle] = 0; + + curl_gc_mutex.Unlock (); + + return handle; + + } + + + int lime_curl_multi_add_handle (value multi_handle, value curl_handle) { + + curl_gc_mutex.Lock (); + + CURLMcode result = curl_multi_add_handle ((CURLM*)val_data (multi_handle), (CURL*)val_data (curl_handle)); + + if (result == CURLM_OK) { + + curlMultiHandles[curl_handle] = multi_handle; + + } + + curl_gc_mutex.Unlock (); + + return result; + + } + + + int lime_curl_multi_perform (value multi_handle) { + + curl_gc_mutex.Lock (); + + int runningHandles = 0; + CURLMcode result = lime_curl_multi_perform ((CURLM*)val_data (multi_handle), &runningHandles); + + curlMultiRunningHandles[multi_handle] = runningHandles; + + curl_gc_mutex.Unlock (); + + return result; + + } + + + int lime_curl_multi_remove_handle (value multi_handle, value curl_handle) { + + curl_gc_mutex.Lock (); + + CURLMcode result = curl_multi_remove_handle ((CURLM*)val_data (multi_handle), (CURL*)val_data (curl_handle)); + + if (/*result == CURLM_OK &&*/ curlMultiHandles.find (curl_handle) != curlMultiHandles.end ()) { + + curlMultiHandles.erase (curl_handle); + + } + + curl_gc_mutex.Unlock (); + + return result; + + } + + //lime_curl_multi_add_handle //lime_curl_multi_assign //lime_curl_multi_cleanup @@ -899,6 +1039,10 @@ namespace lime { DEFINE_PRIME2 (lime_curl_getdate); DEFINE_PRIME0v (lime_curl_global_cleanup); DEFINE_PRIME1 (lime_curl_global_init); + DEFINE_PRIME0 (lime_curl_multi_init); + DEFINE_PRIME2 (lime_curl_multi_add_handle); + DEFINE_PRIME2 (lime_curl_multi_perform); + DEFINE_PRIME2 (lime_curl_multi_remove_handle); DEFINE_PRIME0 (lime_curl_version); DEFINE_PRIME1 (lime_curl_version_info);