aboutsummaryrefslogtreecommitdiff
path: root/etc/check-links-nb.lua
diff options
context:
space:
mode:
Diffstat (limited to 'etc/check-links-nb.lua')
-rw-r--r--etc/check-links-nb.lua81
1 files changed, 48 insertions, 33 deletions
diff --git a/etc/check-links-nb.lua b/etc/check-links-nb.lua
index 7e8df1b..c379e9a 100644
--- a/etc/check-links-nb.lua
+++ b/etc/check-links-nb.lua
@@ -84,17 +84,22 @@ function newcreate(thread)
84 first = (first or 1) - 1 84 first = (first or 1) - 1
85 local result, error 85 local result, error
86 while true do 86 while true do
87 -- tell dispatcher we want to keep sending before we
88 -- yield control
89 sending:insert(tcp)
90 -- return control to dispatcher
91 -- if upon return the dispatcher tells us we timed out,
92 -- return an error to whoever called us
93 if coroutine.yield() == "timeout" then
94 return nil, "timeout"
95 end
96 -- mark time we started waiting
97 context[tcp].last = socket.gettime()
98 -- try sending
87 result, error, first = tcp:send(data, first+1, last) 99 result, error, first = tcp:send(data, first+1, last)
88 if error == "timeout" then 100 -- if we are done, or there was an unexpected error,
89 -- tell dispatcher we want to keep sending 101 -- break away from loop
90 sending:insert(tcp) 102 if error ~= "timeout" then return result, error, first end
91 -- mark time we started waiting
92 context[tcp].last = socket.gettime()
93 -- return control to dispatcher
94 if coroutine.yield() == "timeout" then
95 return nil, "timeout"
96 end
97 else return result, error, first end
98 end 103 end
99 end, 104 end,
100 -- receive in non-blocking mode and yield on timeout 105 -- receive in non-blocking mode and yield on timeout
@@ -102,28 +107,35 @@ function newcreate(thread)
102 local error, partial = "timeout", "" 107 local error, partial = "timeout", ""
103 local value 108 local value
104 while true do 109 while true do
110 -- tell dispatcher we want to keep receiving before we
111 -- yield control
112 receiving:insert(tcp)
113 -- return control to dispatcher
114 -- if upon return the dispatcher tells us we timed out,
115 -- return an error to whoever called us
116 if coroutine.yield() == "timeout" then
117 return nil, "timeout"
118 end
119 -- mark time we started waiting
120 context[tcp].last = socket.gettime()
121 -- try receiving
105 value, error, partial = tcp:receive(pattern, partial) 122 value, error, partial = tcp:receive(pattern, partial)
106 if error == "timeout" then 123 -- if we are done, or there was an unexpected error,
107 -- tell dispatcher we want to keep receiving 124 -- break away from loop
108 receiving:insert(tcp) 125 if error ~= "timeout" then return value, error, partial end
109 -- mark time we started waiting
110 context[tcp].last = socket.gettime()
111 -- return control to dispatcher
112 if coroutine.yield() == "timeout" then
113 return nil, "timeout"
114 end
115 else return value, error, partial end
116 end 126 end
117 end, 127 end,
118 -- connect in non-blocking mode and yield on timeout 128 -- connect in non-blocking mode and yield on timeout
119 connect = function(self, host, port) 129 connect = function(self, host, port)
120 local result, error = tcp:connect(host, port) 130 local result, error = tcp:connect(host, port)
131 -- mark time we started waiting
132 context[tcp].last = socket.gettime()
121 if error == "timeout" then 133 if error == "timeout" then
122 -- tell dispatcher we will be able to write uppon connection 134 -- tell dispatcher we will be able to write uppon connection
123 sending:insert(tcp) 135 sending:insert(tcp)
124 -- mark time we started waiting
125 context[tcp].last = socket.gettime()
126 -- return control to dispatcher 136 -- return control to dispatcher
137 -- if upon return the dispatcher tells us we have a
138 -- timeout, just abort
127 if coroutine.yield() == "timeout" then 139 if coroutine.yield() == "timeout" then
128 return nil, "timeout" 140 return nil, "timeout"
129 end 141 end
@@ -148,10 +160,10 @@ function newcreate(thread)
148end 160end
149 161
150-- get the status of a URL, non-blocking 162-- get the status of a URL, non-blocking
151function getstatus(from, link) 163function getstatus(link)
152 local parsed = url.parse(link, {scheme = "file"}) 164 local parsed = url.parse(link, {scheme = "file"})
153 if parsed.scheme == "http" then 165 if parsed.scheme == "http" then
154 local thread = coroutine.create(function(thread, from, link) 166 local thread = coroutine.create(function(thread, link)
155 local r, c, h, s = http.request{ 167 local r, c, h, s = http.request{
156 method = "HEAD", 168 method = "HEAD",
157 url = link, 169 url = link,
@@ -162,7 +174,7 @@ function getstatus(from, link)
162 nthreads = nthreads - 1 174 nthreads = nthreads - 1
163 end) 175 end)
164 nthreads = nthreads + 1 176 nthreads = nthreads + 1
165 assert(coroutine.resume(thread, thread, from, link)) 177 assert(coroutine.resume(thread, thread, link))
166 end 178 end
167end 179end
168 180
@@ -190,6 +202,8 @@ function dispatch()
190 local now = socket.gettime() 202 local now = socket.gettime()
191 for who, data in pairs(context) do 203 for who, data in pairs(context) do
192 if data.last and now - data.last > TIMEOUT then 204 if data.last and now - data.last > TIMEOUT then
205 sending:remove(who)
206 receiving:remove(who)
193 assert(coroutine.resume(context[who].thread, "timeout")) 207 assert(coroutine.resume(context[who].thread, "timeout"))
194 end 208 end
195 end 209 end
@@ -206,14 +220,15 @@ function readfile(path)
206 else return nil, error end 220 else return nil, error end
207end 221end
208 222
209function retrieve(u) 223function load(u)
210 local parsed = url.parse(u, { scheme = "file" }) 224 local parsed = url.parse(u, { scheme = "file" })
211 local body, headers, code, error 225 local body, headers, code, error
212 local base = u 226 local base = u
213 if parsed.scheme == "http" then 227 if parsed.scheme == "http" then
214 body, code, headers = http.request(u) 228 body, code, headers = http.request(u)
215 if code == 200 then 229 if code == 200 then
216 base = base or headers.location 230 -- if there was a redirect, update base to reflect it
231 base = headers.location or base
217 end 232 end
218 if not body then 233 if not body then
219 error = code 234 error = code
@@ -241,12 +256,13 @@ function getlinks(body, base)
241 return links 256 return links
242end 257end
243 258
244function checklinks(from) 259function checklinks(address)
245 local base, body, error = retrieve(from) 260 local base, body, error = load(address)
246 if not body then print(error) return end 261 if not body then print(error) return end
262 print("Checking ", base)
247 local links = getlinks(body, base) 263 local links = getlinks(body, base)
248 for _, link in ipairs(links) do 264 for _, link in ipairs(links) do
249 getstatus(from, link) 265 getstatus(link)
250 end 266 end
251end 267end
252 268
@@ -255,8 +271,7 @@ if table.getn(arg) < 1 then
255 print("Usage:\n luasocket check-links.lua {<url>}") 271 print("Usage:\n luasocket check-links.lua {<url>}")
256 exit() 272 exit()
257end 273end
258for _, a in ipairs(arg) do 274for _, address in ipairs(arg) do
259 print("Checking ", a) 275 checklinks(url.absolute("file:", address))
260 checklinks(url.absolute("file:", a))
261end 276end
262dispatch() 277dispatch()