Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: kostja@tarantool.org, vdavydov.dev@gmail.com
Subject: [PATCH v4 01/12] sio: introduce sio_uri_to_addr
Date: Thu, 31 Jan 2019 00:28:27 +0300	[thread overview]
Message-ID: <696bb7ee520bd568e5a3d32d2e2aaaecc0a94898.1548883137.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1548883137.git.v.shpilevoy@tarantool.org>
In-Reply-To: <cover.1548883137.git.v.shpilevoy@tarantool.org>

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)

  reply	other threads:[~2019-01-30 21:28 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-30 21:28 [PATCH v4 00/12] SWIM draft Vladislav Shpilevoy
2019-01-30 21:28 ` Vladislav Shpilevoy [this message]
2019-02-15 13:21   ` [tarantool-patches] [PATCH v4 01/12] sio: introduce sio_uri_to_addr Konstantin Osipov
2019-02-15 21:22     ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 10/12] [RAW] swim: introduce 'quit' message Vladislav Shpilevoy
2019-02-21 12:13   ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 11/12] [RAW] swim: introduce broadcast tasks Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 12/12] [RAW] swim: allow to use broadcast tasks to send pings Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 02/12] evio: expose evio_setsockopt_server function Vladislav Shpilevoy
2019-02-15 13:21   ` [tarantool-patches] " Konstantin Osipov
2019-02-15 21:22     ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 03/12] rlist: introduce rlist_add_tail_entry_sorted Vladislav Shpilevoy
2019-02-15 13:26   ` [tarantool-patches] " Konstantin Osipov
2019-02-15 13:34     ` [tarantool-patches] " Vladislav Shpilevoy
2019-02-15 18:07       ` Konstantin Osipov
2019-01-30 21:28 ` [PATCH v4 04/12] [RAW] swim: introduce SWIM's anti-entropy component Vladislav Shpilevoy
2019-02-21 18:35   ` [tarantool-patches] " Konstantin Osipov
2019-02-26 18:28     ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 05/12] [RAW] swim: introduce failure detection component Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 06/12] [RAW] swim: introduce dissemination component Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 07/12] [RAW] swim: keep encoded round message cached Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 08/12] [RAW] swim: introduce payload Vladislav Shpilevoy
2019-01-30 21:28 ` [PATCH v4 09/12] [RAW] swim: introduce routing Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=696bb7ee520bd568e5a3d32d2e2aaaecc0a94898.1548883137.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=vdavydov.dev@gmail.com \
    --subject='Re: [PATCH v4 01/12] sio: introduce sio_uri_to_addr' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox