aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-07-15 00:01:10 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-07-15 00:01:10 +0000
commitd80425dafba47f5b93664fb7fe2bc40afc07c43c (patch)
tree02bbd66233f7731973ac468cf9c3cb6d45a5bf3a
parent84c367eba8bd20381cbdf41a1945e3f7d0cc97fa (diff)
parent9368d27b8e0b4b6d7662c928e4f0c12b841187c8 (diff)
downloadiperf3-android12-mainline-wifi-release.tar.gz
Change-Id: I5ddb3f80914e28569736c058858f34f371e3752b
-rw-r--r--.github/ISSUE_TEMPLATE.md2
-rw-r--r--.gitignore1
-rw-r--r--Android.bp33
-rw-r--r--LICENSE4
-rw-r--r--METADATA9
-rw-r--r--Makefile.in34
l---------NOTICE1
-rw-r--r--README.md34
-rw-r--r--RELNOTES.md77
-rw-r--r--aclocal.m465
-rwxr-xr-xconfig/compile6
-rwxr-xr-xconfig/depcomp2
-rw-r--r--config/iperf_config_static_bin.m412
-rwxr-xr-xconfig/missing2
-rwxr-xr-xconfigure1493
-rw-r--r--configure.ac45
-rw-r--r--contrib/Dockerfile15
-rw-r--r--docs/conf.py6
-rw-r--r--docs/faq.rst69
-rw-r--r--docs/news.rst32
-rw-r--r--examples/Makefile.in5
-rw-r--r--src/Makefile.am14
-rw-r--r--src/Makefile.in70
-rw-r--r--src/cjson.c786
-rw-r--r--src/cjson.h184
-rw-r--r--src/dscp.c5
-rw-r--r--[-rwxr-xr-x]src/iperf.h18
-rw-r--r--src/iperf3.137
-rw-r--r--[-rwxr-xr-x]src/iperf_api.c352
-rw-r--r--[-rwxr-xr-x]src/iperf_api.h38
-rw-r--r--src/iperf_auth.c83
-rw-r--r--src/iperf_auth.h1
-rw-r--r--src/iperf_client_api.c27
-rw-r--r--src/iperf_config.h.in2
-rw-r--r--src/iperf_error.c50
-rw-r--r--src/iperf_locale.c16
-rw-r--r--src/iperf_locale.h6
-rw-r--r--src/iperf_sctp.c86
-rw-r--r--src/iperf_server_api.c32
-rw-r--r--src/iperf_tcp.c1
-rw-r--r--src/iperf_udp.c29
-rw-r--r--src/iperf_util.c8
-rw-r--r--src/iperf_util.h2
-rw-r--r--src/main.c3
-rw-r--r--src/net.c5
-rw-r--r--src/net.h4
-rw-r--r--src/private.pem27
-rw-r--r--src/public.pem9
-rw-r--r--src/t_api.c14
-rw-r--r--src/t_auth.c125
-rw-r--r--src/tcp_info.c4
-rw-r--r--src/timer.h2
-rwxr-xr-xtest_commands.sh8
53 files changed, 3166 insertions, 829 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 1a37a2c..359e1f8 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,7 +1,7 @@
_NOTE: The iperf3 issue tracker is for registering bugs, enhancement
requests, or submissions of code. It is not a means for asking
questions about building or using iperf3. Those are best directed
-towards the iperf3 mailing list at iperf-dev@google-groups.com or
+towards the iperf3 mailing list at iperf-dev@googlegroups.com or
question sites such as Stack Overflow
(http://www.stackoverflow.com/). A list of frequently-asked questions
regarding iperf3 can be found at http://software.es.net/iperf/faq.html._
diff --git a/.gitignore b/.gitignore
index 5d34faa..e7120c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@ src/t_timer
src/t_units
src/t_uuid
src/t_api
+src/t_auth
examples/.libs
examples/Makefile
examples/mic
diff --git a/Android.bp b/Android.bp
index 8c67c9b..7de1b67 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,6 +12,39 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["external_iperf3_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "external_iperf3_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-MIT",
+ "SPDX-license-identifier-NCSA",
+ "legacy_notice",
+ "legacy_unencumbered",
+ ],
+ license_text: [
+ "LICENSE",
+ ],
+}
+
cc_binary {
name: "iperf3",
srcs: [
diff --git a/LICENSE b/LICENSE
index ff2fcd1..3ae3bbf 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-"iperf, Copyright (c) 2014-2019, The Regents of the University of California,
+"iperf, Copyright (c) 2014-2020, 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."
@@ -42,7 +42,7 @@ such enhancements or derivative works thereof, in binary and source code form.
This software contains source code (src/cjson.{c,h}) that is:
- Copyright (c) 2009 Dave Gamble
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/METADATA b/METADATA
index 1477e70..8199d28 100644
--- a/METADATA
+++ b/METADATA
@@ -9,10 +9,11 @@ third_party {
type: GIT
value: "https://github.com/esnet/iperf.git"
}
- version: "3.7"
+ version: "3.9"
+ license_type: NOTICE
last_upgrade_date {
- year: 2019
- month: 7
- day: 2
+ year: 2020
+ month: 8
+ day: 17
}
}
diff --git a/Makefile.in b/Makefile.in
index 0d870bf..3c56ac5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -90,6 +90,7 @@ host_triplet = @host@
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/ax_check_openssl.m4 \
+ $(top_srcdir)/config/iperf_config_static_bin.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -565,6 +566,10 @@ dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
+dist-zstd: distdir
+ tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
+ $(am__post_remove_distdir)
+
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@@ -607,6 +612,8 @@ distcheck: dist
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
+ *.tar.zst*) \
+ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
@@ -784,17 +791,18 @@ uninstall-am:
am--refresh check check-am clean clean-cscope clean-generic \
clean-libtool cscope cscopelist-am ctags ctags-am dist \
dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
- dist-xz dist-zip distcheck distclean distclean-generic \
- distclean-libtool distclean-tags distcleancheck distdir \
- distuninstallcheck dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
- ps ps-am tags tags-am uninstall uninstall-am
+ dist-xz dist-zip dist-zstd distcheck distclean \
+ distclean-generic distclean-libtool distclean-tags \
+ distcleancheck distdir distuninstallcheck dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
.PRECIOUS: Makefile
diff --git a/NOTICE b/NOTICE
deleted file mode 120000
index 7a694c9..0000000
--- a/NOTICE
+++ /dev/null
@@ -1 +0,0 @@
-LICENSE \ No newline at end of file
diff --git a/README.md b/README.md
index 356784b..12df5bc 100644
--- a/README.md
+++ b/README.md
@@ -97,40 +97,26 @@ sensitive information.
If you have a question about usage or about the code, please do *not*
submit an issue. Please use one of the mailing lists for that.
-Changes from iperf 2.x
-----------------------
+Relation to iperf 2.x
+---------------------
-(Note that iperf2 is no longer being developed by its original
+Note that iperf2 is no longer being developed by its original
maintainers. However, beginning in 2014, another developer began
fixing bugs and enhancing functionality, and generating releases of
iperf2. Both projects (as of late 2017) are currently being developed
actively, but independently. The continuing iperf2 development
-project can be found at https://sourceforge.net/projects/iperf2/.)
+project can be found at https://sourceforge.net/projects/iperf2/.
-New options:
-
- -V, --verbose more detailed output than before
- -J, --json output in JSON format
- -Z, --zerocopy use a 'zero copy' sendfile() method of sending data
- -O, --omit N omit the first n seconds (to ignore slowstart)
- -T, --title str prefix every output line with this string
- -F, --file name xmit/recv the specified file
- -A, --affinity n/n,m set CPU affinity (Linux and FreeBSD only)
- -k, --blockcount #[KMG] number of blocks (packets) to transmit (instead
- of -t or -n)
- -L, --flowlabel set IPv6 flow label (Linux only)
-
-Changed flags:
+iperf3 contains a number of options and functions not present in
+iperf2. In addition, some flags are changed from their iperf2
+counterparts:
-C, --linux-congestion set congestion control algorithm (Linux only)
(-Z in iperf2)
--bidir bidirectional testing mode
(-d in iperf2)
-Deprecated options:
-
-Not planning to support these iperf2 flags. If you really miss these
-options, please submit a request in the issue tracker:
+Some iperf2 options are not available in iperf3:
-r, --tradeoff Do a bidirectional test individually
-T, --ttl time-to-live, for multicast (default 1)
@@ -138,7 +124,7 @@ options, please submit a request in the issue tracker:
S(settings) V(server) reports
-y, --reportstyle C report as a Comma-Separated Values
-Also deprecated is the ability to set the options via environment
+Also removed is the ability to set the options via environment
variables.
Known Issues
@@ -163,7 +149,7 @@ responsibility for the content of these pages.
Copyright
---------
-iperf, Copyright (c) 2014-2019, The Regents of the University of
+iperf, Copyright (c) 2014-2020, 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.
diff --git a/RELNOTES.md b/RELNOTES.md
index ff02ba9..21f0801 100644
--- a/RELNOTES.md
+++ b/RELNOTES.md
@@ -1,6 +1,83 @@
iperf3 Release Notes
====================
+iperf 3.9 2020-08-17
+--------------------
+
+* Notable user-visible changes
+
+ * A --timestamps flag has been added, which prepends a timestamp to
+ each output line. An optional argument to this flag, which is a
+ format specification to strftime(3), allows for custom timestamp
+ formats (#909, #1028).
+
+ * A --server-bitrate-limit flag has been added as a server-side
+ command-line argument. It allows a server to enforce a maximum
+ throughput rate; client connections that specify a higher bitrate
+ or exceed this bitrate during a test will be terminated. The
+ bitrate is expressed in bits per second, with an optional trailing
+ slash and integer count that specifies an averaging interval over
+ which to enforce the limit (#999).
+
+ * A bug that caused increased CPU usage with the --bidir option has
+ been fixed (#1011).
+
+* Notable developer-visible changes
+
+ * Fixed various minor memory leaks (#1023).
+
+iperf 3.8.1 2020-06-10
+----------------------
+
+* Notable user-visible changes
+
+ * A regression with "make install", where the libiperf shared
+ library files were not getting installed, has been fixed (#1013 /
+ #1014).
+
+iperf 3.8 2020-06-08
+--------------------
+
+* Notable user-visible changes
+
+ * Profiled libraries and binaries are no longer built by default
+ (#950).
+
+ * A minimal Dockerfile has been added (#824).
+
+ * A bug with burst mode and unlimited rate has been fixed (#898).
+
+ * Configuring with the --enable-static-bin flag will now cause
+ a statically-linked iperf3 binary to be built (#989).
+
+ * Configuring with the --without-sctp flag will now prevent SCTP
+ from being auto-detected (#1008). This flag allows building a
+ static binary (see above item) on a CentOS system with SCTP
+ installed, because no static SCTP libraries are available.
+
+ * Clock skew between the iperf3 client and server will no longer
+ skew the computation of jitter during UDP tests (#842 / #990).
+
+ * A possible buffer overflow in the authentication feature has been
+ fixed. This was only relevant when configuration authentication
+ using the libiperf3 API, and did not affect command-line usage.
+ Various other improvements and fixes in this area were also made
+ (#996).
+
+* Notable developer-visible changes
+
+ * The embedded version of cJSON has been updated to 1.7.13 (#978).
+
+ * Some server authentication functions have been added to the API
+ (#911).
+
+ * API access has been added to the connection timeout parameter
+ (#1001).
+
+ * Tests for some authentication functions have been added.
+
+ * Various compiler errors and warnings have been fixed.
+
iperf 3.7 2019-06-21
--------------------
diff --git a/aclocal.m4 b/aclocal.m4
index 107b3a9..df70996 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -1081,16 +1081,11 @@ _LT_EOF
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
- _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
- 10.[[012]][[,.]]*)
+ darwin*)
+ case ${MACOSX_DEPLOYMENT_TARGET},$host in
+ 10.[[012]],*|,*powerpc*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
- 10.*)
+ *)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
esac
;;
@@ -9049,7 +9044,7 @@ m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
-# Copyright (C) 2002-2018 Free Software Foundation, Inc.
+# Copyright (C) 2002-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9064,7 +9059,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.16.1], [],
+m4_if([$1], [1.16.2], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -9080,14 +9075,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.16.1])dnl
+[AM_AUTOMAKE_VERSION([1.16.2])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9139,7 +9134,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
-# Copyright (C) 1997-2018 Free Software Foundation, Inc.
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9170,7 +9165,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9361,7 +9356,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9400,7 +9395,9 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
done
if test $am_rc -ne 0; then
AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
- for automatic dependency tracking. Try re-running configure with the
+ for automatic dependency tracking. If GNU make was not used, consider
+ re-running the configure script with MAKE="gmake" (or whatever is
+ necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).])
fi
@@ -9427,7 +9424,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*-
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9624,7 +9621,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9645,7 +9642,7 @@ if test x"${install_sh+set}" != xset; then
fi
AC_SUBST([install_sh])])
-# Copyright (C) 2003-2018 Free Software Foundation, Inc.
+# Copyright (C) 2003-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9667,7 +9664,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9702,7 +9699,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*-
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9745,7 +9742,7 @@ AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-# Copyright (C) 1997-2018 Free Software Foundation, Inc.
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9786,7 +9783,7 @@ fi
# Obsolete and "removed" macros, that must however still report explicit
# error messages when used, to smooth transition.
#
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9813,7 +9810,7 @@ AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES])
# Helper functions for option handling. -*- Autoconf -*-
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9842,7 +9839,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9889,7 +9886,7 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9908,7 +9905,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9989,7 +9986,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
-# Copyright (C) 2009-2018 Free Software Foundation, Inc.
+# Copyright (C) 2009-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -10049,7 +10046,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -10077,7 +10074,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006-2018 Free Software Foundation, Inc.
+# Copyright (C) 2006-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -10096,7 +10093,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
-# Copyright (C) 2004-2018 Free Software Foundation, Inc.
+# Copyright (C) 2004-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/config/compile b/config/compile
index 99e5052..23fcba0 100755
--- a/config/compile
+++ b/config/compile
@@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ func_file_conv ()
MINGW*)
file_conv=mingw
;;
- CYGWIN*)
+ CYGWIN* | MSYS*)
file_conv=cygwin
;;
*)
@@ -67,7 +67,7 @@ func_file_conv ()
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
- cygwin/*)
+ cygwin/* | msys/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
diff --git a/config/depcomp b/config/depcomp
index 65cbf70..6b39162 100755
--- a/config/depcomp
+++ b/config/depcomp
@@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/config/iperf_config_static_bin.m4 b/config/iperf_config_static_bin.m4
new file mode 100644
index 0000000..5229394
--- /dev/null
+++ b/config/iperf_config_static_bin.m4
@@ -0,0 +1,12 @@
+# Also link binaries as static
+AC_ARG_ENABLE([static-bin],
+ AS_HELP_STRING([--enable-static-bin], [link iperf3 binary statically]),
+ [enable_static=yes
+ enable_shared=no
+ enable_static_bin=yes],
+ [:])
+AM_CONDITIONAL([ENABLE_STATIC_BIN], [test x$enable_static_bin = xno])
+
+AS_IF([test "x$enable_static_bin" == xyes],
+ [LDFLAGS="$LDFLAGS --static"]
+ [])
diff --git a/config/missing b/config/missing
index 625aeb1..8d0eaad 100755
--- a/config/missing
+++ b/config/missing
@@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
diff --git a/configure b/configure
index c9e1015..ee03ab2 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for iperf 3.7.
+# Generated by GNU Autoconf 2.69 for iperf 3.9.
#
# Report bugs to <https://github.com/esnet/iperf>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='iperf'
PACKAGE_TARNAME='iperf'
-PACKAGE_VERSION='3.7'
-PACKAGE_STRING='iperf 3.7'
+PACKAGE_VERSION='3.9'
+PACKAGE_STRING='iperf 3.9'
PACKAGE_BUGREPORT='https://github.com/esnet/iperf'
PACKAGE_URL='https://software.es.net/iperf/'
@@ -641,6 +641,9 @@ OPENSSL_INCLUDES
PKG_CONFIG
ENABLE_PROFILING_FALSE
ENABLE_PROFILING_TRUE
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
CPP
LT_SYS_LIBRARY_PATH
OTOOL64
@@ -649,10 +652,12 @@ LIPO
NMEDIT
DSYMUTIL
MANIFEST_TOOL
+RANLIB
ac_ct_AR
AR
DLLTOOL
OBJDUMP
+LN_S
NM
ac_ct_DUMPBIN
DUMPBIN
@@ -661,9 +666,6 @@ FGREP
EGREP
GREP
SED
-LIBTOOL
-LN_S
-RANLIB
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
@@ -688,9 +690,7 @@ build_os
build_vendor
build_cpu
build
-MAINT
-MAINTAINER_MODE_FALSE
-MAINTAINER_MODE_TRUE
+LIBTOOL
AM_BACKSLASH
AM_DEFAULT_VERBOSITY
AM_DEFAULT_V
@@ -718,6 +718,8 @@ am__isrc
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
+ENABLE_STATIC_BIN_FALSE
+ENABLE_STATIC_BIN_TRUE
target_alias
host_alias
build_alias
@@ -760,18 +762,20 @@ am__quote'
ac_subst_files=''
ac_user_opts='
enable_option_checking
+enable_static_bin
enable_silent_rules
-enable_maintainer_mode
-enable_dependency_tracking
enable_shared
enable_static
with_pic
enable_fast_install
with_aix_soname
+enable_dependency_tracking
with_gnu_ld
with_sysroot
enable_libtool_lock
+enable_maintainer_mode
enable_profiling
+with_sctp
with_openssl
'
ac_precious_vars='build_alias
@@ -1324,7 +1328,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures iperf 3.7 to adapt to many kinds of systems.
+\`configure' configures iperf 3.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1394,7 +1398,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of iperf 3.7:";;
+ short | recursive ) echo "Configuration of iperf 3.9:";;
esac
cat <<\_ACEOF
@@ -1402,21 +1406,22 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-static-bin link iperf3 binary statically
--enable-silent-rules less verbose build output (undo: "make V=1")
--disable-silent-rules verbose build output (undo: "make V=0")
- --enable-maintainer-mode
- enable make rules and dependencies not useful (and
- sometimes confusing) to the casual installer
- --enable-dependency-tracking
- do not reject slow dependency extractors
- --disable-dependency-tracking
- speeds up one-time build
--enable-shared[=PKGS] build shared libraries [default=yes]
--enable-static[=PKGS] build static libraries [default=yes]
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
+ --enable-dependency-tracking
+ do not reject slow dependency extractors
+ --disable-dependency-tracking
+ speeds up one-time build
--disable-libtool-lock avoid locking (might break parallel builds)
- --disable-profiling Disable iperf profiling binary
+ --enable-maintainer-mode
+ enable make rules and dependencies not useful (and
+ sometimes confusing) to the casual installer
+ --enable-profiling Enable iperf3 profiling binary
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1429,6 +1434,7 @@ Optional Packages:
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-sysroot[=DIR] Search for dependent libraries within DIR (or the
compiler's sysroot if not specified).
+ --without-sctp disable SCTP
--with-openssl=DIR root of the OpenSSL directory
Some influential environment variables:
@@ -1510,7 +1516,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-iperf configure 3.7
+iperf configure 3.9
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1879,7 +1885,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by iperf $as_me 3.7, which was
+It was created by iperf $as_me 3.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2284,6 +2290,30 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+# Also link binaries as static
+# Check whether --enable-static-bin was given.
+if test "${enable_static_bin+set}" = set; then :
+ enableval=$enable_static_bin; enable_static=yes
+ enable_shared=no
+ enable_static_bin=yes
+else
+ :
+fi
+
+ if test x$enable_static_bin = xno; then
+ ENABLE_STATIC_BIN_TRUE=
+ ENABLE_STATIC_BIN_FALSE='#'
+else
+ ENABLE_STATIC_BIN_TRUE='#'
+ ENABLE_STATIC_BIN_FALSE=
+fi
+
+
+if test "x$enable_static_bin" == xyes; then :
+ LDFLAGS="$LDFLAGS --static"
+
+fi
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2811,7 +2841,7 @@ fi
# Define the identity of the package.
PACKAGE='iperf'
- VERSION='3.7'
+ VERSION='3.9'
cat >>confdefs.h <<_ACEOF
@@ -2904,32 +2934,70 @@ END
fi
fi
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
-$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
- # Check whether --enable-maintainer-mode was given.
-if test "${enable_maintainer_mode+set}" = set; then :
- enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=0;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
else
- USE_MAINTAINER_MODE=no
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
-$as_echo "$USE_MAINTAINER_MODE" >&6; }
- if test $USE_MAINTAINER_MODE = yes; then
- MAINTAINER_MODE_TRUE=
- MAINTAINER_MODE_FALSE='#'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
- MAINTAINER_MODE_TRUE='#'
- MAINTAINER_MODE_FALSE=
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
+AM_BACKSLASH='\'
+
+case `pwd` in
+ *\ * | *\ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.6'
+macro_revision='2.4.6'
- MAINT=$MAINTAINER_MODE_TRUE
-ac_config_headers="$ac_config_headers src/iperf_config.h"
+
+
+
+
+
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
@@ -3001,9 +3069,138 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO ""
+}
+
+case $ECHO in
+ printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+ print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+ *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
+cat > confinc.mk << 'END'
+am__doit:
+ @echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+ { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
+ (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ case $?:`cat confinc.out 2>/dev/null` in #(
+ '0:this is the am__doit target') :
+ case $s in #(
+ BSD) :
+ am__include='.include' am__quote='"' ;; #(
+ *) :
+ am__include='include' am__quote='' ;;
+esac ;; #(
+ *) :
+ ;;
+esac
+ if test "$am__include" != "#"; then
+ _am_result="yes ($s style)"
+ break
+ fi
+done
+rm -f confinc.* confmf.*
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+$as_echo "${_am_result}" >&6; }
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
-# Checks for tools: c compiler, ranlib (used for creating static libraries),
-# symlinks and libtool
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3851,69 +4048,6 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-DEPDIR="${am__leading_dot}deps"
-
-ac_config_commands="$ac_config_commands depfiles"
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
-$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
-cat > confinc.mk << 'END'
-am__doit:
- @echo this is the am__doit target >confinc.out
-.PHONY: am__doit
-END
-am__include="#"
-am__quote=
-# BSD make does it like this.
-echo '.include "confinc.mk" # ignored' > confmf.BSD
-# Other make implementations (GNU, Solaris 10, AIX) do it like this.
-echo 'include confinc.mk # ignored' > confmf.GNU
-_am_result=no
-for s in GNU BSD; do
- { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
- (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
- case $?:`cat confinc.out 2>/dev/null` in #(
- '0:this is the am__doit target') :
- case $s in #(
- BSD) :
- am__include='.include' am__quote='"' ;; #(
- *) :
- am__include='include' am__quote='' ;;
-esac ;; #(
- *) :
- ;;
-esac
- if test "$am__include" != "#"; then
- _am_result="yes ($s style)"
- break
- fi
-done
-rm -f confinc.* confmf.*
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
-$as_echo "${_am_result}" >&6; }
-
-# Check whether --enable-dependency-tracking was given.
-if test "${enable_dependency_tracking+set}" = set; then :
- enableval=$enable_dependency_tracking;
-fi
-
-if test "x$enable_dependency_tracking" != xno; then
- am_depcomp="$ac_aux_dir/depcomp"
- AMDEPBACKSLASH='\'
- am__nodep='_no'
-fi
- if test "x$enable_dependency_tracking" != xno; then
- AMDEP_TRUE=
- AMDEP_FALSE='#'
-else
- AMDEP_TRUE='#'
- AMDEP_FALSE=
-fi
-
-
depcc="$CC" am_compiler_list=
@@ -4043,203 +4177,6 @@ else
fi
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
- ac_ct_RANLIB=$RANLIB
- # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_RANLIB"; then
- ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_RANLIB" = x; then
- RANLIB=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- RANLIB=$ac_ct_RANLIB
- fi
-else
- RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
-$as_echo_n "checking whether ln -s works... " >&6; }
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
-$as_echo "no, using $LN_S" >&6; }
-fi
-
-case `pwd` in
- *\ * | *\ *)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
-$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
-esac
-
-
-
-macro_version='2.4.6'
-macro_revision='2.4.6'
-
-
-
-
-
-
-
-
-
-
-
-
-
-ltmain=$ac_aux_dir/ltmain.sh
-
-# Backslashify metacharacters that are still active within
-# double-quoted strings.
-sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\(["`\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to delay expansion of an escaped single quote.
-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
-ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
-$as_echo_n "checking how to print strings... " >&6; }
-# Test print first, because it will be a builtin if present.
-if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
- test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
- ECHO='print -r --'
-elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
- ECHO='printf %s\n'
-else
- # Use this function as a fallback that always works.
- func_fallback_echo ()
- {
- eval 'cat <<_LTECHO_EOF
-$1
-_LTECHO_EOF'
- }
- ECHO='func_fallback_echo'
-fi
-
-# func_echo_all arg...
-# Invoke $ECHO with all args, space-separated.
-func_echo_all ()
-{
- $ECHO ""
-}
-
-case $ECHO in
- printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
-$as_echo "printf" >&6; } ;;
- print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
-$as_echo "print -r" >&6; } ;;
- *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
-$as_echo "cat" >&6; } ;;
-esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
$as_echo_n "checking for a sed that does not truncate output... " >&6; }
if ${ac_cv_path_SED+:} false; then :
@@ -4857,6 +4794,17 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
$as_echo "$lt_cv_nm_interface" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
# find the maximum length of command line arguments
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
$as_echo_n "checking the maximum length of command line arguments... " >&6; }
@@ -7488,16 +7436,11 @@ $as_echo "$lt_cv_ld_force_load" >&6; }
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
- _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
- 10.[012][,.]*)
+ darwin*)
+ case ${MACOSX_DEPLOYMENT_TARGET},$host in
+ 10.[012],*|,*powerpc*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
- 10.*)
+ *)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
esac
;;
@@ -12130,17 +12073,876 @@ CC=$lt_save_CC
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+ # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+ enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+ac_config_headers="$ac_config_headers src/iperf_config.h"
+
+
+
+
+# Checks for tools: c compiler, ranlib (used for creating static libraries),
+# symlinks and libtool
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+
+
# Add -Wall if we are using GCC.
if test "x$GCC" = "xyes"; then
CFLAGS="$CFLAGS -Wall"
fi
-# Check if profiling must be disabled
+# Check if enable profiling
# Check whether --enable-profiling was given.
if test "${enable_profiling+set}" = set; then :
- enableval=$enable_profiling; :
-else
- enable_profiling=yes
+ enableval=$enable_profiling;
fi
if test x$enable_profiling = xyes; then
@@ -12555,7 +13357,34 @@ fi
done
+# SCTP. Allow user to disable SCTP support with --without-sctp.
+# Otherwise we try to find whatever support is required.
+try_sctp=true
+
+# Check whether --with-sctp was given.
+if test "${with_sctp+set}" = set; then :
+ withval=$with_sctp;
+ case "$withval" in
+ y | ye | yes)
+ ;;
+ n | no)
+ try_sctp=false
+ ;;
+ *)
+ as_fn_error $? "Invalid --with-sctp value" "$LINENO" 5
+ ;;
+ esac
+
+else
+
+ try_sctp=true
+
+
+fi
+
+
# Check for SCTP support
+if $try_sctp; then
for ac_header in sys/socket.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default"
@@ -12580,7 +13409,7 @@ if test "x$ac_cv_header_netinet_sctp_h" = xyes; then :
#define HAVE_NETINET_SCTP_H 1
_ACEOF
-$as_echo "#define HAVE_SCTP 1" >>confdefs.h
+$as_echo "#define HAVE_SCTP_H 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sctp_bindx" >&5
$as_echo_n "checking for library containing sctp_bindx... " >&6; }
@@ -12707,6 +13536,7 @@ fi
done
+fi
ac_fn_c_check_header_mongrel "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default"
if test "x$ac_cv_header_endian_h" = xyes; then :
@@ -12950,6 +13780,11 @@ rm -f core conftest.err conftest.$ac_objext \
if $have_ssl; then
+ case $host in
+ *-*-cygwin)
+ CFLAGS="$CFLAGS -DNOCRYPT"
+ ;;
+ esac
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
LIBS="$OPENSSL_LIBS $LIBS"
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
@@ -13295,6 +14130,10 @@ LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
+if test -z "${ENABLE_STATIC_BIN_TRUE}" && test -z "${ENABLE_STATIC_BIN_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_STATIC_BIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
$as_echo_n "checking that generated files are newer than configure... " >&6; }
if test -n "$am_sleep_pid"; then
@@ -13311,10 +14150,6 @@ else
am__EXEEXT_FALSE=
fi
-if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
- as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
as_fn_error $? "conditional \"AMDEP\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -13323,6 +14158,14 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${ENABLE_PROFILING_TRUE}" && test -z "${ENABLE_PROFILING_FALSE}"; then
as_fn_error $? "conditional \"ENABLE_PROFILING\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -13724,7 +14567,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by iperf $as_me 3.7, which was
+This file was extended by iperf $as_me 3.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -13791,7 +14634,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-iperf config.status 3.7
+iperf config.status 3.9
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -14203,9 +15046,9 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
for ac_config_target in $ac_config_targets
do
case $ac_config_target in
- "src/iperf_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/iperf_config.h" ;;
"depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
"libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+ "src/iperf_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/iperf_config.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
"src/version.h") CONFIG_FILES="$CONFIG_FILES src/version.h" ;;
@@ -14888,7 +15731,9 @@ $as_echo X/"$am_mf" |
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "Something went wrong bootstrapping makefile fragments
- for automatic dependency tracking. Try re-running configure with the
+ for automatic dependency tracking. If GNU make was not used, consider
+ re-running the configure script with MAKE=\"gmake\" (or whatever is
+ necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).
See \`config.log' for more details" "$LINENO" 5; }
diff --git a/configure.ac b/configure.ac
index 0ff6549..939cf0a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-# iperf, Copyright (c) 2014-2018, The Regents of the University of
+# iperf, Copyright (c) 2014-2020, 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.
@@ -24,8 +24,9 @@
# file for complete information.
# Initialize the autoconf system for the specified tool, version and mailing list
-AC_INIT(iperf, 3.7, https://github.com/esnet/iperf, iperf, https://software.es.net/iperf/)
+AC_INIT(iperf, 3.9, https://github.com/esnet/iperf, iperf, https://software.es.net/iperf/)
m4_include([config/ax_check_openssl.m4])
+m4_include([config/iperf_config_static_bin.m4])
AC_LANG(C)
# Specify where the auxiliary files created by configure should go. The config
@@ -35,6 +36,9 @@ AC_CONFIG_AUX_DIR(config)
# Initialize the automake system
AM_INIT_AUTOMAKE([foreign])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+LT_INIT
+
AM_MAINTAINER_MODE
AM_CONFIG_HEADER(src/iperf_config.h)
@@ -52,11 +56,9 @@ if test "x$GCC" = "xyes"; then
CFLAGS="$CFLAGS -Wall"
fi
-# Check if profiling must be disabled
+# Check if enable profiling
AC_ARG_ENABLE([profiling],
- AS_HELP_STRING([--disable-profiling], [Disable iperf profiling binary]),
- [:],
- [enable_profiling=yes])
+ AS_HELP_STRING([--enable-profiling], [Enable iperf3 profiling binary]))
AM_CONDITIONAL([ENABLE_PROFILING], [test x$enable_profiling = xyes])
# Checks for header files.
@@ -89,10 +91,33 @@ AC_C_CONST
# Check for poll.h (it's in POSIX so everyone should have it?)
AC_CHECK_HEADERS([poll.h])
+# SCTP. Allow user to disable SCTP support with --without-sctp.
+# Otherwise we try to find whatever support is required.
+try_sctp=true
+AC_ARG_WITH([sctp],
+ [AS_HELP_STRING([--without-sctp],
+ [disable SCTP])],
+ [
+ case "$withval" in
+ y | ye | yes)
+ ;;
+ n | no)
+ try_sctp=false
+ ;;
+ *)
+ AC_MSG_ERROR([Invalid --with-sctp value])
+ ;;
+ esac
+ ], [
+ try_sctp=true
+ ]
+)
+
# Check for SCTP support
+if $try_sctp; then
AC_CHECK_HEADERS([sys/socket.h])
AC_CHECK_HEADERS([netinet/sctp.h],
- AC_DEFINE([HAVE_SCTP], [1], [Have SCTP support.])
+ AC_DEFINE([HAVE_SCTP_H], [1], [Have SCTP support.])
AC_SEARCH_LIBS(sctp_bindx, [sctp])
AC_CHECK_TYPES([struct sctp_assoc_value], [], [],
[[#include <netinet/sctp.h>]]),
@@ -101,6 +126,7 @@ AC_CHECK_HEADERS([netinet/sctp.h],
#include <sys/socket.h>
#endif
])
+fi
AC_CHECK_HEADER([endian.h],
AC_DEFINE([HAVE_ENDIAN_H], [1], [Define to 1 if you have the <endian.h> header file.]),
@@ -123,6 +149,11 @@ else
fi ]
)
if $have_ssl; then
+ case $host in
+ *-*-cygwin)
+ CFLAGS="$CFLAGS -DNOCRYPT"
+ ;;
+ esac
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
LIBS="$OPENSSL_LIBS $LIBS"
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
diff --git a/contrib/Dockerfile b/contrib/Dockerfile
new file mode 100644
index 0000000..79f6c75
--- /dev/null
+++ b/contrib/Dockerfile
@@ -0,0 +1,15 @@
+# Instructions:
+# - Configure for a static binary: ./configure --enable-static "LDFLAGS=--static" --disable-shared --without-openssl
+# - Build: make
+# - Build Docker image: docker build -t iperf3 -f contrib/Dockerfile .
+#
+# Example invocations:
+# - Help: docker run iperf3 --help
+# - Server: docker run -p 5201:5201 -it iperf3 -s
+# - Client: docker run -it iperf3 -c 192.168.1.1 (note: since this is a minimal image and does not include DNS, name resolution will not work)
+FROM scratch
+COPY src/iperf3 /iperf3
+COPY tmp /tmp
+ENTRYPOINT ["/iperf3"]
+EXPOSE 5201
+CMD ["-s"]
diff --git a/docs/conf.py b/docs/conf.py
index 0db2c7e..083a3bf 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -45,17 +45,17 @@ master_doc = 'index'
# General information about the project.
project = u'iperf3'
-copyright = u'2014-2019, ESnet'
+copyright = u'2014-2020, ESnet'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '3.6'
+version = '3.8.1'
# The full version, including alpha/beta/rc tags.
-release = '3.6'
+release = '3.8.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/faq.rst b/docs/faq.rst
index babf528..d7d182e 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -63,7 +63,11 @@ How can I build a statically-linked executable of iperf3?
#. Configure iperf3 thusly: ``configure "LDFLAGS=--static"
--disable-shared`` These options are necessary to disable the
generation of shared libraries and link the executable
- statically.
+ statically. For iperf-3.8 or later, configuring as ``configure
+ --enable-static-bin`` is another, shorter way to accomplish
+ this. If SCTP is installed on the system it might also be
+ necessary to pass the ``--without-sctp`` flag at configure
+ time.
#. Compile as normal.
@@ -72,10 +76,16 @@ How can I build a statically-linked executable of iperf3?
How can I build on a system that doesn't support profiled executables?
This problem has been noted by users attempting to build iperf3 for
- Android systems. There are several workarounds. In order from least
+ Android systems, as well as some recent versions of macOS.
+ There are several workarounds. In order from least
effort to most effort:
- #. Beginning with iperf-3.6, the ``--disable-profiling`` flag can be
+ #. Beginning with iperf-3.8, profiled executables are actually not
+ built by default, so this question becomes somewhat moot. Pass
+ the ``--enable-profiling`` flag to ``configure`` to build
+ profiled executables.
+
+ #. In iperf-3.6 and iperf-3.7, the ``--disable-profiling`` flag can be
passed to ``configure`` to disable the building of profiled
object files and the profiled executable.
@@ -117,6 +127,59 @@ I'm seeing quite a bit of unexpected UDP loss. Why?
iperf3 UDP does not seem to work at bandwidths less than 100Kbps. Why?
You'll need to reduce the default packet length to get UDP rates of less that 100Kbps. Try ``-l100``.
+TCP throughput drops to (almost) zero during a test, what's going on?
+ A drop in throughput to almost zero, except maybe for the first
+ reported interval(s), may be related to problems in NIC TCP Offload,
+ which is used to offload TCP functionality to the NIC (see
+ https://en.wikipedia.org/wiki/TCP_offload_engine). The goal of TCP
+ Offload is to save main CPU performance, mainly in the areas of
+ segmentation and reassembly of large packets and checksum
+ computation.
+
+ When TCP packets are sent with the "Don't Fragment" flag set, which
+ is the recommended setting, segmentation is done by the TCP stack
+ based on the reported next hop MSS in the ICMP Fragmentation Needed
+ message. With TCP Offload, active segmentation is done by the NIC on
+ the sending side, which is known as TCP Segmentation offload (TSO)
+ or in Windows as Large Send Offload (LSO). It seems that there are
+ TSO/LSO implementations which for some reason ignore the reported
+ MSS and therefore don’t perform segmentation. In these cases, when
+ large packets are sent, e.g. the default iperf3 128KB (131,072
+ bytes), iperf3 will show that data was sent in the first interval,
+ but since the packets don’t get to the server, no ack is received
+ and therefore no data is sent in the following intervals. It may
+ happen that after certain timeout the main CPU will re-send the
+ packet by re-segmenting it, and in these cases data will get to the
+ server after a while. However, it seems that segmentation is not
+ automatically continued with the next packet, so the data transfer
+ rate be very low.
+
+ The recommended solution in such a case is to disable TSO/LSO, at
+ least on the relevant port. See for example:
+ https://atomicit.ca/kb/articles/slow-network-speed-windows-10/. If
+ that doesn’t help then "Don't Fragment" TCP flag may be
+ disabled. See for example:
+ https://support.microsoft.com/en-us/help/900926/recommended-tcp-ip-settings-for-wan-links-with-a-mtu-size-of-less-than. However,
+ note that disabling the “Don’t Fragment” flag may cause other
+ issues.
+
+ To test whether TSO/LSO may be the problem, do the following:
+
+ * If different machine configurations are used for the client and
+ server, try the iperf3 reverse mode (``-R``). If TSO/LSO is only
+ enabled on the client machine, this test should succeed.
+ * Reduce the sending length to a small value that should not require
+ segmentation, using the iperf3 ``-l`` option, e.g. ``-l 512``. It
+ may also help to reduce the MTU by using the iperf3 ``-M`` option,
+ e.g. ``-M 1460``.
+ * Using tools like Wireshark, identify the required MSS in the ICMP
+ Fragmentation Needed messages (if reported). Run tests with the
+ ``-l`` value set to 2 times the MSS and then 4 times, 6 times,
+ etc. With TSO/LSO issue in each test the throughput should be
+ reduced more. It may help to increase the testing time beyond the
+ default 10 seconds to better see the behavior (iperf3 ``-t``
+ option).
+
What congestion control algorithms are supported?
On Linux, run this command to see the available congestion control
algorithms (note that some algorithms are packaged as kernel
diff --git a/docs/news.rst b/docs/news.rst
index 35cce4f..72c0d93 100644
--- a/docs/news.rst
+++ b/docs/news.rst
@@ -1,6 +1,38 @@
iperf3 Project News
===================
+2020-06-10: iperf-3.8.1 released
+---------------------------------
+
+| URL: https://downloads.es.net/pub/iperf/iperf-3.8.1.tar.gz
+| SHA256: ``e5b080f3273a8a715a4100f13826ac2ca31cc7b1315925631b2ecf64957ded96 iperf-3.8.1.tar.gz``
+
+iperf 3.8.1 fixes a regression with ``make install`` in iperf 3.8. It
+is otherwise identical to iperf 3.8.
+
+2020-06-08: iperf-3.8 released
+-------------------------------
+
+| URL: https://downloads.es.net/pub/iperf/iperf-3.8.tar.gz
+| SHA256: ``edc1c317b0ae31925e5eb84f0295faefbaa1db3229f4693e11d954d114de4bcd iperf-3.8.tar.gz``
+
+iperf 3.8 contains minor bugfixes and enhancements.
+
+
+2019-06-21: iperf-3.7 released
+-------------------------------
+
+| URL: https://downloads.es.net/pub/iperf/iperf-3.7.tar.gz
+| SHA256: ``d846040224317caf2f75c843d309a950a7db23f9b44b94688ccbe557d6d1710c iperf-3.7.tar.gz``
+
+iperf 3.7 adds the ``--bidir`` flag for bidirectional tests, includes
+some minor enhancements, and fixes a number of bugs. More details can
+be found in the release notes.
+
+Note: Documentation for the ``--bidir`` flag was inadvertently
+omitted from the manual page. This will be fixed in a future
+release.
+
2018-06-25: iperf-3.6 released
-------------------------------
diff --git a/examples/Makefile.in b/examples/Makefile.in
index b0049bc..a74833f 100644
--- a/examples/Makefile.in
+++ b/examples/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -92,6 +92,7 @@ noinst_PROGRAMS = mic$(EXEEXT) mis$(EXEEXT)
subdir = examples
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/ax_check_openssl.m4 \
+ $(top_srcdir)/config/iperf_config_static_bin.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
diff --git a/src/Makefile.am b/src/Makefile.am
index 5be8562..11d3e17 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,9 +1,9 @@
lib_LTLIBRARIES = libiperf.la # Build and install an iperf library
bin_PROGRAMS = iperf3 # Build and install an iperf binary
if ENABLE_PROFILING
-noinst_PROGRAMS = t_timer t_units t_uuid t_api iperf3_profile # Build, but don't install the test programs and a profiled version of iperf3
+noinst_PROGRAMS = t_timer t_units t_uuid t_api t_auth iperf3_profile # Build, but don't install the test programs and a profiled version of iperf3
else
-noinst_PROGRAMS = t_timer t_units t_uuid t_api # Build, but don't install the test programs
+noinst_PROGRAMS = t_timer t_units t_uuid t_api t_auth # Build, but don't install the test programs
endif
include_HEADERS = iperf_api.h # Defines the headers that get installed with the program
@@ -52,7 +52,7 @@ iperf3_LDADD = libiperf.la
iperf3_LDFLAGS = -g
if ENABLE_PROFILING
-# If the iperf-profiled-binary is enabled (and this condition is true by default)
+# If the iperf-profiled-binary is enabled
# Specify the sources and various flags for the profiled iperf binary. This
# binary recompiles all the source files to make sure they are all profiled.
iperf3_profile_SOURCES = main.c \
@@ -84,6 +84,11 @@ t_api_CFLAGS = -g
t_api_LDFLAGS =
t_api_LDADD = libiperf.la
+t_auth_SOURCES = t_auth.c
+t_auth_CFLAGS = -g
+t_auth_LDFLAGS =
+t_auth_LDADD = libiperf.la
+
# Specify which tests to run during a "make check"
@@ -91,6 +96,7 @@ TESTS = \
t_timer \
t_units \
t_uuid \
- t_api
+ t_api \
+ t_auth
dist_man_MANS = iperf3.1 libiperf.3
diff --git a/src/Makefile.in b/src/Makefile.in
index 619cd45..271ef6c 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -93,15 +93,17 @@ host_triplet = @host@
bin_PROGRAMS = iperf3$(EXEEXT)
@ENABLE_PROFILING_FALSE@noinst_PROGRAMS = t_timer$(EXEEXT) \
@ENABLE_PROFILING_FALSE@ t_units$(EXEEXT) t_uuid$(EXEEXT) \
-@ENABLE_PROFILING_FALSE@ t_api$(EXEEXT)
+@ENABLE_PROFILING_FALSE@ t_api$(EXEEXT) t_auth$(EXEEXT)
@ENABLE_PROFILING_TRUE@noinst_PROGRAMS = t_timer$(EXEEXT) \
@ENABLE_PROFILING_TRUE@ t_units$(EXEEXT) t_uuid$(EXEEXT) \
-@ENABLE_PROFILING_TRUE@ t_api$(EXEEXT) iperf3_profile$(EXEEXT)
+@ENABLE_PROFILING_TRUE@ t_api$(EXEEXT) t_auth$(EXEEXT) \
+@ENABLE_PROFILING_TRUE@ iperf3_profile$(EXEEXT)
TESTS = t_timer$(EXEEXT) t_units$(EXEEXT) t_uuid$(EXEEXT) \
- t_api$(EXEEXT)
+ t_api$(EXEEXT) t_auth$(EXEEXT)
subdir = src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/ax_check_openssl.m4 \
+ $(top_srcdir)/config/iperf_config_static_bin.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -198,6 +200,12 @@ t_api_DEPENDENCIES = libiperf.la
t_api_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_api_CFLAGS) $(CFLAGS) \
$(t_api_LDFLAGS) $(LDFLAGS) -o $@
+am_t_auth_OBJECTS = t_auth-t_auth.$(OBJEXT)
+t_auth_OBJECTS = $(am_t_auth_OBJECTS)
+t_auth_DEPENDENCIES = libiperf.la
+t_auth_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_auth_CFLAGS) $(CFLAGS) \
+ $(t_auth_LDFLAGS) $(LDFLAGS) -o $@
am_t_timer_OBJECTS = t_timer-t_timer.$(OBJEXT)
t_timer_OBJECTS = $(am_t_timer_OBJECTS)
t_timer_DEPENDENCIES = libiperf.la
@@ -256,9 +264,10 @@ am__depfiles_remade = ./$(DEPDIR)/cjson.Plo ./$(DEPDIR)/dscp.Plo \
./$(DEPDIR)/iperf_tcp.Plo ./$(DEPDIR)/iperf_time.Plo \
./$(DEPDIR)/iperf_udp.Plo ./$(DEPDIR)/iperf_util.Plo \
./$(DEPDIR)/net.Plo ./$(DEPDIR)/t_api-t_api.Po \
- ./$(DEPDIR)/t_timer-t_timer.Po ./$(DEPDIR)/t_units-t_units.Po \
- ./$(DEPDIR)/t_uuid-t_uuid.Po ./$(DEPDIR)/tcp_info.Plo \
- ./$(DEPDIR)/timer.Plo ./$(DEPDIR)/units.Plo
+ ./$(DEPDIR)/t_auth-t_auth.Po ./$(DEPDIR)/t_timer-t_timer.Po \
+ ./$(DEPDIR)/t_units-t_units.Po ./$(DEPDIR)/t_uuid-t_uuid.Po \
+ ./$(DEPDIR)/tcp_info.Plo ./$(DEPDIR)/timer.Plo \
+ ./$(DEPDIR)/units.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -279,11 +288,12 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libiperf_la_SOURCES) $(iperf3_SOURCES) \
- $(iperf3_profile_SOURCES) $(t_api_SOURCES) $(t_timer_SOURCES) \
- $(t_units_SOURCES) $(t_uuid_SOURCES)
+ $(iperf3_profile_SOURCES) $(t_api_SOURCES) $(t_auth_SOURCES) \
+ $(t_timer_SOURCES) $(t_units_SOURCES) $(t_uuid_SOURCES)
DIST_SOURCES = $(libiperf_la_SOURCES) $(iperf3_SOURCES) \
$(am__iperf3_profile_SOURCES_DIST) $(t_api_SOURCES) \
- $(t_timer_SOURCES) $(t_units_SOURCES) $(t_uuid_SOURCES)
+ $(t_auth_SOURCES) $(t_timer_SOURCES) $(t_units_SOURCES) \
+ $(t_uuid_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -294,8 +304,8 @@ man3dir = $(mandir)/man3
NROFF = nroff
MANS = $(dist_man_MANS)
HEADERS = $(include_HEADERS)
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
- $(LISP)iperf_config.h.in
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
+ iperf_config.h.in
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
@@ -664,7 +674,7 @@ iperf3_CFLAGS = -g
iperf3_LDADD = libiperf.la
iperf3_LDFLAGS = -g
-# If the iperf-profiled-binary is enabled (and this condition is true by default)
+# If the iperf-profiled-binary is enabled
# Specify the sources and various flags for the profiled iperf binary. This
# binary recompiles all the source files to make sure they are all profiled.
@ENABLE_PROFILING_TRUE@iperf3_profile_SOURCES = main.c \
@@ -691,6 +701,10 @@ t_api_SOURCES = t_api.c
t_api_CFLAGS = -g
t_api_LDFLAGS =
t_api_LDADD = libiperf.la
+t_auth_SOURCES = t_auth.c
+t_auth_CFLAGS = -g
+t_auth_LDFLAGS =
+t_auth_LDADD = libiperf.la
dist_man_MANS = iperf3.1 libiperf.3
all: iperf_config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -852,6 +866,10 @@ t_api$(EXEEXT): $(t_api_OBJECTS) $(t_api_DEPENDENCIES) $(EXTRA_t_api_DEPENDENCIE
@rm -f t_api$(EXEEXT)
$(AM_V_CCLD)$(t_api_LINK) $(t_api_OBJECTS) $(t_api_LDADD) $(LIBS)
+t_auth$(EXEEXT): $(t_auth_OBJECTS) $(t_auth_DEPENDENCIES) $(EXTRA_t_auth_DEPENDENCIES)
+ @rm -f t_auth$(EXEEXT)
+ $(AM_V_CCLD)$(t_auth_LINK) $(t_auth_OBJECTS) $(t_auth_LDADD) $(LIBS)
+
t_timer$(EXEEXT): $(t_timer_OBJECTS) $(t_timer_DEPENDENCIES) $(EXTRA_t_timer_DEPENDENCIES)
@rm -f t_timer$(EXEEXT)
$(AM_V_CCLD)$(t_timer_LINK) $(t_timer_OBJECTS) $(t_timer_LDADD) $(LIBS)
@@ -904,6 +922,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_util.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_api-t_api.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_auth-t_auth.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_timer-t_timer.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_units-t_units.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_uuid-t_uuid.Po@am__quote@ # am--include-marker
@@ -1218,6 +1237,20 @@ t_api-t_api.obj: t_api.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_api_CFLAGS) $(CFLAGS) -c -o t_api-t_api.obj `if test -f 't_api.c'; then $(CYGPATH_W) 't_api.c'; else $(CYGPATH_W) '$(srcdir)/t_api.c'; fi`
+t_auth-t_auth.o: t_auth.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_auth_CFLAGS) $(CFLAGS) -MT t_auth-t_auth.o -MD -MP -MF $(DEPDIR)/t_auth-t_auth.Tpo -c -o t_auth-t_auth.o `test -f 't_auth.c' || echo '$(srcdir)/'`t_auth.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_auth-t_auth.Tpo $(DEPDIR)/t_auth-t_auth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t_auth.c' object='t_auth-t_auth.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_auth_CFLAGS) $(CFLAGS) -c -o t_auth-t_auth.o `test -f 't_auth.c' || echo '$(srcdir)/'`t_auth.c
+
+t_auth-t_auth.obj: t_auth.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_auth_CFLAGS) $(CFLAGS) -MT t_auth-t_auth.obj -MD -MP -MF $(DEPDIR)/t_auth-t_auth.Tpo -c -o t_auth-t_auth.obj `if test -f 't_auth.c'; then $(CYGPATH_W) 't_auth.c'; else $(CYGPATH_W) '$(srcdir)/t_auth.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_auth-t_auth.Tpo $(DEPDIR)/t_auth-t_auth.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t_auth.c' object='t_auth-t_auth.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_auth_CFLAGS) $(CFLAGS) -c -o t_auth-t_auth.obj `if test -f 't_auth.c'; then $(CYGPATH_W) 't_auth.c'; else $(CYGPATH_W) '$(srcdir)/t_auth.c'; fi`
+
t_timer-t_timer.o: t_timer.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_timer_CFLAGS) $(CFLAGS) -MT t_timer-t_timer.o -MD -MP -MF $(DEPDIR)/t_timer-t_timer.Tpo -c -o t_timer-t_timer.o `test -f 't_timer.c' || echo '$(srcdir)/'`t_timer.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_timer-t_timer.Tpo $(DEPDIR)/t_timer-t_timer.Po
@@ -1594,6 +1627,13 @@ t_api.log: t_api$(EXEEXT)
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
+t_auth.log: t_auth$(EXEEXT)
+ @p='t_auth$(EXEEXT)'; \
+ b='t_auth'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
.test.log:
@p='$<'; \
$(am__set_b); \
@@ -1726,6 +1766,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/iperf_util.Plo
-rm -f ./$(DEPDIR)/net.Plo
-rm -f ./$(DEPDIR)/t_api-t_api.Po
+ -rm -f ./$(DEPDIR)/t_auth-t_auth.Po
-rm -f ./$(DEPDIR)/t_timer-t_timer.Po
-rm -f ./$(DEPDIR)/t_units-t_units.Po
-rm -f ./$(DEPDIR)/t_uuid-t_uuid.Po
@@ -1811,6 +1852,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/iperf_util.Plo
-rm -f ./$(DEPDIR)/net.Plo
-rm -f ./$(DEPDIR)/t_api-t_api.Po
+ -rm -f ./$(DEPDIR)/t_auth-t_auth.Po
-rm -f ./$(DEPDIR)/t_timer-t_timer.Po
-rm -f ./$(DEPDIR)/t_units-t_units.Po
-rm -f ./$(DEPDIR)/t_uuid-t_uuid.Po
diff --git a/src/cjson.c b/src/cjson.c
index a31874d..bf0b8b4 100644
--- a/src/cjson.c
+++ b/src/cjson.c
@@ -23,23 +23,39 @@
/* cJSON */
/* JSON parser in C. */
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
#ifdef __GNUC__
#pragma GCC visibility push(default)
#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
-#include <float.h>
#include <limits.h>
#include <ctype.h>
+#include <float.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <sys/types.h>
+
+#ifdef ENABLE_LOCALES
#include <locale.h>
+#endif
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
#ifdef __GNUC__
#pragma GCC visibility pop
#endif
@@ -47,9 +63,28 @@
#include "cjson.h"
/* define our own boolean type */
+#ifdef true
+#undef true
+#endif
#define true ((cJSON_bool)1)
+
+#ifdef false
+#undef false
+#endif
#define false ((cJSON_bool)0)
+/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
+#ifndef isinf
+#define isinf(d) (isnan((d - d)) && !isnan(d))
+#endif
+#ifndef isnan
+#define isnan(d) (d != d)
+#endif
+
+#ifndef NAN
+#define NAN 0.0/0.0
+#endif
+
typedef struct {
const unsigned char *json;
size_t position;
@@ -68,8 +103,28 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position);
}
+CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item)
+{
+ if (!cJSON_IsString(item))
+ {
+ return NULL;
+ }
+
+ return item->valuestring;
+}
+
+CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item)
+{
+ if (!cJSON_IsNumber(item))
+ {
+ return NAN;
+ }
+
+ return item->valuedouble;
+}
+
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
-#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 2)
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 13)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
@@ -107,12 +162,35 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned
typedef struct internal_hooks
{
- void *(*allocate)(size_t size);
- void (*deallocate)(void *pointer);
- void *(*reallocate)(void *pointer, size_t size);
+ void *(CJSON_CDECL *allocate)(size_t size);
+ void (CJSON_CDECL *deallocate)(void *pointer);
+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
} internal_hooks;
-static internal_hooks global_hooks = { malloc, free, realloc };
+#if defined(_MSC_VER)
+/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
+static void * CJSON_CDECL internal_malloc(size_t size)
+{
+ return malloc(size);
+}
+static void CJSON_CDECL internal_free(void *pointer)
+{
+ free(pointer);
+}
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
+{
+ return realloc(pointer, size);
+}
+#else
+#define internal_malloc malloc
+#define internal_free free
+#define internal_realloc realloc
+#endif
+
+/* strlen of character literals resolved at compile time */
+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
+
+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
{
@@ -125,7 +203,8 @@ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_h
}
length = strlen((const char*)string) + sizeof("");
- if (!(copy = (unsigned char*)hooks->allocate(length)))
+ copy = (unsigned char*)hooks->allocate(length);
+ if (copy == NULL)
{
return NULL;
}
@@ -204,8 +283,12 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
/* get the decimal point character of the current locale */
static unsigned char get_decimal_point(void)
{
+#ifdef ENABLE_LOCALES
struct lconv *lconv = localeconv();
return (unsigned char) lconv->decimal_point[0];
+#else
+ return '.';
+#endif
}
typedef struct
@@ -219,7 +302,6 @@ typedef struct
/* check if the given size is left to read in a given parse buffer (starting with 1) */
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
-#define cannot_read(buffer, size) (!can_read(buffer, size))
/* check if the buffer can be accessed at the given index (starting with 0) */
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
@@ -288,7 +370,7 @@ loop_end:
{
item->valueint = LLONG_MAX;
}
- else if (number <= LLONG_MIN)
+ else if (number <= (double)LLONG_MIN)
{
item->valueint = LLONG_MIN;
}
@@ -310,7 +392,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
{
object->valueint = LLONG_MAX;
}
- else if (number <= LLONG_MIN)
+ else if (number <= (double)LLONG_MIN)
{
object->valueint = LLONG_MIN;
}
@@ -322,6 +404,33 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
return object->valuedouble = number;
}
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
+{
+ char *copy = NULL;
+ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
+ if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
+ {
+ return NULL;
+ }
+ if (strlen(valuestring) <= strlen(object->valuestring))
+ {
+ strcpy(object->valuestring, valuestring);
+ return object->valuestring;
+ }
+ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
+ if (copy == NULL)
+ {
+ return NULL;
+ }
+ if (object->valuestring != NULL)
+ {
+ cJSON_free(object->valuestring);
+ }
+ object->valuestring = copy;
+
+ return copy;
+}
+
typedef struct
{
unsigned char *buffer;
@@ -350,9 +459,9 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL;
}
- if (needed > LLONG_MAX)
+ if (needed > SIZE_MAX)
{
- /* sizes bigger than LLONG_MAX are currently not supported */
+ /* sizes bigger than SIZE_MAX are currently not supported */
return NULL;
}
@@ -367,12 +476,12 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
}
/* calculate new buffer size */
- if (needed > (LLONG_MAX / 2))
+ if (needed > (SIZE_MAX / 2))
{
- /* overflow of int, use LLONG_MAX if possible */
- if (needed <= LLONG_MAX)
+ /* overflow of int, use SIZE_MAX if possible */
+ if (needed <= SIZE_MAX)
{
- newsize = LLONG_MAX;
+ newsize = SIZE_MAX;
}
else
{
@@ -388,6 +497,14 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
{
/* reallocate with realloc if available */
newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
+ if (newbuffer == NULL)
+ {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
}
else
{
@@ -426,6 +543,13 @@ static void update_offset(printbuffer * const buffer)
buffer->offset += strlen((const char*)buffer_pointer);
}
+/* securely comparison of floating-point variables */
+static cJSON_bool compare_double(double a, double b)
+{
+ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
+ return (fabs(a - b) <= maxVal * DBL_EPSILON);
+}
+
/* Render the number nicely from the given item into a string. */
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
{
@@ -433,9 +557,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
double d = item->valuedouble;
int length = 0;
size_t i = 0;
- unsigned char number_buffer[26]; /* temporary buffer to print the number into */
+ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
unsigned char decimal_point = get_decimal_point();
- double test;
+ double test = 0.0;
if (output_buffer == NULL)
{
@@ -443,7 +567,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
}
/* This checks for NaN and Infinity */
- if ((d * 0) != 0)
+ if (isnan(d) || isinf(d))
{
length = sprintf((char*)number_buffer, "null");
}
@@ -453,21 +577,21 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
length = sprintf((char*)number_buffer, "%1.15g", d);
/* Check whether the original double can be recovered */
- if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
+ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
{
/* If not, print with 17 decimal places of precision */
length = sprintf((char*)number_buffer, "%1.17g", d);
}
}
- /* sprintf failed or buffer overrun occured */
+ /* sprintf failed or buffer overrun occurred */
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
{
return false;
}
/* reserve appropriate space in the output */
- output_pointer = ensure(output_buffer, (size_t)length);
+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
if (output_pointer == NULL)
{
return false;
@@ -923,6 +1047,11 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
return NULL;
}
+ if (cannot_access_at_index(buffer, 0))
+ {
+ return buffer;
+ }
+
while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
{
buffer->offset++;
@@ -936,9 +1065,40 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
return buffer;
}
-/* Parse an object - create a new root, and populate. */
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
+ {
+ return NULL;
+ }
+
+ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
+ {
+ buffer->offset += 3;
+ }
+
+ return buffer;
+}
+
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
{
+ size_t buffer_length;
+
+ if (NULL == value)
+ {
+ return NULL;
+ }
+
+ /* Adding null character size due to require_null_terminated. */
+ buffer_length = strlen(value) + sizeof("");
+
+ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
cJSON *item = NULL;
@@ -946,13 +1106,13 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
global_error.json = NULL;
global_error.position = 0;
- if (value == NULL)
+ if (value == NULL || 0 == buffer_length)
{
goto fail;
}
buffer.content = (const unsigned char*)value;
- buffer.length = strlen((const char*)value) + sizeof("");
+ buffer.length = buffer_length;
buffer.offset = 0;
buffer.hooks = global_hooks;
@@ -962,7 +1122,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
goto fail;
}
- if (!parse_value(item, buffer_skip_whitespace(&buffer)))
+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
{
/* parse failure. ep is set. */
goto fail;
@@ -1009,10 +1169,8 @@ fail:
{
*return_parse_end = (const char*)local_error.json + local_error.position;
}
- else
- {
- global_error = local_error;
- }
+
+ global_error = local_error;
}
return NULL;
@@ -1024,17 +1182,24 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
return cJSON_ParseWithOpts(value, 0, 0);
}
-#define cjson_min(a, b) ((a < b) ? a : b)
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
+{
+ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
+}
+
+#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
{
+ static const size_t default_buffer_size = 256;
printbuffer buffer[1];
unsigned char *printed = NULL;
memset(buffer, 0, sizeof(buffer));
/* create buffer */
- buffer->buffer = (unsigned char*) hooks->allocate(256);
+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
+ buffer->length = default_buffer_size;
buffer->format = format;
buffer->hooks = *hooks;
if (buffer->buffer == NULL)
@@ -1052,11 +1217,11 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
/* check if reallocate is available */
if (hooks->reallocate != NULL)
{
- printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->length);
- buffer->buffer = NULL;
+ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
if (printed == NULL) {
goto fail;
}
+ buffer->buffer = NULL;
}
else /* otherwise copy the JSON over to a new buffer */
{
@@ -1122,26 +1287,27 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
if (!print_value(item, &p))
{
+ global_hooks.deallocate(p.buffer);
return NULL;
}
return (char*)p.buffer;
}
-CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
{
printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
- if (len < 0)
+ if ((length < 0) || (buffer == NULL))
{
return false;
}
- p.buffer = (unsigned char*)buf;
- p.length = (size_t)len;
+ p.buffer = (unsigned char*)buffer;
+ p.length = (size_t)length;
p.offset = 0;
p.noalloc = true;
- p.format = fmt;
+ p.format = format;
p.hooks = global_hooks;
return print_value(item, &p);
@@ -1199,7 +1365,6 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf
return parse_object(item, input_buffer);
}
-
return false;
}
@@ -1250,10 +1415,6 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp
size_t raw_length = 0;
if (item->valuestring == NULL)
{
- if (!output_buffer->noalloc)
- {
- output_buffer->hooks.deallocate(output_buffer->buffer);
- }
return false;
}
@@ -1499,7 +1660,7 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
buffer_skip_whitespace(input_buffer);
if (!parse_string(current_item, input_buffer))
{
- goto fail; /* faile to parse name */
+ goto fail; /* failed to parse name */
}
buffer_skip_whitespace(input_buffer);
@@ -1619,7 +1780,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
update_offset(output_buffer);
/* print comma if not last */
- length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
+ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
output_pointer = ensure(output_buffer, length + 1);
if (output_pointer == NULL)
{
@@ -1663,17 +1824,25 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
/* Get Array size/item / object item. */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
{
- cJSON *c = array->child;
- size_t i = 0;
- while(c)
+ cJSON *child = NULL;
+ size_t size = 0;
+
+ if (array == NULL)
+ {
+ return 0;
+ }
+
+ child = array->child;
+
+ while(child != NULL)
{
- i++;
- c = c->next;
+ size++;
+ child = child->next;
}
/* FIXME: Can overflow here. Cannot be fixed without breaking the API */
- return (int)i;
+ return (int)size;
}
static cJSON* get_array_item(const cJSON *array, size_t index)
@@ -1717,7 +1886,7 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
current_element = object->child;
if (case_sensitive)
{
- while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
+ while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
{
current_element = current_element->next;
}
@@ -1730,6 +1899,10 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
}
}
+ if ((current_element == NULL) || (current_element->string == NULL)) {
+ return NULL;
+ }
+
return current_element;
}
@@ -1758,88 +1931,263 @@ static void suffix_object(cJSON *prev, cJSON *item)
/* Utility for handling references. */
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
{
- cJSON *ref = cJSON_New_Item(hooks);
- if (!ref)
+ cJSON *reference = NULL;
+ if (item == NULL)
+ {
+ return NULL;
+ }
+
+ reference = cJSON_New_Item(hooks);
+ if (reference == NULL)
{
return NULL;
}
- memcpy(ref, item, sizeof(cJSON));
- ref->string = NULL;
- ref->type |= cJSON_IsReference;
- ref->next = ref->prev = NULL;
- return ref;
+
+ memcpy(reference, item, sizeof(cJSON));
+ reference->string = NULL;
+ reference->type |= cJSON_IsReference;
+ reference->next = reference->prev = NULL;
+ return reference;
}
-/* Add item to array/object. */
-CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
- if ((item == NULL) || (array == NULL))
+ if ((item == NULL) || (array == NULL) || (array == item))
{
- return;
+ return false;
}
child = array->child;
-
+ /*
+ * To find the last item in array quickly, we use prev in array
+ */
if (child == NULL)
{
/* list is empty, start new one */
array->child = item;
+ item->prev = item;
+ item->next = NULL;
}
else
{
/* append to the end */
- while (child->next)
+ if (child->prev)
{
- child = child->next;
+ suffix_object(child->prev, item);
+ array->child->prev = item;
+ }
+ else
+ {
+ while (child->next)
+ {
+ child = child->next;
+ }
+ suffix_object(child, item);
+ array->child->prev = item;
}
- suffix_object(child, item);
}
+
+ return true;
}
-CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+/* Add item to array/object. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
- /* call cJSON_AddItemToObjectCS for code reuse */
- cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
- /* remove cJSON_StringIsConst flag */
- item->type &= ~cJSON_StringIsConst;
+ return add_item_to_array(array, item);
}
-#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic push
#endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
+/* helper function to cast away const */
+static void* cast_away_const(const void* string)
+{
+ return (void*)string;
+}
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic pop
+#endif
+
+
+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
+{
+ char *new_key = NULL;
+ int new_type = cJSON_Invalid;
+
+ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
+ {
+ return false;
+ }
+
+ if (constant_key)
+ {
+ new_key = (char*)cast_away_const(string);
+ new_type = item->type | cJSON_StringIsConst;
+ }
+ else
+ {
+ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
+ if (new_key == NULL)
+ {
+ return false;
+ }
+
+ new_type = item->type & ~cJSON_StringIsConst;
+ }
+
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+ {
+ hooks->deallocate(item->string);
+ }
+
+ item->string = new_key;
+ item->type = new_type;
+
+ return add_item_to_array(object, item);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ return add_item_to_object(object, string, item, &global_hooks, false);
+}
/* Add an item to an object with constant string as key */
-CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
{
- if (!item)
+ return add_item_to_object(object, string, item, &global_hooks, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ if (array == NULL)
{
- return;
+ return false;
+ }
+
+ return add_item_to_array(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+ if ((object == NULL) || (string == NULL))
+ {
+ return false;
}
- if (!(item->type & cJSON_StringIsConst) && item->string)
+
+ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
+{
+ cJSON *null = cJSON_CreateNull();
+ if (add_item_to_object(object, name, null, &global_hooks, false))
{
- global_hooks.deallocate(item->string);
+ return null;
}
- item->string = (char*)string;
- item->type |= cJSON_StringIsConst;
- cJSON_AddItemToArray(object, item);
+
+ cJSON_Delete(null);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
+{
+ cJSON *true_item = cJSON_CreateTrue();
+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
+ {
+ return true_item;
+ }
+
+ cJSON_Delete(true_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
+{
+ cJSON *false_item = cJSON_CreateFalse();
+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
+ {
+ return false_item;
+ }
+
+ cJSON_Delete(false_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
+{
+ cJSON *bool_item = cJSON_CreateBool(boolean);
+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
+ {
+ return bool_item;
+ }
+
+ cJSON_Delete(bool_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
+{
+ cJSON *number_item = cJSON_CreateNumber(number);
+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
+ {
+ return number_item;
+ }
+
+ cJSON_Delete(number_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
+{
+ cJSON *string_item = cJSON_CreateString(string);
+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
+ {
+ return string_item;
+ }
+
+ cJSON_Delete(string_item);
+ return NULL;
}
-#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
- #pragma GCC diagnostic pop
-#endif
-CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
{
- cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
+ cJSON *raw_item = cJSON_CreateRaw(raw);
+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
+ {
+ return raw_item;
+ }
+
+ cJSON_Delete(raw_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
+{
+ cJSON *object_item = cJSON_CreateObject();
+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
+ {
+ return object_item;
+ }
+
+ cJSON_Delete(object_item);
+ return NULL;
}
-CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
{
- cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
+ cJSON *array = cJSON_CreateArray();
+ if (add_item_to_object(object, name, array, &global_hooks, false))
+ {
+ return array;
+ }
+
+ cJSON_Delete(array);
+ return NULL;
}
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
@@ -1849,7 +2197,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
return NULL;
}
- if (item->prev != NULL)
+ if (item != parent->child)
{
/* not the first element */
item->prev->next = item->next;
@@ -1912,20 +2260,19 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const
}
/* Replace array/object items with new ones. */
-CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
{
cJSON *after_inserted = NULL;
if (which < 0)
{
- return;
+ return false;
}
after_inserted = get_array_item(array, (size_t)which);
if (after_inserted == NULL)
{
- cJSON_AddItemToArray(array, newitem);
- return;
+ return add_item_to_array(array, newitem);
}
newitem->next = after_inserted;
@@ -1939,11 +2286,12 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
{
newitem->prev->next = newitem;
}
+ return true;
}
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
{
- if ((parent == NULL) || (replacement == NULL))
+ if ((parent == NULL) || (replacement == NULL) || (item == NULL))
{
return false;
}
@@ -1960,14 +2308,20 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
{
replacement->next->prev = replacement;
}
- if (replacement->prev != NULL)
- {
- replacement->prev->next = replacement;
- }
if (parent->child == item)
{
parent->child = replacement;
}
+ else
+ { /*
+ * To find the last item in array quickly, we use prev in array.
+ * We can't modify the last item's next pointer where this item was the parent's child
+ */
+ if (replacement->prev != NULL)
+ {
+ replacement->prev->next = replacement;
+ }
+ }
item->next = NULL;
item->prev = NULL;
@@ -1976,24 +2330,42 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
return true;
}
-CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
{
if (which < 0)
{
- return;
+ return false;
+ }
+
+ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
+{
+ if ((replacement == NULL) || (string == NULL))
+ {
+ return false;
+ }
+
+ /* replace the name in the replacement */
+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
+ {
+ cJSON_free(replacement->string);
}
+ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ replacement->type &= ~cJSON_StringIsConst;
- cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
+ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
}
-CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
{
- cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItem(object, string), newitem);
+ return replace_item_in_object(object, string, newitem, false);
}
-CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
{
- cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItemCaseSensitive(object, string), newitem);
+ return replace_item_in_object(object, string, newitem, true);
}
/* Create basic types: */
@@ -2030,12 +2402,12 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
return item;
}
-CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if(item)
{
- item->type = b ? cJSON_True : cJSON_False;
+ item->type = boolean ? cJSON_True : cJSON_False;
}
return item;
@@ -2054,7 +2426,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
{
item->valueint = LLONG_MAX;
}
- else if (num <= LLONG_MIN)
+ else if (num <= (double)LLONG_MIN)
{
item->valueint = LLONG_MIN;
}
@@ -2084,6 +2456,39 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
return item;
}
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL)
+ {
+ item->type = cJSON_String | cJSON_IsReference;
+ item->valuestring = (char*)cast_away_const(string);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Object | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Array | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
{
cJSON *item = cJSON_New_Item(&global_hooks);
@@ -2131,7 +2536,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
cJSON *p = NULL;
cJSON *a = NULL;
- if (count < 0)
+ if ((count < 0) || (numbers == NULL))
{
return NULL;
}
@@ -2166,7 +2571,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
cJSON *p = NULL;
cJSON *a = NULL;
- if (count < 0)
+ if ((count < 0) || (numbers == NULL))
{
return NULL;
}
@@ -2202,7 +2607,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
cJSON *p = NULL;
cJSON *a = NULL;
- if (count < 0)
+ if ((count < 0) || (numbers == NULL))
{
return NULL;
}
@@ -2231,14 +2636,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
return a;
}
-CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
{
size_t i = 0;
cJSON *n = NULL;
cJSON *p = NULL;
cJSON *a = NULL;
- if (count < 0)
+ if ((count < 0) || (strings == NULL))
{
return NULL;
}
@@ -2347,63 +2752,96 @@ fail:
return NULL;
}
-CJSON_PUBLIC(void) cJSON_Minify(char *json)
+static void skip_oneline_comment(char **input)
{
- unsigned char *into = (unsigned char*)json;
- while (*json)
+ *input += static_strlen("//");
+
+ for (; (*input)[0] != '\0'; ++(*input))
{
- if (*json == ' ')
- {
- json++;
- }
- else if (*json == '\t')
- {
- /* Whitespace characters. */
- json++;
+ if ((*input)[0] == '\n') {
+ *input += static_strlen("\n");
+ return;
}
- else if (*json == '\r')
- {
- json++;
- }
- else if (*json=='\n')
+ }
+}
+
+static void skip_multiline_comment(char **input)
+{
+ *input += static_strlen("/*");
+
+ for (; (*input)[0] != '\0'; ++(*input))
+ {
+ if (((*input)[0] == '*') && ((*input)[1] == '/'))
{
- json++;
+ *input += static_strlen("*/");
+ return;
}
- else if ((*json == '/') && (json[1] == '/'))
- {
- /* double-slash comments, to end of line. */
- while (*json && (*json != '\n'))
- {
- json++;
- }
+ }
+}
+
+static void minify_string(char **input, char **output) {
+ (*output)[0] = (*input)[0];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+
+
+ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
+ (*output)[0] = (*input)[0];
+
+ if ((*input)[0] == '\"') {
+ (*output)[0] = '\"';
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+ return;
+ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
+ (*output)[1] = (*input)[1];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
}
- else if ((*json == '/') && (json[1] == '*'))
+ }
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+ char *into = json;
+
+ if (json == NULL)
+ {
+ return;
+ }
+
+ while (json[0] != '\0')
+ {
+ switch (json[0])
{
- /* multiline comments. */
- while (*json && !((*json == '*') && (json[1] == '/')))
- {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
json++;
- }
- json += 2;
- }
- else if (*json == '\"')
- {
- /* string literals, which are \" sensitive. */
- *into++ = (unsigned char)*json++;
- while (*json && (*json != '\"'))
- {
- if (*json == '\\')
+ break;
+
+ case '/':
+ if (json[1] == '/')
{
- *into++ = (unsigned char)*json++;
+ skip_oneline_comment(&json);
}
- *into++ = (unsigned char)*json++;
- }
- *into++ = (unsigned char)*json++;
- }
- else
- {
- /* All other characters. */
- *into++ = (unsigned char)*json++;
+ else if (json[1] == '*')
+ {
+ skip_multiline_comment(&json);
+ } else {
+ json++;
+ }
+ break;
+
+ case '\"':
+ minify_string(&json, (char**)&into);
+ break;
+
+ default:
+ into[0] = json[0];
+ json++;
+ into++;
}
}
@@ -2550,7 +2988,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
return true;
case cJSON_Number:
- if (a->valuedouble == b->valuedouble)
+ if (compare_double(a->valuedouble, b->valuedouble))
{
return true;
}
@@ -2585,16 +3023,22 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
b_element = b_element->next;
}
+ /* one of the arrays is longer than the other */
+ if (a_element != b_element) {
+ return false;
+ }
+
return true;
}
case cJSON_Object:
{
cJSON *a_element = NULL;
+ cJSON *b_element = NULL;
cJSON_ArrayForEach(a_element, a)
{
/* TODO This has O(n^2) runtime, which is horrible! */
- cJSON *b_element = get_object_item(b, a_element->string, case_sensitive);
+ b_element = get_object_item(b, a_element->string, case_sensitive);
if (b_element == NULL)
{
return false;
@@ -2606,6 +3050,22 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
}
}
+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
+ * TODO: Do this the proper way, this is just a fix for now */
+ cJSON_ArrayForEach(b_element, b)
+ {
+ a_element = get_object_item(a, b_element->string, case_sensitive);
+ if (a_element == NULL)
+ {
+ return false;
+ }
+
+ if (!cJSON_Compare(b_element, a_element, case_sensitive))
+ {
+ return false;
+ }
+ }
+
return true;
}
diff --git a/src/cjson.h b/src/cjson.h
index fa7cb73..03bc353 100644
--- a/src/cjson.h
+++ b/src/cjson.h
@@ -33,10 +33,60 @@ extern "C"
{
#endif
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
+
+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+For *nix builds that support visibility attribute, you can define similar behavior by
+
+setting default visibility to hidden by adding
+-fvisibility=hidden (for gcc)
+or
+-xldscope=hidden (for sun cc)
+to CFLAGS
+
+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+*/
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type) type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
/* project version */
#define CJSON_VERSION_MAJOR 1
-#define CJSON_VERSION_MINOR 5
-#define CJSON_VERSION_PATCH 2
+#define CJSON_VERSION_MINOR 7
+#define CJSON_VERSION_PATCH 13
#include <stddef.h>
@@ -79,55 +129,13 @@ typedef struct cJSON
typedef struct cJSON_Hooks
{
- void *(*malloc_fn)(size_t sz);
- void (*free_fn)(void *ptr);
+ /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+ void *(CJSON_CDECL *malloc_fn)(size_t sz);
+ void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
-#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
-#define __WINDOWS__
-#endif
-#ifdef __WINDOWS__
-
-/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
-
-CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
-CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
-CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
-
-For *nix builds that support visibility attribute, you can define similar behavior by
-
-setting default visibility to hidden by adding
--fvisibility=hidden (for gcc)
-or
--xldscope=hidden (for sun cc)
-to CFLAGS
-
-then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
-
-*/
-
-/* export symbols by default, this is necessary for copy pasting the C and header file */
-#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
-#define CJSON_EXPORT_SYMBOLS
-#endif
-
-#if defined(CJSON_HIDE_SYMBOLS)
-#define CJSON_PUBLIC(type) type __stdcall
-#elif defined(CJSON_EXPORT_SYMBOLS)
-#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
-#elif defined(CJSON_IMPORT_SYMBOLS)
-#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
-#endif
-#else /* !WIN32 */
-#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
-#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
-#else
-#define CJSON_PUBLIC(type) type
-#endif
-#endif
-
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
@@ -143,6 +151,12 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
+
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
@@ -153,11 +167,11 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
-CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
-/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
@@ -166,6 +180,10 @@ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *st
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+/* Check item type and return its value */
+CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
+CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item);
+
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
@@ -190,24 +208,33 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
-/* These utilities create an Array of count items. */
+/* Create a string where valuestring references a string so
+ * it will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
+/* Create an object/array that only references it's elements so
+ * they will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
+
+/* These utilities create an Array of count items.
+ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
-CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
-CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
-CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
-CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
-CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
-CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
-/* Remove/Detatch items from Arrays/Objects. */
+/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
@@ -217,44 +244,47 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
-CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
-CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
-CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
-CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
-need to be released. With recurse!=0, it will duplicate any children connected to the item.
-The item->next and ->prev pointers are always zero on return from Duplicate. */
+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.
+ * The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
-
-/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
-/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
-CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
-
+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
+ * The input pointer json cannot point to a read-only address area, such as a string constant,
+ * but should point to a readable and writable adress area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
-/* Macros for creating things quickly. */
-#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
-#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
-#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
-#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
-#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
-#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
-#define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s))
+/* Helper functions for creating and adding items to an object at the same time.
+ * They return the added item or NULL on failure. */
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
-/* Macro for iterating over an array */
+/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
diff --git a/src/dscp.c b/src/dscp.c
index 329b304..d0c109b 100644
--- a/src/dscp.c
+++ b/src/dscp.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <string.h>
+#include <strings.h>
#include <stdlib.h>
#include <inttypes.h>
@@ -42,10 +43,10 @@ const char * iptos2str(int iptos);
* Definitions for IP type of service (ip_tos)
*/
-#if HAVE_NETINET_IN_SYSTM_H
+#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
-#if HAVE_NETINET_IP_H
+#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
diff --git a/src/iperf.h b/src/iperf.h
index 6ce77f5..5b1da46 100755..100644
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2019, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -68,7 +68,9 @@
#include <openssl/evp.h>
#endif // HAVE_SSL
+#if !defined(__IPERF_API_H)
typedef uint64_t iperf_size_t;
+#endif // __IPERF_API_H
struct iperf_interval_results
{
@@ -135,7 +137,10 @@ struct iperf_settings
int domain; /* AF_INET or AF_INET6 */
int socket_bufsize; /* window size for TCP */
int blksize; /* size of read/writes (-l) */
- uint64_t rate; /* target data rate for application pacing*/
+ iperf_size_t rate; /* target data rate for application pacing*/
+ iperf_size_t bitrate_limit; /* server's maximum allowed total data rate for all streams*/
+ double bitrate_limit_interval; /* interval for avaraging total data rate */
+ int bitrate_limit_stats_per_interval; /* calculated number of stats periods for averaging total data rate */
uint64_t fqrate; /* target data rate for FQ pacing*/
int pacing_timer; /* pacing timer in microseconds */
int burst; /* packets per burst */
@@ -298,6 +303,8 @@ struct iperf_test
int forceflush; /* --forceflush - flushing output at every interval */
int multisend;
int repeating_payload; /* --repeating-payload */
+ int timestamps; /* --timestamps */
+ char *timestamp_format;
char *json_output_string; /* rendered JSON output if json_output is set */
/* Select related parameters */
@@ -328,6 +335,11 @@ struct iperf_test
iperf_size_t bytes_received;
iperf_size_t blocks_received;
+ iperf_size_t bitrate_limit_stats_count; /* Number of stats periods accumulated for server's total bitrate average */
+ iperf_size_t *bitrate_limit_intervals_traffic_bytes; /* Pointer to a cyclic array that includes the last interval's bytes transferred */
+ iperf_size_t bitrate_limit_last_interval_index; /* Index of the last interval traffic insrted into the cyclic array */
+ int bitrate_limit_exceeded; /* Set by callback routine when average data rate exceeded the server's bitrate limit */
+
char cookie[COOKIE_SIZE];
// struct iperf_stream *streams; /* pointer to list of struct stream */
SLIST_HEAD(slisthead, iperf_stream) streams;
@@ -385,6 +397,8 @@ struct iperf_test
#define MAX_MSS (9 * 1024)
#define MAX_STREAMS 128
+#define TIMESTAMP_FORMAT "%c "
+
extern int gerror; /* error value from getaddrinfo(3), for use in internal error handling */
#endif /* !__IPERF_H */
diff --git a/src/iperf3.1 b/src/iperf3.1
index 8b08fcb..97d66ed 100644
--- a/src/iperf3.1
+++ b/src/iperf3.1
@@ -1,4 +1,4 @@
-.TH IPERF3 1 "June 2018" ESnet "User Manuals"
+.TH IPERF3 1 "July 2020" ESnet "User Manuals"
.SH NAME
iperf3 \- perform network throughput tests
.SH SYNOPSIS
@@ -153,6 +153,14 @@ send output to a log file.
force flushing output at every interval.
Used to avoid buffering when sending output to pipe.
.TP
+.BR --timestamps " [\fIformat\fR]"
+prepend a timestamp at the start of each output line.
+By default, timestamps have the format emitted by
+.BR ctime ( 1 ).
+Optionally, a format specification can be passed to customize the
+timestamps, see
+.BR strftime ( 3 ).
+.TP
.BR -d ", " --debug " "
emit debugging output.
Primarily (perhaps exclusively) of use to developers.
@@ -177,6 +185,15 @@ write a file with the process ID, most useful when running as a daemon.
.BR -1 ", " --one-off
handle one client connection, then exit.
.TP
+.BR --server-bitrate-limit " \fIn\fR[KMGT]"
+set a limit on the server side, which will cause a test to abort if
+the client specifies a test of more than \fIn\fR bits per second, or
+if the average data sent or received by the client (including all data
+streams) is greater than \fIn\fR bits per second. The default limit
+is zero, which implies no limit. The interval over which to average
+the data rate is 5 seconds by default, but can be specified by adding
+a '/' and a number to the bitrate specifier.
+.TP
.BR --rsa-private-key-path " \fIfile\fR"
path to the RSA private key (not password-protected) used to decrypt
authentication credentials from the client (if built with OpenSSL
@@ -209,7 +226,7 @@ connection establishment.
Providing a shorter value may speed up detection of a down iperf3
server.
.TP
-.BR -b ", " --bitrate " \fIn\fR[KM]"
+.BR -b ", " --bitrate " \fIn\fR[KMGT]"
set target bitrate to \fIn\fR bits/sec (default 1 Mbit/sec for UDP,
unlimited for TCP/SCTP).
If there are multiple streams (\-P flag), the throughput limit is applied
@@ -226,7 +243,7 @@ Compare with the \--fq-rate flag.
This option replaces the \--bandwidth flag, which is now deprecated
but (at least for now) still accepted.
.TP
-.BR --pacing-timer " \fIn\fR[KMG]"
+.BR --pacing-timer " \fIn\fR[KMGT]"
set pacing timer interval in microseconds (default 1000 microseconds,
or 1 ms).
This controls iperf3's internal pacing timer for the \-b/\--bitrate
@@ -236,7 +253,7 @@ Smaller values of the pacing timer parameter smooth out the traffic
emitted by iperf3, but potentially at the cost of performance due to
more frequent timer processing.
.TP
-.BR --fq-rate " \fIn\fR[KM]"
+.BR --fq-rate " \fIn\fR[KMGT]"
Set a rate to be used with fair-queueing based socket-level pacing,
in bits per second.
This pacing (if specified) will be in addition to any pacing due to
@@ -253,13 +270,13 @@ It is equivalent to specifying --fq-rate=0.
.BR -t ", " --time " \fIn\fR"
time in seconds to transmit for (default 10 secs)
.TP
-.BR -n ", " --bytes " \fIn\fR[KM]"
+.BR -n ", " --bytes " \fIn\fR[KMGT]"
number of bytes to transmit (instead of \-t)
.TP
-.BR -k ", " --blockcount " \fIn\fR[KM]"
+.BR -k ", " --blockcount " \fIn\fR[KMGT]"
number of blocks (packets) to transmit (instead of \-t or \-n)
.TP
-.BR -l ", " --length " \fIn\fR[KM]"
+.BR -l ", " --length " \fIn\fR[KMGT]"
length of buffer to read or write. For TCP tests, the default value
is 128KB.
In the case of UDP, iperf3 tries to dynamically determine a reasonable
@@ -278,7 +295,11 @@ number of parallel client streams to run. Note that iperf3 is single threaded, s
reverse the direction of a test, so that the server sends data to the
client
.TP
-.BR -w ", " --window " \fIn\fR[KM]"
+.BR --bidir
+test in both directions (normal and reverse), with both the client and
+server sending and receiving data simultaneously
+.TP
+.BR -w ", " --window " \fIn\fR[KMGT]"
window size / socket buffer size (this gets sent to the server and used on that side too)
.TP
.BR -M ", " --set-mss " \fIn\fR"
diff --git a/src/iperf_api.c b/src/iperf_api.c
index e1bbfa5..88fed30 100755..100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2019, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -57,12 +57,17 @@
#include <sched.h>
#include <setjmp.h>
#include <stdarg.h>
+#include <math.h>
#if defined(HAVE_CPUSET_SETAFFINITY)
#include <sys/param.h>
#include <sys/cpuset.h>
#endif /* HAVE_CPUSET_SETAFFINITY */
+#if defined(__CYGWIN__) || defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
+#define CPU_SETSIZE __CPU_SETSIZE
+#endif /* __CYGWIN__, _WIN32, _WIN64, __WINDOWS__ */
+
#if defined(HAVE_SETPROCESSAFFINITYMASK)
#include <Windows.h>
#endif /* HAVE_SETPROCESSAFFINITYMASK */
@@ -72,9 +77,9 @@
#include "iperf_api.h"
#include "iperf_udp.h"
#include "iperf_tcp.h"
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
#include "iperf_sctp.h"
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
#include "timer.h"
#include "cjson.h"
@@ -115,7 +120,7 @@ usage_long(FILE *f)
}
-void warning(char *str)
+void warning(const char *str)
{
fprintf(stderr, "warning: %s\n", str);
}
@@ -160,6 +165,24 @@ iperf_get_test_rate(struct iperf_test *ipt)
}
uint64_t
+iperf_get_test_bitrate_limit(struct iperf_test *ipt)
+{
+ return ipt->settings->bitrate_limit;
+}
+
+double
+iperf_get_test_bitrate_limit_interval(struct iperf_test *ipt)
+{
+ return ipt->settings->bitrate_limit_interval;
+}
+
+int
+iperf_get_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt)
+{
+ return ipt->settings->bitrate_limit_stats_per_interval;
+}
+
+uint64_t
iperf_get_test_fqrate(struct iperf_test *ipt)
{
return ipt->settings->fqrate;
@@ -238,6 +261,18 @@ iperf_get_test_num_streams(struct iperf_test *ipt)
}
int
+iperf_get_test_timestamps(struct iperf_test *ipt)
+{
+ return ipt->timestamps;
+}
+
+const char *
+iperf_get_test_timestamp_format(struct iperf_test *ipt)
+{
+ return ipt->timestamp_format;
+}
+
+int
iperf_get_test_repeating_payload(struct iperf_test *ipt)
{
return ipt->repeating_payload;
@@ -340,6 +375,12 @@ iperf_get_test_no_delay(struct iperf_test *ipt)
return ipt->no_delay;
}
+int
+iperf_get_test_connect_timeout(struct iperf_test *ipt)
+{
+ return ipt->settings->connect_timeout;
+}
+
/************** Setter routines for some fields inside iperf_test *************/
void
@@ -391,7 +432,7 @@ iperf_set_test_blksize(struct iperf_test *ipt, int blksize)
}
void
-iperf_set_test_logfile(struct iperf_test *ipt, char *logfile)
+iperf_set_test_logfile(struct iperf_test *ipt, const char *logfile)
{
ipt->logfile = strdup(logfile);
}
@@ -403,6 +444,24 @@ iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
}
void
+iperf_set_test_bitrate_limit_maximum(struct iperf_test *ipt, uint64_t total_rate)
+{
+ ipt->settings->bitrate_limit = total_rate;
+}
+
+void
+iperf_set_test_bitrate_limit_interval(struct iperf_test *ipt, uint64_t bitrate_limit_interval)
+{
+ ipt->settings->bitrate_limit_interval = bitrate_limit_interval;
+}
+
+void
+iperf_set_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt, uint64_t bitrate_limit_stats_per_interval)
+{
+ ipt->settings->bitrate_limit_stats_per_interval = bitrate_limit_stats_per_interval;
+}
+
+void
iperf_set_test_fqrate(struct iperf_test *ipt, uint64_t fqrate)
{
ipt->settings->fqrate = fqrate;
@@ -456,6 +515,18 @@ iperf_set_test_repeating_payload(struct iperf_test *ipt, int repeating_payload)
ipt->repeating_payload = repeating_payload;
}
+void
+iperf_set_test_timestamps(struct iperf_test *ipt, int timestamps)
+{
+ ipt->timestamps = timestamps;
+}
+
+void
+iperf_set_test_timestamp_format(struct iperf_test *ipt, const char *tf)
+{
+ ipt->timestamp_format = strdup(tf);
+}
+
static void
check_sender_has_retransmits(struct iperf_test *ipt)
{
@@ -470,7 +541,9 @@ iperf_set_test_role(struct iperf_test *ipt, char role)
{
ipt->role = role;
if (!ipt->reverse) {
- if (role == 'c')
+ if (ipt->bidirectional)
+ ipt->mode = BIDIRECTIONAL;
+ else if (role == 'c')
ipt->mode = SENDER;
else if (role == 's')
ipt->mode = RECEIVER;
@@ -484,13 +557,13 @@ iperf_set_test_role(struct iperf_test *ipt, char role)
}
void
-iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname)
+iperf_set_test_server_hostname(struct iperf_test *ipt, const char *server_hostname)
{
ipt->server_hostname = strdup(server_hostname);
}
void
-iperf_set_test_template(struct iperf_test *ipt, char *tmp_template)
+iperf_set_test_template(struct iperf_test *ipt, const char *tmp_template)
{
ipt->tmp_template = strdup(tmp_template);
}
@@ -545,26 +618,38 @@ iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format)
#if defined(HAVE_SSL)
void
-iperf_set_test_client_username(struct iperf_test *ipt, char *client_username)
+iperf_set_test_client_username(struct iperf_test *ipt, const char *client_username)
{
- ipt->settings->client_username = client_username;
+ ipt->settings->client_username = strdup(client_username);
}
void
-iperf_set_test_client_password(struct iperf_test *ipt, char *client_password)
+iperf_set_test_client_password(struct iperf_test *ipt, const char *client_password)
{
- ipt->settings->client_password = client_password;
+ ipt->settings->client_password = strdup(client_password);
}
void
-iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, char *client_rsa_pubkey_base64)
+iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, const char *client_rsa_pubkey_base64)
{
ipt->settings->client_rsa_pubkey = load_pubkey_from_base64(client_rsa_pubkey_base64);
}
+
+void
+iperf_set_test_server_authorized_users(struct iperf_test *ipt, const char *server_authorized_users)
+{
+ ipt->server_authorized_users = strdup(server_authorized_users);
+}
+
+void
+iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, const char *server_rsa_privkey_base64)
+{
+ ipt->server_rsa_private_key = load_privkey_from_base64(server_rsa_privkey_base64);
+}
#endif // HAVE_SSL
void
-iperf_set_test_bind_address(struct iperf_test *ipt, char *bnd_address)
+iperf_set_test_bind_address(struct iperf_test *ipt, const char *bnd_address)
{
ipt->bind_address = strdup(bnd_address);
}
@@ -588,9 +673,9 @@ iperf_set_test_tos(struct iperf_test *ipt, int tos)
}
void
-iperf_set_test_extra_data(struct iperf_test *ipt, char *dat)
+iperf_set_test_extra_data(struct iperf_test *ipt, const char *dat)
{
- ipt->extra_data = dat;
+ ipt->extra_data = strdup(dat);
}
void
@@ -609,6 +694,13 @@ iperf_set_test_no_delay(struct iperf_test* ipt, int no_delay)
ipt->no_delay = no_delay;
}
+void
+iperf_set_test_connect_timeout(struct iperf_test* ipt, int ct)
+{
+ ipt->settings->connect_timeout = ct;
+}
+
+
/********************** Get/set test protocol structure ***********************/
struct protocol *
@@ -755,7 +847,7 @@ iperf_on_connect(struct iperf_test *test)
}
}
if (test->settings->rate)
- iperf_printf(test, " Target Bitrate: %llu\n", test->settings->rate);
+ iperf_printf(test, " Target Bitrate: %"PRIu64"\n", test->settings->rate);
}
}
@@ -785,6 +877,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"udp", no_argument, NULL, 'u'},
{"bitrate", required_argument, NULL, 'b'},
{"bandwidth", required_argument, NULL, 'b'},
+ {"server-bitrate-limit", required_argument, NULL, OPT_SERVER_BITRATE_LIMIT},
{"time", required_argument, NULL, 't'},
{"bytes", required_argument, NULL, 'n'},
{"blockcount", required_argument, NULL, 'k'},
@@ -809,6 +902,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"omit", required_argument, NULL, 'O'},
{"file", required_argument, NULL, 'F'},
{"repeating-payload", no_argument, NULL, OPT_REPEATING_PAYLOAD},
+ {"timestamps", optional_argument, NULL, OPT_TIMESTAMPS},
#if defined(HAVE_CPU_AFFINITY)
{"affinity", required_argument, NULL, 'A'},
#endif /* HAVE_CPU_AFFINITY */
@@ -817,7 +911,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"congestion", required_argument, NULL, 'C'},
{"linux-congestion", required_argument, NULL, 'C'},
#endif /* HAVE_TCP_CONGESTION */
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
{"sctp", no_argument, NULL, OPT_SCTP},
{"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
{"xbind", required_argument, NULL, 'X'},
@@ -937,14 +1031,14 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
client_flag = 1;
break;
case OPT_SCTP:
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
set_protocol(test, Psctp);
client_flag = 1;
break;
-#else /* HAVE_SCTP */
+#else /* HAVE_SCTP_H */
i_errno = IEUNIMP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
case OPT_NUMSTREAMS:
#if defined(linux) || defined(__FreeBSD__)
@@ -970,6 +1064,21 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
rate_flag = 1;
client_flag = 1;
break;
+ case OPT_SERVER_BITRATE_LIMIT:
+ slash = strchr(optarg, '/');
+ if (slash) {
+ *slash = '\0';
+ ++slash;
+ test->settings->bitrate_limit_interval = atof(slash);
+ if (test->settings->bitrate_limit_interval != 0 && /* Using same Max/Min limits as for Stats Interval */
+ (test->settings->bitrate_limit_interval < MIN_INTERVAL || test->settings->bitrate_limit_interval > MAX_INTERVAL) ) {
+ i_errno = IETOTALINTERVAL;
+ return -1;
+ }
+ }
+ test->settings->bitrate_limit = unit_atof_rate(optarg);
+ server_flag = 1;
+ break;
case 't':
test->duration = atoi(optarg);
if (test->duration > MAX_TIME) {
@@ -1118,6 +1227,15 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
test->repeating_payload = 1;
client_flag = 1;
break;
+ case OPT_TIMESTAMPS:
+ iperf_set_test_timestamps(test, 1);
+ if (optarg) {
+ iperf_set_test_timestamp_format(test, optarg);
+ }
+ else {
+ iperf_set_test_timestamp_format(test, TIMESTAMP_FORMAT);
+ }
+ break;
case 'O':
test->omit = atoi(optarg);
if (test->omit < 0 || test->omit > 60) {
@@ -1261,14 +1379,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
if ((client_password = getenv("IPERF3_PASSWORD")) != NULL)
client_password = strdup(client_password);
else if (iperf_getpass(&client_password, &s, stdin) < 0){
- return -1;
- }
-
- if (strlen(client_username) > 20 || strlen(client_password) > 20){
i_errno = IESETCLIENTAUTH;
return -1;
- }
-
+ }
if (test_load_pubkey_from_file(client_rsa_public_key) < 0){
i_errno = IESETCLIENTAUTH;
return -1;
@@ -1349,6 +1462,13 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
return -1;
}
+ /* Set Total-rate average interval to multiplicity of State interval */
+ if (test->settings->bitrate_limit_interval != 0) {
+ test->settings->bitrate_limit_stats_per_interval =
+ (test->settings->bitrate_limit_interval <= test->stats_interval ?
+ 1 : round(test->settings->bitrate_limit_interval/test->stats_interval) );
+ }
+
/* Show warning if JSON output is used with explicit report format */
if ((test->json_output) && (test->settings->unit_format != 'a')) {
warning("Report format (-f) flag ignored with JSON output (-J)");
@@ -1397,7 +1517,7 @@ iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP)
double seconds;
uint64_t bits_per_second;
- if (sp->test->done)
+ if (sp->test->done || sp->test->settings->rate == 0 || sp->test->settings->burst != 0)
return;
iperf_time_diff(&sp->result->start_time_fixed, nowP, &temp_time);
seconds = iperf_time_in_secs(&temp_time);
@@ -1411,6 +1531,45 @@ iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP)
}
}
+/* Verify that average traffic is not greater than the specifid limit */
+void
+iperf_check_total_rate(struct iperf_test *test, iperf_size_t last_interval_bytes_transferred)
+{
+ double seconds;
+ uint64_t bits_per_second;
+ iperf_size_t total_bytes;
+ int i;
+
+ if (test->done || test->settings->bitrate_limit == 0) // Continue only if check should be done
+ return;
+
+ /* Add last inetrval's transffered bytes to the array */
+ if (++test->bitrate_limit_last_interval_index >= test->settings->bitrate_limit_stats_per_interval)
+ test->bitrate_limit_last_interval_index = 0;
+ test->bitrate_limit_intervals_traffic_bytes[test->bitrate_limit_last_interval_index] = last_interval_bytes_transferred;
+
+ /* Ensure that enough stats periods passed to allow averaging throughput */
+ test->bitrate_limit_stats_count += 1;
+ if (test->bitrate_limit_stats_count < test->settings->bitrate_limit_stats_per_interval)
+ return;
+
+ /* Calculating total bytes traffic to be averaged */
+ for (total_bytes = 0, i = 0; i < test->settings->bitrate_limit_stats_per_interval; i++) {
+ total_bytes += test->bitrate_limit_intervals_traffic_bytes[i];
+ }
+
+ seconds = test->stats_interval * test->settings->bitrate_limit_stats_per_interval;
+ bits_per_second = total_bytes * 8 / seconds;
+ if (test->debug) {
+ iperf_printf(test,"Interval %" PRIu64 " - throughput %" PRIu64 " bps (limit %" PRIu64 ")\n", test->bitrate_limit_stats_count, bits_per_second, test->settings->bitrate_limit);
+ }
+
+ if (bits_per_second > test->settings->bitrate_limit) {
+ iperf_err(test, "Total throughput of %" PRIu64 " bps exceeded %" PRIu64 " bps limit", bits_per_second, test->settings->bitrate_limit);
+ test->bitrate_limit_exceeded = 1;
+ }
+}
+
int
iperf_send(struct iperf_test *test, fd_set *write_setP)
{
@@ -1442,8 +1601,7 @@ iperf_send(struct iperf_test *test, fd_set *write_setP)
streams_active = 1;
test->bytes_sent += r;
++test->blocks_sent;
- if (test->settings->rate != 0 && test->settings->burst == 0)
- iperf_check_throttle(sp, &now);
+ iperf_check_throttle(sp, &now);
if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
break;
if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)
@@ -1456,7 +1614,8 @@ iperf_send(struct iperf_test *test, fd_set *write_setP)
if (test->settings->burst != 0) {
iperf_time_now(&now);
SLIST_FOREACH(sp, &test->streams, streams)
- iperf_check_throttle(sp, &now);
+ if (sp->sender)
+ iperf_check_throttle(sp, &now);
}
if (write_setP != NULL)
SLIST_FOREACH(sp, &test->streams, streams)
@@ -1538,7 +1697,7 @@ iperf_create_send_timers(struct iperf_test * test)
}
SLIST_FOREACH(sp, &test->streams, streams) {
sp->green_light = 1;
- if (test->settings->rate != 0) {
+ if (test->settings->rate != 0 && sp->sender) {
cd.p = sp;
sp->send_timer = tmr_create(NULL, send_timer_proc, cd, test->settings->pacing_timer, 1);
if (sp->send_timer == NULL) {
@@ -1559,15 +1718,18 @@ int test_is_authorized(struct iperf_test *test){
if (test->settings->authtoken){
char *username = NULL, *password = NULL;
time_t ts;
- decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
+ int rc = decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
+ if (rc) {
+ return -1;
+ }
int ret = check_authentication(username, password, ts, test->server_authorized_users);
if (ret == 0){
- iperf_printf(test, report_authetication_successed, username, ts);
+ iperf_printf(test, report_authentication_succeeded, username, ts);
free(username);
free(password);
return 0;
} else {
- iperf_printf(test, report_authetication_failed, username, ts);
+ iperf_printf(test, report_authentication_failed, username, ts);
free(username);
free(password);
return -1;
@@ -1627,6 +1789,7 @@ iperf_exchange_parameters(struct iperf_test *test)
}
return -1;
}
+
FD_SET(s, &test->read_set);
test->max_fd = (s > test->max_fd) ? s : test->max_fd;
test->prot_listener = s;
@@ -1730,15 +1893,25 @@ send_parameters(struct iperf_test *test)
if (test->repeating_payload)
cJSON_AddNumberToObject(j, "repeating_payload", test->repeating_payload);
#if defined(HAVE_SSL)
- if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){
- encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken);
- cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken);
- }
+ /* Send authentication parameters */
+ if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){
+ int rc = encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken);
+
+ if (rc) {
+ cJSON_Delete(j);
+ i_errno = IESENDPARAMS;
+ return -1;
+ }
+
+ cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken);
+ }
#endif // HAVE_SSL
cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
if (test->debug) {
- printf("send_parameters:\n%s\n", cJSON_Print(j));
+ char *str = cJSON_Print(j);
+ printf("send_parameters:\n%s\n", str);
+ cJSON_free(str);
}
if (JSON_write(test->ctrl_sck, j) < 0) {
@@ -1768,7 +1941,7 @@ get_parameters(struct iperf_test *test)
char *str;
str = cJSON_Print(j);
printf("get_parameters:\n%s\n", str );
- free(str);
+ cJSON_free(str);
}
if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
@@ -1833,8 +2006,8 @@ get_parameters(struct iperf_test *test)
#endif //HAVE_SSL
if (test->mode && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
test->sender_has_retransmits = 1;
- if (test->settings->rate)
- cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
+ if (test->settings->rate)
+ cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
cJSON_Delete(j);
}
return r;
@@ -1935,7 +2108,7 @@ send_results(struct iperf_test *test)
if (r == 0 && test->debug) {
char *str = cJSON_Print(j);
printf("send_results\n%s\n", str);
- free(str);
+ cJSON_free(str);
}
if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
i_errno = IESENDRESULTS;
@@ -1993,7 +2166,7 @@ get_results(struct iperf_test *test)
if (test->debug) {
char *str = cJSON_Print(j);
printf("get_results\n%s\n", str);
- free(str);
+ cJSON_free(str);
}
test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
@@ -2130,7 +2303,7 @@ JSON_write(int fd, cJSON *json)
if (Nwrite(fd, str, hsize, Ptcp) < 0)
r = -1;
}
- free(str);
+ cJSON_free(str);
}
return r;
}
@@ -2252,6 +2425,14 @@ iperf_new_test()
}
memset(test->settings, 0, sizeof(struct iperf_settings));
+ test->bitrate_limit_intervals_traffic_bytes = (iperf_size_t *) malloc(sizeof(iperf_size_t) * MAX_INTERVAL);
+ if (!test->bitrate_limit_intervals_traffic_bytes) {
+ free(test);
+ i_errno = IENEWTEST;
+ return NULL;
+ }
+ memset(test->bitrate_limit_intervals_traffic_bytes, 0, sizeof(sizeof(iperf_size_t) * MAX_INTERVAL));
+
/* By default all output goes to stdout */
test->outfile = stdout;
@@ -2285,9 +2466,9 @@ int
iperf_defaults(struct iperf_test *testp)
{
struct protocol *tcp, *udp;
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
struct protocol *sctp;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
testp->omit = OMIT;
testp->duration = DURATION;
@@ -2319,6 +2500,9 @@ iperf_defaults(struct iperf_test *testp)
testp->settings->socket_bufsize = 0; /* use autotuning */
testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
testp->settings->rate = 0;
+ testp->settings->bitrate_limit = 0;
+ testp->settings->bitrate_limit_interval = 5;
+ testp->settings->bitrate_limit_stats_per_interval = 0;
testp->settings->fqrate = 0;
testp->settings->pacing_timer = 1000;
testp->settings->burst = 0;
@@ -2366,7 +2550,7 @@ iperf_defaults(struct iperf_test *testp)
set_protocol(testp, Ptcp);
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
sctp = protocol_new();
if (!sctp) {
protocol_free(tcp);
@@ -2384,7 +2568,7 @@ iperf_defaults(struct iperf_test *testp)
sctp->init = iperf_sctp_init;
SLIST_INSERT_AFTER(udp, sctp, protocols);
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
testp->on_new_stream = iperf_on_new_stream;
testp->on_test_start = iperf_on_test_start;
@@ -2460,6 +2644,8 @@ iperf_free_test(struct iperf_test *test)
free(test->congestion_used);
if (test->remote_congestion_used)
free(test->remote_congestion_used);
+ if (test->timestamp_format)
+ free(test->timestamp_format);
if (test->omit_timer != NULL)
tmr_cancel(test->omit_timer);
if (test->timer != NULL)
@@ -2476,6 +2662,15 @@ iperf_free_test(struct iperf_test *test)
free(prot);
}
+ if (test->logfile) {
+ free(test->logfile);
+ test->logfile = NULL;
+ if (test->outfile) {
+ fclose(test->outfile);
+ test->outfile = NULL;
+ }
+ }
+
if (test->server_output_text) {
free(test->server_output_text);
test->server_output_text = NULL;
@@ -2507,6 +2702,10 @@ iperf_free_test(struct iperf_test *test)
}
}
+ /* Free interval's traffic array for avrage rate calculations */
+ if (test->bitrate_limit_intervals_traffic_bytes != NULL)
+ free(test->bitrate_limit_intervals_traffic_bytes);
+
/* XXX: Why are we setting these values to NULL? */
// test->streams = NULL;
test->stats_callback = NULL;
@@ -2519,6 +2718,7 @@ void
iperf_reset_test(struct iperf_test *test)
{
struct iperf_stream *sp;
+ int i;
/* Free streams */
while (!SLIST_EMPTY(&test->streams)) {
@@ -2572,6 +2772,13 @@ iperf_reset_test(struct iperf_test *test)
test->other_side_has_retransmits = 0;
+ test->bitrate_limit_stats_count = 0;
+ test->bitrate_limit_last_interval_index = 0;
+ test->bitrate_limit_exceeded = 0;
+
+ for (i = 0; i < MAX_INTERVAL; i++)
+ test->bitrate_limit_intervals_traffic_bytes[i] = 0;
+
test->reverse = 0;
test->bidirectional = 0;
test->no_delay = 0;
@@ -2675,12 +2882,16 @@ iperf_stats_callback(struct iperf_test *test)
struct iperf_stream_result *rp = NULL;
struct iperf_interval_results *irp, temp;
struct iperf_time temp_time;
+ iperf_size_t total_interval_bytes_transferred = 0;
temp.omitted = test->omitting;
SLIST_FOREACH(sp, &test->streams, streams) {
rp = sp->result;
temp.bytes_transferred = sp->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
-
+
+ // Total bytes transferred this interval
+ total_interval_bytes_transferred += rp->bytes_sent_this_interval + rp->bytes_received_this_interval;
+
irp = TAILQ_LAST(&rp->interval_results, irlisthead);
/* result->end_time contains timestamp of previous interval */
if ( irp != NULL ) /* not the 1st interval */
@@ -2739,6 +2950,11 @@ iperf_stats_callback(struct iperf_test *test)
add_to_interval_list(rp, &temp);
rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
}
+
+ /* Verify that total server's throughput is not above specified limit */
+ if (test->role == 's') {
+ iperf_check_total_rate(test, total_interval_bytes_transferred);
+ }
}
/**
@@ -3417,7 +3633,9 @@ iperf_print_results(struct iperf_test *test)
/* Print server output if we're on the client and it was requested/provided */
if (test->role == 'c' && iperf_get_test_get_server_output(test) && !test->json_output) {
if (test->json_server_output) {
- iperf_printf(test, "\nServer JSON output:\n%s\n", cJSON_Print(test->json_server_output));
+ char *str = cJSON_Print(test->json_server_output);
+ iperf_printf(test, "\nServer JSON output:\n%s\n", str);
+ cJSON_free(str);
cJSON_Delete(test->json_server_output);
test->json_server_output = NULL;
}
@@ -3849,9 +4067,15 @@ diskfile_recv(struct iperf_stream *sp)
void
iperf_catch_sigend(void (*handler)(int))
{
+#ifdef SIGINT
signal(SIGINT, handler);
+#endif
+#ifdef SIGTERM
signal(SIGTERM, handler);
+#endif
+#ifdef SIGHUP
signal(SIGHUP, handler);
+#endif
}
/**
@@ -3995,6 +4219,8 @@ iperf_json_finish(struct iperf_test *test)
return -1;
fprintf(test->outfile, "%s\n", test->json_output_string);
iflush(test);
+ cJSON_free(test->json_output_string);
+ test->json_output_string = NULL;
cJSON_Delete(test->json_top);
test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
return 0;
@@ -4088,11 +4314,24 @@ iperf_clearaffinity(struct iperf_test *test)
#endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
}
+char iperf_timestr[100];
+
int
iperf_printf(struct iperf_test *test, const char* format, ...)
{
va_list argp;
int r = -1;
+ time_t now;
+ struct tm *ltm = NULL;
+ char *ct = NULL;
+
+ /* Timestamp if requested */
+ if (iperf_get_test_timestamps(test)) {
+ time(&now);
+ ltm = localtime(&now);
+ strftime(iperf_timestr, sizeof(iperf_timestr), iperf_get_test_timestamp_format(test), ltm);
+ ct = iperf_timestr;
+ }
/*
* There are roughly two use cases here. If we're the client,
@@ -4107,6 +4346,9 @@ iperf_printf(struct iperf_test *test, const char* format, ...)
* to be buffered up anyway.
*/
if (test->role == 'c') {
+ if (ct) {
+ fprintf(test->outfile, "%s", ct);
+ }
if (test->title)
fprintf(test->outfile, "%s: ", test->title);
va_start(argp, format);
@@ -4115,8 +4357,12 @@ iperf_printf(struct iperf_test *test, const char* format, ...)
}
else if (test->role == 's') {
char linebuffer[1024];
+ int i = 0;
+ if (ct) {
+ i = sprintf(linebuffer, "%s", ct);
+ }
va_start(argp, format);
- r = vsnprintf(linebuffer, sizeof(linebuffer), format, argp);
+ r = vsnprintf(linebuffer + i, sizeof(linebuffer), format, argp);
va_end(argp);
fprintf(test->outfile, "%s", linebuffer);
diff --git a/src/iperf_api.h b/src/iperf_api.h
index f9f964e..a51b773 100755..100644
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2019, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -45,6 +45,10 @@ struct iperf_interval_results;
struct iperf_stream;
struct iperf_time;
+#if !defined(__IPERF_H)
+typedef uint64_t iperf_size_t;
+#endif // __IPERF_H
+
/* default settings */
#define Ptcp SOCK_STREAM
#define Pudp SOCK_DGRAM
@@ -73,6 +77,8 @@ struct iperf_time;
#define OPT_REPEATING_PAYLOAD 18
#define OPT_EXTRA_DATA 19
#define OPT_BIDIRECTIONAL 20
+#define OPT_SERVER_BITRATE_LIMIT 21
+#define OPT_TIMESTAMPS 22
/* states */
#define TEST_START 1
@@ -113,6 +119,8 @@ double iperf_get_test_reporter_interval( struct iperf_test* ipt );
double iperf_get_test_stats_interval( struct iperf_test* ipt );
int iperf_get_test_num_streams( struct iperf_test* ipt );
int iperf_get_test_repeating_payload( struct iperf_test* ipt );
+int iperf_get_test_timestamps( struct iperf_test* ipt );
+const char* iperf_get_test_timestamp_format( struct iperf_test* ipt );
int iperf_get_test_server_port( struct iperf_test* ipt );
char* iperf_get_test_server_hostname( struct iperf_test* ipt );
char* iperf_get_test_template( struct iperf_test* ipt );
@@ -128,6 +136,7 @@ int iperf_get_test_tos( struct iperf_test* ipt );
char* iperf_get_extra_data( struct iperf_test* ipt );
char* iperf_get_iperf_version(void);
int iperf_get_test_no_delay( struct iperf_test* ipt );
+int iperf_get_test_connect_timeout( struct iperf_test* ipt );
/* Setter routines for some fields inside iperf_test. */
void iperf_set_verbose( struct iperf_test* ipt, int verbose );
@@ -138,7 +147,7 @@ void iperf_set_test_reporter_interval( struct iperf_test* ipt, double reporter_i
void iperf_set_test_stats_interval( struct iperf_test* ipt, double stats_interval );
void iperf_set_test_state( struct iperf_test* ipt, signed char state );
void iperf_set_test_blksize( struct iperf_test* ipt, int blksize );
-void iperf_set_test_logfile( struct iperf_test* ipt, char *logfile );
+void iperf_set_test_logfile( struct iperf_test* ipt, const char *logfile );
void iperf_set_test_rate( struct iperf_test* ipt, uint64_t rate );
void iperf_set_test_pacing_timer( struct iperf_test* ipt, int pacing_timer );
void iperf_set_test_bytes( struct iperf_test* ipt, uint64_t bytes );
@@ -148,28 +157,34 @@ void iperf_set_test_server_port( struct iperf_test* ipt, int server_port );
void iperf_set_test_socket_bufsize( struct iperf_test* ipt, int socket_bufsize );
void iperf_set_test_num_streams( struct iperf_test* ipt, int num_streams );
void iperf_set_test_repeating_payload( struct iperf_test* ipt, int repeating_payload );
+void iperf_set_test_timestamps( struct iperf_test* ipt, int timestamps );
+void iperf_set_test_timestamp_format( struct iperf_test*, const char *tf );
void iperf_set_test_role( struct iperf_test* ipt, char role );
-void iperf_set_test_server_hostname( struct iperf_test* ipt, char* server_hostname );
-void iperf_set_test_template( struct iperf_test *ipt, char *tmp_template );
+void iperf_set_test_server_hostname( struct iperf_test* ipt, const char* server_hostname );
+void iperf_set_test_template( struct iperf_test *ipt, const char *tmp_template );
void iperf_set_test_reverse( struct iperf_test* ipt, int reverse );
void iperf_set_test_json_output( struct iperf_test* ipt, int json_output );
int iperf_has_zerocopy( void );
void iperf_set_test_zerocopy( struct iperf_test* ipt, int zerocopy );
void iperf_set_test_get_server_output( struct iperf_test* ipt, int get_server_output );
-void iperf_set_test_bind_address( struct iperf_test* ipt, char *bind_address );
+void iperf_set_test_bind_address( struct iperf_test* ipt, const char *bind_address );
void iperf_set_test_udp_counters_64bit( struct iperf_test* ipt, int udp_counters_64bit );
void iperf_set_test_one_off( struct iperf_test* ipt, int one_off );
void iperf_set_test_tos( struct iperf_test* ipt, int tos );
-void iperf_set_extra_data( struct iperf_test* ipt, char *dat);
+void iperf_set_test_extra_data( struct iperf_test* ipt, const char *dat );
void iperf_set_test_bidirectional( struct iperf_test* ipt, int bidirectional);
void iperf_set_test_no_delay( struct iperf_test* ipt, int no_delay);
#if defined(HAVE_SSL)
-void iperf_set_test_client_username(struct iperf_test *ipt, char *client_username);
-void iperf_set_test_client_password(struct iperf_test *ipt, char *client_password);
-void iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, char *client_rsa_pubkey_base64);
+void iperf_set_test_client_username(struct iperf_test *ipt, const char *client_username);
+void iperf_set_test_client_password(struct iperf_test *ipt, const char *client_password);
+void iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, const char *client_rsa_pubkey_base64);
+void iperf_set_test_server_authorized_users(struct iperf_test *ipt, const char *server_authorized_users);
+void iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, const char *server_rsa_privkey_base64);
#endif // HAVE_SSL
+void iperf_set_test_connect_timeout(struct iperf_test *ipt, int ct);
+
/**
* exchange_parameters - handles the param_Exchange part for client
*
@@ -263,7 +278,7 @@ void iperf_catch_sigend(void (*handler)(int));
void iperf_got_sigend(struct iperf_test *test) __attribute__ ((noreturn));
void usage(void);
void usage_long(FILE * f);
-void warning(char *);
+void warning(const char *);
int iperf_exchange_results(struct iperf_test *);
int iperf_init_test(struct iperf_test *);
int iperf_create_send_timers(struct iperf_test *);
@@ -296,6 +311,7 @@ int iperf_accept(struct iperf_test *);
int iperf_handle_message_server(struct iperf_test *);
int iperf_create_pidfile(struct iperf_test *);
int iperf_delete_pidfile(struct iperf_test *);
+void iperf_check_total_rate(struct iperf_test *, iperf_size_t);
/* JSON output routines. */
int iperf_json_start(struct iperf_test *);
@@ -343,6 +359,8 @@ enum {
IEBADFORMAT = 24, // Bad format argument to -f
IEREVERSEBIDIR = 25, // Iperf cannot be both reverse and bidirectional
IEBADPORT = 26, // Bad port number
+ IETOTALRATE = 27, // Total required bandwidth is larger than server's limit
+ IETOTALINTERVAL = 28, // Invalid time interval for calculating average data rate
/* Test errors */
IENEWTEST = 100, // Unable to create a new test (check perror)
IEINITTEST = 101, // Test initialization failed (check perror)
diff --git a/src/iperf_auth.c b/src/iperf_auth.c
index 9965e19..eb4610f 100644
--- a/src/iperf_auth.c
+++ b/src/iperf_auth.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -43,6 +43,9 @@
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <openssl/buffer.h>
+#include <openssl/err.h>
+
+const char *auth_text_format = "user: %s\npwd: %s\nts: %ld";
void sha256(const char *string, char outputBuffer[65])
{
@@ -151,7 +154,6 @@ int Base64Decode(const char* b64message, unsigned char** buffer, size_t* length)
return (0); //success
}
-
EVP_PKEY *load_pubkey_from_file(const char *file) {
BIO *key = NULL;
EVP_PKEY *pkey = NULL;
@@ -159,7 +161,7 @@ EVP_PKEY *load_pubkey_from_file(const char *file) {
if (file) {
key = BIO_new_file(file, "r");
pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL);
-
+
BIO_free(key);
}
return (pkey);
@@ -172,7 +174,9 @@ EVP_PKEY *load_pubkey_from_base64(const char *buffer) {
BIO* bio = BIO_new(BIO_s_mem());
BIO_write(bio, key, key_len);
+ free(key);
EVP_PKEY *pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
+ BIO_free(bio);
return (pkey);
}
@@ -189,6 +193,18 @@ EVP_PKEY *load_privkey_from_file(const char *file) {
return (pkey);
}
+EVP_PKEY *load_privkey_from_base64(const char *buffer) {
+ unsigned char *key = NULL;
+ size_t key_len;
+ Base64Decode(buffer, &key, &key_len);
+
+ BIO* bio = BIO_new(BIO_s_mem());
+ BIO_write(bio, key, key_len);
+ free(key);
+ EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return (pkey);
+}
int test_load_pubkey_from_file(const char *file){
EVP_PKEY *key = load_pubkey_from_file(file);
@@ -227,6 +243,11 @@ int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned ch
OPENSSL_free(rsa_buffer);
BIO_free(bioBuff);
+ if (encryptedtext_len < 0) {
+ /* We probably shoudln't be printing stuff like this */
+ fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
+ }
+
return encryptedtext_len;
}
@@ -249,24 +270,43 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt
OPENSSL_free(rsa_buffer);
BIO_free(bioBuff);
+ if (plaintext_len < 0) {
+ /* We probably shoudln't be printing stuff like this */
+ fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
+ }
+
return plaintext_len;
}
int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken){
time_t t = time(NULL);
time_t utc_seconds = mktime(localtime(&t));
- char text[150];
- sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds);
+
+ /*
+ * Compute a pessimistic/conservative estimate of storage required.
+ * It's OK to allocate too much storage but too little is bad.
+ */
+ const int text_len = strlen(auth_text_format) + strlen(username) + strlen(password) + 32;
+ char *text = (char *) calloc(text_len, sizeof(char));
+ if (text == NULL) {
+ return -1;
+ }
+ snprintf(text, text_len, auth_text_format, username, password, utc_seconds);
+
unsigned char *encrypted = NULL;
int encrypted_len;
encrypted_len = encrypt_rsa_message(text, public_key, &encrypted);
+ free(text);
+ if (encrypted_len < 0) {
+ return -1;
+ }
Base64Encode(encrypted, encrypted_len, authtoken);
OPENSSL_free(encrypted);
return (0); //success
}
-int decode_auth_setting(int enable_debug, char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){
+int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){
unsigned char *encrypted_b64 = NULL;
size_t encrypted_len_b64;
Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64);
@@ -274,19 +314,36 @@ int decode_auth_setting(int enable_debug, char *authtoken, EVP_PKEY *private_key
unsigned char *plaintext = NULL;
int plaintext_len;
plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext);
- plaintext[plaintext_len] = '\0';
free(encrypted_b64);
+ if (plaintext_len < 0) {
+ return -1;
+ }
+ plaintext[plaintext_len] = '\0';
+
+ char *s_username, *s_password;
+ s_username = (char *) calloc(plaintext_len, sizeof(char));
+ if (s_username == NULL) {
+ return -1;
+ }
+ s_password = (char *) calloc(plaintext_len, sizeof(char));
+ if (s_password == NULL) {
+ free(s_username);
+ return -1;
+ }
+
+ int rc = sscanf((char *) plaintext, auth_text_format, s_username, s_password, ts);
+ if (rc != 3) {
+ free(s_password);
+ free(s_username);
+ return -1;
+ }
- char s_username[20], s_password[20];
- sscanf ((char *)plaintext,"user: %s\npwd: %s\nts: %ld", s_username, s_password, ts);
if (enable_debug) {
printf("Auth Token Content:\n%s\n", plaintext);
printf("Auth Token Credentials:\n--> %s %s\n", s_username, s_password);
}
- *username = (char *) calloc(21, sizeof(char));
- *password = (char *) calloc(21, sizeof(char));
- strncpy(*username, s_username, 20);
- strncpy(*password, s_password, 20);
+ *username = s_username;
+ *password = s_password;
OPENSSL_free(plaintext);
return (0);
}
diff --git a/src/iperf_auth.h b/src/iperf_auth.h
index 0c6fb0f..0dd6c4c 100644
--- a/src/iperf_auth.h
+++ b/src/iperf_auth.h
@@ -34,6 +34,7 @@ int test_load_private_key_from_file(const char *private_keyfile);
EVP_PKEY *load_pubkey_from_file(const char *file);
EVP_PKEY *load_pubkey_from_base64(const char *buffer);
EVP_PKEY *load_privkey_from_file(const char *file);
+EVP_PKEY *load_privkey_from_base64(const char *buffer);
int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken);
int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts);
int check_authentication(const char *username, const char *password, const time_t ts, const char *filename);
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 20ea6fd..d0edf7d 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -478,7 +478,7 @@ iperf_run_client(struct iperf_test * test)
/* Start the client and connect to the server */
if (iperf_connect(test) < 0)
- return -1;
+ goto cleanup_and_fail;
/* Begin calculating CPU utilization */
cpu_util(NULL);
@@ -492,12 +492,12 @@ iperf_run_client(struct iperf_test * test)
result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
if (result < 0 && errno != EINTR) {
i_errno = IESELECT;
- return -1;
+ goto cleanup_and_fail;
}
if (result > 0) {
if (FD_ISSET(test->ctrl_sck, &read_set)) {
if (iperf_handle_message_client(test) < 0) {
- return -1;
+ goto cleanup_and_fail;
}
FD_CLR(test->ctrl_sck, &read_set);
}
@@ -521,17 +521,17 @@ iperf_run_client(struct iperf_test * test)
if (test->mode == BIDIRECTIONAL)
{
if (iperf_send(test, &write_set) < 0)
- return -1;
+ goto cleanup_and_fail;
if (iperf_recv(test, &read_set) < 0)
- return -1;
+ goto cleanup_and_fail;
} else if (test->mode == SENDER) {
// Regular mode. Client sends.
if (iperf_send(test, &write_set) < 0)
- return -1;
+ goto cleanup_and_fail;
} else {
// Reverse mode. Client receives.
if (iperf_recv(test, &read_set) < 0)
- return -1;
+ goto cleanup_and_fail;
}
@@ -557,7 +557,7 @@ iperf_run_client(struct iperf_test * test)
cpu_util(test->cpu_util);
test->stats_callback(test);
if (iperf_set_send_state(test, TEST_END) != 0)
- return -1;
+ goto cleanup_and_fail;
}
}
// If we're in reverse mode, continue draining the data
@@ -567,7 +567,7 @@ iperf_run_client(struct iperf_test * test)
// from the client side.
else if (test->mode == RECEIVER && test->state == TEST_END) {
if (iperf_recv(test, &read_set) < 0)
- return -1;
+ goto cleanup_and_fail;
}
}
@@ -582,4 +582,11 @@ iperf_run_client(struct iperf_test * test)
iflush(test);
return 0;
+
+ cleanup_and_fail:
+ iperf_client_end(test);
+ if (test->json_output)
+ iperf_json_finish(test);
+ iflush(test);
+ return -1;
}
diff --git a/src/iperf_config.h.in b/src/iperf_config.h.in
index e543cbd..1a7cbec 100644
--- a/src/iperf_config.h.in
+++ b/src/iperf_config.h.in
@@ -40,7 +40,7 @@
#undef HAVE_SCHED_SETAFFINITY
/* Have SCTP support. */
-#undef HAVE_SCTP
+#undef HAVE_SCTP_H
/* Define to 1 if you have the `sendfile' function. */
#undef HAVE_SENDFILE
diff --git a/src/iperf_error.c b/src/iperf_error.c
index fd3cccc..cfe4cbd 100644
--- a/src/iperf_error.c
+++ b/src/iperf_error.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2019, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -35,12 +35,25 @@
int gerror;
+char iperf_timestrerr[100];
+
/* Do a printf to stderr. */
void
iperf_err(struct iperf_test *test, const char *format, ...)
{
va_list argp;
char str[1000];
+ time_t now;
+ struct tm *ltm = NULL;
+ char *ct = NULL;
+
+ /* Timestamp if requested */
+ if (test != NULL && test->timestamps) {
+ time(&now);
+ ltm = localtime(&now);
+ strftime(iperf_timestrerr, sizeof(iperf_timestrerr), test->timestamp_format, ltm);
+ ct = iperf_timestrerr;
+ }
va_start(argp, format);
vsnprintf(str, sizeof(str), format, argp);
@@ -48,9 +61,15 @@ iperf_err(struct iperf_test *test, const char *format, ...)
cJSON_AddStringToObject(test->json_top, "error", str);
else
if (test && test->outfile && test->outfile != stdout) {
+ if (ct) {
+ fprintf(test->outfile, "%s", ct);
+ }
fprintf(test->outfile, "iperf3: %s\n", str);
}
else {
+ if (ct) {
+ fprintf(stderr, "%s", ct);
+ }
fprintf(stderr, "iperf3: %s\n", str);
}
va_end(argp);
@@ -62,6 +81,17 @@ iperf_errexit(struct iperf_test *test, const char *format, ...)
{
va_list argp;
char str[1000];
+ time_t now;
+ struct tm *ltm = NULL;
+ char *ct = NULL;
+
+ /* Timestamp if requested */
+ if (test != NULL && test->timestamps) {
+ time(&now);
+ ltm = localtime(&now);
+ strftime(iperf_timestrerr, sizeof(iperf_timestrerr), "%c ", ltm);
+ ct = iperf_timestrerr;
+ }
va_start(argp, format);
vsnprintf(str, sizeof(str), format, argp);
@@ -70,9 +100,15 @@ iperf_errexit(struct iperf_test *test, const char *format, ...)
iperf_json_finish(test);
} else
if (test && test->outfile && test->outfile != stdout) {
+ if (ct) {
+ fprintf(test->outfile, "%s", ct);
+ }
fprintf(test->outfile, "iperf3: %s\n", str);
}
else {
+ if (ct) {
+ fprintf(stderr, "%s", ct);
+ }
fprintf(stderr, "iperf3: %s\n", str);
}
va_end(argp);
@@ -134,10 +170,10 @@ iperf_strerror(int int_errno)
snprintf(errstr, len, "bad TOS value (must be between 0 and 255 inclusive)");
break;
case IESETCLIENTAUTH:
- snprintf(errstr, len, "you must specify username (max 20 chars), password (max 20 chars) and a path to a valid public rsa client to be used");
+ snprintf(errstr, len, "you must specify a username, password, and path to a valid RSA public key");
break;
case IESETSERVERAUTH:
- snprintf(errstr, len, "you must specify path to a valid private rsa server to be used and a user credential file");
+ snprintf(errstr, len, "you must specify a path to a valid RSA private key and a user credential file");
break;
case IEBADFORMAT:
snprintf(errstr, len, "bad format specifier (valid formats are in the set [kmgtKMGT])");
@@ -385,7 +421,13 @@ iperf_strerror(int int_errno)
case IEREVERSEBIDIR:
snprintf(errstr, len, "cannot be both reverse and bidirectional");
break;
-
+ case IETOTALRATE:
+ snprintf(errstr, len, "total required bandwidth is larger than server limit");
+ break;
+ default:
+ snprintf(errstr, len, "int_errno=%d", int_errno);
+ perr = 1;
+ break;
}
/* Append the result of strerror() or gai_strerror() if appropriate */
diff --git a/src/iperf_locale.c b/src/iperf_locale.c
index 0d8a7ec..d5a5354 100644
--- a/src/iperf_locale.c
+++ b/src/iperf_locale.c
@@ -1,5 +1,5 @@
/*---------------------------------------------------------------
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -109,6 +109,9 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" -J, --json output in JSON format\n"
" --logfile f send output to a log file\n"
" --forceflush force flushing output at every interval\n"
+ " --timestamps <format> emit a timestamp at the start of each output line\n"
+ " (using optional format string as per strftime(3))\n"
+
" -d, --debug emit debugging output\n"
" -v, --version show version information and quit\n"
" -h, --help show this message and quit\n"
@@ -117,6 +120,9 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" -D, --daemon run the server as a daemon\n"
" -I, --pidfile file write PID file\n"
" -1, --one-off handle one client connection then exit\n"
+ " --server-bitrate-limit #[KMG][/#] server's total bit rate limit (default 0 = no limit)\n"
+ " (optional slash and number of secs interval for averaging\n"
+ " total data rate. Default is 5 seconds)\n"
#if defined(HAVE_SSL)
" --rsa-private-key-path path to the RSA private key used to decrypt\n"
" authentication credentials\n"
@@ -125,11 +131,11 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
#endif //HAVE_SSL
"Client specific:\n"
" -c, --client <host> run in client mode, connecting to <host>\n"
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
" --sctp use SCTP rather than TCP\n"
" -X, --xbind <name> bind SCTP association to links\n"
" --nstreams # number of SCTP streams\n"
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
" -u, --udp use UDP rather than TCP\n"
" --connect-timeout # timeout for control connection setup (ms)\n"
" -b, --bitrate #[KMG][/#] target bitrate in bits/sec (0 for unlimited)\n"
@@ -272,10 +278,10 @@ const char report_time[] =
const char report_connecting[] =
"Connecting to host %s, port %d\n";
-const char report_authetication_successed[] =
+const char report_authentication_succeeded[] =
"Authentication successed for user '%s' ts %ld\n";
-const char report_authetication_failed[] =
+const char report_authentication_failed[] =
"Authentication failed for user '%s' ts %ld\n";
const char report_reverse[] =
diff --git a/src/iperf_locale.h b/src/iperf_locale.h
index ad784a6..15bdcdb 100644
--- a/src/iperf_locale.h
+++ b/src/iperf_locale.h
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -54,8 +54,8 @@ extern const char report_reverse[] ;
extern const char report_accepted[] ;
extern const char report_cookie[] ;
extern const char report_connected[] ;
-extern const char report_authetication_successed[] ;
-extern const char report_authetication_failed[] ;
+extern const char report_authentication_succeeded[] ;
+extern const char report_authentication_failed[] ;
extern const char report_window[] ;
extern const char report_autotune[] ;
extern const char report_omit_done[] ;
diff --git a/src/iperf_sctp.c b/src/iperf_sctp.c
index 06e1e23..e0c1ec1 100644
--- a/src/iperf_sctp.c
+++ b/src/iperf_sctp.c
@@ -57,7 +57,7 @@
int
iperf_sctp_recv(struct iperf_stream *sp)
{
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
int r;
r = Nread(sp->socket, sp->buffer, sp->settings->blksize, Psctp);
@@ -78,7 +78,7 @@ iperf_sctp_recv(struct iperf_stream *sp)
#else
i_errno = IENOSCTP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
}
@@ -89,7 +89,7 @@ iperf_sctp_recv(struct iperf_stream *sp)
int
iperf_sctp_send(struct iperf_stream *sp)
{
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
int r;
r = Nwrite(sp->socket, sp->buffer, sp->settings->blksize, Psctp);
@@ -103,7 +103,7 @@ iperf_sctp_send(struct iperf_stream *sp)
#else
i_errno = IENOSCTP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
}
@@ -115,7 +115,7 @@ iperf_sctp_send(struct iperf_stream *sp)
int
iperf_sctp_accept(struct iperf_test * test)
{
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
int s;
signed char rbuf = ACCESS_DENIED;
char cookie[COOKIE_SIZE];
@@ -131,12 +131,14 @@ iperf_sctp_accept(struct iperf_test * test)
if (Nread(s, cookie, COOKIE_SIZE, Psctp) < 0) {
i_errno = IERECVCOOKIE;
+ close(s);
return -1;
}
- if (strcmp(test->cookie, cookie) != 0) {
+ if (strncmp(test->cookie, cookie, COOKIE_SIZE) != 0) {
if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Psctp) < 0) {
i_errno = IESENDMESSAGE;
+ close(s);
return -1;
}
close(s);
@@ -146,7 +148,7 @@ iperf_sctp_accept(struct iperf_test * test)
#else
i_errno = IENOSCTP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
}
@@ -157,7 +159,7 @@ iperf_sctp_accept(struct iperf_test * test)
int
iperf_sctp_listen(struct iperf_test *test)
{
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
struct addrinfo hints, *res;
char portstr[6];
int s, opt, saved_errno;
@@ -189,6 +191,26 @@ iperf_sctp_listen(struct iperf_test *test)
return -1;
}
+ if ((opt = test->settings->socket_bufsize)) {
+ int saved_errno;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
+ saved_errno = errno;
+ close(s);
+ freeaddrinfo(res);
+ errno = saved_errno;
+ i_errno = IESETBUF;
+ return -1;
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
+ saved_errno = errno;
+ close(s);
+ freeaddrinfo(res);
+ errno = saved_errno;
+ i_errno = IESETBUF;
+ return -1;
+ }
+ }
+
#if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
if (res->ai_family == AF_INET6 && (test->settings->domain == AF_UNSPEC ||
test->settings->domain == AF_INET6)) {
@@ -220,9 +242,11 @@ iperf_sctp_listen(struct iperf_test *test)
/* servers must call sctp_bindx() _instead_ of bind() */
if (!TAILQ_EMPTY(&test->xbind_addrs)) {
- freeaddrinfo(res);
- if (iperf_sctp_bindx(test, s, IPERF_SCTP_SERVER))
+ if (iperf_sctp_bindx(test, s, IPERF_SCTP_SERVER)) {
+ close(s);
+ freeaddrinfo(res);
return -1;
+ }
} else
if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {
saved_errno = errno;
@@ -246,7 +270,7 @@ iperf_sctp_listen(struct iperf_test *test)
#else
i_errno = IENOSCTP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
}
@@ -257,7 +281,7 @@ iperf_sctp_listen(struct iperf_test *test)
int
iperf_sctp_connect(struct iperf_test *test)
{
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
int s, opt, saved_errno;
char portstr[6];
struct addrinfo hints, *local_res, *server_res;
@@ -292,6 +316,26 @@ iperf_sctp_connect(struct iperf_test *test)
return -1;
}
+ if ((opt = test->settings->socket_bufsize)) {
+ int saved_errno;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
+ saved_errno = errno;
+ close(s);
+ freeaddrinfo(server_res);
+ errno = saved_errno;
+ i_errno = IESETBUF;
+ return -1;
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
+ saved_errno = errno;
+ close(s);
+ freeaddrinfo(server_res);
+ errno = saved_errno;
+ i_errno = IESETBUF;
+ return -1;
+ }
+ }
+
/*
* Various ways to bind the local end of the connection.
* 1. --bind (with or without --cport).
@@ -433,8 +477,11 @@ iperf_sctp_connect(struct iperf_test *test)
/* clients must call bind() followed by sctp_bindx() before connect() */
if (!TAILQ_EMPTY(&test->xbind_addrs)) {
- if (iperf_sctp_bindx(test, s, IPERF_SCTP_CLIENT))
+ if (iperf_sctp_bindx(test, s, IPERF_SCTP_CLIENT)) {
+ freeaddrinfo(server_res);
+ close(s);
return -1;
+ }
}
/* TODO support sctp_connectx() to avoid heartbeating. */
@@ -446,12 +493,12 @@ iperf_sctp_connect(struct iperf_test *test)
i_errno = IESTREAMCONNECT;
return -1;
}
- freeaddrinfo(server_res);
/* Send cookie for verification */
if (Nwrite(s, test->cookie, COOKIE_SIZE, Psctp) < 0) {
saved_errno = errno;
close(s);
+ freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESENDCOOKIE;
return -1;
@@ -475,11 +522,12 @@ iperf_sctp_connect(struct iperf_test *test)
return -1;
}
+ freeaddrinfo(server_res);
return s;
#else
i_errno = IENOSCTP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
}
@@ -487,12 +535,12 @@ iperf_sctp_connect(struct iperf_test *test)
int
iperf_sctp_init(struct iperf_test *test)
{
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
return 0;
#else
i_errno = IENOSCTP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
}
@@ -504,7 +552,7 @@ iperf_sctp_init(struct iperf_test *test)
int
iperf_sctp_bindx(struct iperf_test *test, int s, int is_server)
{
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
struct addrinfo hints;
char portstr[6];
char *servname;
@@ -653,5 +701,5 @@ out:
#else
i_errno = IENOSCTP;
return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
}
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 40d99bc..e2ddf7f 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2018 The Regents of the University of
+ * iperf, Copyright (c) 2014-2020 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.
@@ -354,6 +354,15 @@ create_server_omit_timer(struct iperf_test * test)
static void
cleanup_server(struct iperf_test *test)
{
+ struct iperf_stream *sp;
+
+ /* Close open streams */
+ SLIST_FOREACH(sp, &test->streams, streams) {
+ FD_CLR(sp->socket, &test->read_set);
+ FD_CLR(sp->socket, &test->write_set);
+ close(sp->socket);
+ }
+
/* Close open test sockets */
if (test->ctrl_sck) {
close(test->ctrl_sck);
@@ -437,12 +446,20 @@ iperf_run_server(struct iperf_test *test)
while (test->state != IPERF_DONE) {
+ // Check if average transfer rate was exceeded (condition set in the callback routines)
+ if (test->bitrate_limit_exceeded) {
+ cleanup_server(test);
+ i_errno = IETOTALRATE;
+ return -1;
+ }
+
memcpy(&read_set, &test->read_set, sizeof(fd_set));
memcpy(&write_set, &test->write_set, sizeof(fd_set));
iperf_time_now(&now);
timeout = tmr_timeout(&now);
result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
+
if (result < 0 && errno != EINTR) {
cleanup_server(test);
i_errno = IESELECT;
@@ -596,6 +613,17 @@ iperf_run_server(struct iperf_test *test)
}
}
test->prot_listener = -1;
+
+ /* Ensure that total requested data rate is not above limit */
+ iperf_size_t total_requested_rate = test->num_streams * test->settings->rate * (test->mode == BIDIRECTIONAL? 2 : 1);
+ if (test->settings->bitrate_limit > 0 && total_requested_rate > test->settings->bitrate_limit) {
+ iperf_err(test, "Client total requested throughput rate of %" PRIu64 " bps exceeded %" PRIu64 " bps limit",
+ total_requested_rate, test->settings->bitrate_limit);
+ cleanup_server(test);
+ i_errno = IETOTALRATE;
+ return -1;
+ }
+
if (iperf_set_send_state(test, TEST_START) != 0) {
cleanup_server(test);
return -1;
@@ -647,7 +675,7 @@ iperf_run_server(struct iperf_test *test)
return -1;
}
}
- }
+ }
}
if (result == 0 ||
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index 232aaa1..47252d0 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
diff --git a/src/iperf_udp.c b/src/iperf_udp.c
index 3d37dab..2fd7bf5 100644
--- a/src/iperf_udp.c
+++ b/src/iperf_udp.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -30,6 +30,7 @@
#include <errno.h>
#include <unistd.h>
#include <assert.h>
+#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
@@ -51,7 +52,13 @@
#if defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#else
-# define PRIu64 "llu"
+# ifndef PRIu64
+# if sizeof(long) == 8
+# define PRIu64 "lu"
+# else
+# define PRIu64 "llu"
+# endif
+# endif
#endif
/* iperf_udp_recv
@@ -65,6 +72,7 @@ iperf_udp_recv(struct iperf_stream *sp)
uint64_t pcount;
int r;
int size = sp->settings->blksize;
+ int first_packet = 0;
double transit = 0, d = 0;
struct iperf_time sent_time, arrival_time, temp_time;
@@ -80,9 +88,19 @@ iperf_udp_recv(struct iperf_stream *sp)
/* Only count bytes received while we're in the correct state. */
if (sp->test->state == TEST_RUNNING) {
+
+ /*
+ * For jitter computation below, it's important to know if this
+ * packet is the first packet received.
+ */
+ if (sp->result->bytes_received == 0) {
+ first_packet = 1;
+ }
+
sp->result->bytes_received += r;
sp->result->bytes_received_this_interval += r;
+ /* Dig the various counters out of the incoming UDP packet */
if (sp->test->udp_counters_64bit) {
memcpy(&sec, sp->buffer, sizeof(sec));
memcpy(&usec, sp->buffer+4, sizeof(usec));
@@ -149,7 +167,7 @@ iperf_udp_recv(struct iperf_stream *sp)
/* Log the out-of-order packet */
if (sp->test->debug)
- fprintf(stderr, "OUT OF ORDER - incoming packet sequence %" PRIu64 " but expected sequence %d on stream %d", pcount, sp->packet_count, sp->socket);
+ fprintf(stderr, "OUT OF ORDER - incoming packet sequence %" PRIu64 " but expected sequence %d on stream %d", pcount, sp->packet_count + 1, sp->socket);
}
/*
@@ -167,6 +185,11 @@ iperf_udp_recv(struct iperf_stream *sp)
iperf_time_diff(&arrival_time, &sent_time, &temp_time);
transit = iperf_time_in_secs(&temp_time);
+
+ /* Hack to handle the first packet by initializing prev_transit. */
+ if (first_packet)
+ sp->prev_transit = transit;
+
d = transit - sp->prev_transit;
if (d < 0)
d = -d;
diff --git a/src/iperf_util.c b/src/iperf_util.c
index 412397a..9ca1eec 100644
--- a/src/iperf_util.c
+++ b/src/iperf_util.c
@@ -111,7 +111,7 @@ void fill_with_repeating_pattern(void *out, size_t outsize)
*/
void
-make_cookie(char *cookie)
+make_cookie(const char *cookie)
{
unsigned char *out = (unsigned char*)cookie;
size_t pos;
@@ -267,7 +267,7 @@ get_optional_features(void)
numfeatures++;
#endif /* HAVE_FLOWLABEL */
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
if (numfeatures > 0) {
strncat(features, ", ",
sizeof(features) - strlen(features) - 1);
@@ -275,7 +275,7 @@ get_optional_features(void)
strncat(features, "SCTP",
sizeof(features) - strlen(features) - 1);
numfeatures++;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
#if defined(HAVE_TCP_CONGESTION)
if (numfeatures > 0) {
@@ -402,7 +402,7 @@ iperf_json_printf(const char *format, ...)
/* Debugging routine to dump out an fd_set. */
void
-iperf_dump_fdset(FILE *fp, char *str, int nfds, fd_set *fds)
+iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds)
{
int fd;
int comma;
diff --git a/src/iperf_util.h b/src/iperf_util.h
index 76bfd20..b109af2 100644
--- a/src/iperf_util.h
+++ b/src/iperf_util.h
@@ -54,7 +54,7 @@ const char* get_optional_features(void);
cJSON* iperf_json_printf(const char *format, ...);
-void iperf_dump_fdset(FILE *fp, char *str, int nfds, fd_set *fds);
+void iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds);
#ifndef HAVE_DAEMON
extern int daemon(int nochdir, int noclose);
diff --git a/src/main.c b/src/main.c
index fe10a2f..c82ee43 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_util.h"
#include "iperf_locale.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..8fde9c3 100644
--- a/src/net.c
+++ b/src/net.c
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
+#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
@@ -120,7 +121,7 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen,
/* make connection to server */
int
-netdial(int domain, int proto, char *local, int local_port, char *server, int port, int timeout)
+netdial(int domain, int proto, const char *local, int local_port, const char *server, int port, int timeout)
{
struct addrinfo hints, *local_res, *server_res;
int s, saved_errno;
@@ -217,7 +218,7 @@ netdial(int domain, int proto, char *local, int local_port, char *server, int po
/***************************************************************/
int
-netannounce(int domain, int proto, char *local, int port)
+netannounce(int domain, int proto, const char *local, int port)
{
struct addrinfo hints, *res;
char portstr[6];
diff --git a/src/net.h b/src/net.h
index 3738d6a..80a2161 100644
--- a/src/net.h
+++ b/src/net.h
@@ -28,8 +28,8 @@
#define __NET_H
int timeout_connect(int s, const struct sockaddr *name, socklen_t namelen, int timeout);
-int netdial(int domain, int proto, char *local, int local_port, char *server, int port, int timeout);
-int netannounce(int domain, int proto, char *local, int port);
+int netdial(int domain, int proto, const char *local, int local_port, const char *server, int port, int timeout);
+int netannounce(int domain, int proto, const char *local, int port);
int Nread(int fd, char *buf, size_t count, int prot);
int Nwrite(int fd, const char *buf, size_t count, int prot) /* __attribute__((hot)) */;
int has_sendfile(void);
diff --git a/src/private.pem b/src/private.pem
new file mode 100644
index 0000000..8b1c5b6
--- /dev/null
+++ b/src/private.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAwVbvPf/eDIZKmEVth9+VPgSx1RkXOAPCJ5tl51bcYoy9P10N
+noutsTK/64VclIuyUDUdAw81Vu5tYRcBeB8Jllp02xL8kPo0IROsT3wmMYbPziUG
+/I2988sAP9mL8QbtKydnADHMikfadfyPkfxW2naFtquWT/vKKVkhC2LHJyTpmAVj
+pp6R9LDDu/YY0/kb5DvYPpe62xgNWjNVIhABu3R+StAAL25SaLXuaGSVpDe6Sphn
+TqVf+LmKCkZmSMSfQoozXomNyFpLU8ODoV3QyHYi6QSWWFtU6gu0uso/9pfRFjbN
+GV9lxokKNz/cZGyu0SFddMiTGrt24NROi0RHwwIDAQABAoIBACVG+cHef5WyntdV
+K5UzCrd2eEM6HzvxnZG9aJx+JufpcuOwsVuMWuT7f/2NLRiHBs5oLzvTxtkIB5bc
+tK/QbCzNLBLBSmk5lKt7+5EnwsVx1MdOZFZ1jdZfoaCt9Ul3qGrVogprj6Bp0jlF
+hPkEyko85/McilLJnWTzhmeHmBZ3tOJ9LWHgVdXGXZx/pBuxZ+UB/xgZdvdZK86F
+xndWqD8lvfpoSsVwzCORdXvQWs78CtT2KXYvt8S6mrLMoIoHLO/1rwwKKoZfFuja
+NouN36PGaSo4/9O1d11/s9zwdJH3ShozY0Fao8I3XhdH0uvTirmAEPh7U1Lo71pP
+ksUvbUECgYEA/7p1Bg/XsSK72KgJ695B2hi8g9+wv0eKCpGwkKJQZKE338it8zIn
++JMaeDjObLhb4B2QP/3iL0mdU2mJzm0X8hYCKqBdyICb9wixznLLAej+uw2j60Ef
+tlGenCqAkVL3pRS5txztNhFsXx3JwxCSj4zwmVm5oyxkpAeuwvZ1cPkCgYEAwYuC
+6nPlRf6GEf/MuHCziaCCPrDm1u472uspxHn41crw6BaMl5xcmr0Z8O7heOtlVmMl
+Mn3gfIbd/NGyjs8ejmWcO5mZHtESGM/zAaVyu7bn3ij37OEndbEpZsCpRtxvtaji
+MTMwhdV2xteJ0+KCtg66ziSyJv3krQTEW8DZKZsCgYB8BcnLbtOErPu9T4HASsJV
+K7oBmvL1UZS5G38uJgonQ6j9dy4lzCVmgLFNrP8v6xljz/Ktlkuj82fBlGWpH2+F
+kPbsBWp2WylI3YaeQT4DZyRjQ3JEHglrOppZ0qMX180S2sJW9Eh2+Gw+lQvM9rSd
+uhTVypYldNo6Ux+GnlDGwQKBgQC/6W4uvCyjcvXN8y8z08yysw1yzEaY6DFBqd0I
+jUlH9Ktb9sABtXG9nbSTSssX85HQTw8bOeXWlISZo/TB1m4eFHMORgemnviq0cfL
+4hoaOAtCJq1vnPJbqQe8c11mfj3mi0d+MZvzmO7ly+NGzlt92q0wqwJb13VgelGa
+CWdL8QKBgQD1ABK8WJuMowihrQsLaUxNO/1hsN8CP/rjoi9D5NdSFt5zzcC3D/RA
+m42ScOaAFIh44Js5aAROvbDqIlelhwRlmutP/lYyQRZDZm7X6u/bKuqK4H/sM6ZB
+SICe2eWFvbKexI7QnreRltOWIFrNoZy9FdELM8DS+kePAlVt7c83Uw==
+-----END RSA PRIVATE KEY-----
diff --git a/src/public.pem b/src/public.pem
new file mode 100644
index 0000000..71f4f13
--- /dev/null
+++ b/src/public.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwVbvPf/eDIZKmEVth9+V
+PgSx1RkXOAPCJ5tl51bcYoy9P10NnoutsTK/64VclIuyUDUdAw81Vu5tYRcBeB8J
+llp02xL8kPo0IROsT3wmMYbPziUG/I2988sAP9mL8QbtKydnADHMikfadfyPkfxW
+2naFtquWT/vKKVkhC2LHJyTpmAVjpp6R9LDDu/YY0/kb5DvYPpe62xgNWjNVIhAB
+u3R+StAAL25SaLXuaGSVpDe6SphnTqVf+LmKCkZmSMSfQoozXomNyFpLU8ODoV3Q
+yHYi6QSWWFtU6gu0uso/9pfRFjbNGV9lxokKNz/cZGyu0SFddMiTGrt24NROi0RH
+wwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/src/t_api.c b/src/t_api.c
index 0669917..f5e0984 100644
--- a/src/t_api.c
+++ b/src/t_api.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2017, The Regents of the University of
+ * iperf, Copyright (c) 2017-2020, 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.
@@ -45,9 +45,21 @@ int
main(int argc, char **argv)
{
const char *ver;
+ struct iperf_test *test;
+ int sint, gint;
ver = iperf_get_iperf_version();
assert(strcmp(ver, IPERF_VERSION) == 0);
+ test = iperf_new_test();
+ assert(test != NULL);
+
+ iperf_defaults(test);
+
+ sint = 10;
+ iperf_set_test_connect_timeout(test, sint);
+ gint = iperf_get_test_connect_timeout(test);
+ assert(sint == gint);
+
return 0;
}
diff --git a/src/t_auth.c b/src/t_auth.c
new file mode 100644
index 0000000..ff9cffe
--- /dev/null
+++ b/src/t_auth.c
@@ -0,0 +1,125 @@
+/*
+ * iperf, Copyright (c) 2020, 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.
+ */
+#include "iperf_config.h"
+
+#include <assert.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include "iperf.h"
+#include "iperf_api.h"
+#if defined(HAVE_SSL)
+#include "iperf_auth.h"
+#endif /* HAVE_SSL */
+
+#include "version.h"
+
+#include "units.h"
+
+#if defined(HAVE_SSL)
+int test_authtoken(const char *authUser, const char *authPassword, EVP_PKEY *pubkey, EVP_PKEY *privkey);
+
+int
+main(int argc, char **argv)
+{
+ /* sha256 */
+ void sha256(const char *string, char outputBuffer[65]);
+ const char sha256String[] = "This is a SHA256 test.";
+ const char sha256Digest[] = "4816482f8b4149f687a1a33d61a0de6b611364ec0fb7adffa59ff2af672f7232"; /* echo -n "This is a SHA256 test." | shasum -a256 */
+ char sha256Output[65];
+
+ sha256(sha256String, sha256Output);
+ assert(strcmp(sha256Output, sha256Digest) == 0);
+
+ /* Base64{Encode,Decode} */
+ int Base64Encode(const unsigned char* buffer, const size_t length, char** b64text);
+ int Base64Decode(const char* b64message, unsigned char** buffer, size_t* length);
+ const char base64String[] = "This is a Base64 test.";
+ char *base64Text;
+ char *base64Decode;
+ size_t base64DecodeLength;
+ const char base64EncodeCheck[] = "VGhpcyBpcyBhIEJhc2U2NCB0ZXN0Lg=="; /* echo -n "This is a Base64 test." | b64encode -r - */
+
+ assert(Base64Encode((unsigned char *) base64String, strlen(base64String), &base64Text) == 0);
+ assert(strcmp(base64Text, base64EncodeCheck) == 0);
+ assert(Base64Decode(base64Text, (unsigned char **) &base64Decode, &base64DecodeLength) == 0);
+ assert(strcmp(base64String, base64Decode) == 0);
+
+ /* public/private key tests */
+ const char *pubkeyfile = "public.pem";
+ const char *privkeyfile = "private.pem";
+
+ /* built-in tests */
+ assert(test_load_pubkey_from_file(pubkeyfile) == 0);
+ assert(test_load_private_key_from_file(privkeyfile) == 0);
+
+ /* load public key pair for use in further tests */
+ EVP_PKEY *pubkey, *privkey;
+ pubkey = load_pubkey_from_file(pubkeyfile);
+ assert(pubkey);
+ privkey = load_privkey_from_file(privkeyfile);
+ assert(privkey);
+
+ /* authentication token tests */
+ assert(test_authtoken("kilroy", "fubar", pubkey, privkey) == 0);
+
+ /* This should fail because the data is way too long for the RSA key */
+ /* assert(test_authtoken("kilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroykilroy", "fubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubarfubar", pubkey, privkey) < 0); */
+
+ return 0;
+}
+
+int
+test_authtoken(const char *authUser, const char *authPassword, EVP_PKEY *pubkey, EVP_PKEY *privkey) {
+ char *authToken;
+ char *decodeUser;
+ char *decodePassword;
+ time_t decodeTime;
+
+ assert(encode_auth_setting(authUser, authPassword, pubkey, &authToken) == 0);
+ assert(decode_auth_setting(0, authToken, privkey, &decodeUser, &decodePassword, &decodeTime) == 0);
+
+ assert(strcmp(decodeUser, authUser) == 0);
+ assert(strcmp(decodePassword, authPassword) == 0);
+
+ time_t now = time(NULL);
+
+ assert(now - decodeTime >= 0); /* time has to go forwards */
+ assert(now - decodeTime <= 1); /* shouldn't take more than a second to run */
+
+ return 0;
+}
+#else
+int
+main(int argc, char **argv)
+{
+ return 0;
+}
+#endif /* HAVE_SSL */
diff --git a/src/tcp_info.c b/src/tcp_info.c
index bfbb9ea..d63e5b4 100644
--- a/src/tcp_info.c
+++ b/src/tcp_info.c
@@ -197,13 +197,13 @@ get_pmtu(struct iperf_interval_results *irp)
void
build_tcpinfo_message(struct iperf_interval_results *r, char *message)
{
-#if defined(linux)
+#if defined(linux) && defined(TCP_INFO)
sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, r->tcpInfo.tcpi_snd_ssthresh,
r->tcpInfo.tcpi_rcv_ssthresh, r->tcpInfo.tcpi_unacked, r->tcpInfo.tcpi_sacked,
r->tcpInfo.tcpi_lost, r->tcpInfo.tcpi_retrans, r->tcpInfo.tcpi_fackets,
r->tcpInfo.tcpi_rtt, r->tcpInfo.tcpi_reordering);
#endif
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) && defined(TCP_INFO)
sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd,
r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt);
#endif
diff --git a/src/timer.h b/src/timer.h
index 301cdf3..58c3db8 100644
--- a/src/timer.h
+++ b/src/timer.h
@@ -31,6 +31,8 @@
#define __TIMER_H
#include <time.h>
+#include <sys/time.h>
+
#include "iperf_time.h"
/* TimerClientData is an opaque value that tags along with a timer. The
diff --git a/test_commands.sh b/test_commands.sh
index 2ed0f82..146d1da 100755
--- a/test_commands.sh
+++ b/test_commands.sh
@@ -29,12 +29,20 @@ host=$1
# force V6
./src/iperf3 -c $host -6 -t 5
./src/iperf3 -c $host -6 -u -t 5
+# FQ rate
+./src/iperf3 -c $host -V -t 5 --fq-rate 5m
+./src/iperf3 -c $host -u -V -t 5 --fq-rate 5m
+# SCTP
+./src/iperf3 -c $host --sctp -V -t 5
# parallel streams
./src/iperf3 -c $host -P 3 -t 5
./src/iperf3 -c $host -u -P 3 -t 5
# reverse mode
./src/iperf3 -c $host -P 2 -t 5 -R
./src/iperf3 -c $host -u -P 2 -t 5 -R
+# bidirectional mode
+./src/iperf3 -c $host -P 2 -t 5 --bidir
+./src/iperf3 -c $host -u -P 2 -t 5 --bidir
# zero copy
./src/iperf3 -c $host -Z -t 5
./src/iperf3 -c $host -Z -t 5 -R