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.
22 #ifndef WITHOUT_OPENSSL
23 #include <openssl/ssl.h>
26 static int nixio__tls_sock_perror(lua_State *L, SSL *sock, int code) {
28 lua_pushinteger(L, code);
29 lua_pushinteger(L, SSL_get_error(sock, code));
33 static int nixio__tls_sock_pstatus(lua_State *L, SSL *sock, int code) {
35 lua_pushboolean(L, 1);
38 return nixio__tls_sock_perror(L, sock, code);
42 static SSL* nixio__checktlssock(lua_State *L) {
43 SSL **sock = (SSL **)luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META);
44 luaL_argcheck(L, *sock, 1, "invalid context");
48 static int nixio_tls_sock_recv(lua_State *L) {
49 SSL *sock = nixio__checktlssock(L);
50 int req = luaL_checkinteger(L, 2);
52 luaL_argcheck(L, req >= 0, 2, "out of range");
54 /* We limit the readsize to NIXIO_BUFFERSIZE */
55 req = (req > NIXIO_BUFFERSIZE) ? NIXIO_BUFFERSIZE : req;
57 char buffer[NIXIO_BUFFERSIZE];
58 int readc = SSL_read(sock, buffer, req);
61 return nixio__tls_sock_pstatus(L, sock, readc);
63 lua_pushlstring(L, buffer, readc);
68 lua_pushliteral(L, "");
72 /* AXTLS doesn't handle buffering for us, so we have to hack around*/
74 lua_getmetatable(L, 1);
75 lua_getfield(L, -1, "_axbuffer");
77 if (lua_isstring(L, -1)) {
78 buflen = lua_objlen(L, -1);
82 const char *axbuf = lua_tostring(L, -1);
83 lua_pushlstring(L, axbuf, req);
84 lua_pushlstring(L, axbuf + req, buflen - req);
85 lua_setfield(L, -4, "_axbuffer");
88 if (!lua_isstring(L, -1)) {
90 lua_pushliteral(L, "");
96 /* while handshake pending */
97 while ((axread = ssl_read(sock, (uint8_t**)&axbuf)) == SSL_OK);
100 /* There is an error */
102 if (axread != SSL_ERROR_CONN_LOST) {
103 lua_pushliteral(L, "");
104 lua_setfield(L, -3, "_axbuffer");
105 return nixio__tls_sock_perror(L, sock, axread);
107 lua_pushliteral(L, "");
110 int stillwant = req - buflen;
111 if (stillwant < axread) {
112 /* we got more data than we need */
113 lua_pushlstring(L, axbuf, stillwant);
116 /* remaining data goes into the buffer */
117 lua_pushlstring(L, axbuf + stillwant, axread - stillwant);
119 lua_pushlstring(L, axbuf, axread);
121 lua_pushliteral(L, "");
124 lua_setfield(L, -3, "_axbuffer");
131 static int nixio_tls_sock_send(lua_State *L) {
132 SSL *sock = nixio__checktlssock(L);
135 const char *data = luaL_checklstring(L, 2, &len);
136 sent = SSL_write(sock, data, len);
138 lua_pushinteger(L, sent);
141 return nixio__tls_sock_pstatus(L, sock, len);
145 static int nixio_tls_sock_accept(lua_State *L) {
146 SSL *sock = nixio__checktlssock(L);
147 return nixio__tls_sock_pstatus(L, sock, SSL_accept(sock));
150 static int nixio_tls_sock_connect(lua_State *L) {
151 SSL *sock = nixio__checktlssock(L);
152 return nixio__tls_sock_pstatus(L, sock, SSL_connect(sock));
155 static int nixio_tls_sock_shutdown(lua_State *L) {
156 SSL *sock = nixio__checktlssock(L);
157 return nixio__tls_sock_pstatus(L, sock, SSL_shutdown(sock));
160 static int nixio_tls_sock__gc(lua_State *L) {
161 SSL **sock = (SSL **)luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META);
169 static int nixio_tls_sock__tostring(lua_State *L) {
170 SSL *sock = nixio__checktlssock(L);
171 lua_pushfstring(L, "nixio TLS socket: %p", sock);
176 /* ctx function table */
177 static const luaL_reg M[] = {
178 {"recv", nixio_tls_sock_recv},
179 {"send", nixio_tls_sock_send},
180 {"accept", nixio_tls_sock_accept},
181 {"connect", nixio_tls_sock_connect},
182 {"shutdown", nixio_tls_sock_shutdown},
183 {"__gc", nixio_tls_sock__gc},
184 {"__tostring", nixio_tls_sock__tostring},
189 void nixio_open_tls_socket(lua_State *L) {
190 /* create socket metatable */
191 luaL_newmetatable(L, NIXIO_TLS_SOCK_META);
192 luaL_register(L, NULL, M);
193 lua_pushvalue(L, -1);
194 lua_setfield(L, -2, "__index");
195 lua_setfield(L, -2, "tls_socket_meta");