diff options
| author | ruki <[email protected]> | 2019-12-20 00:53:14 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-12-19 23:19:27 +0800 |
| commit | 4ce400a33c26c4d59e76ccb5dc321fe6dabc60f7 (patch) | |
| tree | 7fba42df02bab3ab2702ad57c896002b22cb6518 | |
| parent | db52fd10877391ebc89be2c6551b94901a31e7b6 (diff) | |
add unix socket support
| -rw-r--r-- | core/src/xmake/io/socket_bind.c | 14 | ||||
| -rw-r--r-- | core/src/xmake/io/socket_connect.c | 14 | ||||
| -rw-r--r-- | tests/modules/socket/unix_tcp/echo_client.lua | 20 | ||||
| -rw-r--r-- | tests/modules/socket/unix_tcp/echo_server.lua | 31 | ||||
| -rw-r--r-- | tests/modules/socket/unix_tcp/file_client.lua | 34 | ||||
| -rw-r--r-- | tests/modules/socket/unix_tcp/file_server.lua | 22 | ||||
| -rw-r--r-- | xmake/core/base/socket.lua | 87 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/base/socket.lua | 27 |
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 |
