lahttp.lua

changeset 0
6e60da4625db
equal deleted inserted replaced
-1:000000000000 0:6e60da4625db
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";

mercurial