mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-26 12:28:21 +01:00
Add. acceptfd method.
socket.tcp can accept fd and socket type ('master'(default), 'client') acceptfd method can be used to write multi-threaded server. ```lua -- main thread local fd = srv_sock:acceptfd() Threads.runfile('echo.lua', fd) -- echo.lua local fd = ... local sock = socket.tcp(fd,'client') ``` or to interact with library such as [ESL](http://wiki.freeswitch.org/wiki/Event_Socket_Library) ```lua local fd = srv_sock:acceptfd() Threads.runfile('worker.lua', fd) -- worker.lua local sock = ESLconnection((...)) ``` If we need just close fd (for example we can not run worker thread) we should call `socket.tcp(fd,'client'):close()`
This commit is contained in:
parent
5341131cd0
commit
addee9d8fb
39
src/tcp.c
39
src/tcp.c
@ -3,6 +3,7 @@
|
|||||||
* LuaSocket toolkit
|
* LuaSocket toolkit
|
||||||
\*=========================================================================*/
|
\*=========================================================================*/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
@ -31,6 +32,7 @@ static int meth_getpeername(lua_State *L);
|
|||||||
static int meth_shutdown(lua_State *L);
|
static int meth_shutdown(lua_State *L);
|
||||||
static int meth_receive(lua_State *L);
|
static int meth_receive(lua_State *L);
|
||||||
static int meth_accept(lua_State *L);
|
static int meth_accept(lua_State *L);
|
||||||
|
static int meth_acceptfd(lua_State *L);
|
||||||
static int meth_close(lua_State *L);
|
static int meth_close(lua_State *L);
|
||||||
static int meth_getoption(lua_State *L);
|
static int meth_getoption(lua_State *L);
|
||||||
static int meth_setoption(lua_State *L);
|
static int meth_setoption(lua_State *L);
|
||||||
@ -44,6 +46,7 @@ static luaL_Reg tcp_methods[] = {
|
|||||||
{"__gc", meth_close},
|
{"__gc", meth_close},
|
||||||
{"__tostring", auxiliar_tostring},
|
{"__tostring", auxiliar_tostring},
|
||||||
{"accept", meth_accept},
|
{"accept", meth_accept},
|
||||||
|
{"acceptfd", meth_acceptfd},
|
||||||
{"bind", meth_bind},
|
{"bind", meth_bind},
|
||||||
{"close", meth_close},
|
{"close", meth_close},
|
||||||
{"connect", meth_connect},
|
{"connect", meth_connect},
|
||||||
@ -213,6 +216,28 @@ static int meth_accept(lua_State *L)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*\
|
||||||
|
* Waits for and returns a client object attempting connection to the
|
||||||
|
* server object
|
||||||
|
\*-------------------------------------------------------------------------*/
|
||||||
|
static int meth_acceptfd(lua_State *L)
|
||||||
|
{
|
||||||
|
p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp{server}", 1);
|
||||||
|
p_timeout tm = timeout_markstart(&server->tm);
|
||||||
|
t_socket sock;
|
||||||
|
const char *err = inet_tryaccept(&server->sock, server->family, &sock, tm);
|
||||||
|
/* if successful, push client socket */
|
||||||
|
if (err == NULL) {
|
||||||
|
lua_pushnumber(L, sock);
|
||||||
|
assert((t_socket)lua_tonumber(L, -1) == sock); // do we need check at runtime?
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushstring(L, err);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Binds an object to an address
|
* Binds an object to an address
|
||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
@ -356,14 +381,24 @@ static int meth_settimeout(lua_State *L)
|
|||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
static int tcp_create(lua_State *L, int family) {
|
static int tcp_create(lua_State *L, int family) {
|
||||||
t_socket sock;
|
t_socket sock;
|
||||||
const char *err = inet_trycreate(&sock, family, SOCK_STREAM);
|
const char *err;
|
||||||
|
const int is_inherite = lua_isnumber(L,1);
|
||||||
|
const char *obj_type = "tcp{master}";
|
||||||
|
if (is_inherite){
|
||||||
|
err = NULL;
|
||||||
|
sock = (t_socket)lua_tonumber(L, 1);
|
||||||
|
if(strstr(luaL_optstring(L,2,""),"client"))
|
||||||
|
obj_type = "tcp{client}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = inet_trycreate(&sock, family, SOCK_STREAM);
|
||||||
/* try to allocate a system socket */
|
/* try to allocate a system socket */
|
||||||
if (!err) {
|
if (!err) {
|
||||||
/* allocate tcp object */
|
/* allocate tcp object */
|
||||||
p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
|
p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
|
||||||
memset(tcp, 0, sizeof(t_tcp));
|
memset(tcp, 0, sizeof(t_tcp));
|
||||||
/* set its type as master object */
|
/* set its type as master object */
|
||||||
auxiliar_setclass(L, "tcp{master}", -1);
|
auxiliar_setclass(L, obj_type, -1);
|
||||||
/* initialize remaining structure fields */
|
/* initialize remaining structure fields */
|
||||||
socket_setnonblocking(&sock);
|
socket_setnonblocking(&sock);
|
||||||
if (family == PF_INET6) {
|
if (family == PF_INET6) {
|
||||||
|
22
test/test_acceptfd.lua
Normal file
22
test/test_acceptfd.lua
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
local socket = require "socket"
|
||||||
|
|
||||||
|
local host, port = "127.0.0.1", "5462"
|
||||||
|
|
||||||
|
local srv = assert(socket.bind(host, port))
|
||||||
|
|
||||||
|
local sock = socket.tcp()
|
||||||
|
assert(sock:connect(host, port))
|
||||||
|
|
||||||
|
local fd = assert(srv:acceptfd())
|
||||||
|
assert(type(fd) == "number")
|
||||||
|
|
||||||
|
local cli = assert(socket.tcp(fd, "client"))
|
||||||
|
|
||||||
|
assert(5 == assert(cli:send("hello")))
|
||||||
|
assert("hello" == assert(sock:receive(5)))
|
||||||
|
|
||||||
|
cli:close()
|
||||||
|
sock:close()
|
||||||
|
srv:close()
|
||||||
|
|
||||||
|
print("done!")
|
Loading…
Reference in New Issue
Block a user