root/src/modules/lua_noit.c

Revision 1d24f9eb2f57e2ec2176345ab54522661ae88465, 52.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

If the SSL connect "completed" (good or bad) without blocking, we
would lua_resume while already in lua. That resume should only
happen when we're called from the scheduler. So, from the original
instigator, we'll just do the SSL connect manually and handle the
"immediate" connection correctly.

  • 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   int tmpmask, rv;
533
534   ci = get_ci(L);
535   assert(ci);
536
537   eptr = lua_touserdata(L, lua_upvalueindex(1));
538   if(eptr != lua_touserdata(L, 1))
539     luaL_error(L, "must be called as method");
540   e = *eptr;
541   cert = lua_tostring(L, 2);
542   key = lua_tostring(L, 3);
543   ca = lua_tostring(L, 4);
544   ciphers = lua_tostring(L, 5);
545
546   sslctx = eventer_ssl_ctx_new(SSL_CLIENT, cert, key, ca, ciphers);
547   if(!sslctx) {
548     lua_pushinteger(L, -1);
549     return 1;
550   }
551
552   eventer_ssl_ctx_set_verify(sslctx, eventer_ssl_verify_cert, NULL);
553   EVENTER_ATTACH_SSL(e, sslctx);
554
555   /* We need do the ssl connect and register a completion if
556    * it comes back with an EAGAIN.
557    */
558   tmpmask = EVENTER_READ|EVENTER_WRITE;
559   rv = eventer_SSL_connect(e, &tmpmask);
560   if(rv <= 0 && errno == EAGAIN) {
561     /* Need completion */
562     e->mask = tmpmask | EVENTER_EXCEPTION;
563     e->callback = noit_lua_ssl_upgrade;
564     eventer_add(e);
565     return noit_lua_yield(ci, 0);
566   }
567   lua_pushinteger(L, (rv > 0) ? 0 : -1);
568   return 1;
569 }
570
571 static int
572 noit_lua_socket_do_read(eventer_t e, int *mask, struct nl_slcl *cl,
573                         int *read_complete) {
574   char buff[4096];
575   int len;
576   *read_complete = 0;
577   while((len = e->opset->read(e->fd, buff, sizeof(buff), mask, e)) > 0) {
578     if(cl->read_goal) {
579       int remaining = cl->read_goal - cl->read_sofar;
580       /* copy up to the goal into the inbuff */
581       inbuff_addlstring(cl, buff, MIN(len, remaining));
582       cl->read_sofar += len;
583       if(cl->read_sofar >= cl->read_goal) { /* We're done */
584         lua_pushlstring(cl->L, cl->inbuff, cl->read_goal);
585         *read_complete = 1;
586         cl->read_sofar -= cl->read_goal;
587         cl->inbuff_len = 0;
588         if(cl->read_sofar > 0) {  /* We have to buffer this for next read */
589           inbuff_addlstring(cl, buff + remaining, cl->read_sofar);
590         }
591         break;
592       }
593     }
594     else if(cl->read_terminator) {
595       const char *cp;
596       int remaining = len;
597       cp = strnstrn(cl->read_terminator, strlen(cl->read_terminator),
598                     buff, len);
599       if(cp) remaining = cp - buff + strlen(cl->read_terminator);
600       inbuff_addlstring(cl, buff, MIN(len, remaining));
601       cl->read_sofar += len;
602       if(cp) {
603         lua_pushlstring(cl->L, cl->inbuff, cl->inbuff_len);
604         *read_complete = 1;
605        
606         cl->read_sofar = len - remaining;
607         cl->inbuff_len = 0;
608         if(cl->read_sofar > 0) { /* We have to buffer this for next read */
609           inbuff_addlstring(cl, buff + remaining, cl->read_sofar);
610         }
611         break;
612       }
613     }
614   }
615   if(len == 0 && cl->inbuff_len) {
616     /* EOF */
617     *read_complete = 1;
618     lua_pushlstring(cl->L, cl->inbuff, cl->inbuff_len);
619     cl->inbuff_len = 0;
620   }
621   return len;
622 }
623 static int
624 noit_lua_socket_read_complete(eventer_t e, int mask, void *vcl,
625                               struct timeval *now) {
626   noit_lua_check_info_t *ci;
627   struct nl_slcl *cl = vcl;
628   int len;
629   int args = 0;
630
631   ci = get_ci(cl->L);
632   assert(ci);
633
634   len = noit_lua_socket_do_read(e, &mask, cl, &args);
635   if(len >= 0) {
636     /* We broke out, cause we read enough... */
637   }
638   else if(len == -1 && errno == EAGAIN) {
639     return mask | EVENTER_EXCEPTION;
640   }
641   else {
642     lua_pushnil(cl->L);
643     args = 1;
644   }
645   eventer_remove_fd(e->fd);
646   noit_lua_check_deregister_event(ci, e, 0);
647   *(cl->eptr) = eventer_alloc();
648   memcpy(*cl->eptr, e, sizeof(*e));
649   noit_lua_check_register_event(ci, *cl->eptr);
650   noit_lua_resume(ci, args);
651   return 0;
652 }
653
654 static int
655 noit_lua_socket_read(lua_State *L) {
656   int args, mask, len;
657   struct nl_slcl *cl;
658   noit_lua_check_info_t *ci;
659   eventer_t e, *eptr;
660
661   ci = get_ci(L);
662   assert(ci);
663
664   eptr = lua_touserdata(L, lua_upvalueindex(1));
665   if(eptr != lua_touserdata(L, 1))
666     luaL_error(L, "must be called as method");
667   e = *eptr;
668   cl = e->closure;
669   cl->read_goal = 0;
670   cl->read_terminator = NULL;
671
672   if(lua_isnumber(L, 2)) {
673     cl->read_goal = lua_tointeger(L, 2);
674     if(cl->read_goal <= cl->read_sofar) {
675      i_know_better:
676       /* We have enough, we can service this right here */
677       lua_pushlstring(L, cl->inbuff, cl->read_goal);
678       cl->read_sofar -= cl->read_goal;
679       if(cl->read_sofar) {
680         memmove(cl->inbuff, cl->inbuff + cl->read_goal, cl->read_sofar);
681       }
682       cl->inbuff_len = cl->read_sofar;
683       return 1;
684     }
685   }
686   else {
687     cl->read_terminator = lua_tostring(L, 2);
688     if(cl->read_sofar) {
689       const char *cp;
690       /* Ugh... inernalism */
691       cp = strnstrn(cl->read_terminator, strlen(cl->read_terminator),
692                     cl->inbuff, cl->read_sofar);
693       if(cp) {
694         /* Here we matched... and we _know_ that someone actually wants:
695          * strlen(cl->read_terminator) + cp - cl->inbuff.buffer bytes...
696          * give it to them.
697          */
698         cl->read_goal = strlen(cl->read_terminator) + cp - cl->inbuff;
699         cl->read_terminator = NULL;
700         assert(cl->read_goal <= cl->read_sofar);
701         goto i_know_better;
702       }
703     }
704   }
705
706   len = noit_lua_socket_do_read(e, &mask, cl, &args);
707   if(args == 1) return 1; /* completed read, return result */
708   if(len == -1 && errno == EAGAIN) {
709     /* we need to drop into eventer */
710   }
711   else {
712     lua_pushnil(cl->L);
713     args = 1;
714     return args;
715   }
716
717   e->callback = noit_lua_socket_read_complete;
718   e->mask = mask | EVENTER_EXCEPTION;
719   eventer_add(e);
720   return noit_lua_yield(ci, 0);
721 }
722 static int
723 noit_lua_socket_write_complete(eventer_t e, int mask, void *vcl,
724                                struct timeval *now) {
725   noit_lua_check_info_t *ci;
726   struct nl_slcl *cl = vcl;
727   int rv;
728   int args = 0;
729
730   ci = get_ci(cl->L);
731   assert(ci);
732
733   if(mask & EVENTER_EXCEPTION) {
734     lua_pushinteger(cl->L, -1);
735     args = 1;
736     goto alldone;
737   }
738   while((rv = e->opset->write(e->fd,
739                               cl->outbuff + cl->write_sofar,
740                               MIN(cl->send_size, cl->write_goal),
741                               &mask, e)) > 0) {
742     cl->write_sofar += rv;
743     assert(cl->write_sofar <= cl->write_goal);
744     if(cl->write_sofar == cl->write_goal) break;
745   }
746   if(rv > 0) {
747     lua_pushinteger(cl->L, cl->write_goal);
748     args = 1;
749   }
750   else if(rv == -1 && errno == EAGAIN) {
751     return mask | EVENTER_EXCEPTION;
752   }
753   else {
754     lua_pushinteger(cl->L, -1);
755     args = 1;
756     if(rv == -1) {
757       lua_pushstring(cl->L, strerror(errno));
758       args++;
759     }
760   }
761
762  alldone:
763   eventer_remove_fd(e->fd);
764   noit_lua_check_deregister_event(ci, e, 0);
765   *(cl->eptr) = eventer_alloc();
766   memcpy(*cl->eptr, e, sizeof(*e));
767   noit_lua_check_register_event(ci, *cl->eptr);
768   noit_lua_resume(ci, args);
769   return 0;
770 }
771 static int
772 noit_lua_socket_write(lua_State *L) {
773   int rv, mask;
774   struct nl_slcl *cl;
775   noit_lua_check_info_t *ci;
776   eventer_t e, *eptr;
777
778   ci = get_ci(L);
779   assert(ci);
780
781   eptr = lua_touserdata(L, lua_upvalueindex(1));
782   if(eptr != lua_touserdata(L, 1))
783     luaL_error(L, "must be called as method");
784   e = *eptr;
785   cl = e->closure;
786   cl->write_sofar = 0;
787   cl->outbuff = lua_tolstring(L, 2, &cl->write_goal);
788
789   while((rv = e->opset->write(e->fd,
790                               cl->outbuff + cl->write_sofar,
791                               MIN(cl->send_size, cl->write_goal),
792                               &mask, e)) > 0) {
793     cl->write_sofar += rv;
794     assert(cl->write_sofar <= cl->write_goal);
795     if(cl->write_sofar == cl->write_goal) break;
796   }
797   if(rv > 0) {
798     lua_pushinteger(L, cl->write_goal);
799     return 1;
800   }
801   if(rv == -1 && errno == EAGAIN) {
802     e->callback = noit_lua_socket_write_complete;
803     e->mask = mask | EVENTER_EXCEPTION;
804     eventer_add(e);
805     return noit_lua_yield(ci, 0);
806   }
807   lua_pushinteger(L, -1);
808   return 1;
809 }
810 static int
811 noit_lua_socket_ssl_ctx(lua_State *L) {
812   eventer_t *eptr, e;
813   eventer_ssl_ctx_t **ssl_ctx_holder, *ssl_ctx;
814
815   eptr = lua_touserdata(L, lua_upvalueindex(1));
816   if(eptr != lua_touserdata(L, 1))
817     luaL_error(L, "must be called as method");
818   e = *eptr;
819
820   ssl_ctx = eventer_get_eventer_ssl_ctx(e);
821   if(!ssl_ctx) {
822     lua_pushnil(L);
823     return 1;
824   }
825
826   ssl_ctx_holder = (eventer_ssl_ctx_t **)lua_newuserdata(L, sizeof(ssl_ctx));
827   *ssl_ctx_holder = ssl_ctx;
828   luaL_getmetatable(L, "noit.eventer.ssl_ctx");
829   lua_setmetatable(L, -2);
830   return 1;
831 }
832 static int
833 noit_eventer_index_func(lua_State *L) {
834   int n;
835   const char *k;
836   eventer_t *udata;
837   n = lua_gettop(L); /* number of arguments */
838   assert(n == 2);
839   if(!luaL_checkudata(L, 1, "noit.eventer")) {
840     luaL_error(L, "metatable error, arg1 not a noit.eventer!");
841   }
842   udata = lua_touserdata(L, 1);
843   if(!lua_isstring(L, 2)) {
844     luaL_error(L, "metatable error, arg2 not a string!");
845   }
846   k = lua_tostring(L, 2);
847   switch(*k) {
848     case 'c':
849      LUA_DISPATCH(connect, noit_lua_socket_connect);
850      break;
851     case 'r':
852      LUA_DISPATCH(read, noit_lua_socket_read);
853      LUA_DISPATCH(recv, noit_lua_socket_recv);
854      break;
855     case 's':
856      LUA_DISPATCH(send, noit_lua_socket_send);
857      LUA_DISPATCH(sendto, noit_lua_socket_sendto);
858      LUA_DISPATCH(ssl_upgrade_socket, noit_lua_socket_connect_ssl);
859      LUA_DISPATCH(ssl_ctx, noit_lua_socket_ssl_ctx);
860      break;
861     case 'w':
862      LUA_DISPATCH(write, noit_lua_socket_write);
863      break;
864     default:
865       break;
866   }
867   luaL_error(L, "noit.eventer no such element: %s", k);
868   return 0;
869 }
870
871 static eventer_t *
872 noit_lua_event(lua_State *L, eventer_t e) {
873   eventer_t *addr;
874   addr = (eventer_t *)lua_newuserdata(L, sizeof(e));
875   *addr = e;
876   luaL_getmetatable(L, "noit.eventer");
877   lua_setmetatable(L, -2);
878   return addr;
879 }
880
881 static int
882 noit_ssl_ctx_index_func(lua_State *L) {
883   int n;
884   const char *k;
885   eventer_ssl_ctx_t **udata, *ssl_ctx;
886   n = lua_gettop(L); /* number of arguments */
887   assert(n == 2);
888   if(!luaL_checkudata(L, 1, "noit.eventer.ssl_ctx")) {
889     luaL_error(L, "metatable error, arg1 not a noit.eventer.ssl_ctx!");
890   }
891   udata = lua_touserdata(L, 1);
892   ssl_ctx = *udata;
893   if(!lua_isstring(L, 2)) {
894     luaL_error(L, "metatable error, arg2 not a string!");
895   }
896   k = lua_tostring(L, 2);
897   switch(*k) {
898     case 'e':
899       LUA_RETSTRING(error, eventer_ssl_get_peer_error(ssl_ctx));
900       LUA_RETINTEGER(end_time, eventer_ssl_get_peer_end_time(ssl_ctx));
901       break;
902     case 'i':
903       LUA_RETSTRING(issuer, eventer_ssl_get_peer_issuer(ssl_ctx));
904       break;
905     case 's':
906       LUA_RETSTRING(subject, eventer_ssl_get_peer_subject(ssl_ctx));
907       LUA_RETINTEGER(start_time, eventer_ssl_get_peer_start_time(ssl_ctx));
908       break;
909     default:
910       break;
911   }
912   luaL_error(L, "noit.eventer.ssl_ctx no such element: %s", k);
913   return 0;
914 }
915
916 static int
917 nl_sleep_complete(eventer_t e, int mask, void *vcl, struct timeval *now) {
918   noit_lua_check_info_t *ci;
919   struct nl_slcl *cl = vcl;
920   struct timeval diff;
921   double p_int;
922
923   ci = get_ci(cl->L);
924   assert(ci);
925   noit_lua_check_deregister_event(ci, e, 0);
926
927   sub_timeval(*now, cl->start, &diff);
928   p_int = diff.tv_sec + diff.tv_usec / 1000000.0;
929   lua_pushnumber(cl->L, p_int);
930   free(cl);
931   noit_lua_resume(ci, 1);
932   return 0;
933 }
934
935 static int
936 nl_sleep(lua_State *L) {
937   noit_lua_check_info_t *ci;
938   struct nl_slcl *cl;
939   struct timeval diff;
940   eventer_t e;
941   double p_int;
942
943   ci = get_ci(L);
944   assert(ci);
945
946   p_int = lua_tonumber(L, 1);
947   cl = calloc(1, sizeof(*cl));
948   cl->free = nl_extended_free;
949   cl->L = L;
950   gettimeofday(&cl->start, NULL);
951
952   e = eventer_alloc();
953   e->mask = EVENTER_TIMER;
954   e->callback = nl_sleep_complete;
955   e->closure = cl;
956   memcpy(&e->whence, &cl->start, sizeof(cl->start));
957   diff.tv_sec = floor(p_int);
958   diff.tv_usec = (p_int - floor(p_int)) * 1000000;
959   add_timeval(e->whence, diff, &e->whence);
960   noit_lua_check_register_event(ci, e);
961   eventer_add(e);
962   return noit_lua_yield(ci, 0);
963 }
964
965 static int
966 nl_log(lua_State *L) {
967   int i, n;
968   const char *log_dest, *message;
969   noit_log_stream_t ls;
970
971   if(lua_gettop(L) < 2) luaL_error(L, "bad call to noit.log");
972
973   log_dest = lua_tostring(L, 1);
974   ls = noit_log_stream_find(log_dest);
975   if(!ls) {
976     noitL(noit_stderr, "Cannot find log stream: '%s'\n", log_dest);
977     return 0;
978   }
979
980   n = lua_gettop(L);
981   lua_pushstring(L, "string");
982   lua_gettable(L, LUA_GLOBALSINDEX);
983   lua_pushstring(L, "format");
984   lua_gettable(L, -1);
985   for(i=2;i<=n;i++)
986     lua_pushvalue(L, i);
987   lua_call(L, n-1, 1);
988   message = lua_tostring(L, -1);
989   noitL(ls, "%s", message);
990   lua_pop(L, 1); /* formatted string */
991   lua_pop(L, 1); /* "string" table */
992   return 0;
993 }
994 static int
995 nl_crc32(lua_State *L) {
996   size_t inlen;
997   const char *input;
998   uLong start = 0, inputidx = 1;
999   if(lua_isnil(L,1)) start = crc32(0, NULL, 0);
1000   if(lua_gettop(L) == 2) {
1001     start = lua_tointeger(L, 2);
1002     inputidx = 2;
1003   }
1004   input = lua_tolstring(L, inputidx, &inlen);
1005   lua_pushnumber(L, (double)crc32(start, (Bytef *)input, inlen));
1006   return 1;
1007 }
1008 static int
1009 nl_base32_decode(lua_State *L) {
1010   size_t inlen, decoded_len;
1011   const char *message;
1012   unsigned char *decoded;
1013
1014   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.decode");
1015
1016   message = lua_tolstring(L, 1, &inlen);
1017   decoded = malloc(MAX(1,inlen));
1018   if(!decoded) luaL_error(L, "out-of-memory");
1019   decoded_len = noit_b32_decode(message, inlen, decoded, MAX(1,inlen));
1020   lua_pushlstring(L, (char *)decoded, decoded_len);
1021   return 1;
1022 }
1023 static int
1024 nl_base32_encode(lua_State *L) {
1025   size_t inlen, encoded_len;
1026   const unsigned char *message;
1027   char *encoded;
1028
1029   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.encode");
1030
1031   message = (const unsigned char *)lua_tolstring(L, 1, &inlen);
1032   encoded_len = (((inlen + 7) / 5) * 8) + 1;
1033   encoded = malloc(encoded_len);
1034   if(!encoded) luaL_error(L, "out-of-memory");
1035   encoded_len = noit_b32_encode(message, inlen, encoded, encoded_len);
1036   lua_pushlstring(L, (char *)encoded, encoded_len);
1037   return 1;
1038 }
1039 static int
1040 nl_base64_decode(lua_State *L) {
1041   size_t inlen, decoded_len;
1042   const char *message;
1043   unsigned char *decoded;
1044
1045   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.decode");
1046
1047   message = lua_tolstring(L, 1, &inlen);
1048   decoded = malloc(MAX(1,inlen));
1049   if(!decoded) luaL_error(L, "out-of-memory");
1050   decoded_len = noit_b64_decode(message, inlen, decoded, MAX(1,inlen));
1051   lua_pushlstring(L, (char *)decoded, decoded_len);
1052   return 1;
1053 }
1054 static int
1055 nl_base64_encode(lua_State *L) {
1056   size_t inlen, encoded_len;
1057   const unsigned char *message;
1058   char *encoded;
1059
1060   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.encode");
1061
1062   message = (const unsigned char *)lua_tolstring(L, 1, &inlen);
1063   encoded_len = (((inlen + 2) / 3) * 4) + 1;
1064   encoded = malloc(encoded_len);
1065   if(!encoded) luaL_error(L, "out-of-memory");
1066   encoded_len = noit_b64_encode(message, inlen, encoded, encoded_len);
1067   lua_pushlstring(L, (char *)encoded, encoded_len);
1068   return 1;
1069 }
1070 static const char _hexchars[16] =
1071   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1072 static int
1073 nl_md5_hex(lua_State *L) {
1074   int i;
1075   MD5_CTX ctx;
1076   size_t inlen;
1077   const char *in;
1078   unsigned char md5[MD5_DIGEST_LENGTH];
1079   char md5_hex[MD5_DIGEST_LENGTH * 2 + 1];
1080
1081   if(lua_gettop(L) != 1) luaL_error(L, "bad call to noit.md5_hex");
1082   MD5_Init(&ctx);
1083   in = lua_tolstring(L, 1, &inlen);
1084   MD5_Update(&ctx, (const void *)in, (unsigned long)inlen);
1085   MD5_Final(md5, &ctx);
1086   for(i=0;i<MD5_DIGEST_LENGTH;i++) {
1087     md5_hex[i*2] = _hexchars[(md5[i] >> 4) & 0xf];
1088     md5_hex[i*2+1] = _hexchars[md5[i] & 0xf];
1089   }
1090   md5_hex[i*2] = '\0';
1091   lua_pushstring(L, md5_hex);
1092   return 1;
1093 }
1094 static int
1095 nl_gettimeofday(lua_State *L) {
1096   struct timeval now;
1097   gettimeofday(&now, NULL);
1098   lua_pushinteger(L, now.tv_sec);
1099   lua_pushinteger(L, now.tv_usec);
1100   return 2;
1101 }
1102 static int
1103 nl_socket_internal(lua_State *L, int family, int proto) {
1104   struct nl_slcl *cl;
1105   noit_lua_check_info_t *ci;
1106   socklen_t optlen;
1107   int fd;
1108   eventer_t e;
1109
1110   fd = socket(family, proto, 0);
1111   if(fd < 0) {
1112     lua_pushnil(L);
1113     return 1;
1114   }
1115   if(eventer_set_fd_nonblocking(fd)) {
1116     close(fd);
1117     lua_pushnil(L);
1118     return 1;
1119   }
1120
1121   ci = get_ci(L);
1122   assert(ci);
1123
1124   cl = calloc(1, sizeof(*cl));
1125   cl->free = nl_extended_free;
1126   cl->L = L;
1127
1128   optlen = sizeof(cl->send_size);
1129   if(getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &cl->send_size, &optlen) != 0)
1130     cl->send_size = 4096;
1131
1132   e = eventer_alloc();
1133   e->fd = fd;
1134   e->mask = EVENTER_EXCEPTION;
1135   e->callback = NULL;
1136   e->closure = cl;
1137   cl->eptr = noit_lua_event(L, e);
1138
1139   noit_lua_check_register_event(ci, e);
1140   return 1;
1141 }
1142 static int
1143 nl_socket(lua_State *L) {
1144   int n = lua_gettop(L);
1145   uint8_t family = AF_INET;
1146   union {
1147     struct in_addr addr4;
1148     struct in6_addr addr6;
1149   } a;
1150
1151   if(n > 0 && lua_isstring(L,1)) {
1152     const char *fam = lua_tostring(L,1);
1153     if(!fam) fam = "";
1154     if(!strcmp(fam, "inet")) family = AF_INET;
1155     else if(!strcmp(fam, "inet6")) family = AF_INET6;
1156     else if(inet_pton(AF_INET, fam, &a) == 1) family = AF_INET;
1157     else if(inet_pton(AF_INET6, fam, &a) == 1) family = AF_INET6;
1158     else luaL_error(L, "noit.socket family for %s unknown", fam);
1159   }
1160
1161   if(n <= 1) return nl_socket_internal(L, family, SOCK_STREAM);
1162   if(n == 2 && lua_isstring(L,2)) {
1163     const char *type = lua_tostring(L,2);
1164     if(!strcmp(type, "tcp"))
1165       return nl_socket_internal(L, family, SOCK_STREAM);
1166     else if(!strcmp(type, "udp"))
1167       return nl_socket_internal(L, family, SOCK_DGRAM);
1168   }
1169   luaL_error(L, "noit.socket called with invalid arguments");
1170   return 0;
1171 }
1172
1173 struct gunzip_crutch {
1174   z_stream *stream;
1175   void *scratch_buffer;
1176 };
1177 static int
1178 nl_gunzip_deflate(lua_State *L) {
1179   struct gunzip_crutch *crutch;
1180   const char *input;
1181   size_t inlen;
1182   z_stream *stream;
1183   Bytef *data = NULL;
1184   uLong outlen = 0;
1185   int limit = 1024*1024;
1186   int err, n = lua_gettop(L);
1187
1188   if(n < 1 || n > 2) {
1189     lua_pushnil(L);
1190     return 1;
1191   }
1192
1193   crutch = lua_touserdata(L, lua_upvalueindex(1));
1194   stream = crutch->stream;
1195
1196   input = lua_tolstring(L, 1, &inlen);
1197   if(!input) {
1198     lua_pushnil(L);
1199     return 1;
1200   }
1201   if(n == 2)
1202     limit = lua_tointeger(L, 2);
1203
1204   stream->next_in = (Bytef *)input;
1205   stream->avail_in = inlen;
1206   while(1) {
1207     err = inflate(stream, Z_FULL_FLUSH);
1208     if(err == Z_OK || err == Z_STREAM_END) {
1209       /* got some data */
1210       int size_read = DEFLATE_CHUNK_SIZE - stream->avail_out;
1211       uLong newoutlen = outlen + size_read;
1212       if(newoutlen > limit) {
1213         err = Z_MEM_ERROR;
1214         break;
1215       }
1216       if(newoutlen > outlen) {
1217         Bytef *newdata;
1218         if(data) newdata = realloc(data, newoutlen);
1219         else newdata = malloc(newoutlen);
1220         if(!newdata) {
1221           err = Z_MEM_ERROR;
1222           break;
1223         }
1224         data = newdata;
1225         memcpy(data + outlen, stream->next_out - size_read, size_read);
1226         outlen += size_read;
1227         stream->next_out -= size_read;
1228         stream->avail_out += size_read;
1229       }
1230       if(err == Z_STREAM_END) {
1231         /* Good to go */
1232         break;
1233       }
1234     }
1235     else break;
1236     if(stream->avail_in == 0) break;
1237   }
1238   if(err == Z_OK || err == Z_STREAM_END) {
1239     if(outlen > 0) lua_pushlstring(L, (char *)data, outlen);
1240     else lua_pushstring(L, "");
1241     if(data) free(data);
1242     return 1;
1243   }
1244   if(data) free(data);
1245   switch(err) {
1246     case Z_NEED_DICT: luaL_error(L, "zlib: dictionary error"); break;
1247     case Z_STREAM_ERROR: luaL_error(L, "zlib: stream error"); break;
1248     case Z_DATA_ERROR: luaL_error(L, "zlib: data error"); break;
1249     case Z_MEM_ERROR: luaL_error(L, "zlib: out-of-memory"); break;
1250     case Z_BUF_ERROR: luaL_error(L, "zlib: buffer error"); break;
1251     case Z_VERSION_ERROR: luaL_error(L, "zlib: version mismatch"); break;
1252     case Z_ERRNO: luaL_error(L, strerror(errno)); break;
1253   }
1254   lua_pushnil(L);
1255   return 1;
1256 }
1257 static int
1258 nl_gunzip(lua_State *L) {
1259   struct gunzip_crutch *crutch;
1260   z_stream *stream;
1261  
1262   crutch = (struct gunzip_crutch *)lua_newuserdata(L, sizeof(*crutch));
1263   crutch->stream = malloc(sizeof(*stream));
1264   memset(crutch->stream, 0, sizeof(*crutch->stream));
1265   luaL_getmetatable(L, "noit.gunzip");
1266   lua_setmetatable(L, -2);
1267
1268   crutch->stream->next_in = NULL;
1269   crutch->stream->avail_in = 0;
1270   crutch->scratch_buffer =
1271     crutch->stream->next_out = malloc(DEFLATE_CHUNK_SIZE);
1272   crutch->stream->avail_out = crutch->stream->next_out ? DEFLATE_CHUNK_SIZE : 0;
1273   inflateInit2(crutch->stream, MAX_WBITS+32);
1274
1275   lua_pushcclosure(L, nl_gunzip_deflate, 1);
1276   return 1;
1277 }
1278 static int
1279 noit_lua_gunzip_gc(lua_State *L) {
1280   struct gunzip_crutch *crutch;
1281   crutch = (struct gunzip_crutch *)lua_touserdata(L,1);
1282   if(crutch->scratch_buffer) free(crutch->scratch_buffer);
1283   inflateEnd(crutch->stream);
1284   return 0;
1285 }
1286
1287 struct pcre_global_info {
1288   pcre *re;
1289   int offset;
1290 };
1291 static int
1292 noit_lua_pcre_match(lua_State *L) {
1293   const char *subject;
1294   struct pcre_global_info *pgi;
1295   int i, cnt, ovector[30];
1296   size_t inlen;
1297   struct pcre_extra e = { 0 };
1298
1299   pgi = (struct pcre_global_info *)lua_touserdata(L, lua_upvalueindex(1));
1300   subject = lua_tolstring(L,1,&inlen);
1301   if(!subject) {
1302     lua_pushboolean(L,0);
1303     return 1;
1304   }
1305   if(lua_gettop(L) > 1) {
1306     if(!lua_istable(L, 2)) {
1307       noitL(noit_error, "pcre match called with second argument that is not a table\n");
1308     }
1309     else {
1310       lua_pushstring(L, "limit");
1311       lua_gettable(L, -2);
1312       if(lua_isnumber(L, -1)) {
1313         e.flags |= PCRE_EXTRA_MATCH_LIMIT;
1314         e.match_limit = (int)lua_tonumber(L, -1);
1315       }
1316       lua_pop(L, 1);
1317       lua_pushstring(L, "limit_recurse");
1318       lua_gettable(L, -2);
1319       if(lua_isnumber(L, -1)) {
1320         e.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
1321         e.match_limit_recursion = (int)lua_tonumber(L, -1);
1322       }
1323       lua_pop(L, 1);
1324     }
1325   }
1326   if (pgi->offset >= inlen) {
1327     lua_pushboolean(L,0);
1328     return 1;
1329   }
1330   cnt = pcre_exec(pgi->re, &e, subject + pgi->offset,
1331                   inlen - pgi->offset, 0, 0,
1332                   ovector, sizeof(ovector)/sizeof(*ovector));
1333   if(cnt <= 0) {
1334     lua_pushboolean(L,0);
1335     return 1;
1336   }
1337   lua_pushboolean(L,1);
1338   for(i = 0; i < cnt; i++) {
1339     int start = ovector[i*2];
1340     int end = ovector[i*2+1];
1341     lua_pushlstring(L, subject+pgi->offset+start, end-start);
1342   }
1343   pgi->offset += ovector[1]; /* endof the overall match */
1344   return cnt+1;
1345 }
1346 static int
1347 nl_pcre(lua_State *L) {
1348   pcre *re;
1349   struct pcre_global_info *pgi;
1350   const char *expr;
1351   const char *errstr;
1352   int erroff;
1353
1354   expr = lua_tostring(L,1);
1355   re = pcre_compile(expr, 0, &errstr, &erroff, NULL);
1356   if(!re) {
1357     lua_pushnil(L);
1358     lua_pushstring(L, errstr);
1359     lua_pushinteger(L, erroff);
1360     return 3;
1361   }
1362   pgi = (struct pcre_global_info *)lua_newuserdata(L, sizeof(*pgi));
1363   pgi->re = re;
1364   pgi->offset = 0;
1365   luaL_getmetatable(L, "noit.pcre");
1366   lua_setmetatable(L, -2);
1367   lua_pushcclosure(L, noit_lua_pcre_match, 1);
1368   return 1;
1369 }
1370 static int
1371 noit_lua_pcre_gc(lua_State *L) {
1372   struct pcre_global_info *pgi;
1373   pgi = (struct pcre_global_info *)lua_touserdata(L,1);
1374   pcre_free(pgi->re);
1375   return 0;
1376 }
1377
1378 static int
1379 nl_conf_get_string(lua_State *L) {
1380   char *val;
1381   const char *path = lua_tostring(L,1);
1382   if(path &&
1383      noit_conf_get_string(NULL, path, &val)) {
1384     lua_pushstring(L,val);
1385     free(val);
1386   }
1387   else lua_pushnil(L);
1388   return 1;
1389 }
1390 static int
1391 nl_conf_get_integer(lua_State *L) {
1392   int val;
1393   const char *path = lua_tostring(L,1);
1394   if(path &&
1395      noit_conf_get_int(NULL, path, &val)) {
1396     lua_pushinteger(L,val);
1397   }
1398   else lua_pushnil(L);
1399   return 1;
1400 }
1401 static int
1402 nl_conf_get_boolean(lua_State *L) {
1403   noit_boolean val;
1404   const char *path = lua_tostring(L,1);
1405   if(path &&
1406      noit_conf_get_boolean(NULL, path, &val)) {
1407     lua_pushboolean(L,val);
1408   }
1409   else lua_pushnil(L);
1410   return 1;
1411 }
1412 static int
1413 nl_conf_get_float(lua_State *L) {
1414   float val;
1415   const char *path = lua_tostring(L,1);
1416   if(path &&
1417      noit_conf_get_float(NULL, path, &val)) {
1418     lua_pushnumber(L,val);
1419   }
1420   else lua_pushnil(L);
1421   return 1;
1422 }
1423 struct xpath_iter {
1424   xmlXPathContextPtr ctxt;
1425   xmlXPathObjectPtr pobj;
1426   int cnt;
1427   int idx;
1428 };
1429 static int
1430 noit_lua_xpath_iter(lua_State *L) {
1431   struct xpath_iter *xpi;
1432   xpi = lua_touserdata(L, lua_upvalueindex(1));
1433   if(xpi->pobj) {
1434     if(xpi->idx < xpi->cnt) {
1435       xmlNodePtr node, *nodeptr;
1436       node = xmlXPathNodeSetItem(xpi->pobj->nodesetval, xpi->idx);
1437       xpi->idx++;
1438       nodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(node));
1439       *nodeptr = node;
1440       luaL_getmetatable(L, "noit.xmlnode");
1441       lua_setmetatable(L, -2);
1442       return 1;
1443     }
1444   }
1445   return 0;
1446 }
1447 static int
1448 noit_lua_xpath(lua_State *L) {
1449   int n;
1450   const char *xpathexpr;
1451   xmlDocPtr *docptr, doc;
1452   xmlNodePtr *nodeptr = NULL;
1453   xmlXPathContextPtr ctxt;
1454   struct xpath_iter *xpi;
1455
1456   n = lua_gettop(L);
1457   /* the first arg is implicitly self (it's a method) */
1458   docptr = lua_touserdata(L, lua_upvalueindex(1));
1459   if(docptr != lua_touserdata(L, 1))
1460     luaL_error(L, "must be called as method");
1461   if(n < 2 || n > 3) luaL_error(L, "expects 1 or 2 arguments, got %d", n);
1462   doc = *docptr;
1463   xpathexpr = lua_tostring(L, 2);
1464   if(!xpathexpr) luaL_error(L, "no xpath expression provided");
1465   ctxt = xmlXPathNewContext(doc);
1466   if(n == 3) {
1467     nodeptr = lua_touserdata(L, 3);
1468     if(nodeptr) ctxt->node = *nodeptr;
1469   }
1470   if(!ctxt) luaL_error(L, "invalid xpath");
1471
1472   xpi = (struct xpath_iter *)lua_newuserdata(L, sizeof(*xpi));
1473   xpi->ctxt = ctxt;
1474   xpi->pobj = xmlXPathEval((xmlChar *)xpathexpr, xpi->ctxt);
1475   if(!xpi->pobj || xpi->pobj->type != XPATH_NODESET)
1476     xpi->cnt = 0;
1477   else
1478     xpi->cnt = xmlXPathNodeSetGetLength(xpi->pobj->nodesetval);
1479   xpi->idx = 0;
1480   luaL_getmetatable(L, "noit.xpathiter");
1481   lua_setmetatable(L, -2);
1482   lua_pushcclosure(L, noit_lua_xpath_iter, 1);
1483   return 1;
1484 }
1485 static int
1486 noit_lua_xmlnode_name(lua_State *L) {
1487   xmlNodePtr *nodeptr;
1488   /* the first arg is implicitly self (it's a method) */
1489   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1490   if(nodeptr != lua_touserdata(L, 1))
1491     luaL_error(L, "must be called as method");
1492   if(lua_gettop(L) == 1) {
1493     xmlChar *v;
1494     v = (xmlChar *)(*nodeptr)->name;
1495     if(v) {
1496       lua_pushstring(L, (const char *)v);
1497     }
1498     else lua_pushnil(L);
1499     return 1;
1500   }
1501   luaL_error(L,"must be called with no arguments");
1502   return 0;
1503 }
1504 static int
1505 noit_lua_xmlnode_attr(lua_State *L) {
1506   xmlNodePtr *nodeptr;
1507   /* the first arg is implicitly self (it's a method) */
1508   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1509   if(nodeptr != lua_touserdata(L, 1))
1510     luaL_error(L, "must be called as method");
1511   if(lua_gettop(L) == 3 && lua_isstring(L,2)) {
1512     const char *attr = lua_tostring(L,2);
1513     if(lua_isnil(L,3))
1514       xmlSetProp(*nodeptr, (xmlChar *)attr, NULL);
1515     else
1516       xmlSetProp(*nodeptr, (xmlChar *)attr, (xmlChar *)lua_tostring(L,3));
1517     return 0;
1518   }
1519   if(lua_gettop(L) == 2 && lua_isstring(L,2)) {
1520     xmlChar *v;
1521     const char *attr = lua_tostring(L,2);
1522     v = xmlGetProp(*nodeptr, (xmlChar *)attr);
1523     if(v) {
1524       lua_pushstring(L, (const char *)v);
1525       xmlFree(v);
1526     }
1527     else lua_pushnil(L);
1528     return 1;
1529   }
1530   luaL_error(L,"must be called with one argument");
1531   return 0;
1532 }
1533 static int
1534 noit_lua_xmlnode_contents(lua_State *L) {
1535   xmlNodePtr *nodeptr;
1536   /* the first arg is implicitly self (it's a method) */
1537   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1538   if(nodeptr != lua_touserdata(L, 1))
1539     luaL_error(L, "must be called as method");
1540   if(lua_gettop(L) == 2 && lua_isstring(L,2)) {
1541     const char *data = lua_tostring(L,2);
1542     xmlChar *enc = xmlEncodeEntitiesReentrant((*nodeptr)->doc, (xmlChar *)data);
1543     xmlNodeSetContent(*nodeptr, (xmlChar *)enc);
1544     return 0;
1545   }
1546   if(lua_gettop(L) == 1) {
1547     xmlChar *v;
1548     v = xmlNodeGetContent(*nodeptr);
1549     if(v) {
1550       lua_pushstring(L, (const char *)v);
1551       xmlFree(v);
1552     }
1553     else lua_pushnil(L);
1554     return 1;
1555   }
1556   luaL_error(L,"must be called with no arguments");
1557   return 0;
1558 }
1559 static int
1560 noit_lua_xmlnode_next(lua_State *L) {
1561   xmlNodePtr *nodeptr;
1562   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1563   if(*nodeptr) {
1564     xmlNodePtr *newnodeptr;
1565     newnodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(*nodeptr));
1566     *newnodeptr = *nodeptr;
1567     luaL_getmetatable(L, "noit.xmlnode");
1568     lua_setmetatable(L, -2);
1569     *nodeptr = (*nodeptr)->next;
1570     return 1;
1571   }
1572   return 0;
1573 }
1574 static int
1575 noit_lua_xmlnode_addchild(lua_State *L) {
1576   xmlNodePtr *nodeptr;
1577   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1578   if(nodeptr != lua_touserdata(L, 1))
1579     luaL_error(L, "must be called as method");
1580   if(lua_gettop(L) == 2 && lua_isstring(L,2)) {
1581     xmlNodePtr *newnodeptr;
1582     newnodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(*nodeptr));
1583     *newnodeptr = xmlNewChild(*nodeptr, NULL,
1584                               (xmlChar *)lua_tostring(L,2), NULL);
1585     luaL_getmetatable(L, "noit.xmlnode");
1586     lua_setmetatable(L, -2);
1587     return 1;
1588   }
1589   luaL_error(L,"must be called with one argument");
1590   return 0;
1591 }
1592 static int
1593 noit_lua_xmlnode_children(lua_State *L) {
1594   xmlNodePtr *nodeptr, node, cnode;
1595   /* the first arg is implicitly self (it's a method) */
1596   nodeptr = lua_touserdata(L, lua_upvalueindex(1));
1597   if(nodeptr != lua_touserdata(L, 1))
1598     luaL_error(L, "must be called as method");
1599   node = *nodeptr;
1600   cnode = node->children;
1601   nodeptr = lua_newuserdata(L, sizeof(cnode));
1602   *nodeptr = cnode;
1603   luaL_getmetatable(L, "noit.xmlnode");
1604   lua_setmetatable(L, -2);
1605   lua_pushcclosure(L, noit_lua_xmlnode_next, 1);
1606   return 1;
1607 }
1608 static int
1609 noit_lua_xml_tostring(lua_State *L) {
1610   int n;
1611   xmlDocPtr *docptr;
1612   char *xmlstring;
1613   n = lua_gettop(L);
1614   /* the first arg is implicitly self (it's a method) */
1615   docptr = lua_touserdata(L, lua_upvalueindex(1));
1616   if(docptr != lua_touserdata(L, 1))
1617     luaL_error(L, "must be called as method");
1618   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1619   xmlstring = noit_xmlSaveToBuffer(*docptr);
1620   lua_pushstring(L, xmlstring);
1621   free(xmlstring);
1622   return 1;
1623 }
1624 static int
1625 noit_lua_xml_docroot(lua_State *L) {
1626   int n;
1627   xmlDocPtr *docptr;
1628   xmlNodePtr *ptr;
1629   n = lua_gettop(L);
1630   /* the first arg is implicitly self (it's a method) */
1631   docptr = lua_touserdata(L, lua_upvalueindex(1));
1632   if(docptr != lua_touserdata(L, 1))
1633     luaL_error(L, "must be called as method");
1634   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1635   ptr = lua_newuserdata(L, sizeof(*ptr));
1636   *ptr = xmlDocGetRootElement(*docptr);
1637   luaL_getmetatable(L, "noit.xmlnode");
1638   lua_setmetatable(L, -2);
1639   return 1;
1640 }
1641 static int
1642 noit_lua_xpathiter_gc(lua_State *L) {
1643   struct xpath_iter *xpi;
1644   xpi = lua_touserdata(L, 1);
1645   xmlXPathFreeContext(xpi->ctxt);
1646   if(xpi->pobj) xmlXPathFreeObject(xpi->pobj);
1647   return 0;
1648 }
1649 static int
1650 noit_xmlnode_index_func(lua_State *L) {
1651   int n;
1652   const char *k;
1653   xmlNodePtr *udata;
1654   n = lua_gettop(L); /* number of arguments */
1655   assert(n == 2);
1656   if(!luaL_checkudata(L, 1, "noit.xmlnode")) {
1657     luaL_error(L, "metatable error, arg1 not a noit.xmlnode!");
1658   }
1659   udata = lua_touserdata(L, 1);
1660   if(!lua_isstring(L, 2)) {
1661     luaL_error(L, "metatable error, arg2 not a string!");
1662   }
1663   k = lua_tostring(L, 2);
1664   switch(*k) {
1665     case 'a':
1666       LUA_DISPATCH(attr, noit_lua_xmlnode_attr);
1667       LUA_DISPATCH(attribute, noit_lua_xmlnode_attr);
1668       LUA_DISPATCH(addchild, noit_lua_xmlnode_addchild);
1669       break;
1670     case 'c':
1671       LUA_DISPATCH(children, noit_lua_xmlnode_children);
1672       LUA_DISPATCH(contents, noit_lua_xmlnode_contents);
1673       break;
1674     case 'n':
1675       LUA_DISPATCH(name, noit_lua_xmlnode_name);
1676       break;
1677     default:
1678       break;
1679   }
1680   luaL_error(L, "noit.xmlnode no such element: %s", k);
1681   return 0;
1682 }
1683 static int
1684 nl_parsexml(lua_State *L) {
1685   xmlDocPtr *docptr, doc;
1686   const char *in;
1687   size_t inlen;
1688
1689   if(lua_gettop(L) != 1) luaL_error(L, "parsexml requires one argument");
1690
1691   in = lua_tolstring(L, 1, &inlen);
1692   doc = xmlParseMemory(in, inlen);
1693   if(!doc) {
1694     lua_pushnil(L);
1695     return 1;
1696   }
1697
1698   docptr = (xmlDocPtr *)lua_newuserdata(L, sizeof(doc));
1699   *docptr = doc;
1700   luaL_getmetatable(L, "noit.xmldoc");
1701   lua_setmetatable(L, -2);
1702   return 1;
1703 }
1704 static int
1705 noit_lua_xmldoc_gc(lua_State *L) {
1706   xmlDocPtr *holder;
1707   holder = (xmlDocPtr *)lua_touserdata(L,1);
1708   xmlFreeDoc(*holder);
1709   return 0;
1710 }
1711 static int
1712 noit_xmldoc_index_func(lua_State *L) {
1713   int n;
1714   const char *k;
1715   xmlDocPtr *udata;
1716   n = lua_gettop(L); /* number of arguments */
1717   assert(n == 2);
1718   if(!luaL_checkudata(L, 1, "noit.xmldoc")) {
1719     luaL_error(L, "metatable error, arg1 not a noit.xmldoc!");
1720   }
1721   udata = lua_touserdata(L, 1);
1722   if(!lua_isstring(L, 2)) {
1723     luaL_error(L, "metatable error, arg2 not a string!");
1724   }
1725   k = lua_tostring(L, 2);
1726   switch(*k) {
1727     case 'r':
1728      LUA_DISPATCH(root, noit_lua_xml_docroot);
1729      break;
1730     case 't':
1731      LUA_DISPATCH(tostring, noit_lua_xml_tostring);
1732      break;
1733     case 'x':
1734      LUA_DISPATCH(xpath, noit_lua_xpath);
1735      break;
1736     default:
1737      break;
1738   }
1739   luaL_error(L, "noit.xmldoc no such element: %s", k);
1740   return 0;
1741 }
1742
1743 static int
1744 noit_lua_json_tostring(lua_State *L) {
1745   int n;
1746   json_crutch **docptr;
1747   const char *jsonstring;
1748   n = lua_gettop(L);
1749   /* the first arg is implicitly self (it's a method) */
1750   docptr = lua_touserdata(L, lua_upvalueindex(1));
1751   if(docptr != lua_touserdata(L, 1))
1752     luaL_error(L, "must be called as method");
1753   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1754   jsonstring = json_object_to_json_string((*docptr)->root);
1755   lua_pushstring(L, jsonstring);
1756   /* jsonstring is freed with the root object later */
1757   return 1;
1758 }
1759 static int
1760 noit_json_object_to_luatype(lua_State *L, struct json_object *o) {
1761   if(!o) {
1762     lua_pushnil(L);
1763     return 1;
1764   }
1765   switch(json_object_get_type(o)) {
1766     case json_type_null: lua_pushnil(L); break;
1767     case json_type_object:
1768     {
1769       struct lh_table *lh;
1770       struct lh_entry *el;
1771       lh = json_object_get_object(o);
1772       lua_createtable(L, 0, lh->count);
1773       lh_foreach(lh, el) {
1774         noit_json_object_to_luatype(L, (struct json_object *)el->v);
1775         lua_setfield(L, -2, el->k);
1776       }
1777       break;
1778     }
1779     case json_type_string: lua_pushstring(L, json_object_get_string(o)); break;
1780     case json_type_boolean: lua_pushboolean(L, json_object_get_boolean(o)); break;
1781     case json_type_double: lua_pushnumber(L, json_object_get_double(o)); break;
1782     case json_type_int:
1783     {
1784       int64_t i64;
1785       uint64_t u64;
1786       char istr[64];
1787       switch(json_object_get_int_overflow(o)) {
1788         case json_overflow_int:
1789           lua_pushnumber(L, json_object_get_int(o)); break;
1790         case json_overflow_int64:
1791           i64 = json_object_get_int64(o);
1792           snprintf(istr, sizeof(istr), "%lld", i64);
1793           lua_pushstring(L, istr);
1794           break;
1795         case json_overflow_uint64:
1796           u64 = json_object_get_uint64(o);
1797           snprintf(istr, sizeof(istr), "%llu", u64);
1798           lua_pushstring(L, istr);
1799           break;
1800       }
1801       break;
1802     }
1803     case json_type_array:
1804     {
1805       int i, cnt;
1806       struct array_list *al;
1807       al = json_object_get_array(o);
1808       cnt = al ? array_list_length(al) : 0;
1809       lua_createtable(L, 0, cnt);
1810       for(i=0;i<cnt;i++) {
1811         noit_json_object_to_luatype(L, (struct json_object *)array_list_get_idx(al, i));
1812         lua_rawseti(L, -2, i);
1813       }
1814       break;
1815     }
1816   }
1817   return 1;
1818 }
1819 static int
1820 noit_lua_json_document(lua_State *L) {
1821   int n;
1822   json_crutch **docptr;
1823   n = lua_gettop(L);
1824   /* the first arg is implicitly self (it's a method) */
1825   docptr = lua_touserdata(L, lua_upvalueindex(1));
1826   if(docptr != lua_touserdata(L, 1))
1827     luaL_error(L, "must be called as method");
1828   if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1);
1829   return noit_json_object_to_luatype(L, (*docptr)->root);
1830 }
1831 static int
1832 nl_parsejson(lua_State *L) {
1833   json_crutch **docptr, *doc;
1834   const char *in;
1835   size_t inlen;
1836
1837   if(lua_gettop(L) != 1) luaL_error(L, "parsejson requires one argument");
1838
1839   in = lua_tolstring(L, 1, &inlen);
1840   doc = calloc(1, sizeof(*doc));
1841   doc->tok = json_tokener_new();
1842   doc->root = json_tokener_parse_ex(doc->tok, in, inlen);
1843   if(is_error(doc->root)) {
1844     json_tokener_free(doc->tok);
1845     if(doc->root) json_object_put(doc->root);
1846     free(doc);
1847     lua_pushnil(L);
1848     return 1;
1849   }
1850
1851   docptr = (json_crutch **)lua_newuserdata(L, sizeof(doc));
1852   *docptr = doc;
1853   luaL_getmetatable(L, "noit.json");
1854   lua_setmetatable(L, -2);
1855   return 1;
1856 }
1857 static int
1858 noit_lua_json_gc(lua_State *L) {
1859   json_crutch **json;
1860   json = (json_crutch **)lua_touserdata(L,1);
1861   if((*json)->tok) json_tokener_free((*json)->tok);
1862   if((*json)->root) json_object_put((*json)->root);
1863   free(*json);
1864   return 0;
1865 }
1866 static int
1867 noit_json_index_func(lua_State *L) {
1868   int n;
1869   const char *k;
1870   json_crutch **udata;
1871   n = lua_gettop(L); /* number of arguments */
1872   assert(n == 2);
1873   if(!luaL_checkudata(L, 1, "noit.json")) {
1874     luaL_error(L, "metatable error, arg1 not a noit.json!");
1875   }
1876   udata = lua_touserdata(L, 1);
1877   if(!lua_isstring(L, 2)) {
1878     luaL_error(L, "metatable error, arg2 not a string!");
1879   }
1880   k = lua_tostring(L, 2);
1881   switch(*k) {
1882     case 'd':
1883      LUA_DISPATCH(document, noit_lua_json_document);
1884      break;
1885     case 't':
1886      LUA_DISPATCH(tostring, noit_lua_json_tostring);
1887      break;
1888     default:
1889      break;
1890   }
1891   luaL_error(L, "noit.json no such element: %s", k);
1892   return 0;
1893 }
1894 static const luaL_Reg noitlib[] = {
1895   { "sleep", nl_sleep },
1896   { "gettimeofday", nl_gettimeofday },
1897   { "socket", nl_socket },
1898   { "dns", nl_dns_lookup },
1899   { "log", nl_log },
1900   { "crc32", nl_crc32 },
1901   { "base32_decode", nl_base32_decode },
1902   { "base32_encode", nl_base32_encode },
1903   { "base64_decode", nl_base64_decode },
1904   { "base64_encode", nl_base64_encode },
1905   { "md5_hex", nl_md5_hex },
1906   { "pcre", nl_pcre },
1907   { "gunzip", nl_gunzip },
1908   { "conf_get", nl_conf_get_string },
1909   { "conf_get_string", nl_conf_get_string },
1910   { "conf_get_integer", nl_conf_get_integer },
1911   { "conf_get_boolean", nl_conf_get_boolean },
1912   { "conf_get_number", nl_conf_get_float },
1913   { "parsexml", nl_parsexml },
1914   { "parsejson", nl_parsejson },
1915   { NULL, NULL }
1916 };
1917
1918 int luaopen_noit(lua_State *L) {
1919   luaL_newmetatable(L, "noit.eventer");
1920   lua_pushcclosure(L, noit_eventer_index_func, 0);
1921   lua_setfield(L, -2, "__index");
1922
1923   luaL_newmetatable(L, "noit.eventer.ssl_ctx");
1924   lua_pushcclosure(L, noit_ssl_ctx_index_func, 0);
1925   lua_setfield(L, -2, "__index");
1926
1927   luaL_newmetatable(L, "noit.dns");
1928   lua_pushcfunction(L, noit_lua_dns_gc);
1929   lua_setfield(L, -2, "__gc");
1930   luaL_newmetatable(L, "noit.dns");
1931   lua_pushcfunction(L, noit_lua_dns_index_func);
1932   lua_setfield(L, -2, "__index");
1933
1934   luaL_newmetatable(L, "noit.gunzip");
1935   lua_pushcfunction(L, noit_lua_gunzip_gc);
1936   lua_setfield(L, -2, "__gc");
1937
1938   luaL_newmetatable(L, "noit.pcre");
1939   lua_pushcfunction(L, noit_lua_pcre_gc);
1940   lua_setfield(L, -2, "__gc");
1941
1942   luaL_newmetatable(L, "noit.json");
1943   lua_pushcfunction(L, noit_lua_json_gc);
1944   lua_setfield(L, -2, "__gc");
1945   luaL_newmetatable(L, "noit.json");
1946   lua_pushcclosure(L, noit_json_index_func, 0);
1947   lua_setfield(L, -2, "__index");
1948
1949   luaL_newmetatable(L, "noit.xmldoc");
1950   lua_pushcfunction(L, noit_lua_xmldoc_gc);
1951   lua_setfield(L, -2, "__gc");
1952   luaL_newmetatable(L, "noit.xmldoc");
1953   lua_pushcclosure(L, noit_xmldoc_index_func, 0);
1954   lua_setfield(L, -2, "__index");
1955
1956   luaL_newmetatable(L, "noit.xmlnode");
1957   lua_pushcclosure(L, noit_xmlnode_index_func, 0);
1958   lua_setfield(L, -2, "__index");
1959
1960   luaL_newmetatable(L, "noit.xpathiter");
1961   lua_pushcfunction(L, noit_lua_xpathiter_gc);
1962   lua_setfield(L, -2, "__gc");
1963
1964   luaL_register(L, "noit", noitlib);
1965   return 0;
1966 }
1967
1968 void noit_lua_init() {
1969   eventer_name_callback("lua/sleep", nl_sleep_complete);
1970   eventer_name_callback("lua/socket_read",
1971                         noit_lua_socket_read_complete);
1972   eventer_name_callback("lua/socket_write",
1973                         noit_lua_socket_write_complete);
1974   eventer_name_callback("lua/socket_send",
1975                         noit_lua_socket_send_complete);
1976   eventer_name_callback("lua/socket_connect",
1977                         noit_lua_socket_connect_complete);
1978   eventer_name_callback("lua/ssl_upgrade", noit_lua_ssl_upgrade);
1979   noit_lua_init_dns();
1980 }
Note: See TracBrowser for help on using the browser.