summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>2018-06-16 02:44:00 +0900
committerMakoto Kato <m_kato@ga2.so-net.ne.jp>2018-06-16 02:44:00 +0900
commita19bdae674880d7dc4b8d1302b42805c091e4fd0 (patch)
treebb6a86fcbfb5696029a4f96da5896ff95d66fe0e
parent3447f868bc6dfa38fad51038f40011e6588987f8 (diff)
downloadnspr-hg-a19bdae674880d7dc4b8d1302b42805c091e4fd0.tar.gz
Bug 1466771 - Support abstract socket address on Linux and Android. r=glandium
-rw-r--r--pr/src/misc/prnetdb.c16
-rw-r--r--pr/src/pthreads/ptio.c7
-rw-r--r--pr/tests/Makefile.in1
-rwxr-xr-xpr/tests/abstract.c157
-rwxr-xr-xpr/tests/runtests.pl1
-rwxr-xr-xpr/tests/runtests.sh1
6 files changed, 181 insertions, 2 deletions
diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c
index affebf6a..c482e8e4 100644
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -7,6 +7,10 @@
#include <string.h>
+#if defined(LINUX)
+#include <sys/un.h>
+#endif
+
/*
* On Unix, the error code for gethostbyname() and gethostbyaddr()
* is returned in the global variable h_errno, instead of the usual
@@ -1366,7 +1370,17 @@ PRUintn _PR_NetAddrSize(const PRNetAddr* addr)
#endif
#if defined(XP_UNIX) || defined(XP_OS2)
else if (AF_UNIX == addr->raw.family)
- addrsize = sizeof(addr->local);
+ {
+#if defined(LINUX)
+ if (addr->local.path[0] == 0)
+ /* abstract socket address is supported on Linux only */
+ addrsize = strnlen(addr->local.path + 1,
+ sizeof(addr->local.path)) +
+ offsetof(struct sockaddr_un, sun_path) + 1;
+ else
+#endif
+ addrsize = sizeof(addr->local);
+ }
#endif
else addrsize = 0;
diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c
index f6aa5674..1549a905 100644
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -1750,7 +1750,12 @@ static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr)
if (addr->raw.family == AF_UNIX)
{
/* Disallow relative pathnames */
- if (addr->local.path[0] != '/')
+ if (addr->local.path[0] != '/'
+#if defined(LINUX)
+ /* Linux has abstract socket address support */
+ && addr->local.path[0] != 0
+#endif
+ )
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
diff --git a/pr/tests/Makefile.in b/pr/tests/Makefile.in
index 79a67f09..f1cfba9c 100644
--- a/pr/tests/Makefile.in
+++ b/pr/tests/Makefile.in
@@ -18,6 +18,7 @@ include $(topsrcdir)/config/config.mk
DIRS = dll
CSRCS = \
+ abstract.c \
accept.c \
acceptread.c \
acceptreademu.c \
diff --git a/pr/tests/abstract.c b/pr/tests/abstract.c
new file mode 100755
index 00000000..6be5610c
--- /dev/null
+++ b/pr/tests/abstract.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+
+#if defined(LINUX)
+
+#include <string.h>
+#include "nspr.h"
+
+static const char abstractSocketName[] = "\0testsocket";
+
+static void
+ClientThread(void* aArg)
+{
+ PRFileDesc* socket;
+ PRNetAddr addr;
+ PRUint8 buf[1024];
+ PRInt32 len;
+ PRInt32 total;
+
+ addr.local.family = PR_AF_LOCAL;
+ memcpy(addr.local.path, abstractSocketName, sizeof(abstractSocketName));
+
+ socket = PR_OpenTCPSocket(addr.raw.family);
+ if (!socket) {
+ fprintf(stderr, "PR_OpenTCPSokcet failed\n");
+ exit(1);
+ }
+
+ if (PR_Connect(socket, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ fprintf(stderr, "PR_Connect failed\n");
+ exit(1);
+ }
+
+ total = 0;
+ while (total < sizeof(buf)) {
+ len = PR_Recv(socket, buf + total, sizeof(buf) - total, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (len < 1) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ total += len;
+ }
+
+ total = 0;
+ while (total < sizeof(buf)) {
+ len = PR_Send(socket, buf + total, sizeof(buf) - total, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (len < 1) {
+ fprintf(stderr, "PR_Send failed\n");
+ exit(1);
+ }
+ total += len;
+ }
+
+ if (PR_Close(socket) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+int
+main()
+{
+ PRFileDesc* socket;
+ PRFileDesc* acceptSocket;
+ PRThread* thread;
+ PRNetAddr addr;
+ PRUint8 buf[1024];
+ PRInt32 len;
+ PRInt32 total;
+
+ addr.local.family = PR_AF_LOCAL;
+ memcpy(addr.local.path, abstractSocketName, sizeof(abstractSocketName));
+
+ socket = PR_OpenTCPSocket(addr.raw.family);
+ if (!socket) {
+ fprintf(stderr, "PR_OpenTCPSocket failed\n");
+ exit(1);
+ }
+ if (PR_Bind(socket, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+
+ if (PR_Listen(socket, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ thread = PR_CreateThread(PR_USER_THREAD, ClientThread, 0, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (!thread) {
+ fprintf(stderr, "PR_CreateThread failed");
+ exit(1);
+ }
+
+ acceptSocket = PR_Accept(socket, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (!acceptSocket) {
+ fprintf(stderr, "PR_Accept failed\n");
+ exit(1);
+ }
+
+ memset(buf, 'A', sizeof(buf));
+
+ total = 0;
+ while (total < sizeof(buf)) {
+ len = PR_Send(acceptSocket, buf + total, sizeof(buf) - total, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (len < 1) {
+ fprintf(stderr, "PR_Send failed\n");
+ exit(1);
+ }
+ total += len;
+ }
+
+ total = 0;
+ while (total < sizeof(buf)) {
+ len = PR_Recv(acceptSocket, buf + total, sizeof(buf) - total, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (len < 1) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ total += len;
+ }
+
+ if (PR_Close(acceptSocket) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+
+ if (PR_Close(socket) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
+
+#else
+int
+main()
+{
+ prinf("PASS\n");
+ return 0;
+}
+#endif
diff --git a/pr/tests/runtests.pl b/pr/tests/runtests.pl
index 5dbc649b..f1ab7647 100755
--- a/pr/tests/runtests.pl
+++ b/pr/tests/runtests.pl
@@ -241,6 +241,7 @@ $prog = shift; # Program to test
# MAIN ---------------
@progs = (
+"abstract",
"accept",
"acceptread",
"acceptreademu",
diff --git a/pr/tests/runtests.sh b/pr/tests/runtests.sh
index 760f0329..d021287b 100755
--- a/pr/tests/runtests.sh
+++ b/pr/tests/runtests.sh
@@ -71,6 +71,7 @@ LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE}
#
TESTS="
+abstract
accept
acceptread
acceptreademu