diff --git a/src/box/iproto.cc b/src/box/iproto.cc index f31738cb03e7e160bd98473cb7adcf489ed423c7..9dad43b0b8ebf538cd4542c116c226d9782e8ffa 100644 --- a/src/box/iproto.cc +++ b/src/box/iproto.cc @@ -129,6 +129,23 @@ unsigned iproto_readahead = 16320; /* The maximal number of iproto messages in fly. */ static int iproto_msg_max = IPROTO_MSG_MAX_MIN; +/** + * Address the iproto listens for, stored in TX + * thread. Is kept in TX to be shown in box.info. + */ +static struct sockaddr_storage iproto_bound_address_storage; +/** 0 means that no address is listened. */ +static socklen_t iproto_bound_address_len; + +const char * +iproto_bound_address(void) +{ + if (iproto_bound_address_len == 0) + return NULL; + return sio_strfaddr((struct sockaddr *) &iproto_bound_address_storage, + iproto_bound_address_len); +} + /** * How big is a buffer which needs to be shrunk before * it is put back into buffer cache. @@ -2203,8 +2220,14 @@ struct iproto_cfg_msg: public cbus_call_msg /** Operation to execute in iproto thread. */ enum iproto_cfg_op op; union { - /** New URI to bind to. */ - const char *uri; + struct { + /** New URI to bind to. */ + const char *uri; + /** Result address. */ + struct sockaddr_storage addr; + /** Address length. */ + socklen_t addrlen; + }; /** New iproto max message count. */ int iproto_msg_max; @@ -2240,6 +2263,8 @@ iproto_do_cfg_f(struct cbus_call_msg *m) (evio_service_bind(&binary, cfg_msg->uri) != 0 || evio_service_listen(&binary) != 0)) diag_raise(); + cfg_msg->addrlen = binary.addr_len; + cfg_msg->addr = binary.addrstorage; break; default: unreachable(); @@ -2265,6 +2290,8 @@ iproto_listen(const char *uri) iproto_cfg_msg_create(&cfg_msg, IPROTO_CFG_LISTEN); cfg_msg.uri = uri; iproto_do_cfg(&cfg_msg); + iproto_bound_address_storage = cfg_msg.addr; + iproto_bound_address_len = cfg_msg.addrlen; } size_t diff --git a/src/box/iproto.h b/src/box/iproto.h index edb24a7edf55b0656b37316eeda87b5daec47637..1442e68d3db35d663d9ea48da841fd56893668ee 100644 --- a/src/box/iproto.h +++ b/src/box/iproto.h @@ -80,6 +80,13 @@ iproto_request_count(void); void iproto_reset_stat(void); +/** + * String representation of the address served by + * iproto. To be shown in box.info. + */ +const char * +iproto_bound_address(void); + #if defined(__cplusplus) } /* extern "C" */ diff --git a/src/box/lua/info.c b/src/box/lua/info.c index c004fad27264cb9b2bd134d867e32d095f9974da..a789f782288d58b66f63e1f11ee78b536f003655 100644 --- a/src/box/lua/info.c +++ b/src/box/lua/info.c @@ -518,6 +518,14 @@ lbox_info_sql(struct lua_State *L) return 1; } +static int +lbox_info_listen(struct lua_State *L) +{ + /* NULL is ok, no need to check. */ + lua_pushstring(L, iproto_bound_address()); + return 1; +} + static const struct luaL_Reg lbox_info_dynamic_meta[] = { {"id", lbox_info_id}, {"uuid", lbox_info_uuid}, @@ -534,6 +542,7 @@ static const struct luaL_Reg lbox_info_dynamic_meta[] = { {"gc", lbox_info_gc}, {"vinyl", lbox_info_vinyl}, {"sql", lbox_info_sql}, + {"listen", lbox_info_listen}, {NULL, NULL} }; diff --git a/src/lib/core/evio.c b/src/lib/core/evio.c index 2152c15e6c2ef3acf615becb4a1eb9502d2c04a8..fc8f00e0ef5e69e208467e3b373dc637094687ff 100644 --- a/src/lib/core/evio.c +++ b/src/lib/core/evio.c @@ -269,6 +269,13 @@ evio_service_bind_addr(struct evio_service *service) } } + /* + * After binding a result address may be different. For + * example, if a port was 0. + */ + if (sio_getsockname(fd, &service->addr, &service->addr_len) != 0) + goto error; + say_info("%s: bound to %s", evio_service_name(service), sio_strfaddr(&service->addr, service->addr_len)); @@ -400,6 +407,7 @@ evio_service_stop(struct evio_service *service) if (ev_is_active(&service->ev)) { ev_io_stop(service->loop, &service->ev); + service->addr_len = 0; } if (service->ev.fd >= 0) { diff --git a/test/box-tap/cfg.test.lua b/test/box-tap/cfg.test.lua index d529447bbd526d9610db8cebb494ed1f55f53939..569b5f463d3cbafa88f68ef57eb0f13379b4774a 100755 --- a/test/box-tap/cfg.test.lua +++ b/test/box-tap/cfg.test.lua @@ -6,7 +6,7 @@ local socket = require('socket') local fio = require('fio') local uuid = require('uuid') local msgpack = require('msgpack') -test:plan(104) +test:plan(108) -------------------------------------------------------------------------------- -- Invalid values @@ -592,6 +592,18 @@ box.cfg{read_only=true} ]] test:is(run_script(code), PANIC, "panic on bootstrapping a read-only instance as master") +-- +-- gh-4620: box.info.listen. +-- +box.cfg{listen = box.NULL} +test:is(nil, box.info.listen, 'no cfg.listen - no info.listen') + +box.cfg{listen = '127.0.0.1:0'} +test:ok(box.info.listen:match('127.0.0.1'), 'real IP in info.listen') +test:ok(not box.info.listen:match(':0'), 'real port in info.listen') + +box.cfg{listen = box.NULL} +test:is(nil, box.info.listen, 'cfg.listen reset drops info.listen') test:check() os.exit(0) diff --git a/test/box/info.result b/test/box/info.result index 2e84cbbe3e7274bb6d61d4ef6a5e9297afb08970..e6d0ba6aa914f3e6f188a97f8e16fc0761120462 100644 --- a/test/box/info.result +++ b/test/box/info.result @@ -77,6 +77,7 @@ t - - cluster - gc - id + - listen - lsn - memory - package