1
0
mirror of https://github.com/lxsang/antd-lua-plugin synced 2024-12-26 17:38:21 +01:00

improvement and add more lua C wrappers

This commit is contained in:
DanyLE 2022-08-30 16:31:45 +02:00
parent b83beb5a16
commit e6004d8ccd
3 changed files with 210 additions and 45 deletions

View File

@ -1,5 +1,15 @@
#include <antd/ws.h> #include <antd/ws.h>
#include <antd/base64.h> #include <antd/base64.h>
#include <poll.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <time.h>
#include <fcntl.h>
#include "../lualib.h" #include "../lualib.h"
// add a length field, and // add a length field, and
void lua_new_byte_array(lua_State *L, int n) void lua_new_byte_array(lua_State *L, int n)
@ -724,6 +734,148 @@ static int l_is_dir(lua_State *L)
return 1; return 1;
} }
static int l_pfork(lua_State* L)
{
antd_client_t* client = (antd_client_t*)lua_touserdata(L,1);
int sock = client->sock;
// create domain socket
struct sockaddr_un address;
address.sun_family = AF_UNIX;
(void)snprintf(address.sun_path, sizeof(address.sun_path), "/tmp/antd_pfork_%d.sock",sock);
unlink(address.sun_path);
int pfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(pfd == -1)
{
ERROR( "Unable to create Unix domain socket: %s", strerror(errno));
lua_pushnumber(L, -1);
return 1;
}
if (bind(pfd, (struct sockaddr *)(&address), sizeof(address)) == -1)
{
ERROR("Unable to bind name: %s to a socket: %s", address.sun_path, strerror(errno));
lua_pushnumber(L, -1);
return 1;
}
// mark the socket as passive mode
if (listen(pfd, 10) == -1)
{
ERROR("Unable to listen to socket: %d (%s): %s", pfd, address.sun_path, strerror(errno));
lua_pushnumber(L, -1);
close(pfd);
return 1;
}
LOG( "Socket %s is created successfully", address.sun_path);
set_nonblock(pfd);
int pid = fork();
if(pid == 0)
{
int child = socket(AF_UNIX, SOCK_STREAM, 0);
if(child == -1)
{
ERROR( "Unable to create Unix domain socket: %s", strerror(errno));
lua_pushnumber(L, -1);
return -1;
}
if(connect(child, (struct sockaddr*)(&address), sizeof(address)) == -1)
{
ERROR( "Unable to connect to socket '%s': %s", address.sun_path, strerror(errno));
lua_pushnumber(L, -1);
close(child);
return -1;
}
client->sock = child;
client->z_level = ANTD_CNONE;
lua_pushnumber(L, 0);
}
else
{
int ret, status;
struct pollfd pfds[2];
pfds[0].fd = pfd;
pfds[0].events = POLLIN;
ret = poll(pfds, 1, -1);
if(ret < 0 || (pfds[0].revents & (POLLERR | POLLHUP)))
{
ERROR("Unable to wait for child process");
lua_pushnumber(L, -1);
close(pfd);
return 1;
}
// now wait for child process
int cfd = accept(pfd, NULL, NULL);
if(cfd == -1)
{
ERROR("Unable to connect to child process");
lua_pushnumber(L, -1);
close(pfd);
return 1;
}
LOG("Child process %d is accessible from %d", pid, cfd);
set_nonblock(cfd);
uint8_t buff[BUFFLEN];
pfds[0].fd = sock;
pfds[0].events = POLLIN;
pfds[1].fd = cfd;
pfds[1].events = POLLIN;
memset(buff, 0, sizeof(buff));
while((ret = poll(pfds, 2, 200)) != -1)
{
if(waitpid(pid, &status, WNOHANG) != 0)
{
break;
}
if(ret == 0)
{
continue;
}
if(pfds[0].revents & POLLIN)
{
ret = read(client->sock,buff, BUFFLEN);
if(ret <= 0)
{
LOG("antd_recv_upto() on %d: %s",sock, strerror(errno));
break;
}
// write data to the other side
if(write(cfd,buff, ret) != ret)
{
ERROR("Error on send(): %s", strerror(errno));
break;
}
}
else if (pfds[0].revents &(POLLERR | POLLHUP))
{
break;
}
if(pfds[1].revents & POLLIN)
{
ret = read(cfd, buff, sizeof(buff));
if(ret <= 0)
{
ERROR("error read() on %d: %s",cfd, strerror(errno));
break;
}
if(antd_send(client,buff, ret) != ret)
{
ERROR("Error atnd_send(): %s", strerror(errno));
break;
}
}
else if (pfds[1].revents &(POLLERR | POLLHUP))
{
break;
}
}
close(cfd);
}
close(pfd);
unlink(address.sun_path);
lua_pushnumber(L, pid);
return 1;
}
static int l_std_error(lua_State *L) static int l_std_error(lua_State *L)
{ {
void *client = lua_touserdata(L, 1); void *client = lua_touserdata(L, 1);
@ -804,6 +956,7 @@ static const struct luaL_Reg standard[] = {
{"ws_b", l_ws_bin}, {"ws_b", l_ws_bin},
{"ws_close", l_ws_close}, {"ws_close", l_ws_close},
{"is_dir", l_is_dir}, {"is_dir", l_is_dir},
{"pfork", l_pfork},
{NULL, NULL}}; {NULL, NULL}};
int luaopen_std(lua_State *L) int luaopen_std(lua_State *L)

View File

@ -37,7 +37,7 @@ static int l_check_login (lua_State *L) {
if (pwd == NULL) if (pwd == NULL)
{ {
lua_pushboolean(L,0); lua_pushboolean(L,0);
printf("Cannot find pwd record of %s\n", username ); ERROR("Cannot find pwd record of %s", username );
return 1; return 1;
} }
spwd = getspnam(username); spwd = getspnam(username);
@ -63,25 +63,23 @@ static int l_check_login (lua_State *L) {
if (encrypted == NULL) if (encrypted == NULL)
{ {
lua_pushboolean(L,0); lua_pushboolean(L,0);
printf("Cant crypt \n" ); ERROR("Cant crypt %s", strerror(errno) );
return 1; return 1;
} }
if(strcmp(encrypted, pwd->pw_passwd) == 0) if(strcmp(encrypted, pwd->pw_passwd) == 0)
{ {
lua_pushboolean(L,1); lua_pushboolean(L,1);
printf("%s\n","Successful login" );
return 1; return 1;
} else } else
{ {
lua_pushboolean(L,0); lua_pushboolean(L,0);
printf("Password incorrect \n" );
return 1; return 1;
} }
#else #else
// macos // macos
// just pass the check, for test only // just pass the check, for test only
lua_pushboolean(L,1); lua_pushboolean(L,0);
printf("%s\n","Successful login" ); ERROR("Login by shadow passd is not supported on this system");
return 1; return 1;
#endif #endif
} }
@ -117,6 +115,7 @@ static int l_fork(lua_State* L)
lua_pushnumber(L, pid); lua_pushnumber(L, pid);
return 1; return 1;
} }
static int l_waitpid(lua_State* L) static int l_waitpid(lua_State* L)
{ {
int pid = luaL_checknumber(L,1); int pid = luaL_checknumber(L,1);
@ -138,7 +137,7 @@ static int l_kill(lua_State* L)
{ {
int pid = luaL_checknumber(L,1); int pid = luaL_checknumber(L,1);
if(pid == -1) pid = getpid(); if(pid == -1) pid = getpid();
int status = kill(pid, SIGKILL); int status = kill(pid, SIGHUP);
lua_pushnumber(L, status); lua_pushnumber(L, status);
return 1; return 1;
} }
@ -149,7 +148,7 @@ static int l_setuid(lua_State* L)
{ {
if(setuid(uid) < 0) if(setuid(uid) < 0)
{ {
printf("UID set problem: %s\n", strerror(errno)); ERROR("UID set problem: %s", strerror(errno));
lua_pushboolean(L,0); lua_pushboolean(L,0);
} }
else else
@ -169,7 +168,7 @@ static int l_setgid(lua_State* L)
{ {
if(setgid(gid) < 0) if(setgid(gid) < 0)
{ {
printf("GID set problem: %s\n", strerror(errno)); ERROR("GID set problem: %s", strerror(errno));
lua_pushboolean(L,0); lua_pushboolean(L,0);
} }
else else
@ -214,12 +213,12 @@ static int l_getuid(lua_State* L)
/* Retrieve group list */ /* Retrieve group list */
groups = malloc(ngroups * sizeof (gid_t)); groups = malloc(ngroups * sizeof (gid_t));
if (groups == NULL) { if (groups == NULL) {
LOG("malloc eror \n"); LOG("malloc eror");
return 1; return 1;
} }
if (getgrouplist(name, gid, groups, &ngroups) == -1) { if (getgrouplist(name, gid, groups, &ngroups) == -1) {
free(groups); free(groups);
LOG("getgrouplist() returned -1; ngroups = %d\n", ngroups); LOG("getgrouplist() returned -1; ngroups = %d", ngroups);
return 1; return 1;
} }
/* retrieved groups, along with group names */ /* retrieved groups, along with group names */

View File

@ -12,8 +12,8 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/select.h>
#include <time.h> #include <time.h>
#include <poll.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
#include <sys/time.h> #include <sys/time.h>
@ -25,7 +25,6 @@
#define MAX_SOCK_NAME 64 #define MAX_SOCK_NAME 64
#define SOCKET_NAME "lua.sock" #define SOCKET_NAME "lua.sock"
#define MAX_SESSION_TIMEOUT (15u * 60u) //15 min
#define PING_INTERVAL 10u // 10s #define PING_INTERVAL 10u // 10s
#define PROCESS_TIMEOUT 200u //100ms #define PROCESS_TIMEOUT 200u //100ms
@ -72,12 +71,14 @@ static int mk_socket()
if (bind(fd, (struct sockaddr *)(&address), sizeof(address)) == -1) if (bind(fd, (struct sockaddr *)(&address), sizeof(address)) == -1)
{ {
ERROR("Unable to bind name: %s to a socket: %s", address.sun_path, strerror(errno)); ERROR("Unable to bind name: %s to a socket: %s", address.sun_path, strerror(errno));
close(fd);
return -1; return -1;
} }
// mark the socket as passive mode // mark the socket as passive mode
if (listen(fd, 500) == -1) if (listen(fd, 500) == -1)
{ {
ERROR("Unable to listen to socket: %d (%s): %s", fd, sock_path, strerror(errno)); ERROR("Unable to listen to socket: %d (%s): %s", fd, sock_path, strerror(errno));
close(fd);
return -1; return -1;
} }
LOG("Socket %s is created successfully: %d", sock_path, fd); LOG("Socket %s is created successfully: %d", sock_path, fd);
@ -123,25 +124,25 @@ static void lua_serve()
ERROR("Unable to set reuse address on %d - setsockopt: %s", socket, strerror(errno)); ERROR("Unable to set reuse address on %d - setsockopt: %s", socket, strerror(errno));
} }
LOG("LUA server online"); LOG("LUA server online");
/*set log level*/ /*set log level*/
const char * enable_debug = getenv("ANTD_DEBUG"); const char * enable_debug = getenv("ANTD_DEBUG");
int log_level = LOG_ERR; int log_level = LOG_ERR;
if(enable_debug) if(enable_debug)
{ {
if(atoi(enable_debug)) if(atoi(enable_debug))
{ {
LOG("LUA Debug is enabled"); LOG("LUA Debug is enabled");
log_level = LOG_NOTICE; log_level = LOG_NOTICE;
} }
} }
setlogmask(LOG_UPTO(log_level)); setlogmask(LOG_UPTO(log_level));
while((fd = accept(socket, NULL, NULL)) > 0) while((fd = accept(socket, NULL, NULL)) > 0)
{ {
pthread_t thread; pthread_t thread;
lua_thread_data_t* data = (lua_thread_data_t*)malloc(sizeof(lua_thread_data_t)); lua_thread_data_t* data = (lua_thread_data_t*)malloc(sizeof(lua_thread_data_t));
data->__plugin__ = &__plugin__; data->__plugin__ = &__plugin__;
data->fd = fd; data->fd = fd;
set_nonblock(fd); //set_nonblock(fd);
if (pthread_create(&thread, NULL, (void *(*)(void*))handle_fn, (void *)data) != 0) if (pthread_create(&thread, NULL, (void *(*)(void*))handle_fn, (void *)data) != 0)
{ {
ERROR("pthread_create: cannot create lua thread: %s", strerror(errno)); ERROR("pthread_create: cannot create lua thread: %s", strerror(errno));
@ -168,7 +169,7 @@ static void lua_serve()
void init() void init()
{ {
(void)snprintf(sock_path, sizeof(sock_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME); (void)snprintf(sock_path, sizeof(sock_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME);
LOG("Lua socket will be stored in %s", sock_path); LOG("Lua socket will be stored in %s", sock_path);
pid = fork(); pid = fork();
if (pid == 0) if (pid == 0)
@ -203,26 +204,24 @@ static void push_dict_to_socket(antd_client_t* cl, char* name, char* parent_name
static void *process(void *data) static void *process(void *data)
{ {
fd_set fd_in;
antd_request_t *rq = (antd_request_t *)data; antd_request_t *rq = (antd_request_t *)data;
antd_client_t* cl = (antd_client_t* ) dvalue(rq->request, "LUA_CL_DATA"); antd_client_t* cl = (antd_client_t* ) dvalue(rq->request, "LUA_CL_DATA");
struct timeval timeout; struct pollfd pfds[2];
timeout.tv_sec = 0; pfds[0].fd = rq->client->sock;
timeout.tv_usec = PROCESS_TIMEOUT; pfds[0].events = POLLIN;
FD_ZERO(&fd_in); pfds[1].fd = cl->sock;
FD_SET(rq->client->sock, &fd_in); pfds[1].events = POLLIN;
FD_SET(cl->sock, &fd_in);
int max_fdm = rq->client->sock > cl->sock ? rq->client->sock : cl->sock; int rc = poll(pfds, 2, PROCESS_TIMEOUT);
int rc = select(max_fdm + 1, &fd_in, NULL, NULL, &timeout);
antd_task_t* task; antd_task_t* task;
uint8_t buff[BUFFLEN]; uint8_t buff[BUFFLEN];
int ret; int ret;
switch (rc) switch (rc)
{ {
case -1: case -1:
ERROR("Error on select(): %s", strerror(errno)); ERROR("Error on poll(): %s", strerror(errno));
antd_close(cl); antd_close(cl);
dput(rq->request, "LUA_CL_DATA", NULL); dput(rq->request, "LUA_CL_DATA", NULL);
return antd_create_task(NULL, data, NULL, rq->client->last_io); return antd_create_task(NULL, data, NULL, rq->client->last_io);
case 0: case 0:
// time out // time out
@ -233,7 +232,7 @@ static void *process(void *data)
// we have data // we have data
default: default:
// If data is on webserver // If data is on webserver
if (FD_ISSET(rq->client->sock, &fd_in)) if (pfds[0].revents & POLLIN)
{ {
while((ret = antd_recv_upto(rq->client,buff, BUFFLEN)) > 0) while((ret = antd_recv_upto(rq->client,buff, BUFFLEN)) > 0)
{ {
@ -242,7 +241,7 @@ static void *process(void *data)
{ {
ERROR("Error on atnd_send(): %s", strerror(errno)); ERROR("Error on atnd_send(): %s", strerror(errno));
antd_close(cl); antd_close(cl);
dput(rq->request, "LUA_CL_DATA", NULL); dput(rq->request, "LUA_CL_DATA", NULL);
return antd_create_task(NULL, data, NULL, rq->client->last_io); return antd_create_task(NULL, data, NULL, rq->client->last_io);
} }
} }
@ -250,11 +249,18 @@ static void *process(void *data)
{ {
LOG("antd_recv_upto() on %d: %s",rq->client->sock, strerror(errno)); LOG("antd_recv_upto() on %d: %s",rq->client->sock, strerror(errno));
antd_close(cl); antd_close(cl);
dput(rq->request, "LUA_CL_DATA", NULL); dput(rq->request, "LUA_CL_DATA", NULL);
return antd_create_task(NULL, data, NULL, rq->client->last_io); return antd_create_task(NULL, data, NULL, rq->client->last_io);
} }
} }
else if(FD_ISSET(cl->sock, &fd_in)) else if(pfds[0].revents &(POLLERR | POLLHUP))
{
ERROR("POLLERR or POLLHUP received on %d", rq->client->sock);
antd_close(cl);
dput(rq->request, "LUA_CL_DATA", NULL);
return antd_create_task(NULL, data, NULL, rq->client->last_io);
}
if(pfds[1].revents & POLLIN)
{ {
while((ret = antd_recv_upto(cl,buff, BUFFLEN)) > 0) while((ret = antd_recv_upto(cl,buff, BUFFLEN)) > 0)
{ {
@ -263,7 +269,7 @@ static void *process(void *data)
{ {
ERROR("Error atnd_send(): %s", strerror(errno)); ERROR("Error atnd_send(): %s", strerror(errno));
antd_close(cl); antd_close(cl);
dput(rq->request, "LUA_CL_DATA", NULL); dput(rq->request, "LUA_CL_DATA", NULL);
return antd_create_task(NULL, data, NULL, rq->client->last_io); return antd_create_task(NULL, data, NULL, rq->client->last_io);
} }
} }
@ -271,10 +277,17 @@ static void *process(void *data)
{ {
LOG("antd_recv_upto() on %d: %s", cl->sock, strerror(errno)); LOG("antd_recv_upto() on %d: %s", cl->sock, strerror(errno));
antd_close(cl); antd_close(cl);
dput(rq->request, "LUA_CL_DATA", NULL); dput(rq->request, "LUA_CL_DATA", NULL);
return antd_create_task(NULL, data, NULL, rq->client->last_io); return antd_create_task(NULL, data, NULL, rq->client->last_io);
} }
} }
else if(pfds[1].revents &(POLLERR | POLLHUP))
{
ERROR("POLLERR or POLLHUP received on %d", cl->sock);
antd_close(cl);
dput(rq->request, "LUA_CL_DATA", NULL);
return antd_create_task(NULL, data, NULL, rq->client->last_io);
}
task = antd_create_task(process, (void *)rq, NULL, time(NULL)); task = antd_create_task(process, (void *)rq, NULL, time(NULL));
antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE);
antd_task_bind_event(task, cl->sock, 0, TASK_EVT_ON_READABLE); antd_task_bind_event(task, cl->sock, 0, TASK_EVT_ON_READABLE);
@ -304,7 +317,7 @@ void* handle(void* data)
cl->z_status = 0; cl->z_status = 0;
cl->z_level = ANTD_CNONE; cl->z_level = ANTD_CNONE;
cl->zstream = NULL; cl->zstream = NULL;
rq->client->z_level = ANTD_CNONE; rq->client->z_level = ANTD_CNONE;
push_dict_to_socket(cl, "request","HTTP_REQUEST", rq->request); push_dict_to_socket(cl, "request","HTTP_REQUEST", rq->request);
antd_send(cl,"\r\n", 2); antd_send(cl,"\r\n", 2);
dput(rq->request, "LUA_CL_DATA", cl); dput(rq->request, "LUA_CL_DATA", cl);