2 * nixio - Linux I/O library for lua
4 * Copyright (C) 2009 Steven Barth <steven@midlink.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include "nixio-tls.h"
23 static int nixio__tls_sock_perror(lua_State *L, SSL *sock, int code) {
25 lua_pushinteger(L, SSL_get_error(sock, code));
29 static int nixio__tls_sock_pstatus(lua_State *L, SSL *sock, int code) {
31 lua_pushboolean(L, 1);
34 return nixio__tls_sock_perror(L, sock, code);
38 static SSL* nixio__checktlssock(lua_State *L) {
39 if (lua_istable(L, 1)) {
40 lua_getfield(L, 1, "connection");
43 nixio_tls_sock *sock = luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META);
44 luaL_argcheck(L, sock->socket, 1, "invalid context");
49 #define nixio_tls__check_connected(L) ;
51 #define nixio_tls__set_connected(L, val) ;
53 #define nixio_tls__check_connected(L) \
54 nixio_tls_sock *ctsock = luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META); \
55 if (!ctsock->connected) { \
57 lua_pushinteger(L, 1); \
61 #define nixio_tls__set_connected(L, val) \
62 ((nixio_tls_sock*)luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META))->connected = val;
63 #endif /* WITH_AXTLS */
65 static int nixio_tls_sock_recv(lua_State *L) {
66 SSL *sock = nixio__checktlssock(L);
67 nixio_tls__check_connected(L);
68 uint req = luaL_checkinteger(L, 2);
70 luaL_argcheck(L, req >= 0, 2, "out of range");
72 /* We limit the readsize to NIXIO_BUFFERSIZE */
73 req = (req > NIXIO_BUFFERSIZE) ? NIXIO_BUFFERSIZE : req;
77 char buffer[NIXIO_BUFFERSIZE];
78 int readc = SSL_read(sock, buffer, req);
81 return nixio__tls_sock_pstatus(L, sock, readc);
83 lua_pushlstring(L, buffer, readc);
90 lua_pushliteral(L, "");
94 nixio_tls_sock *t = lua_touserdata(L, 1);
96 /* AXTLS doesn't handle buffering for us, so we have to hack around*/
97 if (req < t->pbufsiz) {
98 lua_pushlstring(L, t->pbufpos, req);
106 /* while handshake pending */
107 while ((axread = ssl_read(sock, &axbuf)) == SSL_OK);
110 lua_pushlstring(L, t->pbufpos, t->pbufsiz);
114 /* There is an error */
116 t->pbuffer = t->pbufpos = NULL;
118 if (axread != SSL_ERROR_CONN_LOST) {
120 return nixio__tls_sock_perror(L, sock, axread);
123 lua_pushliteral(L, "");
129 int stillwant = req - t->pbufsiz;
130 if (stillwant < axread) {
131 /* we got more data than we need */
132 lua_pushlstring(L, (char *)axbuf, stillwant);
137 /* remaining data goes into the buffer */
138 t->pbufpos = t->pbuffer;
139 t->pbufsiz = axread - stillwant;
140 t->pbuffer = realloc(t->pbuffer, t->pbufsiz);
145 return luaL_error(L, "out of memory");
148 t->pbufpos = t->pbuffer;
149 memcpy(t->pbufpos, axbuf + stillwant, t->pbufsiz);
151 lua_pushlstring(L, (char *)axbuf, axread);
158 t->pbuffer = t->pbufpos = NULL;
165 #endif /* WITH_AXTLS */
169 static int nixio_tls_sock_send(lua_State *L) {
170 SSL *sock = nixio__checktlssock(L);
171 nixio_tls__check_connected(L);
174 const char *data = luaL_checklstring(L, 2, &len);
176 if (lua_gettop(L) > 2) {
177 int offset = luaL_optint(L, 3, 0);
187 unsigned int wlen = luaL_optint(L, 4, len);
193 sent = SSL_write(sock, data, len);
195 lua_pushinteger(L, sent);
198 return nixio__tls_sock_pstatus(L, sock, sent);
202 static int nixio_tls_sock_accept(lua_State *L) {
203 SSL *sock = nixio__checktlssock(L);
204 const int stat = SSL_accept(sock);
205 nixio_tls__set_connected(L, stat == 1);
206 return nixio__tls_sock_pstatus(L, sock, stat);
209 static int nixio_tls_sock_connect(lua_State *L) {
210 SSL *sock = nixio__checktlssock(L);
211 const int stat = SSL_connect(sock);
212 nixio_tls__set_connected(L, stat == 1);
213 return nixio__tls_sock_pstatus(L, sock, stat);
216 static int nixio_tls_sock_shutdown(lua_State *L) {
217 SSL *sock = nixio__checktlssock(L);
218 nixio_tls__set_connected(L, 0);
219 return nixio__tls_sock_pstatus(L, sock, SSL_shutdown(sock));
222 static int nixio_tls_sock__gc(lua_State *L) {
223 nixio_tls_sock *sock = luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META);
225 SSL_free(sock->socket);
234 static int nixio_tls_sock__tostring(lua_State *L) {
235 SSL *sock = nixio__checktlssock(L);
236 lua_pushfstring(L, "nixio TLS connection: %p", sock);
241 /* ctx function table */
242 static const luaL_reg M[] = {
243 {"recv", nixio_tls_sock_recv},
244 {"send", nixio_tls_sock_send},
245 {"read", nixio_tls_sock_recv},
246 {"write", nixio_tls_sock_send},
247 {"accept", nixio_tls_sock_accept},
248 {"connect", nixio_tls_sock_connect},
249 {"shutdown", nixio_tls_sock_shutdown},
250 {"__gc", nixio_tls_sock__gc},
251 {"__tostring", nixio_tls_sock__tostring},
256 void nixio_open_tls_socket(lua_State *L) {
257 /* create socket metatable */
258 luaL_newmetatable(L, NIXIO_TLS_SOCK_META);
259 luaL_register(L, NULL, M);
260 lua_pushvalue(L, -1);
261 lua_setfield(L, -2, "__index");
262 lua_setfield(L, -2, "meta_tls_socket");