summaryrefslogtreecommitdiffstats
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/Makefile.am22
-rw-r--r--compat/Makefile.in617
-rw-r--r--compat/Thread.c582
-rw-r--r--compat/delay.c407
-rw-r--r--compat/error.c210
-rw-r--r--compat/gettcpinfo.c110
-rw-r--r--compat/gettimeofday.c92
-rw-r--r--compat/inet_ntop.c210
-rw-r--r--compat/inet_pton.c209
-rw-r--r--compat/signal.c204
-rw-r--r--compat/snprintf.c101
-rw-r--r--compat/string.c76
12 files changed, 2840 insertions, 0 deletions
diff --git a/compat/Makefile.am b/compat/Makefile.am
new file mode 100644
index 0000000..75ac787
--- /dev/null
+++ b/compat/Makefile.am
@@ -0,0 +1,22 @@
+noinst_LIBRARIES = libcompat.a
+
+AM_CPPFLAGS = @STRIP_BEGIN@ \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ @STRIP_END@
+
+AM_CXXFLAGS = -Wall
+AM_CFLAGS = -Wall
+AM_LDFLAGS = -lrt
+
+libcompat_a_SOURCES = \
+ Thread.c \
+ error.c \
+ delay.c \
+ gettimeofday.c \
+ gettcpinfo.c \
+ inet_ntop.c \
+ inet_pton.c \
+ signal.c \
+ snprintf.c \
+ string.c
diff --git a/compat/Makefile.in b/compat/Makefile.in
new file mode 100644
index 0000000..5d5bbcd
--- /dev/null
+++ b/compat/Makefile.in
@@ -0,0 +1,617 @@
+# Makefile.in generated by automake 1.16.2 from Makefile.am.
+# @configure_input@
+
+# 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,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = compat
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/m4/dast.m4 $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libcompat_a_AR = $(AR) $(ARFLAGS)
+libcompat_a_LIBADD =
+am_libcompat_a_OBJECTS = Thread.$(OBJEXT) error.$(OBJEXT) \
+ delay.$(OBJEXT) gettimeofday.$(OBJEXT) gettcpinfo.$(OBJEXT) \
+ inet_ntop.$(OBJEXT) inet_pton.$(OBJEXT) signal.$(OBJEXT) \
+ snprintf.$(OBJEXT) string.$(OBJEXT)
+libcompat_a_OBJECTS = $(am_libcompat_a_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/Thread.Po ./$(DEPDIR)/delay.Po \
+ ./$(DEPDIR)/error.Po ./$(DEPDIR)/gettcpinfo.Po \
+ ./$(DEPDIR)/gettimeofday.Po ./$(DEPDIR)/inet_ntop.Po \
+ ./$(DEPDIR)/inet_pton.Po ./$(DEPDIR)/signal.Po \
+ ./$(DEPDIR)/snprintf.Po ./$(DEPDIR)/string.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libcompat_a_SOURCES)
+DIST_SOURCES = $(libcompat_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+STRIP_BEGIN = @STRIP_BEGIN@
+STRIP_DUMMY = @STRIP_DUMMY@
+STRIP_END = @STRIP_END@
+VERSION = @VERSION@
+WEB100_CFLAGS = @WEB100_CFLAGS@
+WEB100_CONFIG = @WEB100_CONFIG@
+WEB100_LIBS = @WEB100_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libcompat.a
+AM_CPPFLAGS = @STRIP_BEGIN@ \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ @STRIP_END@
+
+AM_CXXFLAGS = -Wall
+AM_CFLAGS = -Wall
+AM_LDFLAGS = -lrt
+libcompat_a_SOURCES = \
+ Thread.c \
+ error.c \
+ delay.c \
+ gettimeofday.c \
+ gettcpinfo.c \
+ inet_ntop.c \
+ inet_pton.c \
+ signal.c \
+ snprintf.c \
+ string.c
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu compat/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu compat/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libcompat.a: $(libcompat_a_OBJECTS) $(libcompat_a_DEPENDENCIES) $(EXTRA_libcompat_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libcompat.a
+ $(AM_V_AR)$(libcompat_a_AR) libcompat.a $(libcompat_a_OBJECTS) $(libcompat_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libcompat.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delay.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettcpinfo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_pton.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/Thread.Po
+ -rm -f ./$(DEPDIR)/delay.Po
+ -rm -f ./$(DEPDIR)/error.Po
+ -rm -f ./$(DEPDIR)/gettcpinfo.Po
+ -rm -f ./$(DEPDIR)/gettimeofday.Po
+ -rm -f ./$(DEPDIR)/inet_ntop.Po
+ -rm -f ./$(DEPDIR)/inet_pton.Po
+ -rm -f ./$(DEPDIR)/signal.Po
+ -rm -f ./$(DEPDIR)/snprintf.Po
+ -rm -f ./$(DEPDIR)/string.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/Thread.Po
+ -rm -f ./$(DEPDIR)/delay.Po
+ -rm -f ./$(DEPDIR)/error.Po
+ -rm -f ./$(DEPDIR)/gettcpinfo.Po
+ -rm -f ./$(DEPDIR)/gettimeofday.Po
+ -rm -f ./$(DEPDIR)/inet_ntop.Po
+ -rm -f ./$(DEPDIR)/inet_pton.Po
+ -rm -f ./$(DEPDIR)/signal.Po
+ -rm -f ./$(DEPDIR)/snprintf.Po
+ -rm -f ./$(DEPDIR)/string.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-noinstLIBRARIES cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-tags distdir 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 \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/compat/Thread.c b/compat/Thread.c
new file mode 100644
index 0000000..307535e
--- /dev/null
+++ b/compat/Thread.c
@@ -0,0 +1,582 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ *
+ * Thread.c
+ * by Kevin Gibbs <kgibbs@nlanr.net>
+ *
+ * Based on:
+ * Thread.cpp
+ * by Mark Gates <mgates@nlanr.net>
+ * -------------------------------------------------------------------
+ * The thread subsystem is responsible for all thread functions. It
+ * provides a thread implementation agnostic interface to Iperf. If
+ * threads are not available (HAVE_THREAD is undefined), thread_start
+ * does not start a new thread but just launches the specified object
+ * in the current thread. Everything that defines a thread of
+ * execution in Iperf is contained in an thread_Settings structure. To
+ * start a thread simply pass one such structure into thread_start.
+ * -------------------------------------------------------------------
+ * headers
+ * uses
+ * <stdlib.h>
+ * <stdio.h>
+ * <assert.h>
+ * <errno.h>
+ * Thread.h may include <pthread.h>
+ * ------------------------------------------------------------------- */
+
+#include "headers.h"
+
+#include "Thread.h"
+#include "Locale.h"
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if HAVE_THREAD_DEBUG
+#include <time.h>
+#include <unistd.h>
+#if HAVE_GETTID_SYSCALL
+#include <sys/syscall.h>
+#endif
+#include <sys/types.h>
+#include <stdarg.h>
+#include "Reporter.h"
+void reporttype_text(struct ReportHeader *reporthdr, char *rs) {
+ switch (reporthdr->type) {
+ case DATA_REPORT:
+ strncpy(rs,"data", REPORTTXTMAX);
+ break;
+ case SUM_REPORT:
+ strncpy(rs,"sum", REPORTTXTMAX);
+ break;
+ case SETTINGS_REPORT:
+ strncpy(rs,"settings", REPORTTXTMAX);
+ break;
+ case CONNECTION_REPORT:
+ strncpy(rs,"connection", REPORTTXTMAX);
+ break;
+ case SERVER_RELAY_REPORT:
+ strncpy(rs,"server", REPORTTXTMAX);
+ break;
+ default :
+ strncpy(rs,"unknown", REPORTTXTMAX);
+ }
+ rs[REPORTTXTMAX-1] = '\0';
+}
+
+Mutex thread_debug_mutex;
+static void __gettimestamp(char *timestr) {
+ struct timespec t1;
+ clock_gettime(CLOCK_REALTIME, &t1);
+ struct tm *t;
+ t=localtime(&t1.tv_sec);
+ if (t) {
+#if WIN32
+ strftime(timestr, 200, "%Y-%m-%d %H:%M:%S", t);
+#else
+ strftime(timestr, 200, "%T", t);
+#endif
+ // strftime(buf, len, "%F %T", &t);
+ snprintf(&timestr[strlen(timestr)], strlen(timestr), ".%09ld", t1.tv_nsec);
+ timestr[199]='\0';
+ } else {
+ *timestr='\0';
+ }
+}
+static int __log(const char *level, const char *format, va_list args) {
+ int len;
+ char *newformat;
+ char timestamp[200];
+ char logformat[]="%s(%ld):[%s] %s\n";
+
+ __gettimestamp(timestamp);
+ #if HAVE_GETTID_SYSCALL
+ unsigned long tid = syscall(SYS_gettid);
+ #else
+ unsigned long tid = -1;
+ #endif
+ len = snprintf(NULL, 0, logformat, level, tid, timestamp, format);
+ len++; // Trailing null byte + extra
+ newformat = malloc(len);
+ len = snprintf(newformat, len, logformat, level, tid, timestamp, format);
+ if (len > 0) {
+ len = vprintf(newformat, args);
+ }
+ free(newformat);
+ return len;
+}
+
+void thread_debug(const char *format, ...) {
+ Mutex_Lock(&thread_debug_mutex);
+ va_list ap;
+ va_start(ap, format);
+ __log("THREAD", format, ap);
+ va_end(ap);
+ fflush(stdout);
+ Mutex_Unlock(&thread_debug_mutex);
+}
+#endif
+
+/* -------------------------------------------------------------------
+ * define static variables.
+ * ------------------------------------------------------------------- */
+
+// number of currently running threads
+int thread_sNum = 0;
+// number of currently running traffic threads
+int thread_trfc_sNum = 0;
+int thread_trfctx_sNum = 0;
+int thread_trfcrx_sNum = 0;
+// number of non-terminating running threads (ie listener thread)
+int nonterminating_num = 0;
+// condition to protect updating the above and alerting on
+// changes to above
+struct Condition thread_sNum_cond;
+
+
+/* -------------------------------------------------------------------
+ * Initialize the thread subsystems variables and set the concurrency
+ * level in solaris.
+ * ------------------------------------------------------------------- */
+void thread_init() {
+ Condition_Initialize(&thread_sNum_cond);
+#if defined(sun)
+ /* Solaris apparently doesn't default to timeslicing threads,
+ * as such we force it to play nice. This may not work perfectly
+ * when _sending_ multiple _UDP_ streams.
+ */
+ pthread_setconcurrency (3);
+#endif
+}
+
+/* -------------------------------------------------------------------
+ * Destroy the thread subsystems variables.
+ * ------------------------------------------------------------------- */
+void thread_destroy() {
+ Condition_Destroy(&thread_sNum_cond);
+}
+
+/* -------------------------------------------------------------------
+ * Start the specified object's thread execution. Increments thread
+ * count, spawns new thread, and stores thread ID.
+ * ------------------------------------------------------------------- */
+void thread_start_all(struct thread_Settings* thread) {
+ struct thread_Settings *ithread = thread;
+ while(ithread) {
+ thread_start(ithread);
+ ithread = ithread->runNow;
+ }
+}
+
+void thread_start(struct thread_Settings* thread) {
+ // Make sure this object has not been started already
+ if (!thread_equalid(thread->mTID, thread_zeroid())) {
+ WARN(1, "thread_start called on running thread");
+#if HAVE_THREAD_DEBUG
+ thread_debug("Thread_start info %p id=%d ", (void *)thread, (int)thread->mTID);
+#endif
+ } else {
+ // increment thread count
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum++;
+ if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) {
+ thread_trfc_sNum++;
+ }
+ Condition_Unlock(thread_sNum_cond);
+
+#if defined(HAVE_POSIX_THREAD)
+ // pthreads -- spawn new thread
+ if (pthread_create(&thread->mTID, NULL, thread_run_wrapper, thread) != 0) {
+ WARN(1, "pthread_create");
+
+ // decrement thread count
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum--;
+ if (thread->mThreadMode == kMode_Client) {
+ thread_trfc_sNum--;
+ thread_trfctx_sNum--;
+ }
+ if (thread->mThreadMode == kMode_Server) {
+ thread_trfc_sNum--;
+ thread_trfcrx_sNum--;
+ }
+ Condition_Unlock(thread_sNum_cond);
+ }
+#if HAVE_THREAD_DEBUG
+ thread_debug("Thread_run_wrapper(%p mode=%x) thread counts tot/trfc=%d/%d (id=%d)", (void *)thread, thread->mThreadMode, thread_sNum, thread_trfc_sNum, (int)thread->mTID);
+#endif
+#elif defined(HAVE_WIN32_THREAD)
+ // Win32 threads -- spawn new thread
+ // Win32 has a thread handle in addition to the thread ID
+ thread->mHandle = CreateThread(NULL, 0, thread_run_wrapper, thread, 0, &thread->mTID);
+ if (thread->mHandle == NULL) {
+ WARN(1, "CreateThread");
+
+ // decrement thread count
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum--;
+ if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) {
+ thread_trfc_sNum--;
+ }
+ Condition_Unlock(thread_sNum_cond);
+ }
+#else
+ // single-threaded -- call Run_Wrapper in this thread
+ thread_run_wrapper(thread);
+#endif
+ }
+} // end thread_start
+
+/* -------------------------------------------------------------------
+ * Stop the specified object's thread execution (if any) immediately.
+ * Decrements thread count and resets the thread ID.
+ *
+ * Note: This does not free any objects and calling it without
+ * lots of conideration will likely cause memory leaks. Better to let
+ * thread_start's thread_run_wrapper run to completion and not
+ * preemptively stop a thread.
+ * ------------------------------------------------------------------- */
+void thread_stop(struct thread_Settings* thread) {
+#ifdef HAVE_THREAD
+ #ifdef HAVE_THREAD_DEBUG
+ thread_debug("Thread stop invoked %p (%d/%d)", (void *)thread, thread_sNum, thread_trfc_sNum);
+ #endif
+ // Make sure we have been started
+ if (!thread_equalid(thread->mTID, thread_zeroid())) {
+
+ // decrement thread count
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum--;
+ if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) {
+ thread_trfc_sNum--;
+ }
+ Condition_Signal(&thread_sNum_cond);
+ Condition_Unlock(thread_sNum_cond);
+
+ // use exit() if called from within this thread
+ // use cancel() if called from a different thread
+ if (thread_equalid(thread_getid(), thread->mTID)) {
+
+ // Destroy the object
+ Settings_Destroy(thread);
+
+ // Exit
+#if defined(HAVE_POSIX_THREAD)
+ pthread_exit(NULL);
+#else // Win32
+ CloseHandle(thread->mHandle);
+ ExitThread(0);
+#endif
+ } else {
+
+ // Cancel
+#if defined(HAVE_POSIX_THREAD)
+ // Cray J90 doesn't have pthread_cancel; Iperf works okay without
+#ifdef HAVE_PTHREAD_CANCEL
+ pthread_cancel(thread->mTID);
+#endif
+#else // Win32
+ // this is a somewhat dangerous function; it's not
+ // suggested to Stop() threads a lot.
+ TerminateThread(thread->mHandle, 0);
+#endif
+
+ // Destroy the object only after killing the thread
+ Settings_Destroy(thread);
+ }
+ }
+#endif
+} // end Stop
+
+/* -------------------------------------------------------------------
+ * This function is the entry point for new threads created in
+ * thread_start.
+ * ------------------------------------------------------------------- */
+#if defined(HAVE_WIN32_THREAD)
+DWORD WINAPI
+#else
+void*
+#endif
+thread_run_wrapper(void* paramPtr) {
+ bool signal_on_exit = false;
+ struct thread_Settings* thread = (struct thread_Settings*) paramPtr;
+
+ // which type of object are we
+ switch (thread->mThreadMode) {
+ case kMode_Server:
+ {
+ signal_on_exit = true;
+ /* Spawn a Server thread with these settings */
+ server_spawn(thread);
+ } break;
+ case kMode_Client:
+ {
+ signal_on_exit = true;
+ /* Spawn a Client thread with these settings */
+ client_spawn(thread);
+ } break;
+ case kMode_Reporter:
+ case kMode_ReporterClient:
+ {
+ /* Spawn a Reporter thread with these settings */
+ reporter_spawn(thread);
+ } break;
+ case kMode_Listener:
+ {
+ // Increment the non-terminating thread count
+ thread_register_nonterm();
+ /* Spawn a Listener thread with these settings */
+ listener_spawn(thread);
+ // Decrement the non-terminating thread count
+ thread_unregister_nonterm();
+ } break;
+ default:
+ {
+ FAIL(1, "Unknown Thread Type!\n", thread);
+ } break;
+ }
+
+#ifdef HAVE_POSIX_THREAD
+ // detach Thread. If someone already joined it will not do anything
+ // If none has then it will free resources upon return from this
+ // function (Run_Wrapper)
+ pthread_detach(thread->mTID);
+#endif
+
+ // decrement thread count and send condition signal
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum--;
+ if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) {
+ thread_trfc_sNum--;
+ }
+ Condition_Signal(&thread_sNum_cond);
+ Condition_Unlock(thread_sNum_cond);
+
+ // Check if we need to start up a thread after executing this one
+ if (thread->runNext != NULL) {
+ thread_start(thread->runNext);
+ }
+ // Destroy this thread object
+ Settings_Destroy(thread);
+ // signal the reporter thread now that thread state has changed
+ if (signal_on_exit) {
+ Condition_Signal(&ReportCond);
+#if HAVE_THREAD_DEBUG
+ thread_debug("Signal sent to reporter thread");
+#endif
+ }
+ return 0;
+} // end run_wrapper
+
+/* -------------------------------------------------------------------
+ * Wait for all thread object's execution to complete. Depends on the
+ * thread count being accurate and the threads sending a condition
+ * signal when they terminate.
+ * ------------------------------------------------------------------- */
+void thread_joinall(void) {
+ Condition_Lock(thread_sNum_cond);
+ while (thread_sNum > 0) {
+ Condition_Wait(&thread_sNum_cond);
+ }
+ Condition_Unlock(thread_sNum_cond);
+} // end Joinall
+
+
+/* -------------------------------------------------------------------
+ * Compare the thread ID's (inLeft == inRight); return true if they
+ * are equal. On some OS's nthread_t is a struct so == will not work.
+ * TODO use pthread_equal. Any Win32 equivalent??
+ * ------------------------------------------------------------------- */
+int thread_equalid(nthread_t inLeft, nthread_t inRight) {
+ return(memcmp(&inLeft, &inRight, sizeof(inLeft)) == 0);
+}
+
+/* -------------------------------------------------------------------
+ * Return a zero'd out thread ID. On some OS's nthread_t is a struct
+ * so == 0 will not work.
+ * [static]
+ * ------------------------------------------------------------------- */
+nthread_t thread_zeroid(void) {
+ nthread_t a;
+ memset(&a, 0, sizeof(a));
+ return a;
+}
+
+/* -------------------------------------------------------------------
+ * set a thread to be ignorable, so joinall won't wait on it
+ * this simply decrements the thread count that joinall uses.
+ * This is utilized by the reporter thread which knows when it
+ * is ok to quit (aka no pending reports).
+ * ------------------------------------------------------------------- */
+void thread_setignore() {
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum--;
+ Condition_Signal(&thread_sNum_cond);
+ Condition_Unlock(thread_sNum_cond);
+}
+
+/* -------------------------------------------------------------------
+ * unset a thread from being ignorable, so joinall will wait on it
+ * this simply increments the thread count that joinall uses.
+ * This is utilized by the reporter thread which knows when it
+ * is ok to quit (aka no pending reports).
+ * ------------------------------------------------------------------- */
+void thread_unsetignore(void) {
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum++;
+ Condition_Signal(&thread_sNum_cond);
+ Condition_Unlock(thread_sNum_cond);
+}
+
+/* -------------------------------------------------------------------
+ * set a thread to be non-terminating, so if you cancel through
+ * Ctrl-C they can be ignored by the joinall.
+ * ------------------------------------------------------------------- */
+void thread_register_nonterm(void) {
+ Condition_Lock(thread_sNum_cond);
+ nonterminating_num++;
+ Condition_Unlock(thread_sNum_cond);
+}
+
+/* -------------------------------------------------------------------
+ * unset a thread from being non-terminating, so if you cancel through
+ * Ctrl-C they can be ignored by the joinall.
+ * ------------------------------------------------------------------- */
+void thread_unregister_nonterm(void) {
+ Condition_Lock(thread_sNum_cond);
+ if (nonterminating_num == 0) {
+ // nonterminating has been released with release_nonterm
+ // Add back to the threads to wait on
+ thread_sNum++;
+ } else {
+ nonterminating_num--;
+ }
+ Condition_Unlock(thread_sNum_cond);
+}
+
+/* -------------------------------------------------------------------
+ * this function releases all non-terminating threads from the list
+ * of active threads, so that when all terminating threads quit
+ * the joinall will complete. This is called on a Ctrl-C input. It is
+ * also used by the -P usage on the server side
+ * ------------------------------------------------------------------- */
+int thread_release_nonterm(int interrupt) {
+ Condition_Lock(thread_sNum_cond);
+ thread_sNum -= nonterminating_num;
+ if (thread_sNum > 1 && nonterminating_num > 0 && interrupt != 0) {
+ fprintf(stderr, "%s", wait_server_threads);
+ }
+ nonterminating_num = 0;
+ Condition_Signal(&thread_sNum_cond);
+ Condition_Unlock(thread_sNum_cond);
+ return thread_sNum;
+}
+
+/* -------------------------------------------------------------------
+ * Return the number of threads currently running (doesn't include
+ * active threads that have called setdaemon (aka reporter thread))
+ * ------------------------------------------------------------------- */
+int thread_numuserthreads(void) {
+ return thread_sNum;
+}
+
+/* -------------------------------------------------------------------
+ * Return the number of taffic threads currently running
+ * ------------------------------------------------------------------- */
+int thread_numtrafficthreads(void) {
+ return thread_trfc_sNum;
+}
+
+/* -------------------------------------------------------------------
+ * Support for realtime scheduling of threads
+ * ------------------------------------------------------------------- */
+#if HAVE_SCHED_SETSCHEDULER
+#include <sched.h>
+#endif
+#ifdef HAVE_MLOCKALL
+#include <sys/mman.h>
+#endif
+void thread_setscheduler(struct thread_Settings *thread) {
+#if HAVE_SCHED_SETSCHEDULER
+ if (isRealtime(thread)) {
+ struct sched_param sp;
+ sp.sched_priority = sched_get_priority_max(SCHED_RR);
+ // SCHED_OTHER, SCHED_FIFO, SCHED_RR
+ if (sched_setscheduler(0, SCHED_RR, &sp) < 0) {
+ perror("Client set scheduler");
+#ifdef HAVE_MLOCKALL
+ } else if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
+ // lock the threads memory
+ perror ("mlockall");
+#endif // MLOCK
+ }
+ }
+#endif // SCHED
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Allow another thread to execute. If no other threads are runable this
+ * is not guarenteed to actually rest.
+ * ------------------------------------------------------------------- */
+void thread_rest (void) {
+#if defined(HAVE_THREAD)
+#if defined(HAVE_POSIX_THREAD)
+ #if HAVE_SCHED_YIELD
+ sched_yield();
+ #endif
+#else // Win32
+ SwitchToThread();
+#endif
+#endif
+}
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
diff --git a/compat/delay.c b/compat/delay.c
new file mode 100644
index 0000000..95bde3e
--- /dev/null
+++ b/compat/delay.c
@@ -0,0 +1,407 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ *
+ * delay.c
+ * by Mark Gates <mgates@nlanr.net>
+ * updates
+ * by Robert J. McMahon <rmcmahon@broadcom.com> <rjmcmahon@rjmcmahon.com>
+ * -------------------------------------------------------------------
+ * attempts at accurate microsecond delays
+ * ------------------------------------------------------------------- */
+#include "headers.h"
+#include "util.h"
+#include "delay.h"
+#include "Thread.h"
+#include <math.h>
+
+#define MILLION 1000000
+#define BILLION 1000000000
+
+/* -------------------------------------------------------------------
+ * A micro-second delay function
+ * o Use a busy loop or nanosleep
+ *
+ * Some notes:
+ * o clock nanosleep with a relative is preferred (see man page for why)
+ * o clock_gettime() (if available) is preferred over gettimeofday()
+ * as it give nanosecond resolution and should be more efficient.
+ * It also supports CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW
+ * though CLOCK_REALTIME is being used by the code.
+ * o This code does not use Timestamp object, as the goal of these
+ * functions is accurate delays (vs accurate timestamps.)
+ * o The syscalls such as nanosleep guarantee at least the request time
+ * and can and will delay longer, particularly due to things like context
+ * switching, causing the delay to lose accuracy
+ * o Kalman filtering is used to predict delay error which in turn
+ * is used to adjust the delay, hopefully mitigating the above.
+ * Note: This can cause the delay to return faster than the request,
+ * i.e. the *at least* guarantee is not preserved for the kalman
+ * adjusted delay calls.
+ * o Remember, the Client is keeping a running average delay for the
+ * thread so errors in delay will also be adjusted there. (Assuming
+ * it's possible. It's not really possible at top line link rates
+ * because lost time can't be made up for by speeding up the transmits.
+ * Hence, don't lose time with delay calls which error on the side of
+ * taking too long. Kalman should help much here.)
+ *
+ * POSIX nanosleep(). This allows a higher timing resolution
+ * (under Linux e.g. it uses hrtimers), does not affect any signals,
+ * and will use up remaining time when interrupted.
+ * ------------------------------------------------------------------- */
+
+void delay_loop(unsigned long usec)
+{
+#ifdef HAVE_CLOCK_NANOSLEEP
+ {
+ struct timespec res;
+ res.tv_sec = usec/MILLION;
+ res.tv_nsec = (usec * 1000) % BILLION;
+ #ifndef WIN32
+ clock_nanosleep(CLOCK_MONOTONIC, 0, &res, NULL);
+ #else
+ clock_nanosleep(0, 0, &res, NULL);
+ #endif
+ }
+#else
+ #ifdef HAVE_KALMAN
+ delay_kalman(usec);
+ #else
+ #ifdef HAVE_NANOSLEEP
+ delay_nanosleep(usec);
+ #else
+ delay_busyloop(usec);
+ #endif
+ #endif
+#endif
+}
+
+int clock_usleep (struct timeval *request) {
+ int rc = 0;
+#if HAVE_THREAD_DEBUG
+ thread_debug("Thread called clock_usleep() until %ld.%ld", request->tv_sec, request->tv_usec);
+#endif
+#ifdef HAVE_CLOCK_NANOSLEEP
+ struct timespec tmp;
+ tmp.tv_sec = request->tv_sec;
+ tmp.tv_nsec = request->tv_usec * 1000;
+
+// Cygwin systems have an issue with CLOCK_MONOTONIC
+#if defined(CLOCK_MONOTONIC) && !defined(WIN32)
+ rc = clock_nanosleep(CLOCK_MONOTONIC, 0, &tmp, NULL);
+#else
+ rc = clock_nanosleep(0, 0, &tmp, NULL);
+#endif
+ if (rc) {
+ fprintf(stderr, "failed clock_nanosleep()=%d\n", rc);
+ }
+#else
+ struct timeval now;
+ struct timeval next = *request;
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec t1;
+ clock_gettime(CLOCK_REALTIME, &t1);
+ now.tv_sec = t1.tv_sec;
+ now.tv_usec = t1.tv_nsec / 1000;
+#else
+ gettimeofday(&now, NULL);
+#endif
+ double delta_usecs;
+ if ((delta_usecs = TimeDifference(next, now)) > 0.0) {
+ delay_loop(delta_usecs);
+ }
+#endif
+ return rc;
+}
+
+int clock_usleep_abstime (struct timeval *request) {
+ int rc = 0;
+#if defined(HAVE_CLOCK_NANOSLEEP) && defined(TIMER_ABSTIME) && !defined(WIN32)
+ struct timespec tmp;
+ tmp.tv_sec = request->tv_sec;
+ tmp.tv_nsec = request->tv_usec * 1000;
+ rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &tmp, NULL);
+ if (rc) {
+ fprintf(stderr, "failed clock_nanosleep()=%d\n", rc);
+ }
+#else
+ struct timeval now;
+ struct timeval next = *request;
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec t1;
+ clock_gettime(CLOCK_REALTIME, &t1);
+ now.tv_sec = t1.tv_sec;
+ now.tv_usec = t1.tv_nsec / 1000;
+#else
+ gettimeofday(&now, NULL);
+#endif
+ double delta_usecs;
+ if ((delta_usecs = (1e6 * TimeDifference(next, now))) > 0.0) {
+ delay_loop(delta_usecs);
+ }
+#endif
+ return rc;
+}
+
+#ifdef HAVE_NANOSLEEP
+// Can use the nanosleep syscall suspending the thread
+void delay_nanosleep (unsigned long usec) {
+ struct timespec requested, remaining;
+ requested.tv_sec = 0;
+ requested.tv_nsec = usec * 1000L;
+ // Note, signals will cause the nanosleep
+ // to return early. That's fine.
+ nanosleep(&requested, &remaining);
+}
+#endif
+
+#if defined (HAVE_NANOSLEEP) || defined (HAVE_CLOCK_GETTIME)
+static void timespec_add_ulong (struct timespec *tv0, unsigned long value) {
+ tv0->tv_sec += (value / BILLION);
+ tv0->tv_nsec += (value % BILLION);
+ if (tv0->tv_nsec >= BILLION) {
+ tv0->tv_sec++;
+ tv0->tv_nsec -= BILLION;
+ }
+}
+#endif
+
+#ifdef HAVE_KALMAN
+// Kalman versions attempt to support delay request
+// accuracy over a minimum guaranteed delay by
+// prediciting the delay error. This is
+// the basic recursive algorithm.
+static void kalman_update (struct kalman_state *state, double measurement) {
+ //prediction update
+ state->p = state->p + state->q;
+ //measurement update
+ state->k = state->p / (state->p + state->r);
+ state->x = state->x + (state->k * (measurement - state->x));
+ state->p = (1 - state->k) * state->p;
+}
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+// Delay calls for systems with clock_gettime
+// Working units are nanoseconds and structures are timespec
+static void timespec_add_double (struct timespec *tv0, double value) {
+ tv0->tv_nsec += (unsigned long) value;
+ if (tv0->tv_nsec >= BILLION) {
+ tv0->tv_sec++;
+ tv0->tv_nsec -= BILLION;
+ }
+}
+// tv1 assumed greater than tv0
+static double timespec_diff (struct timespec tv1, struct timespec tv0) {
+ double result;
+ if (tv1.tv_nsec < tv0.tv_nsec) {
+ tv1.tv_nsec += BILLION;
+ tv1.tv_sec--;
+ }
+ result = (double) (((tv1.tv_sec - tv0.tv_sec) * BILLION) + (tv1.tv_nsec - tv0.tv_nsec));
+ return result;
+}
+static void timespec_add( struct timespec *tv0, struct timespec *tv1)
+{
+ tv0->tv_sec += tv1->tv_sec;
+ tv0->tv_nsec += tv1->tv_nsec;
+ if ( tv0->tv_nsec >= BILLION ) {
+ tv0->tv_nsec -= BILLION;
+ tv0->tv_sec++;
+ }
+}
+static inline
+int timespec_greaterthan(struct timespec tv1, struct timespec tv0) {
+ if (tv1.tv_sec > tv0.tv_sec || \
+ ((tv0.tv_sec == tv1.tv_sec) && (tv1.tv_nsec > tv0.tv_nsec))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+// A cpu busy loop for systems with clock_gettime
+void delay_busyloop (unsigned long usec) {
+ struct timespec t1, t2;
+ clock_gettime(CLOCK_REALTIME, &t1);
+ timespec_add_ulong(&t1, (usec * 1000L));
+ while (1) {
+ clock_gettime(CLOCK_REALTIME, &t2);
+ if (timespec_greaterthan(t2, t1))
+ break;
+ }
+}
+// Kalman routines for systems with clock_gettime
+#ifdef HAVE_KALMAN
+// Request units is microseconds
+// Adjust units is nanoseconds
+void delay_kalman (unsigned long usec) {
+ struct timespec t1, t2, finishtime, requested={0,0}, remaining;
+ double nsec_adjusted, err;
+ static struct kalman_state kalmanerr={
+ 0.00001, //q process noise covariance
+ 0.1, //r measurement noise covariance
+ 0.0, //x value, error predictio (units nanoseconds)
+ 1, //p estimation error covariance
+ 0.75 //k kalman gain
+ };
+ // Get the current clock
+ clock_gettime(CLOCK_REALTIME, &t1);
+ // Perform the kalman adjust per the predicted delay error
+ nsec_adjusted = (usec * 1000.0) - kalmanerr.x;
+ // Set a timespec to be used by the nanosleep
+ // as well as for the finished time calculation
+ timespec_add_double(&requested, nsec_adjusted);
+ // Set the finish time in timespec format
+ finishtime = t1;
+ timespec_add(&finishtime, &requested);
+# ifdef HAVE_NANOSLEEP
+ // Don't call nanosleep for values less than 10 microseconds
+ // as the syscall is too expensive. Let the busy loop
+ // provide the delay for times under that.
+ if (nsec_adjusted > 10000) {
+ nanosleep(&requested, &remaining);
+ }
+# endif
+ while (1) {
+ clock_gettime(CLOCK_REALTIME, &t2);
+ if (timespec_greaterthan(t2, finishtime))
+ break;
+ }
+ // Compute the delay error in units of nanoseconds
+ // and cast to type double
+ err = (timespec_diff(t2, t1) - (usec * 1000));
+ // printf("req: %ld adj: %f err: %.5f (ns)\n", usec, nsec_adjusted, kalmanerr.x);
+ kalman_update(&kalmanerr, err);
+}
+#endif // HAVE_KALMAN
+#else
+// Sadly, these systems must use the not so efficient gettimeofday()
+// and working units are microseconds, struct is timeval
+static void timeval_add_ulong (struct timeval *tv0, unsigned long value) {
+ tv0->tv_usec += value;
+ if (tv0->tv_usec >= MILLION) {
+ tv0->tv_sec++;
+ tv0->tv_usec -= MILLION;
+ }
+}
+static inline
+int timeval_greaterthan(struct timeval tv1, struct timeval tv0) {
+ if (tv1.tv_sec > tv0.tv_sec || \
+ ((tv0.tv_sec == tv1.tv_sec) && (tv1.tv_usec > tv0.tv_usec))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+// tv1 assumed greater than tv0
+static double timeval_diff (struct timeval tv1, struct timeval tv0) {
+ double result;
+ if (tv1.tv_usec < tv0.tv_usec) {
+ tv1.tv_usec += MILLION;
+ tv1.tv_sec--;
+ }
+ result = (double) (((tv1.tv_sec - tv0.tv_sec) * MILLION) + (tv1.tv_usec - tv0.tv_usec));
+ return result;
+}
+void delay_busyloop (unsigned long usec) {
+ struct timeval t1, t2;
+ gettimeofday( &t1, NULL );
+ timeval_add_ulong(&t1, usec);
+ while (1) {
+ gettimeofday( &t2, NULL );
+ if (timeval_greaterthan(t2, t1))
+ break;
+ }
+}
+#ifdef HAVE_KALMAN
+// Request units is microseconds
+// Adjust units is microseconds
+void delay_kalman (unsigned long usec) {
+ struct timeval t1, t2, finishtime;
+ long usec_adjusted;
+ double err;
+ static struct kalman_state kalmanerr={
+ 0.00001, //q process noise covariance
+ 0.1, //r measurement noise covariance
+ 0.0, //x value, error predictio (units nanoseconds)
+ 1, //p estimation error covariance
+ 0.25 //k kalman gain
+ };
+ // Get the current clock
+ gettimeofday( &t1, NULL );
+ // Perform the kalman adjust per the predicted delay error
+ if (kalmanerr.x > 0) {
+ usec_adjusted = usec - (long) floor(kalmanerr.x);
+ if (usec_adjusted < 0)
+ usec_adjusted = 0;
+ }
+ else
+ usec_adjusted = usec + (long) floor(kalmanerr.x);
+ // Set the finishtime
+ finishtime = t1;
+ timeval_add_ulong(&finishtime, usec_adjusted);
+# ifdef HAVE_NANOSLEEP
+ // Don't call nanosleep for values less than 10 microseconds
+ // as the syscall is too expensive. Let the busy loop
+ // provide the delay for times under that.
+ if (usec_adjusted > 10) {
+ struct timespec requested={0,0}, remaining;
+ timespec_add_ulong(&requested, (usec_adjusted * 1000));
+ nanosleep(&requested, &remaining);
+ }
+# endif
+ while (1) {
+ gettimeofday(&t2, NULL );
+ if (timeval_greaterthan(t2, finishtime))
+ break;
+ }
+ // Compute the delay error in units of microseconds
+ // and cast to type double
+ err = (double)(timeval_diff(t2, t1) - usec);
+ // printf("req: %ld adj: %ld err: %.5f (us)\n", usec, usec_adjusted, kalmanerr.x);
+ kalman_update(&kalmanerr, err);
+}
+#endif // Kalman
+#endif
diff --git a/compat/error.c b/compat/error.c
new file mode 100644
index 0000000..53d1727
--- /dev/null
+++ b/compat/error.c
@@ -0,0 +1,210 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ *
+ * error.c
+ * by Mark Gates <mgates@nlanr.net>
+ * -------------------------------------------------------------------
+ * error handlers
+ * ------------------------------------------------------------------- */
+
+#include "headers.h"
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WIN32
+
+/* -------------------------------------------------------------------
+ * Implement a simple Win32 strerror function for our purposes.
+ * These error values weren't handled by FormatMessage;
+ * any particular reason why not??
+ * ------------------------------------------------------------------- */
+
+struct mesg {
+ DWORD err;
+ const char* str;
+};
+
+const struct mesg error_mesgs[] =
+{
+ { WSAEACCES, "Permission denied"},
+ { WSAEADDRINUSE, "Address already in use"},
+ { WSAEADDRNOTAVAIL, "Cannot assign requested address"},
+ { WSAEAFNOSUPPORT, "Address family not supported by protocol family"},
+ { WSAEALREADY, "Operation already in progress"},
+ { WSAECONNABORTED, "Software caused connection abort"},
+ { WSAECONNREFUSED, "Connection refused"},
+ { WSAECONNRESET, "Connection reset by peer"},
+ { WSAEDESTADDRREQ, "Destination address required"},
+ { WSAEFAULT, "Bad address"},
+ { WSAEHOSTDOWN, "Host is down"},
+ { WSAEHOSTUNREACH, "No route to host"},
+ { WSAEINPROGRESS, "Operation now in progress"},
+ { WSAEINTR, "Interrupted function call."},
+ { WSAEINVAL, "Invalid argument."},
+ { WSAEISCONN, "Socket is already connected."},
+ { WSAEMFILE, "Too many open files."},
+ { WSAEMSGSIZE, "Message too long"},
+ { WSAENETDOWN, "Network is down"},
+ { WSAENETRESET, "Network dropped connection on reset"},
+ { WSAENETUNREACH, "Network is unreachable"},
+ { WSAENOBUFS, "No buffer space available."},
+ { WSAENOPROTOOPT, "Bad protocol option."},
+ { WSAENOTCONN, "Socket is not connected"},
+ { WSAENOTSOCK, "Socket operation on non-socket."},
+ { WSAEOPNOTSUPP, "Operation not supported"},
+ { WSAEPFNOSUPPORT, "Protocol family not supported"},
+ { WSAEPROCLIM, "Too many processes."},
+ { WSAEPROTONOSUPPORT, "Protocol not supported"},
+ { WSAEPROTOTYPE, "Protocol wrong type for socket"},
+ { WSAESHUTDOWN, "Cannot send after socket shutdown"},
+ { WSAESOCKTNOSUPPORT, "Socket type not supported."},
+ { WSAETIMEDOUT, "Connection timed out."},
+ { WSATYPE_NOT_FOUND, "Class type not found."},
+ { WSAEWOULDBLOCK, "Resource temporarily unavailable"},
+ { WSAHOST_NOT_FOUND, "Host not found."},
+ { WSA_INVALID_HANDLE, "Specified event object handle is invalid."},
+ { WSA_INVALID_PARAMETER, "One or more parameters are invalid."},
+ { WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state."},
+ { WSA_IO_PENDING, "Overlapped operations will complete later."},
+ { WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available."},
+ { WSANOTINITIALISED, "Successful WSAStartup not yet performed."},
+ { WSANO_DATA, "Valid name, no data record of requested type."},
+ { WSANO_RECOVERY, "This is a non-recoverable error."},
+ { WSASYSCALLFAILURE, "System call failure."},
+ { WSASYSNOTREADY, "Network subsystem is unavailable."},
+ { WSATRY_AGAIN, "Non-authoritative host not found."},
+ { WSAVERNOTSUPPORTED, "WINSOCK.DLL version out of range."},
+ { WSAEDISCON, "Graceful shutdown in progress."},
+ { WSA_OPERATION_ABORTED, "Overlapped operation aborted."},
+ { 0, "No error."}
+
+ /* These appeared in the documentation, but didn't compile.
+ * { WSAINVALIDPROCTABLE, "Invalid procedure table from service provider." },
+ * { WSAINVALIDPROVIDER, "Invalid service provider version number." },
+ * { WSAPROVIDERFAILEDINIT, "Unable to initialize a service provider." },
+ */
+
+}; /* end error_mesgs[] */
+
+const char* winsock_strerror( DWORD inErrno );
+
+/* -------------------------------------------------------------------
+ * winsock_strerror
+ *
+ * returns a string representing the error code. The error messages
+ * were taken from Microsoft's online developer library.
+ * ------------------------------------------------------------------- */
+
+const char* winsock_strerror( DWORD inErrno ) {
+ const char* str = "Unknown error";
+ int i;
+ for ( i = 0; i < sizeof(error_mesgs); i++ ) {
+ if ( error_mesgs[i].err == inErrno ) {
+ str = error_mesgs[i].str;
+ break;
+ }
+ }
+
+ return str;
+} /* end winsock_strerror */
+
+#endif /* WIN32 */
+
+/* -------------------------------------------------------------------
+ * warn
+ *
+ * Prints message and return
+ * ------------------------------------------------------------------- */
+
+void warn( const char *inMessage, const char *inFile, int inLine ) {
+ fflush( 0 );
+
+#ifdef NDEBUG
+ fprintf( stderr, "%s failed\n", inMessage );
+#else
+
+ /* while debugging output file/line number also */
+ fprintf( stderr, "%s failed (%s:%d)\n", inMessage, inFile, inLine );
+#endif
+} /* end warn */
+
+/* -------------------------------------------------------------------
+ * warn_errno
+ *
+ * Prints message and errno message, and return.
+ * ------------------------------------------------------------------- */
+
+void warn_errno( const char *inMessage, const char *inFile, int inLine ) {
+ int my_err;
+ const char* my_str;
+
+ /* get platform's errno and error message */
+#ifdef WIN32
+ my_err = WSAGetLastError();
+ my_str = winsock_strerror( my_err );
+#else
+ my_err = errno;
+ my_str = strerror( my_err );
+#endif
+
+ fflush( 0 );
+
+#ifdef NDEBUG
+ fprintf( stderr, "%s failed: %s\n", inMessage, my_str );
+#else
+
+ /* while debugging output file/line number and errno value also */
+ fprintf( stderr, "%s failed (%s:%d): %s (%d)\n",
+ inMessage, inFile, inLine, my_str, my_err );
+#endif
+} /* end warn_errno */
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
diff --git a/compat/gettcpinfo.c b/compat/gettcpinfo.c
new file mode 100644
index 0000000..11f92fe
--- /dev/null
+++ b/compat/gettcpinfo.c
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 2021
+ * Broadcom Corporation
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the name of Broadcom Coporation,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ *
+ * gettcpinfo.c
+ * Suppport for tcp info in a portable way
+ *
+ * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com)
+ * -------------------------------------------------------------------
+ */
+#include "headers.h"
+#include "gettcpinfo.h"
+#ifdef HAVE_THREAD_DEBUG
+// needed for thread_debug
+#include "Thread.h"
+#endif
+
+#if HAVE_TCP_STATS
+inline void gettcpinfo (int sock, struct iperf_tcpstats *stats) {
+ assert(stats);
+#if HAVE_DECL_TCP_INFO
+ struct tcp_info tcp_info_buf;
+ socklen_t tcp_info_length = sizeof(struct tcp_info);
+ if ((sock > 0) && !(getsockopt(sock, IPPROTO_TCP, TCP_INFO, &tcp_info_buf, &tcp_info_length) < 0)) {
+ stats->cwnd = tcp_info_buf.tcpi_snd_cwnd * tcp_info_buf.tcpi_snd_mss / 1024;
+ stats->rtt = tcp_info_buf.tcpi_rtt;
+ stats->rttvar = tcp_info_buf.tcpi_rttvar;
+ stats->retry_tot = tcp_info_buf.tcpi_total_retrans;
+ stats->mss_negotiated = tcp_info_buf.tcpi_snd_mss;
+ stats->isValid = true;
+#elif HAVE_DECL_TCP_CONNECTION_INFO
+ struct tcp_connection_info tcp_info_buf;
+ socklen_t tcp_info_length = sizeof(struct tcp_connection_info);
+ if ((sock > 0) && !(getsockopt(sock, IPPROTO_TCP, TCP_CONNECTION_INFO, &tcp_info_buf, &tcp_info_length) < 0)) {
+#ifdef __APPLE__
+ stats->cwnd = tcp_info_buf.tcpi_snd_cwnd / 1024;
+#else
+ stats->cwnd = tcp_info_buf.tcpi_snd_cwnd * tcp_info_buf.tcpi_maxseg / 1024;
+#endif
+ stats->rtt = tcp_info_buf.tcpi_rttcur * 1000; // OS X units is ms
+ stats->rttvar = tcp_info_buf.tcpi_rttvar;
+ stats->retry_tot = tcp_info_buf.tcpi_txretransmitpackets;
+ stats->mss_negotiated = tcp_info_buf.tcpi_maxseg;
+ stats->isValid = true;
+#endif
+ } else {
+ stats->rtt = 1;
+ stats->isValid = false;
+ }
+}
+inline void tcpstats_copy (struct iperf_tcpstats *stats_dst, struct iperf_tcpstats *stats_src) {
+ stats_dst->cwnd = stats_src->cwnd;
+ stats_dst->rtt = stats_src->rtt;
+ stats_dst->rttvar = stats_src->rttvar;
+ stats_dst->mss_negotiated = stats_src->mss_negotiated;
+ stats_dst->retry_tot = stats_src->retry_tot;
+ stats_dst->connecttime = stats_src->connecttime;
+ stats_dst->isValid = stats_src->isValid;
+}
+#else
+#if WIN32
+inline void gettcpinfo (SOCKET sock, struct iperf_tcpstats *stats) {
+#else
+inline void gettcpinfo (int sock, struct iperf_tcpstats *stats) {
+#endif
+ stats->rtt = 1;
+ stats->isValid = false;
+};
+inline void tcpstats_copy (struct iperf_tcpstats *stats_dst, struct iperf_tcpstats *stats_src) {
+ stats_dst->rtt = stats_src->rtt;
+ stats_dst->isValid = stats_src->isValid;
+}
+#endif
diff --git a/compat/gettimeofday.c b/compat/gettimeofday.c
new file mode 100644
index 0000000..0e20123
--- /dev/null
+++ b/compat/gettimeofday.c
@@ -0,0 +1,92 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ *
+ * gettimeofday.c
+ * by Mark Gates <mgates@nlanr.net>
+ * -------------------------------------------------------------------
+ * A (hack) implementation of gettimeofday for Windows.
+ * Since I send sec/usec in UDP packets, this made the most sense.
+ * ------------------------------------------------------------------- */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+
+ #include "headers.h"
+ #include "gettimeofday.h"
+
+ #ifdef __cplusplus
+extern "C" {
+#endif
+
+int gettimeofday( struct timeval* tv, void* timezone ) {
+ FILETIME time;
+ double timed;
+
+ GetSystemTimeAsFileTime( &time );
+
+ // Apparently Win32 has units of 1e-7 sec (tenths of microsecs)
+ // 4294967296 is 2^32, to shift high word over
+ // 11644473600 is the number of seconds between
+ // the Win32 epoch 1601-Jan-01 and the Unix epoch 1970-Jan-01
+ // Tests found floating point to be 10x faster than 64bit int math.
+
+ timed = ((time.dwHighDateTime * 4294967296e-7) - 11644473600.0) +
+ (time.dwLowDateTime * 1e-7);
+
+ tv->tv_sec = (long) timed;
+ tv->tv_usec = (long) ((timed - tv->tv_sec) * 1e6);
+
+ return 0;
+}
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* HAVE_GETTIMEOFDAY */
diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c
new file mode 100644
index 0000000..d34e737
--- /dev/null
+++ b/compat/inet_ntop.c
@@ -0,0 +1,210 @@
+#include "inet_aton.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Copyright (C) 1996-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+// support for hiding v4 addresses from outputs
+const char*
+inet_ntop_hide(int af, const void *src, char *dst, socklen_t size) {
+ switch ( af ) {
+ case AF_INET:
+ return(inet_ntop4_hide(src, dst, size));
+ default:
+ return NULL;
+ }
+ /* NOTREACHED */
+}
+const char*
+inet_ntop4_hide(const unsigned char *src, char *dst, socklen_t size) {
+ static const char *fmt = "%s.%s.%s.%u";
+ char tmp[sizeof "255.255.255.255"];
+
+ if ( (size_t)sprintf(tmp, fmt, "*","*","*", src[3]) >= size ) {
+ return NULL;
+ }
+ strcpy(dst, tmp);
+
+ return dst;
+}
+
+
+#ifndef HAVE_INET_NTOP
+#define NS_INT16SZ 2
+#define NS_INADDRSZ 4
+#define NS_IN6ADDRSZ 16
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+
+/* char *
+ * isc_net_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char*
+inet_ntop(int af, const void *src, char *dst, socklen_t size) {
+ switch ( af ) {
+ case AF_INET:
+ return(inet_ntop4(src, dst, size));
+#if HAVE_IPV6
+ case AF_INET6:
+ return(inet_ntop6(src, dst, size));
+#endif
+ default:
+ return NULL;
+ }
+ /* NOTREACHED */
+}
+
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a unsigned char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char*
+inet_ntop4(const unsigned char *src, char *dst, socklen_t size) {
+ static const char *fmt = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+
+ if ( (size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size ) {
+ return NULL;
+ }
+ strcpy(dst, tmp);
+
+ return dst;
+}
+
+/* const char *
+ * isc_inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+#if HAVE_IPV6
+const char*
+inet_ntop6(const unsigned char *src, char *dst, socklen_t size) {
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct {
+ int base, len;
+ } best, cur;
+ unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for ( i = 0; i < NS_IN6ADDRSZ; i++ )
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for ( i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++ ) {
+ if ( words[i] == 0 ) {
+ if ( cur.base == -1 )
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if ( cur.base != -1 ) {
+ if ( best.base == -1 || cur.len > best.len )
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if ( cur.base != -1 ) {
+ if ( best.base == -1 || cur.len > best.len )
+ best = cur;
+ }
+ if ( best.base != -1 && best.len < 2 )
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for ( i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++ ) {
+ /* Are we inside the best run of 0x00's? */
+ if ( best.base != -1 && i >= best.base &&
+ i < (best.base + best.len) ) {
+ if ( i == best.base )
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if ( i != 0 )
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if ( i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff)) ) {
+ if ( !inet_ntop4(src+12, tp,
+ sizeof tmp - (tp - tmp)) )
+ return NULL;
+ tp += strlen(tp);
+ break;
+ }
+ tp += sprintf(tp, "%x", words[i]);
+ }
+ /* Was it a trailing run of 0x00's? */
+ if ( best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ) )
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ( (size_t)(tp - tmp) > size ) {
+ errno = ENOSPC;
+ return NULL;
+ }
+ strcpy(dst, tmp);
+ return dst;
+}
+#endif /* HAVE_IPV6 */
+#endif /* HAVE_INET_NTOP */
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
diff --git a/compat/inet_pton.c b/compat/inet_pton.c
new file mode 100644
index 0000000..32ee887
--- /dev/null
+++ b/compat/inet_pton.c
@@ -0,0 +1,209 @@
+#include "inet_aton.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Copyright (C) 1996-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#ifndef HAVE_INET_PTON
+#define NS_INT16SZ 2
+#define NS_INADDRSZ 4
+#define NS_IN6ADDRSZ 16
+
+/* int
+ * isc_net_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(int af,
+ const char *src,
+ void *dst) {
+ switch ( af ) {
+ case AF_INET:
+ return(inet_pton4(src, dst));
+#if HAVE_IPV6
+ case AF_INET6:
+ return(inet_pton6(src, dst));
+#endif
+ default:
+ return 0;
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton4(src, dst)
+const char *src;
+unsigned char *dst;
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ( (ch = *src++) != '\0' ) {
+ const char *pch;
+
+ if ( (pch = strchr(digits, ch)) != NULL ) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if ( new > 255 )
+ return(0);
+ *tp = new;
+ if ( ! saw_digit ) {
+ if ( ++octets > 4 )
+ return(0);
+ saw_digit = 1;
+ }
+ } else if ( ch == '.' && saw_digit ) {
+ if ( octets == 4 )
+ return(0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return(0);
+ }
+ if ( octets < 4 )
+ return(0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return(1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+#if HAVE_IPV6
+int
+inet_pton6(src, dst)
+const char *src;
+unsigned char *dst;
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ unsigned int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if ( *src == ':' )
+ if ( *++src != ':' )
+ return(0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while ( (ch = *src++) != '\0' ) {
+ const char *pch;
+
+ if ( (pch = strchr((xdigits = xdigits_l), ch)) == NULL )
+ pch = strchr((xdigits = xdigits_u), ch);
+ if ( pch != NULL ) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if ( val > 0xffff )
+ return(0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if ( ch == ':' ) {
+ curtok = src;
+ if ( !saw_xdigit ) {
+ if ( colonp )
+ return(0);
+ colonp = tp;
+ continue;
+ }
+ if ( tp + NS_INT16SZ > endp )
+ return(0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if ( ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0 ) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return(0);
+ }
+ if ( saw_xdigit ) {
+ if ( tp + NS_INT16SZ > endp )
+ return(0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if ( colonp != NULL ) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for ( i = 1; i <= n; i++ ) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if ( tp != endp )
+ return(0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return(1);
+}
+#endif
+
+#endif /* HAVE_INET_PTON */
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
diff --git a/compat/signal.c b/compat/signal.c
new file mode 100644
index 0000000..7060305
--- /dev/null
+++ b/compat/signal.c
@@ -0,0 +1,204 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ *
+ * signal.c
+ * by Mark Gates <mgates@nlanr.net>
+ * -------------------------------------------------------------------
+ * standard signal installer
+ * ------------------------------------------------------------------- */
+
+#include "headers.h"
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WIN32
+
+/* list of signal handlers. _NSIG is number of signals defined. */
+
+static SigfuncPtr handlers[ _NSIG ] = { 0};
+
+/* -------------------------------------------------------------------
+ * sig_dispatcher
+ *
+ * dispatches the signal to appropriate signal handler. This emulates
+ * the signal handling of Unix.
+ *
+ * ------------------------------------------------------------------- */
+
+BOOL WINAPI sig_dispatcher( DWORD type ) {
+ SigfuncPtr h = NULL;
+ int signo;
+
+ switch ( type ) {
+ case CTRL_C_EVENT:
+ signo = SIGINT;
+ h = handlers[ SIGINT ];
+ break;
+
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ signo = SIGTERM;
+ h = handlers[ SIGTERM ];
+ break;
+
+ default:
+ break;
+ }
+
+ if ( h != NULL ) {
+ // call the signal handler
+ h( signo );
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* -------------------------------------------------------------------
+ * my_signal
+ *
+ * installs a signal handler. I emulate Unix signals by storing the
+ * function pointers and dispatching events myself, using the
+ * sig_dispatcher above.
+ * ------------------------------------------------------------------- */
+
+SigfuncPtr my_signal( int inSigno, SigfuncPtr inFunc ) {
+ SigfuncPtr old = NULL;
+
+ if ( inSigno >= 0 && inSigno < _NSIG ) {
+ old = handlers[ inSigno ];
+ handlers[ inSigno ] = inFunc;
+ }
+
+ return old;
+} /* end my_signal */
+
+#else /* not WIN32 */
+
+/* -------------------------------------------------------------------
+ * my_signal
+ *
+ * installs a signal handler, and returns the old handler.
+ * This emulates the semi-standard signal() function in a
+ * standard way using the Posix sigaction function.
+ *
+ * from Stevens, 1998, section 5.8
+ * ------------------------------------------------------------------- */
+
+SigfuncPtr my_signal( int inSigno, SigfuncPtr inFunc ) {
+ struct sigaction theNewAction, theOldAction;
+
+ assert( inFunc != NULL );
+
+ theNewAction.sa_handler = inFunc;
+ sigemptyset( &theNewAction.sa_mask );
+ theNewAction.sa_flags = 0;
+
+ if ( inSigno == SIGALRM ) {
+#ifdef SA_INTERRUPT
+ theNewAction.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
+#endif
+ } else {
+#ifdef SA_RESTART
+ theNewAction.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
+#endif
+ }
+
+ if ( sigaction( inSigno, &theNewAction, &theOldAction ) < 0 ) {
+ return SIG_ERR;
+ } else {
+ return theOldAction.sa_handler;
+ }
+} /* end my_signal */
+
+#endif /* not WIN32 */
+
+/* -------------------------------------------------------------------
+ * sig_exit
+ *
+ * Quietly exits. This protects some against being called multiple
+ * times. (TODO: should use a mutex to ensure (num++ == 0) is atomic.)
+ * ------------------------------------------------------------------- */
+
+void sig_exit( int inSigno ) {
+ static int num = 0;
+ if ( num++ == 0 ) {
+ fflush( 0 );
+ _exit(0);
+ }
+} /* end sig_exit */
+
+void disarm_itimer(void) {
+#ifdef HAVE_SETITIMER
+ struct itimerval it;
+ memset (&it, 0, sizeof (it));
+ setitimer(ITIMER_REAL, &it, NULL);
+#endif
+}
+
+int set_itimer(uintmax_t usecs) {
+ int err = 0;
+#ifdef HAVE_SETITIMER
+ if (usecs < 0) {
+ WARN(1, "set_itimer value invalid");
+ } else {
+ struct itimerval it;
+ memset (&it, 0, sizeof (it));
+ it.it_value.tv_sec = (int)(usecs / 1000000);
+ it.it_value.tv_usec = (int)(usecs % 1000000);
+ err = setitimer(ITIMER_REAL, &it, NULL);
+ }
+#endif
+ return err;
+}
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
diff --git a/compat/snprintf.c b/compat/snprintf.c
new file mode 100644
index 0000000..be56a53
--- /dev/null
+++ b/compat/snprintf.c
@@ -0,0 +1,101 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ * Author: Mark Gates
+ *
+ * snprintf.c
+ *
+ * This is from
+ * W. Richard Stevens, 'UNIX Network Programming', Vol 1, 2nd Edition,
+ * Prentice Hall, 1998.
+ *
+ *
+ * Throughout the book I use snprintf() because it's safer than sprintf().
+ * But as of the time of this writing, not all systems provide this
+ * function. The function below should only be built on those systems
+ * that do not provide a real snprintf().
+ * The function below just acts like sprintf(); it is not safe, but it
+ * tries to detect overflow.
+ * ________________________________________________________________ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#ifndef HAVE_SNPRINTF
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <stdarg.h>
+
+ #include "snprintf.h"
+
+ #ifdef __cplusplus
+extern "C" {
+#endif
+
+int snprintf(char *buf, size_t size, const char *fmt, ...) {
+ int n;
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsprintf(buf, fmt, ap); /* Sigh, some vsprintf's return ptr, not length */
+ n = strlen(buf);
+ va_end(ap);
+
+ if ( n >= size ) {
+ fprintf( stderr, "snprintf: overflowed array\n" );
+ exit(1);
+ }
+
+ return(n);
+}
+
+#ifdef __cplusplus
+} /* end extern "C" */
+ #endif
+
+#endif /* HAVE_SNPRINTF */
diff --git a/compat/string.c b/compat/string.c
new file mode 100644
index 0000000..99415b5
--- /dev/null
+++ b/compat/string.c
@@ -0,0 +1,76 @@
+/*---------------------------------------------------------------
+ * Copyright (c) 1999,2000,2001,2002,2003
+ * The Board of Trustees of the University of Illinois
+ * All Rights Reserved.
+ *---------------------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software (Iperf) and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and
+ * the following disclaimers.
+ *
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimers in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * Neither the names of the University of Illinois, NCSA,
+ * nor the names of its contributors may be used to endorse
+ * or promote products derived from this Software without
+ * specific prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ________________________________________________________________
+ * National Laboratory for Applied Network Research
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * http://www.ncsa.uiuc.edu
+ * ________________________________________________________________
+ *
+ * string.c
+ * by Mark Gates <mgates@nlanr.net>
+ * -------------------------------------------------------------------
+ * various string utilities
+ * ------------------------------------------------------------------- */
+
+#include "headers.h"
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------------------------------------------------------------------
+ * pattern
+ *
+ * Initialize the buffer with a pattern of (index mod 10).
+ * ------------------------------------------------------------------- */
+
+void pattern( char *outBuf, int inBytes ) {
+ assert( outBuf != NULL );
+
+ while ( inBytes-- > 0 ) {
+ outBuf[ inBytes ] = (inBytes % 10) + '0';
+ }
+} /* end pattern */
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif