sq_axtls.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4. #include "squirrel.h"
  5. #include <stdlib.h> /* for malloc */
  6. #include <assert.h> /* for a few sanity tests */
  7. #define GET_INT(idx, var) int var; sq_getinteger(sqvm, idx, &var)
  8. #define GET_STR(idx, var) const SQChar *var; sq_getstring(sqvm, idx, &var)
  9. #include "ssl.h"
  10. #define SQ_NETLIBNAME "axtlsl"
  11. typedef struct {
  12. SSL_CTX *ptr;
  13. } SSL_CTX_ptr;
  14. static const char *SSL_CTX_metaTag = "sq_axtls";
  15. static SSL_CTX_ptr *sq_ssl_get_ctx(HSQUIRRELVM sqvm, int index) {
  16. SSL_CTX_ptr *ssl_ctx_ptr = (SSL_CTX_ptr*)luaL_checkudata(sqvm, index, SSL_CTX_metaTag);
  17. if (ssl_ctx_ptr == NULL)
  18. luaL_argerror(sqvm, index, "bad SSL CONTEXT");
  19. if (ssl_ctx_ptr->ptr == NULL)
  20. luaL_argerror(sqvm, index, "SSL CONTEXT has NULL value");
  21. return ssl_ctx_ptr;
  22. }
  23. typedef struct {
  24. SSL *ptr;
  25. int free_ptr_on_gc;
  26. } SSL_ptr;
  27. static const char *SSL_metaTag = "axtls.ssl";
  28. static SSL_ptr *sq_ssl_get_ssl(HSQUIRRELVM sqvm, int index) {
  29. SSL_ptr *ssl_ptr = (SSL_ptr*)luaL_checkudata(sqvm, index, SSL_metaTag);
  30. if (ssl_ptr == NULL)
  31. luaL_argerror(sqvm, index, "bad SSL");
  32. if (ssl_ptr->ptr == NULL)
  33. luaL_argerror(sqvm, index, "SSL has NULL value");
  34. return ssl_ptr;
  35. }
  36. static int sq_ssl_ctx_new(HSQUIRRELVM sqvm){
  37. int options = sq_getinteger(sqvm, 1);
  38. int num_sessions = sq_getinteger(sqvm, 2);
  39. SSL_CTX *ssl_ctx = ssl_ctx_new(options, num_sessions);
  40. if(ssl_ctx) {
  41. SSL_CTX_ptr *ssl_ctx_ptr = (SSL_CTX_ptr*)sq_newuserdata(sqvm, sizeof(SSL_CTX_ptr));
  42. ssl_ctx_ptr->ptr = ssl_ctx;
  43. luaL_newmetatable(sqvm, SSL_CTX_metaTag);
  44. sq_setmetatable(sqvm, -2); /* set metatable */
  45. } else sq_pushnil(L);
  46. return 1;
  47. }
  48. static int sq_ssl_ctx_free(HSQUIRRELVM sqvm){
  49. SSL_CTX_ptr *ssl_ctx_ptr = sq_ssl_get_ctx(sqvm, 1);
  50. if(ssl_ctx_ptr->ptr){
  51. ssl_ctx_free(ssl_ctx_ptr->ptr);
  52. ssl_ctx_ptr->ptr = NULL;
  53. }
  54. return 0;
  55. }
  56. static int sq_ssl_server_new(HSQUIRRELVM sqvm){
  57. SSL_CTX_ptr *ssl_ctx_ptr = sq_ssl_get_ctx(sqvm, 1);
  58. int client_fd = sq_getinteger(sqvm, 2);
  59. SSL *ssl = ssl_server_new(ssl_ctx_ptr->ptr, client_fd);
  60. if(ssl) {
  61. SSL_ptr *ssl_ptr = (SSL_ptr*)sq_newuserdata(sqvm, sizeof(SSL_ptr));
  62. ssl_ptr->ptr = ssl;
  63. ssl_ptr->free_ptr_on_gc = 1;
  64. luaL_newmetatable(sqvm, SSL_metaTag);
  65. sq_setmetatable(sqvm, -2); /* set metatable */
  66. } else sq_pushnil(L);
  67. return 1;
  68. }
  69. static int sq_ssl_client_new(HSQUIRRELVM sqvm){
  70. SSL_CTX_ptr *ssl_ctx_ptr = sq_ssl_get_ctx(sqvm, 1);
  71. int client_fd = sq_getinteger(sqvm, 2);
  72. uint8_t *session_id = (uint8_t *)luaL_optstring(sqvm, 3, NULL);
  73. uint8_t sess_id_size= luaL_optint(sqvm, 4, 0);
  74. SSL *ssl = ssl_client_new(ssl_ctx_ptr->ptr, client_fd, session_id, sess_id_size);
  75. if(ssl) {
  76. SSL_ptr *ssl_ptr = (SSL_ptr*)sq_newuserdata(sqvm, sizeof(SSL_ptr));
  77. ssl_ptr->ptr = ssl;
  78. ssl_ptr->free_ptr_on_gc = 1;
  79. luaL_newmetatable(sqvm, SSL_metaTag);
  80. sq_setmetatable(sqvm, -2); /* set metatable */
  81. } else sq_pushnil(L);
  82. return 1;
  83. }
  84. static int sq_ssl_free(HSQUIRRELVM sqvm){
  85. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  86. if(ssl_ptr->ptr && ssl_ptr->free_ptr_on_gc){
  87. ssl_free(ssl_ptr->ptr);
  88. ssl_ptr->ptr = NULL;
  89. }
  90. return 0;
  91. }
  92. static int sq_ssl_read(HSQUIRRELVM sqvm){
  93. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  94. uint8_t *in_data;
  95. int result = ssl_read(ssl_ptr->ptr, &in_data);
  96. sq_pushinteger(sqvm, result);
  97. int return_params = 1;
  98. if (result > SSL_OK) {
  99. sq_pushlstring(sqvm, (char *)in_data, result);
  100. return_params++;
  101. }
  102. return return_params;
  103. }
  104. static int sq_ssl_write(HSQUIRRELVM sqvm){
  105. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  106. uint8_t *out_data;
  107. sq_getstring(sqvm, 2, &out_data);
  108. int out_len;
  109. if(sq_gettop(sqvm) > 2) sq_getinteger(sqvm, 3, &out_len);
  110. else out_len = sq_getsize(sqvm, 2);
  111. sq_pushinteger(sqvm, ssl_write(ssl_ptr->ptr, out_data, out_len));
  112. return 1;
  113. }
  114. static int sq_ssl_find(HSQUIRRELVM sqvm){
  115. SSL_CTX_ptr *ssl_ctx_ptr = sq_ssl_get_ctx(sqvm, 1);
  116. GET_INT(2, client_fd);
  117. SSL *ssl = ssl_find(ssl_ctx_ptr->ptr, client_fd);
  118. if(ssl){
  119. SSL_ptr *ssl_ptr = (SSL_ptr*)sq_newuserdata(sqvm, sizeof(SSL_ptr));
  120. ssl_ptr->ptr = ssl;
  121. //we don't want to free this SSL when collecting garbage
  122. ssl_ptr->free_ptr_on_gc = 0;
  123. luaL_newmetatable(sqvm, SSL_metaTag);
  124. sq_setmetatable(sqvm, -2); /* set metatable */
  125. } else sq_pushnil(L);
  126. return 1;
  127. }
  128. static int sq_ssl_get_session_id(HSQUIRRELVM sqvm){
  129. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  130. const uint8_t * result = ssl_get_session_id(ssl_ptr->ptr);
  131. sq_pushlstring(sqvm, (char *)result, ssl_get_session_id_size(ssl_ptr->ptr));
  132. return 1;
  133. }
  134. static int sq_ssl_get_session_id_size(HSQUIRRELVM sqvm){
  135. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  136. uint8_t result = ssl_get_session_id_size(ssl_ptr->ptr);
  137. sq_pushinteger(sqvm, result);
  138. return 1;
  139. }
  140. static int sq_ssl_get_cipher_id(HSQUIRRELVM sqvm){
  141. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  142. uint8_t result = ssl_get_cipher_id(ssl_ptr->ptr);
  143. sq_pushinteger(sqvm, result);
  144. return 1;
  145. }
  146. static int sq_ssl_handshake_status(HSQUIRRELVM sqvm){
  147. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  148. int result = ssl_handshake_status(ssl_ptr->ptr);
  149. sq_pushinteger(sqvm, result);
  150. return 1;
  151. }
  152. static int sq_ssl_get_config(HSQUIRRELVM sqvm){
  153. GET_INT(1, info);
  154. sq_pushinteger(sqvm, ssl_get_config(info));
  155. return 1;
  156. }
  157. static int sq_ssl_display_error(HSQUIRRELVM sqvm){
  158. GET_INT(1, error);
  159. ssl_display_error(error);
  160. return 0;
  161. }
  162. static int sq_ssl_verify_cert(HSQUIRRELVM sqvm){
  163. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  164. int result = ssl_verify_cert(ssl_ptr->ptr);
  165. sq_pushinteger(sqvm, result);
  166. return 1;
  167. }
  168. static int sq_ssl_get_cert_dn(HSQUIRRELVM sqvm){
  169. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  170. GET_INT(2, component);
  171. const char* result = ssl_get_cert_dn(ssl_ptr->ptr, component);
  172. sq_pushstring(sqvm, result);
  173. return 1;
  174. }
  175. static int sq_ssl_get_cert_subject_alt_dnsname(HSQUIRRELVM sqvm){
  176. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  177. GET_INT(2, dnsindex);
  178. const char* result = ssl_get_cert_subject_alt_dnsname(ssl_ptr->ptr, dnsindex);
  179. sq_pushstring(sqvm, result);
  180. return 1;
  181. }
  182. static int sq_ssl_renegotiate(HSQUIRRELVM sqvm){
  183. SSL_ptr *ssl_ptr = sq_ssl_get_ssl(sqvm, 1);
  184. int result = ssl_renegotiate(ssl_ptr->ptr);
  185. sq_pushinteger(sqvm, result);
  186. return 1;
  187. }
  188. static int sq_ssl_obj_load(HSQUIRRELVM sqvm){
  189. SSL_CTX_ptr *ssl_ctx_ptr = sq_ssl_get_ctx(sqvm, 1);
  190. GET_INT(2, obj_type);
  191. GET_STR(3, filename);
  192. GET_STR(4, password);
  193. int result = ssl_obj_load(ssl_ctx_ptr->ptr, obj_type,filename,password);
  194. sq_pushinteger(sqvm, result);
  195. return 1;
  196. }
  197. static int sq_ssl_obj_memory_load(HSQUIRRELVM sqvm){
  198. SSL_CTX_ptr *ssl_ctx_ptr = sq_ssl_get_ctx(sqvm, 1);
  199. GET_INT(2, obj_type);
  200. uint8_t *data;
  201. sq_getstring(sqvm, 3, &data);
  202. GET_INT(4, data_len);
  203. GET_STR(5, password);
  204. int result = ssl_obj_memory_load(ssl_ctx_ptr->ptr, obj_type,data,data_len, password);
  205. sq_pushinteger(sqvm, result);
  206. return 1;
  207. }
  208. static int sq_ssl_version(HSQUIRRELVM sqvm){
  209. sq_pushstring(sqvm,(const char*)ssl_version());
  210. return 1;
  211. }
  212. static SQInteger ssl_ctx_release_hook(SQUserPointer p, SQInteger size)
  213. {
  214. ssl_ctx_free((SSL_CTX *)p);
  215. return 1;
  216. }
  217. static SQInteger ssl_ctx_constructor(HSQUIRRELVM sqvm)
  218. {
  219. SQInteger options, num_sessions;
  220. sq_getinteger(sqvm, 2, &options);
  221. sq_getinteger(sqvm, 3, &num_sessions);
  222. SSL_CTX *ssl_ctx = ssl_ctx_new(options, num_sessions);
  223. if(!ssl_ctx)
  224. return sq_throwerror(sqvm, _SC("Could'nt create an ssl context."))
  225. sq_setinstanceup(sqvm, 1, ssl_ctx);
  226. RELEASE_HOOK(sq_setreleasehook(sqvm,1, ssl_ctx_release_hook));
  227. return 1;
  228. }
  229. static SQInteger ssl_release_hook(SQUserPointer p, SQInteger size)
  230. {
  231. ssl_free((SSL *)p);
  232. return 1;
  233. }
  234. static SQInteger ssl_constructor(HSQUIRRELVM sqvm)
  235. {
  236. SQInteger socket_fd, num_sessions;
  237. sq_getinteger(sqvm, 2, &options);
  238. sq_getinteger(sqvm, 3, &num_sessions);
  239. SSL *ssl = ssl_new(options, num_sessions);
  240. if(!ssl)
  241. return sq_throwerror(sqvm, _SC("Could'nt create an ssl server/client."))
  242. sq_setinstanceup(sqvm, 1, ssl);
  243. RELEASE_HOOK(sq_setreleasehook(sqvm,1, ssl_release_hook));
  244. return 1;
  245. }
  246. #define _DECL_FL_FUNC(name,nparams,pmask) {_SC(#name),sq_##name,nparams,pmask}
  247. static SQRegFunction ssl_ctx_obj_funcs[]={
  248. _DECL_FL_BOX_FUNC(constructor,3,_SC("xii")),
  249. _DECL_FL_FUNC(server_new,2,_SC("xx")),
  250. _DECL_FL_FUNC(client_new,2,_SC("xxii")),
  251. _DECL_FL_FUNC(find,2,_SC("tu")),
  252. _DECL_FL_FUNC(get_session_id,2,_SC("tu")),
  253. _DECL_FL_FUNC(get_session_id_size,2,_SC("tu")),
  254. _DECL_FL_FUNC(get_cipher_id,2,_SC("tu")),
  255. _DECL_FL_FUNC(handshake_status,2,_SC("tu")),
  256. _DECL_FL_FUNC(get_config,2,_SC("tu")),
  257. _DECL_FL_FUNC(display_error,2,_SC("tu")),
  258. _DECL_FL_FUNC(verify_cert,2,_SC("tu")),
  259. _DECL_FL_FUNC(get_cert_dn,2,_SC("tu")),
  260. _DECL_FL_FUNC(get_cert_subject_alt_dnsname,2,_SC("tu")),
  261. _DECL_FL_FUNC(renegotiate,2,_SC("tu")),
  262. _DECL_FL_FUNC(obj_load,2,_SC("tu")),
  263. _DECL_FL_FUNC(obj_memory_load,2,_SC("tu")),
  264. _DECL_FL_FUNC(version,2,_SC("tu")),
  265. {0,0}
  266. };
  267. #undef _DECL_FL_FUNC
  268. #define _DECL_FL_FUNC(name,nparams,pmask) {_SC(#name),sq_##name,nparams,pmask}
  269. static SQRegFunction ssl_obj_funcs[]={
  270. _DECL_FL_FUNC(ctx_new,3,_SC("tii")),
  271. _DECL_FL_FUNC(ctx_free,2,_SC("tu")),
  272. _DECL_FL_FUNC(server_new,2,_SC("tu")),
  273. _DECL_FL_FUNC(client_new,2,_SC("tu")),
  274. _DECL_FL_FUNC(free,2,_SC("tu")),
  275. _DECL_FL_FUNC(read,2,_SC("tu")),
  276. _DECL_FL_FUNC(write,2,_SC("tu")),
  277. _DECL_FL_FUNC(find,2,_SC("tu")),
  278. _DECL_FL_FUNC(get_session_id,2,_SC("tu")),
  279. _DECL_FL_FUNC(get_session_id_size,2,_SC("tu")),
  280. _DECL_FL_FUNC(get_cipher_id,2,_SC("tu")),
  281. _DECL_FL_FUNC(handshake_status,2,_SC("tu")),
  282. _DECL_FL_FUNC(get_config,2,_SC("tu")),
  283. _DECL_FL_FUNC(display_error,2,_SC("tu")),
  284. _DECL_FL_FUNC(verify_cert,2,_SC("tu")),
  285. _DECL_FL_FUNC(get_cert_dn,2,_SC("tu")),
  286. _DECL_FL_FUNC(get_cert_subject_alt_dnsname,2,_SC("tu")),
  287. _DECL_FL_FUNC(renegotiate,2,_SC("tu")),
  288. _DECL_FL_FUNC(obj_load,2,_SC("tu")),
  289. _DECL_FL_FUNC(obj_memory_load,2,_SC("tu")),
  290. _DECL_FL_FUNC(version,2,_SC("tu")),
  291. {0,0}
  292. };
  293. #undef _DECL_FL_FUNC
  294. typedef struct {
  295. const SQChar *Str;
  296. SQInteger Val;
  297. } KeyIntType, * KeyIntPtrType;
  298. static KeyIntType axtls_constants[] = {
  299. #define MK_CONST(c) {_SC(#c), c}
  300. MK_CONST(SSL_SESSION_ID_SIZE),
  301. MK_CONST(SSL_CLIENT_AUTHENTICATION),
  302. MK_CONST(SSL_SERVER_VERIFY_LATER),
  303. MK_CONST(SSL_NO_DEFAULT_KEY),
  304. MK_CONST(SSL_DISPLAY_STATES),
  305. MK_CONST(SSL_DISPLAY_BYTES),
  306. MK_CONST(SSL_DISPLAY_CERTS),
  307. MK_CONST(SSL_DISPLAY_RSA),
  308. MK_CONST(SSL_CONNECT_IN_PARTS),
  309. MK_CONST(SSL_OK),
  310. MK_CONST(SSL_NOT_OK),
  311. MK_CONST(SSL_ERROR_DEAD),
  312. MK_CONST(SSL_CLOSE_NOTIFY),
  313. MK_CONST(SSL_ERROR_CONN_LOST),
  314. MK_CONST(SSL_ERROR_SOCK_SETUP_FAILURE),
  315. MK_CONST(SSL_ERROR_INVALID_HANDSHAKE),
  316. MK_CONST(SSL_ERROR_INVALID_PROT_MSG),
  317. MK_CONST(SSL_ERROR_INVALID_HMAC),
  318. MK_CONST(SSL_ERROR_INVALID_VERSION),
  319. MK_CONST(SSL_ERROR_INVALID_SESSION),
  320. MK_CONST(SSL_ERROR_NO_CIPHER),
  321. MK_CONST(SSL_ERROR_BAD_CERTIFICATE),
  322. MK_CONST(SSL_ERROR_INVALID_KEY),
  323. MK_CONST(SSL_ERROR_FINISHED_INVALID),
  324. MK_CONST(SSL_ERROR_NO_CERT_DEFINED),
  325. MK_CONST(SSL_ERROR_NO_CLIENT_RENOG),
  326. MK_CONST(SSL_ERROR_NOT_SUPPORTED),
  327. MK_CONST(SSL_X509_OFFSET),
  328. MK_CONST(SSL_ALERT_TYPE_WARNING),
  329. MK_CONST(SLL_ALERT_TYPE_FATAL),
  330. MK_CONST(SSL_ALERT_CLOSE_NOTIFY),
  331. MK_CONST(SSL_ALERT_UNEXPECTED_MESSAGE),
  332. MK_CONST(SSL_ALERT_BAD_RECORD_MAC),
  333. MK_CONST(SSL_ALERT_HANDSHAKE_FAILURE),
  334. MK_CONST(SSL_ALERT_BAD_CERTIFICATE),
  335. MK_CONST(SSL_ALERT_ILLEGAL_PARAMETER),
  336. MK_CONST(SSL_ALERT_DECODE_ERROR),
  337. MK_CONST(SSL_ALERT_DECRYPT_ERROR),
  338. MK_CONST(SSL_ALERT_INVALID_VERSION),
  339. MK_CONST(SSL_ALERT_NO_RENEGOTIATION),
  340. MK_CONST(SSL_AES128_SHA),
  341. MK_CONST(SSL_AES256_SHA),
  342. MK_CONST(SSL_RC4_128_SHA),
  343. MK_CONST(SSL_RC4_128_MD5),
  344. MK_CONST(SSL_BUILD_SKELETON_MODE),
  345. MK_CONST(SSL_BUILD_SERVER_ONLY),
  346. MK_CONST(SSL_BUILD_ENABLE_VERIFICATION),
  347. MK_CONST(SSL_BUILD_ENABLE_CLIENT),
  348. MK_CONST(SSL_BUILD_FULL_MODE),
  349. MK_CONST(SSL_BUILD_MODE),
  350. MK_CONST(SSL_MAX_CERT_CFG_OFFSET),
  351. MK_CONST(SSL_MAX_CA_CERT_CFG_OFFSET),
  352. MK_CONST(SSL_HAS_PEM),
  353. MK_CONST(SSL_DEFAULT_SVR_SESS),
  354. MK_CONST(SSL_DEFAULT_CLNT_SESS),
  355. MK_CONST(SSL_X509_CERT_COMMON_NAME),
  356. MK_CONST(SSL_X509_CERT_ORGANIZATION),
  357. MK_CONST(SSL_X509_CERT_ORGANIZATIONAL_NAME),
  358. MK_CONST(SSL_X509_CA_CERT_COMMON_NAME),
  359. MK_CONST(SSL_X509_CA_CERT_ORGANIZATION),
  360. MK_CONST(SSL_X509_CA_CERT_ORGANIZATIONAL_NAME),
  361. MK_CONST(SSL_OBJ_X509_CERT),
  362. MK_CONST(SSL_OBJ_X509_CACERT),
  363. MK_CONST(SSL_OBJ_RSA_KEY),
  364. MK_CONST(SSL_OBJ_PKCS8),
  365. MK_CONST(SSL_OBJ_PKCS12),
  366. {0,0}
  367. };
  368. /* This defines a function that opens up your library. */
  369. SQRESULT sq_register_axtlsl (HSQUIRRELVM sqvm) {
  370. //add constants
  371. sq_pushconsttable(sqvm); //get the constants table first
  372. for (KeyIntPtrType KeyIntPtr = axtls_constants; KeyIntPtr->Str; KeyIntPtr++) {
  373. sq_pushstring(sqvm, KeyIntPtr->Str, -1); //first the key
  374. sq_pushinteger(sqvm, KeyIntPtr->Val); //then the value
  375. sq_newslot(sqvm, -3, SQFalse); //store then
  376. }
  377. sq_poptop(sqvm); //pop remove constants table when we finished
  378. //add a namespace axtls
  379. sq_pushstring(sqvm,_SC("axtls"),-1);
  380. sq_newtable(sqvm);
  381. //now create the SSL Context class
  382. sq_pushstring(sqvm,_SC("ssl_ctx"),-1);
  383. sq_newclass(sqvm,SQFalse);
  384. sq_settypetag(sqvm,-1,(void*)SSL_CTX_TAG(Fl));
  385. insertFuncs(sqvm, ssl_ctx_obj_funcs);
  386. sq_newslot(sqvm,-3,SQFalse);
  387. //now create the SSL class
  388. sq_pushstring(sqvm,_SC("ssl"),-1);
  389. sq_newclass(sqvm,SQFalse);
  390. sq_settypetag(sqvm,-1,(void*)SSL_TAG(Fl));
  391. insertFuncs(sqvm, ssl_obj_funcs);
  392. sq_newslot(sqvm,-3,SQFalse);
  393. sq_newslot(sqvm,-3,SQFalse); //add axtls table to the root table
  394. sq_poptop(sqvm); //removes axtls table
  395. return SQ_OK;
  396. }
  397. #ifdef __cplusplus
  398. }
  399. #endif