diff --git a/LuaEngine.cpp b/LuaEngine.cpp index 2e8f22e..8cb45e3 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -11,8 +11,10 @@ void InitLuaEngine(lua_State* L) InitMusic(L); InitCommon(L); InitTCPSocket(L); - InitThread(L); + InitUDPSocket(L); + InitNetwork(L); InitSocketSelector(L); + InitThread(L); } void InitEngine() @@ -26,7 +28,7 @@ void InitEngine() SDL_Log("Mix_OpenAudio: %s\n", Mix_GetError()); exit(2); } - + Mix_AllocateChannels(16); // Stop text input event SDL_StopTextInput(); diff --git a/Music.cpp b/Music.cpp index 39077f0..535fe7a 100644 --- a/Music.cpp +++ b/Music.cpp @@ -4,7 +4,8 @@ module Music load(filename: string): MusicMedia loadChunk(filename: string): ChunkMedia - play(music: MusicMedia, [loops: int]) + play(music: MusicMedia, [loops: int]) Loops default to 1 time + playChunk(chunk: ChunkMedia, channel: int, [loops: int]) Loops default to 1 time. pause() resume() */ @@ -106,7 +107,7 @@ int music_loadchunkmem(lua_State* L) int music_play(lua_State* L) { auto music = lua_checkpointer(L, 1, "LuaEngineMusicMedia"); - int loops = -1; + int loops = 0; if (!lua_isnone(L, 2)) { loops = luaL_checkinteger(L, 2); @@ -118,6 +119,24 @@ int music_play(lua_State* L) return 0; } +int music_playchunk(lua_State* L) +{ + auto chunk = lua_checkpointer(L, 1, "LuaEngineChunkMedia"); + int channel = luaL_checkinteger(L, 2); + int loops = 0; + if (!lua_isnone(L, 3)) + { + loops = luaL_checkinteger(L, 3); + } + int ret = Mix_PlayChannel(channel, chunk, loops); + if (ret == -1) + { + return MixError(L, Mix_PlayChannel); + } + lua_pushinteger(L, ret); + return 1; +} + int music_pause(lua_State* L) { Mix_PauseMusic(); @@ -140,6 +159,7 @@ void InitMusic(lua_State* L) lua_setfield_function(L, "loadChunk", music_loadchunk); lua_setfield_function(L, "loadChunkmem", music_loadchunkmem); lua_setfield_function(L, "play", music_play); + lua_setfield_function(L, "playChunk", music_playchunk); lua_setfield_function(L, "pause", music_pause); lua_setfield_function(L, "resume", music_resume); lua_setfield(L, -2, "Music"); diff --git a/NetworkWin.cpp b/NetworkWin.cpp new file mode 100644 index 0000000..2a748a2 --- /dev/null +++ b/NetworkWin.cpp @@ -0,0 +1,57 @@ +#include "include.h" + +#ifdef _WIN32 +#define _WIN32_WINNT 0x0A00 // Win10 +#include +#include + +int network_getip(lua_State* L) +{ + const char* host = luaL_checkstring(L, 1); + addrinfo* result = NULL; + + if (getaddrinfo(host, NULL, NULL, &result) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "getaddrinfo"); + return lua_error(L); + } + + int cnt = 0; + for (addrinfo* pinfo = result; pinfo; pinfo = pinfo->ai_next) + { + switch (pinfo->ai_family) + { + case AF_INET: + { + char buffer[1024] = { 0 }; + if (inet_ntop(AF_INET, &((sockaddr_in*)(pinfo->ai_addr))->sin_addr, buffer, 1024)) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_ntop"); + freeaddrinfo(result); + return lua_error(L); + } + lua_pushstring(L, buffer); + cnt++; + + break; + } + } + } + + freeaddrinfo(result); + return cnt; +} + +void InitNetwork(lua_State* L) +{ + lua_getglobal(L, "package"); + lua_getfield(L, -1, "loaded"); + lua_newtable(L); + lua_setfield_function(L, "getip", network_getip); + lua_setfield(L, -2, "network"); + lua_pop(L, 2); +} + +#endif // End of _WIN32 diff --git a/SelectWin.cpp b/SelectWin.cpp index d5aa968..2cc3882 100644 --- a/SelectWin.cpp +++ b/SelectWin.cpp @@ -1,5 +1,5 @@ #include "Select.h" -#include "TCP.h" +#include "Socket.h" #ifdef _WIN32 #define _WIN32_WINNT 0x0A00 // Win10 @@ -8,57 +8,59 @@ #include using namespace std; +inline void luatable_to_fdset(lua_State* L, int tbl_index, fd_set& fds) +{ + lua_pushnil(L); + while (lua_next(L, tbl_index)) + { + lua_pop(L, 1); + auto s = lua_testblock(L, -1, "LuaEngineTCPSocket") ? lua_checkblock(L, -1, "LuaEngineTCPSocket") : lua_checkblock(L, -1, "LuaEngineUDPSocket"); + if (s->fd > 0) + { + FD_SET(s->fd, &fds); + } + } +} + +inline void fdset_to_luatable(lua_State* L, int tbl_index, fd_set& fds) +{ + lua_newtable(L); // ... RetT + lua_pushnil(L); // ... RetT nil + while (lua_next(L, tbl_index)) + { + lua_pop(L, 1); // ... RetT Socket + auto s = lua_testblock(L, -1, "LuaEngineTCPSocket") ? lua_checkblock(L, -1, "LuaEngineTCPSocket") : lua_checkblock(L, -1, "LuaEngineUDPSocket"); + if (s->fd > 0 && FD_ISSET(s->fd, &fds)) + { + lua_pushvalue(L, -1); // ... RetT Socket Socket + lua_pushboolean(L, true); // ... RetT Socket Socket true + lua_settable(L, -4); // ... RetT Socket + } + } +} + int select_call(lua_State* L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 2, LUA_TTABLE); luaL_checktype(L, 3, LUA_TTABLE); int us = luaL_checkinteger(L, 4); - FD_SET readset, writeset, errorset; + fd_set readset, writeset, errorset; FD_ZERO(&readset); - lua_pushnil(L); - while (lua_next(L, 1)) - { - lua_pop(L, 1); - auto s = lua_checkblock(L, -1, "LuaEngineTCPSocket"); - if (s->fd > 0) - { - FD_SET(s->fd, &readset); - } - } + luatable_to_fdset(L, 1, readset); FD_ZERO(&writeset); - lua_pushnil(L); - while (lua_next(L, 2)) - { - lua_pop(L, 1); - auto s = lua_checkblock(L, -1, "LuaEngineTCPSocket"); - if (s->fd > 0) - { - FD_SET(s->fd, &writeset); - } - } + luatable_to_fdset(L, 2, writeset); FD_ZERO(&errorset); - lua_pushnil(L); - while (lua_next(L, 3)) - { - lua_pop(L, 1); - auto s = lua_checkblock(L, -1, "LuaEngineTCPSocket"); - if (s->fd > 0) - { - FD_SET(s->fd, &errorset); - } - } + luatable_to_fdset(L, 3, errorset); timeval tm; tm.tv_sec = us / 1000000; tm.tv_usec = us % 1000000; - printf("[DEBUG] select() start\n"); int ret = select(1024, &readset, &writeset, &errorset, &tm); - printf("[DEBUG] select() done. ret=%d\n", ret); if (ret < 0) { @@ -72,47 +74,9 @@ int select_call(lua_State* L) } else { - lua_newtable(L); // ... RetT - lua_pushnil(L); // ... RetT nil - while (lua_next(L, 1)) - { - lua_pop(L, 1); // ... RetT Socket - auto s = lua_checkblock(L, -1, "LuaEngineTCPSocket"); - if (s->fd > 0 && FD_ISSET(s->fd, &readset)) - { - lua_pushvalue(L, -1); // ... RetT Socket Socket - lua_pushboolean(L, true); // ... RetT Socket Socket true - lua_settable(L, -4); // ... RetT Socket - } - } - - lua_newtable(L); // ... RetT - lua_pushnil(L); // ... RetT nil - while (lua_next(L, 2)) - { - lua_pop(L, 1); // ... RetT Socket - auto s = lua_checkblock(L, -1, "LuaEngineTCPSocket"); - if (s->fd > 0 && FD_ISSET(s->fd, &writeset)) - { - lua_pushvalue(L, -1); // ... RetT Socket Socket - lua_pushboolean(L, true); // ... RetT Socket Socket true - lua_settable(L, -4); // ... RetT Socket - } - } - - lua_newtable(L); // ... RetT - lua_pushnil(L); // ... RetT nil - while (lua_next(L, 3)) - { - lua_pop(L, 1); // ... RetT Socket - auto s = lua_checkblock(L, -1, "LuaEngineTCPSocket"); - if (s->fd > 0 && FD_ISSET(s->fd, &errorset)) - { - lua_pushvalue(L, -1); // ... RetT Socket Socket - lua_pushboolean(L, true); // ... RetT Socket Socket true - lua_settable(L, -4); // ... RetT Socket - } - } + fdset_to_luatable(L, 1, readset); // +1 + fdset_to_luatable(L, 2, writeset); // +1 + fdset_to_luatable(L, 3, errorset); // +1 return 3; // ... RetT RetT RetT } diff --git a/Socket.h b/Socket.h new file mode 100644 index 0000000..0aa5f46 --- /dev/null +++ b/Socket.h @@ -0,0 +1,11 @@ +#include "include.h" +#include + +class SocketData +{ +public: + int fd; + bool nonblocking; + std::vector data; + int buffsz; +}; diff --git a/TCP.h b/TCP.h index b8061f9..9f8ae39 100644 --- a/TCP.h +++ b/TCP.h @@ -1,5 +1,4 @@ -#include "include.h" -#include +#include "Socket.h" /* class TCPSocket @@ -8,7 +7,7 @@ class TCPSocket setblocking(nonblocking: boolean) listen([ip: string], port: int, [backlog: int]) Address default to 0.0.0.0, backlog default to 10. - # Blocking mode: All non-expected error will be raised as exception. + # Blocking mode: All unexpected error will be raised as exception. connect(ip: string, port: int) accept(): TCPSocket PeerIP PeerPort send(data: string) All data will be sent before return. @@ -20,12 +19,3 @@ class TCPSocket send(data: string) recv([maxsize: int]): string */ - -class TCPSocket -{ -public: - int fd; - bool nonblocking; - std::vector data; - int buffsz; -}; diff --git a/TCPWin.cpp b/TCPWin.cpp index fc62018..a987a46 100644 --- a/TCPWin.cpp +++ b/TCPWin.cpp @@ -9,19 +9,19 @@ using namespace std; int tcp_socket_dtor(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); if (s->fd > 0) { closesocket(s->fd); s->fd = -1; } - s->~TCPSocket(); + s->~SocketData(); return 0; } int tcp_socket_close(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); if (s->fd > 0) { closesocket(s->fd); @@ -32,7 +32,7 @@ int tcp_socket_close(lua_State* L) int tcp_socket_send(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); size_t sz; const char* str = luaL_checklstring(L, 2, &sz); size_t done = 0; @@ -59,7 +59,7 @@ int tcp_socket_send(lua_State* L) int tcp_socket_recv(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); int ret = recv(s->fd, s->data.data(), s->buffsz, 0); if (ret < 0) { @@ -79,14 +79,19 @@ int tcp_socket_recv(lua_State* L) int tcp_socket_connect(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); const char* ip = luaL_checkstring(L, 2); int port = luaL_checkinteger(L, 3); sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(ip); + if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_pton"); + return lua_error(L); + } addr.sin_port = htons(port); int ret = connect(s->fd, (const sockaddr*)&addr, sizeof(addr)); @@ -107,7 +112,7 @@ int tcp_socket_connect(lua_State* L) int tcp_socket_listen(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); const char* ip = NULL; int port; int backlog = 10; @@ -134,7 +139,12 @@ int tcp_socket_listen(lua_State* L) addr.sin_family = AF_INET; if (ip && strcmp(ip, "0.0.0.0")) { - addr.sin_addr.s_addr = inet_addr(ip); + if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_pton"); + return lua_error(L); + } } else { @@ -163,7 +173,7 @@ int tcp_socket_listen(lua_State* L) int tcp_socket_setblocking(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); luaL_checkany(L, 2); bool blocking = lua_toboolean(L, 2); if (blocking != s->nonblocking) @@ -199,7 +209,7 @@ int tcp_socket_accept(lua_State* L); void put_tcp_socket(lua_State* L, int fd, bool nonblocking) { - auto s = new (lua_newblock(L)) TCPSocket; + auto s = new (lua_newblock(L)) SocketData; if (luaL_newmetatable(L, "LuaEngineTCPSocket")) { lua_setfield_function(L, "__gc", tcp_socket_dtor); @@ -222,7 +232,7 @@ void put_tcp_socket(lua_State* L, int fd, bool nonblocking) int tcp_socket_accept(lua_State* L) { - auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); + auto s = lua_checkblock(L, 1, "LuaEngineTCPSocket"); sockaddr_in addr; int addrsz = sizeof(addr); int ret = accept(s->fd, (sockaddr*)&addr, &addrsz); @@ -237,7 +247,15 @@ int tcp_socket_accept(lua_State* L) return lua_error(L); } put_tcp_socket(L, ret, false); - lua_pushstring(L, inet_ntoa(addr.sin_addr)); + + char buffer[1024] = { 0 }; + if (inet_ntop(AF_INET, &addr.sin_addr, buffer, 1024) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_ntop"); + return lua_error(L); + } + lua_pushstring(L, buffer); lua_pushinteger(L, ntohs(addr.sin_port)); return 3; } diff --git a/UDP.cpp b/UDP.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/UDP.h b/UDP.h new file mode 100644 index 0000000..e54784e --- /dev/null +++ b/UDP.h @@ -0,0 +1,16 @@ +#include "Socket.h" + +/* +class UDPSocket + constructor() + close() + setblocking(nonblocking: boolean) + setbroadcast(isbroadcast: boolean) Broadcast default to false. + listen([ip: string], port: int) Address default to 0.0.0.0. + + connect(ip: string, port: int) + send(data: string) + recv([maxsize: int]): string. Default to 4KB. + sendto([ip: string], port: int, data: string) If ip is empty, default to 255.255.255.255 (broadcast) + recvfrom(): data: string, ip: string, port: int +*/ diff --git a/UDPWin.cpp b/UDPWin.cpp new file mode 100644 index 0000000..a4612e5 --- /dev/null +++ b/UDPWin.cpp @@ -0,0 +1,348 @@ +#include "UDP.h" + +#ifdef _WIN32 +#define _WIN32_WINNT 0x0A00 // Win10 +#include +#include + +int udp_socket_dtor(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + if (s->fd > 0) + { + closesocket(s->fd); + s->fd = -1; + } + s->~SocketData(); + return 0; +} + +int udp_socket_close(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + if (s->fd > 0) + { + closesocket(s->fd); + s->fd = -1; + } + return 0; +} + +int udp_socket_send(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + size_t sz; + const char* str = luaL_checklstring(L, 2, &sz); + int ret = send(s->fd, str, sz, 0); + if (ret < 0) + { + int errcode = WSAGetLastError(); + if (s->nonblocking && errcode == WSAEWOULDBLOCK) + { + lua_pushboolean(L, true); + return 1; + } + put_winerror(L, errcode, "send"); + return lua_error(L); + } + return 0; +} + +int udp_socket_recv(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + int ret = recv(s->fd, s->data.data(), s->buffsz, 0); + if (ret < 0) + { + int errcode = WSAGetLastError(); + if (s->nonblocking && errcode == WSAEWOULDBLOCK) + { + return 0; + } + put_winerror(L, errcode, "recv"); + return lua_error(L); + } + lua_pushlstring(L, s->data.data(), ret); + return 1; +} + +int udp_socket_sendto(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + const char* ip = NULL; + int port; + size_t sz; + const char* str = NULL; + if (lua_type(L, 2) == LUA_TSTRING) + { + ip = luaL_checkstring(L, 2); + port = luaL_checkinteger(L, 3); + str = luaL_checklstring(L, 4, &sz); + } + else + { + port = luaL_checkinteger(L, 2); + str = luaL_checklstring(L, 3, &sz); + } + + sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (ip && strcmp(ip, "255.255.255.255")) + { + if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_pton"); + return lua_error(L); + } + } + else + { + addr.sin_addr.s_addr = INADDR_BROADCAST; + } + int ret = sendto(s->fd, str, sz, 0, (const sockaddr*)&addr, sizeof(addr)); + if (ret < 0) + { + int errcode = WSAGetLastError(); + if (s->nonblocking && errcode == WSAEWOULDBLOCK) + { + lua_pushboolean(L, true); + return 1; + } + put_winerror(L, errcode, "sendto"); + return lua_error(L); + } + return 0; +} + +int udp_socket_recvfrom(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + sockaddr_in addr; + int addrlen = sizeof(addr); + int ret = recvfrom(s->fd, s->data.data(), s->buffsz, 0, (sockaddr*)&addr, &addrlen); + if (ret < 0) + { + int errcode = WSAGetLastError(); + if (s->nonblocking && errcode == WSAEWOULDBLOCK) + { + return 0; + } + put_winerror(L, errcode, "recvfrom"); + return lua_error(L); + } + char buffer[1024] = { 0 }; + if (inet_ntop(AF_INET, &addr.sin_addr, buffer, 1024) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_ntop"); + return lua_error(L); + } + + lua_pushlstring(L, s->data.data(), ret); + lua_pushstring(L, buffer); + lua_pushinteger(L, ntohs(addr.sin_port)); + return 3; +} + +int udp_socket_connect(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + const char* ip = luaL_checkstring(L, 2); + int port = luaL_checkinteger(L, 3); + + sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_pton"); + return lua_error(L); + } + addr.sin_port = htons(port); + + int ret = connect(s->fd, (const sockaddr*)&addr, sizeof(addr)); + if (ret < 0) + { + int errcode = WSAGetLastError(); + if (s->nonblocking && errcode == WSAEWOULDBLOCK) + { + lua_pushboolean(L, true); + return 1; + } + put_winerror(L, errcode, "connect"); + return lua_error(L); + } + + return 0; +} + +int udp_socket_setblocking(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + luaL_checkany(L, 2); + bool blocking = lua_toboolean(L, 2); + if (blocking != s->nonblocking) + { + return 0; + } + if (blocking) // set to blocking + { + u_long arg = 0; + int ret = ioctlsocket(s->fd, FIONBIO, &arg); + if (ret) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "ioctlsocket"); + return lua_error(L); + } + } + else // set to nonblocking + { + u_long arg = 1; + int ret = ioctlsocket(s->fd, FIONBIO, &arg); + if (ret) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "ioctlsocket"); + return lua_error(L); + } + } + return 0; +} + +int udp_socket_setbroadcast(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + socklen_t opt = 0; + if (!lua_isnone(L, 2) && lua_toboolean(L, 2)) + { + opt = 1; + } + + int ret = setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(opt)); + if (ret < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "setsockopt"); + return lua_error(L); + } + + return 0; +} + +int udp_socket_listen(lua_State* L) +{ + auto s = lua_checkblock(L, 1, "LuaEngineUDPSocket"); + const char* ip = NULL; + int port; + if (lua_type(L, 2) == LUA_TSTRING) + { + ip = luaL_checkstring(L, 2); + port = luaL_checkinteger(L, 3); + } + else + { + port = luaL_checkinteger(L, 2); + } + + sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + if (ip && strcmp(ip, "0.0.0.0")) + { + if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "inet_pton"); + return lua_error(L); + } + } + else + { + addr.sin_addr.s_addr = INADDR_ANY; + } + addr.sin_port = htons(port); + + int ret = bind(s->fd, (const sockaddr*)&addr, sizeof(addr)); + if (ret < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "bind"); + return lua_error(L); + } + + return 0; +} + +void put_udp_socket(lua_State* L, int fd, bool nonblocking) +{ + auto s = new (lua_newblock(L)) SocketData; + if (luaL_newmetatable(L, "LuaEngineUDPSocket")) + { + lua_setfield_function(L, "__gc", udp_socket_dtor); + lua_newtable(L); + lua_setfield_function(L, "close", udp_socket_close); + lua_setfield_function(L, "send", udp_socket_send); + lua_setfield_function(L, "recv", udp_socket_recv); + lua_setfield_function(L, "sendto", udp_socket_sendto); + lua_setfield_function(L, "recvfrom", udp_socket_recvfrom); + lua_setfield_function(L, "listen", udp_socket_listen); + lua_setfield_function(L, "connect", udp_socket_connect); + lua_setfield_function(L, "setblocking", udp_socket_setblocking); + lua_setfield_function(L, "setbroadcast", udp_socket_setbroadcast); + lua_setfield(L, -2, "__index"); + } + lua_setmetatable(L, -2); + s->fd = fd; + s->nonblocking = nonblocking; + s->buffsz = 4096; + s->data.resize(s->buffsz); +} + +int udp_socket_new(lua_State* L) +{ + bool nonblocking = false; + if (!lua_isnone(L, 1)) + { + if (lua_toboolean(L, 1)) + { + nonblocking = true; + } + } + int fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) + { + int errcode = WSAGetLastError(); + put_winerror(L, errcode, "socket"); + return lua_error(L); + } + if (nonblocking) + { + u_long arg = 1; + int ret = ioctlsocket(fd, FIONBIO, &arg); + if (ret) + { + int errcode = WSAGetLastError(); + closesocket(fd); + put_winerror(L, errcode, "ioctlsocket"); + return lua_error(L); + } + } + put_udp_socket(L, fd, nonblocking); + return 1; +} + +void InitUDPSocket(lua_State* L) +{ + lua_getglobal(L, "package"); + lua_getfield(L, -1, "loaded"); + lua_pushcfunction(L, udp_socket_new); + lua_setfield(L, -2, "UDPSocket"); + lua_pop(L, 2); +} + +#endif // end of _WIN32 diff --git a/include.h b/include.h index 2db443b..3fb46bc 100644 --- a/include.h +++ b/include.h @@ -33,6 +33,12 @@ T* lua_checkblock(lua_State* L, int idx, const char* name) return (T*)luaL_checkudata(L, idx, name); } +template +T* lua_testblock(lua_State* L, int idx, const char* name) +{ + return (T*)luaL_testudata(L, idx, name); +} + // Shared Functions void put_surface(lua_State* L, SDL_Surface* surf); void put_texture(lua_State* L, SDL_Texture* text); @@ -45,6 +51,8 @@ void InitMusic(lua_State* L); void InitEvent(lua_State* L); void InitCommon(lua_State* L); void InitTCPSocket(lua_State* L); +void InitUDPSocket(lua_State* L); +void InitNetwork(lua_State* L); void InitThread(lua_State* L); void InitSocketSelector(lua_State* L); diff --git a/main.cpp b/main.cpp index 44721c9..0a2be8f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ #include "LuaEngine.h" #include #include +#include using namespace std; string LoadFile(const string& filename) @@ -28,7 +29,8 @@ int main() lua_State* L = luaL_newstate(); luaL_openlibs(L); InitLuaEngine(L); - string code = LoadFile("game/app.lua"); + _chdir("game"); + string code = LoadFile("test.lua"); if (luaL_loadstring(L, code.c_str())) { cout << lua_tostring(L, -1) << endl;