root/src/modules/lua_noit.c

Revision 6472d772d6de63a64379d00f69533dd377597142, 59.7 kB (checked in by Phoebe Simon <phoebe.simon@rackspace.com>, 2 years ago)

lua_noit.c: Included check to ensure that addition does not overflow and the individual values are positive

Otherwise, could have resulted in remote execution or potential denial of service due to a server crash

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