root/src/modules/lua_noit.c

Revision 79dcf4400f8b66d4ba7a389cc0c320576fe5764c, 51.8 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

fixes #354

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007-2010, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34
35 #include <assert.h>
36 #include <math.h>
37 #include <errno.h>
38 #include <unistd.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #ifdef HAVE_SYS_FILIO_H
42 #include <sys/filio.h>
43 #endif
44 #include <zlib.h>
45 #include <libxml/parser.h>
46 #include <libxml/xpath.h>
47 #include <libxml/tree.h>
48 #include <openssl/md5.h>
49
50 #include "noit_conf.h"
51 #include "noit_module.h"
52 #include "noit_check.h"
53 #include "noit_check_tools.h"
54 #include "noit_xml.h"
55 #include "utils/noit_log.h"
56 #include "utils/noit_str.h"
57 #include "utils/noit_b32.h"
58 #include "utils/noit_b64.h"
59 #include "eventer/eventer.h"
60 #include "json-lib/json.h"
61 #include "lua_noit.h"
62
63 #define DEFLATE_CHUNK_SIZE 32768
64
65 #define LUA_DISPATCH(n, f) \
66      if(!strcmp(k, #n)) { \
67        lua_pushlightuserdata(L, udata); \
68        lua_pushcclosure(L, f, 1); \
69        return 1; \
70      }
71 #define LUA_RETSTRING(n, g) \
72      if(!strcmp(k, #n)) { \
73        lua_pushstring(L, g); \
74        return 1; \
75      }
76 #define LUA_RETINTEGER(n, g) \
77      if(!strcmp(k, #n)) { \
78        lua_pushinteger(L, g); \
79        return 1; \
80      }
81
82 typedef struct {
83   struct json_tokener *tok;
84   struct json_object *root;
85 } json_crutch;
86
87 static void
88 nl_extended_free(void *vcl) {
89   struct nl_slcl *cl = vcl;
90   if(cl->inbuff) free(cl->inbuff);
91   free(cl);
92 }
93 static int
94 lua_push_inet_ntop(lua_State *L, struct sockaddr *r) {
95   char remote_str[128];
96   int len;
97   switch(r->sa_family) {
98     case AF_INET:
99       len = sizeof(struct sockaddr_in);
100       inet_ntop(AF_INET, &((struct sockaddr_in *)r)->sin_addr,
101                 remote_str, len);
102       lua_pushstring(L, remote_str);
103       lua_pushinteger(L, ntohs(((struct sockaddr_in *)r)->sin_port));
104       break;
105     case AF_INET6:
106       len = sizeof(struct sockaddr_in6);
107       inet_ntop(AF_INET6, &((struct sockaddr_in6 *)r)->sin6_addr,
108                 remote_str, len);
109       lua_pushstring(L, remote_str);
110       lua_pushinteger(L, ntohs(((struct sockaddr_in6 *)r)->sin6_port));
111       break;
112     default:
113       lua_pushnil(L);
114       lua_pushnil(L);
115   }
116   return 2;
117 }
118 static void
119 inbuff_addlstring(struct nl_slcl *cl, const char *b, int l) {
120   int newsize = 0;
121   char *newbuf;
122   if(cl->inbuff_len + l > cl->inbuff_allocd)
123     newsize = cl->inbuff_len + l;
124   if(newsize) {
125     newbuf = cl->inbuff_allocd ? realloc(cl->inbuff, newsize) : malloc(newsize);
126     assert(newbuf);
127     cl->inbuff = newbuf;
128     cl->inbuff_allocd = newsize;
129   }
130   memcpy(cl->inbuff + cl->inbuff_len, b, l);
131   cl->inbuff_len += l;
132 }
133
134 static int
135 noit_lua_socket_connect_complete(eventer_t e, int mask, void *vcl,
136                                  struct timeval *now) {
137   noit_lua_check_info_t *ci;
138   struct nl_slcl *cl = vcl;
139   int args = 0, aerrno;
140   socklen_t aerrno_len = sizeof(aerrno);
141
142   ci = get_ci(cl->L);
143   assert(ci);
144   noit_lua_check_deregister_event(ci, e, 0);
145
146   *(cl->eptr) = eventer_alloc();
147   memcpy(*cl->eptr, e, sizeof(*e));
148   noit_lua_check_register_event(ci, *cl->eptr);
149
150   if(getsockopt(e->fd,SOL_SOCKET,SO_ERROR, &aerrno, &aerrno_len) == 0)
151     if(aerrno != 0) goto connerr;
152
153   if(!(mask & EVENTER_EXCEPTION) &&
154      mask & EVENTER_WRITE) {
155     /* Connect completed successfully */
156     lua_pushinteger(cl->L, 0);
157     args = 1;
158   }
159   else {
160     aerrno = errno;
161    connerr:
162     lua_pushinteger(cl->L, -1);
163     lua_pushstring(cl->L, strerror(aerrno));
164     args = 2;
165   }
166   noit_lua_resume(ci, args);
167   return 0;
168 }
169 static int
170 noit_lua_socket_recv_complete(eventer_t e, int mask, void *vcl,
171                               struct timeval *now) {
172   noit_lua_check_info_t *ci;
173   struct nl_slcl *cl = vcl;
174   int rv, args = 0;
175   void *inbuff = NULL;
176   socklen_t alen;
177
178   ci = get_ci(cl->L);
179   assert(ci);
180
181   if(mask & EVENTER_EXCEPTION) {
182     lua_pushinteger(cl->L, -1);
183     args = 1;
184     goto alldone;
185   }
186
187   inbuff = malloc(cl->read_goal);
188   if(!inbuff) {
189     lua_pushinteger(cl->L, -1);
190     args = 1;
191     goto alldone;
192   }
193
194   alen = sizeof(cl->address);
195   while((rv = recvfrom(e->fd, inbuff, cl->read_goal, 0,
196                        (struct sockaddr *)&cl->address, &alen)) == -1 &&
197         errno == EINTR);
198   if(rv < 0) {
199     if(errno == EAGAIN) {
200       free(inbuff);
201       return EVENTER_READ | EVENTER_EXCEPTION;
202     }
203     lua_pushinteger(cl->L, rv);
204     lua_pushstring(cl->L, strerror(errno));
205     args = 2;
206   }
207   else {
208     lua_pushinteger(cl->L, rv);
209     lua_pushlstring(cl->L, inbuff, rv);
210     args = 2;
211     args += lua_push_inet_ntop(cl->L, (struct sockaddr *)&cl->address);
212   }
213
214  alldone:
215   if(inbuff) free(inbuff);
216   eventer_remove_fd(e->fd);
217   noit_lua_check_deregister_event(ci, e, 0);
218   *(cl->eptr) = eventer_alloc();
219   memcpy(*cl->eptr, e, sizeof(*e));
220   noit_lua_check_register_event(ci, *cl->eptr);
221   noit_lua_resume(ci, args);
222   return 0;
223 }
224 static int
225 noit_lua_socket_recv(lua_State *L) {
226   int args, rv;
227   struct nl_slcl *cl;
228   noit_lua_check_info_t *ci;
229   eventer_t e, *eptr;
230   void *inbuff;
231   socklen_t alen;
232
233   ci = get_ci(L);
234   assert(ci);
235
236   eptr = lua_touserdata(L, lua_upvalueindex(1));
237   if(eptr != lua_touserdata(L, 1))
238     luaL_error(L, "must be called as method");
239   e = *eptr;
240   cl = e->closure;
241   cl->read_goal = lua_tointeger(L, 2);
242   inbuff = malloc(cl->read_goal);
243
244   alen = sizeof(cl->address);
245   while((rv = recvfrom(e->fd, inbuff, cl->read_goal, 0,
246                        (struct sockaddr *)&cl->address, &alen)) == -1 &&
247         errno == EINTR);
248   if(rv < 0) {
249     if(errno == EAGAIN) {
250       e->callback = noit_lua_socket_recv_complete;
251       e->mask = EVENTER_READ | EVENTER_EXCEPTION;
252       eventer_add(e);
253       free(inbuff);
254       return noit_lua_yield(ci, 0);
255     }
256     lua_pushinteger(cl->L, rv);
257     lua_pushstring(cl->L, strerror(errno));
258     args = 2;
259   }
260   else {
261     lua_pushinteger(cl->L, rv);
262     lua_pushlstring(cl->L, inbuff, rv);
263     args = 2;
264     args += lua_push_inet_ntop(cl->L, (struct sockaddr *)&cl->address);
265   }
266   free(inbuff);
267   return args;
268 }
269 static int
270 noit_lua_socket_send_complete(eventer_t e, int mask, void *vcl,
271                               struct timeval *now) {
272   noit_lua_check_info_t *ci;
273   struct nl_slcl *cl = vcl;
274   int sbytes;
275   int args = 0;
276
277   ci = get_ci(cl->L);
278   assert(ci);
279
280   if(mask & EVENTER_EXCEPTION) {
281     lua_pushinteger(cl->L, -1);
282     args = 1;
283     goto alldone;
284   }
285   if(cl->sendto) {
286     while((sbytes = sendto(e->fd, cl->outbuff, cl->write_goal, 0,
287                            (struct sockaddr *)&cl->address,
288                            cl->address.sin4.sin_family==AF_INET ?
289                                sizeof(cl->address.sin4) :
290                                sizeof(cl->address.sin6))) == -1 &&
291           errno == EINTR);
292   }
293   else {
294     while((sbytes = send(e->fd, cl->outbuff, cl->write_goal, 0)) == -1 &&
295           errno == EINTR);
296   }
297   if(sbytes > 0) {
298     lua_pushinteger(cl->L, sbytes);
299     args = 1;
300   }
301   else if(sbytes == -1 && errno == EAGAIN) {
302     return EVENTER_WRITE | EVENTER_EXCEPTION;
303   }
304   else {
305     lua_pushinteger(cl->L, sbytes);
306     args = 1;
307     if(sbytes == -1) {
308       lua_pushstring(cl->L, strerror(errno));
309       args++;
310     }
311   }
312
313  alldone:
314   eventer_remove_fd(e->fd);
315   noit_lua_check_deregister_event(ci, e, 0);
316   *(cl->eptr) = eventer_alloc();
317   memcpy(*cl->eptr, e, sizeof(*e));
318   noit_lua_check_register_event(ci, *cl->eptr);
319   noit_lua_resume(ci, args);
320   return 0;
321 }
322 static int
323 noit_lua_socket_send(lua_State *L) {
324   noit_lua_check_info_t *ci;
325   eventer_t e, *eptr;
326   const void *bytes;
327   size_t nbytes;
328   ssize_t sbytes;
329
330   ci = get_ci(L);
331   assert(ci);
332
333   eptr = lua_touserdata(L, lua_upvalueindex(1));
334   if(eptr != lua_touserdata(L, 1))
335     luaL_error(L, "must be called as method");
336   e = *eptr;
337   if(lua_gettop(L) != 2)
338     luaL_error(L, "noit.socket.send with bad arguments");
339   bytes = lua_tolstring(L, 2, &nbytes);
340
341   while((sbytes = send(e->fd, bytes, nbytes, 0)) == -1 && errno == EINTR);
342   if(sbytes < 0 && errno == EAGAIN) {
343     struct nl_slcl *cl;
344     /* continuation */
345     cl = e->closure;
346     cl->write_sofar = 0;
347     cl->outbuff = bytes;
348     cl->write_goal = nbytes;
349     cl->sendto = 0;
350     e->callback = noit_lua_socket_send_complete;
351     e->mask = EVENTER_WRITE | EVENTER_EXCEPTION;
352     eventer_add(e);
353     return noit_lua_yield(ci, 0);
354   }
355   lua_pushinteger(L, sbytes);
356   if(sbytes < 0) {
357     lua_pushstring(L, strerror(errno));
358     return 2;
359   }
360   return 1;
361 }
362
363 static int
364 noit_lua_socket_sendto(lua_State *L) {
365   noit_lua_check_info_t *ci;
366   eventer_t e, *eptr;
367   const char *target;
368   unsigned short port;
369   int8_t family;
370   int rv;
371   const void *bytes;
372   size_t nbytes;
373   ssize_t sbytes;
374   union {
375     struct sockaddr_in sin4;
376     struct sockaddr_in6 sin6;
377   } a;
378
379   ci = get_ci(L);
380   assert(ci);
381
382   eptr = lua_touserdata(L, lua_upvalueindex(1));
383   if(eptr != lua_touserdata(L, 1))
384     luaL_error(L, "must be called as method");
385   e = *eptr;
386   if(lua_gettop(L) != 4)
387     luaL_error(L, "noit.socket.sendto with bad arguments");
388   bytes = lua_tolstring(L, 2, &nbytes);
389   target = lua_tostring(L, 3);
390   if(!target) target = "";
391   port = lua_tointeger(L, 4);
392
393   family = AF_INET;
394   rv = inet_pton(family, target, &a.sin4.sin_addr);
395   if(rv != 1) {
396     family = AF_INET6;
397     rv = inet_pton(family, target, &a.sin6.sin6_addr);
398     if(rv != 1) {
399       memset(&a, 0, sizeof(a));
400       lua_pushinteger(L, -1);
401       lua_pushfstring(L, "Cannot translate '%s' to IP\n", target);
402       return 2;
403     }
404     else {
405       /* We've IPv6 */
406       a.sin6.sin6_family = AF_INET6;
407       a.sin6.sin6_port = htons(port);
408     }
409   }
410   else {
411     a.sin4.sin_family = family;
412     a.sin4.sin_port = htons(port);
413   }
414
415   while((sbytes = sendto(e->fd, bytes, nbytes, 0, (struct sockaddr *)&a,
416                          family==AF_INET ? sizeof(a.sin4)
417                                          : sizeof(a.sin6))) == -1 &&
418         errno == EINTR);
419   if(sbytes < 0 && errno == EAGAIN) {
420     struct nl_slcl *cl;
421     /* continuation */
422     cl = e->closure;
423     cl->write_sofar = 0;
424     cl->outbuff = bytes;
425     cl->write_goal = nbytes;
426     cl->sendto = 1;
427     e->callback = noit_lua_socket_send_complete;
428     e->mask = EVENTER_WRITE | EVENTER_EXCEPTION;
429     eventer_add(e);
430     return noit_lua_yield(ci, 0);
431   }
432   lua_pushinteger(L, sbytes);
433   if(sbytes < 0) {
434     lua_pushstring(L, strerror(errno));
435     return 2;
436   }
437   return 1;
438 }
439 static int
440 noit_lua_socket_connect(lua_State *L) {
441   noit_lua_check_info_t *ci;
442   eventer_t e, *eptr;
443   const char *target;
444   unsigned short port;
445   int8_t family;
446   int rv;
447   union {
448     struct sockaddr_in sin4;
449     struct sockaddr_in6 sin6;
450   } a;
451
452   ci = get_ci(L);
453   assert(ci);
454
455   eptr = lua_touserdata(L, lua_upvalueindex(1));
456   if(eptr != lua_touserdata(L, 1))
457     luaL_error(L, "must be called as method");
458   e = *eptr;
459   target = lua_tostring(L, 2);
460   if(!target) target = "";
461   port = lua_tointeger(L, 3);
462
463   family = AF_INET;
464   rv = inet_pton(family, target, &a.sin4.sin_addr);
465   if(rv != 1) {
466     family = AF_INET6;
467     rv = inet_pton(family, target, &a.sin6.sin6_addr);
468     if(rv != 1) {
469       memset(&a, 0, sizeof(a));
470       lua_pushinteger(L, -1);
471       lua_pushfstring(L, "Cannot translate '%s' to IP\n", target);
472       return 2;
473     }
474     else {
475       /* We've IPv6 */
476       a.sin6.sin6_family = AF_INET6;
477       a.sin6.sin6_port = htons(port);
478     }
479   }
480   else {
481     a.sin4.sin_family = family;
482     a.sin4.sin_port = htons(port);
483   }
484
485   rv = connect(e->fd, (struct sockaddr *)&a,
486                family==AF_INET ? sizeof(a.sin4) : sizeof(a.sin6));
487   if(rv == 0) {
488     lua_pushinteger(L, 0);
489     return 1;
490   }
491   if(rv == -1 && errno == EINPROGRESS) {
492     /* Need completion */
493     e->callback = noit_lua_socket_connect_complete;
494     e->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
495     eventer_add(e);
496     return noit_lua_yield(ci, 0);
497   }
498   lua_pushinteger(L, -1);
499   lua_pushstring(L, strerror(errno));
500   return 2;
501 }
502 static int
503 noit_lua_ssl_upgrade(eventer_t e, int mask, void *vcl,
504                      struct timeval *now) {
505   noit_lua_check_info_t *ci;
506   struct nl_slcl *cl = vcl;
507   int rv;
508  
509   rv = eventer_SSL_connect(e, &mask);
510   if(rv <= 0 && errno == EAGAIN) return mask | EVENTER_EXCEPTION;
511
512   ci = get_ci(cl->L);
513   assert(ci);
514   noit_lua_check_deregister_event(ci, e, 0);
515  
516   *(cl->eptr) = eventer_alloc();
517   memcpy(*cl->eptr, e, sizeof(*e));
518   noit_lua_check_register_event(ci, *cl->eptr);
519
520   /* Upgrade completed successfully */
521   lua_pushinteger(cl->L, (rv > 0) ? 0 : -1);
522   noit_lua_resume(ci, 1);
523   return 0;
524 }
525 static int
526 noit_lua_socket_connect_ssl(lua_State *L) {
527   const char *ca, *ciphers, *cert, *key;
528   eventer_ssl_ctx_t *sslctx;
529   noit_lua_check_info_t *ci;
530   eventer_t e, *eptr;
531   struct timeval now;
532
533   ci = get_ci(L);
534   assert(ci);
535
536   eptr = lua_touserdata(L, lua_upvalueindex(1));
537   if(eptr != lua_touserdata(L, 1))
538     luaL_error(L, "must be called as method");
539   e = *eptr;
540   cert = lua_tostring(L, 2);
541   key = lua_tostring(L, 3);
542   ca = lua_tostring(L, 4);
543   ciphers = lua_tostring(L, 5);
544
545   sslctx = eventer_ssl_ctx_new(SSL_CLIENT, cert, key, ca, ciphers);
546   if(!sslctx) {
547     lua_pushinteger(L, -1);
548     return 1;
549   }
550
551   eventer_ssl_ctx_set_verify(sslctx, eventer_ssl_verify_cert, NULL);
552   EVENTER_ATTACH_SSL(e, sslctx);
553   e->callback = noit_lua_ssl_upgrade;
554   gettimeofday(&now, NULL);
555   e->mask = e->callback(e, EVENTER_READ|EVENTER_WRITE, e->closure, &now);
556   if(e->mask & (EVENTER_READ|EVENTER_WRITE)) {
557     /* Need completion */
558     eventer_add(e);
559     return noit_lua_yield(ci, 0);
560   }
561   lua_pushinteger(L, 0);
562   return 1;
563 }
564
565 static int
566 noit_lua_socket_do_read(eventer_t e, int *mask, struct nl_slcl *cl,
567                         int *read_complete) {
568   char buff[4096];
569   int len;
570   *read_complete = 0;
571   while((len = e->opset->read(e->fd, buff, sizeof(buff), mask, e)) > 0) {
572     if(cl->read_goal) {
573       int remaining = cl->read_goal - cl->read_sofar;
574       /* copy up to the goal into the inbuff */
575       inbuff_addlstring(cl, buff, MIN(len, remaining));
576       cl->read_sofar += len;
577       if(cl->read_sofar >= cl->read_goal) { /* We're done */
578         lua_pushlstring(cl->L, cl->inbuff, cl->read_goal);
579         *read_complete = 1;
580         cl->read_sofar -= cl->read_goal;
581         cl->inbuff_len = 0;
582         if(cl->read_sofar > 0) {  /* We have to buffer this for next read */
583           inbuff_addlstring(cl, buff + remaining, cl->read_sofar);
584         }
585         break;
586       }
587     }
588     else if(cl->read_terminator) {
589       const char *cp;
590       int remaining = len;
591       cp = strnstrn(cl->read_terminator, strlen(cl->read_terminator),
592                     buff, len);
593       if(cp) remaining = cp - buff + strlen(cl->read_terminator);
594       inbuff_addlstring(cl, buff, MIN(len, remaining));
595       cl->read_sofar += len;
596       if(cp) {
597         lua_pushlstring(cl->L, cl->inbuff, cl->inbuff_len);
598         *read_complete = 1;
599        
600         cl->read_sofar = len - remaining;
601         cl->inbuff_len = 0;
602         if(cl->read_sofar > 0) { /* We have to buffer this for next read */
603           inbuff_addlstring(cl, buff + remaining, cl->read_sofar);
604         }
605         break;
606       }
607     }
608   }
609   if(len == 0 && cl->inbuff_len) {
610     /* EOF */
611     *read_complete = 1;
612     lua_pushlstring(cl->L, cl->inbuff, cl->inbuff_len);
613     cl->inbuff_len = 0;
614   }
615   return len;
616 }
617 static int
618 noit_lua_socket_read_complete(eventer_t e, int mask, void *vcl,
619                               struct timeval *now) {
620   noit_lua_check_info_t *ci;
621   struct nl_slcl *cl = vcl;
622   int len;
623   int args = 0;
624
625   ci = get_ci(cl->L);
626   assert(ci);
627
628   len = noit_lua_socket_do_read(e, &mask, cl, &args);
629   if(len >= 0) {
630     /* We broke out, cause we read enough... */
631   }
632   else if(len == -1 && errno == EAGAIN) {
633     return mask | EVENTER_EXCEPTION;
634   }
635   else {
636     lua_pushnil(cl->L);
637     args = 1;
638   }
639   eventer_remove_fd(e->fd);
640   noit_lua_check_deregister_event(ci, e, 0);
641   *(cl->eptr) = eventer_alloc();
642   memcpy(*cl->eptr, e, sizeof(*e));
643   noit_lua_check_register_event(ci, *cl->eptr);
644   noit_lua_resume(ci, args);
645   return 0;
646 }
647
648 static int
649 noit_lua_socket_read(lua_State *L) {
650   int args, mask, len;
651   struct nl_slcl *cl;
652   noit_lua_check_info_t *ci;
653   eventer_t e, *eptr;
654
655   ci = get_ci(L);
656   assert(ci);
657
658   eptr = lua_touserdata(L, lua_upvalueindex(1));
659   if(eptr != lua_touserdata(L, 1))
660     luaL_error(L, "must be called as method");
661   e = *eptr;
662   cl = e->closure;
663   cl->read_goal = 0;
664   cl->read_terminator = NULL;
665
666   if(lua_isnumber(L, 2)) {
667     cl->read_goal = lua_tointeger(L, 2);
668     if(cl->read_goal <= cl->read_sofar) {
669      i_know_better:
670       /* We have enough, we can service this right here */
671       lua_pushlstring(L, cl->inbuff, cl->read_goal);
672       cl->read_sofar -= cl->read_goal;
673       if(cl->read_sofar) {
674         memmove(cl->inbuff, cl->inbuff + cl->read_goal, cl->read_sofar);
675       }
676       cl->inbuff_len = cl->read_sofar;
677       return 1;
678     }
679   }
680   else {
681     cl->read_terminator = lua_tostring(L, 2);
682     if(cl->read_sofar) {
683       const char *cp;
684       /* Ugh... inernalism */
685       cp = strnstrn(cl->read_terminator, strlen(cl->read_terminator),
686                     cl->inbuff, cl->read_sofar);
687       if(cp) {
688         /* Here we matched... and we _know_ that someone actually wants:
689          * strlen(cl->read_terminator) + cp - cl->inbuff.buffer bytes...
690          * give it to them.
691          */
692         cl->read_goal = strlen(cl->read_terminator) + cp - cl->inbuff;
693         cl->read_terminator = NULL;
694         assert(cl->read_goal <= cl->read_sofar);
695         goto i_know_better;
696       }
697     }
698   }
699
700   len = noit_lua_socket_do_read(e, &mask, cl, &args);
701   if(args == 1) return 1; /* completed read, return result */
702   if(len == -1 && errno == EAGAIN) {
703     /* we need to drop into eventer */
704   }
705   else {
706     lua_pushnil(cl->L);
707     args = 1;
708     return args;
709   }
710
711   e->callback = noit_lua_socket_read_complete;
712   e->mask = mask | EVENTER_EXCEPTION;
713   eventer_add(e);
714   return noit_lua_yield(ci, 0);
715 }
716 static int
717 noit_lua_socket_write_complete(eventer_t e, int mask, void *vcl,
718                                struct timeval *now) {
719   noit_lua_check_info_t *ci;
720   struct nl_slcl *cl = vcl;
721   int rv;
722   int args = 0;
723
724   ci = get_ci(cl->L);
725   assert(ci);
726
727   if(mask & EVENTER_EXCEPTION) {
728     lua_pushinteger(cl->L, -1);
729     args = 1;
730     goto alldone;
731   }
732   while((rv = e->opset->write(e->fd,
733                               cl->outbuff + cl->write_sofar,
734                               MIN(cl->send_size, cl->write_goal),
735                               &mask, e)) > 0) {
736     cl->write_sofar += rv;
737     assert(cl->write_sofar <= cl->write_goal);
738     if(cl->write_sofar == cl->write_goal) break;
739   }
740   if(rv > 0) {
741     lua_pushinteger(cl->L, cl->write_goal);
742     args = 1;
743   }
744   else if(rv == -1 && errno == EAGAIN) {
745     return mask | EVENTER_EXCEPTION;
746   }
747   else {
748     lua_pushinteger(cl->L, -1);
749     args = 1;
750     if(rv == -1) {
751       lua_pushstring(cl->L, strerror(errno));
752       args++;
753     }
754   }
755
756  alldone:
757   eventer_remove_fd(e->fd);
758   noit_lua_check_deregister_event(ci, e, 0);
759   *(cl->eptr) = eventer_alloc();
760   memcpy(*cl->eptr, e, sizeof(*e));
761   noit_lua_check_register_event(ci, *cl->eptr);
762   noit_lua_resume(ci, args);
763   return 0;
764 }
765 static int
766 noit_lua_socket_write(lua_State *L) {
767   int rv, mask;
768   struct nl_slcl *cl;
769   noit_lua_check_info_t *ci;
770   eventer_t e, *eptr;
771
772   ci = get_ci(L);
773   assert(ci);
774
775   eptr = lua_touserdata(L, lua_upvalueindex(1));
776   if(eptr != lua_touserdata(L, 1))
777     luaL_error(L, "must be called as method");
778   e = *eptr;
779   cl = e->closure;
780   cl->write_sofar = 0;
781   cl->outbuff = lua_tolstring(L, 2, &cl->write_goal);
782
783   while((rv = e->opset->write(e->fd,
784                               cl->outbuff + cl->write_sofar,
785                               MIN(cl->send_size, cl->write_goal),
786                               &mask, e)) > 0) {
787     cl->write_sofar += rv;
788     assert(cl->write_sofar <= cl->write_goal);
789     if(cl->write_sofar == cl->write_goal) break;
790   }
791   if(rv > 0) {
792     lua_pushinteger(L, cl->write_goal);
793     return 1;
794   }
795   if(rv == -1 && errno == EAGAIN) {
796     e->callback = noit_lua_socket_write_complete;
797     e->mask = mask | EVENTER_EXCEPTION;
798     eventer_add(e);
799     return noit_lua_yield(ci, 0);
800   }
801   lua_pushinteger(L, -1);
802   return 1;
803 }
804 static int
805 noit_lua_socket_ssl_ctx(lua_State *L) {
806   eventer_t *eptr, e;
807   eventer_ssl_ctx_t **ssl_ctx_holder, *ssl_ctx;
808
809   eptr = lua_touserdata(L, lua_upvalueindex(1));
810   if(eptr != lua_touserdata(L, 1))
811     luaL_error(L, "must be called as method");
812   e = *eptr;
813
814   ssl_ctx = eventer_get_eventer_ssl_ctx(e);
815   if(!ssl_ctx) {
816     lua_pushnil(L);
817     return 1;
818   }
819
820   ssl_ctx_holder = (eventer_ssl_ctx_t **)lua_newuserdata(L, sizeof(ssl_ctx));
821   *ssl_ctx_holder = ssl_ctx;
822   luaL_getmetatable(L, "noit.eventer.ssl_ctx");
823   lua_setmetatable(L, -2);
824   return 1;
825 }
826 static int
827 noit_eventer_index_func(lua_State *L) {
828   int n;
829   const char *k;
830   eventer_t *udata;
831   n = lua_gettop(L); /* number of arguments */
832   assert(n == 2);
833   if(!luaL_checkudata(L, 1, "noit.eventer")) {
834     luaL_error(L, "metatable error, arg1 not a noit.eventer!");
835   }
836   udata = lua_touserdata(L, 1);
837   if(!lua_isstring(L, 2)) {
838     luaL_error(L, "metatable error, arg2 not a string!");
839   }
840   k = lua_tostring(L, 2);
841   switch(*k) {
842     case 'c':
843      LUA_DISPATCH(connect, noit_lua_socket_connect);
844      break;
845     case 'r':
846      LUA_DISPATCH(read, noit_lua_socket_read);
847      LUA_DISPATCH(recv, noit_lua_socket_recv);
848      break;
849     case 's':
850      LUA_DISPATCH(send, noit_lua_socket_send);
851      LUA_DISPATCH(sendto, noit_lua_socket_sendto);
852      LUA_DISPATCH(ssl_upgrade_socket, noit_lua_socket_connect_ssl);
853      LUA_DISPATCH(ssl_ctx, noit_lua_socket_ssl_ctx);
854      break;
855     case 'w':
856      LUA_DISPATCH(write, noit_lua_socket_write);
857      break;
858     default:
859       break;
860   }
861   luaL_error(L, "noit.eventer no such element: %s", k);
862   return 0;
863 }
864
865 static eventer_t *
866 noit_lua_event(lua_State *L, eventer_t e) {
867   eventer_t *addr;
868   addr = (eventer_t *)lua_newuserdata(L, sizeof(e));
869   *addr = e;
870   luaL_getmetatable(L, "noit.eventer");
871   lua_setmetatable(L, -2);
872   return addr;
873 }
874
875 static int
876 noit_ssl_ctx_index_func(lua_State *L) {
877   int n;
878   const char *k;
879   eventer_ssl_ctx_t **udata, *ssl_ctx;
880   n = lua_gettop(L); /* number of arguments */
881   assert(n == 2);
882   if(!luaL_checkudata(L, 1, "noit.eventer.ssl_ctx")) {
883     luaL_error(L, "metatable error, arg1 not a noit.eventer.ssl_ctx!");
884   }
885   udata = lua_touserdata(L, 1);
886   ssl_ctx = *udata;
887   if(!lua_isstring(L, 2)) {
888     luaL_error(L, "metatable error, arg2 not a string!");
889   }
890   k = lua_tostring(L, 2);
891   switch(*k) {
892     case 'e':
893       LUA_RETSTRING(error, eventer_ssl_get_peer_error(ssl_ctx));
894       LUA_RETINTEGER(end_time, eventer_ssl_get_peer_end_time(ssl_ctx));
895       break;
896     case 'i':
897       LUA_RETSTRING(issuer, eventer_ssl_get_peer_issuer(ssl_ctx));
898       break;
899     case 's':
900       LUA_RETSTRING(subject, eventer_ssl_get_peer_subject(ssl_ctx));
901       LUA_RETINTEGER(start_time, eventer_ssl_get_peer_start_time(ssl_ctx));
902       break;
903     default:
904       break;
905   }
906   luaL_error(L, "noit.eventer.ssl_ctx no such element: %s", k);
907   return 0;
908 }
909
910 static int
911 nl_sleep_complete(eventer_t e, int mask, void *vcl, struct timeval *now) {
912   noit_lua_check_info_t *ci;
913   struct nl_slcl *cl = vcl;
914   struct timeval diff;
915   double p_int;
916
917   ci = get_ci(cl->L);
918   assert(ci);
919   noit_lua_check_deregister_event(ci, e, 0);
920
921   sub_timeval(*now, cl->start, &diff);
922   p_int = diff.tv_sec + diff.tv_usec / 1000000.0;
923   lua_pushnumber(cl->L, p_int);
924   free(cl);
925   noit_lua_resume(ci, 1);
926   return 0;
927 }
928
929 static int
930 nl_sleep(lua_State *L) {
931   noit_lua_check_info_t *ci;
932   struct nl_slcl *cl;
933   struct timeval diff;
934   eventer_t e;
935   double p_int;
936
937   ci = get_ci(L);
938   assert(ci);
939
940   p_int = lua_tonumber(L, 1);
941   cl = calloc(1, sizeof(*cl));
942   cl->free = nl_extended_free;
943   cl->L = L;
944   gettimeofday(&cl->start, NULL);
945
946   e = eventer_alloc();
947   e->mask = EVENTER_TIMER;
948   e->callback = nl_sleep_complete;
949   e->closure = cl;
950   memcpy(&e->whence, &cl->start, sizeof(cl->start));
951   diff.tv_sec = floor(p_int);
952   diff.tv_usec = (p_int - floor(p_int)) * 1000000;
953   add_timeval(e->whence, diff, &e->whence);
954   noit_lua_check_register_event(ci, e);
955   eventer_add(e);
956   return noit_lua_yield(ci, 0);
957 }
958
959 static int
960 nl_log(lua_State *L) {
961   int i, n;
962   const char *log_dest, *message;
963   noit_log_stream_t ls;
964
965   if(lua_gettop(L) < 2) luaL_error(L, "bad call to noit.log");
966
967   log_dest = lua_tostring(L, 1);
968   ls = noit_log_stream_find(log_dest);
969   if(!ls) {
970     noitL(noit_stderr, "Cannot find log stream: '%s'\n", log_dest);
971     return 0;
972   }
973
974   n = lua_gettop(L);
975   lua_pushstring(L, "string");
976   lua_gettable(L, LUA_GLOBALSINDEX);
977   lua_pushstring(L, "format");
978   lua_gettable(L, -1);
979   for(i=2;i<=n;i++)
980     lua_pushvalue(L, i);
981   lua_call(L, n-1, 1);
982   message = lua_tostring(L, -1);
983   noitL(ls, "%s", message);
984   lua_pop(L, 1); /* formatted string */
985   lua_pop(L, 1); /* "string" table */
986   return 0;
987 }
988 static int
989 nl_base32_decode(lua_State *L) {
990   size_t inlen, decoded_len;
991   const char *message;
992   unsigned char *decoded;
993
994   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.decode");
995
996   message = lua_tolstring(L, 1, &inlen);
997   decoded = malloc(MAX(1,inlen));
998   if(!decoded) luaL_error(L, "out-of-memory");
999   decoded_len = noit_b32_decode(message, inlen, decoded, MAX(1,inlen));
1000   lua_pushlstring(L, (char *)decoded, decoded_len);
1001   return 1;
1002 }
1003 static int
1004 nl_base32_encode(lua_State *L) {
1005   size_t inlen, encoded_len;
1006   const unsigned char *message;
1007   char *encoded;
1008
1009   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.encode");
1010
1011   message = (const unsigned char *)lua_tolstring(L, 1, &inlen);
1012   encoded_len = (((inlen + 7) / 5) * 8) + 1;
1013   encoded = malloc(encoded_len);
1014   if(!encoded) luaL_error(L, "out-of-memory");
1015   encoded_len = noit_b32_encode(message, inlen, encoded, encoded_len);
1016   lua_pushlstring(L, (char *)encoded, encoded_len);
1017   return 1;
1018 }
1019 static int
1020 nl_base64_decode(lua_State *L) {
1021   size_t inlen, decoded_len;
1022   const char *message;
1023   unsigned char *decoded;
1024
1025   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.decode");
1026
1027   message = lua_tolstring(L, 1, &inlen);
1028   decoded = malloc(MAX(1,inlen));
1029   if(!decoded) luaL_error(L, "out-of-memory");
1030   decoded_len = noit_b64_decode(message, inlen, decoded, MAX(1,inlen));
1031   lua_pushlstring(L, (char *)decoded, decoded_len);
1032   return 1;
1033 }
1034 static int
1035 nl_base64_encode(lua_State *L) {
1036   size_t inlen, encoded_len;
1037   const unsigned char *message;
1038   char *encoded;
1039
1040   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.encode");
1041
1042   message = (const unsigned char *)lua_tolstring(L, 1, &inlen);
1043   encoded_len = (((inlen + 2) / 3) * 4) + 1;
1044   encoded = malloc(encoded_len);
1045   if(!encoded) luaL_error(L, "out-of-memory");
1046   encoded_len = noit_b64_encode(message, inlen, encoded, encoded_len);
1047   lua_pushlstring(L, (char *)encoded, encoded_len);
1048   return 1;
1049 }
1050 static const char _hexchars[16] =
1051   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1052 static int
1053 nl_md5_hex(lua_State *L) {
1054   int i;
1055   MD5_CTX ctx;
1056   size_t inlen;
1057   const char *in;
1058   unsigned char md5[MD5_DIGEST_LENGTH];
1059   char md5_hex[MD5_DIGEST_LENGTH * 2 + 1];
1060
1061   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.md5_hex");
1062   MD5_Init(&ctx);
1063   in = lua_tolstring(L, 1, &inlen);
1064   MD5_Update(&ctx, (const void *)in, (unsigned long)inlen);
1065   MD5_Final(md5, &ctx);
1066   for(i=0;i<MD5_DIGEST_LENGTH;i++) {
1067     md5_hex[i*2] = _hexchars[(md5[i] >> 4) & 0xf];
1068     md5_hex[i*2+1] = _hexchars[md5[i] & 0xf];
1069   }
1070   md5_hex[i*2] = '\0';
1071   lua_pushstring(L, md5_hex);
1072   return 1;
1073 }
1074 static int
1075 nl_gettimeofday(lua_State *L) {
1076   struct timeval now;
1077   gettimeofday(&now, NULL);
1078   lua_pushinteger(L, now.tv_sec);
1079   lua_pushinteger(L, now.tv_usec);
1080   return 2;
1081 }
1082 static int
1083 nl_socket_internal(lua_State *L, int family, int proto) {
1084   struct nl_slcl *cl;
1085   noit_lua_check_info_t *ci;
1086   socklen_t optlen;
1087   int fd;
1088   eventer_t e;
1089
1090   fd = socket(family, proto, 0);
1091   if(fd < 0) {
1092     lua_pushnil(L);
1093     return 1;
1094   }
1095   if(eventer_set_fd_nonblocking(fd)) {
1096     close(fd);
1097     lua_pushnil(L);
1098     return 1;
1099   }
1100
1101   ci = get_ci(L);
1102   assert(ci);
1103
1104   cl = calloc(1, sizeof(*cl));
1105   cl->free = nl_extended_free;
1106   cl->L = L;
1107
1108   optlen = sizeof(cl->send_size);
1109   if(getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &cl->send_size, &optlen) != 0)
1110     cl->send_size = 4096;
1111
1112   e = eventer_alloc();
1113   e->fd = fd;
1114   e->mask = EVENTER_EXCEPTION;
1115   e->callback = NULL;
1116   e->closure = cl;
1117   cl->eptr = noit_lua_event(L, e);
1118
1119   noit_lua_check_register_event(ci, e);
1120   return 1;
1121 }
1122 static int
1123 nl_socket(lua_State *L) {
1124   int n = lua_gettop(L);
1125   uint8_t family = AF_INET;
1126   union {
1127     struct in_addr addr4;
1128     struct in6_addr addr6;
1129   } a;
1130
1131   if(n > 0 && lua_isstring(L,1)) {
1132     const char *fam = lua_tostring(L,1);
1133     if(!fam) fam = "";
1134     if(!strcmp(fam, "inet")) family = AF_INET;
1135     else if(!strcmp(fam, "inet6")) family = AF_INET6;
1136     else if(inet_pton(AF_INET, fam, &a) == 1) family = AF_INET;
1137     else if(inet_pton(AF_INET6, fam, &a) == 1) family = AF_INET6;
1138     else luaL_error(L, "noit.socket family for %s unknown", fam);
1139   }
1140
1141   if(n <= 1) return nl_socket_internal(L, family, SOCK_STREAM);
1142   if(n == 2 && lua_isstring(L,2)) {
1143     const char *type = lua_tostring(L,2);
1144     if(!strcmp(type, "tcp"))
1145       return nl_socket_internal(L, family, SOCK_STREAM);
1146     else if(!strcmp(type, "udp"))
1147       return nl_socket_internal(L, family, SOCK_DGRAM);
1148   }
1149   luaL_error(L, "noit.socket called with invalid arguments");
1150   return 0;
1151 }
1152
1153 struct gunzip_crutch {
1154   z_stream *stream;
1155   void *scratch_buffer;
1156 };
1157 static int
1158 nl_gunzip_deflate(lua_State *L) {
1159   struct gunzip_crutch *crutch;
1160   const char *input;
1161   size_t inlen;
1162   z_stream *stream;
1163   Bytef *data = NULL;
1164   uLong outlen = 0;
1165   int limit = 1024*1024;
1166   int err, n = lua_gettop(L);
1167
1168   if(n < 1 || n > 2) {
1169     lua_pushnil(L);
1170     return 1;
1171   }
1172
1173   crutch = lua_touserdata(L, lua_upvalueindex(1));
1174   stream = crutch->stream;
1175
1176   input = lua_tolstring(L, 1, &inlen);
1177   if(!input) {
1178     lua_pushnil(L);
1179     return 1;
1180   }
1181   if(n == 2)
1182     limit = lua_tointeger(L, 2);
1183
1184   stream->next_in = (Bytef *)input;
1185   stream->avail_in = inlen;
1186   while(1) {
1187     err = inflate(stream, Z_FULL_FLUSH);
1188     if(err == Z_OK || err == Z_STREAM_END) {
1189       /* got some data */
1190       int size_read = DEFLATE_CHUNK_SIZE - stream->avail_out;
1191       uLong newoutlen = outlen + size_read;
1192       if(newoutlen > limit) {
1193         err = Z_MEM_ERROR;
1194         break;
1195       }
1196       if(newoutlen > outlen) {
1197         Bytef *newdata;
1198         if(data) newdata = realloc(data, newoutlen);
1199         else newdata = malloc(newoutlen);
1200         if(!newdata) {
1201           err = Z_MEM_ERROR;
1202           break;
1203         }
1204         data = newdata;
1205         memcpy(data + outlen, stream->next_out - size_read, size_read);
1206         outlen += size_read;
1207         stream->next_out -= size_read;
1208         stream->avail_out += size_read;
1209       }
1210       if(err == Z_STREAM_END) {
1211         /* Good to go */
1212         break;
1213       }
1214     }
1215     else break;
1216     if(stream->avail_in == 0) break;
1217   }
1218   if(err == Z_OK || err == Z_STREAM_END) {
1219     if(outlen > 0) lua_pushlstring(L, (char *)data, outlen);
1220     else lua_pushstring(L, "");
1221     if(data) free(data);
1222     return 1;
1223   }
1224   if(data) free(data);
1225   switch(err) {
1226     case Z_NEED_DICT: luaL_error(L, "zlib: dictionary error"); break;
1227     case Z_STREAM_ERROR: luaL_error(L, "zlib: stream error"); break;
1228     case Z_DATA_ERROR: luaL_error(L, "zlib: data error"); break;
1229     case Z_MEM_ERROR: luaL_error(L, "zlib: out-of-memory"); break;
1230     case Z_BUF_ERROR: luaL_error(L, "zlib: buffer error"); break;
1231     case Z_VERSION_ERROR: luaL_error(L, "zlib: version mismatch"); break;
1232     case Z_ERRNO: luaL_error(L, strerror(errno)); break;
1233   }
1234   lua_pushnil(L);
1235   return 1;
1236 }
1237 static int
1238 nl_gunzip(lua_State *L) {
1239   struct gunzip_crutch *crutch;
1240   z_stream *stream;
1241  
1242   crutch = (struct gunzip_crutch *)lua_newuserdata(L, sizeof(*crutch));
1243   crutch->stream = malloc(sizeof(*stream));
1244   memset(crutch->stream, 0, sizeof(*crutch->stream));
1245   luaL_getmetatable(L, "noit.gunzip");
1246   lua_setmetatable(L, -2);
1247
1248   crutch->stream->next_in = NULL;
1249   crutch->stream->avail_in = 0;
1250   crutch->scratch_buffer =
1251     crutch->stream->next_out = malloc(DEFLATE_CHUNK_SIZE);
1252   crutch->stream->avail_out = crutch->stream->next_out ? DEFLATE_CHUNK_SIZE : 0;
1253   inflateInit2(crutch->stream, MAX_WBITS+32);
1254
1255   lua_pushcclosure(L, nl_gunzip_deflate, 1);
1256   return 1;
1257 }
1258 static int
1259 noit_lua_gunzip_gc(lua_State *L) {
1260   struct gunzip_crutch *crutch;
1261   crutch = (struct gunzip_crutch *)lua_touserdata(L,1);
1262   if(crutch->scratch_buffer) free(crutch->scratch_buffer);
1263   inflateEnd(crutch->stream);
1264   return 0;
1265 }
1266
1267 struct pcre_global_info {
1268   pcre *re;
1269   int offset;
1270 };
1271 static int
1272 noit_lua_pcre_match(lua_State *L) {
1273   const char *subject;
1274   struct pcre_global_info *pgi;
1275   int i, cnt, ovector[30];
1276   size_t inlen;
1277   struct pcre_extra e = { 0 };
1278
1279   pgi = (struct pcre_global_info *)lua_touserdata(L, lua_upvalueindex(1));
1280   subject = lua_tolstring(L,1,&inlen);
1281   if(!subject) {
1282     lua_pushboolean(L,0);
1283     return 1;
1284   }
1285   if(lua_gettop(L) > 1) {
1286     if(!lua_istable(L, 2)) {
1287       noitL(noit_error, "pcre match called with second argument that is not a table\n");
1288     }
1289     else {
1290       lua_pushstring(L, "limit");
1291       lua_gettable(L, -2);
1292       if(lua_isnumber(L, -1)) {
1293         e.flags |= PCRE_EXTRA_MATCH_LIMIT;
1294         e.match_limit = (int)lua_tonumber(L, -1);
1295       }
1296       lua_pop(L, 1);
1297       lua_pushstring(L, "limit_recurse");
1298       lua_gettable(L, -2);
1299       if(lua_isnumber(L, -1)) {
1300         e.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
1301         e.match_limit_recursion = (int)lua_tonumber(L, -1);
1302       }
1303       lua_pop(L, 1);
1304     }
1305   }
1306   if (pgi->offset >= inlen) {
1307     lua_pushboolean(L,0);
1308     return 1;
1309   }
1310   cnt = pcre_exec(pgi->re, &e, subject + pgi->offset,
1311                   inlen - pgi->offset, 0, 0,
1312                   ovector, sizeof(ovector)/sizeof(*ovector));
1313   if(cnt <= 0) {
1314     lua_pushboolean(L,0);
1315     return 1;
1316   }
1317   lua_pushboolean(L,1);
1318   for(i = 0; i < cnt; i++) {
1319     int start = ovector[i*2];
1320     int end = ovector[i*2+1];
1321     lua_pushlstring(L, subject+pgi->offset+start, end-start);
1322   }
1323   pgi->offset += ovector[1]; /* endof the overall match */
1324   return cnt+1;
1325 }
1326 static int
1327 nl_pcre(lua_State *L) {
1328   pcre *re;
1329   struct pcre_global_info *pgi;
1330   const char *expr;
1331   const char *errstr;
1332   int erroff;
1333
1334   expr = lua_tostring(L,1);
1335   re = pcre_compile(expr, 0, &errstr, &erroff, NULL);
1336   if(!re) {
1337     lua_pushnil(L);
1338     lua_pushstring(L, errstr);
1339     lua_pushinteger(L, erroff);
1340     return 3;
1341   }
1342   pgi = (struct pcre_global_info *)lua_newuserdata(L, sizeof(*pgi));
1343   pgi->re = re;
1344   pgi->offset = 0;
1345   luaL_getmetatable(L, "noit.pcre");
1346   lua_setmetatable(L, -2);
1347   lua_pushcclosure(L, noit_lua_pcre_match, 1);
1348   return 1;
1349 }
1350 static int
1351 noit_lua_pcre_gc(lua_State *L) {
1352   struct pcre_global_info *pgi;
1353   pgi = (struct pcre_global_info *)lua_touserdata(L,1);
1354   pcre_free(pgi->re);
1355   return 0;
1356 }
1357
1358 static int
1359 nl_conf_get_string(lua_State *L) {
1360   char *val;
1361   const char *path = lua_tostring(L,1);
1362   if(path &&
1363      noit_conf_get_string(NULL, path, &val)) {
1364     lua_pushstring(L,val);
1365     free(val);
1366   }
1367   else lua_pushnil(L);
1368   return 1;
1369 }
1370 static int
1371 nl_conf_get_integer(lua_State *L) {
1372   int val;
1373   const char *path = lua_tostring(L,1);
1374   if(path &&
1375      noit_conf_get_int(NULL, path, &val)) {
1376     lua_pushinteger(L,val);
1377   }
1378   else lua_pushnil(L);
1379   return 1;
1380 }
1381 static int
1382 nl_conf_get_boolean(lua_State *L) {
1383   noit_boolean val;
1384   const char *path = lua_tostring(L,1);
1385   if(path &&
1386      noit_conf_get_boolean(NULL, path, &val)) {
1387     lua_pushboolean(L,val);
1388   }
1389   else lua_pushnil(L);
1390   return 1;
1391 }
1392 static int
1393 nl_conf_get_float(lua_State *L) {
1394   float val;
1395   const char *path = lua_tostring(L,1);
1396   if(path &&
1397      noit_conf_get_float(NULL, path, &val)) {
1398     lua_pushnumber(L,val);
1399   }
1400   else lua_pushnil(L);
1401   return 1;
1402 }
1403 struct xpath_iter {
1404   xmlXPathContextPtr ctxt;
1405   xmlXPathObjectPtr pobj;
1406   int cnt;
1407   int idx;
1408 };
1409 static int
1410 noit_lua_xpath_iter(lua_State *L) {
1411   struct xpath_iter *xpi;
1412   xpi = lua_touserdata(L, lua_upvalueindex(1));
1413   if(xpi->pobj) {
1414     if(xpi->idx < xpi->cnt) {
1415       xmlNodePtr node, *nodeptr;
1416       node = xmlXPathNodeSetItem(xpi->pobj->nodesetval, xpi->idx);
1417       xpi->idx++;
1418       nodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(node));
1419       *nodeptr = node;
1420       luaL_getmetatable(L, "noit.xmlnode");
1421       lua_setmetatable(L, -2);
1422       return 1;
1423     }
1424   }
1425   return 0;
1426 }
1427 static int
1428 noit_lua_xpath(lua_State *L) {
1429   int n;
1430   const char *xpathexpr;
1431   xmlDocPtr *docptr, doc;
1432   xmlNodePtr *nodeptr = NULL;
1433   xmlXPathContextPtr ctxt;
1434   struct xpath_iter *xpi;
1435
1436   n = lua_gettop(L);
1437   /* the first arg is implicitly self (it's a method) */
1438   docptr = lua_touserdata(L, lua_upvalueindex(1));
1439   if(docptr != lua_touserdata(L, 1))
1440     luaL_error(L, "must be called as method");
1441   if(n < 2 || n > 3) luaL_error(L, "expects 1 or 2 arguments, got %d", n);
1442   doc = *docptr;
1443   xpathexpr = lua_tostring(L, 2);
1444   if(!xpathexpr) luaL_error(L, "no xpath expression provided");
1445   ctxt = xmlXPathNewContext(doc);
1446   if(n == 3) {
1447     nodeptr = lua_touserdata(L, 3);
1448     if(nodeptr) ctxt->node = *nodeptr;
1449   }
1450   if(!ctxt) luaL_error(L, "invalid xpath");
1451
1452   xpi = (struct xpath_iter *)lua_newuserdata(L, sizeof(*xpi));
1453   xpi->ctxt = ctxt;
1454   xpi->pobj = xmlXPathEval((xmlChar *)xpathexpr, xpi->ctxt);
1455   if(!xpi->pobj || xpi->pobj->type != XPATH_NODESET)
1456     xpi->cnt = 0;
1457   else
1458     xpi->cnt = xmlXPathNodeSetGetLength(xpi->pobj->nodesetval);
1459   xpi->idx = 0;
1460   luaL_getmetatable(L, "noit.xpathiter");
1461   lua_setmetatable(L, -2);
1462   lua_pushcclosure(L, noit_lua_xpath_iter, 1);
1463   return 1;
1464 }
1465 static int
1466 noit_lua_xmlnode_name(lua_State *L) {
1467   xmlNodePtr *nodeptr;
1468   /* the first arg is implicitly self (it's a method) */
1469   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1470   if(nodeptr != lua_touserdata(L, 1))
1471     luaL_error(L, "must be called as method");
1472   if(lua_gettop(L) == 1) {
1473     xmlChar *v;
1474     v = (xmlChar *)(*nodeptr)->name;
1475     if(v) {
1476       lua_pushstring(L, (const char *)v);
1477     }
1478     else lua_pushnil(L);
1479     return 1;
1480   }
1481   luaL_error(L,"must be called with no arguments");
1482   return 0;
1483 }
1484 static int
1485 noit_lua_xmlnode_attr(lua_State *L) {
1486   xmlNodePtr *nodeptr;
1487   /* the first arg is implicitly self (it's a method) */
1488   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1489   if(nodeptr != lua_touserdata(L, 1))
1490     luaL_error(L, "must be called as method");
1491   if(lua_gettop(L) == 3 && lua_isstring(L,2)) {
1492     const char *attr = lua_tostring(L,2);
1493     if(lua_isnil(L,3))
1494       xmlSetProp(*nodeptr, (xmlChar *)attr, NULL);
1495     else
1496       xmlSetProp(*nodeptr, (xmlChar *)attr, (xmlChar *)lua_tostring(L,3));
1497     return 0;
1498   }
1499   if(lua_gettop(L) == 2 && lua_isstring(L,2)) {
1500     xmlChar *v;
1501     const char *attr = lua_tostring(L,2);
1502     v = xmlGetProp(*nodeptr, (xmlChar *)attr);
1503     if(v) {
1504       lua_pushstring(L, (const char *)v);
1505       xmlFree(v);
1506     }
1507     else lua_pushnil(L);
1508     return 1;
1509   }
1510   luaL_error(L,"must be called with one argument");
1511   return 0;
1512 }
1513 static int
1514 noit_lua_xmlnode_contents(lua_State *L) {
1515   xmlNodePtr *nodeptr;
1516   /* the first arg is implicitly self (it's a method) */
1517   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1518   if(nodeptr != lua_touserdata(L, 1))
1519     luaL_error(L, "must be called as method");
1520   if(lua_gettop(L) == 2 && lua_isstring(L,2)) {
1521     const char *data = lua_tostring(L,2);
1522     xmlChar *enc = xmlEncodeEntitiesReentrant((*nodeptr)->doc, (xmlChar *)data);
1523     xmlNodeSetContent(*nodeptr, (xmlChar *)enc);
1524     return 0;
1525   }
1526   if(lua_gettop(L) == 1) {
1527     xmlChar *v;
1528     v = xmlNodeGetContent(*nodeptr);
1529     if(v) {
1530       lua_pushstring(L, (const char *)v);
1531       xmlFree(v);
1532     }
1533     else lua_pushnil(L);
1534     return 1;
1535   }
1536   luaL_error(L,"must be called with no arguments");
1537   return 0;
1538 }
1539 static int
1540 noit_lua_xmlnode_next(lua_State *L) {
1541   xmlNodePtr *nodeptr;
1542   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1543   if(*nodeptr) {
1544     xmlNodePtr *newnodeptr;
1545     newnodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(*nodeptr));
1546     *newnodeptr = *nodeptr;
1547     luaL_getmetatable(L, "noit.xmlnode");
1548     lua_setmetatable(L, -2);
1549     *nodeptr = (*nodeptr)->next;
1550     return 1;
1551   }
1552   return 0;
1553 }
1554 static int
1555 noit_lua_xmlnode_addchild(lua_State *L) {
1556   xmlNodePtr *nodeptr;
1557   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1558   if(nodeptr != lua_touserdata(L, 1))
1559     luaL_error(L, "must be called as method");
1560   if(lua_gettop(L) == 2 && lua_isstring(L,2)) {
1561     xmlNodePtr *newnodeptr;
1562     newnodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(*nodeptr));
1563     *newnodeptr = xmlNewChild(*nodeptr, NULL,
1564                               (xmlChar *)lua_tostring(L,2), NULL);
1565     luaL_getmetatable(L, "noit.xmlnode");
1566     lua_setmetatable(L, -2);
1567     return 1;
1568   }
1569   luaL_error(L,"must be called with one argument");
1570   return 0;
1571 }
1572 static int
1573 noit_lua_xmlnode_children(lua_State *L) {
1574   xmlNodePtr *nodeptr, node, cnode;
1575   /* the first arg is implicitly self (it's a method) */
1576   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1577   if(nodeptr != lua_touserdata(L, 1))
1578     luaL_error(L, "must be called as method");
1579   node = *nodeptr;
1580   cnode = node->children;
1581   nodeptr = lua_newuserdata(L, sizeof(cnode));
1582   *nodeptr = cnode;
1583   luaL_getmetatable(L, "noit.xmlnode");
1584   lua_setmetatable(L, -2);
1585   lua_pushcclosure(L, noit_lua_xmlnode_next, 1);
1586   return 1;
1587 }
1588 static int
1589 noit_lua_xml_tostring(lua_State *L) {
1590   int n;
1591   xmlDocPtr *docptr;
1592   char *xmlstring;
1593   n = lua_gettop(L);
1594   /* the first arg is implicitly self (it's a method) */
1595   docptr = lua_touserdata(L, lua_upvalueindex(1));
1596   if(docptr != lua_touserdata(L, 1))
1597     luaL_error(L, "must be called as method");
1598   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1599   xmlstring = noit_xmlSaveToBuffer(*docptr);
1600   lua_pushstring(L, xmlstring);
1601   free(xmlstring);
1602   return 1;
1603 }
1604 static int
1605 noit_lua_xml_docroot(lua_State *L) {
1606   int n;
1607   xmlDocPtr *docptr;
1608   xmlNodePtr *ptr;
1609   n = lua_gettop(L);
1610   /* the first arg is implicitly self (it's a method) */
1611   docptr = lua_touserdata(L, lua_upvalueindex(1));
1612   if(docptr != lua_touserdata(L, 1))
1613     luaL_error(L, "must be called as method");
1614   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1615   ptr = lua_newuserdata(L, sizeof(*ptr));
1616   *ptr = xmlDocGetRootElement(*docptr);
1617   luaL_getmetatable(L, "noit.xmlnode");
1618   lua_setmetatable(L, -2);
1619   return 1;
1620 }
1621 static int
1622 noit_lua_xpathiter_gc(lua_State *L) {
1623   struct xpath_iter *xpi;
1624   xpi = lua_touserdata(L, 1);
1625   xmlXPathFreeContext(xpi->ctxt);
1626   if(xpi->pobj) xmlXPathFreeObject(xpi->pobj);
1627   return 0;
1628 }
1629 static int
1630 noit_xmlnode_index_func(lua_State *L) {
1631   int n;
1632   const char *k;
1633   xmlNodePtr *udata;
1634   n = lua_gettop(L); /* number of arguments */
1635   assert(n == 2);
1636   if(!luaL_checkudata(L, 1, "noit.xmlnode")) {
1637     luaL_error(L, "metatable error, arg1 not a noit.xmlnode!");
1638   }
1639   udata = lua_touserdata(L, 1);
1640   if(!lua_isstring(L, 2)) {
1641     luaL_error(L, "metatable error, arg2 not a string!");
1642   }
1643   k = lua_tostring(L, 2);
1644   switch(*k) {
1645     case 'a':
1646       LUA_DISPATCH(attr, noit_lua_xmlnode_attr);
1647       LUA_DISPATCH(attribute, noit_lua_xmlnode_attr);
1648       LUA_DISPATCH(addchild, noit_lua_xmlnode_addchild);
1649       break;
1650     case 'c':
1651       LUA_DISPATCH(children, noit_lua_xmlnode_children);
1652       LUA_DISPATCH(contents, noit_lua_xmlnode_contents);
1653       break;
1654     case 'n':
1655       LUA_DISPATCH(name, noit_lua_xmlnode_name);
1656       break;
1657     default:
1658       break;
1659   }
1660   luaL_error(L, "noit.xmlnode no such element: %s", k);
1661   return 0;
1662 }
1663 static int
1664 nl_parsexml(lua_State *L) {
1665   xmlDocPtr *docptr, doc;
1666   const char *in;
1667   size_t inlen;
1668
1669   if(lua_gettop(L) != 1) luaL_error(L, "parsexml requires one argument");
1670
1671   in = lua_tolstring(L, 1, &inlen);
1672   doc = xmlParseMemory(in, inlen);
1673   if(!doc) {
1674     lua_pushnil(L);
1675     return 1;
1676   }
1677
1678   docptr = (xmlDocPtr *)lua_newuserdata(L, sizeof(doc));
1679   *docptr = doc;
1680   luaL_getmetatable(L, "noit.xmldoc");
1681   lua_setmetatable(L, -2);
1682   return 1;
1683 }
1684 static int
1685 noit_lua_xmldoc_gc(lua_State *L) {
1686   xmlDocPtr *holder;
1687   holder = (xmlDocPtr *)lua_touserdata(L,1);
1688   xmlFreeDoc(*holder);
1689   return 0;
1690 }
1691 static int
1692 noit_xmldoc_index_func(lua_State *L) {
1693   int n;
1694   const char *k;
1695   xmlDocPtr *udata;
1696   n = lua_gettop(L); /* number of arguments */
1697   assert(n == 2);
1698   if(!luaL_checkudata(L, 1, "noit.xmldoc")) {
1699     luaL_error(L, "metatable error, arg1 not a noit.xmldoc!");
1700   }
1701   udata = lua_touserdata(L, 1);
1702   if(!lua_isstring(L, 2)) {
1703     luaL_error(L, "metatable error, arg2 not a string!");
1704   }
1705   k = lua_tostring(L, 2);
1706   switch(*k) {
1707     case 'r':
1708      LUA_DISPATCH(root, noit_lua_xml_docroot);
1709      break;
1710     case 't':
1711      LUA_DISPATCH(tostring, noit_lua_xml_tostring);
1712      break;
1713     case 'x':
1714      LUA_DISPATCH(xpath, noit_lua_xpath);
1715      break;
1716     default:
1717      break;
1718   }
1719   luaL_error(L, "noit.xmldoc no such element: %s", k);
1720   return 0;
1721 }
1722
1723 static int
1724 noit_lua_json_tostring(lua_State *L) {
1725   int n;
1726   json_crutch **docptr;
1727   const char *jsonstring;
1728   n = lua_gettop(L);
1729   /* the first arg is implicitly self (it's a method) */
1730   docptr = lua_touserdata(L, lua_upvalueindex(1));
1731   if(docptr != lua_touserdata(L, 1))
1732     luaL_error(L, "must be called as method");
1733   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1734   jsonstring = json_object_to_json_string((*docptr)->root);
1735   lua_pushstring(L, jsonstring);
1736   /* jsonstring is freed with the root object later */
1737   return 1;
1738 }
1739 static int
1740 noit_json_object_to_luatype(lua_State *L, struct json_object *o) {
1741   if(!o) {
1742     lua_pushnil(L);
1743     return 1;
1744   }
1745   switch(json_object_get_type(o)) {
1746     case json_type_null: lua_pushnil(L); break;
1747     case json_type_object:
1748     {
1749       struct lh_table *lh;
1750       struct lh_entry *el;
1751       lh = json_object_get_object(o);
1752       lua_createtable(L, 0, lh->count);
1753       lh_foreach(lh, el) {
1754         noit_json_object_to_luatype(L, (struct json_object *)el->v);
1755         lua_setfield(L, -2, el->k);
1756       }
1757       break;
1758     }
1759     case json_type_string: lua_pushstring(L, json_object_get_string(o)); break;
1760     case json_type_boolean: lua_pushboolean(L, json_object_get_boolean(o)); break;
1761     case json_type_double: lua_pushnumber(L, json_object_get_double(o)); break;
1762     case json_type_int: lua_pushnumber(L, json_object_get_int(o)); break;
1763     case json_type_array:
1764     {
1765       int i, cnt;
1766       struct array_list *al;
1767       al = json_object_get_array(o);
1768       cnt = al ? array_list_length(al) : 0;
1769       lua_createtable(L, 0, cnt);
1770       for(i=0;i<cnt;i++) {
1771         noit_json_object_to_luatype(L, (struct json_object *)array_list_get_idx(al, i));
1772         lua_rawseti(L, -2, i);
1773       }
1774       break;
1775     }
1776   }
1777   return 1;
1778 }
1779 static int
1780 noit_lua_json_document(lua_State *L) {
1781   int n;
1782   json_crutch **docptr;
1783   n = lua_gettop(L);
1784   /* the first arg is implicitly self (it's a method) */
1785   docptr = lua_touserdata(L, lua_upvalueindex(1));
1786   if(docptr != lua_touserdata(L, 1))
1787     luaL_error(L, "must be called as method");
1788   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1789   return noit_json_object_to_luatype(L, (*docptr)->root);
1790 }
1791 static int
1792 nl_parsejson(lua_State *L) {
1793   json_crutch **docptr, *doc;
1794   const char *in;
1795   size_t inlen;
1796
1797   if(lua_gettop(L) != 1) luaL_error(L, "parsejson requires one argument");
1798
1799   in = lua_tolstring(L, 1, &inlen);
1800   doc = calloc(1, sizeof(*doc));
1801   doc->tok = json_tokener_new();
1802   doc->root = json_tokener_parse_ex(doc->tok, in, inlen);
1803   if(is_error(doc->root)) {
1804     json_tokener_free(doc->tok);
1805     if(doc->root) json_object_put(doc->root);
1806     free(doc);
1807     lua_pushnil(L);
1808     return 1;
1809   }
1810
1811   docptr = (json_crutch **)lua_newuserdata(L, sizeof(doc));
1812   *docptr = doc;
1813   luaL_getmetatable(L, "noit.json");
1814   lua_setmetatable(L, -2);
1815   return 1;
1816 }
1817 static int
1818 noit_lua_json_gc(lua_State *L) {
1819   json_crutch **json;
1820   json = (json_crutch **)lua_touserdata(L,1);
1821   if((*json)->tok) json_tokener_free((*json)->tok);
1822   if((*json)->root) json_object_put((*json)->root);
1823   free(*json);
1824   return 0;
1825 }
1826 static int
1827 noit_json_index_func(lua_State *L) {
1828   int n;
1829   const char *k;
1830   json_crutch **udata;
1831   n = lua_gettop(L); /* number of arguments */
1832   assert(n == 2);
1833   if(!luaL_checkudata(L, 1, "noit.json")) {
1834     luaL_error(L, "metatable error, arg1 not a noit.json!");
1835   }
1836   udata = lua_touserdata(L, 1);
1837   if(!lua_isstring(L, 2)) {
1838     luaL_error(L, "metatable error, arg2 not a string!");
1839   }
1840   k = lua_tostring(L, 2);
1841   switch(*k) {
1842     case 'd':
1843      LUA_DISPATCH(document, noit_lua_json_document);
1844      break;
1845     case 't':
1846      LUA_DISPATCH(tostring, noit_lua_json_tostring);
1847      break;
1848     default:
1849      break;
1850   }
1851   luaL_error(L, "noit.json no such element: %s", k);
1852   return 0;
1853 }
1854 static const luaL_Reg noitlib[] = {
1855   { "sleep", nl_sleep },
1856   { "gettimeofday", nl_gettimeofday },
1857   { "socket", nl_socket },
1858   { "dns", nl_dns_lookup },
1859   { "log", nl_log },
1860   { "base32_decode", nl_base32_decode },
1861   { "base32_encode", nl_base32_encode },
1862   { "base64_decode", nl_base64_decode },
1863   { "base64_encode", nl_base64_encode },
1864   { "md5_hex", nl_md5_hex },
1865   { "pcre", nl_pcre },
1866   { "gunzip", nl_gunzip },
1867   { "conf_get", nl_conf_get_string },
1868   { "conf_get_string", nl_conf_get_string },
1869   { "conf_get_integer", nl_conf_get_integer },
1870   { "conf_get_boolean", nl_conf_get_boolean },
1871   { "conf_get_number", nl_conf_get_float },
1872   { "parsexml", nl_parsexml },
1873   { "parsejson", nl_parsejson },
1874   { NULL, NULL }
1875 };
1876
1877 int luaopen_noit(lua_State *L) {
1878   luaL_newmetatable(L, "noit.eventer");
1879   lua_pushcclosure(L, noit_eventer_index_func, 0);
1880   lua_setfield(L, -2, "__index");
1881
1882   luaL_newmetatable(L, "noit.eventer.ssl_ctx");
1883   lua_pushcclosure(L, noit_ssl_ctx_index_func, 0);
1884   lua_setfield(L, -2, "__index");
1885
1886   luaL_newmetatable(L, "noit.dns");
1887   lua_pushcfunction(L, noit_lua_dns_gc);
1888   lua_setfield(L, -2, "__gc");
1889   luaL_newmetatable(L, "noit.dns");
1890   lua_pushcfunction(L, noit_lua_dns_index_func);
1891   lua_setfield(L, -2, "__index");
1892
1893   luaL_newmetatable(L, "noit.gunzip");
1894   lua_pushcfunction(L, noit_lua_gunzip_gc);
1895   lua_setfield(L, -2, "__gc");
1896
1897   luaL_newmetatable(L, "noit.pcre");
1898   lua_pushcfunction(L, noit_lua_pcre_gc);
1899   lua_setfield(L, -2, "__gc");
1900
1901   luaL_newmetatable(L, "noit.json");
1902   lua_pushcfunction(L, noit_lua_json_gc);
1903   lua_setfield(L, -2, "__gc");
1904   luaL_newmetatable(L, "noit.json");
1905   lua_pushcclosure(L, noit_json_index_func, 0);
1906   lua_setfield(L, -2, "__index");
1907
1908   luaL_newmetatable(L, "noit.xmldoc");
1909   lua_pushcfunction(L, noit_lua_xmldoc_gc);
1910   lua_setfield(L, -2, "__gc");
1911   luaL_newmetatable(L, "noit.xmldoc");
1912   lua_pushcclosure(L, noit_xmldoc_index_func, 0);
1913   lua_setfield(L, -2, "__index");
1914
1915   luaL_newmetatable(L, "noit.xmlnode");
1916   lua_pushcclosure(L, noit_xmlnode_index_func, 0);
1917   lua_setfield(L, -2, "__index");
1918
1919   luaL_newmetatable(L, "noit.xpathiter");
1920   lua_pushcfunction(L, noit_lua_xpathiter_gc);
1921   lua_setfield(L, -2, "__gc");
1922
1923   luaL_register(L, "noit", noitlib);
1924   return 0;
1925 }
1926
1927 void noit_lua_init() {
1928   eventer_name_callback("lua/sleep", nl_sleep_complete);
1929   eventer_name_callback("lua/socket_read",
1930                         noit_lua_socket_read_complete);
1931   eventer_name_callback("lua/socket_write",
1932                         noit_lua_socket_write_complete);
1933   eventer_name_callback("lua/socket_send",
1934                         noit_lua_socket_send_complete);
1935   eventer_name_callback("lua/socket_connect",
1936                         noit_lua_socket_connect_complete);
1937   eventer_name_callback("lua/ssl_upgrade", noit_lua_ssl_upgrade);
1938   noit_lua_init_dns();
1939 }
Note: See TracBrowser for help on using the browser.