1
0
Fork 0
mirror of https://github.com/ctruLua/ctruLua.git synced 2025-10-27 16:39:29 +00:00

Added SSL support to sockets, Added console/stdout support, Removed apt.init/apt.shutdown, Added some SSL options to httpc

The console can __not__ be used with gfx.start() on a screen. You don't have to gfx.render() while print()ing, but you should do it when you are in the main loop.
The SSL sockets don't work with Citra.
This commit is contained in:
Firew0lf 2016-04-10 01:47:52 +02:00
parent e87651a404
commit e7ff54d58c
9 changed files with 333 additions and 75 deletions

View file

@ -13,30 +13,6 @@ Used to manage the applets and application status.
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
/***
Initialize the APT module. Useless.
@function init
*/
static int apt_init(lua_State *L) {
Result ret = aptInit();
if (ret!=0) {
lua_pushboolean(L, false);
lua_pushinteger(L, ret);
return 2;
}
lua_pushboolean(L, true);
return 1;
}
/***
Shutdown the APT module. Useless, don't use it.
@function shutdown
*/
static int apt_shutdown(lua_State *L) {
aptExit();
return 0;
}
/*** /***
Open an APT session. Should only work if you don't use the homebrew menu. Open an APT session. Should only work if you don't use the homebrew menu.
@function openSession @function openSession
@ -132,8 +108,6 @@ static int apt_getMenuAppID(lua_State *L) {
} }
static const struct luaL_Reg apt_lib[] = { static const struct luaL_Reg apt_lib[] = {
{"init", apt_init },
{"shutdown", apt_shutdown },
{"openSession", apt_openSession }, {"openSession", apt_openSession },
{"closeSession", apt_closeSession }, {"closeSession", apt_closeSession },
{"setStatus", apt_setStatus }, {"setStatus", apt_setStatus },
@ -327,6 +301,8 @@ struct { char *name; int value; } apt_constants[] = {
}; };
int luaopen_apt_lib(lua_State *L) { int luaopen_apt_lib(lua_State *L) {
aptInit();
luaL_newlib(L, apt_lib); luaL_newlib(L, apt_lib);
for (int i = 0; apt_constants[i].name; i++) { for (int i = 0; apt_constants[i].name; i++) {
@ -340,3 +316,7 @@ int luaopen_apt_lib(lua_State *L) {
void load_apt_lib(lua_State *L) { void load_apt_lib(lua_State *L) {
luaL_requiref(L, "ctr.apt", luaopen_apt_lib, false); luaL_requiref(L, "ctr.apt", luaopen_apt_lib, false);
} }
void unload_apt_lib(lua_State *L) {
aptExit();
}

View file

@ -14,13 +14,17 @@ Used to get some user config.
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
bool initStateCFGU = false;
/*** /***
Initialize the CFGU module. Initialize the CFGU module.
@function init @function init
*/ */
static int cfgu_init(lua_State *L) { static int cfgu_init(lua_State *L) {
if (!initStateCFGU) {
cfguInit(); cfguInit();
initStateCFGU = true;
}
return 0; return 0;
} }
@ -29,8 +33,10 @@ Disable the CFGU module.
@function shutdown @function shutdown
*/ */
static int cfgu_shutdown(lua_State *L) { static int cfgu_shutdown(lua_State *L) {
if (initStateCFGU) {
cfguExit(); cfguExit();
initStateCFGU = false;
}
return 0; return 0;
} }
@ -309,3 +315,10 @@ int luaopen_cfgu_lib(lua_State *L) {
void load_cfgu_lib(lua_State *L) { void load_cfgu_lib(lua_State *L) {
luaL_requiref(L, "ctr.cfgu", luaopen_cfgu_lib, false); luaL_requiref(L, "ctr.cfgu", luaopen_cfgu_lib, false);
} }
void unload_cfgu_lib(lua_State *L) {
if (initStateCFGU) {
initStateCFGU = false;
cfguExit();
}
}

View file

@ -28,6 +28,7 @@ The `ctr.news` module.
@see ctr.news @see ctr.news
*/ */
void load_news_lib(lua_State *L); void load_news_lib(lua_State *L);
void unload_news_lib(lua_State *L);
/*** /***
The `ctr.ptm` module. The `ctr.ptm` module.
@ -35,6 +36,7 @@ The `ctr.ptm` module.
@see ctr.ptm @see ctr.ptm
*/ */
void load_ptm_lib(lua_State *L); void load_ptm_lib(lua_State *L);
void unload_ptm_lib(lua_State *L);
/*** /***
The `ctr.hid` module. The `ctr.hid` module.
@ -80,6 +82,7 @@ The `ctr.cfgu` module.
@see ctr.cfgu @see ctr.cfgu
*/ */
void load_cfgu_lib(lua_State *L); void load_cfgu_lib(lua_State *L);
void unload_cfgu_lib(lua_State *L);
/*** /***
The `ctr.socket` module. The `ctr.socket` module.
@ -109,6 +112,7 @@ The `ctr.apt` module.
@see ctr.apt @see ctr.apt
*/ */
void load_apt_lib(lua_State *L); void load_apt_lib(lua_State *L);
void unload_apt_lib(lua_State *L);
/*** /***
The `ctr.mic` module. The `ctr.mic` module.
@ -168,18 +172,18 @@ static const struct luaL_Reg ctr_lib[] = {
// Subtables // Subtables
struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } ctr_libs[] = { struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } ctr_libs[] = {
{ "gfx", load_gfx_lib, unload_gfx_lib }, { "gfx", load_gfx_lib, unload_gfx_lib },
{ "news", load_news_lib, NULL }, { "news", load_news_lib, unload_news_lib },
{ "ptm", load_ptm_lib, NULL }, { "ptm", load_ptm_lib, unload_ptm_lib },
{ "hid", load_hid_lib, unload_hid_lib }, { "hid", load_hid_lib, unload_hid_lib },
{ "ir", load_ir_lib, NULL }, { "ir", load_ir_lib, NULL },
{ "fs", load_fs_lib, unload_fs_lib }, { "fs", load_fs_lib, unload_fs_lib },
{ "httpc", load_httpc_lib, unload_httpc_lib }, { "httpc", load_httpc_lib, unload_httpc_lib },
{ "qtm", load_qtm_lib, NULL }, { "qtm", load_qtm_lib, NULL },
{ "cfgu", load_cfgu_lib, NULL }, { "cfgu", load_cfgu_lib, unload_cfgu_lib },
{ "socket", load_socket_lib, NULL }, { "socket", load_socket_lib, NULL },
{ "cam", load_cam_lib, NULL }, { "cam", load_cam_lib, NULL },
{ "audio", load_audio_lib, unload_audio_lib }, { "audio", load_audio_lib, unload_audio_lib },
{ "apt", load_apt_lib, NULL }, { "apt", load_apt_lib, unload_apt_lib },
{ "mic", load_mic_lib, NULL }, { "mic", load_mic_lib, NULL },
{ "thread", load_thread_lib, NULL }, { "thread", load_thread_lib, NULL },
{ NULL, NULL, NULL } { NULL, NULL, NULL }

View file

@ -12,6 +12,7 @@ The `gfx` module.
//#include <3ds/vram.h> //#include <3ds/vram.h>
//#include <3ds/services/gsp.h> //#include <3ds/services/gsp.h>
#include <3ds/console.h>
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
@ -524,6 +525,51 @@ static int gfx_target___index(lua_State *L) {
return 1; return 1;
} }
/***
Initialize the console. You can print on it using print(), or any function that normally outputs to stdout.
Warning: you can't use a screen for both a console and drawing, you have to disable the console first.
@function console
@tparam[opt=gfx.TOP] number screen screen to draw the console on.
@tparam[opt=true] boolean debug enable stderr output on the console
*/
u8 consoleScreen = GFX_TOP;
static int gfx_console(lua_State *L) {
consoleScreen = luaL_optinteger(L, 1, GFX_TOP);
bool err = false;
if (lua_isboolean(L, 2)) {
err = lua_toboolean(L, 2);
}
consoleInit(consoleScreen, NULL);
if (err)
consoleDebugInit(debugDevice_CONSOLE);
return 0;
}
/***
Clear the console.
@function clearConsole
*/
static int gfx_clearConsole(lua_State *L) {
consoleClear();
return 0;
}
/***
Disable the console.
@function disableConsole
*/
static int gfx_disableConsole(lua_State *L) {
gfxSetScreenFormat(consoleScreen, GSP_BGR8_OES);
gfxSetDoubleBuffering(consoleScreen, true);
gfxSwapBuffersGpu();
gspWaitForVBlank();
return 0;
}
// Functions // Functions
static const struct luaL_Reg gfx_lib[] = { static const struct luaL_Reg gfx_lib[] = {
{ "start", gfx_start }, { "start", gfx_start },
@ -546,6 +592,9 @@ static const struct luaL_Reg gfx_lib[] = {
{ "getTextSize", gfx_getTextSize }, { "getTextSize", gfx_getTextSize },
{ "scissor", gfx_scissor }, { "scissor", gfx_scissor },
{ "target", gfx_target }, { "target", gfx_target },
{ "console", gfx_console },
{ "clearConsole", gfx_clearConsole },
{ "disableConsole", gfx_disableConsole },
{ NULL, NULL } { NULL, NULL }
}; };

View file

@ -9,6 +9,7 @@ The `httpc` module.
#include <3ds.h> #include <3ds.h>
#include <3ds/types.h> #include <3ds/types.h>
#include <3ds/services/httpc.h> #include <3ds/services/httpc.h>
#include <3ds/services/sslc.h>
#include <lapi.h> #include <lapi.h>
#include <lauxlib.h> #include <lauxlib.h>
@ -239,6 +240,25 @@ static int httpc_addTrustedRootCA(lua_State *L) {
return 1; return 1;
} }
/***
Set SSL options for a context.
@function :setSSLOptions
@tparam boolean disableVerify disable server certificate verification if `true`
@tparam[opt=false] boolean tlsv10 use TLS v1.0 if `true`
*/
static int httpc_setSSLOptions(lua_State *L) {
httpcContext *context = lua_touserdata(L, 1);
bool disVer = lua_toboolean(L, 2);
bool tsl10 = false;
if (lua_isboolean(L, 3))
tsl10 = lua_toboolean(L, 3);
httpcSetSSLOpt(context, (disVer?SSLCOPT_DisableVerify:0)|(tsl10?SSLCOPT_TLSv10:0));
return 0;
}
// object // object
static const struct luaL_Reg httpc_methods[] = { static const struct luaL_Reg httpc_methods[] = {
{"open", httpc_open }, {"open", httpc_open },
@ -252,6 +272,7 @@ static const struct luaL_Reg httpc_methods[] = {
{"addPostData", httpc_addPostData }, {"addPostData", httpc_addPostData },
{"getResponseHeader", httpc_getResponseHeader }, {"getResponseHeader", httpc_getResponseHeader },
{"addTrustedRootCA", httpc_addTrustedRootCA }, {"addTrustedRootCA", httpc_addTrustedRootCA },
{"setSSLOptions", httpc_setSSLOptions },
{NULL, NULL} {NULL, NULL}
}; };

View file

@ -13,13 +13,17 @@ The `news` module.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
bool initStateNews = false;
/*** /***
Initialize the news module. Initialize the news module.
@function init @function init
*/ */
static int news_init(lua_State *L) { static int news_init(lua_State *L) {
if (!initStateNews) {
newsInit(); newsInit();
initStateNews = true;
}
return 0; return 0;
} }
@ -63,8 +67,10 @@ Disable the news module.
@function shutdown @function shutdown
*/ */
static int news_shutdown(lua_State *L) { static int news_shutdown(lua_State *L) {
if (initStateNews) {
newsExit(); newsExit();
initStateNews = false;
}
return 0; return 0;
} }
@ -83,3 +89,10 @@ int luaopen_news_lib(lua_State *L) {
void load_news_lib(lua_State *L) { void load_news_lib(lua_State *L) {
luaL_requiref(L, "ctr.news", luaopen_news_lib, 0); luaL_requiref(L, "ctr.news", luaopen_news_lib, 0);
} }
void unload_news_lib(lua_State *L) {
if (initStateNews) {
newsExit();
initStateNews = false;
}
}

View file

@ -10,14 +10,20 @@ The `ptm` module.
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
bool initStatePTM = false;
/*** /***
Initialize the PTM module. Initialize the PTM module.
@function init @function init
*/ */
static int ptm_init(lua_State *L) { static int ptm_init(lua_State *L) {
if (!initStatePTM) {
ptmuInit(); ptmuInit();
ptmSysmInit(); ptmSysmInit();
initStatePTM = true;
}
return 0; return 0;
} }
@ -26,9 +32,13 @@ Disable the PTM module.
@function shutdown @function shutdown
*/ */
static int ptm_shutdown(lua_State *L) { static int ptm_shutdown(lua_State *L) {
if (initStatePTM) {
ptmuExit(); ptmuExit();
ptmSysmExit(); ptmSysmExit();
initStatePTM = false;
}
return 0; return 0;
} }
@ -146,3 +156,10 @@ int luaopen_ptm_lib(lua_State *L) {
void load_ptm_lib(lua_State *L) { void load_ptm_lib(lua_State *L) {
luaL_requiref(L, "ctr.ptm", luaopen_ptm_lib, 0); luaL_requiref(L, "ctr.ptm", luaopen_ptm_lib, 0);
} }
void unload_ptm_lib(lua_State *L) {
if (initStatePTM) {
ptmuExit();
ptmSysmExit();
}
}

View file

@ -8,6 +8,7 @@ The UDP part is only without connection.
#include <3ds.h> #include <3ds.h>
#include <3ds/types.h> #include <3ds/types.h>
#include <3ds/services/soc.h> #include <3ds/services/soc.h>
#include <3ds/services/sslc.h>
#include <lapi.h> #include <lapi.h>
#include <lauxlib.h> #include <lauxlib.h>
@ -15,7 +16,9 @@ The UDP part is only without connection.
#include <malloc.h> #include <malloc.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -26,16 +29,36 @@ typedef struct {
int socket; int socket;
struct sockaddr_in addr; struct sockaddr_in addr;
struct hostent *host; // only used for client sockets struct hostent *host; // only used for client sockets
sslcContext sslContext;
bool isSSL;
} socket_userdata; } socket_userdata;
bool initStateSocket = false;
u32 rootCertChain = 0;
/*** /***
Initialize the socket module Initialize the socket module
@function init @function init
@tparam[opt=0x100000] number buffer size (in bytes), must be a multiple of 0x1000 @tparam[opt=0x100000] number buffer size (in bytes), must be a multiple of 0x1000
*/ */
static int socket_init(lua_State *L) { static int socket_init(lua_State *L) {
if (!initStateSocket) {
u32 size = luaL_optinteger(L, 1, 0x100000); u32 size = luaL_optinteger(L, 1, 0x100000);
Result ret = socInit((u32*)memalign(0x1000, size), size); if (size%0x1000 != 0) {
lua_pushboolean(L, false);
lua_pushstring(L, "Not a multiple of 0x1000");
return 2;
}
u32* mem = (u32*)memalign(0x1000, size);
if (mem == NULL) {
lua_pushboolean(L, false);
lua_pushstring(L, "Failed to allocate memory");
return 2;
}
Result ret = socInit(mem, size);
if (ret) { if (ret) {
lua_pushboolean(L, false); lua_pushboolean(L, false);
@ -43,6 +66,23 @@ static int socket_init(lua_State *L) {
return 2; return 2;
} }
ret = sslcInit(0);
if (R_FAILED(ret)) {
lua_pushboolean(L, false);
lua_pushinteger(L, ret);
return 2;
}
sslcCreateRootCertChain(&rootCertChain);
sslcRootCertChainAddDefaultCert(rootCertChain, SSLC_DefaultRootCert_CyberTrust, NULL);
sslcRootCertChainAddDefaultCert(rootCertChain, SSLC_DefaultRootCert_AddTrust_External_CA, NULL);
sslcRootCertChainAddDefaultCert(rootCertChain, SSLC_DefaultRootCert_COMODO, NULL);
sslcRootCertChainAddDefaultCert(rootCertChain, SSLC_DefaultRootCert_USERTrust, NULL);
sslcRootCertChainAddDefaultCert(rootCertChain, SSLC_DefaultRootCert_DigiCert_EV, NULL);
initStateSocket = true;
}
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 1; return 1;
} }
@ -52,8 +92,11 @@ Disable the socket module. Must be called before exiting ctrµLua.
@function shutdown @function shutdown
*/ */
static int socket_shutdown(lua_State *L) { static int socket_shutdown(lua_State *L) {
sslcDestroyRootCertChain(rootCertChain);
sslcExit();
socExit(); socExit();
initStateSocket = false;
return 0; return 0;
} }
@ -76,6 +119,8 @@ static int socket_tcp(lua_State *L) {
userdata->addr.sin_family = AF_INET; userdata->addr.sin_family = AF_INET;
userdata->isSSL = false;
return 1; return 1;
} }
@ -92,15 +137,36 @@ static int socket_udp(lua_State *L) {
userdata->socket = socket(AF_INET, SOCK_DGRAM, 0); userdata->socket = socket(AF_INET, SOCK_DGRAM, 0);
if (userdata->socket < 0) { if (userdata->socket < 0) {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, "Failed to create a TCP socket"); lua_pushstring(L, strerror(errno));
return 2; return 2;
} }
fcntl(userdata->socket, F_SETFL, O_NONBLOCK);
userdata->addr.sin_family = AF_INET; userdata->addr.sin_family = AF_INET;
return 1; return 1;
} }
/***
Add a trusted root CA to the certChain.
@function addTrustedRootCA
@tparam string cert DER cert
*/
static int socket_addTrustedRootCA(lua_State *L) {
size_t size = 0;
const char* cert = luaL_checklstring(L, 1, &size);
Result ret = sslcAddTrustedRootCA(rootCertChain, (u8*)cert, size, NULL);
if (R_FAILED(ret)) {
lua_pushnil(L);
lua_pushinteger(L, ret);
return 2;
}
lua_pushboolean(L, true);
return 1;
}
/*** /***
All sockets All sockets
@section sockets @section sockets
@ -130,6 +196,10 @@ Close an existing socket.
static int socket_close(lua_State *L) { static int socket_close(lua_State *L) {
socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket"); socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket");
if (userdata->isSSL) {
sslcDestroyContext(&userdata->sslContext);
}
closesocket(userdata->socket); closesocket(userdata->socket);
return 0; return 0;
@ -158,6 +228,7 @@ static int socket_accept(lua_State *L) {
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
} }
fcntl(client->socket, F_SETFL, O_NONBLOCK);
return 1; return 1;
} }
@ -167,6 +238,7 @@ Connect a socket to a server. The TCP object becomes a TCPClient object.
@function :connect @function :connect
@tparam string host address of the host @tparam string host address of the host
@tparam number port port of the server @tparam number port port of the server
@tparam[opt=false] boolean ssl use SSL if `true`
@treturn[1] boolean true if success @treturn[1] boolean true if success
@treturn[2] boolean false if failed @treturn[2] boolean false if failed
@treturn[2] string error string @treturn[2] string error string
@ -175,11 +247,12 @@ static int socket_connect(lua_State *L) {
socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket"); socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket");
char *addr = (char*)luaL_checkstring(L, 2); char *addr = (char*)luaL_checkstring(L, 2);
int port = luaL_checkinteger(L, 3); int port = luaL_checkinteger(L, 3);
bool ssl = lua_toboolean(L, 4);
userdata->host = gethostbyname(addr); userdata->host = gethostbyname(addr);
if (userdata->host == NULL) { if (userdata->host == NULL) {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, "No such host"); lua_pushstring(L, strerror(errno));
return 2; return 2;
} }
@ -188,10 +261,23 @@ static int socket_connect(lua_State *L) {
if (connect(userdata->socket, (const struct sockaddr*)&userdata->addr, sizeof(userdata->addr)) < 0) { if (connect(userdata->socket, (const struct sockaddr*)&userdata->addr, sizeof(userdata->addr)) < 0) {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, "Connection failed"); lua_pushstring(L, strerror(errno));
return 2; return 2;
} }
if (ssl) { // SSL context setup
sslcCreateContext(&userdata->sslContext, userdata->socket, SSLCOPT_Default, addr);
sslcContextSetRootCertChain(&userdata->sslContext, rootCertChain);
if (R_FAILED(sslcStartConnection(&userdata->sslContext, NULL, NULL))) {
sslcDestroyContext(&userdata->sslContext);
lua_pushnil(L);
lua_pushstring(L, "SSL connection failed");
return 2;
}
userdata->isSSL = true;
}
fcntl(userdata->socket, F_SETFL, O_NONBLOCK);
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
@ -237,7 +323,11 @@ static int socket_receive(lua_State *L) {
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
char buff; char buff;
if (!userdata->isSSL) {
while (recv(userdata->socket, &buff, 1, flags) > 0 && buff != '\n') luaL_addchar(&b, buff); while (recv(userdata->socket, &buff, 1, flags) > 0 && buff != '\n') luaL_addchar(&b, buff);
} else {
while (!R_FAILED(sslcRead(&userdata->sslContext, &buff, 1, false)) && buff != '\n') luaL_addchar(&b, buff);
}
luaL_pushresult(&b); luaL_pushresult(&b);
return 1; return 1;
@ -247,7 +337,11 @@ static int socket_receive(lua_State *L) {
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
char buff; char buff;
if (!userdata->isSSL) {
while (buff != '\n' && recv(userdata->socket, &buff, 1, flags) > 0) luaL_addchar(&b, buff); while (buff != '\n' && recv(userdata->socket, &buff, 1, flags) > 0) luaL_addchar(&b, buff);
} else {
while (buff != '\n' && !R_FAILED(sslcRead(&userdata->sslContext, &buff, 1, false))) luaL_addchar(&b, buff);
}
luaL_pushresult(&b); luaL_pushresult(&b);
return 1; return 1;
@ -258,7 +352,17 @@ static int socket_receive(lua_State *L) {
} }
char *buff = malloc(count+1); char *buff = malloc(count+1);
int len = recv(userdata->socket, buff, count, flags); int len;
if (!userdata->isSSL) {
len = recv(userdata->socket, buff, count, flags);
} else {
len = sslcRead(&userdata->sslContext, buff, count, false);
if (R_FAILED(len)) {
lua_pushnil(L);
lua_pushinteger(L, len);
return 2;
}
}
*(buff+len) = 0x0; // text end *(buff+len) = 0x0; // text end
lua_pushstring(L, buff); lua_pushstring(L, buff);
@ -276,12 +380,68 @@ static int socket_send(lua_State *L) {
size_t size = 0; size_t size = 0;
char *data = (char*)luaL_checklstring(L, 2, &size); char *data = (char*)luaL_checklstring(L, 2, &size);
size_t sent = send(userdata->socket, data, size, 0); size_t sent;
if (!userdata->isSSL) {
sent = send(userdata->socket, data, size, 0);
} else {
sent = sslcWrite(&userdata->sslContext, data, size);
if (R_FAILED(sent)) {
lua_pushnil(L);
lua_pushinteger(L, sent);
return 2;
}
}
if (sent < 0) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
}
lua_pushinteger(L, sent); lua_pushinteger(L, sent);
return 1; return 1;
} }
/***
Get some informations from a socket.
@function :getpeername
@treturn string IP
@treturn number port
*/
static int socket_getpeername(lua_State *L) {
socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket");
struct sockaddr_in addr;
socklen_t addrSize = sizeof(addr);
getpeername(userdata->socket, (struct sockaddr*)&addr, &addrSize);
lua_pushstring(L, inet_ntoa(addr.sin_addr));
lua_pushinteger(L, ntohs(addr.sin_port));
return 2;
}
/***
Get some local informations from a socket.
@function :getsockname
@treturn string IP
@treturn number port
*/
static int socket_getsockname(lua_State *L) {
socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket");
struct sockaddr_in addr;
socklen_t addrSize = sizeof(addr);
getsockname(userdata->socket, (struct sockaddr*)&addr, &addrSize);
lua_pushstring(L, inet_ntoa(addr.sin_addr));
lua_pushinteger(L, ntohs(addr.sin_port));
return 2;
}
/*** /***
UDP sockets UDP sockets
@section UDP @section UDP
@ -364,6 +524,7 @@ static const struct luaL_Reg socket_functions[] = {
{"shutdown", socket_shutdown }, {"shutdown", socket_shutdown },
{"tcp", socket_tcp }, {"tcp", socket_tcp },
{"udp", socket_udp }, {"udp", socket_udp },
{"addTrustedRootCA", socket_addTrustedRootCA},
{NULL, NULL} {NULL, NULL}
}; };
@ -379,6 +540,8 @@ static const struct luaL_Reg socket_methods[] = {
{"receivefrom", socket_receivefrom}, {"receivefrom", socket_receivefrom},
{"send", socket_send }, {"send", socket_send },
{"sendto", socket_sendto }, {"sendto", socket_sendto },
{"getpeername", socket_getpeername},
{"getsockname", socket_getsockname},
{NULL, NULL} {NULL, NULL}
}; };

View file

@ -280,23 +280,10 @@ static int texture_save(lua_State *L) {
const char* path = luaL_checkstring(L, 2); const char* path = luaL_checkstring(L, 2);
u8 type = luaL_optinteger(L, 3, 0); u8 type = luaL_optinteger(L, 3, 0);
u32* buff = malloc(texture->texture->width * texture->texture->height * 4);
if (buff == NULL) {
lua_pushnil(L);
lua_pushstring(L, "Failed to allocate buffer");
return 2;
}
for (int y=0;y<texture->texture->height;y++) {
for (int x=0;x<texture->texture->width;x++) {
buff[x+(y*texture->texture->width)] = __builtin_bswap32(sf2d_get_pixel(texture->texture, x, y));
}
}
int result = 0; int result = 0;
if (type == 0) { // PNG if (type == 0) { // PNG
FILE* file = fopen(path, "wb"); FILE* file = fopen(path, "wb");
if (file == NULL) { if (file == NULL) {
free(buff);
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, "Can open file"); lua_pushstring(L, "Can open file");
return 2; return 2;
@ -313,7 +300,7 @@ static int texture_save(lua_State *L) {
for(int y=0;y<texture->texture->height;y++) { for(int y=0;y<texture->texture->height;y++) {
for (int x=0;x<texture->texture->width;x++) { for (int x=0;x<texture->texture->width;x++) {
((u32*)row)[x] = buff[x+(y*texture->texture->width)]; ((u32*)row)[x] = __builtin_bswap32(sf2d_get_pixel(texture->texture, x, y));
} }
png_write_row(png, row); png_write_row(png, row);
} }
@ -328,14 +315,25 @@ static int texture_save(lua_State *L) {
result = 1; result = 1;
} else if (type == 2) { // BMP } else if (type == 2) { // BMP
u32* buff = malloc(texture->texture->width * texture->texture->height * 4);
if (buff == NULL) {
lua_pushnil(L);
lua_pushstring(L, "Failed to allocate buffer");
return 2;
}
for (int y=0;y<texture->texture->height;y++) {
for (int x=0;x<texture->texture->width;x++) {
buff[x+(y*texture->texture->width)] = __builtin_bswap32(sf2d_get_pixel(texture->texture, x, y));
}
}
result = stbi_write_bmp(path, texture->texture->width, texture->texture->height, 4, buff); result = stbi_write_bmp(path, texture->texture->width, texture->texture->height, 4, buff);
} else {
free(buff); free(buff);
} else {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, "Not a valid type"); lua_pushstring(L, "Not a valid type");
return 2; return 2;
} }
free(buff);
if (result == 0) { if (result == 0) {
lua_pushnil(L); lua_pushnil(L);