summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2019-12-20 00:53:14 +0800
committerruki <[email protected]>2019-12-19 23:19:27 +0800
commit4ce400a33c26c4d59e76ccb5dc321fe6dabc60f7 (patch)
tree7fba42df02bab3ab2702ad57c896002b22cb6518
parentdb52fd10877391ebc89be2c6551b94901a31e7b6 (diff)
add unix socket support
-rw-r--r--core/src/xmake/io/socket_bind.c14
-rw-r--r--core/src/xmake/io/socket_connect.c14
-rw-r--r--tests/modules/socket/unix_tcp/echo_client.lua20
-rw-r--r--tests/modules/socket/unix_tcp/echo_server.lua31
-rw-r--r--tests/modules/socket/unix_tcp/file_client.lua34
-rw-r--r--tests/modules/socket/unix_tcp/file_server.lua22
-rw-r--r--xmake/core/base/socket.lua87
-rw-r--r--xmake/core/sandbox/modules/import/core/base/socket.lua27
8 files changed, 241 insertions, 8 deletions
diff --git a/core/src/xmake/io/socket_bind.c b/core/src/xmake/io/socket_bind.c
index 7f1bae584..dd3248084 100644
--- a/core/src/xmake/io/socket_bind.c
+++ b/core/src/xmake/io/socket_bind.c
@@ -56,15 +56,21 @@ tb_int_t xm_io_socket_bind(lua_State* lua)
tb_char_t const* address = lua_tostring(lua, 2);
tb_assert_and_check_return_val(address, 0);
- // get port
- tb_uint16_t port = (tb_uint16_t)luaL_checknumber(lua, 3);
-
// get family
tb_uint8_t family = (tb_uint8_t)luaL_checknumber(lua, 4);
// init address
tb_ipaddr_t addr;
- tb_ipaddr_set(&addr, address, port, family);
+ if (family == TB_IPADDR_FAMILY_UNIX)
+ {
+ tb_bool_t is_abstract = (tb_bool_t)lua_toboolean(lua, 3);
+ tb_ipaddr_unix_set_cstr(&addr, address, is_abstract);
+ }
+ else
+ {
+ tb_uint16_t port = (tb_uint16_t)luaL_checknumber(lua, 3);
+ tb_ipaddr_set(&addr, address, port, family);
+ }
// bind socket
lua_pushboolean(lua, tb_socket_bind(sock, &addr));
diff --git a/core/src/xmake/io/socket_connect.c b/core/src/xmake/io/socket_connect.c
index 68fe60d7d..d7a8faa4d 100644
--- a/core/src/xmake/io/socket_connect.c
+++ b/core/src/xmake/io/socket_connect.c
@@ -56,15 +56,21 @@ tb_int_t xm_io_socket_connect(lua_State* lua)
tb_char_t const* address = lua_tostring(lua, 2);
tb_assert_and_check_return_val(address, 0);
- // get port
- tb_uint16_t port = (tb_uint16_t)luaL_checknumber(lua, 3);
-
// get family
tb_uint8_t family = (tb_uint8_t)luaL_checknumber(lua, 4);
// init address
tb_ipaddr_t addr;
- tb_ipaddr_set(&addr, address, port, family);
+ if (family == TB_IPADDR_FAMILY_UNIX)
+ {
+ tb_bool_t is_abstract = (tb_bool_t)lua_toboolean(lua, 3);
+ tb_ipaddr_unix_set_cstr(&addr, address, is_abstract);
+ }
+ else
+ {
+ tb_uint16_t port = (tb_uint16_t)luaL_checknumber(lua, 3);
+ tb_ipaddr_set(&addr, address, port, family);
+ }
// connect socket
lua_pushnumber(lua, (tb_int_t)tb_socket_connect(sock, &addr));
diff --git a/tests/modules/socket/unix_tcp/echo_client.lua b/tests/modules/socket/unix_tcp/echo_client.lua
new file mode 100644
index 000000000..53788d428
--- /dev/null
+++ b/tests/modules/socket/unix_tcp/echo_client.lua
@@ -0,0 +1,20 @@
+import("core.base.socket")
+
+function main(addr)
+ addr = addr or path.join(os.tmpdir(), "echo.socket")
+ print("connect %s ..", addr)
+ local sock = socket.connect_unix(addr)
+ print("%s: connected!", sock)
+ local count = 0
+ while count < 10000 do
+ local send = sock:send("hello world..", {block = true})
+ if send > 0 then
+ sock:recv(13, {block = true})
+ else
+ break
+ end
+ count = count + 1
+ end
+ print("%s: send ok, count: %d!", sock, count)
+ sock:close()
+end
diff --git a/tests/modules/socket/unix_tcp/echo_server.lua b/tests/modules/socket/unix_tcp/echo_server.lua
new file mode 100644
index 000000000..7a2334095
--- /dev/null
+++ b/tests/modules/socket/unix_tcp/echo_server.lua
@@ -0,0 +1,31 @@
+import("core.base.socket")
+
+function main(addr)
+
+ addr = addr or path.join(os.tmpdir(), "echo.socket")
+ local sock = socket.bind_unix(addr)
+ sock:listen(20)
+ print("%s: listening %s ..", sock, addr)
+ while true do
+ local sock_client = sock:accept()
+ if sock_client then
+ print("%s: accepted", sock_client)
+ local count = 0
+ local result = nil
+ while true do
+ local recv, data = sock_client:recv(13, {block = true})
+ if recv > 0 then
+ result = data
+ sock_client:send(data, {block = true})
+ count = count + 1
+ else
+ break
+ end
+ end
+ print("%s: recv: %d, count: %d", sock_client, result and result:size() or 0, count)
+ result:dump()
+ sock_client:close()
+ end
+ end
+ sock:close()
+end
diff --git a/tests/modules/socket/unix_tcp/file_client.lua b/tests/modules/socket/unix_tcp/file_client.lua
new file mode 100644
index 000000000..3f870ae3f
--- /dev/null
+++ b/tests/modules/socket/unix_tcp/file_client.lua
@@ -0,0 +1,34 @@
+import("core.base.socket")
+
+function main(addr)
+ addr = addr or path.join(os.tmpdir(), "file.socket")
+ print("connect %s ..", addr)
+ local sock = socket.connect_unix(addr)
+ print("%s: connected!", sock)
+ local real = 0
+ local recv = 0
+ local data = nil
+ local wait = false
+ local results = {}
+ while true do
+ real, data = sock:recv(8192)
+ if real > 0 then
+ recv = recv + real
+ wait = false
+ table.insert(results, data)
+ elseif real == 0 and not wait then
+ if sock:wait(socket.EV_RECV, -1) == socket.EV_RECV then
+ wait = true
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if #results > 0 then
+ data = bytes(results)
+ end
+ print("%s: recv ok, size: %d, #data: %d!", sock, recv, data and data:size() or 0)
+ sock:close()
+end
diff --git a/tests/modules/socket/unix_tcp/file_server.lua b/tests/modules/socket/unix_tcp/file_server.lua
new file mode 100644
index 000000000..b17d71104
--- /dev/null
+++ b/tests/modules/socket/unix_tcp/file_server.lua
@@ -0,0 +1,22 @@
+import("core.base.socket")
+
+function main(filepath, addr)
+ addr = addr or path.join(os.tmpdir(), "file.socket")
+ local sock = socket.bind_unix(addr)
+ sock:listen(20)
+ print("%s: listening %s ..", sock, addr)
+ while true do
+ local sock_client = sock:accept()
+ if sock_client then
+ print("%s: accepted", sock_client)
+ local file = io.open(filepath, 'rb')
+ if file then
+ local send = sock_client:sendfile(file, {block = true})
+ print("%s: send %s %d bytes!", sock_client, filepath, send)
+ file:close()
+ end
+ sock_client:close()
+ end
+ end
+ sock:close()
+end
diff --git a/xmake/core/base/socket.lua b/xmake/core/base/socket.lua
index 8d6a62499..a20271ac2 100644
--- a/xmake/core/base/socket.lua
+++ b/xmake/core/base/socket.lua
@@ -104,6 +104,29 @@ function _instance:bind(addr, port)
return ok, errors
end
+-- bind socket from the unix address
+function _instance:bind_unix(addr, opt)
+
+ -- ensure opened
+ local ok, errors = self:_ensure_opened()
+ if not ok then
+ return -1, errors
+ end
+
+ -- must be unix socket
+ if self:family() ~= socket.UNIX then
+ return -1, string.format("%s: must be unix socket!", self)
+ end
+
+ -- bind it
+ opt = opt or {}
+ local ok, errors = io.socket_bind(self:csock(), addr, opt.is_abstract, self:family())
+ if not ok and errors then
+ errors = string.format("%s: %s", self, errors)
+ end
+ return ok, errors
+end
+
-- listen socket
function _instance:listen(backlog)
@@ -176,6 +199,37 @@ function _instance:connect(addr, port, opt)
return ok, errors
end
+-- connect socket from the unix address
+function _instance:connect_unix(addr, opt)
+
+ -- ensure opened
+ local ok, errors = self:_ensure_opened()
+ if not ok then
+ return -1, errors
+ end
+
+ -- must be unix socket
+ if self:family() ~= socket.UNIX then
+ return -1, string.format("%s: must be unix socket!", self)
+ end
+
+ -- connect it
+ opt = opt or {}
+ local ok, errors = io.socket_connect(self:csock(), addr, opt.is_abstract, self:family())
+ if ok == 0 then
+ local events, waiterrs = self:wait(socket.EV_CONN, opt.timeout or -1)
+ if events == socket.EV_CONN then
+ ok, errors = io.socket_connect(self:csock(), addr, opt.is_abstract, self:family())
+ else
+ errors = waiterrs
+ end
+ end
+ if ok < 0 and errors then
+ errors = string.format("%s: %s", self, errors)
+ end
+ return ok, errors
+end
+
-- send data to socket
function _instance:send(data, opt)
@@ -593,6 +647,11 @@ function socket.udp(opt)
return socket.open(socket.UDP, opt.family or socket.IPV4)
end
+-- open unix socket
+function socket.unix(opt)
+ return socket.open(socket.TCP, socket.UNIX)
+end
+
-- open and bind tcp socket
function socket.bind(addr, port, opt)
local sock, errors = socket.tcp(opt)
@@ -607,6 +666,20 @@ function socket.bind(addr, port, opt)
return sock
end
+-- open and bind tcp socket from the unix address
+function socket.bind_unix(addr, opt)
+ local sock, errors = socket.unix(opt)
+ if not sock then
+ return nil, errors
+ end
+ local ok, errors = sock:bind_unix(addr, opt)
+ if not ok then
+ sock:close()
+ return nil, string.format("bind unix://%s failed, errors: %s!", addr, errors or "")
+ end
+ return sock
+end
+
-- open and connect tcp socket
function socket.connect(addr, port, opt)
local sock, errors = socket.tcp(opt)
@@ -621,5 +694,19 @@ function socket.connect(addr, port, opt)
return sock
end
+-- open and connect tcp socket from the unix address
+function socket.connect_unix(addr, opt)
+ local sock, errors = socket.unix(opt)
+ if not sock then
+ return nil, errors
+ end
+ local ok, errors = sock:connect_unix(addr, opt)
+ if ok <= 0 then
+ sock:close()
+ return nil, string.format("connect unix://%s failed, errors: %s!", addr, errors or "")
+ end
+ return sock
+end
+
-- return module
return socket
diff --git a/xmake/core/sandbox/modules/import/core/base/socket.lua b/xmake/core/sandbox/modules/import/core/base/socket.lua
index 1cb9cfe6b..cc028c284 100644
--- a/xmake/core/sandbox/modules/import/core/base/socket.lua
+++ b/xmake/core/sandbox/modules/import/core/base/socket.lua
@@ -194,6 +194,15 @@ function sandbox_core_base_socket.udp(opt)
return _socket_wrap(sock)
end
+-- open unix socket
+function sandbox_core_base_socket.unix(opt)
+ local sock, errors = socket.unix(opt)
+ if not sock then
+ raise(errors)
+ end
+ return _socket_wrap(sock)
+end
+
-- open and bind tcp socket
function sandbox_core_base_socket.bind(addr, port, opt)
local sock, errors = socket.bind(addr, port, opt)
@@ -203,6 +212,15 @@ function sandbox_core_base_socket.bind(addr, port, opt)
return _socket_wrap(sock)
end
+-- open and bind tcp socket from the unix socket
+function sandbox_core_base_socket.bind_unix(addr, opt)
+ local sock, errors = socket.bind_unix(addr, opt)
+ if not sock then
+ raise(errors)
+ end
+ return _socket_wrap(sock)
+end
+
-- open and connect tcp socket
function sandbox_core_base_socket.connect(addr, port, opt)
local sock, errors = socket.connect(addr, port, opt)
@@ -212,6 +230,15 @@ function sandbox_core_base_socket.connect(addr, port, opt)
return _socket_wrap(sock)
end
+-- open and connect tcp socket from the unix socket
+function sandbox_core_base_socket.connect_unix(addr, opt)
+ local sock, errors = socket.connect_unix(addr, opt)
+ if not sock then
+ raise(errors)
+ end
+ return _socket_wrap(sock)
+end
+
-- return module
return sandbox_core_base_socket