root/src/modules/lua_noit.c

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

Updated SSL connection to correct use the header_Host field to compare to the CN and SANs in the SSL certificates to verify that they match

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