Merge tag '3.7' into HEAD
This removes a bunch of workarounds which are no longer necessary,
greatly reducing the diff between us and upstream. The diffstat is now:
.gitignore | 2 --
BUILD.gn | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
README.fuchsia | 19 +++++++++++++++++++
meta/iperf3.cmx | 13 +++++++++++++
src/fuchsia/fuchsia-compat.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/fuchsia/fuchsia-compat.h | 16 ++++++++++++++++
src/iperf_api.c | 2 ++
src/iperf_client_api.c | 7 +++++++
src/iperf_config.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/iperf_sctp.c | 5 +++++
src/iperf_server_api.c | 10 ++++++++++
src/iperf_tcp.c | 5 +++++
src/iperf_util.c | 30 ++++++++++++++++++++++++++++++
src/main.c | 3 ++-
src/net.c | 5 +++++
src/version.h | 27 +++++++++++++++++++++++++++
16 files changed, 529 insertions(+), 3 deletions(-)
which should make future merges simpler.
Test:
as client: fx shell iperf3 -c fe80::2bb1:ddd5:10c7:d54e%2
as server: fx shell iperf3 -s -6 # exercises IPV6_ONLY
Change-Id: I9fb62d791c9ed4420692fc9e75fe7a01ff3e0372
diff --git a/.gitignore b/.gitignore
index 424b143..5d34faa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,8 +16,6 @@
src/.deps
src/.libs
src/Makefile
-src/iperf_config.h
-src/version.h
src/stamp-h1
src/iperf3
src/iperf3_profile
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..29779e6
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,93 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 THE COPYRIGHT
+# OWNER 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.
+
+import("//build/package.gni")
+
+package("iperf") {
+ meta = [
+ {
+ path = "meta/iperf3.cmx"
+ dest = "iperf3.cmx"
+ },
+ ]
+
+ deps = [ ":iperf3" ]
+
+ binaries = [
+ {
+ name = "iperf3"
+ shell = true
+ },
+ ]
+}
+
+config("iperf_config") {
+ visibility = [ ":*" ]
+ include_dirs = [ "src" ]
+}
+
+source_set("fuchsia-compat") {
+ sources = [ "src/fuchsia/fuchsia-compat.c" ]
+ public_deps = [ "//zircon/public/lib/fdio" ]
+}
+
+executable("iperf3") {
+ sources = [
+ "src/cjson.c",
+ "src/dscp.c",
+ "src/iperf_api.c",
+ "src/iperf_auth.c",
+ "src/iperf_client_api.c",
+ "src/iperf_error.c",
+ "src/iperf_locale.c",
+ "src/iperf_server_api.c",
+ "src/iperf_tcp.c",
+ "src/iperf_time.c",
+ "src/iperf_udp.c",
+ "src/iperf_util.c",
+ "src/main.c",
+ "src/net.c",
+ "src/tcp_info.c",
+ "src/timer.c",
+ "src/units.c",
+ ]
+ defines = [
+ "_BSD_SOURCE",
+ "_POSIX_C_SOURCE=200809L",
+ ]
+ cflags_c = [
+ "-Wno-format",
+ "-Wno-implicit-int-float-conversion",
+ "-Wno-int-conversion",
+ "-Wno-pointer-sign",
+ "-Wno-sign-compare",
+ ]
+ libs = [ "zircon" ]
+ deps = [ ":fuchsia-compat" ]
+}
diff --git a/README.fuchsia b/README.fuchsia
new file mode 100644
index 0000000..7d5dab2
--- /dev/null
+++ b/README.fuchsia
@@ -0,0 +1,19 @@
+Modifications from upstream for Fuchsia compatibility
+-------
+* Use Fuchsia specific random in iperf_util.c
+* Shim rusage in iperf_util.c
+* Avoid sys/resource.h imports
+
+Testing Changes
+-------
+Common commands to ensure that things are working correctly
+
+### Server side: ###
+iperf3 -s -4 #Starts a server with IPV4 only
+
+### Client side: ###
+iperf3 -c <host ip> #Short 10-second max-rate TCP test
+iperf3 -c <host ip> -b 20M #20Mbps 'good-put'
+iperf3 -c <host ip> -P 40 #40 streams in parallel, max rate TCP
+
+Also try using the -R option to reverse the data flow
diff --git a/meta/iperf3.cmx b/meta/iperf3.cmx
new file mode 100644
index 0000000..a534e9a
--- /dev/null
+++ b/meta/iperf3.cmx
@@ -0,0 +1,13 @@
+{
+ "program": {
+ "binary": "bin/iperf3"
+ },
+ "sandbox": {
+ "features": [
+ "isolated-temp"
+ ],
+ "services": [
+ "fuchsia.posix.socket.Provider"
+ ]
+ }
+}
diff --git a/src/fuchsia/fuchsia-compat.c b/src/fuchsia/fuchsia-compat.c
new file mode 100644
index 0000000..85f956d
--- /dev/null
+++ b/src/fuchsia/fuchsia-compat.c
@@ -0,0 +1,174 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <assert.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <lib/fdio/fd.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/spawn.h>
+#include <lib/fdio/unsafe.h>
+#include <zircon/syscalls.h>
+#include <zircon/syscalls/port.h>
+
+// This is a very inefficient way to emulate select() by creating a port, adding all of the fds
+// of interest as async waits, and blocking until we get a port packet back.
+// The callers of this (like serverloop) generally have a static set of fds they care about, so
+// it'd be much more efficient for them to register async waits on a port object that persists
+// across blocking calls.
+int fuchsia_select(int nfds, void* readfds, void* writefds, struct timeval *timeout) {
+ fd_set* readfds_fd_set = (fd_set*) readfds;
+ fd_set* writefds_fd_set = (fd_set*) writefds;
+
+ int ret = 0;
+ zx_handle_t port = ZX_HANDLE_INVALID;
+ fdio_t* ios[FD_SETSIZE] = { 0 };
+
+ // Create a fresh port for this wait.
+ zx_status_t st = zx_port_create(0, &port);
+
+ if (st != ZX_OK) {
+ fprintf(stderr, "Can't allocate new port.\n");
+ errno = EINVAL;
+ ret = -1;
+ goto cleanup;
+ }
+
+
+ // Register port waits for file descriptors in the read and write sets.
+ for (int fd = 0; fd < nfds; ++fd) {
+ uint32_t events = 0;
+ if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
+ events |= POLLIN;
+ }
+ if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
+ events |= POLLOUT;
+ }
+ if (!events)
+ continue;
+
+ fdio_t* io;
+ // This acquires a reference to the fdio which is released in the cleanup path below.
+ if ((io = fdio_unsafe_fd_to_io(fd)) == NULL) {
+ errno = EBADF;
+ ret = -1;
+ goto cleanup;
+ }
+ ios[fd] = io;
+ zx_handle_t h;
+ zx_signals_t sigs;
+ // Translate the poll-style events to fdio-specific signal bits to wait on.
+ fdio_unsafe_wait_begin(io, events, &h, &sigs);
+ if (h == ZX_HANDLE_INVALID) {
+ errno = EBADF;
+ ret = -1;
+ goto cleanup;
+ }
+ uint64_t key = fd;
+ st = zx_object_wait_async(h, port, key, sigs, ZX_WAIT_ASYNC_ONCE);
+ if (st != ZX_OK) {
+ fprintf(stderr, "Can't wait on object %d.\n", st);
+ errno = EINVAL;
+ ret = -1;
+ goto cleanup;
+ }
+ }
+
+ zx_time_t deadline = (timeout == NULL) ? ZX_TIME_INFINITE :
+ zx_deadline_after(ZX_SEC(timeout->tv_sec) + ZX_USEC(timeout->tv_usec));
+
+ for (;;) {
+ zx_port_packet_t packet;
+ st = zx_port_wait(port, deadline, &packet);
+
+ // We expect zx_port_wait to return either ZX_ERR_TIMED_OUT if nothing happened, or ZX_OK
+ // if at least one thing happened.
+ if (st == ZX_OK) {
+ if (packet.type != ZX_PKT_TYPE_SIGNAL_ONE) {
+ fprintf(stderr, "Unexpected port packet type %u\n", packet.type);
+ errno = EINVAL;
+ ret = -1;
+ goto cleanup;
+ }
+ // We've heard about an fd in the set we care about. Update the read/write
+ // sets to reflect this information, then remove them from the set we are
+ // listening to.
+ int fd = (int)packet.key;
+ uint32_t events = 0;
+ fdio_t* io = ios[fd];
+ if (!io) {
+ fprintf(stderr, "Can't find fd for packet key %d.\n", fd);
+ errno = EINVAL;
+ ret = -1;
+ goto cleanup;
+ }
+ // fdio_unsafe_wait_end translates the signals back to poll-style flags.
+ fdio_unsafe_wait_end(io, packet.signal.observed, &events);
+ if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
+ if (events & POLLIN)
+ ret++;
+ else
+ FD_CLR(fd, readfds_fd_set);
+ }
+ if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
+ if (events & POLLOUT)
+ ret++;
+ else
+ FD_CLR(fd, writefds_fd_set);
+ }
+ // The read and write sets for this fd are now updated, and our wait has expired, so
+ // remove this fd from the set of things we care about.
+ ios[fd] = NULL;
+ fdio_unsafe_release(io);
+ } else if (st == ZX_ERR_TIMED_OUT) {
+ break;
+ } else {
+ fprintf(stderr, "Port wait return unexpected error %d.\n", st);
+ errno = EINVAL;
+ ret = -1;
+ goto cleanup;
+ }
+
+ // After pulling the first packet out, poll without blocking by doing another wait with a
+ // deadline in the past. This will populate any other members of the read/write set that
+ // are ready to go now.
+ deadline = 0;
+ }
+
+ // If there are any entries left in ios at this point, we have not received a port packet
+ // indicating that those fds are readable or writable and so we should clear those from the
+ // read/write sets.
+ for (int fd = 0; fd < nfds; ++fd) {
+ if (ios[fd]) {
+ if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
+ FD_CLR(fd, readfds_fd_set);
+ }
+ if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
+ FD_CLR(fd, writefds_fd_set);
+ }
+ }
+ }
+
+cleanup:
+ // Release reference to any fdio objects we acquired with fdio_unsafe_fd_to_io().
+ for (int fd = 0; fd < nfds; ++fd) {
+ if (ios[fd]) {
+ fdio_unsafe_release(ios[fd]);
+ }
+ }
+
+ if (port != ZX_HANDLE_INVALID) {
+ zx_handle_close(port);
+ }
+ return ret;
+}
diff --git a/src/fuchsia/fuchsia-compat.h b/src/fuchsia/fuchsia-compat.h
new file mode 100644
index 0000000..1ca0660
--- /dev/null
+++ b/src/fuchsia/fuchsia-compat.h
@@ -0,0 +1,16 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+#include <zircon/types.h>
+
+struct timeval;
+
+// This implements the subset of select() functionality used by openssh.
+// Uses void* instead of fd_set* for the read/write fd sets since this compat
+// header is included in smult_curve25519_ref.c, which declares a completely
+// unrelated function called select(). Doesn't export exceptfds.
+int fuchsia_select(int nfds, void* readfds, void* writefds,
+ struct timeval* timeout);
+
diff --git a/src/iperf_api.c b/src/iperf_api.c
index e1bbfa5..5c3f153 100755
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -51,7 +51,9 @@
#endif
#include <netinet/tcp.h>
#include <sys/time.h>
+#ifndef __Fuchsia__
#include <sys/resource.h>
+#endif
#include <sys/mman.h>
#include <sys/stat.h>
#include <sched.h>
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 20ea6fd..b3efd99 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -44,6 +44,9 @@
#include "iperf_time.h"
#include "net.h"
#include "timer.h"
+#ifdef __Fuchsia__
+#include "fuchsia/fuchsia-compat.h"
+#endif
#if defined(HAVE_TCP_CONGESTION)
#if !defined(TCP_CA_NAME_MAX)
@@ -489,7 +492,11 @@
memcpy(&write_set, &test->write_set, sizeof(fd_set));
iperf_time_now(&now);
timeout = tmr_timeout(&now);
+ #ifdef __Fuchsia__
+ result = fuchsia_select(test->max_fd + 1, &read_set, &write_set, timeout);
+ #else
result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
+ #endif
if (result < 0 && errno != EINTR) {
i_errno = IESELECT;
return -1;
diff --git a/src/iperf_config.h b/src/iperf_config.h
new file mode 100644
index 0000000..1e3afd1
--- /dev/null
+++ b/src/iperf_config.h
@@ -0,0 +1,121 @@
+/* src/iperf_config.h. Generated by hand. */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if you have the `cpuset_setaffinity' function. */
+#undef HAVE_CPUSET_SETAFFINITY
+
+/* Have CPU affinity support. */
+#undef HAVE_CPU_AFFINITY
+
+/* Define to 1 if you have the `daemon' function. */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <endian.h> header file. */
+#define HAVE_ENDIAN_H 1
+
+/* Have IPv6 flowlabel support. */
+#undef HAVE_FLOWLABEL
+
+/* Define to 1 if you have the `getline' function. */
+#undef HAVE_GETLINE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netinet/sctp.h> header file. */
+#define HAVE_NETINET_SCTP_H 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have the `sched_setaffinity' function. */
+#define HAVE_SCHED_SETAFFINITY 1
+
+/* Have SCTP support. */
+#undef HAVE_SCTP
+
+/* Define to 1 if you have the `sendfile' function. */
+#define HAVE_SENDFILE 1
+
+/* Define to 1 if you have the `SetProcessAffinityMask' function. */
+#undef HAVE_SETPROCESSAFFINITYMASK
+
+/* Have SO_MAX_PACING_RATE sockopt. */
+#define HAVE_SO_MAX_PACING_RATE 1
+
+/* OpenSSL Is Available */
+#undef HAVE_SSL
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct sctp_assoc_value'. */
+#define HAVE_STRUCT_SCTP_ASSOC_VALUE 1
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#undef HAVE_SYS_ENDIAN_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Have TCP_CONGESTION sockopt. */
+#undef HAVE_TCP_CONGESTION
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "iperf"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://github.com/esnet/iperf"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "iperf"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "iperf 3.7-FUCHSIA"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "iperf"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "https://software.es.net/iperf/"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.7-FUCHSIA"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "3.7-FUCHSIA"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
diff --git a/src/iperf_sctp.c b/src/iperf_sctp.c
index 06e1e23..a3487a0 100644
--- a/src/iperf_sctp.c
+++ b/src/iperf_sctp.c
@@ -209,7 +209,12 @@
#endif /* IPV6_V6ONLY */
opt = 1;
+ // TODO(eyalsoha): Remove this when SO_REUSEADDR is supported.
+#if defined(__Fuchsia__)
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
+#else
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+#endif
saved_errno = errno;
close(s);
freeaddrinfo(res);
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 40d99bc..41471cb 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -44,7 +44,9 @@
#include <stdint.h>
#endif
#include <sys/time.h>
+#ifndef __Fuchsia__
#include <sys/resource.h>
+#endif
#include <sched.h>
#include <setjmp.h>
@@ -59,6 +61,10 @@
#include "units.h"
#include "iperf_util.h"
#include "iperf_locale.h"
+#ifdef __Fuchsia__
+#include "fuchsia/fuchsia-compat.h"
+#endif
+
#if defined(HAVE_TCP_CONGESTION)
#if !defined(TCP_CA_NAME_MAX)
@@ -442,7 +448,11 @@
iperf_time_now(&now);
timeout = tmr_timeout(&now);
+ #ifdef __Fuchsia__
+ result = fuchsia_select(test->max_fd + 1, &read_set, &write_set, timeout);
+ #else
result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
+ #endif
if (result < 0 && errno != EINTR) {
cleanup_server(test);
i_errno = IESELECT;
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index 232aaa1..d311831 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -259,7 +259,12 @@
}
}
opt = 1;
+ // TODO(eyalsoha): Remove this when SO_REUSEADDR is supported.
+#if defined(__Fuchsia__)
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
+#else
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+#endif
saved_errno = errno;
close(s);
freeaddrinfo(res);
diff --git a/src/iperf_util.c b/src/iperf_util.c
index 412397a..c456fae 100644
--- a/src/iperf_util.c
+++ b/src/iperf_util.c
@@ -40,7 +40,29 @@
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
+#ifndef __Fuchsia__
#include <sys/resource.h>
+#else
+#include <zircon/syscalls.h>
+#include <time.h>
+// NB. rusage was removed from Fuchsia in
+// https://fuchsia.googlesource.com/fuchsia/+/67fec6d without replacement.
+#define RUSAGE_SELF CLOCK_PROCESS_CPUTIME_ID
+struct rusage {
+ struct timeval ru_utime;
+};
+static inline int getrusage(int who, struct rusage* ru) {
+ struct timespec ts;
+ int r = clock_gettime(who, &ts);
+ if (r) {
+ return r;
+ }
+ ru->ru_utime.tv_sec = ts.tv_sec;
+ ru->ru_utime.tv_usec = ts.tv_nsec/1000;
+ return 0;
+}
+#define ru_stime ru_utime
+#endif
#include <sys/utsname.h>
#include <time.h>
#include <errno.h>
@@ -50,6 +72,7 @@
#include "iperf.h"
#include "iperf_api.h"
+#ifndef __Fuchsia__
/*
* Read entropy from /dev/urandom
* Errors are fatal.
@@ -77,6 +100,13 @@
}
return 0;
}
+#else
+int readentropy(void *out, size_t outsize)
+{
+ zx_cprng_draw(out, outsize);
+ return 0;
+}
+#endif
/*
diff --git a/src/main.c b/src/main.c
index fe10a2f..87b36ac 100644
--- a/src/main.c
+++ b/src/main.c
@@ -44,9 +44,10 @@
#include "iperf.h"
#include "iperf_api.h"
-#include "units.h"
#include "iperf_locale.h"
+#include "iperf_util.h"
#include "net.h"
+#include "units.h"
static int run(struct iperf_test *test);
diff --git a/src/net.c b/src/net.c
index 96fb7ed..2788648 100644
--- a/src/net.c
+++ b/src/net.c
@@ -255,7 +255,12 @@
}
opt = 1;
+ // TODO(eyalsoha): Remove this when SO_REUSEADDR is supported.
+#if defined(__Fuchsia__)
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
+#else
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+#endif
(char *) &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..495af71
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,27 @@
+/*
+ * iperf, Copyright (c) 2014, The Regents of the University of
+ * California, through Lawrence Berkeley National Laboratory (subject
+ * to receipt of any required approvals from the U.S. Dept. of
+ * Energy). All rights reserved.
+ *
+ * If you have questions about your rights to use or distribute this
+ * software, please contact Berkeley Lab's Technology Transfer
+ * Department at TTD@lbl.gov.
+ *
+ * NOTICE. This software is owned by the U.S. Department of Energy.
+ * As such, the U.S. Government has been granted for itself and others
+ * acting on its behalf a paid-up, nonexclusive, irrevocable,
+ * worldwide license in the Software to reproduce, prepare derivative
+ * works, and perform publicly and display publicly. Beginning five
+ * (5) years after the date permission to assert copyright is obtained
+ * from the U.S. Department of Energy, and subject to any subsequent
+ * five (5) year renewals, the U.S. Government is granted for itself
+ * and others acting on its behalf a paid-up, nonexclusive,
+ * irrevocable, worldwide license in the Software to reproduce,
+ * prepare derivative works, distribute copies to the public, perform
+ * publicly and display publicly, and to permit others to do so.
+ *
+ * This code is distributed under a BSD style license, see the LICENSE
+ * file for complete information.
+ */
+#define IPERF_VERSION "3-CURRENT"