diff --git a/src/lib/core/sio.c b/src/lib/core/sio.c index bb8e508d94549d661d39f29879231555f5fb6d19..8f25b8159a45f6ad7463d5d09af7f4a3650c4dd7 100644 --- a/src/lib/core/sio.c +++ b/src/lib/core/sio.c @@ -293,6 +293,16 @@ sio_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) return 0; } +int +sio_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) +{ + if (getsockname(fd, addr, addrlen) < 0) { + diag_set(SocketError, sio_socketname(fd), "getsockname"); + return -1; + } + return 0; +} + const char * sio_strfaddr(const struct sockaddr *addr, socklen_t addrlen) { diff --git a/src/lib/core/sio.h b/src/lib/core/sio.h index f0998e2f357290a47fe13e05c5bc41d443f610ed..093b5f5baa6c4245814ed5b5ac5fdf7a3dc3eee4 100644 --- a/src/lib/core/sio.h +++ b/src/lib/core/sio.h @@ -86,6 +86,21 @@ sio_strfaddr(const struct sockaddr *addr, socklen_t addrlen); int sio_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); +/** + * Fill @a addr with a real address currently bound to @a fd + * socket. + * + * @param fd Socket. + * @param[out] addr An address structure to fill. + * @param[in][out] addlen On input it is a size of @a addr as a + * buffer. On output it becomes a size of a new + * content of @a addr. + * @retval 0 Success. + * @retval -1 Error. + */ +int +sio_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); + /** * Advance write position in the iovec array * based on its current value and the number of diff --git a/test/unit/sio.c b/test/unit/sio.c index 84a86aac3f037fe05e6132ef5ee6394650525e66..dffdd5592d100c8addf71c3373b4fe9a6ed9e81d 100644 --- a/test/unit/sio.c +++ b/test/unit/sio.c @@ -78,6 +78,26 @@ check_uri_to_addr(void) footer(); } +static void +check_auto_bind(void) +{ + header(); + plan(3); + + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + sio_uri_to_addr("127.0.0.1:0", (struct sockaddr *) &addr); + int fd = sio_socket(AF_INET, SOCK_STREAM, 0); + is(sio_bind(fd, (struct sockaddr *) &addr, sizeof(addr)), 0, + "bind to 0 works"); + is(sio_getsockname(fd, (struct sockaddr *) &addr, &addrlen), 0, + "getsockname works on 0 bind"); + isnt(addr.sin_port, 0, "a real port is returned"); + + check_plan(); + footer(); +} + int main(void) { @@ -85,8 +105,9 @@ main(void) fiber_init(fiber_c_invoke); header(); - plan(1); + plan(2); check_uri_to_addr(); + check_auto_bind(); int rc = check_plan(); footer(); diff --git a/test/unit/sio.result b/test/unit/sio.result index 32a5babae6ceb36bea5cd38818fe0d1769506713..e5712ad3ccf03b24e7f5bb80e39b4051dd5d8f4d 100644 --- a/test/unit/sio.result +++ b/test/unit/sio.result @@ -1,5 +1,5 @@ *** main *** -1..1 +1..2 *** check_uri_to_addr *** 1..18 ok 1 - invalid uri is detected @@ -22,4 +22,11 @@ ok 18 - invalid IP ok 1 - subtests *** check_uri_to_addr: done *** + *** check_auto_bind *** + 1..3 + ok 1 - bind to 0 works + ok 2 - getsockname works on 0 bind + ok 3 - a real port is returned +ok 2 - subtests + *** check_auto_bind: done *** *** main: done ***