[PATCH v4 01/12] sio: introduce sio_uri_to_addr
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Thu Jan 31 00:28:27 MSK 2019
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 <limits.h>
#include <netinet/in.h> /* TCP_NODELAY */
#include <netinet/tcp.h> /* TCP_NODELAY */
+#include <arpa/inet.h>
#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 <COPYRIGHT HOLDER> ``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
+ * <COPYRIGHT HOLDER> 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 <sys/un.h>
+#include <arpa/inet.h>
+#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)
More information about the Tarantool-patches
mailing list