root/src/modules/lua_noit.c

Revision d814e6a85d60c4fcbee542f4a47d07b9526866af, 20.3 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 5 years ago)

learn lua better and add a streaming gunzip implementation that auto garbage collects

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, 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 "noit_conf.h"
36 #include "noit_module.h"
37 #include "noit_check.h"
38 #include "noit_check_tools.h"
39 #include "utils/noit_log.h"
40 #include "utils/noit_str.h"
41 #include "eventer/eventer.h"
42 #include "lua_noit.h"
43
44 #include <assert.h>
45 #include <math.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
52 #endif
53 #include <zlib.h>
54
55 #define DEFLATE_CHUNK_SIZE 32768
56
57 static void
58 nl_extended_free(void *vcl) {
59   struct nl_slcl *cl = vcl;
60   if(cl->inbuff) free(cl->inbuff);
61   free(cl);
62 }
63 static void
64 inbuff_addlstring(struct nl_slcl *cl, const char *b, int l) {
65   int newsize = 0;
66   char *newbuf;
67   if(cl->inbuff_len + l > cl->inbuff_allocd)
68     newsize = cl->inbuff_len + l;
69   if(newsize) {
70     newbuf = cl->inbuff_allocd ? realloc(cl->inbuff, newsize) : malloc(newsize);
71     assert(newbuf);
72     cl->inbuff = newbuf;
73     cl->inbuff_allocd = newsize;
74   }
75   memcpy(cl->inbuff + cl->inbuff_len, b, l);
76   cl->inbuff_len += l;
77 }
78
79 static int
80 noit_lua_socket_connect_complete(eventer_t e, int mask, void *vcl,
81                                  struct timeval *now) {
82   noit_lua_check_info_t *ci;
83   struct nl_slcl *cl = vcl;
84   int args = 0, aerrno;
85   socklen_t aerrno_len = sizeof(aerrno);
86
87   ci = get_ci(cl->L);
88   assert(ci);
89   noit_lua_check_deregister_event(ci, e, 0);
90
91   *(cl->eptr) = eventer_alloc();
92   memcpy(*cl->eptr, e, sizeof(*e));
93   noit_lua_check_register_event(ci, *cl->eptr);
94
95   if(getsockopt(e->fd,SOL_SOCKET,SO_ERROR, &aerrno, &aerrno_len) == 0)
96     if(aerrno != 0) goto connerr;
97
98   if(!(mask & EVENTER_EXCEPTION) &&
99      mask & EVENTER_WRITE) {
100     /* Connect completed successfully */
101     lua_pushinteger(cl->L, 0);
102     args = 1;
103   }
104   else {
105     aerrno = errno;
106    connerr:
107     lua_pushinteger(cl->L, -1);
108     lua_pushstring(cl->L, strerror(aerrno));
109     args = 2;
110   }
111   noit_lua_resume(ci, args);
112   return 0;
113 }
114 static int
115 noit_lua_socket_connect(lua_State *L) {
116   noit_lua_check_info_t *ci;
117   eventer_t e, *eptr;
118   const char *target;
119   unsigned short port;
120   int8_t family;
121   int rv;
122   union {
123     struct sockaddr_in sin4;
124     struct sockaddr_in6 sin6;
125   } a;
126
127   ci = get_ci(L);
128   assert(ci);
129
130   eptr = lua_touserdata(L, lua_upvalueindex(1));
131   if(eptr != lua_touserdata(L, 1))
132     luaL_error(L, "must be called as method");
133   e = *eptr;
134   target = lua_tostring(L, 2);
135   port = lua_tointeger(L, 3);
136
137   family = AF_INET;
138   rv = inet_pton(family, target, &a.sin4.sin_addr);
139   if(rv != 1) {
140     family = AF_INET6;
141     rv = inet_pton(family, target, &a.sin6.sin6_addr);
142     if(rv != 1) {
143       noitL(noit_stderr, "Cannot translate '%s' to IP\n", target);
144       memset(&a, 0, sizeof(a));
145       lua_pushinteger(L, -1);
146       lua_pushfstring(L, "Cannot translate '%s' to IP\n", target);
147       return 2;
148     }
149     else {
150       /* We've IPv6 */
151       a.sin6.sin6_family = AF_INET6;
152       a.sin6.sin6_port = htons(port);
153     }
154   }
155   else {
156     a.sin4.sin_family = family;
157     a.sin4.sin_port = htons(port);
158   }
159
160   rv = connect(e->fd, (struct sockaddr *)&a,
161                family==AF_INET ? sizeof(a.sin4) : sizeof(a.sin6));
162   if(rv == 0) {
163     lua_pushinteger(L, 0);
164     return 1;
165   }
166   if(rv == -1 && errno == EINPROGRESS) {
167     /* Need completion */
168     e->callback = noit_lua_socket_connect_complete;
169     e->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
170     eventer_add(e);
171     return noit_lua_yield(ci, 0);
172   }
173   lua_pushinteger(L, -1);
174   lua_pushstring(L, strerror(errno));
175   return 2;
176 }
177 static int
178 noit_lua_ssl_upgrade(eventer_t e, int mask, void *vcl,
179                      struct timeval *now) {
180   noit_lua_check_info_t *ci;
181   struct nl_slcl *cl = vcl;
182   int rv;
183  
184   rv = eventer_SSL_connect(e, &mask);
185   if(rv <= 0 && errno == EAGAIN) return mask | EVENTER_EXCEPTION;
186
187   ci = get_ci(cl->L);
188   assert(ci);
189   noit_lua_check_deregister_event(ci, e, 0);
190  
191   *(cl->eptr) = eventer_alloc();
192   memcpy(*cl->eptr, e, sizeof(*e));
193   noit_lua_check_register_event(ci, *cl->eptr);
194
195   /* Upgrade completed successfully */
196   lua_pushinteger(cl->L, (rv > 0) ? 0 : -1);
197   noit_lua_resume(ci, 1);
198   return 0;
199 }
200 static int
201 noit_lua_socket_connect_ssl(lua_State *L) {
202   const char *ca, *ciphers, *cert, *key;
203   eventer_ssl_ctx_t *sslctx;
204   noit_lua_check_info_t *ci;
205   eventer_t e, *eptr;
206   struct timeval now;
207
208   ci = get_ci(L);
209   assert(ci);
210
211   eptr = lua_touserdata(L, lua_upvalueindex(1));
212   if(eptr != lua_touserdata(L, 1))
213     luaL_error(L, "must be called as method");
214   e = *eptr;
215   ca = lua_tostring(L, 2);
216   ciphers = lua_tostring(L, 3);
217   cert = lua_tostring(L, 4);
218   key = lua_tostring(L, 5);
219
220   sslctx = eventer_ssl_ctx_new(SSL_CLIENT, cert, key, ca, ciphers);
221   if(!sslctx) {
222     lua_pushinteger(L, -1);
223     return 1;
224   }
225
226   eventer_ssl_ctx_set_verify(sslctx, eventer_ssl_verify_cert, NULL);
227   EVENTER_ATTACH_SSL(e, sslctx);
228   e->callback = noit_lua_ssl_upgrade;
229   gettimeofday(&now, NULL);
230   e->mask = e->callback(e, EVENTER_READ|EVENTER_WRITE, e->closure, &now);
231   if(e->mask & (EVENTER_READ|EVENTER_WRITE)) {
232     /* Need completion */
233     eventer_add(e);
234     return noit_lua_yield(ci, 0);
235   }
236   lua_pushinteger(L, 0);
237   return 1;
238 }
239
240 static int
241 noit_lua_socket_read_complete(eventer_t e, int mask, void *vcl,
242                               struct timeval *now) {
243   char buff[4096];
244   noit_lua_check_info_t *ci;
245   struct nl_slcl *cl = vcl;
246   int len;
247   int args = 0;
248
249   ci = get_ci(cl->L);
250   assert(ci);
251
252   if(mask & EVENTER_EXCEPTION) {
253     lua_pushnil(cl->L);
254     args = 1;
255     goto alldone;
256   }
257
258   while((len = e->opset->read(e->fd, buff, sizeof(buff), &mask, e)) > 0) {
259     if(cl->read_goal) {
260       int remaining = cl->read_goal - cl->read_sofar;
261       /* copy up to the goal into the inbuff */
262       inbuff_addlstring(cl, buff, MIN(len, remaining));
263       cl->read_sofar += len;
264       if(cl->read_sofar >= cl->read_goal) { /* We're done */
265         lua_pushlstring(cl->L, cl->inbuff, cl->read_goal);
266         args = 1;
267         cl->read_sofar -= cl->read_goal;
268         if(cl->read_sofar > 0) {  /* We have to buffer this for next read */
269           cl->inbuff_len = 0;
270           inbuff_addlstring(cl, buff + remaining, cl->read_sofar);
271         }
272         break;
273       }
274     }
275     else if(cl->read_terminator) {
276       const char *cp;
277       int remaining = len;
278       cp = strnstrn(cl->read_terminator, strlen(cl->read_terminator),
279                     buff, len);
280       if(cp) remaining = cp - buff + strlen(cl->read_terminator);
281       inbuff_addlstring(cl, buff, MIN(len, remaining));
282       cl->read_sofar += len;
283       if(cp) {
284         lua_pushlstring(cl->L, cl->inbuff, cl->inbuff_len);
285         args = 1;
286        
287         cl->read_sofar = len - remaining;
288         cl->inbuff_len = 0;
289         if(cl->read_sofar > 0) { /* We have to buffer this for next read */
290           inbuff_addlstring(cl, buff + remaining, cl->read_sofar);
291         }
292         break;
293       }
294     }
295   }
296   if(len >= 0) {
297     /* We broke out, cause we read enough... */
298   }
299   else if(len == -1 && errno == EAGAIN) {
300     return mask | EVENTER_EXCEPTION;
301   }
302   else {
303     lua_pushnil(cl->L);
304     args = 1;
305   }
306  alldone:
307   eventer_remove_fd(e->fd);
308   noit_lua_check_deregister_event(ci, e, 0);
309   *(cl->eptr) = eventer_alloc();
310   memcpy(*cl->eptr, e, sizeof(*e));
311   noit_lua_check_register_event(ci, *cl->eptr);
312   noit_lua_resume(ci, args);
313   return 0;
314 }
315
316 static int
317 noit_lua_socket_read(lua_State *L) {
318   struct nl_slcl *cl;
319   noit_lua_check_info_t *ci;
320   eventer_t e, *eptr;
321
322   ci = get_ci(L);
323   assert(ci);
324
325   eptr = lua_touserdata(L, lua_upvalueindex(1));
326   if(eptr != lua_touserdata(L, 1))
327     luaL_error(L, "must be called as method");
328   e = *eptr;
329   cl = e->closure;
330   cl->read_goal = 0;
331   cl->read_terminator = NULL;
332
333   if(lua_isnumber(L, 2)) {
334     cl->read_goal = lua_tointeger(L, 2);
335     if(cl->read_goal <= cl->read_sofar) {
336       int base;
337      i_know_better:
338       base = lua_gettop(L);
339       /* We have enough, we can service this right here */
340       lua_pushlstring(L, cl->inbuff, cl->read_goal);
341       cl->read_sofar -= cl->read_goal;
342       if(cl->read_sofar) {
343         memmove(cl->inbuff, cl->inbuff + cl->read_goal, cl->read_sofar);
344       }
345       cl->inbuff_len = cl->read_sofar;
346       return 1;
347     }
348   }
349   else {
350     cl->read_terminator = lua_tostring(L, 2);
351     if(cl->read_sofar) {
352       const char *cp;
353       /* Ugh... inernalism */
354       cp = strnstrn(cl->read_terminator, strlen(cl->read_terminator),
355                     cl->inbuff, cl->read_sofar);
356       if(cp) {
357         /* Here we matched... and we _know_ that someone actually wants:
358          * strlen(cl->read_terminator) + cp - cl->inbuff.buffer bytes...
359          * give it to them.
360          */
361         cl->read_goal = strlen(cl->read_terminator) + cp - cl->inbuff;
362         cl->read_terminator = NULL;
363         assert(cl->read_goal <= cl->read_sofar);
364         goto i_know_better;
365       }
366     }
367   }
368
369   e->callback = noit_lua_socket_read_complete;
370   e->mask = EVENTER_READ | EVENTER_EXCEPTION;
371   eventer_add(e);
372   return noit_lua_yield(ci, 0);
373 }
374 static int
375 noit_lua_socket_write_complete(eventer_t e, int mask, void *vcl,
376                                struct timeval *now) {
377   noit_lua_check_info_t *ci;
378   struct nl_slcl *cl = vcl;
379   int rv;
380   int args = 0;
381
382   ci = get_ci(cl->L);
383   assert(ci);
384
385   if(mask & EVENTER_EXCEPTION) {
386     lua_pushinteger(cl->L, -1);
387     args = 1;
388     goto alldone;
389   }
390   while((rv = e->opset->write(e->fd,
391                               cl->outbuff + cl->write_sofar,
392                               MIN(cl->send_size, cl->write_goal),
393                               &mask, e)) > 0) {
394     cl->write_sofar += rv;
395     assert(cl->write_sofar <= cl->write_goal);
396     if(cl->write_sofar == cl->write_goal) break;
397   }
398   if(rv > 0) {
399     lua_pushinteger(cl->L, cl->write_goal);
400     args = 1;
401   }
402   else if(rv == -1 && errno == EAGAIN) {
403     return mask | EVENTER_EXCEPTION;
404   }
405   else {
406     lua_pushinteger(cl->L, -1);
407     args = 1;
408     if(rv == -1) {
409       lua_pushstring(cl->L, strerror(errno));
410       args++;
411     }
412   }
413
414  alldone:
415   eventer_remove_fd(e->fd);
416   noit_lua_check_deregister_event(ci, e, 0);
417   *(cl->eptr) = eventer_alloc();
418   memcpy(*cl->eptr, e, sizeof(*e));
419   noit_lua_check_register_event(ci, *cl->eptr);
420   noit_lua_resume(ci, args);
421   return 0;
422 }
423 static int
424 noit_lua_socket_write(lua_State *L) {
425   int rv, mask;
426   struct nl_slcl *cl;
427   noit_lua_check_info_t *ci;
428   eventer_t e, *eptr;
429
430   ci = get_ci(L);
431   assert(ci);
432
433   eptr = lua_touserdata(L, lua_upvalueindex(1));
434   if(eptr != lua_touserdata(L, 1))
435     luaL_error(L, "must be called as method");
436   e = *eptr;
437   cl = e->closure;
438   cl->write_sofar = 0;
439   cl->outbuff = lua_tolstring(L, 2, &cl->write_goal);
440
441   while((rv = e->opset->write(e->fd,
442                               cl->outbuff + cl->write_sofar,
443                               MIN(cl->send_size, cl->write_goal),
444                               &mask, e)) > 0) {
445     cl->write_sofar += rv;
446     assert(cl->write_sofar <= cl->write_goal);
447     if(cl->write_sofar == cl->write_goal) break;
448   }
449   if(rv > 0) {
450     lua_pushinteger(L, cl->write_goal);
451     return 1;
452   }
453   if(rv == -1 && errno == EAGAIN) {
454     e->callback = noit_lua_socket_write_complete;
455     e->mask = mask | EVENTER_EXCEPTION;
456     eventer_add(e);
457     return noit_lua_yield(ci, 0);
458   }
459   lua_pushinteger(L, -1);
460   return 1;
461 }
462 static int
463 noit_eventer_index_func(lua_State *L) {
464   int n;
465   const char *k;
466   eventer_t *udata, e;
467   n = lua_gettop(L); /* number of arguments */
468   assert(n == 2);
469   if(!luaL_checkudata(L, 1, "noit.eventer")) {
470     luaL_error(L, "metatable error, arg1 not a noit.eventer!");
471   }
472   udata = lua_touserdata(L, 1);
473   e = *udata;
474   if(!lua_isstring(L, 2)) {
475     luaL_error(L, "metatable error, arg2 not a string!");
476   }
477   k = lua_tostring(L, 2);
478   switch(*k) {
479     case 'c':
480      if(!strcmp(k, "connect")) {
481        lua_pushlightuserdata(L, udata);
482        lua_pushcclosure(L, noit_lua_socket_connect, 1);
483        return 1;
484      }
485      break;
486     case 'r':
487      if(!strcmp(k, "read")) {
488        lua_pushlightuserdata(L, udata);
489        lua_pushcclosure(L, noit_lua_socket_read, 1);
490        return 1;
491      }
492      break;
493     case 's':
494      if(!strcmp(k, "ssl_upgrade_socket")) {
495        lua_pushlightuserdata(L, udata);
496        lua_pushcclosure(L, noit_lua_socket_connect_ssl, 1);
497        return 1;
498      }
499      break;
500     case 'w':
501      if(!strcmp(k, "write")) {
502        lua_pushlightuserdata(L, udata);
503        lua_pushcclosure(L, noit_lua_socket_write, 1);
504        return 1;
505      }
506      break;
507     default:
508       break;
509   }
510   luaL_error(L, "eventer_t no such element: %s", k);
511   return 0;
512 }
513
514 static eventer_t *
515 noit_lua_event(lua_State *L, eventer_t e) {
516   eventer_t *addr;
517   addr = (eventer_t *)lua_newuserdata(L, sizeof(e));
518   *addr = e;
519   luaL_getmetatable(L, "noit.eventer");
520   lua_setmetatable(L, -2);
521   return addr;
522 }
523
524 static int
525 nl_sleep_complete(eventer_t e, int mask, void *vcl, struct timeval *now) {
526   noit_lua_check_info_t *ci;
527   struct nl_slcl *cl = vcl;
528   struct timeval diff;
529   double p_int;
530
531   ci = get_ci(cl->L);
532   assert(ci);
533   noit_lua_check_deregister_event(ci, e, 0);
534
535   sub_timeval(*now, cl->start, &diff);
536   p_int = diff.tv_sec + diff.tv_usec / 1000000.0;
537   lua_pushnumber(cl->L, p_int);
538   free(cl);
539   noit_lua_resume(ci, 1);
540   return 0;
541 }
542
543 static int
544 nl_sleep(lua_State *L) {
545   noit_lua_check_info_t *ci;
546   struct nl_slcl *cl;
547   struct timeval diff;
548   eventer_t e;
549   double p_int;
550
551   ci = get_ci(L);
552   assert(ci);
553
554   p_int = lua_tonumber(L, 1);
555   cl = calloc(1, sizeof(*cl));
556   cl->free = nl_extended_free;
557   cl->L = L;
558   gettimeofday(&cl->start, NULL);
559
560   e = eventer_alloc();
561   e->mask = EVENTER_TIMER;
562   e->callback = nl_sleep_complete;
563   e->closure = cl;
564   memcpy(&e->whence, &cl->start, sizeof(cl->start));
565   diff.tv_sec = floor(p_int);
566   diff.tv_usec = (p_int - floor(p_int)) * 1000000;
567   add_timeval(e->whence, diff, &e->whence);
568   noit_lua_check_register_event(ci, e);
569   eventer_add(e);
570   return noit_lua_yield(ci, 0);
571 }
572
573 static int
574 nl_log(lua_State *L) {
575   int i, n;
576   const char *log_dest, *message;
577   noit_log_stream_t ls;
578
579   if(lua_gettop(L) < 2) luaL_error(L, "bad call to noit.log");
580
581   log_dest = lua_tostring(L, 1);
582   ls = noit_log_stream_find(log_dest);
583   if(!ls) {
584     noitL(noit_stderr, "Cannot find log stream: '%s'\n", log_dest);
585     return 0;
586   }
587
588   n = lua_gettop(L);
589   lua_pushstring(L, "string");
590   lua_gettable(L, LUA_GLOBALSINDEX);
591   lua_pushstring(L, "format");
592   lua_gettable(L, -1);
593   for(i=2;i<=n;i++)
594     lua_pushvalue(L, i);
595   lua_call(L, n-1, 1);
596   message = lua_tostring(L, -1);
597   noitL(ls, "%s", message);
598   lua_pop(L, 1); /* formatted string */
599   lua_pop(L, 1); /* "string" table */
600   return 0;
601 }
602 static int
603 nl_gettimeofday(lua_State *L) {
604   struct timeval now;
605   gettimeofday(&now, NULL);
606   lua_pushinteger(L, now.tv_sec);
607   lua_pushinteger(L, now.tv_usec);
608   return 2;
609 }
610 static int
611 nl_socket_tcp(lua_State *L, int family) {
612   struct nl_slcl *cl;
613   noit_lua_check_info_t *ci;
614   socklen_t optlen;
615   int fd;
616   eventer_t e;
617
618   fd = socket(family, SOCK_STREAM, 0);
619   if(fd < 0) {
620     lua_pushnil(L);
621     return 1;
622   }
623   if(eventer_set_fd_nonblocking(fd)) {
624     close(fd);
625     lua_pushnil(L);
626     return 1;
627   }
628
629   ci = get_ci(L);
630   assert(ci);
631
632   cl = calloc(1, sizeof(*cl));
633   cl->free = nl_extended_free;
634   cl->L = L;
635
636   optlen = sizeof(cl->send_size);
637   if(getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &cl->send_size, &optlen) != 0)
638     cl->send_size = 4096;
639
640   e = eventer_alloc();
641   e->fd = fd;
642   e->mask = EVENTER_EXCEPTION;
643   e->callback = NULL;
644   e->closure = cl;
645   cl->eptr = noit_lua_event(L, e);
646
647   noit_lua_check_register_event(ci, e);
648   return 1;
649 }
650 static int
651 nl_socket(lua_State *L) {
652   return nl_socket_tcp(L, AF_INET);
653 }
654 static int
655 nl_socket_ipv6(lua_State *L) {
656   return nl_socket_tcp(L, AF_INET6);
657 }
658
659 static int
660 nl_gunzip_deflate(lua_State *L) {
661   const char *input;
662   size_t inlen;
663   z_stream *stream;
664   Bytef *data = NULL;
665   uLong outlen = 0;
666   int limit = 1024*1024;
667   int err, n = lua_gettop(L);
668
669   if(n < 1 || n > 2) {
670     lua_pushnil(L);
671     return 1;
672   }
673
674   stream = lua_touserdata(L, lua_upvalueindex(1));
675
676   input = lua_tolstring(L, 1, &inlen);
677   if(!input) {
678     lua_pushnil(L);
679     return 1;
680   }
681   if(n == 2)
682     limit = lua_tointeger(L, 2);
683
684   stream->next_in = (Bytef *)input;
685   stream->avail_in = inlen;
686   while(1) {
687     err = inflate(stream, Z_FULL_FLUSH);
688     if(err == Z_OK || err == Z_STREAM_END) {
689       /* got some data */
690       int size_read = DEFLATE_CHUNK_SIZE - stream->avail_out;
691       uLong newoutlen = outlen + size_read;
692       if(newoutlen > limit) {
693         err = Z_MEM_ERROR;
694         break;
695       }
696       if(newoutlen > outlen) {
697         Bytef *newdata;
698         if(data) newdata = realloc(data, newoutlen);
699         else newdata = malloc(newoutlen);
700         if(!newdata) {
701           err = Z_MEM_ERROR;
702           break;
703         }
704         data = newdata;
705         memcpy(data + outlen, stream->next_out - size_read, size_read);
706         outlen += size_read;
707         stream->next_out -= size_read;
708         stream->avail_out += size_read;
709       }
710       if(err == Z_STREAM_END) {
711         /* Good to go */
712         break;
713       }
714     }
715     else break;
716     if(stream->avail_in == 0) break;
717   }
718   if(err == Z_OK || err == Z_STREAM_END) {
719     if(outlen > 0) lua_pushlstring(L, (char *)data, outlen);
720     else lua_pushstring(L, "");
721     if(data) free(data);
722     return 1;
723   }
724   lua_pushnil(L);
725   return 1;
726 }
727 static int
728 nl_gunzip(lua_State *L) {
729   z_stream *stream;
730  
731   stream = (z_stream *)lua_newuserdata(L, sizeof(*stream));
732   memset(stream, 0, sizeof(*stream));
733   luaL_getmetatable(L, "noit.gunzip");
734   lua_setmetatable(L, -2);
735
736   stream->next_in = NULL;
737   stream->avail_in = 0;
738   stream->next_out = malloc(DEFLATE_CHUNK_SIZE);
739   stream->avail_out = stream->next_out ? DEFLATE_CHUNK_SIZE : 0;
740   inflateInit2(stream, MAX_WBITS+32);
741
742   lua_pushcclosure(L, nl_gunzip_deflate, 1);
743   return 1;
744 }
745 static int
746 noit_lua_gunzip_gc(lua_State *L) {
747   z_stream *stream;
748   noitL(noit_debug, "lua: noit.gunzip.__gc for decompression stream\n");
749   stream = (z_stream *)lua_touserdata(L,1);
750   if(stream->next_out) free(stream->next_out);
751   inflateEnd(stream);
752   return 0;
753 }
754
755
756 static const luaL_Reg noitlib[] = {
757   { "sleep", nl_sleep },
758   { "gettimeofday", nl_gettimeofday },
759   { "socket", nl_socket },
760   { "log", nl_log },
761   { "socket_ipv6", nl_socket_ipv6 },
762   { "gunzip", nl_gunzip },
763   { NULL, NULL }
764 };
765
766 int luaopen_noit(lua_State *L) {
767   luaL_newmetatable(L, "noit.eventer");
768   lua_pushcclosure(L, noit_eventer_index_func, 0);
769   lua_setfield(L, -2, "__index");
770
771   luaL_newmetatable(L, "noit.gunzip");
772   lua_pushcfunction(L, noit_lua_gunzip_gc);
773   lua_setfield(L, -2, "__gc");
774
775   luaL_register(L, "noit", noitlib);
776   return 0;
777 }
778
779 void noit_lua_init() {
780   eventer_name_callback("lua/sleep", nl_sleep_complete);
781   eventer_name_callback("lua/socket_read",
782                         noit_lua_socket_read_complete);
783   eventer_name_callback("lua/socket_write",
784                         noit_lua_socket_write_complete);
785   eventer_name_callback("lua/socket_connect",
786                         noit_lua_socket_connect_complete);
787   eventer_name_callback("lua/ssl_upgrade", noit_lua_ssl_upgrade);
788 }
Note: See TracBrowser for help on using the browser.