@@ -42,6 +42,57 @@ function buffer_send_data(input::Channel{T}) where T <: ProtoType
4242end
4343=#
4444
45+ function share_lock (easy_p:: Ptr{Cvoid} , data:: curl_lock_data , access:: curl_lock_access , userptr:: Ptr{Cvoid} )
46+ share = unsafe_pointer_to_objref (Ptr {CurlShare} (userptr)):: CurlShare
47+ lock (share. locks[data])
48+ nothing
49+ end
50+
51+ function share_unlock (easy_p:: Ptr{Cvoid} , data:: curl_lock_data , userptr:: Ptr{Cvoid} )
52+ share = unsafe_pointer_to_objref (Ptr {CurlShare} (userptr)):: CurlShare
53+ unlock (share. locks[data])
54+ nothing
55+ end
56+
57+ mutable struct CurlShare
58+ shptr:: Ptr{CURLSH}
59+ locks:: Vector{ReentrantLock}
60+ closed:: Bool
61+
62+ function CurlShare ()
63+ shptr = curl_share_init ()
64+ curl_share_setopt (shptr, CURLSHOPT_SHARE, CURL_LOCK_DATA_SHARE)
65+ curl_share_setopt (shptr, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE)
66+ curl_share_setopt (shptr, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS)
67+ curl_share_setopt (shptr, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL)
68+ curl_share_setopt (shptr, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT)
69+
70+ share_lock_cb = @cfunction (share_lock, Cvoid, (Ptr{Cvoid}, Cuint, Cuint, Ptr{Cvoid}))
71+ share_unlock_cb = @cfunction (share_unlock, Cvoid, (Ptr{Cvoid}, Cuint, Ptr{Cvoid}))
72+
73+ @ccall LibCURL. LibCURL_jll. libcurl. curl_share_setopt (shptr:: Ptr{CURLSH} , CURLSHOPT_LOCKFUNC:: CURLSHoption ; share_lock_cb:: Ptr{Cvoid} ):: CURLSHcode
74+ @ccall LibCURL. LibCURL_jll. libcurl. curl_share_setopt (shptr:: Ptr{CURLSH} , CURLSHOPT_UNLOCKFUNC:: CURLSHoption ; share_unlock_cb:: Ptr{Cvoid} ):: CURLSHcode
75+
76+ locks = Vector (undef, CURL_LOCK_DATA_LAST)
77+ for idx in 1 : CURL_LOCK_DATA_LAST
78+ locks[idx] = ReentrantLock ()
79+ end
80+
81+ obj = new (shptr, locks, false )
82+ userptr = pointer_from_objref (obj)
83+ @ccall LibCURL. LibCURL_jll. libcurl. curl_share_setopt (shptr:: Ptr{CURLSH} , CURLSHOPT_USERDATA:: CURLSHoption ; userptr:: Ptr{Cvoid} ):: CURLSHcode
84+ obj
85+ end
86+ end
87+
88+ function close (share:: CurlShare )
89+ if share. closed
90+ curl_share_cleanup (share. shptr)
91+ share. closed = true
92+ end
93+ nothing
94+ end
95+
4596function send_data (easy:: Curl.Easy , input:: Channel{T} , max_send_message_length:: Int ) where T <: ProtoType
4697 while true
4798 yield ()
@@ -95,7 +146,7 @@ function grpc_request_header(request_timeout::Real)
95146 end
96147end
97148
98- function easy_handle (maxage:: Clong , keepalive:: Clong , negotiation:: Symbol , revocation:: Bool , request_timeout:: Real )
149+ function easy_handle (curlshare :: Union{Nothing,Ptr{CURLSH}} , maxage:: Clong , keepalive:: Clong , negotiation:: Symbol , revocation:: Bool , request_timeout:: Real )
99150 easy = Curl. Easy ()
100151 http_version = (negotiation === :http2 ) ? CURL_HTTP_VERSION_2_0 :
101152 (negotiation === :http2_tls ) ? CURL_HTTP_VERSION_2TLS :
@@ -105,6 +156,9 @@ function easy_handle(maxage::Clong, keepalive::Clong, negotiation::Symbol, revoc
105156 Curl. setopt (easy, CURLOPT_PIPEWAIT, Clong (1 ))
106157 Curl. setopt (easy, CURLOPT_POST, Clong (1 ))
107158 Curl. setopt (easy, CURLOPT_HTTPHEADER, grpc_request_header (request_timeout))
159+ if curlshare != = nothing
160+ Curl. setopt (easy, CURLOPT_SHARE, curlshare)
161+ end
108162 if ! revocation
109163 Curl. setopt (easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE)
110164 end
@@ -200,7 +254,7 @@ function get_grpc_status(easy::Curl.Easy)
200254 return grpc_status, grpc_message
201255end
202256
203- function grpc_request (downloader:: Downloader , url:: String , input:: Channel{T1} , output:: Channel{T2} ;
257+ function grpc_request (curlshare :: Union{Nothing,Ptr{CURLSH}} , downloader:: Downloader , url:: String , input:: Channel{T1} , output:: Channel{T2} ;
204258 maxage:: Clong = typemax (Clong),
205259 keepalive:: Clong = 60 ,
206260 negotiation:: Symbol = :http2_prior_knowledge ,
@@ -210,7 +264,7 @@ function grpc_request(downloader::Downloader, url::String, input::Channel{T1}, o
210264 max_recv_message_length:: Int = DEFAULT_MAX_RECV_MESSAGE_LENGTH,
211265 max_send_message_length:: Int = DEFAULT_MAX_SEND_MESSAGE_LENGTH,
212266 verbose:: Bool = false ):: gRPCStatus where {T1 <: ProtoType , T2 <: ProtoType }
213- Curl. with_handle (easy_handle (maxage, keepalive, negotiation, revocation, request_timeout)) do easy
267+ Curl. with_handle (easy_handle (curlshare, maxage, keepalive, negotiation, revocation, request_timeout)) do easy
214268 # setup the request
215269 Curl. set_url (easy, url)
216270 Curl. set_timeout (easy, request_timeout)
0 commit comments