about summary refs log tree commit diff stats
path: root/src/luasec/luasocket
diff options
context:
space:
mode:
Diffstat (limited to 'src/luasec/luasocket')
-rw-r--r--src/luasec/luasocket/LICENSE21
-rw-r--r--src/luasec/luasocket/Makefile26
-rw-r--r--src/luasec/luasocket/buffer.c282
-rw-r--r--src/luasec/luasocket/buffer.h45
-rw-r--r--src/luasec/luasocket/io.c30
-rw-r--r--src/luasec/luasocket/io.h65
-rw-r--r--src/luasec/luasocket/socket.h78
-rw-r--r--src/luasec/luasocket/timeout.c220
-rw-r--r--src/luasec/luasocket/timeout.h28
-rw-r--r--src/luasec/luasocket/usocket.c439
-rw-r--r--src/luasec/luasocket/usocket.h70
-rw-r--r--src/luasec/luasocket/wsocket.c429
-rw-r--r--src/luasec/luasocket/wsocket.h38
13 files changed, 1771 insertions, 0 deletions
diff --git a/src/luasec/luasocket/LICENSE b/src/luasec/luasocket/LICENSE
new file mode 100644
index 0000000..eadb747
--- /dev/null
+++ b/src/luasec/luasocket/LICENSE
@@ -0,0 +1,21 @@
+LuaSocket 3.0-RC1 license
+Copyright (C) 2004-2013 Diego Nehab
+
+Permission is hereby granted, free  of charge, to any person obtaining
+a  copy  of this  software  and  associated documentation  files  (the
+"Software"), to  deal in  the Software without  restriction, including
+without limitation  the rights to  use, copy, modify,  merge, publish,
+distribute, sublicense,  and/or sell  copies of  the Software,  and to
+permit persons to whom the Software  is furnished to do so, subject to
+the following conditions:
+
+The  above  copyright  notice  and this  permission  notice  shall  be
+included in all copies or substantial portions of the Software.
+
+THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT  SHALL THE AUTHORS OR COPYRIGHT HOLDERS  BE LIABLE FOR ANY
+CLAIM, DAMAGES OR  OTHER LIABILITY, WHETHER IN AN  ACTION OF CONTRACT,
+TORT OR  OTHERWISE, ARISING  FROM, OUT  OF OR  IN CONNECTION  WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/luasec/luasocket/Makefile b/src/luasec/luasocket/Makefile
new file mode 100644
index 0000000..b700fb6
--- /dev/null
+++ b/src/luasec/luasocket/Makefile
@@ -0,0 +1,26 @@
+OBJS= \
+ io.o \
+ buffer.o \
+ timeout.o \
+ usocket.o
+
+CC	?= cc
+CFLAGS	+= $(MYCFLAGS) -DLUASOCKET_DEBUG
+AR	?= ar
+RANLIB	?= ranlib
+
+.PHONY: all clean
+
+all: libluasocket.a
+
+libluasocket.a: $(OBJS)
+	$(AR) rcu $@ $(OBJS)
+	$(RANLIB) $@
+
+clean:
+	rm -f $(OBJS) libluasocket.a
+
+buffer.o: buffer.c buffer.h io.h timeout.h
+io.o: io.c io.h timeout.h
+timeout.o: timeout.c timeout.h
+usocket.o: usocket.c socket.h io.h timeout.h usocket.h
diff --git a/src/luasec/luasocket/buffer.c b/src/luasec/luasocket/buffer.c
new file mode 100644
index 0000000..33882fc
--- /dev/null
+++ b/src/luasec/luasocket/buffer.c
@@ -0,0 +1,282 @@
+/*=========================================================================*\
+* Input/Output interface for Lua programs
+* LuaSocket toolkit
+\*=========================================================================*/
+#include "../../lua.h"
+#include "../../lauxlib.h"
+
+#include "buffer.h"
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b);
+static int recvline(p_buffer buf, luaL_Buffer *b);
+static int recvall(p_buffer buf, luaL_Buffer *b);
+static int buffer_get(p_buffer buf, const char **data, size_t *count);
+static void buffer_skip(p_buffer buf, size_t count);
+static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent);
+
+/* min and max macros */
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? x : y)
+#endif
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? x : y)
+#endif
+
+/*=========================================================================*\
+* Exported functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Initializes module
+\*-------------------------------------------------------------------------*/
+int buffer_open(lua_State *L) {
+    (void) L;
+    return 0;
+}
+
+/*-------------------------------------------------------------------------*\
+* Initializes C structure 
+\*-------------------------------------------------------------------------*/
+void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
+    buf->first = buf->last = 0;
+    buf->io = io;
+    buf->tm = tm;
+    buf->received = buf->sent = 0;
+    buf->birthday = timeout_gettime();
+}
+
+/*-------------------------------------------------------------------------*\
+* object:getstats() interface
+\*-------------------------------------------------------------------------*/
+int buffer_meth_getstats(lua_State *L, p_buffer buf) {
+    lua_pushnumber(L, (lua_Number) buf->received);
+    lua_pushnumber(L, (lua_Number) buf->sent);
+    lua_pushnumber(L, timeout_gettime() - buf->birthday);
+    return 3;
+}
+
+/*-------------------------------------------------------------------------*\
+* object:setstats() interface
+\*-------------------------------------------------------------------------*/
+int buffer_meth_setstats(lua_State *L, p_buffer buf) {
+    buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); 
+    buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); 
+    if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4);
+    lua_pushnumber(L, 1);
+    return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* object:send() interface
+\*-------------------------------------------------------------------------*/
+int buffer_meth_send(lua_State *L, p_buffer buf) {
+    int top = lua_gettop(L);
+    int err = IO_DONE;
+    size_t size = 0, sent = 0;
+    const char *data = luaL_checklstring(L, 2, &size);
+    long start = (long) luaL_optnumber(L, 3, 1);
+    long end = (long) luaL_optnumber(L, 4, -1);
+#ifdef LUASOCKET_DEBUG
+    p_timeout tm = timeout_markstart(buf->tm);
+#endif
+    if (start < 0) start = (long) (size+start+1);
+    if (end < 0) end = (long) (size+end+1);
+    if (start < 1) start = (long) 1;
+    if (end > (long) size) end = (long) size;
+    if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent);
+    /* check if there was an error */
+    if (err != IO_DONE) {
+        lua_pushnil(L);
+        lua_pushstring(L, buf->io->error(buf->io->ctx, err)); 
+        lua_pushnumber(L, (lua_Number) (sent+start-1));
+    } else {
+        lua_pushnumber(L, (lua_Number) (sent+start-1));
+        lua_pushnil(L);
+        lua_pushnil(L);
+    }
+#ifdef LUASOCKET_DEBUG
+    /* push time elapsed during operation as the last return value */
+    lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm));
+#endif
+    return lua_gettop(L) - top;
+}
+
+/*-------------------------------------------------------------------------*\
+* object:receive() interface
+\*-------------------------------------------------------------------------*/
+int buffer_meth_receive(lua_State *L, p_buffer buf) {
+    luaL_Buffer b;
+    size_t size;
+    const char *part;
+    int err = IO_DONE;
+    int top = lua_gettop(L);
+    if (top < 3) {
+        lua_settop(L, 3);
+        top = 3;
+    }
+    part = luaL_optlstring(L, 3, "", &size);
+#ifdef LUASOCKET_DEBUG
+    p_timeout tm = timeout_markstart(buf->tm);
+#endif
+    /* initialize buffer with optional extra prefix 
+     * (useful for concatenating previous partial results) */
+    luaL_buffinit(L, &b);
+    luaL_addlstring(&b, part, size);
+    /* receive new patterns */
+    if (!lua_isnumber(L, 2)) {
+        const char *p= luaL_optstring(L, 2, "*l");
+        if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
+        else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); 
+        else luaL_argcheck(L, 0, 2, "invalid receive pattern");
+    /* get a fixed number of bytes (minus what was already partially 
+     * received) */
+    } else {
+        double n = lua_tonumber(L, 2); 
+        size_t wanted = (size_t) n;
+        luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
+        if (size == 0 || wanted > size)
+            err = recvraw(buf, wanted-size, &b);
+    }
+    /* check if there was an error */
+    if (err != IO_DONE) {
+        /* we can't push anything in the stack before pushing the
+         * contents of the buffer. this is the reason for the complication */
+        luaL_pushresult(&b);
+        lua_pushstring(L, buf->io->error(buf->io->ctx, err)); 
+        lua_pushvalue(L, -2); 
+        lua_pushnil(L);
+        lua_replace(L, -4);
+    } else {
+        luaL_pushresult(&b);
+        lua_pushnil(L);
+        lua_pushnil(L);
+    }
+#ifdef LUASOCKET_DEBUG
+    /* push time elapsed during operation as the last return value */
+    lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm));
+#endif
+    return lua_gettop(L) - top;
+}
+
+/*-------------------------------------------------------------------------*\
+* Determines if there is any data in the read buffer
+\*-------------------------------------------------------------------------*/
+int buffer_isempty(p_buffer buf) {
+    return buf->first >= buf->last;
+}
+
+/*=========================================================================*\
+* Internal functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Sends a block of data (unbuffered)
+\*-------------------------------------------------------------------------*/
+#define STEPSIZE 8192
+static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) {
+    p_io io = buf->io;
+    p_timeout tm = buf->tm;
+    size_t total = 0;
+    int err = IO_DONE;
+    while (total < count && err == IO_DONE) {
+        size_t done = 0;
+        size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE;
+        err = io->send(io->ctx, data+total, step, &done, tm);
+        total += done;
+    }
+    *sent = total;
+    buf->sent += total;
+    return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* Reads a fixed number of bytes (buffered)
+\*-------------------------------------------------------------------------*/
+static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) {
+    int err = IO_DONE;
+    size_t total = 0;
+    while (err == IO_DONE) {
+        size_t count; const char *data;
+        err = buffer_get(buf, &data, &count);
+        count = MIN(count, wanted - total);
+        luaL_addlstring(b, data, count);
+        buffer_skip(buf, count);
+        total += count;
+        if (total >= wanted) break;
+    }
+    return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* Reads everything until the connection is closed (buffered)
+\*-------------------------------------------------------------------------*/
+static int recvall(p_buffer buf, luaL_Buffer *b) {
+    int err = IO_DONE;
+    size_t total = 0;
+    while (err == IO_DONE) {
+        const char *data; size_t count;
+        err = buffer_get(buf, &data, &count);
+        total += count;
+        luaL_addlstring(b, data, count);
+        buffer_skip(buf, count);
+    }
+    if (err == IO_CLOSED) {
+        if (total > 0) return IO_DONE;
+        else return IO_CLOSED;
+    } else return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF 
+* are not returned by the function and are discarded from the buffer
+\*-------------------------------------------------------------------------*/
+static int recvline(p_buffer buf, luaL_Buffer *b) {
+    int err = IO_DONE;
+    while (err == IO_DONE) {
+        size_t count, pos; const char *data;
+        err = buffer_get(buf, &data, &count);
+        pos = 0;
+        while (pos < count && data[pos] != '\n') {
+            /* we ignore all \r's */
+            if (data[pos] != '\r') luaL_addchar(b, data[pos]);
+            pos++;
+        }
+        if (pos < count) { /* found '\n' */
+            buffer_skip(buf, pos+1); /* skip '\n' too */
+            break; /* we are done */
+        } else /* reached the end of the buffer */
+            buffer_skip(buf, pos);
+    }
+    return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* Skips a given number of bytes from read buffer. No data is read from the
+* transport layer
+\*-------------------------------------------------------------------------*/
+static void buffer_skip(p_buffer buf, size_t count) {
+    buf->received += count;
+    buf->first += count;
+    if (buffer_isempty(buf)) 
+        buf->first = buf->last = 0;
+}
+
+/*-------------------------------------------------------------------------*\
+* Return any data available in buffer, or get more data from transport layer
+* if buffer is empty
+\*-------------------------------------------------------------------------*/
+static int buffer_get(p_buffer buf, const char **data, size_t *count) {
+    int err = IO_DONE;
+    p_io io = buf->io;
+    p_timeout tm = buf->tm;
+    if (buffer_isempty(buf)) {
+        size_t got;
+        err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm);
+        buf->first = 0;
+        buf->last = got;
+    }
+    *count = buf->last - buf->first;
+    *data = buf->data + buf->first;
+    return err;
+}
diff --git a/src/luasec/luasocket/buffer.h b/src/luasec/luasocket/buffer.h
new file mode 100644
index 0000000..a9cbd3a
--- /dev/null
+++ b/src/luasec/luasocket/buffer.h
@@ -0,0 +1,45 @@
+#ifndef BUF_H
+#define BUF_H 
+/*=========================================================================*\
+* Input/Output interface for Lua programs
+* LuaSocket toolkit
+*
+* Line patterns require buffering. Reading one character at a time involves
+* too many system calls and is very slow. This module implements the
+* LuaSocket interface for input/output on connected objects, as seen by 
+* Lua programs. 
+*
+* Input is buffered. Output is *not* buffered because there was no simple
+* way of making sure the buffered output data would ever be sent.
+*
+* The module is built on top of the I/O abstraction defined in io.h and the
+* timeout management is done with the timeout.h interface.
+\*=========================================================================*/
+#include "../../lua.h"
+
+#include "io.h"
+#include "timeout.h"
+
+/* buffer size in bytes */
+#define BUF_SIZE 8192
+
+/* buffer control structure */
+typedef struct t_buffer_ {
+    double birthday;        /* throttle support info: creation time, */
+    size_t sent, received;  /* bytes sent, and bytes received */
+    p_io io;                /* IO driver used for this buffer */
+    p_timeout tm;           /* timeout management for this buffer */
+    size_t first, last;     /* index of first and last bytes of stored data */
+    char data[BUF_SIZE];    /* storage space for buffer data */
+} t_buffer;
+typedef t_buffer *p_buffer;
+
+int buffer_open(lua_State *L);
+void buffer_init(p_buffer buf, p_io io, p_timeout tm);
+int buffer_meth_send(lua_State *L, p_buffer buf);
+int buffer_meth_receive(lua_State *L, p_buffer buf);
+int buffer_meth_getstats(lua_State *L, p_buffer buf);
+int buffer_meth_setstats(lua_State *L, p_buffer buf);
+int buffer_isempty(p_buffer buf);
+
+#endif /* BUF_H */
diff --git a/src/luasec/luasocket/io.c b/src/luasec/luasocket/io.c
new file mode 100644
index 0000000..35f46f7
--- /dev/null
+++ b/src/luasec/luasocket/io.c
@@ -0,0 +1,30 @@
+/*=========================================================================*\
+* Input/Output abstraction
+* LuaSocket toolkit
+\*=========================================================================*/
+#include "io.h"
+
+/*=========================================================================*\
+* Exported functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Initializes C structure
+\*-------------------------------------------------------------------------*/
+void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) {
+    io->send = send;
+    io->recv = recv;
+    io->error = error;
+    io->ctx = ctx;
+}
+
+/*-------------------------------------------------------------------------*\
+* I/O error strings
+\*-------------------------------------------------------------------------*/
+const char *io_strerror(int err) {
+    switch (err) {
+        case IO_DONE: return NULL;
+        case IO_CLOSED: return "closed";
+        case IO_TIMEOUT: return "timeout";
+        default: return "unknown error"; 
+    }
+}
diff --git a/src/luasec/luasocket/io.h b/src/luasec/luasocket/io.h
new file mode 100644
index 0000000..b1f35ad
--- /dev/null
+++ b/src/luasec/luasocket/io.h
@@ -0,0 +1,65 @@
+#ifndef IO_H
+#define IO_H
+/*=========================================================================*\
+* Input/Output abstraction
+* LuaSocket toolkit
+*
+* This module defines the interface that LuaSocket expects from the
+* transport layer for streamed input/output. The idea is that if any
+* transport implements this interface, then the buffer.c functions
+* automatically work on it.
+*
+* The module socket.h implements this interface, and thus the module tcp.h
+* is very simple.
+\*=========================================================================*/
+#include <stdio.h>
+#include "../../lua.h"
+
+#include "timeout.h"
+
+/* IO error codes */
+enum {
+    IO_DONE = 0,        /* operation completed successfully */
+    IO_TIMEOUT = -1,    /* operation timed out */
+    IO_CLOSED = -2,     /* the connection has been closed */
+	IO_UNKNOWN = -3     
+};
+
+/* interface to error message function */
+typedef const char *(*p_error) (
+    void *ctx,          /* context needed by send */
+    int err             /* error code */
+);
+
+/* interface to send function */
+typedef int (*p_send) (
+    void *ctx,          /* context needed by send */
+    const char *data,   /* pointer to buffer with data to send */
+    size_t count,       /* number of bytes to send from buffer */
+    size_t *sent,       /* number of bytes sent uppon return */
+    p_timeout tm        /* timeout control */
+);
+
+/* interface to recv function */
+typedef int (*p_recv) (
+    void *ctx,          /* context needed by recv */
+    char *data,         /* pointer to buffer where data will be written */
+    size_t count,       /* number of bytes to receive into buffer */
+    size_t *got,        /* number of bytes received uppon return */
+    p_timeout tm        /* timeout control */
+);
+
+/* IO driver definition */
+typedef struct t_io_ {
+    void *ctx;          /* context needed by send/recv */
+    p_send send;        /* send function pointer */
+    p_recv recv;        /* receive function pointer */
+    p_error error;      /* strerror function */
+} t_io;
+typedef t_io *p_io;
+
+void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx);
+const char *io_strerror(int err);
+
+#endif /* IO_H */
+
diff --git a/src/luasec/luasocket/socket.h b/src/luasec/luasocket/socket.h
new file mode 100644
index 0000000..07c20fe
--- /dev/null
+++ b/src/luasec/luasocket/socket.h
@@ -0,0 +1,78 @@
+#ifndef SOCKET_H
+#define SOCKET_H
+/*=========================================================================*\
+* Socket compatibilization module
+* LuaSocket toolkit
+*
+* BSD Sockets and WinSock are similar, but there are a few irritating
+* differences. Also, not all *nix platforms behave the same. This module
+* (and the associated usocket.h and wsocket.h) factor these differences and
+* creates a interface compatible with the io.h module.
+\*=========================================================================*/
+#include "io.h"
+
+/*=========================================================================*\
+* Platform specific compatibilization
+\*=========================================================================*/
+#ifdef _WIN32
+#include "wsocket.h"
+#else
+#include "usocket.h"
+#endif
+
+/*=========================================================================*\
+* The connect and accept functions accept a timeout and their
+* implementations are somewhat complicated. We chose to move
+* the timeout control into this module for these functions in
+* order to simplify the modules that use them. 
+\*=========================================================================*/
+#include "timeout.h"
+
+/* we are lazy... */
+typedef struct sockaddr SA;
+
+/*=========================================================================*\
+* Functions below implement a comfortable platform independent 
+* interface to sockets
+\*=========================================================================*/
+int socket_open(void);
+int socket_close(void);
+void socket_destroy(p_socket ps);
+void socket_shutdown(p_socket ps, int how); 
+int socket_sendto(p_socket ps, const char *data, size_t count, 
+        size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm);
+int socket_recvfrom(p_socket ps, char *data, size_t count, 
+        size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm);
+
+void socket_setnonblocking(p_socket ps);
+void socket_setblocking(p_socket ps);
+
+int socket_waitfd(p_socket ps, int sw, p_timeout tm);
+int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, 
+        p_timeout tm);
+
+int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); 
+int socket_create(p_socket ps, int domain, int type, int protocol);
+int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); 
+int socket_listen(p_socket ps, int backlog);
+int socket_accept(p_socket ps, p_socket pa, SA *addr, 
+        socklen_t *addr_len, p_timeout tm);
+
+const char *socket_hoststrerror(int err);
+const char *socket_gaistrerror(int err);
+const char *socket_strerror(int err);
+
+/* these are perfect to use with the io abstraction module 
+   and the buffered input module */
+int socket_send(p_socket ps, const char *data, size_t count, 
+        size_t *sent, p_timeout tm);
+int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
+int socket_write(p_socket ps, const char *data, size_t count, 
+        size_t *sent, p_timeout tm);
+int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
+const char *socket_ioerror(p_socket ps, int err);
+
+int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp);
+int socket_gethostbyname(const char *addr, struct hostent **hp);
+
+#endif /* SOCKET_H */
diff --git a/src/luasec/luasocket/timeout.c b/src/luasec/luasocket/timeout.c
new file mode 100644
index 0000000..d1faded
--- /dev/null
+++ b/src/luasec/luasocket/timeout.c
@@ -0,0 +1,220 @@
+/*=========================================================================*\
+* Timeout management functions
+* LuaSocket toolkit
+\*=========================================================================*/
+#include <stdio.h>
+#include <limits.h>
+#include <float.h>
+
+#include "../../lua.h"
+#include "../../lauxlib.h"
+
+#include "timeout.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+/* min and max macros */
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? x : y)
+#endif
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? x : y)
+#endif
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int timeout_lua_gettime(lua_State *L);
+static int timeout_lua_sleep(lua_State *L);
+
+static luaL_Reg func[] = {
+    { "gettime", timeout_lua_gettime },
+    { "sleep", timeout_lua_sleep },
+    { NULL, NULL }
+};
+
+/*=========================================================================*\
+* Exported functions.
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Initialize structure
+\*-------------------------------------------------------------------------*/
+void timeout_init(p_timeout tm, double block, double total) {
+    tm->block = block;
+    tm->total = total;
+}
+
+/*-------------------------------------------------------------------------*\
+* Determines how much time we have left for the next system call,
+* if the previous call was successful 
+* Input
+*   tm: timeout control structure
+* Returns
+*   the number of ms left or -1 if there is no time limit
+\*-------------------------------------------------------------------------*/
+double timeout_get(p_timeout tm) {
+    if (tm->block < 0.0 && tm->total < 0.0) {
+        return -1;
+    } else if (tm->block < 0.0) {
+        double t = tm->total - timeout_gettime() + tm->start;
+        return MAX(t, 0.0);
+    } else if (tm->total < 0.0) {
+        return tm->block;
+    } else {
+        double t = tm->total - timeout_gettime() + tm->start;
+        return MIN(tm->block, MAX(t, 0.0));
+    }
+}
+
+/*-------------------------------------------------------------------------*\
+* Returns time since start of operation
+* Input
+*   tm: timeout control structure
+* Returns
+*   start field of structure
+\*-------------------------------------------------------------------------*/
+double timeout_getstart(p_timeout tm) {
+    return tm->start;
+}
+
+/*-------------------------------------------------------------------------*\
+* Determines how much time we have left for the next system call,
+* if the previous call was a failure
+* Input
+*   tm: timeout control structure
+* Returns
+*   the number of ms left or -1 if there is no time limit
+\*-------------------------------------------------------------------------*/
+double timeout_getretry(p_timeout tm) {
+    if (tm->block < 0.0 && tm->total < 0.0) {
+        return -1;
+    } else if (tm->block < 0.0) {
+        double t = tm->total - timeout_gettime() + tm->start;
+        return MAX(t, 0.0);
+    } else if (tm->total < 0.0) {
+        double t = tm->block - timeout_gettime() + tm->start;
+        return MAX(t, 0.0);
+    } else {
+        double t = tm->total - timeout_gettime() + tm->start;
+        return MIN(tm->block, MAX(t, 0.0));
+    }
+}
+
+/*-------------------------------------------------------------------------*\
+* Marks the operation start time in structure 
+* Input
+*   tm: timeout control structure
+\*-------------------------------------------------------------------------*/
+p_timeout timeout_markstart(p_timeout tm) {
+    tm->start = timeout_gettime();
+    return tm;
+}
+
+/*-------------------------------------------------------------------------*\
+* Gets time in s, relative to January 1, 1970 (UTC) 
+* Returns
+*   time in s.
+\*-------------------------------------------------------------------------*/
+#ifdef _WIN32
+double timeout_gettime(void) {
+    FILETIME ft;
+    double t;
+    GetSystemTimeAsFileTime(&ft);
+    /* Windows file time (time since January 1, 1601 (UTC)) */
+    t  = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
+    /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
+    return (t - 11644473600.0);
+}
+#else
+double timeout_gettime(void) {
+    struct timeval v;
+    gettimeofday(&v, (struct timezone *) NULL);
+    /* Unix Epoch time (time since January 1, 1970 (UTC)) */
+    return v.tv_sec + v.tv_usec/1.0e6;
+}
+#endif
+
+/*-------------------------------------------------------------------------*\
+* Initializes module
+\*-------------------------------------------------------------------------*/
+int timeout_open(lua_State *L) {
+#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
+    luaL_setfuncs(L, func, 0);
+#else
+    luaL_openlib(L, NULL, func, 0);
+#endif
+    return 0;
+}
+
+/*-------------------------------------------------------------------------*\
+* Sets timeout values for IO operations
+* Lua Input: base, time [, mode]
+*   time: time out value in seconds
+*   mode: "b" for block timeout, "t" for total timeout. (default: b)
+\*-------------------------------------------------------------------------*/
+int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
+    double t = luaL_optnumber(L, 2, -1);
+    const char *mode = luaL_optstring(L, 3, "b");
+    switch (*mode) {
+        case 'b':
+            tm->block = t; 
+            break;
+        case 'r': case 't':
+            tm->total = t;
+            break;
+        default:
+            luaL_argcheck(L, 0, 3, "invalid timeout mode");
+            break;
+    }
+    lua_pushnumber(L, 1);
+    return 1;
+}
+
+/*=========================================================================*\
+* Test support functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Returns the time the system has been up, in secconds.
+\*-------------------------------------------------------------------------*/
+static int timeout_lua_gettime(lua_State *L)
+{
+    lua_pushnumber(L, timeout_gettime());
+    return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Sleep for n seconds.
+\*-------------------------------------------------------------------------*/
+#ifdef _WIN32
+int timeout_lua_sleep(lua_State *L)
+{
+    double n = luaL_checknumber(L, 1);
+    if (n < 0.0) n = 0.0;
+    if (n < DBL_MAX/1000.0) n *= 1000.0;
+    if (n > INT_MAX) n = INT_MAX;
+    Sleep((int)n);
+    return 0;
+}
+#else
+int timeout_lua_sleep(lua_State *L)
+{
+    double n = luaL_checknumber(L, 1);
+    struct timespec t, r;
+    if (n < 0.0) n = 0.0;
+    if (n > INT_MAX) n = INT_MAX;
+    t.tv_sec = (int) n;
+    n -= t.tv_sec;
+    t.tv_nsec = (int) (n * 1000000000);
+    if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
+    while (nanosleep(&t, &r) != 0) {
+        t.tv_sec = r.tv_sec;
+        t.tv_nsec = r.tv_nsec;
+    }
+    return 0;
+}
+#endif
diff --git a/src/luasec/luasocket/timeout.h b/src/luasec/luasocket/timeout.h
new file mode 100644
index 0000000..69751da
--- /dev/null
+++ b/src/luasec/luasocket/timeout.h
@@ -0,0 +1,28 @@
+#ifndef TIMEOUT_H
+#define TIMEOUT_H
+/*=========================================================================*\
+* Timeout management functions
+* LuaSocket toolkit
+\*=========================================================================*/
+#include "../../lua.h"
+
+/* timeout control structure */
+typedef struct t_timeout_ {
+    double block;          /* maximum time for blocking calls */
+    double total;          /* total number of milliseconds for operation */
+    double start;          /* time of start of operation */
+} t_timeout;
+typedef t_timeout *p_timeout;
+
+int timeout_open(lua_State *L);
+void timeout_init(p_timeout tm, double block, double total);
+double timeout_get(p_timeout tm);
+double timeout_getretry(p_timeout tm);
+p_timeout timeout_markstart(p_timeout tm);
+double timeout_getstart(p_timeout tm);
+double timeout_gettime(void);
+int timeout_meth_settimeout(lua_State *L, p_timeout tm);
+
+#define timeout_iszero(tm)   ((tm)->block == 0.0)
+
+#endif /* TIMEOUT_H */
diff --git a/src/luasec/luasocket/usocket.c b/src/luasec/luasocket/usocket.c
new file mode 100644
index 0000000..775e6fd
--- /dev/null
+++ b/src/luasec/luasocket/usocket.c
@@ -0,0 +1,439 @@
+/*=========================================================================*\
+* Socket compatibilization module for Unix
+* LuaSocket toolkit
+*
+* The code is now interrupt-safe.
+* The penalty of calling select to avoid busy-wait is only paid when
+* the I/O call fail in the first place. 
+\*=========================================================================*/
+#include <string.h> 
+#include <signal.h>
+
+#include "socket.h"
+
+/*-------------------------------------------------------------------------*\
+* Wait for readable/writable/connected socket with timeout
+\*-------------------------------------------------------------------------*/
+#ifndef SOCKET_SELECT
+int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
+    int ret;
+    struct pollfd pfd;
+    pfd.fd = *ps;
+    pfd.events = sw;
+    pfd.revents = 0;
+    if (timeout_iszero(tm)) return IO_TIMEOUT;  /* optimize timeout == 0 case */
+    do {
+        int t = (int)(timeout_getretry(tm)*1e3);
+        ret = poll(&pfd, 1, t >= 0? t: -1);
+    } while (ret == -1 && errno == EINTR);
+    if (ret == -1) return errno;
+    if (ret == 0) return IO_TIMEOUT;
+    if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;
+    return IO_DONE;
+}
+#else
+int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
+    int ret;
+    fd_set rfds, wfds, *rp, *wp;
+    struct timeval tv, *tp;
+    double t;
+    if (*ps >= FD_SETSIZE) return EINVAL;
+    if (timeout_iszero(tm)) return IO_TIMEOUT;  /* optimize timeout == 0 case */
+    do {
+        /* must set bits within loop, because select may have modified them */
+        rp = wp = NULL;
+        if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; }
+        if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
+        t = timeout_getretry(tm);
+        tp = NULL;
+        if (t >= 0.0) {
+            tv.tv_sec = (int)t;
+            tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6);
+            tp = &tv;
+        }
+        ret = select(*ps+1, rp, wp, NULL, tp);
+    } while (ret == -1 && errno == EINTR);
+    if (ret == -1) return errno;
+    if (ret == 0) return IO_TIMEOUT;
+    if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED;
+    return IO_DONE;
+}
+#endif
+
+
+/*-------------------------------------------------------------------------*\
+* Initializes module 
+\*-------------------------------------------------------------------------*/
+int socket_open(void) {
+    /* instals a handler to ignore sigpipe or it will crash us */
+    signal(SIGPIPE, SIG_IGN);
+    return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Close module 
+\*-------------------------------------------------------------------------*/
+int socket_close(void) {
+    return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Close and inutilize socket
+\*-------------------------------------------------------------------------*/
+void socket_destroy(p_socket ps) {
+    if (*ps != SOCKET_INVALID) {
+        socket_setblocking(ps);
+        close(*ps);
+        *ps = SOCKET_INVALID;
+    }
+}
+
+/*-------------------------------------------------------------------------*\
+* Select with timeout control
+\*-------------------------------------------------------------------------*/
+int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, 
+        p_timeout tm) {
+    int ret;
+    do {
+        struct timeval tv;
+        double t = timeout_getretry(tm);
+        tv.tv_sec = (int) t;
+        tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
+        /* timeout = 0 means no wait */
+        ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL);
+    } while (ret < 0 && errno == EINTR);
+    return ret;
+}
+
+/*-------------------------------------------------------------------------*\
+* Creates and sets up a socket
+\*-------------------------------------------------------------------------*/
+int socket_create(p_socket ps, int domain, int type, int protocol) {
+    *ps = socket(domain, type, protocol);
+    if (*ps != SOCKET_INVALID) return IO_DONE; 
+    else return errno; 
+}
+
+/*-------------------------------------------------------------------------*\
+* Binds or returns error message
+\*-------------------------------------------------------------------------*/
+int socket_bind(p_socket ps, SA *addr, socklen_t len) {
+    int err = IO_DONE;
+    socket_setblocking(ps);
+    if (bind(*ps, addr, len) < 0) err = errno; 
+    socket_setnonblocking(ps);
+    return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* 
+\*-------------------------------------------------------------------------*/
+int socket_listen(p_socket ps, int backlog) {
+    int err = IO_DONE; 
+    socket_setblocking(ps);
+    if (listen(*ps, backlog)) err = errno; 
+    socket_setnonblocking(ps);
+    return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* 
+\*-------------------------------------------------------------------------*/
+void socket_shutdown(p_socket ps, int how) {
+    socket_setblocking(ps);
+    shutdown(*ps, how);
+    socket_setnonblocking(ps);
+}
+
+/*-------------------------------------------------------------------------*\
+* Connects or returns error message
+\*-------------------------------------------------------------------------*/
+int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
+    int err;
+    /* avoid calling on closed sockets */
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    /* call connect until done or failed without being interrupted */
+    do if (connect(*ps, addr, len) == 0) return IO_DONE;
+    while ((err = errno) == EINTR);
+    /* if connection failed immediately, return error code */
+    if (err != EINPROGRESS && err != EAGAIN) return err; 
+    /* zero timeout case optimization */
+    if (timeout_iszero(tm)) return IO_TIMEOUT;
+    /* wait until we have the result of the connection attempt or timeout */
+    err = socket_waitfd(ps, WAITFD_C, tm);
+    if (err == IO_CLOSED) {
+        if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE;
+        else return errno;
+    } else return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* Accept with timeout
+\*-------------------------------------------------------------------------*/
+int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) {
+    if (*ps == SOCKET_INVALID) return IO_CLOSED; 
+    for ( ;; ) {
+        int err;
+        if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
+        err = errno;
+        if (err == EINTR) continue;
+        if (err != EAGAIN && err != ECONNABORTED) return err;
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
+    }
+    /* can't reach here */
+    return IO_UNKNOWN;
+}
+
+/*-------------------------------------------------------------------------*\
+* Send with timeout
+\*-------------------------------------------------------------------------*/
+int socket_send(p_socket ps, const char *data, size_t count, 
+        size_t *sent, p_timeout tm)
+{
+    int err;
+    *sent = 0;
+    /* avoid making system calls on closed sockets */
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    /* loop until we send something or we give up on error */
+    for ( ;; ) {
+        long put = (long) send(*ps, data, count, 0);
+        /* if we sent anything, we are done */
+        if (put >= 0) {
+            *sent = put;
+            return IO_DONE;
+        }
+        err = errno;
+        /* EPIPE means the connection was closed */
+        if (err == EPIPE) return IO_CLOSED;
+        /* we call was interrupted, just try again */
+        if (err == EINTR) continue;
+        /* if failed fatal reason, report error */
+        if (err != EAGAIN) return err;
+        /* wait until we can send something or we timeout */
+        if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
+    }
+    /* can't reach here */
+    return IO_UNKNOWN;
+}
+
+/*-------------------------------------------------------------------------*\
+* Sendto with timeout
+\*-------------------------------------------------------------------------*/
+int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, 
+        SA *addr, socklen_t len, p_timeout tm)
+{
+    int err;
+    *sent = 0;
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        long put = (long) sendto(*ps, data, count, 0, addr, len);  
+        if (put >= 0) {
+            *sent = put;
+            return IO_DONE;
+        }
+        err = errno;
+        if (err == EPIPE) return IO_CLOSED;
+        if (err == EINTR) continue;
+        if (err != EAGAIN) return err;
+        if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
+    }
+    return IO_UNKNOWN;
+}
+
+/*-------------------------------------------------------------------------*\
+* Receive with timeout
+\*-------------------------------------------------------------------------*/
+int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
+    int err;
+    *got = 0;
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        long taken = (long) recv(*ps, data, count, 0);
+        if (taken > 0) {
+            *got = taken;
+            return IO_DONE;
+        }
+        err = errno;
+        if (taken == 0) return IO_CLOSED;
+        if (err == EINTR) continue;
+        if (err != EAGAIN) return err; 
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; 
+    }
+    return IO_UNKNOWN;
+}
+
+/*-------------------------------------------------------------------------*\
+* Recvfrom with timeout
+\*-------------------------------------------------------------------------*/
+int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, 
+        SA *addr, socklen_t *len, p_timeout tm) {
+    int err;
+    *got = 0;
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        long taken = (long) recvfrom(*ps, data, count, 0, addr, len);
+        if (taken > 0) {
+            *got = taken;
+            return IO_DONE;
+        }
+        err = errno;
+        if (taken == 0) return IO_CLOSED;
+        if (err == EINTR) continue;
+        if (err != EAGAIN) return err; 
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; 
+    }
+    return IO_UNKNOWN;
+}
+
+
+/*-------------------------------------------------------------------------*\
+* Write with timeout
+*
+* socket_read and socket_write are cut-n-paste of socket_send and socket_recv,
+* with send/recv replaced with write/read. We can't just use write/read
+* in the socket version, because behaviour when size is zero is different.
+\*-------------------------------------------------------------------------*/
+int socket_write(p_socket ps, const char *data, size_t count, 
+        size_t *sent, p_timeout tm)
+{
+    int err;
+    *sent = 0;
+    /* avoid making system calls on closed sockets */
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    /* loop until we send something or we give up on error */
+    for ( ;; ) {
+        long put = (long) write(*ps, data, count);
+        /* if we sent anything, we are done */
+        if (put >= 0) {
+            *sent = put;
+            return IO_DONE;
+        }
+        err = errno;
+        /* EPIPE means the connection was closed */
+        if (err == EPIPE) return IO_CLOSED;
+        /* we call was interrupted, just try again */
+        if (err == EINTR) continue;
+        /* if failed fatal reason, report error */
+        if (err != EAGAIN) return err;
+        /* wait until we can send something or we timeout */
+        if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
+    }
+    /* can't reach here */
+    return IO_UNKNOWN;
+}
+
+/*-------------------------------------------------------------------------*\
+* Read with timeout
+* See note for socket_write
+\*-------------------------------------------------------------------------*/
+int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
+    int err;
+    *got = 0;
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        long taken = (long) read(*ps, data, count);
+        if (taken > 0) {
+            *got = taken;
+            return IO_DONE;
+        }
+        err = errno;
+        if (taken == 0) return IO_CLOSED;
+        if (err == EINTR) continue;
+        if (err != EAGAIN) return err; 
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; 
+    }
+    return IO_UNKNOWN;
+}
+
+/*-------------------------------------------------------------------------*\
+* Put socket into blocking mode
+\*-------------------------------------------------------------------------*/
+void socket_setblocking(p_socket ps) {
+    int flags = fcntl(*ps, F_GETFL, 0);
+    flags &= (~(O_NONBLOCK));
+    fcntl(*ps, F_SETFL, flags);
+}
+
+/*-------------------------------------------------------------------------*\
+* Put socket into non-blocking mode
+\*-------------------------------------------------------------------------*/
+void socket_setnonblocking(p_socket ps) {
+    int flags = fcntl(*ps, F_GETFL, 0);
+    flags |= O_NONBLOCK;
+    fcntl(*ps, F_SETFL, flags);
+}
+
+/*-------------------------------------------------------------------------*\
+* DNS helpers 
+\*-------------------------------------------------------------------------*/
+int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
+    *hp = gethostbyaddr(addr, len, AF_INET);
+    if (*hp) return IO_DONE;
+    else if (h_errno) return h_errno;
+    else if (errno) return errno;
+    else return IO_UNKNOWN;
+}
+
+int socket_gethostbyname(const char *addr, struct hostent **hp) {
+    *hp = gethostbyname(addr);
+    if (*hp) return IO_DONE;
+    else if (h_errno) return h_errno;
+    else if (errno) return errno;
+    else return IO_UNKNOWN;
+}
+
+/*-------------------------------------------------------------------------*\
+* Error translation functions
+* Make sure important error messages are standard
+\*-------------------------------------------------------------------------*/
+const char *socket_hoststrerror(int err) {
+    if (err <= 0) return io_strerror(err);
+    switch (err) {
+        case HOST_NOT_FOUND: return "host not found";
+        default: return hstrerror(err);
+    }
+}
+
+const char *socket_strerror(int err) {
+    if (err <= 0) return io_strerror(err);
+    switch (err) {
+        case EADDRINUSE: return "address already in use";
+        case EISCONN: return "already connected";
+        case EACCES: return "permission denied";
+        case ECONNREFUSED: return "connection refused";
+        case ECONNABORTED: return "closed";
+        case ECONNRESET: return "closed";
+        case ETIMEDOUT: return "timeout";
+        default: return strerror(err);
+    }
+}
+
+const char *socket_ioerror(p_socket ps, int err) {
+    (void) ps;
+    return socket_strerror(err);
+} 
+
+const char *socket_gaistrerror(int err) {
+    if (err == 0) return NULL; 
+    switch (err) {
+        case EAI_AGAIN: return "temporary failure in name resolution";
+        case EAI_BADFLAGS: return "invalid value for ai_flags";
+#ifdef EAI_BADHINTS
+        case EAI_BADHINTS: return "invalid value for hints";
+#endif
+        case EAI_FAIL: return "non-recoverable failure in name resolution";
+        case EAI_FAMILY: return "ai_family not supported";
+        case EAI_MEMORY: return "memory allocation failure";
+        case EAI_NONAME: 
+            return "host or service not provided, or not known";
+        case EAI_OVERFLOW: return "argument buffer overflow";
+#ifdef EAI_PROTOCOL
+        case EAI_PROTOCOL: return "resolved protocol is unknown";
+#endif
+        case EAI_SERVICE: return "service not supported for socket type";
+        case EAI_SOCKTYPE: return "ai_socktype not supported";
+        case EAI_SYSTEM: return strerror(errno); 
+        default: return gai_strerror(err);
+    }
+}
+
diff --git a/src/luasec/luasocket/usocket.h b/src/luasec/luasocket/usocket.h
new file mode 100644
index 0000000..ecbcd8e
--- /dev/null
+++ b/src/luasec/luasocket/usocket.h
@@ -0,0 +1,70 @@
+#ifndef USOCKET_H
+#define USOCKET_H
+/*=========================================================================*\
+* Socket compatibilization module for Unix
+* LuaSocket toolkit
+\*=========================================================================*/
+
+/*=========================================================================*\
+* BSD include files
+\*=========================================================================*/
+/* error codes */
+#include <errno.h>
+/* close function */
+#include <unistd.h>
+/* fnctnl function and associated constants */
+#include <fcntl.h>
+/* struct sockaddr */
+#include <sys/types.h>
+/* socket function */
+#include <sys/socket.h>
+/* struct timeval */
+#include <sys/time.h>
+/* gethostbyname and gethostbyaddr functions */
+#include <netdb.h>
+/* sigpipe handling */
+#include <signal.h>
+/* IP stuff*/
+#include <netinet/in.h>
+#include <arpa/inet.h>
+/* TCP options (nagle algorithm disable) */
+#include <netinet/tcp.h>
+#include <net/if.h>
+
+#ifndef SOCKET_SELECT
+#include <sys/poll.h>
+#define WAITFD_R        POLLIN
+#define WAITFD_W        POLLOUT
+#define WAITFD_C        (POLLIN|POLLOUT)
+#else
+#define WAITFD_R        1
+#define WAITFD_W        2
+#define WAITFD_C        (WAITFD_R|WAITFD_W)
+#endif
+
+#ifndef SO_REUSEPORT
+#define SO_REUSEPORT SO_REUSEADDR
+#endif
+
+/* Some platforms use IPV6_JOIN_GROUP instead if
+ * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */
+#ifndef IPV6_ADD_MEMBERSHIP
+#ifdef IPV6_JOIN_GROUP
+#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+#endif /* IPV6_JOIN_GROUP */
+#endif /* !IPV6_ADD_MEMBERSHIP */
+
+/* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */
+#ifndef IPV6_DROP_MEMBERSHIP
+#ifdef IPV6_LEAVE_GROUP
+#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
+#endif /* IPV6_LEAVE_GROUP */
+#endif /* !IPV6_DROP_MEMBERSHIP */
+
+typedef int t_socket;
+typedef t_socket *p_socket;
+typedef struct sockaddr_storage t_sockaddr_storage;
+
+#define SOCKET_INVALID (-1)
+
+#endif /* USOCKET_H */
diff --git a/src/luasec/luasocket/wsocket.c b/src/luasec/luasocket/wsocket.c
new file mode 100644
index 0000000..8c7640e
--- /dev/null
+++ b/src/luasec/luasocket/wsocket.c
@@ -0,0 +1,429 @@
+/*=========================================================================*\
+* Socket compatibilization module for Win32
+* LuaSocket toolkit
+*
+* The penalty of calling select to avoid busy-wait is only paid when
+* the I/O call fail in the first place. 
+\*=========================================================================*/
+#include <string.h>
+
+#include "socket.h"
+
+/* WinSock doesn't have a strerror... */
+static const char *wstrerror(int err);
+
+/*-------------------------------------------------------------------------*\
+* Initializes module 
+\*-------------------------------------------------------------------------*/
+int socket_open(void) {
+    WSADATA wsaData;
+    WORD wVersionRequested = MAKEWORD(2, 0); 
+    int err = WSAStartup(wVersionRequested, &wsaData );
+    if (err != 0) return 0;
+    if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) &&
+        (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
+        WSACleanup();
+        return 0; 
+    }
+    return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Close module 
+\*-------------------------------------------------------------------------*/
+int socket_close(void) {
+    WSACleanup();
+    return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Wait for readable/writable/connected socket with timeout
+\*-------------------------------------------------------------------------*/
+int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
+    int ret;
+    fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
+    struct timeval tv, *tp = NULL;
+    double t;
+    if (timeout_iszero(tm)) return IO_TIMEOUT;  /* optimize timeout == 0 case */
+    if (sw & WAITFD_R) { 
+        FD_ZERO(&rfds); 
+        FD_SET(*ps, &rfds);
+        rp = &rfds; 
+    }
+    if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
+    if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
+    if ((t = timeout_get(tm)) >= 0.0) {
+        tv.tv_sec = (int) t;
+        tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6);
+        tp = &tv;
+    }
+    ret = select(0, rp, wp, ep, tp);
+    if (ret == -1) return WSAGetLastError();
+    if (ret == 0) return IO_TIMEOUT;
+    if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED;
+    return IO_DONE;
+}
+
+/*-------------------------------------------------------------------------*\
+* Select with int timeout in ms
+\*-------------------------------------------------------------------------*/
+int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, 
+        p_timeout tm) {
+    struct timeval tv; 
+    double t = timeout_get(tm);
+    tv.tv_sec = (int) t;
+    tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
+    if (n <= 0) {
+        Sleep((DWORD) (1000*t));
+        return 0;
+    } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL);
+}
+
+/*-------------------------------------------------------------------------*\
+* Close and inutilize socket
+\*-------------------------------------------------------------------------*/
+void socket_destroy(p_socket ps) {
+    if (*ps != SOCKET_INVALID) {
+        socket_setblocking(ps); /* close can take a long time on WIN32 */
+        closesocket(*ps);
+        *ps = SOCKET_INVALID;
+    }
+}
+
+/*-------------------------------------------------------------------------*\
+* 
+\*-------------------------------------------------------------------------*/
+void socket_shutdown(p_socket ps, int how) {
+    socket_setblocking(ps);
+    shutdown(*ps, how);
+    socket_setnonblocking(ps);
+}
+
+/*-------------------------------------------------------------------------*\
+* Creates and sets up a socket
+\*-------------------------------------------------------------------------*/
+int socket_create(p_socket ps, int domain, int type, int protocol) {
+    *ps = socket(domain, type, protocol);
+    if (*ps != SOCKET_INVALID) return IO_DONE;
+    else return WSAGetLastError();
+}
+
+/*-------------------------------------------------------------------------*\
+* Connects or returns error message
+\*-------------------------------------------------------------------------*/
+int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
+    int err;
+    /* don't call on closed socket */
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    /* ask system to connect */
+    if (connect(*ps, addr, len) == 0) return IO_DONE;
+    /* make sure the system is trying to connect */
+    err = WSAGetLastError();
+    if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err;
+    /* zero timeout case optimization */
+    if (timeout_iszero(tm)) return IO_TIMEOUT;
+    /* we wait until something happens */
+    err = socket_waitfd(ps, WAITFD_C, tm);
+    if (err == IO_CLOSED) {
+        int len = sizeof(err);
+        /* give windows time to set the error (yes, disgusting) */
+        Sleep(10);
+        /* find out why we failed */
+        getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); 
+        /* we KNOW there was an error. if 'why' is 0, we will return
+        * "unknown error", but it's not really our fault */
+        return err > 0? err: IO_UNKNOWN; 
+    } else return err;
+
+}
+
+/*-------------------------------------------------------------------------*\
+* Binds or returns error message
+\*-------------------------------------------------------------------------*/
+int socket_bind(p_socket ps, SA *addr, socklen_t len) {
+    int err = IO_DONE;
+    socket_setblocking(ps);
+    if (bind(*ps, addr, len) < 0) err = WSAGetLastError();
+    socket_setnonblocking(ps);
+    return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* 
+\*-------------------------------------------------------------------------*/
+int socket_listen(p_socket ps, int backlog) {
+    int err = IO_DONE;
+    socket_setblocking(ps);
+    if (listen(*ps, backlog) < 0) err = WSAGetLastError();
+    socket_setnonblocking(ps);
+    return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* Accept with timeout
+\*-------------------------------------------------------------------------*/
+int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, 
+        p_timeout tm) {
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        int err;
+        /* try to get client socket */
+        if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
+        /* find out why we failed */
+        err = WSAGetLastError(); 
+        /* if we failed because there was no connectoin, keep trying */
+        if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
+        /* call select to avoid busy wait */
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
+    } 
+}
+
+/*-------------------------------------------------------------------------*\
+* Send with timeout
+* On windows, if you try to send 10MB, the OS will buffer EVERYTHING 
+* this can take an awful lot of time and we will end up blocked. 
+* Therefore, whoever calls this function should not pass a huge buffer.
+\*-------------------------------------------------------------------------*/
+int socket_send(p_socket ps, const char *data, size_t count, 
+        size_t *sent, p_timeout tm)
+{
+    int err;
+    *sent = 0;
+    /* avoid making system calls on closed sockets */
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    /* loop until we send something or we give up on error */
+    for ( ;; ) {
+        /* try to send something */
+        int put = send(*ps, data, (int) count, 0);
+        /* if we sent something, we are done */
+        if (put > 0) {
+            *sent = put;
+            return IO_DONE;
+        }
+        /* deal with failure */
+        err = WSAGetLastError(); 
+        /* we can only proceed if there was no serious error */
+        if (err != WSAEWOULDBLOCK) return err;
+        /* avoid busy wait */
+        if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
+    } 
+}
+
+/*-------------------------------------------------------------------------*\
+* Sendto with timeout
+\*-------------------------------------------------------------------------*/
+int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, 
+        SA *addr, socklen_t len, p_timeout tm)
+{
+    int err;
+    *sent = 0;
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        int put = sendto(*ps, data, (int) count, 0, addr, len);
+        if (put > 0) {
+            *sent = put;
+            return IO_DONE;
+        }
+        err = WSAGetLastError(); 
+        if (err != WSAEWOULDBLOCK) return err;
+        if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
+    } 
+}
+
+/*-------------------------------------------------------------------------*\
+* Receive with timeout
+\*-------------------------------------------------------------------------*/
+int socket_recv(p_socket ps, char *data, size_t count, size_t *got, 
+        p_timeout tm) 
+{
+    int err, prev = IO_DONE;
+    *got = 0;
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        int taken = recv(*ps, data, (int) count, 0);
+        if (taken > 0) {
+            *got = taken;
+            return IO_DONE;
+        }
+        if (taken == 0) return IO_CLOSED;
+        err = WSAGetLastError();
+        /* On UDP, a connreset simply means the previous send failed. 
+         * So we try again. 
+         * On TCP, it means our socket is now useless, so the error passes. 
+         * (We will loop again, exiting because the same error will happen) */
+        if (err != WSAEWOULDBLOCK) {
+            if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
+            prev = err;
+        }
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
+    }
+}
+
+/*-------------------------------------------------------------------------*\
+* Recvfrom with timeout
+\*-------------------------------------------------------------------------*/
+int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, 
+        SA *addr, socklen_t *len, p_timeout tm) 
+{
+    int err, prev = IO_DONE;
+    *got = 0;
+    if (*ps == SOCKET_INVALID) return IO_CLOSED;
+    for ( ;; ) {
+        int taken = recvfrom(*ps, data, (int) count, 0, addr, len);
+        if (taken > 0) {
+            *got = taken;
+            return IO_DONE;
+        }
+        if (taken == 0) return IO_CLOSED;
+        err = WSAGetLastError();
+        /* On UDP, a connreset simply means the previous send failed. 
+         * So we try again. 
+         * On TCP, it means our socket is now useless, so the error passes.
+         * (We will loop again, exiting because the same error will happen) */
+        if (err != WSAEWOULDBLOCK) {
+            if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
+            prev = err;
+        }
+        if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
+    }
+}
+
+/*-------------------------------------------------------------------------*\
+* Put socket into blocking mode
+\*-------------------------------------------------------------------------*/
+void socket_setblocking(p_socket ps) {
+    u_long argp = 0;
+    ioctlsocket(*ps, FIONBIO, &argp);
+}
+
+/*-------------------------------------------------------------------------*\
+* Put socket into non-blocking mode
+\*-------------------------------------------------------------------------*/
+void socket_setnonblocking(p_socket ps) {
+    u_long argp = 1;
+    ioctlsocket(*ps, FIONBIO, &argp);
+}
+
+/*-------------------------------------------------------------------------*\
+* DNS helpers 
+\*-------------------------------------------------------------------------*/
+int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
+    *hp = gethostbyaddr(addr, len, AF_INET);
+    if (*hp) return IO_DONE;
+    else return WSAGetLastError();
+}
+
+int socket_gethostbyname(const char *addr, struct hostent **hp) {
+    *hp = gethostbyname(addr);
+    if (*hp) return IO_DONE;
+    else return  WSAGetLastError();
+}
+
+/*-------------------------------------------------------------------------*\
+* Error translation functions
+\*-------------------------------------------------------------------------*/
+const char *socket_hoststrerror(int err) {
+    if (err <= 0) return io_strerror(err);
+    switch (err) {
+        case WSAHOST_NOT_FOUND: return "host not found";
+        default: return wstrerror(err); 
+    }
+}
+
+const char *socket_strerror(int err) {
+    if (err <= 0) return io_strerror(err);
+    switch (err) {
+        case WSAEADDRINUSE: return "address already in use";
+        case WSAECONNREFUSED: return "connection refused";
+        case WSAEISCONN: return "already connected";
+        case WSAEACCES: return "permission denied";
+        case WSAECONNABORTED: return "closed";
+        case WSAECONNRESET: return "closed";
+        case WSAETIMEDOUT: return "timeout";
+        default: return wstrerror(err);
+    }
+}
+
+const char *socket_ioerror(p_socket ps, int err) {
+    (void) ps;
+    return socket_strerror(err);
+}
+
+static const char *wstrerror(int err) {
+    switch (err) {
+        case WSAEINTR: return "Interrupted function call";
+        case WSAEACCES: return "Permission denied";
+        case WSAEFAULT: return "Bad address";
+        case WSAEINVAL: return "Invalid argument";
+        case WSAEMFILE: return "Too many open files";
+        case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
+        case WSAEINPROGRESS: return "Operation now in progress";
+        case WSAEALREADY: return "Operation already in progress";
+        case WSAENOTSOCK: return "Socket operation on nonsocket";
+        case WSAEDESTADDRREQ: return "Destination address required";
+        case WSAEMSGSIZE: return "Message too long";
+        case WSAEPROTOTYPE: return "Protocol wrong type for socket";
+        case WSAENOPROTOOPT: return "Bad protocol option";
+        case WSAEPROTONOSUPPORT: return "Protocol not supported";
+        case WSAESOCKTNOSUPPORT: return "Socket type not supported";
+        case WSAEOPNOTSUPP: return "Operation not supported";
+        case WSAEPFNOSUPPORT: return "Protocol family not supported";
+        case WSAEAFNOSUPPORT: 
+            return "Address family not supported by protocol family"; 
+        case WSAEADDRINUSE: return "Address already in use";
+        case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
+        case WSAENETDOWN: return "Network is down";
+        case WSAENETUNREACH: return "Network is unreachable";
+        case WSAENETRESET: return "Network dropped connection on reset";
+        case WSAECONNABORTED: return "Software caused connection abort";
+        case WSAECONNRESET: return "Connection reset by peer";
+        case WSAENOBUFS: return "No buffer space available";
+        case WSAEISCONN: return "Socket is already connected";
+        case WSAENOTCONN: return "Socket is not connected";
+        case WSAESHUTDOWN: return "Cannot send after socket shutdown";
+        case WSAETIMEDOUT: return "Connection timed out";
+        case WSAECONNREFUSED: return "Connection refused";
+        case WSAEHOSTDOWN: return "Host is down";
+        case WSAEHOSTUNREACH: return "No route to host";
+        case WSAEPROCLIM: return "Too many processes";
+        case WSASYSNOTREADY: return "Network subsystem is unavailable";
+        case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
+        case WSANOTINITIALISED: 
+            return "Successful WSAStartup not yet performed";
+        case WSAEDISCON: return "Graceful shutdown in progress";
+        case WSAHOST_NOT_FOUND: return "Host not found";
+        case WSATRY_AGAIN: return "Nonauthoritative host not found";
+        case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; 
+        case WSANO_DATA: return "Valid name, no data record of requested type";
+        default: return "Unknown error";
+    }
+}
+
+const char *socket_gaistrerror(int err) {
+    if (err == 0) return NULL; 
+    switch (err) {
+        case EAI_AGAIN: return "temporary failure in name resolution";
+        case EAI_BADFLAGS: return "invalid value for ai_flags";
+#ifdef EAI_BADHINTS
+        case EAI_BADHINTS: return "invalid value for hints";
+#endif
+        case EAI_FAIL: return "non-recoverable failure in name resolution";
+        case EAI_FAMILY: return "ai_family not supported";
+        case EAI_MEMORY: return "memory allocation failure";
+        case EAI_NONAME: 
+            return "host or service not provided, or not known";
+#ifdef EAI_OVERFLOW
+        case EAI_OVERFLOW: return "argument buffer overflow";
+#endif
+#ifdef EAI_PROTOCOL
+        case EAI_PROTOCOL: return "resolved protocol is unknown";
+#endif
+        case EAI_SERVICE: return "service not supported for socket type";
+        case EAI_SOCKTYPE: return "ai_socktype not supported";
+#ifdef EAI_SYSTEM
+        case EAI_SYSTEM: return strerror(errno); 
+#endif
+        default: return gai_strerror(err);
+    }
+}
+
diff --git a/src/luasec/luasocket/wsocket.h b/src/luasec/luasocket/wsocket.h
new file mode 100644
index 0000000..c5a4b1c
--- /dev/null
+++ b/src/luasec/luasocket/wsocket.h
@@ -0,0 +1,38 @@
+#ifndef WSOCKET_H
+#define WSOCKET_H
+/*=========================================================================*\
+* Socket compatibilization module for Win32
+* LuaSocket toolkit
+\*=========================================================================*/
+
+/*=========================================================================*\
+* WinSock include files
+\*=========================================================================*/
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+typedef int socklen_t;
+typedef SOCKADDR_STORAGE t_sockaddr_storage;
+typedef SOCKET t_socket;
+typedef t_socket *p_socket;
+
+#define WAITFD_R        1
+#define WAITFD_W        2
+#define WAITFD_E        4
+#define WAITFD_C        (WAITFD_E|WAITFD_W)
+
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 27
+#endif
+
+#define SOCKET_INVALID (INVALID_SOCKET)
+
+#ifndef SO_REUSEPORT
+#define SO_REUSEPORT SO_REUSEADDR
+#endif
+
+#ifndef AI_NUMERICSERV
+#define AI_NUMERICSERV (0)
+#endif
+
+#endif /* WSOCKET_H */