@@ -31,6 +31,12 @@ local FLAGS = {
3131 [ uv .READABLE + uv .WRITABLE ] = curl .CSELECT_IN + curl .CSELECT_OUT ;
3232}
3333
34+ local POLL_IO_FLAGS = {
35+ [ curl .POLL_IN ] = uv .READABLE ;
36+ [ curl .POLL_OUT ] = uv .WRITABLE ;
37+ [ curl .POLL_INOUT ] = uv .READABLE + uv .WRITABLE ;
38+ }
39+
3440local Context = ut .class () do
3541
3642function Context :__init (fd )
@@ -67,6 +73,31 @@ local qtask = ut.Queue.new() -- wait tasks
6773local qfree = ut .Queue .new () -- avaliable easy handles
6874local qeasy = {} -- all easy handles
6975
76+ local function on_begin (handle , url , num )
77+ local filename = tostring (num ) .. " .download"
78+ local file = io.open (filename , " w" )
79+ if not file then
80+ fprintf (stderr , " Error opening %s\n " , filename )
81+ return
82+ end
83+ handle .data .file = file
84+ handle :setopt_writefunction (file )
85+
86+ fprintf (stderr , " Added download %s -> %s\n " , url , filename );
87+ return true
88+ end
89+
90+ local function on_end (handle , err , url )
91+ handle .data .file :close ()
92+ handle .data .file = nil
93+
94+ if err then
95+ printf (" %s ERROR - %s\n " , url , tostring (err ));
96+ else
97+ printf (" %s DONE\n " , url );
98+ end
99+ end
100+
70101local function cleanup ()
71102 timer :close ()
72103
81112local proceed_queue , add_download do
82113
83114proceed_queue = function ()
84- if qtask :empty () then return end
85-
86- if qfree :empty () then
87- if # qeasy < MAX_REQUESTS then
88- local easy = assert (curl .easy ())
89- qeasy [# qeasy + 1 ] = easy
90- qfree :push (easy )
91- else
92- return
115+ while true do
116+ if qtask :empty () then return end
117+
118+ if qfree :empty () then
119+ if # qeasy < MAX_REQUESTS then
120+ local easy = assert (curl .easy ())
121+ qeasy [# qeasy + 1 ] = easy
122+ qfree :push (easy )
123+ else
124+ return
125+ end
93126 end
94- end
95127
96- local task = assert (qtask :pop ())
97- local url , num = task [1 ], task [2 ]
128+ local task = assert (qtask :pop ())
129+ local url , num = task [1 ], task [2 ]
98130
99- local filename = tostring (num ) .. " .download"
100- local file = io.open (filename , " w" )
101- if not file then
102- fprintf (stderr , " Error opening %s\n " , filename )
103- return
104- end
105-
106- local handle = assert (qfree :pop ())
131+ local handle = assert (qfree :pop ())
107132
108- handle :setopt {
109- url = url ;
110- writefunction = file ;
111- }
133+ handle :setopt {
134+ url = url ;
135+ fresh_connect = true ;
136+ forbid_reuse = true ;
137+ }
112138
113- handle .data = { file = file }
139+ handle .data = {}
114140
115- multi :add_handle (handle )
116-
117- fprintf (stderr , " Added download %s -> %s\n " , url , filename );
141+ if on_begin (handle , url , num ) then
142+ multi :add_handle (handle )
143+ else
144+ handle :reset ().data = nil
145+ qfree :push (handle )
146+ end
147+ end
118148end
119149
120150add_download = function (url , num )
@@ -143,17 +173,14 @@ on_curl_action = function(easy, fd, action)
143173 trace (" CURL::SOCKET" , easy , s , ACTION_NAMES [action ] or action )
144174
145175 local context = easy .data .context
146- if (action == curl .POLL_IN ) or (action == curl .POLL_OUT ) then
176+
177+ local flag = POLL_IO_FLAGS [action ]
178+ if flag then
147179 if not context then
148180 context = Context .new (fd )
149181 easy .data .context = context
150182 end
151- end
152-
153- assert (context :fileno () == fd )
154-
155- if action == curl .POLL_IN then context :poll (uv .READABLE , on_libuv_poll )
156- elseif action == curl .POLL_OUT then context :poll (uv .WRITABLE , on_libuv_poll )
183+ context :poll (flag , on_libuv_poll )
157184 elseif action == curl .POLL_REMOVE then
158185 if context then
159186 easy .data .context = nil
@@ -185,20 +212,15 @@ local curl_check_multi_info = function()
185212
186213 local context = easy .data .context
187214 if context then context :close () end
188- local file = assert (easy .data .file )
189- file :close ()
190-
191- easy .data = nil
192- qfree :push (easy )
215+ easy .data .context = nil
193216
194- if ok then
195- printf (" %s DONE\n " , done_url );
196- elseif data == " error" then
197- printf (" %s ERROR - %s\n " , done_url , tostring (err ));
198- end
217+ if ok then on_end (easy , nil , done_url ) else on_end (easy , err , done_url ) end
199218
200- proceed_queue ()
219+ easy :reset ().data = nil
220+ qfree :push (easy )
201221 end
222+
223+ proceed_queue ()
202224end
203225
204226on_libuv_poll = function (handle , err , events )
0 commit comments