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");