From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladislav Shpilevoy Subject: [PATCH v4 01/12] sio: introduce sio_uri_to_addr Date: Thu, 31 Jan 2019 00:28:27 +0300 Message-Id: <696bb7ee520bd568e5a3d32d2e2aaaecc0a94898.1548883137.git.v.shpilevoy@tarantool.org> In-Reply-To: References: In-Reply-To: References: To: tarantool-patches@freelists.org Cc: kostja@tarantool.org, vdavydov.dev@gmail.com List-ID: The function parses string URI consisting of either IP and port, or UNIX socket address, and stores the result into struct sockaddr. --- src/CMakeLists.txt | 2 +- src/sio.c | 41 +++++++++++++++++ src/sio.h | 7 +++ test/unit/CMakeLists.txt | 3 ++ test/unit/sio.c | 96 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 test/unit/sio.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 04de5ad04..38bd576e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -120,7 +120,7 @@ endif () add_library(core STATIC ${core_sources}) target_link_libraries(core - salad small + salad small uri ${LIBEV_LIBRARIES} ${LIBEIO_LIBRARIES} ${LIBCORO_LIBRARIES} diff --git a/src/sio.c b/src/sio.c index 613cd9412..419f4e0f4 100644 --- a/src/sio.c +++ b/src/sio.c @@ -36,9 +36,11 @@ #include #include /* TCP_NODELAY */ #include /* TCP_NODELAY */ +#include #include "say.h" #include "trivia/util.h" #include "exception.h" +#include "uri.h" const char * sio_socketname(int fd) @@ -321,3 +323,42 @@ sio_strfaddr(struct sockaddr *addr, socklen_t addrlen) } return name; } + +int +sio_uri_to_addr(const char *uri, struct sockaddr *addr) +{ + struct uri u; + if (uri_parse(&u, uri) != 0 || u.service == NULL) + goto invalid_uri; + if (u.host_len == strlen(URI_HOST_UNIX) && + memcmp(u.host, URI_HOST_UNIX, u.host_len) == 0) { + struct sockaddr_un *un = (struct sockaddr_un *) addr; + if (u.service_len + 1 > sizeof(un->sun_path)) + goto invalid_uri; + memcpy(un->sun_path, u.service, u.service_len); + un->sun_path[u.service_len] = 0; + un->sun_family = AF_UNIX; + return 0; + } + in_addr_t iaddr; + if (u.host_len == 0) { + iaddr = htonl(INADDR_ANY); + } else if (u.host_len == 9 && memcmp("localhost", u.host, 9) == 0) { + iaddr = htonl(INADDR_LOOPBACK); + } else { + iaddr = inet_addr(tt_cstr(u.host, u.host_len)); + if (iaddr == (in_addr_t) -1) + goto invalid_uri; + } + struct sockaddr_in *in = (struct sockaddr_in *) addr; + int port = htons(atoi(u.service)); + memset(in, 0, sizeof(*in)); + in->sin_family = AF_INET; + in->sin_addr.s_addr = iaddr; + in->sin_port = port; + return 0; + +invalid_uri: + diag_set(SocketError, sio_socketname(-1), "invalid uri \"%s\"", uri); + return -1; +} diff --git a/src/sio.h b/src/sio.h index 3067dc111..27988a232 100644 --- a/src/sio.h +++ b/src/sio.h @@ -203,6 +203,13 @@ ssize_t sio_sendto(int fd, const void *buf, size_t len, int flags, ssize_t sio_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); +/** + * Convert a string URI like "ip:port" or "unix/:path" to + * sockaddr_in/un structure. + */ +int +sio_uri_to_addr(const char *uri, struct sockaddr *addr); + #if defined(__cplusplus) } /* extern "C" */ #endif /* defined(__cplusplus) */ diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 0025d3611..16739f75d 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -203,3 +203,6 @@ add_executable(checkpoint_schedule.test ${PROJECT_SOURCE_DIR}/src/box/checkpoint_schedule.c ) target_link_libraries(checkpoint_schedule.test m unit) + +add_executable(sio.test sio.c) +target_link_libraries(sio.test unit core) diff --git a/test/unit/sio.c b/test/unit/sio.c new file mode 100644 index 000000000..84a86aac3 --- /dev/null +++ b/test/unit/sio.c @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "unit.h" +#include "memory.h" +#include "fiber.h" +#include +#include +#include "sio.h" + +static void +check_uri_to_addr(void) +{ + header(); + plan(18); + struct sockaddr_storage storage; + struct sockaddr *addr = (struct sockaddr *) &storage; + struct sockaddr_un *un = (struct sockaddr_un *) addr; + struct sockaddr_in *in = (struct sockaddr_in *) addr; + isnt(0, sio_uri_to_addr("invalid uri", addr), + "invalid uri is detected"); + + char long_path[1000]; + char *pos = long_path + sprintf(long_path, "unix/:/"); + memset(pos, 'a', 900); + pos[900] = 0; + isnt(0, sio_uri_to_addr(long_path, addr), "too long UNIX path"); + + is(0, sio_uri_to_addr("unix/:/normal_path", addr), "UNIX"); + is(0, strcmp(un->sun_path, "/normal_path"), "UNIX path"); + is(AF_UNIX, un->sun_family, "UNIX family"); + + is(0, sio_uri_to_addr("localhost:1234", addr), "localhost"); + is(AF_INET, in->sin_family, "localhost family"); + is(htonl(INADDR_LOOPBACK), in->sin_addr.s_addr, "localhost address"); + is(htons(1234), in->sin_port, "localhost port"); + + is(0, sio_uri_to_addr("5678", addr), "'any'"); + is(AF_INET, in->sin_family, "'any' family"); + is(htonl(INADDR_ANY), in->sin_addr.s_addr, "'any' address"); + is(htons(5678), in->sin_port, "'any' port"); + + is(0, sio_uri_to_addr("192.168.0.1:9101", addr), "IP"); + is(AF_INET, in->sin_family, "IP family"); + is(inet_addr("192.168.0.1"), in->sin_addr.s_addr, "IP address"); + is(htons(9101), in->sin_port, "IP port"); + + isnt(0, sio_uri_to_addr("192.168.0.300:1112", addr), "invalid IP"); + + check_plan(); + footer(); +} + +int +main(void) +{ + memory_init(); + fiber_init(fiber_c_invoke); + + header(); + plan(1); + check_uri_to_addr(); + int rc = check_plan(); + footer(); + + fiber_free(); + memory_free(); + return rc; +} -- 2.17.2 (Apple Git-113)