Hello,
I’m trying to do a SSL connection like client but i didn’t find any documentation Could anyone say me the name of the SSL guide and where can I download it??
Searching in google I found this code: (I don’t know if it works because i don’t know how it works if I don’t have documentation )
#include "https.h"
#include "wip.h"
#include <assert.h>
#include "oatlua.h"
#ifdef __Security_PLUGIN_VERSION__
#include "wip_ssl.h"
#endif
/* State automaton:
* - initial state = IDLE
* - when a request is made from Lua, a TCP connection is requested,
* state = OPENING;
* - when the connection is accepted (WIP_CEV_OPEN), we start sending
* the request to the peer, state = SENDING;
* - when the whole body has been sent, we expect to get the response,
* state = RECEIVING;
* - when the response is complete, we go back to state = IDLE.
* We're then ready to perform another HTTP request.
*
* If anything goes wrong at any point, we revert to STATE = IDLE.
*
* The algorithm is not reentrant: it's the Lua wrapper's responsibility
* to ensure that two requests don't mix with each other.
*/
enum { IDLE, OPENING, SENDING, RECEIVING } state;
/* TCP channel used for the request. */
wip_channel_t channel = NULL;
/* Try to reuse last SSL session. */
#ifdef __Security_PLUGIN_VERSION__
wip_SSLSession_t lastSSLSession = NULL;
#endif
/* How many bytes of the request have already been sent. */
int send_offset = 0;
/* In addition to the C globals, the system relies on the "https_body"
* field in Lua's registry.
*
* - In OPENING and SENDING states, it contains the request to send,
* as a string.
* - In RECEIVING state, it contains the partial response,
* as a list of strings.
* - In IDLE state, it's left as nil.
*/
/* Signal an error (the signal argument is popped from top of stack),
* revert to IDLE state,
* free any taken resource.
*/
static void error( lua_State *L) {
const char *msg = luaL_checkstring(L, -1);
lua_pushnil( L);
lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
state = IDLE;
wip_close( channel);
luaW_signal_str( L, "https", "error", LUAW_SIG_STRING, msg, LUAW_SIG_END);
}
/* React to WIP events */
static void evh_request( wip_event_t *ev, void *ctx) {
lua_State *L = GlobalL;
switch( ev->kind) {
case WIP_CEV_OPEN:
assert( OPENING == state);
state = SENDING;
send_offset = 0;
# ifdef __Security_PLUGIN_VERSION__
if( wip_hasType( ev->channel, WIP_CTYPE_SSL)) {
if( lastSSLSession) wip_SSLReleaseSession( lastSSLSession);
lastSSLSession = wip_SSLGetSession( ev->channel);
}
# endif
break;
case WIP_CEV_ERROR:
lua_pushinteger( L, ev->content.error.errnum);
error( L);
break;
case WIP_CEV_READ: {
if( RECEIVING != state) {
luaW_debug( "https", "ERROR", "Peer doesn't respect HTTP protocol");
lua_pushstring( L, "protocol violation");
error( L);
} else {
# define READ_BUFFER_SIZE 256
int read;
lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
if( ! lua_istable( L, -1)) {
luaW_debug( "https", "ERROR", "https_body must be a table when receiving");
lua_pushstring( L, "internal inconsistency");
error( L);
} else do { // https_body
char buffer [READ_BUFFER_SIZE];
int n_received_segments = lua_objlen( L, -1);
read = wip_read( channel, buffer, sizeof( buffer));
luaW_debug("https", "DEBUG", "Read %d bytes", read);
if( read > 0) { // https_body
lua_pushinteger( L, ++n_received_segments); // https_body, n
lua_pushlstring( L, buffer, read); // https_body, n, segment
lua_settable( L, -3); // https_body
}
} while( READ_BUFFER_SIZE == read);
lua_pop( L, 1);
luaW_signal_str( L, "https", "data", LUAW_SIG_END); // -
# undef READ_BUFFER_SIZE
}
break;
}
case WIP_CEV_WRITE: {
const char *buffer;
size_t len, to_send;
lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
buffer = luaL_checklstring( L, -1, & len);
to_send = len - send_offset;
if( to_send > 0) {
size_t sent = wip_write( channel, (void*) (buffer + send_offset), to_send);
if( sent>0) {
to_send -= sent;
send_offset += sent;
}
}
if( 0 == to_send) {
lua_newtable( L); lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
state = RECEIVING;
}
break;
}
case WIP_CEV_PEER_CLOSE: {
lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
//lua_pushnil( L);
//lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
if( state == RECEIVING && lua_istable( L, -1)) {
luaW_signal_str( L, "https", "response", LUAW_SIG_END);
} else {
luaW_debug( "https", "ERROR", "Closed before sending response");
}
state = IDLE;
wip_close( channel);
break;
}
default:
luaW_debug( "https", "WARNING", "Unexpected TCP event %d", ev->kind);
}
}
/* Signal the the channel, the last resource being kept, has been released. */
static void finalizer( void *ctx) {
luaW_signal_str( GlobalL, "https", "released", 0);
}
/* Receive a request from Lua. Parameters:
* - the server name
* - the server port
* - the complete request to send, as a string
*
* Produce no result, the request's response will eventually be broadcast as a signal.
*/
static int api_request( lua_State *L) {
# define CHECK( test, msg) \
if( ! (test)){ lua_pushnil( L); lua_pushstring( L, msg); return 2; }
const char *protocol = luaL_checkstring( L, 1);
const char *host = luaL_checkstring( L, 2);
int port = luaL_checkinteger( L, 3);
(void) luaL_checkstring( L, 4); // Request body
CHECK( state == IDLE, "request pending");
/* Save body in the registry, for future reference
* and to protect against garbage collection. */
lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
if( ! strcmp( "https", protocol)) {
# ifdef __Security_PLUGIN_VERSION__
if( lastSSLSession) {
channel = wip_SSLClientCreateOpts( (ascii*) host, port, evh_request, NULL,
WIP_COPT_SESSION, lastSSLSession,
WIP_COPT_FINALIZER, finalizer,
WIP_COPT_END);
} else {
channel = wip_SSLClientCreateOpts( (ascii*) host, port, evh_request, NULL,
WIP_COPT_FINALIZER, finalizer,
WIP_COPT_END);
}
# else
CHECK( 0, "HTTPS protocol not supported, recompile with security plugin.");
# endif
} else {
channel = wip_TCPClientCreateOpts( (ascii*) host, port, evh_request, NULL,
WIP_COPT_FINALIZER, finalizer,
WIP_COPT_END);
}
CHECK( channel, "cannot open channel");
state = OPENING;
lua_pushboolean( L, 1);
return 1;
# undef CHECK
}
static int api_abort( lua_State *L) {
wip_close( channel);
state = IDLE;
lua_pushnil( L);
lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
return 0;
}
static int api_getbody( lua_State *L) {
lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
return 1;
}
#ifdef __Security_PLUGIN_VERSION__
static int api_sslinit( lua_State *L) {
const char *certificate = luaL_checkstring( L, 1);
const char *key = luaL_checkstring( L, 2);
const char *authority = luaL_optstring( L, 3, certificate);
const char *verifystr = luaL_optstring( L, 4, "always");
int verify;
if( ! strcmp( verifystr, "once")) verify = WIP_SSL_ONCE;
else if( ! strcmp( verifystr, "never")) verify = WIP_SSL_NEVER;
else verify = WIP_SSL_ALWAYS;
int r = wip_SSLInitOpts(
WIP_COPT_CERT_AUTHORITY, authority,
WIP_COPT_CERT, certificate,
WIP_COPT_PRIVATE_KEY, key,
WIP_COPT_VERIFY, verify,
//WIP_COPT_KEY, WIP_SSL_ALL,
WIP_COPT_AUTHENTICATION, WIP_SSL_RSA,
WIP_COPT_ENCRYPTION, WIP_SSL_3DES,
//WIP_COPT_VERSION, WIP_SSL_ALL,
WIP_COPT_END);
if( 0 == r) { lua_pushboolean( L, 1); return 1; }
else { lua_pushnil( L); lua_pushinteger( L, r); return 2; }
}
#endif
/* Register the functions. */
int luaopen_https_core( lua_State *L) {
lua_getglobal( L, "internal");
# define REGISTER( name) \
lua_pushcfunction( L, api_##name); lua_setfield( L, -2, "https_"#name)
REGISTER( request);
REGISTER( abort);
REGISTER( getbody);
# ifdef __Security_PLUGIN_VERSION__
REGISTER( sslinit);
# endif
# undef REGISTER
lua_pop( L, 1);
return 0;
}