From bed435660ee5d56ea8a2e6ffa11b4db7a19a2bae Mon Sep 17 00:00:00 2001 From: "IAN.Z" <1274803758@qq.com> Date: Sat, 27 Dec 2025 17:11:52 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20httpc=E6=94=AF=E6=8C=81ipv6=20(#2125)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: httpc支持ipv6 * httpc ip:port解析放在c层 * lua-socket.c listen增加ip:port字符串解析, 相关cluster代码修改 #2124 * socketchannel changehost port可置空 * socketchannel changehost恢复port判空 * httpc解析域名加端口号逻辑优化 * 注释中字符串模式内容格式优化 --------- Co-authored-by: zhuyin.zhu --- lualib-src/lua-socket.c | 10 ++++++++-- lualib/http/httpc.lua | 33 ++++++++++++++++++++------------- lualib/skynet/socket.lua | 5 ----- lualib/skynet/socketchannel.lua | 10 +++++----- lualib/snax/gateserver.lua | 4 ++-- service/clusterd.lua | 14 ++++---------- service/clustersender.lua | 4 ++-- 7 files changed, 41 insertions(+), 39 deletions(-) diff --git a/lualib-src/lua-socket.c b/lualib-src/lua-socket.c index 7e22d2ed..bfb0ad04 100644 --- a/lualib-src/lua-socket.c +++ b/lualib-src/lua-socket.c @@ -484,8 +484,14 @@ lshutdown(lua_State *L) { static int llisten(lua_State *L) { - const char * host = luaL_checkstring(L,1); - int port = luaL_checkinteger(L,2); + size_t sz = 0; + const char * addr = luaL_checklstring(L, 1, &sz); + char tmp[sz]; + int port = 0; + const char * host = address_port(L, tmp, addr, 2, &port); + if (port == 0) { + return luaL_error(L, "Invalid port"); + } int backlog = luaL_optinteger(L,3,BACKLOG); struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1)); int id = skynet_socket_listen(ctx, host,port,backlog); diff --git a/lualib/http/httpc.lua b/lualib/http/httpc.lua index 057aa61a..2c65d74c 100644 --- a/lualib/http/httpc.lua +++ b/lualib/http/httpc.lua @@ -68,22 +68,29 @@ end local function connect(host, timeout) local protocol protocol, host = check_protocol(host) - local hostaddr, port = host:match"([^:]+):?(%d*)$" - if port == "" then + + local hostname, port + if async_dns then + -- hostname string (ends with ":?%d*") must begin with a substring that doesn't contain colon "[^:]" + -- and end with a character that is not a colon or a digit "[^%d%]:]". + -- hostname not end with ".", pattern "%." can avoid splitting "127.0.0.1" into "127.0.0." and "1" + hostname, port = host:match "^([^:]-[^%d%]:%.]):?(%d*)$" + if hostname then + local msg + host, msg = dns.resolve(hostname) + if not host then + error(string.format("%s dns resolve failed msg:%s", hostname, msg)) + end + end + end + + if port == "" or (port == nil and not host:find ":%d+$") then port = protocol=="http" and 80 or protocol=="https" and 443 - else - port = tonumber(port) end - local hostname - if not hostaddr:match(".*%d+$") then - hostname = hostaddr - if async_dns then - hostaddr = dns.resolve(hostname) - end - end - local fd = socket.connect(hostaddr, port, timeout) + + local fd = socket.connect(host, port, timeout) if not fd then - error(string.format("%s connect error host:%s, port:%s, timeout:%s", protocol, hostaddr, port, timeout)) + error(string.format("%s connect error host:%s, port:%s, timeout:%s", protocol, host, port, timeout)) end -- print("protocol hostname port", protocol, hostname, port) local interface = gen_interface(protocol, fd, hostname) diff --git a/lualib/skynet/socket.lua b/lualib/skynet/socket.lua index 84f64b2b..98f5c345 100644 --- a/lualib/skynet/socket.lua +++ b/lualib/skynet/socket.lua @@ -407,11 +407,6 @@ function socket.disconnected(id) end function socket.listen(host, port, backlog) - if port == nil then - host, port = string.match(host, "(.+):([^:]+)$") - host = host:match("^%[(.-)%]$") or host - port = tonumber(port) - end local id = driver.listen(host, port, backlog) local s = { id = id, diff --git a/lualib/skynet/socketchannel.lua b/lualib/skynet/socketchannel.lua index b7646fd5..cd5ebf74 100644 --- a/lualib/skynet/socketchannel.lua +++ b/lualib/skynet/socketchannel.lua @@ -26,7 +26,7 @@ socket_channel.error = socket_error function socket_channel.channel(desc) local c = { __host = assert(desc.host), - __port = assert(desc.port), + __port = desc.port, __backup = desc.backup, __auth = desc.auth, __response = desc.response, -- It's for session mode @@ -328,7 +328,7 @@ local function connect_once(self) self.__overload = true overload(true) else - skynet.error(string.format("WARNING: %d K bytes need to send out (fd = %d %s:%s)", size, id, self.__host, self.__port)) + skynet.error(string.format("WARNING: %d K bytes need to send out (fd = %d)", size, id), self.__host, self.__port) end end end @@ -464,7 +464,7 @@ local function block_connect(self, once) r = check_connection(self) if r == nil then - skynet.error(string.format("Connect to %s:%d failed (%s)", self.__host, self.__port, err)) + skynet.error("Connect failed", err, self.__host, self.__port) error(socket_error) else return r @@ -553,9 +553,9 @@ end function channel:changehost(host, port) self.__host = host - if port then + if port then self.__port = port - end + end if not self.__closed then close_channel_socket(self) end diff --git a/lualib/snax/gateserver.lua b/lualib/snax/gateserver.lua index 0f20ba38..80563633 100644 --- a/lualib/snax/gateserver.lua +++ b/lualib/snax/gateserver.lua @@ -39,10 +39,10 @@ function gateserver.start(handler) function CMD.open( source, conf ) assert(not socket) local address = conf.address or "0.0.0.0" - local port = assert(conf.port) + local port = conf.port maxclient = conf.maxclient or 1024 nodelay = conf.nodelay - skynet.error(string.format("Listen on %s:%d", address, port)) + skynet.error("Listen on", address, port) socket = socketdriver.listen(address, port, conf.backlog) listen_context.co = coroutine.running() listen_context.fd = socket diff --git a/service/clusterd.lua b/service/clusterd.lua index a1d8a2b5..94954013 100644 --- a/service/clusterd.lua +++ b/service/clusterd.lua @@ -39,11 +39,9 @@ local function open_channel(t, key) end local succ, err, c if address then - local host, port = string.match(address, "(.+):([^:]+)$") - host = host:match("^%[(.-)%]$") or host c = node_sender[key] if c == nil then - c = skynet.newservice("clustersender", key, nodename, host, port) + c = skynet.newservice("clustersender", key, nodename, address) if node_sender[key] then -- double check skynet.kill(c) @@ -53,14 +51,14 @@ local function open_channel(t, key) end end - succ = pcall(skynet.call, c, "lua", "changenode", host, port) + succ = pcall(skynet.call, c, "lua", "changenode", address) if succ then t[key] = c ct.channel = c node_sender_closed[key] = nil else - err = string.format("changenode [%s] (%s:%s) failed", key, host, port) + err = string.format("changenode [%s] (%s:%s) failed", key, address) end elseif address == false then c = node_sender[key] @@ -147,11 +145,7 @@ function command.listen(source, addr, port, maxclient) local gate = skynet.newservice("gate") if port == nil then local address = assert(node_address[addr], addr .. " is down") - addr, port = string.match(address, "(.+):([^:]+)$") - addr = addr:match("^%[(.-)%]$") or addr - port = tonumber(port) - assert(port ~= 0) - skynet.call(gate, "lua", "open", { address = addr, port = port, maxclient = maxclient }) + skynet.call(gate, "lua", "open", { address = address, port = port, maxclient = maxclient }) skynet.ret(skynet.pack(addr, port)) else local realaddr, realport = skynet.call(gate, "lua", "open", { address = addr, port = port, maxclient = maxclient }) diff --git a/service/clustersender.lua b/service/clustersender.lua index f4c0b572..46cffb24 100644 --- a/service/clustersender.lua +++ b/service/clustersender.lua @@ -60,10 +60,10 @@ end function command.changenode(host, port) if not host then - skynet.error(string.format("Close cluster sender %s:%d", channel.__host, channel.__port)) + skynet.error("Close cluster sender", channel.__host, channel.__port) channel:close() else - channel:changehost(host, tonumber(port)) + channel:changehost(host, port) channel:connect(true) end skynet.ret(skynet.pack(nil))