|
1 package.preload['util.logger']=(function(...) |
|
2 local t; |
|
3 if os.getenv("LAHTTP_DEBUG")then |
|
4 t=_G.print; |
|
5 else |
|
6 t=function()end; |
|
7 end |
|
8 local i,a=select,tostring; |
|
9 module"logger" |
|
10 local function e(t,...) |
|
11 local e,o=0,#arg; |
|
12 return(t:gsub("%%(.)",function(t)if t~="%"and e<=o then e=e+1;return a(arg[e]);end end)); |
|
13 end |
|
14 local function s(n,...) |
|
15 local e,t=0,i('#',...); |
|
16 local o={...}; |
|
17 return(n:gsub("%%(.)",function(i)if e<=t then e=e+1;return a(o[e]);end end)); |
|
18 end |
|
19 function init(e) |
|
20 return function(a,e,...) |
|
21 t(a,s(e,...)); |
|
22 end |
|
23 end |
|
24 return _M; |
|
25 end) |
|
26 package.preload['net.server']=(function(...) |
|
27 local l=function(e) |
|
28 return _G[e] |
|
29 end |
|
30 local J=function(e) |
|
31 for t,a in pairs(e)do |
|
32 e[t]=nil |
|
33 end |
|
34 end |
|
35 local w,e=require("util.logger").init("socket"),table.concat; |
|
36 local n=function(...)return w("debug",e{...});end |
|
37 local H=function(...)return w("warn",e{...});end |
|
38 local e=collectgarbage |
|
39 local ie=1 |
|
40 local A=l"type" |
|
41 local T=l"pairs" |
|
42 local he=l"ipairs" |
|
43 local h=l"tostring" |
|
44 local e=l"collectgarbage" |
|
45 local o=l"os" |
|
46 local a=l"table" |
|
47 local t=l"string" |
|
48 local e=l"coroutine" |
|
49 local V=o.time |
|
50 local R=o.difftime |
|
51 local te=a.concat |
|
52 local a=a.remove |
|
53 local B=t.len |
|
54 local de=t.sub |
|
55 local ue=e.wrap |
|
56 local le=e.yield |
|
57 local I=select(2,pcall(require,"ssl")) |
|
58 local L=require"socket" |
|
59 local ee=(I and I.wrap) |
|
60 local fe=L.bind |
|
61 local me=L.sleep |
|
62 local ce=L.select |
|
63 local e=(I and I.newcontext) |
|
64 local G |
|
65 local X |
|
66 local Z |
|
67 local W |
|
68 local Y |
|
69 local ne |
|
70 local re |
|
71 local se |
|
72 local ae |
|
73 local oe |
|
74 local P |
|
75 local d |
|
76 local Q |
|
77 local t |
|
78 local D |
|
79 local K |
|
80 local p |
|
81 local s |
|
82 local C |
|
83 local r |
|
84 local i |
|
85 local k |
|
86 local b |
|
87 local f |
|
88 local c |
|
89 local a |
|
90 local o |
|
91 local v |
|
92 local U |
|
93 local S |
|
94 local _ |
|
95 local j |
|
96 local M |
|
97 local u |
|
98 local z |
|
99 local x |
|
100 local O |
|
101 local E |
|
102 local q |
|
103 local N |
|
104 local F |
|
105 local g |
|
106 p={} |
|
107 s={} |
|
108 r={} |
|
109 C={} |
|
110 i={} |
|
111 b={} |
|
112 f={} |
|
113 k={} |
|
114 a=0 |
|
115 o=0 |
|
116 v=0 |
|
117 U=0 |
|
118 S=0 |
|
119 _=1 |
|
120 j=0 |
|
121 z=51e3*1024 |
|
122 x=25e3*1024 |
|
123 O=12e5 |
|
124 E=6e4 |
|
125 q=6*60*60 |
|
126 N=false |
|
127 g=1e3 |
|
128 _maxsslhandshake=30 |
|
129 ae=function(y,l,k,u,b,t,p,v) |
|
130 p=p or g |
|
131 local f=0 |
|
132 local g,c=y.onincoming,y.ondisconnect |
|
133 local m |
|
134 local c=false |
|
135 if t then |
|
136 c=true |
|
137 if not e then |
|
138 H"luasec not found" |
|
139 c=false |
|
140 end |
|
141 if A(t)~="table"then |
|
142 H"server.lua: wrong server sslctx" |
|
143 c=false |
|
144 end |
|
145 local o; |
|
146 o,m=e(t) |
|
147 if not o then |
|
148 m=m or"wrong sslctx parameters" |
|
149 local a; |
|
150 a=m:match("^error loading (.-) %("); |
|
151 if a then |
|
152 if a=="private key"then |
|
153 a=t.key or"your private key"; |
|
154 elseif a=="certificate"then |
|
155 a=t.certificate or"your certificate file"; |
|
156 end |
|
157 local e=m:match("%((.+)%)$")or"some reason"; |
|
158 if e=="Permission denied"then |
|
159 e="Check that the permissions allow Prosody to read this file."; |
|
160 elseif e=="No such file or directory"then |
|
161 e="Check that the path is correct, and the file exists."; |
|
162 elseif e=="system lib"then |
|
163 e="Previous error (see logs), or other system error."; |
|
164 else |
|
165 e="Reason: "..h(e or"unknown"):lower(); |
|
166 end |
|
167 w("error","SSL/TLS: Failed to load %s: %s",a,e); |
|
168 else |
|
169 w("error","SSL/TLS: Error initialising for port %d: %s",u,m); |
|
170 end |
|
171 c=false |
|
172 end |
|
173 t=o; |
|
174 end |
|
175 if not c then |
|
176 t=false; |
|
177 if v then |
|
178 w("error","Failed to listen on port %d due to SSL/TLS to SSL/TLS initialisation errors (see logs)",u) |
|
179 return nil,"Cannot start ssl, see log for details" |
|
180 end |
|
181 end |
|
182 local m=l.accept |
|
183 local e={} |
|
184 e.shutdown=function()end |
|
185 e.ssl=function() |
|
186 return c |
|
187 end |
|
188 e.sslctx=function() |
|
189 return t |
|
190 end |
|
191 e.remove=function() |
|
192 f=f-1 |
|
193 end |
|
194 e.close=function() |
|
195 for t,e in T(i)do |
|
196 if e.serverport==u then |
|
197 e.disconnect(e,"server closed") |
|
198 e:close(true) |
|
199 end |
|
200 end |
|
201 l:close() |
|
202 o=d(r,l,o) |
|
203 a=d(s,l,a) |
|
204 i[l]=nil |
|
205 e=nil |
|
206 l=nil |
|
207 n"server.lua: closed server handler and removed sockets from list" |
|
208 end |
|
209 e.ip=function() |
|
210 return k |
|
211 end |
|
212 e.serverport=function() |
|
213 return u |
|
214 end |
|
215 e.socket=function() |
|
216 return l |
|
217 end |
|
218 e.readbuffer=function() |
|
219 if f>p then |
|
220 n("server.lua: refused new client connection: server full") |
|
221 return false |
|
222 end |
|
223 local a,s=m(l) |
|
224 if a then |
|
225 local i,o=a:getpeername() |
|
226 a:settimeout(0) |
|
227 local e,a,t=D(e,y,a,i,u,o,b,t,v) |
|
228 if t then |
|
229 return false |
|
230 end |
|
231 f=f+1 |
|
232 n("server.lua: accepted new client connection from ",h(i),":",h(o)," to ",h(u)) |
|
233 return g(e) |
|
234 elseif s then |
|
235 n("server.lua: error with new client connection: ",h(s)) |
|
236 return false |
|
237 end |
|
238 end |
|
239 return e |
|
240 end |
|
241 D=function(M,e,t,I,Y,L,_,p,P) |
|
242 t:settimeout(0) |
|
243 local w |
|
244 local T |
|
245 local q |
|
246 local v |
|
247 local O=e.onincoming |
|
248 local F=e.status |
|
249 local g=e.ondisconnect |
|
250 local y={} |
|
251 local m=0 |
|
252 local C |
|
253 local A |
|
254 local D |
|
255 local l=0 |
|
256 local j=false |
|
257 local E=false |
|
258 local H,R=0,0 |
|
259 local z=z |
|
260 local x=x |
|
261 local e=y |
|
262 e.dispatch=function() |
|
263 return O |
|
264 end |
|
265 e.disconnect=function() |
|
266 return g |
|
267 end |
|
268 e.setlistener=function(a,t) |
|
269 O=t.onincoming |
|
270 g=t.ondisconnect |
|
271 end |
|
272 e.getstats=function() |
|
273 return R,H |
|
274 end |
|
275 e.ssl=function() |
|
276 return v |
|
277 end |
|
278 e.sslctx=function() |
|
279 return p |
|
280 end |
|
281 e.send=function(n,i,o,a) |
|
282 return w(t,i,o,a) |
|
283 end |
|
284 e.receive=function(a,o) |
|
285 return T(t,a,o) |
|
286 end |
|
287 e.shutdown=function(a) |
|
288 return q(t,a) |
|
289 end |
|
290 e.close=function(u,h) |
|
291 if not e then return true;end |
|
292 a=d(s,t,a) |
|
293 b[e]=nil |
|
294 if m~=0 then |
|
295 if not(h or A)then |
|
296 e.sendbuffer() |
|
297 if m~=0 then |
|
298 if e then |
|
299 e.write=nil |
|
300 end |
|
301 C=true |
|
302 return false |
|
303 end |
|
304 else |
|
305 w(t,te(y,"",1,m),1,l) |
|
306 end |
|
307 end |
|
308 if t then |
|
309 c=q and q(t) |
|
310 t:close() |
|
311 o=d(r,t,o) |
|
312 i[t]=nil |
|
313 t=nil |
|
314 else |
|
315 n"server.lua: socket already closed" |
|
316 end |
|
317 if e then |
|
318 f[e]=nil |
|
319 k[e]=nil |
|
320 e=nil |
|
321 end |
|
322 if M then |
|
323 M.remove() |
|
324 end |
|
325 n"server.lua: closed client handler and removed socket from list" |
|
326 return true |
|
327 end |
|
328 e.ip=function() |
|
329 return I |
|
330 end |
|
331 e.serverport=function() |
|
332 return Y |
|
333 end |
|
334 e.clientport=function() |
|
335 return L |
|
336 end |
|
337 local k=function(i,a) |
|
338 l=l+B(a) |
|
339 if l>z then |
|
340 k[e]="send buffer exceeded" |
|
341 e.write=W |
|
342 return false |
|
343 elseif t and not r[t]then |
|
344 o=addsocket(r,t,o) |
|
345 end |
|
346 m=m+1 |
|
347 y[m]=a |
|
348 if e then |
|
349 f[e]=f[e]or u |
|
350 end |
|
351 return true |
|
352 end |
|
353 e.write=k |
|
354 e.bufferqueue=function(t) |
|
355 return y |
|
356 end |
|
357 e.socket=function(a) |
|
358 return t |
|
359 end |
|
360 e.pattern=function(a,t) |
|
361 _=t or _ |
|
362 return _ |
|
363 end |
|
364 e.set_send=function(a,t) |
|
365 w=t or w |
|
366 return w |
|
367 end |
|
368 e.bufferlen=function(o,t,a) |
|
369 z=a or z |
|
370 x=t or x |
|
371 return l,x,z |
|
372 end |
|
373 e.lock_read=function(i,o) |
|
374 if o==true then |
|
375 local o=a |
|
376 a=d(s,t,a) |
|
377 b[e]=nil |
|
378 if a~=o then |
|
379 j=true |
|
380 end |
|
381 elseif o==false then |
|
382 if j then |
|
383 j=false |
|
384 a=addsocket(s,t,a) |
|
385 b[e]=u |
|
386 end |
|
387 end |
|
388 return j |
|
389 end |
|
390 e.lock=function(i,a) |
|
391 e.lock_read(a) |
|
392 if a==true then |
|
393 e.write=W |
|
394 local a=o |
|
395 o=d(r,t,o) |
|
396 f[e]=nil |
|
397 if o~=a then |
|
398 E=true |
|
399 end |
|
400 elseif a==false then |
|
401 e.write=k |
|
402 if E then |
|
403 E=false |
|
404 k("") |
|
405 end |
|
406 end |
|
407 return j,E |
|
408 end |
|
409 local b=function() |
|
410 local o,t,a=T(t,_) |
|
411 if not t or(t=="wantread"or t=="timeout")or B(a)>0 then |
|
412 local o=o or a or"" |
|
413 local a=B(o) |
|
414 if a>x then |
|
415 g(e,"receive buffer exceeded") |
|
416 e.close(true) |
|
417 return false |
|
418 end |
|
419 local a=a*ie |
|
420 R=R+a |
|
421 S=S+a |
|
422 b[e]=u |
|
423 return O(e,o,t) |
|
424 else |
|
425 n("server.lua: client ",h(I),":",h(L)," read error: ",h(t)) |
|
426 A=true |
|
427 g(e,t) |
|
428 c=e and e.close() |
|
429 return false |
|
430 end |
|
431 end |
|
432 local f=function() |
|
433 local p,a,i,s,v; |
|
434 local v; |
|
435 if t then |
|
436 s=te(y,"",1,m) |
|
437 p,a,i=w(t,s,1,l) |
|
438 v=(p or i or 0)*ie |
|
439 H=H+v |
|
440 U=U+v |
|
441 c=N and J(y) |
|
442 else |
|
443 p,a,v=false,"closed",0; |
|
444 end |
|
445 if p then |
|
446 m=0 |
|
447 l=0 |
|
448 o=d(r,t,o) |
|
449 c=D and e:starttls(true) |
|
450 f[e]=nil |
|
451 c=C and e.close() |
|
452 return true |
|
453 elseif i and(a=="timeout"or a=="wantwrite")then |
|
454 s=de(s,i+1,l) |
|
455 y[1]=s |
|
456 m=1 |
|
457 l=l-i |
|
458 f[e]=u |
|
459 return true |
|
460 else |
|
461 n("server.lua: client ",h(I),":",h(L)," write error: ",h(a)) |
|
462 A=true |
|
463 g(e,a) |
|
464 c=e and e.close() |
|
465 return false |
|
466 end |
|
467 end |
|
468 local l; |
|
469 function e.set_sslctx(i,t) |
|
470 v=true |
|
471 p=t; |
|
472 local u |
|
473 local m |
|
474 l=ue(function(t) |
|
475 local i |
|
476 for l=1,_maxsslhandshake do |
|
477 o=(u and d(r,t,o))or o |
|
478 a=(m and d(s,t,a))or a |
|
479 m,u=nil,nil |
|
480 c,i=t:dohandshake() |
|
481 if not i then |
|
482 n("server.lua: ssl handshake done") |
|
483 e.readbuffer=b |
|
484 e.sendbuffer=f |
|
485 c=F and F(e,"ssl-handshake-complete") |
|
486 a=addsocket(s,t,a) |
|
487 return true |
|
488 else |
|
489 n("server.lua: error during ssl handshake: ",h(i)) |
|
490 if i=="wantwrite"and not u then |
|
491 o=addsocket(r,t,o) |
|
492 u=true |
|
493 elseif i=="wantread"and not m then |
|
494 a=addsocket(s,t,a) |
|
495 m=true |
|
496 else |
|
497 break; |
|
498 end |
|
499 le() |
|
500 end |
|
501 end |
|
502 g(e,"ssl handshake failed") |
|
503 c=e and e:close(true) |
|
504 return false |
|
505 end |
|
506 ) |
|
507 end |
|
508 if p then |
|
509 e:set_sslctx(p); |
|
510 if P then |
|
511 local a |
|
512 t,a=ee(t,p) |
|
513 if a then |
|
514 n("server.lua: ssl error: ",h(a)) |
|
515 return nil,nil,a |
|
516 end |
|
517 t:settimeout(0) |
|
518 e.readbuffer=l |
|
519 e.sendbuffer=l |
|
520 l(t) |
|
521 if not t then |
|
522 return nil,nil,"ssl handshake failed"; |
|
523 end |
|
524 else |
|
525 v=false |
|
526 e.starttls=function(c,u) |
|
527 if not u then |
|
528 D=true |
|
529 return |
|
530 end |
|
531 local c,u=t |
|
532 t,u=ee(t,p) |
|
533 if u then |
|
534 n("server.lua: error while starting tls on client: ",h(u)) |
|
535 return nil,u |
|
536 end |
|
537 t:settimeout(0) |
|
538 w=t.send |
|
539 T=t.receive |
|
540 q=G |
|
541 i[t]=e |
|
542 a=addsocket(s,t,a) |
|
543 a=d(s,c,a) |
|
544 o=d(r,c,o) |
|
545 i[c]=nil |
|
546 e.starttls=nil |
|
547 D=nil |
|
548 v=true |
|
549 e.readbuffer=l |
|
550 e.sendbuffer=l |
|
551 l(t) |
|
552 end |
|
553 e.readbuffer=b |
|
554 e.sendbuffer=f |
|
555 end |
|
556 else |
|
557 v=false |
|
558 e.readbuffer=b |
|
559 e.sendbuffer=f |
|
560 end |
|
561 w=t.send |
|
562 T=t.receive |
|
563 q=(v and G)or t.shutdown |
|
564 i[t]=e |
|
565 a=addsocket(s,t,a) |
|
566 return e,t |
|
567 end |
|
568 G=function() |
|
569 end |
|
570 W=function() |
|
571 return false |
|
572 end |
|
573 addsocket=function(a,t,e) |
|
574 if not a[t]then |
|
575 e=e+1 |
|
576 a[e]=t |
|
577 a[t]=e |
|
578 end |
|
579 return e; |
|
580 end |
|
581 d=function(e,a,t) |
|
582 local o=e[a] |
|
583 if o then |
|
584 e[a]=nil |
|
585 local i=e[t] |
|
586 e[t]=nil |
|
587 if i~=a then |
|
588 e[i]=o |
|
589 e[o]=i |
|
590 end |
|
591 return t-1 |
|
592 end |
|
593 return t |
|
594 end |
|
595 P=function(e) |
|
596 o=d(r,e,o) |
|
597 a=d(s,e,a) |
|
598 i[e]=nil |
|
599 e:close() |
|
600 end |
|
601 re=function(o,e,d,u,r,l) |
|
602 local t |
|
603 if A(d)~="table"then |
|
604 t="invalid listener table" |
|
605 end |
|
606 if not A(e)=="number"or not(e>=0 and e<=65535)then |
|
607 t="invalid port" |
|
608 elseif p[e]then |
|
609 t="listeners on port '"..e.."' already exist" |
|
610 elseif r and not I then |
|
611 t="luasec not found" |
|
612 end |
|
613 if t then |
|
614 H("server.lua, port ",e,": ",t) |
|
615 return nil,t |
|
616 end |
|
617 o=o or"*" |
|
618 local t,h=fe(o,e) |
|
619 if h then |
|
620 H("server.lua, port ",e,": ",h) |
|
621 return nil,h |
|
622 end |
|
623 local h,r=ae(d,t,o,e,u,r,g,l) |
|
624 if not h then |
|
625 t:close() |
|
626 return nil,r |
|
627 end |
|
628 t:settimeout(0) |
|
629 a=addsocket(s,t,a) |
|
630 p[e]=h |
|
631 i[t]=h |
|
632 n("server.lua: new server listener on '",o,":",e,"'") |
|
633 return h |
|
634 end |
|
635 se=function(e) |
|
636 return p[e]; |
|
637 end |
|
638 Q=function(e) |
|
639 local t=p[e] |
|
640 if not t then |
|
641 return nil,"no server found on port '"..h(e).."'" |
|
642 end |
|
643 t:close() |
|
644 p[e]=nil |
|
645 return true |
|
646 end |
|
647 ne=function() |
|
648 for t,e in T(i)do |
|
649 e:close() |
|
650 i[t]=nil |
|
651 end |
|
652 a=0 |
|
653 o=0 |
|
654 v=0 |
|
655 p={} |
|
656 s={} |
|
657 r={} |
|
658 C={} |
|
659 i={} |
|
660 end |
|
661 oe=function() |
|
662 return _,j,z,x,O,E,q,N,g,_maxsslhandshake |
|
663 end |
|
664 K=function(e) |
|
665 if A(e)~="table"then |
|
666 return nil,"invalid settings table" |
|
667 end |
|
668 _=tonumber(e.timeout)or _ |
|
669 j=tonumber(e.sleeptime)or j |
|
670 z=tonumber(e.maxsendlen)or z |
|
671 x=tonumber(e.maxreadlen)or x |
|
672 O=tonumber(e.checkinterval)or O |
|
673 E=tonumber(e.sendtimeout)or E |
|
674 q=tonumber(e.readtimeout)or q |
|
675 N=e.cleanqueue |
|
676 g=e._maxclientsperserver or g |
|
677 _maxsslhandshake=e._maxsslhandshake or _maxsslhandshake |
|
678 return true |
|
679 end |
|
680 Y=function(e) |
|
681 if A(e)~="function"then |
|
682 return nil,"invalid listener function" |
|
683 end |
|
684 v=v+1 |
|
685 C[v]=e |
|
686 return true |
|
687 end |
|
688 Z=function() |
|
689 return S,U,a,o,v |
|
690 end |
|
691 local e=true; |
|
692 setquitting=function(t) |
|
693 e=not t; |
|
694 return; |
|
695 end |
|
696 X=function() |
|
697 while e do |
|
698 local a,e,t=ce(s,r,_) |
|
699 for e,t in he(e)do |
|
700 local e=i[t] |
|
701 if e then |
|
702 e.sendbuffer() |
|
703 else |
|
704 P(t) |
|
705 n"server.lua: found no handler and closed socket (writelist)" |
|
706 end |
|
707 end |
|
708 for t,e in he(a)do |
|
709 local t=i[e] |
|
710 if t then |
|
711 t.readbuffer() |
|
712 else |
|
713 P(e) |
|
714 n"server.lua: found no handler and closed socket (readlist)" |
|
715 end |
|
716 end |
|
717 for e,t in T(k)do |
|
718 e.disconnect()(e,t) |
|
719 e:close(true) |
|
720 end |
|
721 J(k) |
|
722 u=V() |
|
723 if R(u-F)>=1 then |
|
724 for e=1,v do |
|
725 C[e](u) |
|
726 end |
|
727 F=u |
|
728 end |
|
729 me(j) |
|
730 end |
|
731 return"quitting" |
|
732 end |
|
733 local function s() |
|
734 return"select"; |
|
735 end |
|
736 local n=function(e,s,n,t,a,h,d) |
|
737 local t=D(nil,t,e,s,n,"clientport",a,h,d) |
|
738 i[e]=t |
|
739 o=addsocket(r,e,o) |
|
740 return t,e |
|
741 end |
|
742 local t=function(a,o,i,s,r,h) |
|
743 local t,e=L.tcp() |
|
744 if e then |
|
745 return nil,e |
|
746 end |
|
747 t:settimeout(0) |
|
748 c,e=t:connect(a,o) |
|
749 if e then |
|
750 local e=n(t,a,o,i) |
|
751 else |
|
752 D(nil,i,t,a,o,"clientport",s,r,h) |
|
753 end |
|
754 end |
|
755 l"setmetatable"(i,{__mode="k"}) |
|
756 l"setmetatable"(b,{__mode="k"}) |
|
757 l"setmetatable"(f,{__mode="k"}) |
|
758 F=V() |
|
759 M=V() |
|
760 Y(function() |
|
761 local e=R(u-M) |
|
762 if e>O then |
|
763 M=u |
|
764 for e,t in T(f)do |
|
765 if R(u-t)>E then |
|
766 e.disconnect()(e,"send timeout") |
|
767 e:close(true) |
|
768 end |
|
769 end |
|
770 for e,t in T(b)do |
|
771 if R(u-t)>q then |
|
772 e.disconnect()(e,"read timeout") |
|
773 e:close() |
|
774 end |
|
775 end |
|
776 end |
|
777 end |
|
778 ) |
|
779 return{ |
|
780 addclient=t, |
|
781 wrapclient=n, |
|
782 loop=X, |
|
783 stats=Z, |
|
784 closeall=ne, |
|
785 addtimer=Y, |
|
786 addserver=re, |
|
787 getserver=se, |
|
788 getsettings=oe, |
|
789 setquitting=setquitting, |
|
790 removeserver=Q, |
|
791 get_backend=s, |
|
792 changesettings=K, |
|
793 } |
|
794 end) |
|
795 package.preload['net.httpclient_listener']=(function(...) |
|
796 local a=require"util.logger".init("httpclient_listener"); |
|
797 local i=require"net.connlisteners".register; |
|
798 local e={}; |
|
799 local t={}; |
|
800 local t={default_port=80,default_mode="*a"}; |
|
801 function t.onincoming(t,o) |
|
802 local e=e[t]; |
|
803 if not e then |
|
804 a("warn","Received response from connection %s with no request attached!",tostring(t)); |
|
805 return; |
|
806 end |
|
807 if o and e.reader then |
|
808 e:reader(o); |
|
809 end |
|
810 end |
|
811 function t.ondisconnect(a,t) |
|
812 local t=e[a]; |
|
813 if t then |
|
814 t:reader(nil); |
|
815 end |
|
816 e[a]=nil; |
|
817 end |
|
818 function t.register_request(o,t) |
|
819 a("debug","Attaching request %s to connection %s",tostring(t.id or t),tostring(o)); |
|
820 e[o]=t; |
|
821 end |
|
822 i("httpclient",t); |
|
823 end) |
|
824 package.preload['net.connlisteners']=(function(...) |
|
825 local r=(CFG_SOURCEDIR or".").."/net/"; |
|
826 local h=require"net.server"; |
|
827 local o=require"util.logger".init("connlisteners"); |
|
828 local i=tostring; |
|
829 local s,n,a= |
|
830 dofile,pcall,error |
|
831 module"connlisteners" |
|
832 local e={}; |
|
833 function register(t,a) |
|
834 if e[t]and e[t]~=a then |
|
835 o("debug","Listener %s is already registered, not registering any more",t); |
|
836 return false; |
|
837 end |
|
838 e[t]=a; |
|
839 o("debug","Registered connection listener %s",t); |
|
840 return true; |
|
841 end |
|
842 function deregister(t) |
|
843 e[t]=nil; |
|
844 end |
|
845 function get(t) |
|
846 local a=e[t]; |
|
847 if not a then |
|
848 local s,n=n(s,r..t:gsub("[^%w%-]","_").."_listener.lua"); |
|
849 if not s then |
|
850 o("error","Error while loading listener '%s': %s",i(t),i(n)); |
|
851 return nil,n; |
|
852 end |
|
853 a=e[t]; |
|
854 end |
|
855 return a; |
|
856 end |
|
857 function start(o,e) |
|
858 local t,n=get(o); |
|
859 if not t then |
|
860 a("No such connection module: "..o..(n and(" ("..n..")")or""),0); |
|
861 end |
|
862 if e then |
|
863 if(e.type=="ssl"or e.type=="tls")and not e.ssl then |
|
864 a("No SSL context supplied for a "..i(e.type):upper().." connection!",0); |
|
865 elseif e.ssl and e.type=="tcp"then |
|
866 a("SSL context supplied for a TCP connection!",0); |
|
867 end |
|
868 end |
|
869 local i=(e and e.interface)or t.default_interface or"*"; |
|
870 local o=(e and e.port)or t.default_port or a("Can't start listener "..o.." because no port was specified, and it has no default port",0); |
|
871 local a=(e and e.mode)or t.default_mode or 1; |
|
872 local n=(e and e.ssl)or nil; |
|
873 local s=99999999; |
|
874 local e=e and e.type=="ssl"; |
|
875 return h.addserver(i,o,t,a,n,e); |
|
876 end |
|
877 return _M; |
|
878 end) |
|
879 package.preload['net.http']=(function(...) |
|
880 local b=require"socket" |
|
881 local v=require"mime" |
|
882 local y=require"socket.url" |
|
883 local p=require"net.server" |
|
884 local e=require"net.connlisteners".get; |
|
885 local d=e("httpclient")or error("No httpclient listener!"); |
|
886 local r,i=table.insert,table.concat; |
|
887 local s,u,c,m,f,l,t,a= |
|
888 tonumber,tostring,pairs,xpcall,select,debug.traceback,string.char,string.format; |
|
889 local n=require"util.logger".init("http"); |
|
890 local o=function()end |
|
891 module"http" |
|
892 function urlencode(e)return e and(e:gsub("%W",function(e)return a("%%%02x",e:byte());end));end |
|
893 function urldecode(e)return e and(e:gsub("%%(%x%x)",function(e)return t(s(e,16));end));end |
|
894 local function w(t,e) |
|
895 if t.method=="HEAD"then return nil end |
|
896 if e==204 or e==304 or e==301 then return nil end |
|
897 if e>=100 and e<200 then return nil end |
|
898 return 1 |
|
899 end |
|
900 local function h(e,t,a) |
|
901 if not t then |
|
902 if e.body then |
|
903 n("debug","Connection closed, but we have data, calling callback..."); |
|
904 e.callback(i(e.body),e.code,e); |
|
905 elseif e.state~="completed"then |
|
906 e.callback("connection-closed",0,e); |
|
907 end |
|
908 destroy_request(e); |
|
909 e.body=nil; |
|
910 e.state="completed"; |
|
911 return; |
|
912 end |
|
913 if e.state=="body"and e.state~="completed"then |
|
914 o("Reading body...") |
|
915 if not e.body then e.body={};e.havebodylength,e.bodylength=0,s(e.responseheaders["content-length"]);end |
|
916 if a then |
|
917 t=t:sub(a,-1) |
|
918 end |
|
919 r(e.body,t); |
|
920 if e.bodylength then |
|
921 e.havebodylength=e.havebodylength+#t; |
|
922 if e.havebodylength>=e.bodylength then |
|
923 n("debug","Have full body, calling callback"); |
|
924 if e.callback then |
|
925 e.callback(i(e.body),e.code,e); |
|
926 end |
|
927 e.body=nil; |
|
928 e.state="completed"; |
|
929 else |
|
930 o("","Have "..e.havebodylength.." bytes out of "..e.bodylength); |
|
931 end |
|
932 end |
|
933 elseif e.state=="headers"then |
|
934 o("Reading headers...") |
|
935 local i=a; |
|
936 local n=e.responseheaders or{}; |
|
937 for t in t:sub(a,-1):gmatch("(.-)\r\n")do |
|
938 a=a+#t+2; |
|
939 local a,i=t:match("(%S+): (.+)"); |
|
940 if a and i then |
|
941 n[a:lower()]=i; |
|
942 o("Header: "..a:lower().." = "..i); |
|
943 elseif#t==0 then |
|
944 e.responseheaders=n; |
|
945 break; |
|
946 else |
|
947 o("Unhandled header line: "..t); |
|
948 end |
|
949 end |
|
950 e.state="body"; |
|
951 if#t>a then |
|
952 return h(e,t,a); |
|
953 end |
|
954 elseif e.state=="status"then |
|
955 o("Reading status...") |
|
956 local i,a,n,o=t:match("^HTTP/(%S+) (%d+) (.-)\r\n()",a); |
|
957 a=s(a); |
|
958 if not a then |
|
959 return e.callback("invalid-status-line",0,e); |
|
960 end |
|
961 e.code,e.responseversion=a,i; |
|
962 if e.onlystatus or not w(e,a)then |
|
963 if e.callback then |
|
964 e.callback(nil,a,e); |
|
965 end |
|
966 destroy_request(e); |
|
967 return; |
|
968 end |
|
969 e.state="headers"; |
|
970 if#t>o then |
|
971 return h(e,t,o); |
|
972 end |
|
973 end |
|
974 end |
|
975 local function w(e)n("error","Traceback[http]: %s: %s",u(e),l());end |
|
976 function request(e,a,s) |
|
977 local e=y.parse(e); |
|
978 if not(e and e.host)then |
|
979 s(nil,0,e); |
|
980 return nil,"invalid-url"; |
|
981 end |
|
982 if not e.path then |
|
983 e.path="/"; |
|
984 end |
|
985 local l,o; |
|
986 local t={["Host"]=e.host,["User-Agent"]="Prosody XMPP Server"} |
|
987 if e.userinfo then |
|
988 t["Authorization"]="Basic "..v.b64(e.userinfo); |
|
989 end |
|
990 if a then |
|
991 l=a.headers; |
|
992 e.onlystatus=a.onlystatus; |
|
993 o=a.body; |
|
994 if o then |
|
995 e.method="POST "; |
|
996 t["Content-Length"]=u(#o); |
|
997 t["Content-Type"]="application/x-www-form-urlencoded"; |
|
998 end |
|
999 if a.method then e.method=a.method;end |
|
1000 end |
|
1001 e.handler,e.conn=p.wrapclient(b.tcp(),e.host,e.port or 80,d,"*a"); |
|
1002 e.write=function(...)return e.handler:write(...);end |
|
1003 e.conn:settimeout(0); |
|
1004 local u,a=e.conn:connect(e.host,e.port or 80); |
|
1005 if not u and a~="timeout"then |
|
1006 s(nil,0,e); |
|
1007 return nil,a; |
|
1008 end |
|
1009 local a={e.method or"GET"," ",e.path," HTTP/1.1\r\n"}; |
|
1010 if e.query then |
|
1011 r(a,4,"?"); |
|
1012 r(a,5,e.query); |
|
1013 end |
|
1014 e.write(i(a)); |
|
1015 local a={[2]=": ",[4]="\r\n"}; |
|
1016 if l then |
|
1017 for o,n in c(l)do |
|
1018 a[1],a[3]=o,n; |
|
1019 e.write(i(a)); |
|
1020 t[o]=nil; |
|
1021 end |
|
1022 end |
|
1023 for o,n in c(t)do |
|
1024 a[1],a[3]=o,n; |
|
1025 e.write(i(a)); |
|
1026 t[o]=nil; |
|
1027 end |
|
1028 e.write("\r\n"); |
|
1029 if o then |
|
1030 e.write(o); |
|
1031 end |
|
1032 e.callback=function(a,t,o)n("debug","Calling callback, status %s",t or"---");return f(2,m(function()return s(a,t,o)end,w));end |
|
1033 e.reader=h; |
|
1034 e.state="status"; |
|
1035 d.register_request(e.handler,e); |
|
1036 return e; |
|
1037 end |
|
1038 function destroy_request(e) |
|
1039 if e.conn then |
|
1040 e.handler.close() |
|
1041 d.ondisconnect(e.conn,"closed"); |
|
1042 end |
|
1043 end |
|
1044 _M.urlencode=urlencode; |
|
1045 return _M; |
|
1046 end) |
|
1047 package.preload['util.timer']=(function(...) |
|
1048 local h=require"net.server".addtimer; |
|
1049 local a=require"net.server".event; |
|
1050 local d=require"net.server".event_base; |
|
1051 local s=os.time; |
|
1052 local n=table.insert; |
|
1053 local e=table.remove; |
|
1054 local e,i=ipairs,pairs; |
|
1055 local r=type; |
|
1056 local o={}; |
|
1057 local t={}; |
|
1058 module"timer" |
|
1059 local e; |
|
1060 if not a then |
|
1061 function e(e,a) |
|
1062 local o=s(); |
|
1063 e=e+o; |
|
1064 if e>=o then |
|
1065 n(t,{e,a}); |
|
1066 else |
|
1067 a(); |
|
1068 end |
|
1069 end |
|
1070 h(function() |
|
1071 local s=s(); |
|
1072 if#t>0 then |
|
1073 for a,e in i(t)do |
|
1074 n(o,e); |
|
1075 end |
|
1076 t={}; |
|
1077 end |
|
1078 for i,t in i(o)do |
|
1079 local t,a=t[1],t[2]; |
|
1080 if t<=s then |
|
1081 o[i]=nil; |
|
1082 local t=a(s); |
|
1083 if r(t)=="number"then e(t,a);end |
|
1084 end |
|
1085 end |
|
1086 end); |
|
1087 else |
|
1088 local t=(a.core and a.core.LEAVE)or-1; |
|
1089 function e(a,e) |
|
1090 d:addevent(nil,0,function() |
|
1091 local e=e(); |
|
1092 if e then |
|
1093 return 0,e; |
|
1094 else |
|
1095 return t; |
|
1096 end |
|
1097 end |
|
1098 ,a); |
|
1099 end |
|
1100 end |
|
1101 add_task=e; |
|
1102 return _M; |
|
1103 end) |
|
1104 package.preload['multihttp']=(function(...) |
|
1105 local s=require"net.http"; |
|
1106 local o=require"net.server"; |
|
1107 local i=require"util.timer"; |
|
1108 local n,h,r,d= |
|
1109 pairs,ipairs,type,setmetatable; |
|
1110 module"multihttp" |
|
1111 __index=_M; |
|
1112 function set_callback(t,e) |
|
1113 t.callback=e; |
|
1114 end |
|
1115 function set_progress_callback(e,a,t) |
|
1116 t=t or 1; |
|
1117 e.progress_callback=a; |
|
1118 i.add_task(t,function() |
|
1119 if e.progress_callback then |
|
1120 e.progress_callback(e); |
|
1121 if e.progress_callback then |
|
1122 return t; |
|
1123 end |
|
1124 end |
|
1125 end); |
|
1126 end |
|
1127 function add_url(t,e) |
|
1128 t.urls[e]=true; |
|
1129 end |
|
1130 function remove_url(t,e) |
|
1131 t.urls[e]=nil; |
|
1132 end |
|
1133 function download(e,i) |
|
1134 e.status="downloading"; |
|
1135 local t=0; |
|
1136 for a in n(e.urls)do |
|
1137 t=t+1; |
|
1138 e.urls[a]= |
|
1139 s.request(a,nil,function(n,t,s) |
|
1140 if e.callback then |
|
1141 e.downloading_count=e.downloading_count-1; |
|
1142 e.callback(a,t,n,s); |
|
1143 if e.downloading_count==0 and i then |
|
1144 o.setquitting(true); |
|
1145 end |
|
1146 end |
|
1147 end); |
|
1148 end |
|
1149 e.download_count=t; |
|
1150 e.downloading_count=t; |
|
1151 if i then |
|
1152 o.loop(); |
|
1153 o.setquitting(false); |
|
1154 end |
|
1155 return t; |
|
1156 end |
|
1157 function progress(e) |
|
1158 local a={total={}}; |
|
1159 for o,t in n(e.urls)do |
|
1160 local e={}; |
|
1161 e.bytes_downloaded=t.havebodylength; |
|
1162 e.bytes_total=t.bodylength; |
|
1163 if e.bytes_total then |
|
1164 e.percent=100/(e.bytes_total/e.bytes_downloaded); |
|
1165 end |
|
1166 a[o]=e; |
|
1167 end |
|
1168 return a; |
|
1169 end |
|
1170 function new(t,e) |
|
1171 local t={callback=t,urls={}}; |
|
1172 if r(e)=="table"then |
|
1173 for a,e in h(e)do |
|
1174 t.urls[e]=true; |
|
1175 end |
|
1176 end |
|
1177 return d(t,_M); |
|
1178 end |
|
1179 return _M; |
|
1180 end) |
|
1181 require"net.connlisteners" |
|
1182 require"net.httpclient_listener" |
|
1183 return require"net.http"; |