root/src/modules/lua_noit.c

Revision 50525e499873f7998d760f0e7601eb24f65625ff, 53.8 kB (checked in by Philip Maddox <pmaddox@circonus.com>, 2 years ago)

Added function to lua_noit to perform HMAC-SHA1 encoding

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