Files
BusyRabbit/Plugins/slua_unreal/External/luasocket/serial.cpp
2025-07-09 01:08:35 +08:00

201 lines
6.6 KiB
C++

/*=========================================================================*\
* Serial stream
* LuaSocket toolkit
\*=========================================================================*/
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "luasocket.h"
#include "auxiliar.h"
#include "socket.h"
#include "options.h"
#include "unix.h"
#ifndef _WIN32
#include <sys/un.h>
#endif
/*
Reuses userdata definition from unix.h, since it is useful for all
stream-like objects.
If we stored the serial path for use in error messages or userdata
printing, we might need our own userdata definition.
Group usage is semi-inherited from unix.c, but unnecessary since we
have only one object type.
*/
namespace NS_SLUA {
/*=========================================================================*\
* Internal function prototypes
\*=========================================================================*/
static int serial_global_create(lua_State *L);
static int serial_meth_send(lua_State *L);
static int serial_meth_receive(lua_State *L);
static int serial_meth_close(lua_State *L);
static int serial_meth_settimeout(lua_State *L);
static int serial_meth_getfd(lua_State *L);
static int serial_meth_setfd(lua_State *L);
static int serial_meth_dirty(lua_State *L);
static int serial_meth_getstats(lua_State *L);
static int serial_meth_setstats(lua_State *L);
/* serial object methods */
static luaL_Reg serial_methods[] = {
{"__gc", serial_meth_close},
{"__tostring", auxiliar_tostring},
{"close", serial_meth_close},
{"dirty", serial_meth_dirty},
{"getfd", serial_meth_getfd},
{"getstats", serial_meth_getstats},
{"setstats", serial_meth_setstats},
{"receive", serial_meth_receive},
{"send", serial_meth_send},
{"setfd", serial_meth_setfd},
{"settimeout", serial_meth_settimeout},
{NULL, NULL}
};
/* our socket creation function */
/* this is an ad-hoc module that returns a single function
* as such, do not include other functions in this array. */
static luaL_Reg serial_func[] = {
{"serial", serial_global_create},
{NULL, NULL}
};
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
/* create classes */
auxiliar_newclass(L, "serial{client}", serial_methods);
/* create class groups */
auxiliar_add2group(L, "serial{client}", "serial{any}");
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
lua_pushcfunction(L, serial_global_create);
(void)serial_func;
#else
/* set function into socket namespace */
luaL_openlib(L, "socket", serial_func, 0);
lua_pushcfunction(L, serial_global_create);
#endif
return 1;
}
/*=========================================================================*\
* Lua methods
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Just call buffered IO methods
\*-------------------------------------------------------------------------*/
static int serial_meth_send(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
return buffer_meth_send(L, &un->buf);
}
static int serial_meth_receive(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
return buffer_meth_receive(L, &un->buf);
}
static int serial_meth_getstats(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
return buffer_meth_getstats(L, &un->buf);
}
static int serial_meth_setstats(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
return buffer_meth_setstats(L, &un->buf);
}
/*-------------------------------------------------------------------------*\
* Select support methods
\*-------------------------------------------------------------------------*/
static int serial_meth_getfd(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
lua_pushnumber(L, (int) un->sock);
return 1;
}
/* this is very dangerous, but can be handy for those that are brave enough */
static int serial_meth_setfd(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
un->sock = (t_socket) luaL_checknumber(L, 2);
return 0;
}
static int serial_meth_dirty(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
lua_pushboolean(L, !buffer_isempty(&un->buf));
return 1;
}
/*-------------------------------------------------------------------------*\
* Closes socket used by object
\*-------------------------------------------------------------------------*/
static int serial_meth_close(lua_State *L)
{
p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
socket_destroy(&un->sock);
lua_pushnumber(L, 1);
return 1;
}
/*-------------------------------------------------------------------------*\
* Just call tm methods
\*-------------------------------------------------------------------------*/
static int serial_meth_settimeout(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
return timeout_meth_settimeout(L, &un->tm);
}
/*=========================================================================*\
* Library functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Creates a serial object
\*-------------------------------------------------------------------------*/
static int serial_global_create(lua_State *L) {
#ifndef _WIN32
const char* path = luaL_checkstring(L, 1);
/* allocate unix object */
p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
/* open serial device */
t_socket sock = open(path, O_NOCTTY|O_RDWR);
/*printf("open %s on %d\n", path, sock);*/
if (sock < 0) {
lua_pushnil(L);
lua_pushstring(L, socket_strerror(errno));
lua_pushnumber(L, errno);
return 3;
}
/* set its type as client object */
auxiliar_setclass(L, "serial{client}", -1);
/* initialize remaining structure fields */
socket_setnonblocking(&sock);
un->sock = sock;
io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
(p_error) socket_ioerror, &un->sock);
timeout_init(&un->tm, -1, -1);
buffer_init(&un->buf, &un->io, &un->tm);
return 1;
#else
return -1;
#endif
}
} // end NS_SLUA