2020-05-24 05:24:13 +08:00
|
|
|
#include "Select.h"
|
2020-05-29 01:39:49 +08:00
|
|
|
#include "Socket.h"
|
2020-05-24 05:24:13 +08:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#define _WIN32_WINNT 0x0A00 // Win10
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
#include <vector>
|
|
|
|
using namespace std;
|
|
|
|
|
2020-05-29 01:39:49 +08:00
|
|
|
inline void luatable_to_fdset(lua_State* L, int tbl_index, fd_set& fds)
|
2020-05-24 05:24:13 +08:00
|
|
|
{
|
|
|
|
lua_pushnil(L);
|
2020-05-29 01:39:49 +08:00
|
|
|
while (lua_next(L, tbl_index))
|
2020-05-24 05:24:13 +08:00
|
|
|
{
|
|
|
|
lua_pop(L, 1);
|
2020-05-29 01:39:49 +08:00
|
|
|
auto s = lua_testblock<SocketData>(L, -1, "LuaEngineTCPSocket") ? lua_checkblock<SocketData>(L, -1, "LuaEngineTCPSocket") : lua_checkblock<SocketData>(L, -1, "LuaEngineUDPSocket");
|
2020-05-24 05:24:13 +08:00
|
|
|
if (s->fd > 0)
|
|
|
|
{
|
2020-05-29 01:39:49 +08:00
|
|
|
FD_SET(s->fd, &fds);
|
2020-05-24 05:24:13 +08:00
|
|
|
}
|
|
|
|
}
|
2020-05-29 01:39:49 +08:00
|
|
|
}
|
2020-05-24 05:24:13 +08:00
|
|
|
|
2020-05-29 01:39:49 +08:00
|
|
|
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))
|
2020-05-24 05:24:13 +08:00
|
|
|
{
|
2020-05-29 01:39:49 +08:00
|
|
|
lua_pop(L, 1); // ... RetT Socket
|
|
|
|
auto s = lua_testblock<SocketData>(L, -1, "LuaEngineTCPSocket") ? lua_checkblock<SocketData>(L, -1, "LuaEngineTCPSocket") : lua_checkblock<SocketData>(L, -1, "LuaEngineUDPSocket");
|
|
|
|
if (s->fd > 0 && FD_ISSET(s->fd, &fds))
|
2020-05-24 05:24:13 +08:00
|
|
|
{
|
2020-05-29 01:39:49 +08:00
|
|
|
lua_pushvalue(L, -1); // ... RetT Socket Socket
|
|
|
|
lua_pushboolean(L, true); // ... RetT Socket Socket true
|
|
|
|
lua_settable(L, -4); // ... RetT Socket
|
2020-05-24 05:24:13 +08:00
|
|
|
}
|
|
|
|
}
|
2020-05-29 01:39:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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_ZERO(&readset);
|
|
|
|
luatable_to_fdset(L, 1, readset);
|
|
|
|
|
|
|
|
FD_ZERO(&writeset);
|
|
|
|
luatable_to_fdset(L, 2, writeset);
|
2020-05-24 05:24:13 +08:00
|
|
|
|
|
|
|
FD_ZERO(&errorset);
|
2020-05-29 01:39:49 +08:00
|
|
|
luatable_to_fdset(L, 3, errorset);
|
2020-05-24 05:24:13 +08:00
|
|
|
|
|
|
|
timeval tm;
|
|
|
|
tm.tv_sec = us / 1000000;
|
|
|
|
tm.tv_usec = us % 1000000;
|
|
|
|
|
|
|
|
int ret = select(1024, &readset, &writeset, &errorset, &tm);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
int errcode = WSAGetLastError();
|
|
|
|
put_winerror(L, errcode, "select");
|
|
|
|
return lua_error(L);
|
|
|
|
}
|
|
|
|
else if (ret == 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-29 01:39:49 +08:00
|
|
|
fdset_to_luatable(L, 1, readset); // +1
|
|
|
|
fdset_to_luatable(L, 2, writeset); // +1
|
|
|
|
fdset_to_luatable(L, 3, errorset); // +1
|
2020-05-24 05:24:13 +08:00
|
|
|
|
|
|
|
return 3; // ... RetT RetT RetT
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitSocketSelector(lua_State* L)
|
|
|
|
{
|
|
|
|
lua_getglobal(L, "package");
|
|
|
|
lua_getfield(L, -1, "loaded");
|
|
|
|
lua_pushcfunction(L, select_call);
|
|
|
|
lua_setfield(L, -2, "select");
|
|
|
|
lua_pop(L, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // End of _WIN32
|