patch 9.2.0170: channel: some issues in ch_listen()

Problem:  channel: some issues in ch_listen()
          (char101, after v9.2.0153)
Solution: On MS-Windows, initialize using channel_init_winsock() and use
          SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR, allow to use port
          0 to have the OS assign a port (Yasuhiro Matsumoto).

related: #19231
closes:  #19690

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yasuhiro Matsumoto
2026-03-15 09:22:29 +00:00
committed by Christian Brabandt
parent 751b59e539
commit e05d897258
3 changed files with 24 additions and 5 deletions
+17 -3
View File
@@ -1440,7 +1440,7 @@ channel_listen_func(typval_T *argvars)
return NULL;
}
port = strtol((char *)(p + 1), &rest, 10);
if (port <= 0 || port >= 65536 || *rest != NUL)
if (port < 0 || port >= 65536 || *rest != NUL)
{
semsg(_(e_invalid_argument_str), address);
return NULL;
@@ -1459,7 +1459,7 @@ channel_listen_func(typval_T *argvars)
return NULL;
}
port = strtol((char *)(p + 1), &rest, 10);
if (port <= 0 || port >= 65536 || *rest != NUL)
if (port < 0 || port >= 65536 || *rest != NUL)
{
semsg(_(e_invalid_argument_str), address);
return NULL;
@@ -1511,6 +1511,10 @@ channel_listen(
int val = 1;
channel_T *channel;
#ifdef MSWIN
channel_init_winsock();
#endif
channel = add_channel();
if (channel == NULL)
{
@@ -1555,7 +1559,7 @@ channel_listen(
}
#ifdef MSWIN
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
if (setsockopt(sd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
(const char *)&val, sizeof(val)) < 0)
#else
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
@@ -1591,6 +1595,16 @@ channel_listen(
return NULL;
}
// When port 0 was specified, retrieve the actual port assigned by the OS.
if (port_in == 0)
{
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
if (getsockname(sd, (struct sockaddr *)&addr, &addr_len) == 0)
port_in = ntohs(addr.sin_port);
}
channel->ch_listen = TRUE;
channel->CH_SOCK_FD = (sock_T)sd;
channel->ch_nb_close_cb = nb_close_cb;
+5 -2
View File
@@ -2798,8 +2798,11 @@ func Test_listen_invalid_address()
" port number too large
call assert_fails("call ch_listen('localhost:99999')", 'E475:')
" port number zero
call assert_fails("call ch_listen('localhost:0')", 'E475:')
" port number zero should let the OS assign an available port
let ch = ch_listen('localhost:0')
call assert_equal('open', ch_status(ch))
call assert_notequal(0, ch_info(ch).port)
call ch_close(ch)
" port number negative
call assert_fails("call ch_listen('localhost:-1')", 'E475:')
+2
View File
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
170,
/**/
169,
/**/