@@ -42,6 +42,55 @@ 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_COOKIE)
65+         curl_share_setopt (shptr, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS)
66+         curl_share_setopt (shptr, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL)
67+ 
68+         share_lock_cb =  @cfunction (share_lock, Cvoid, (Ptr{Cvoid}, Cuint, Cuint, Ptr{Cvoid}))
69+         share_unlock_cb =  @cfunction (share_unlock, Cvoid, (Ptr{Cvoid}, Cuint, Ptr{Cvoid}))
70+ 
71+         @ccall  LibCURL. LibCURL_jll. libcurl. curl_share_setopt (shptr:: Ptr{CURLSH} , CURLSHOPT_LOCKFUNC:: CURLSHoption ; share_lock_cb:: Ptr{Cvoid} ):: CURLSHcode 
72+         @ccall  LibCURL. LibCURL_jll. libcurl. curl_share_setopt (shptr:: Ptr{CURLSH} , CURLSHOPT_UNLOCKFUNC:: CURLSHoption ; share_unlock_cb:: Ptr{Cvoid} ):: CURLSHcode 
73+ 
74+         locks =  Vector (undef, CURL_LOCK_DATA_LAST)
75+         for  idx in  1 : CURL_LOCK_DATA_LAST
76+             locks[idx] =  ReentrantLock ()
77+         end 
78+ 
79+         obj =  new (shptr, locks, false )
80+         userptr =  pointer_from_objref (obj)
81+         @ccall  LibCURL. LibCURL_jll. libcurl. curl_share_setopt (shptr:: Ptr{CURLSH} , CURLSHOPT_USERDATA:: CURLSHoption ; userptr:: Ptr{Cvoid} ):: CURLSHcode 
82+         obj
83+     end 
84+ end 
85+ 
86+ function  close (share:: CurlShare )
87+     if  share. closed
88+         curl_share_cleanup (share. shptr)
89+         share. closed =  true 
90+     end 
91+     nothing 
92+ end 
93+ 
4594function  send_data (easy:: Curl.Easy , input:: Channel{T} , max_send_message_length:: Int ) where  T <:  ProtoType 
4695    while  true 
4796        yield ()
@@ -95,7 +144,7 @@ function grpc_request_header(request_timeout::Real)
95144    end 
96145end 
97146
98- function  easy_handle (maxage:: Clong , keepalive:: Clong , negotiation:: Symbol , revocation:: Bool , request_timeout:: Real )
147+ function  easy_handle (curlshare :: Ptr{CURLSH} ,  maxage:: Clong , keepalive:: Clong , negotiation:: Symbol , revocation:: Bool , request_timeout:: Real )
99148    easy =  Curl. Easy ()
100149    http_version =  (negotiation ===  :http2 ) ?  CURL_HTTP_VERSION_2_0 : 
101150                   (negotiation ===  :http2_tls ) ?  CURL_HTTP_VERSION_2TLS : 
@@ -105,6 +154,7 @@ function easy_handle(maxage::Clong, keepalive::Clong, negotiation::Symbol, revoc
105154    Curl. setopt (easy, CURLOPT_PIPEWAIT, Clong (1 ))
106155    Curl. setopt (easy, CURLOPT_POST, Clong (1 ))
107156    Curl. setopt (easy, CURLOPT_HTTPHEADER, grpc_request_header (request_timeout))
157+     Curl. setopt (easy, CURLOPT_SHARE, curlshare)
108158    if  ! revocation
109159        Curl. setopt (easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE)
110160    end 
@@ -172,7 +222,7 @@ function set_connect_timeout(easy::Curl.Easy, timeout::Real)
172222    end 
173223end 
174224
175- function  grpc_request (downloader:: Downloader , url:: String , input:: Channel{T1} , output:: Channel{T2} ;
225+ function  grpc_request (curlshare :: Ptr{CURLSH} ,  downloader:: Downloader , url:: String , input:: Channel{T1} , output:: Channel{T2} ;
176226        maxage:: Clong  =  typemax (Clong),
177227        keepalive:: Clong  =  60 ,
178228        negotiation:: Symbol  =  :http2_prior_knowledge ,
@@ -182,7 +232,7 @@ function grpc_request(downloader::Downloader, url::String, input::Channel{T1}, o
182232        max_recv_message_length:: Int  =  DEFAULT_MAX_RECV_MESSAGE_LENGTH,
183233        max_send_message_length:: Int  =  DEFAULT_MAX_SEND_MESSAGE_LENGTH,
184234        verbose:: Bool  =  false ):: gRPCStatus  where  {T1 <:  ProtoType , T2 <:  ProtoType }
185-     Curl. with_handle (easy_handle (maxage, keepalive, negotiation, revocation, request_timeout)) do  easy
235+     Curl. with_handle (easy_handle (curlshare,  maxage, keepalive, negotiation, revocation, request_timeout)) do  easy
186236        #  setup the request
187237        Curl. set_url (easy, url)
188238        Curl. set_timeout (easy, request_timeout)
0 commit comments