diff --git a/include/luares.h b/include/luares.h index 92ee895..e90864c 100644 --- a/include/luares.h +++ b/include/luares.h @@ -6,6 +6,7 @@ extern char lua_computer[]; extern char lua_eeprom[]; extern char lua_filesystem[]; extern char lua_init[]; +extern char lua_internet[]; extern char lua_sandbox[]; extern char lua_textgpu[]; extern char lua_utf8_utf8data[]; diff --git a/include/lupi.h b/include/lupi.h index 392ac2f..7591602 100644 --- a/include/lupi.h +++ b/include/lupi.h @@ -25,6 +25,7 @@ void run_init(); void luanative_start(lua_State *L); void setup_modules(lua_State *L); void termutils_start(lua_State *L); +void internet_start(lua_State *L); void epoll_prepare(); int epoll_pull(int timeout); diff --git a/src/c/internet.c b/src/c/internet.c new file mode 100644 index 0000000..a3d4649 --- /dev/null +++ b/src/c/internet.c @@ -0,0 +1,110 @@ +#define _XOPEN_SOURCE 600 + +#include "lupi.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int l_open(lua_State *L) { //TODO: Any mem leaks? + const char* hostaddr = lua_tostring(L, 1); + const char* port = lua_tostring(L, 2); + + struct addrinfo hints, *servinfo, *p; + int status; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ((status = getaddrinfo(hostaddr, port, &hints, &servinfo)) != 0) { + lua_pushnil(L); + lua_pushstring(L, gai_strerror(status)); + return 2; + } + + int sockfd; + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + continue; + } + + if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + close(sockfd); + continue; + } + + fcntl(sockfd, F_SETFL, O_NONBLOCK); + break; + } + + if (p == NULL) { + lua_pushnil(L); + lua_pushstring(L, "client: failed to connect"); + return 2; + } + + freeaddrinfo(servinfo); + lua_pushnumber(L, sockfd); + return 1; +} + +static int l_write(lua_State *L) { + size_t len = 0; + int fd = lua_tonumber(L, 1); + const char* data = lua_tolstring(L, 2, &len); + + int total = 0; + int n; + + while(total < len) { + n = send(fd, data+total, len, 0); + if (n == -1) { break; } + total += n; + len -= n; + } + + lua_pushnumber(L, total); + return 1; +} + +static int l_read(lua_State *L) { + int fd = lua_tonumber(L, 1); + int sz = lua_tonumber(L, 2); + + char *buf = malloc(sz); + + if ((sz = recv(fd, buf, sz, 0)) == -1) { + if(errno == EAGAIN || errno == EWOULDBLOCK) { + lua_pushstring(L, ""); + return 1; + } + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return 2; + } + + lua_pushlstring(L, buf, sz); + free(buf); + return 1; +} + +void internet_start(lua_State *L) { + lua_createtable (L, 0, 1); + + pushctuple(L, "open", l_open); + pushctuple(L, "write", l_write); + pushctuple(L, "read", l_read); + + lua_setglobal(L, "net"); +} diff --git a/src/c/modules.c b/src/c/modules.c index c6a2bd1..1237d99 100644 --- a/src/c/modules.c +++ b/src/c/modules.c @@ -10,17 +10,19 @@ void setup_modules(lua_State *L) { lua_createtable (L, 0, 1); pushstuple(L, "boot", lua_boot); + pushstuple(L, "color", lua_util_color); pushstuple(L, "component", lua_component); pushstuple(L, "computer", lua_computer); pushstuple(L, "eeprom", lua_eeprom); pushstuple(L, "filesystem", lua_filesystem); + pushstuple(L, "internet", lua_internet); pushstuple(L, "sandbox", lua_sandbox); pushstuple(L, "textgpu", lua_textgpu); - pushstuple(L, "color", lua_util_color); pushstuple(L, "random", lua_util_random); pushstuple(L, "utf8data", lua_utf8_utf8data); pushstuple(L, "utf8", lua_utf8_utf8); + pushstuple(L, "eepromDefault", res_eepromDefault); lua_setglobal(L, "moduleCode"); diff --git a/src/c/run.c b/src/c/run.c index 032a844..c26aec1 100644 --- a/src/c/run.c +++ b/src/c/run.c @@ -26,6 +26,7 @@ void run_init() { luaL_openlibs (L); setup_modules (L); luanative_start (L); + internet_start (L); termutils_start (L); epoll_prepare(); diff --git a/src/lua/core/init.lua b/src/lua/core/init.lua index 880c854..2596478 100644 --- a/src/lua/core/init.lua +++ b/src/lua/core/init.lua @@ -56,6 +56,7 @@ function main() loadModule("eeprom") loadModule("textgpu") loadModule("filesystem") + loadModule("internet") --Userspace loadModule("sandbox") @@ -67,6 +68,7 @@ function main() _G.pushEvent = modules.computer.api.pushSignal modules.eeprom.register() + modules.internet.start() modules.filesystem.register("root") modules.filesystem.register("/") --TODO: remove from release modules.computer.tmp = modules.filesystem.register("/tmp/lupi-" .. modules.random.uuid()) diff --git a/src/lua/core/internet.lua b/src/lua/core/internet.lua new file mode 100644 index 0000000..8e2c6ac --- /dev/null +++ b/src/lua/core/internet.lua @@ -0,0 +1,46 @@ +local internet = {} + +function internet.start() + local component = {} + + --Legacy + function component.isHttpEnabled() + return true + end + + function component.isTcpEnabled() + return true + end + + --Old TCP + function component.connect(address, port) + checkArg(1, address, "string") + checkArg(2, port, "number") + + local sfd, reason = net.open(address, tostring(port)) + return { + finishConnect = function() + if not sfd then + return false, reason + end + return true + end, + read = function(n) + n = n or 65535 + checkArg(1, n, "number") + return net.read(sfd, n) + end, + write = function(data) + checkArg(1, data, "string") + return net.write(sfd, data) + end, + close = function() + native.close(sfd) + end + } + end + + modules.component.api.register(nil, "internet", component) +end + +return internet