Initial import of UDT + barchart mods + barchart JNI

master
nathan 2015-01-20 01:22:43 +01:00
commit 0b24133f5d
72 changed files with 30697 additions and 0 deletions

181
.cproject Normal file
View File

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject>
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="converted.config.1797282818">
<storageModule buildSystemId="org.eclipse.cdt.core.defaultConfigDataProvider" id="converted.config.1797282818" moduleId="org.eclipse.cdt.core.settings" name="convertedConfig">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.MachO" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="refreshScope"/>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="false" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
<parser enabled="false"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="false" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="false"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="false" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="false"/>
</scannerInfoProvider>
</profile>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="org.eclipse.cdt.core.pathentry">
<pathentry base-path="UDT" include="jvm/include" kind="inc" path="" system="true"/>
<pathentry include="/usr/include" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/asm" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/bits" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/net" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/netinet" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/sys" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/gdk-pixbuf-2.0" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/gtk-2.0" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/glib-2.0" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/gio-unix-2.0/" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/pixman-1" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/freetype2" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/libpng12" kind="inc" path="" system="true"/>
<pathentry include="/usr/i686-w64-mingw32/include" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/x86_64-linux-gnu" kind="inc" path="" system="true"/>
<pathentry include="/usr/lib/gcc/x86_64-linux-gnu/4.8/include/" kind="inc" path="" system="true"/>
<pathentry include="/usr/share/mingw-w64/include/" kind="inc" path="" system="true"/>
<pathentry kind="mac" name="ENABLE_LGPL" path="" value="true"/>
<pathentry kind="mac" name="ENABLE_CRYPTO" path="" value="true"/>
<pathentry kind="mac" name="DEBUG" path="" value="true"/>
<pathentry kind="mac" name="CUSTOM_RUNTIME" path="" value="true"/>
<pathentry kind="mac" name="ENABLE_INPUT_MONITOR" path="" value="true"/>
<pathentry kind="mac" name="WRAP_BIND_SOCKETS" path="" value="true"/>
<pathentry kind="mac" name="GDK3_LIB" path="" value="1"/>
<pathentry kind="mac" name="GTK3_LIB" path="" value="1"/>
<pathentry kind="mac" name="GTK_LIB" path="" value="1"/>
<pathentry kind="mac" name="GDK_LIB" path="" value="1"/>
<pathentry kind="mac" name="GOBJ_LIB" path="" value="1"/>
<pathentry kind="mac" name="PIXBUF_LIB" path="" value="1"/>
<pathentry kind="mac" name="X11_LIB" path="" value="1"/>
<pathentry kind="mac" name="GTHREAD_LIB" path="" value="1"/>
<pathentry kind="mac" name="X11_TEST_LIB" path="" value="1"/>
<pathentry kind="mac" name="DEFAULT_OS" path="" value="&quot;linux&quot;"/>
<pathentry kind="mac" name="DEFAULT_OS_ARCH" path="" value="&quot;x86_64&quot;"/>
<pathentry kind="src" path="src"/>
<pathentry kind="out" path="bin"/>
<pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
<target name="clean_windows" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_windows.mak</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="windows_32" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_windows.mak COMPILE_OS=windows COMPILE_OS_ARCH=32</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="windows_64" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_windows.mak COMPILE_OS=windows COMPILE_OS_ARCH=64</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean_macosx" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_macosx.mak</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="macosx_32" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_macosx.mak COMPILE_OS=macosx COMPILE_OS_ARCH=32</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="macosx_64" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_macosx.mak COMPILE_OS=macosx COMPILE_OS_ARCH=64</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean_linux" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_linux.mak</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="linux_32" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_linux.mak COMPILE_OS=linux COMPILE_OS_ARCH=32</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="linux_64" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-f make_linux.mak COMPILE_OS=linux COMPILE_OS_ARCH=64</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
</cproject>

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/bin/

86
.project Normal file
View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>UDT</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.make.core.makeBuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>org.eclipse.cdt.core.errorOutputParser</key>
<value>org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser;org.eclipse.cdt.core.GmakeErrorParser;</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.arguments</key>
<value>-f &apos;make_${system:OS}.mak&apos;</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.command</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.location</key>
<value>/UDT/</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.target.auto</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.target.clean</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.target.inc</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.environment</key>
<value>DEFAULT_WS=${system_property:osgi.ws}|JAVA_ROOT=${system_property:java.home}/..|DEFAULT_OS_ARCH=${system_property:osgi.arch}|PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig:/opt/kde3/lib64/pkgconfig:/opt/gnome/lib64/pkgconfig:/opt/gnome/lib64/pkgconfig:/opt/gnome/share/pkgconfig|DEFAULT_OS=${system_property:osgi.os}|</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>false</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.make.core.makeNature</nature>
<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>
<nature>org.eclipse.pde.FeatureNature</nature>
</natures>
</projectDescription>

186
build.sh Executable file
View File

@ -0,0 +1,186 @@
#!/bin/bash
#*******************************************************************************
#
# This will build ALL variants!
#
# This expects the following environment variables set:
#
# COMPILE_OS - linux, macosx, windows
# COMPILE_OS_ARCH - 32, 64, arm
#
#
# possible packages you might need in order to compile:
# gcc-4.8 gcc-4.8-multilib g++-4.8-multilib gdb make libgtk2.0-dev libxtst-dev libc6-dev-i386 mingw-w64
# ccache libssl0.9.8
#
# Then, in gcc_apple_amd64 dir: sudo dpkg -i *.deb (this is 64bit gcc to build macosx binaries)
#
# Because we fake the 32bit/arm library calls during compile time (the libs are
# loaded during run time) we can build 32bit/arm builds on a 64bit system without needing multi-arch
# GTK libraries (fyi: there aren't any... and DO NOT install the i386 ones, since they will REMOVE what
# you already have - buggering your system!)
#
#
#
# TODO: clean up below, verify arm builds.
# # arm: gcc-arm-linux-gnueabi gcc-4.8-arm-linux-gnueabihf
# hf or no hf? beaglebone, rasbpi, ODROID-U3, other ARM devices
#
# ARMv7sf needs gcc-arm-linux-gnueabi, ARMv7hf needs gcc-arm-linux-gnueabihf
#
# To compile for the ARMv7 (BeagleBone Black), follow:
# http://www.michaelhleonard.com/cross-compile-for-beaglebone-black/
#
# for raspi/BBB
# http://www.michaelhleonard.com/cross-compile-for-beaglebone-black/
# http://derekmolloy.ie/beaglebone/setting-up-eclipse-on-the-beaglebone-for-c-development/
# http://stackoverflow.com/questions/9324772/cross-compiling-static-c-hello-world-for-android-using-arm-linux-gnueabi-gcc?rq=1
#
#
#for ANY OTHER OS/ARCH, the easiest, and most straight forward method is to use
# crosstool-ng. http://crosstool-ng.org/
# howto's:
# http://raspberrypi.stackexchange.com/questions/1/how-do-i-build-a-gcc-4-7-toolchain-for-cross-compiling
# http://www.bootc.net/archives/2012/05/26/how-to-build-a-cross-compiler-for-your-raspberry-pi/
# http://www.ps3devwiki.com/wiki/Cross_Compiling
#
#
######################################################################
# as per: http://stackoverflow.com/questions/8937492/what-is-upxs-best-compression-method
# it is NOT a good idea to compress exe's. WHY? Because they run slower, and HDD space is no longer a concern.
# especially since the executable is ~ 500k.
######################################################################
readonly true=1 yes=1 no=0 false=0
BUILD_ENV=`uname -s`-`uname -m`
if [[ "$BUILD_ENV" != "Linux-x86_64" ]]; then
echo " ********"
echo " ******** Can ONLY build on [[ $BUILD_ENV ]]"
echo " ********"
return false
fi
echo " ********"
echo " ******** Build Environment: [[ $BUILD_ENV ]]"
echo " ********"
export PROGRAM_DEPLOY=true
#############
#core function that will build our targets
#############
build() {
BUILD_TYPE=$1
export COMPILE_OS=$2
export COMPILE_OS_ARCH=$3
echo " ********"
echo " ******** Building: ${COMPILE_OS}""_""${COMPILE_OS_ARCH}"
echo " ********"
# compile
make -f $BUILD_TYPE all
}
####################################################################
####################################################################
####################################################################
####################################################################
# DONE WITH FUNCTIONS
####################################################################
####################################################################
####################################################################
BUILD_ALL=false
if [ -z "$1" ]; then
BUILD_ALL=true
elif [[ "$1" == "all" ]]; then
BUILD_ALL=true
fi
# No args will build all.
if [[ $BUILD_ALL == true ]]; then
if [ -z "$1" ]; then
echo " ******** Building linux (32/64), macosx (32/64), windows (32/64)"
echo " ******** Press enter to continue... "
read VARNAME
fi
# LINUX
build "make_linux.mak" linux 32
build "make_linux.mak" linux 64
# WINDOWS
build "make_windows.mak" windows 32
build "make_windows.mak" windows 64
# MAC
build "make_macosx.mak" macosx 32
build "make_macosx.mak" macosx 64
else
# LINUX
if [[ "$1" == "linux" ]]; then
echo " ******** Building linux (32/64)"
build "make_linux.mak" linux 32
build "make_linux.mak" linux 64
elif [[ "$1" == "linux_32" ]]; then
build "make_linux.mak" linux 32
elif [[ "$1" == "linux_64" ]]; then
build "make_linux.mak" linux 64
# WINDOWS
elif [[ "$1" == "windows" ]]; then
#all
echo " ******** Building windows (32/64)"
build "make_windows.mak" windows 32
build "make_windows.mak" windows 64
elif [[ "$1" == "windows_32" ]]; then
build "make_windows.mak" windows 32
elif [[ "$1" == "windows_64" ]]; then
build "make_windows.mak" windows 64
# MAC
elif [[ "$1" == "macosx" ]]; then
#all
echo " ******** Building macosx (32/64)"
build "make_macosx.mak" macosx 32
build "make_macosx.mak" macosx 64
elif [[ "$1" == "macosx_32" ]]; then
build "make_macosx.mak" macosx 32
elif [[ "$1" == "macosx_64" ]]; then
build "make_macosx.mak" macosx 64
else
echo "Please one of the following:"
echo " [all] - builds all of them"
echo ""
echo "linux"
echo " linux [all] - builds 32 and 64 bit linux"
echo " linux_32 [all] - builds 32 bit linux"
echo " linux_64 [all] - builds 64 bit linux"
echo ""
echo "mac"
echo " macosx [all] - builds 32 and 64 bit mac"
echo " macosx_32 [all] - builds 32 bit mac"
echo " macosx_64 [all] - builds 64 bit mac"
echo ""
echo "windows"
echo " windows [all] - builds 32 and 64 bit windows"
echo " windows_32 [all] - builds 32 bit windows"
echo " windows_64 [all] - builds 64 bit windows"
exit 0
fi
fi

View File

@ -0,0 +1,544 @@
/*
* Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef CLASSFILE_CONSTANTS_H
#define CLASSFILE_CONSTANTS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Classfile version number for this information */
#define JVM_CLASSFILE_MAJOR_VERSION 50
#define JVM_CLASSFILE_MINOR_VERSION 0
/* Flags */
enum {
JVM_ACC_PUBLIC = 0x0001,
JVM_ACC_PRIVATE = 0x0002,
JVM_ACC_PROTECTED = 0x0004,
JVM_ACC_STATIC = 0x0008,
JVM_ACC_FINAL = 0x0010,
JVM_ACC_SYNCHRONIZED = 0x0020,
JVM_ACC_SUPER = 0x0020,
JVM_ACC_VOLATILE = 0x0040,
JVM_ACC_BRIDGE = 0x0040,
JVM_ACC_TRANSIENT = 0x0080,
JVM_ACC_VARARGS = 0x0080,
JVM_ACC_NATIVE = 0x0100,
JVM_ACC_INTERFACE = 0x0200,
JVM_ACC_ABSTRACT = 0x0400,
JVM_ACC_STRICT = 0x0800,
JVM_ACC_SYNTHETIC = 0x1000,
JVM_ACC_ANNOTATION = 0x2000,
JVM_ACC_ENUM = 0x4000
};
/* Used in newarray instruction. */
enum {
JVM_T_BOOLEAN = 4,
JVM_T_CHAR = 5,
JVM_T_FLOAT = 6,
JVM_T_DOUBLE = 7,
JVM_T_BYTE = 8,
JVM_T_SHORT = 9,
JVM_T_INT = 10,
JVM_T_LONG = 11
};
/* Constant Pool Entries */
enum {
JVM_CONSTANT_Utf8 = 1,
JVM_CONSTANT_Unicode = 2, /* unused */
JVM_CONSTANT_Integer = 3,
JVM_CONSTANT_Float = 4,
JVM_CONSTANT_Long = 5,
JVM_CONSTANT_Double = 6,
JVM_CONSTANT_Class = 7,
JVM_CONSTANT_String = 8,
JVM_CONSTANT_Fieldref = 9,
JVM_CONSTANT_Methodref = 10,
JVM_CONSTANT_InterfaceMethodref = 11,
JVM_CONSTANT_NameAndType = 12
};
/* StackMapTable type item numbers */
enum {
JVM_ITEM_Top = 0,
JVM_ITEM_Integer = 1,
JVM_ITEM_Float = 2,
JVM_ITEM_Double = 3,
JVM_ITEM_Long = 4,
JVM_ITEM_Null = 5,
JVM_ITEM_UninitializedThis = 6,
JVM_ITEM_Object = 7,
JVM_ITEM_Uninitialized = 8
};
/* Type signatures */
enum {
JVM_SIGNATURE_ARRAY = '[',
JVM_SIGNATURE_BYTE = 'B',
JVM_SIGNATURE_CHAR = 'C',
JVM_SIGNATURE_CLASS = 'L',
JVM_SIGNATURE_ENDCLASS = ';',
JVM_SIGNATURE_ENUM = 'E',
JVM_SIGNATURE_FLOAT = 'F',
JVM_SIGNATURE_DOUBLE = 'D',
JVM_SIGNATURE_FUNC = '(',
JVM_SIGNATURE_ENDFUNC = ')',
JVM_SIGNATURE_INT = 'I',
JVM_SIGNATURE_LONG = 'J',
JVM_SIGNATURE_SHORT = 'S',
JVM_SIGNATURE_VOID = 'V',
JVM_SIGNATURE_BOOLEAN = 'Z'
};
/* Opcodes */
enum {
JVM_OPC_nop = 0,
JVM_OPC_aconst_null = 1,
JVM_OPC_iconst_m1 = 2,
JVM_OPC_iconst_0 = 3,
JVM_OPC_iconst_1 = 4,
JVM_OPC_iconst_2 = 5,
JVM_OPC_iconst_3 = 6,
JVM_OPC_iconst_4 = 7,
JVM_OPC_iconst_5 = 8,
JVM_OPC_lconst_0 = 9,
JVM_OPC_lconst_1 = 10,
JVM_OPC_fconst_0 = 11,
JVM_OPC_fconst_1 = 12,
JVM_OPC_fconst_2 = 13,
JVM_OPC_dconst_0 = 14,
JVM_OPC_dconst_1 = 15,
JVM_OPC_bipush = 16,
JVM_OPC_sipush = 17,
JVM_OPC_ldc = 18,
JVM_OPC_ldc_w = 19,
JVM_OPC_ldc2_w = 20,
JVM_OPC_iload = 21,
JVM_OPC_lload = 22,
JVM_OPC_fload = 23,
JVM_OPC_dload = 24,
JVM_OPC_aload = 25,
JVM_OPC_iload_0 = 26,
JVM_OPC_iload_1 = 27,
JVM_OPC_iload_2 = 28,
JVM_OPC_iload_3 = 29,
JVM_OPC_lload_0 = 30,
JVM_OPC_lload_1 = 31,
JVM_OPC_lload_2 = 32,
JVM_OPC_lload_3 = 33,
JVM_OPC_fload_0 = 34,
JVM_OPC_fload_1 = 35,
JVM_OPC_fload_2 = 36,
JVM_OPC_fload_3 = 37,
JVM_OPC_dload_0 = 38,
JVM_OPC_dload_1 = 39,
JVM_OPC_dload_2 = 40,
JVM_OPC_dload_3 = 41,
JVM_OPC_aload_0 = 42,
JVM_OPC_aload_1 = 43,
JVM_OPC_aload_2 = 44,
JVM_OPC_aload_3 = 45,
JVM_OPC_iaload = 46,
JVM_OPC_laload = 47,
JVM_OPC_faload = 48,
JVM_OPC_daload = 49,
JVM_OPC_aaload = 50,
JVM_OPC_baload = 51,
JVM_OPC_caload = 52,
JVM_OPC_saload = 53,
JVM_OPC_istore = 54,
JVM_OPC_lstore = 55,
JVM_OPC_fstore = 56,
JVM_OPC_dstore = 57,
JVM_OPC_astore = 58,
JVM_OPC_istore_0 = 59,
JVM_OPC_istore_1 = 60,
JVM_OPC_istore_2 = 61,
JVM_OPC_istore_3 = 62,
JVM_OPC_lstore_0 = 63,
JVM_OPC_lstore_1 = 64,
JVM_OPC_lstore_2 = 65,
JVM_OPC_lstore_3 = 66,
JVM_OPC_fstore_0 = 67,
JVM_OPC_fstore_1 = 68,
JVM_OPC_fstore_2 = 69,
JVM_OPC_fstore_3 = 70,
JVM_OPC_dstore_0 = 71,
JVM_OPC_dstore_1 = 72,
JVM_OPC_dstore_2 = 73,
JVM_OPC_dstore_3 = 74,
JVM_OPC_astore_0 = 75,
JVM_OPC_astore_1 = 76,
JVM_OPC_astore_2 = 77,
JVM_OPC_astore_3 = 78,
JVM_OPC_iastore = 79,
JVM_OPC_lastore = 80,
JVM_OPC_fastore = 81,
JVM_OPC_dastore = 82,
JVM_OPC_aastore = 83,
JVM_OPC_bastore = 84,
JVM_OPC_castore = 85,
JVM_OPC_sastore = 86,
JVM_OPC_pop = 87,
JVM_OPC_pop2 = 88,
JVM_OPC_dup = 89,
JVM_OPC_dup_x1 = 90,
JVM_OPC_dup_x2 = 91,
JVM_OPC_dup2 = 92,
JVM_OPC_dup2_x1 = 93,
JVM_OPC_dup2_x2 = 94,
JVM_OPC_swap = 95,
JVM_OPC_iadd = 96,
JVM_OPC_ladd = 97,
JVM_OPC_fadd = 98,
JVM_OPC_dadd = 99,
JVM_OPC_isub = 100,
JVM_OPC_lsub = 101,
JVM_OPC_fsub = 102,
JVM_OPC_dsub = 103,
JVM_OPC_imul = 104,
JVM_OPC_lmul = 105,
JVM_OPC_fmul = 106,
JVM_OPC_dmul = 107,
JVM_OPC_idiv = 108,
JVM_OPC_ldiv = 109,
JVM_OPC_fdiv = 110,
JVM_OPC_ddiv = 111,
JVM_OPC_irem = 112,
JVM_OPC_lrem = 113,
JVM_OPC_frem = 114,
JVM_OPC_drem = 115,
JVM_OPC_ineg = 116,
JVM_OPC_lneg = 117,
JVM_OPC_fneg = 118,
JVM_OPC_dneg = 119,
JVM_OPC_ishl = 120,
JVM_OPC_lshl = 121,
JVM_OPC_ishr = 122,
JVM_OPC_lshr = 123,
JVM_OPC_iushr = 124,
JVM_OPC_lushr = 125,
JVM_OPC_iand = 126,
JVM_OPC_land = 127,
JVM_OPC_ior = 128,
JVM_OPC_lor = 129,
JVM_OPC_ixor = 130,
JVM_OPC_lxor = 131,
JVM_OPC_iinc = 132,
JVM_OPC_i2l = 133,
JVM_OPC_i2f = 134,
JVM_OPC_i2d = 135,
JVM_OPC_l2i = 136,
JVM_OPC_l2f = 137,
JVM_OPC_l2d = 138,
JVM_OPC_f2i = 139,
JVM_OPC_f2l = 140,
JVM_OPC_f2d = 141,
JVM_OPC_d2i = 142,
JVM_OPC_d2l = 143,
JVM_OPC_d2f = 144,
JVM_OPC_i2b = 145,
JVM_OPC_i2c = 146,
JVM_OPC_i2s = 147,
JVM_OPC_lcmp = 148,
JVM_OPC_fcmpl = 149,
JVM_OPC_fcmpg = 150,
JVM_OPC_dcmpl = 151,
JVM_OPC_dcmpg = 152,
JVM_OPC_ifeq = 153,
JVM_OPC_ifne = 154,
JVM_OPC_iflt = 155,
JVM_OPC_ifge = 156,
JVM_OPC_ifgt = 157,
JVM_OPC_ifle = 158,
JVM_OPC_if_icmpeq = 159,
JVM_OPC_if_icmpne = 160,
JVM_OPC_if_icmplt = 161,
JVM_OPC_if_icmpge = 162,
JVM_OPC_if_icmpgt = 163,
JVM_OPC_if_icmple = 164,
JVM_OPC_if_acmpeq = 165,
JVM_OPC_if_acmpne = 166,
JVM_OPC_goto = 167,
JVM_OPC_jsr = 168,
JVM_OPC_ret = 169,
JVM_OPC_tableswitch = 170,
JVM_OPC_lookupswitch = 171,
JVM_OPC_ireturn = 172,
JVM_OPC_lreturn = 173,
JVM_OPC_freturn = 174,
JVM_OPC_dreturn = 175,
JVM_OPC_areturn = 176,
JVM_OPC_return = 177,
JVM_OPC_getstatic = 178,
JVM_OPC_putstatic = 179,
JVM_OPC_getfield = 180,
JVM_OPC_putfield = 181,
JVM_OPC_invokevirtual = 182,
JVM_OPC_invokespecial = 183,
JVM_OPC_invokestatic = 184,
JVM_OPC_invokeinterface = 185,
JVM_OPC_xxxunusedxxx = 186,
JVM_OPC_new = 187,
JVM_OPC_newarray = 188,
JVM_OPC_anewarray = 189,
JVM_OPC_arraylength = 190,
JVM_OPC_athrow = 191,
JVM_OPC_checkcast = 192,
JVM_OPC_instanceof = 193,
JVM_OPC_monitorenter = 194,
JVM_OPC_monitorexit = 195,
JVM_OPC_wide = 196,
JVM_OPC_multianewarray = 197,
JVM_OPC_ifnull = 198,
JVM_OPC_ifnonnull = 199,
JVM_OPC_goto_w = 200,
JVM_OPC_jsr_w = 201,
JVM_OPC_MAX = 201
};
/* Opcode length initializer, use with something like:
* unsigned char opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER;
*/
#define JVM_OPCODE_LENGTH_INITIALIZER { \
1, /* nop */ \
1, /* aconst_null */ \
1, /* iconst_m1 */ \
1, /* iconst_0 */ \
1, /* iconst_1 */ \
1, /* iconst_2 */ \
1, /* iconst_3 */ \
1, /* iconst_4 */ \
1, /* iconst_5 */ \
1, /* lconst_0 */ \
1, /* lconst_1 */ \
1, /* fconst_0 */ \
1, /* fconst_1 */ \
1, /* fconst_2 */ \
1, /* dconst_0 */ \
1, /* dconst_1 */ \
2, /* bipush */ \
3, /* sipush */ \
2, /* ldc */ \
3, /* ldc_w */ \
3, /* ldc2_w */ \
2, /* iload */ \
2, /* lload */ \
2, /* fload */ \
2, /* dload */ \
2, /* aload */ \
1, /* iload_0 */ \
1, /* iload_1 */ \
1, /* iload_2 */ \
1, /* iload_3 */ \
1, /* lload_0 */ \
1, /* lload_1 */ \
1, /* lload_2 */ \
1, /* lload_3 */ \
1, /* fload_0 */ \
1, /* fload_1 */ \
1, /* fload_2 */ \
1, /* fload_3 */ \
1, /* dload_0 */ \
1, /* dload_1 */ \
1, /* dload_2 */ \
1, /* dload_3 */ \
1, /* aload_0 */ \
1, /* aload_1 */ \
1, /* aload_2 */ \
1, /* aload_3 */ \
1, /* iaload */ \
1, /* laload */ \
1, /* faload */ \
1, /* daload */ \
1, /* aaload */ \
1, /* baload */ \
1, /* caload */ \
1, /* saload */ \
2, /* istore */ \
2, /* lstore */ \
2, /* fstore */ \
2, /* dstore */ \
2, /* astore */ \
1, /* istore_0 */ \
1, /* istore_1 */ \
1, /* istore_2 */ \
1, /* istore_3 */ \
1, /* lstore_0 */ \
1, /* lstore_1 */ \
1, /* lstore_2 */ \
1, /* lstore_3 */ \
1, /* fstore_0 */ \
1, /* fstore_1 */ \
1, /* fstore_2 */ \
1, /* fstore_3 */ \
1, /* dstore_0 */ \
1, /* dstore_1 */ \
1, /* dstore_2 */ \
1, /* dstore_3 */ \
1, /* astore_0 */ \
1, /* astore_1 */ \
1, /* astore_2 */ \
1, /* astore_3 */ \
1, /* iastore */ \
1, /* lastore */ \
1, /* fastore */ \
1, /* dastore */ \
1, /* aastore */ \
1, /* bastore */ \
1, /* castore */ \
1, /* sastore */ \
1, /* pop */ \
1, /* pop2 */ \
1, /* dup */ \
1, /* dup_x1 */ \
1, /* dup_x2 */ \
1, /* dup2 */ \
1, /* dup2_x1 */ \
1, /* dup2_x2 */ \
1, /* swap */ \
1, /* iadd */ \
1, /* ladd */ \
1, /* fadd */ \
1, /* dadd */ \
1, /* isub */ \
1, /* lsub */ \
1, /* fsub */ \
1, /* dsub */ \
1, /* imul */ \
1, /* lmul */ \
1, /* fmul */ \
1, /* dmul */ \
1, /* idiv */ \
1, /* ldiv */ \
1, /* fdiv */ \
1, /* ddiv */ \
1, /* irem */ \
1, /* lrem */ \
1, /* frem */ \
1, /* drem */ \
1, /* ineg */ \
1, /* lneg */ \
1, /* fneg */ \
1, /* dneg */ \
1, /* ishl */ \
1, /* lshl */ \
1, /* ishr */ \
1, /* lshr */ \
1, /* iushr */ \
1, /* lushr */ \
1, /* iand */ \
1, /* land */ \
1, /* ior */ \
1, /* lor */ \
1, /* ixor */ \
1, /* lxor */ \
3, /* iinc */ \
1, /* i2l */ \
1, /* i2f */ \
1, /* i2d */ \
1, /* l2i */ \
1, /* l2f */ \
1, /* l2d */ \
1, /* f2i */ \
1, /* f2l */ \
1, /* f2d */ \
1, /* d2i */ \
1, /* d2l */ \
1, /* d2f */ \
1, /* i2b */ \
1, /* i2c */ \
1, /* i2s */ \
1, /* lcmp */ \
1, /* fcmpl */ \
1, /* fcmpg */ \
1, /* dcmpl */ \
1, /* dcmpg */ \
3, /* ifeq */ \
3, /* ifne */ \
3, /* iflt */ \
3, /* ifge */ \
3, /* ifgt */ \
3, /* ifle */ \
3, /* if_icmpeq */ \
3, /* if_icmpne */ \
3, /* if_icmplt */ \
3, /* if_icmpge */ \
3, /* if_icmpgt */ \
3, /* if_icmple */ \
3, /* if_acmpeq */ \
3, /* if_acmpne */ \
3, /* goto */ \
3, /* jsr */ \
2, /* ret */ \
99, /* tableswitch */ \
99, /* lookupswitch */ \
1, /* ireturn */ \
1, /* lreturn */ \
1, /* freturn */ \
1, /* dreturn */ \
1, /* areturn */ \
1, /* return */ \
3, /* getstatic */ \
3, /* putstatic */ \
3, /* getfield */ \
3, /* putfield */ \
3, /* invokevirtual */ \
3, /* invokespecial */ \
3, /* invokestatic */ \
5, /* invokeinterface */ \
0, /* xxxunusedxxx */ \
3, /* new */ \
2, /* newarray */ \
3, /* anewarray */ \
1, /* arraylength */ \
1, /* athrow */ \
3, /* checkcast */ \
3, /* instanceof */ \
1, /* monitorenter */ \
1, /* monitorexit */ \
0, /* wide */ \
4, /* multianewarray */ \
3, /* ifnull */ \
3, /* ifnonnull */ \
5, /* goto_w */ \
5 /* jsr_w */ \
}
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* CLASSFILE_CONSTANTS */

296
jvm/include/jawt.h Normal file
View File

@ -0,0 +1,296 @@
/*
* Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JAWT_H_
#define _JAVASOFT_JAWT_H_
#include "jni.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* AWT native interface (new in JDK 1.3)
*
* The AWT native interface allows a native C or C++ application a means
* by which to access native structures in AWT. This is to facilitate moving
* legacy C and C++ applications to Java and to target the needs of the
* community who, at present, wish to do their own native rendering to canvases
* for performance reasons. Standard extensions such as Java3D also require a
* means to access the underlying native data structures of AWT.
*
* There may be future extensions to this API depending on demand.
*
* A VM does not have to implement this API in order to pass the JCK.
* It is recommended, however, that this API is implemented on VMs that support
* standard extensions, such as Java3D.
*
* Since this is a native API, any program which uses it cannot be considered
* 100% pure java.
*/
/*
* AWT Native Drawing Surface (JAWT_DrawingSurface).
*
* For each platform, there is a native drawing surface structure. This
* platform-specific structure can be found in jawt_md.h. It is recommended
* that additional platforms follow the same model. It is also recommended
* that VMs on Win32 and Solaris support the existing structures in jawt_md.h.
*
*******************
* EXAMPLE OF USAGE:
*******************
*
* In Win32, a programmer wishes to access the HWND of a canvas to perform
* native rendering into it. The programmer has declared the paint() method
* for their canvas subclass to be native:
*
*
* MyCanvas.java:
*
* import java.awt.*;
*
* public class MyCanvas extends Canvas {
*
* static {
* System.loadLibrary("mylib");
* }
*
* public native void paint(Graphics g);
* }
*
*
* myfile.c:
*
* #include "jawt_md.h"
* #include <assert.h>
*
* JNIEXPORT void JNICALL
* Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
* {
* JAWT awt;
* JAWT_DrawingSurface* ds;
* JAWT_DrawingSurfaceInfo* dsi;
* JAWT_Win32DrawingSurfaceInfo* dsi_win;
* jboolean result;
* jint lock;
*
* // Get the AWT
* awt.version = JAWT_VERSION_1_3;
* result = JAWT_GetAWT(env, &awt);
* assert(result != JNI_FALSE);
*
* // Get the drawing surface
* ds = awt.GetDrawingSurface(env, canvas);
* assert(ds != NULL);
*
* // Lock the drawing surface
* lock = ds->Lock(ds);
* assert((lock & JAWT_LOCK_ERROR) == 0);
*
* // Get the drawing surface info
* dsi = ds->GetDrawingSurfaceInfo(ds);
*
* // Get the platform-specific drawing info
* dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
*
* //////////////////////////////
* // !!! DO PAINTING HERE !!! //
* //////////////////////////////
*
* // Free the drawing surface info
* ds->FreeDrawingSurfaceInfo(dsi);
*
* // Unlock the drawing surface
* ds->Unlock(ds);
*
* // Free the drawing surface
* awt.FreeDrawingSurface(ds);
* }
*
*/
/*
* JAWT_Rectangle
* Structure for a native rectangle.
*/
typedef struct jawt_Rectangle {
jint x;
jint y;
jint width;
jint height;
} JAWT_Rectangle;
struct jawt_DrawingSurface;
/*
* JAWT_DrawingSurfaceInfo
* Structure for containing the underlying drawing information of a component.
*/
typedef struct jawt_DrawingSurfaceInfo {
/*
* Pointer to the platform-specific information. This can be safely
* cast to a JAWT_Win32DrawingSurfaceInfo on Windows or a
* JAWT_X11DrawingSurfaceInfo on Solaris. See jawt_md.h for details.
*/
void* platformInfo;
/* Cached pointer to the underlying drawing surface */
struct jawt_DrawingSurface* ds;
/* Bounding rectangle of the drawing surface */
JAWT_Rectangle bounds;
/* Number of rectangles in the clip */
jint clipSize;
/* Clip rectangle array */
JAWT_Rectangle* clip;
} JAWT_DrawingSurfaceInfo;
#define JAWT_LOCK_ERROR 0x00000001
#define JAWT_LOCK_CLIP_CHANGED 0x00000002
#define JAWT_LOCK_BOUNDS_CHANGED 0x00000004
#define JAWT_LOCK_SURFACE_CHANGED 0x00000008
/*
* JAWT_DrawingSurface
* Structure for containing the underlying drawing information of a component.
* All operations on a JAWT_DrawingSurface MUST be performed from the same
* thread as the call to GetDrawingSurface.
*/
typedef struct jawt_DrawingSurface {
/*
* Cached reference to the Java environment of the calling thread.
* If Lock(), Unlock(), GetDrawingSurfaceInfo() or
* FreeDrawingSurfaceInfo() are called from a different thread,
* this data member should be set before calling those functions.
*/
JNIEnv* env;
/* Cached reference to the target object */
jobject target;
/*
* Lock the surface of the target component for native rendering.
* When finished drawing, the surface must be unlocked with
* Unlock(). This function returns a bitmask with one or more of the
* following values:
*
* JAWT_LOCK_ERROR - When an error has occurred and the surface could not
* be locked.
*
* JAWT_LOCK_CLIP_CHANGED - When the clip region has changed.
*
* JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed.
*
* JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed
*/
jint (JNICALL *Lock)
(struct jawt_DrawingSurface* ds);
/*
* Get the drawing surface info.
* The value returned may be cached, but the values may change if
* additional calls to Lock() or Unlock() are made.
* Lock() must be called before this can return a valid value.
* Returns NULL if an error has occurred.
* When finished with the returned value, FreeDrawingSurfaceInfo must be
* called.
*/
JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo)
(struct jawt_DrawingSurface* ds);
/*
* Free the drawing surface info.
*/
void (JNICALL *FreeDrawingSurfaceInfo)
(JAWT_DrawingSurfaceInfo* dsi);
/*
* Unlock the drawing surface of the target component for native rendering.
*/
void (JNICALL *Unlock)
(struct jawt_DrawingSurface* ds);
} JAWT_DrawingSurface;
/*
* JAWT
* Structure for containing native AWT functions.
*/
typedef struct jawt {
/*
* Version of this structure. This must always be set before
* calling JAWT_GetAWT()
*/
jint version;
/*
* Return a drawing surface from a target jobject. This value
* may be cached.
* Returns NULL if an error has occurred.
* Target must be a java.awt.Component (should be a Canvas
* or Window for native rendering).
* FreeDrawingSurface() must be called when finished with the
* returned JAWT_DrawingSurface.
*/
JAWT_DrawingSurface* (JNICALL *GetDrawingSurface)
(JNIEnv* env, jobject target);
/*
* Free the drawing surface allocated in GetDrawingSurface.
*/
void (JNICALL *FreeDrawingSurface)
(JAWT_DrawingSurface* ds);
/*
* Since 1.4
* Locks the entire AWT for synchronization purposes
*/
void (JNICALL *Lock)(JNIEnv* env);
/*
* Since 1.4
* Unlocks the entire AWT for synchronization purposes
*/
void (JNICALL *Unlock)(JNIEnv* env);
/*
* Since 1.4
* Returns a reference to a java.awt.Component from a native
* platform handle. On Windows, this corresponds to an HWND;
* on Solaris and Linux, this is a Drawable. For other platforms,
* see the appropriate machine-dependent header file for a description.
* The reference returned by this function is a local
* reference that is only valid in this environment.
* This function returns a NULL reference if no component could be
* found with matching platform information.
*/
jobject (JNICALL *GetComponent)(JNIEnv* env, void* platformInfo);
} JAWT;
/*
* Get the AWT native structure. This function returns JNI_FALSE if
* an error occurs.
*/
_JNI_IMPORT_OR_EXPORT_
jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt);
#define JAWT_VERSION_1_3 0x00010003
#define JAWT_VERSION_1_4 0x00010004
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* !_JAVASOFT_JAWT_H_ */

254
jvm/include/jdwpTransport.h Normal file
View File

@ -0,0 +1,254 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Java Debug Wire Protocol Transport Service Provider Interface.
*/
#ifndef JDWPTRANSPORT_H
#define JDWPTRANSPORT_H
#include "jni.h"
enum {
JDWPTRANSPORT_VERSION_1_0 = 0x00010000
};
#ifdef __cplusplus
extern "C" {
#endif
struct jdwpTransportNativeInterface_;
struct _jdwpTransportEnv;
#ifdef __cplusplus
typedef _jdwpTransportEnv jdwpTransportEnv;
#else
typedef const struct jdwpTransportNativeInterface_ *jdwpTransportEnv;
#endif /* __cplusplus */
/*
* Errors. Universal errors with JVMTI/JVMDI equivalents keep the
* values the same.
*/
typedef enum {
JDWPTRANSPORT_ERROR_NONE = 0,
JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT = 103,
JDWPTRANSPORT_ERROR_OUT_OF_MEMORY = 110,
JDWPTRANSPORT_ERROR_INTERNAL = 113,
JDWPTRANSPORT_ERROR_ILLEGAL_STATE = 201,
JDWPTRANSPORT_ERROR_IO_ERROR = 202,
JDWPTRANSPORT_ERROR_TIMEOUT = 203,
JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE = 204
} jdwpTransportError;
/*
* Structure to define capabilities
*/
typedef struct {
unsigned int can_timeout_attach :1;
unsigned int can_timeout_accept :1;
unsigned int can_timeout_handshake :1;
unsigned int reserved3 :1;
unsigned int reserved4 :1;
unsigned int reserved5 :1;
unsigned int reserved6 :1;
unsigned int reserved7 :1;
unsigned int reserved8 :1;
unsigned int reserved9 :1;
unsigned int reserved10 :1;
unsigned int reserved11 :1;
unsigned int reserved12 :1;
unsigned int reserved13 :1;
unsigned int reserved14 :1;
unsigned int reserved15 :1;
} JDWPTransportCapabilities;
/*
* Structures to define packet layout.
*
* See: http://java.sun.com/j2se/1.5/docs/guide/jpda/jdwp-spec.html
*/
enum {
JDWPTRANSPORT_FLAGS_NONE = 0x0,
JDWPTRANSPORT_FLAGS_REPLY = 0x80
};
typedef struct {
jint len;
jint id;
jbyte flags;
jbyte cmdSet;
jbyte cmd;
jbyte *data;
} jdwpCmdPacket;
typedef struct {
jint len;
jint id;
jbyte flags;
jshort errorCode;
jbyte *data;
} jdwpReplyPacket;
typedef struct {
union {
jdwpCmdPacket cmd;
jdwpReplyPacket reply;
} type;
} jdwpPacket;
/*
* JDWP functions called by the transport.
*/
typedef struct jdwpTransportCallback {
void *(*alloc)(jint numBytes); /* Call this for all allocations */
void (*free)(void *buffer); /* Call this for all deallocations */
} jdwpTransportCallback;
typedef jint (JNICALL *jdwpTransport_OnLoad_t)(JavaVM *jvm,
jdwpTransportCallback *callback,
jint version,
jdwpTransportEnv** env);
/* Function Interface */
struct jdwpTransportNativeInterface_ {
/* 1 : RESERVED */
void *reserved1;
/* 2 : Get Capabilities */
jdwpTransportError (JNICALL *GetCapabilities)(jdwpTransportEnv* env,
JDWPTransportCapabilities *capabilities_ptr);
/* 3 : Attach */
jdwpTransportError (JNICALL *Attach)(jdwpTransportEnv* env,
const char* address,
jlong attach_timeout,
jlong handshake_timeout);
/* 4: StartListening */
jdwpTransportError (JNICALL *StartListening)(jdwpTransportEnv* env,
const char* address,
char** actual_address);
/* 5: StopListening */
jdwpTransportError (JNICALL *StopListening)(jdwpTransportEnv* env);
/* 6: Accept */
jdwpTransportError (JNICALL *Accept)(jdwpTransportEnv* env,
jlong accept_timeout,
jlong handshake_timeout);
/* 7: IsOpen */
jboolean (JNICALL *IsOpen)(jdwpTransportEnv* env);
/* 8: Close */
jdwpTransportError (JNICALL *Close)(jdwpTransportEnv* env);
/* 9: ReadPacket */
jdwpTransportError (JNICALL *ReadPacket)(jdwpTransportEnv* env,
jdwpPacket *pkt);
/* 10: Write Packet */
jdwpTransportError (JNICALL *WritePacket)(jdwpTransportEnv* env,
const jdwpPacket* pkt);
/* 11: GetLastError */
jdwpTransportError (JNICALL *GetLastError)(jdwpTransportEnv* env,
char** error);
};
/*
* Use inlined functions so that C++ code can use syntax such as
* env->Attach("mymachine:5000", 10*1000, 0);
*
* rather than using C's :-
*
* (*env)->Attach(env, "mymachine:5000", 10*1000, 0);
*/
struct _jdwpTransportEnv {
const struct jdwpTransportNativeInterface_ *functions;
#ifdef __cplusplus
jdwpTransportError GetCapabilities(JDWPTransportCapabilities *capabilities_ptr) {
return functions->GetCapabilities(this, capabilities_ptr);
}
jdwpTransportError Attach(const char* address, jlong attach_timeout,
jlong handshake_timeout) {
return functions->Attach(this, address, attach_timeout, handshake_timeout);
}
jdwpTransportError StartListening(const char* address,
char** actual_address) {
return functions->StartListening(this, address, actual_address);
}
jdwpTransportError StopListening(void) {
return functions->StopListening(this);
}
jdwpTransportError Accept(jlong accept_timeout, jlong handshake_timeout) {
return functions->Accept(this, accept_timeout, handshake_timeout);
}
jboolean IsOpen(void) {
return functions->IsOpen(this);
}
jdwpTransportError Close(void) {
return functions->Close(this);
}
jdwpTransportError ReadPacket(jdwpPacket *pkt) {
return functions->ReadPacket(this, pkt);
}
jdwpTransportError WritePacket(const jdwpPacket* pkt) {
return functions->WritePacket(this, pkt);
}
jdwpTransportError GetLastError(char** error) {
return functions->GetLastError(this, error);
}
#endif /* __cplusplus */
};
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* JDWPTRANSPORT_H */

1959
jvm/include/jni.h Normal file

File diff suppressed because it is too large Load Diff

2520
jvm/include/jvmti.h Normal file

File diff suppressed because it is too large Load Diff

115
jvm/include/jvmticmlr.h Normal file
View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This header file defines the data structures sent by the VM
* through the JVMTI CompiledMethodLoad callback function via the
* "void * compile_info" parameter. The memory pointed to by the
* compile_info parameter may not be referenced after returning from
* the CompiledMethodLoad callback. These are VM implementation
* specific data structures that may evolve in future releases. A
* JVMTI agent should interpret a non-NULL compile_info as a pointer
* to a region of memory containing a list of records. In a typical
* usage scenario, a JVMTI agent would cast each record to a
* jvmtiCompiledMethodLoadRecordHeader, a struct that represents
* arbitrary information. This struct contains a kind field to indicate
* the kind of information being passed, and a pointer to the next
* record. If the kind field indicates inlining information, then the
* agent would cast the record to a jvmtiCompiledMethodLoadInlineRecord.
* This record contains an array of PCStackInfo structs, which indicate
* for every pc address what are the methods on the invocation stack.
* The "methods" and "bcis" fields in each PCStackInfo struct specify a
* 1-1 mapping between these inlined methods and their bytecode indices.
* This can be used to derive the proper source lines of the inlined
* methods.
*/
#ifndef _JVMTI_CMLR_H_
#define _JVMTI_CMLR_H_
enum {
JVMTI_CMLR_MAJOR_VERSION_1 = 0x00000001,
JVMTI_CMLR_MINOR_VERSION_0 = 0x00000000,
JVMTI_CMLR_MAJOR_VERSION = 0x00000001,
JVMTI_CMLR_MINOR_VERSION = 0x00000000
/*
* This comment is for the "JDK import from HotSpot" sanity check:
* version: 1.0.0
*/
};
typedef enum {
JVMTI_CMLR_DUMMY = 1,
JVMTI_CMLR_INLINE_INFO = 2
} jvmtiCMLRKind;
/*
* Record that represents arbitrary information passed through JVMTI
* CompiledMethodLoadEvent void pointer.
*/
typedef struct _jvmtiCompiledMethodLoadRecordHeader {
jvmtiCMLRKind kind; /* id for the kind of info passed in the record */
jint majorinfoversion; /* major and minor info version values. Init'ed */
jint minorinfoversion; /* to current version value in jvmtiExport.cpp. */
struct _jvmtiCompiledMethodLoadRecordHeader* next;
} jvmtiCompiledMethodLoadRecordHeader;
/*
* Record that gives information about the methods on the compile-time
* stack at a specific pc address of a compiled method. Each element in
* the methods array maps to same element in the bcis array.
*/
typedef struct _PCStackInfo {
void* pc; /* the pc address for this compiled method */
jint numstackframes; /* number of methods on the stack */
jmethodID* methods; /* array of numstackframes method ids */
jint* bcis; /* array of numstackframes bytecode indices */
} PCStackInfo;
/*
* Record that contains inlining information for each pc address of
* an nmethod.
*/
typedef struct _jvmtiCompiledMethodLoadInlineRecord {
jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
jint numpcs; /* number of pc descriptors in this nmethod */
PCStackInfo* pcinfo; /* array of numpcs pc descriptors */
} jvmtiCompiledMethodLoadInlineRecord;
/*
* Dummy record used to test that we can pass records with different
* information through the void pointer provided that they can be cast
* to a jvmtiCompiledMethodLoadRecordHeader.
*/
typedef struct _jvmtiCompiledMethodLoadDummyRecord {
jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
char message[50];
} jvmtiCompiledMethodLoadDummyRecord;
#endif

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include "jawt.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* X11-specific declarations for AWT native interface.
* See notes in jawt.h for an example of use.
*/
typedef struct jawt_X11DrawingSurfaceInfo {
Drawable drawable;
Display* display;
VisualID visualID;
Colormap colormapID;
int depth;
/*
* Since 1.4
* Returns a pixel value from a set of RGB values.
* This is useful for paletted color (256 color) modes.
*/
int (JNICALL *GetAWTColor)(JAWT_DrawingSurface* ds,
int r, int g, int b);
} JAWT_X11DrawingSurfaceInfo;
#ifdef __cplusplus
}
#endif
#endif /* !_JAVASOFT_JAWT_MD_H_ */

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 1996, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#define JNIEXPORT
#define JNIIMPORT
#define JNICALL
typedef int jint;
#ifdef _LP64 /* 64-bit Solaris */
typedef long jlong;
#else
typedef long long jlong;
#endif
typedef signed char jbyte;
#endif /* !_JAVASOFT_JNI_MD_H_ */

View File

@ -0,0 +1,15 @@
//
// AWTCocoaComponent.h
//
// Copyright (c) 2003 Apple Computer Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <JavaVM/jni.h>
// This is implemented by a com.apple.eawt.CocoaComponent. It receives messages
// from java safely on the AppKit thread. See the com.apple.eawt.CocoaComponent
// java documentation for more information.
@protocol AWTCocoaComponent
-(void)awtMessage:(jint)messageID message:(jobject)message env:(JNIEnv*)env;
@end

53
jvm/include/macosx/JDWP.h Normal file
View File

@ -0,0 +1,53 @@
/*
* @(#)JDWP.h 1.33 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
#ifndef JDWP_JDWP_H
#define JDWP_JDWP_H
#include "JDWPCommands.h"
/*
* JDWPCommands.h is the javah'ed version of all the constants defined
* com.sun.tools.jdi.JDWP and all its nested classes. Since the names are
* very long, the macros below are provided for convenience.
*/
#define JDWP_COMMAND_SET(name) JDWP_ ## name
#define JDWP_COMMAND(set, name) JDWP_ ## set ## _ ## name
#define JDWP_REQUEST_MODIFIER(name) \
JDWP_EventRequest_Set_Out_modifiers_Modifier_ ## name
#define JDWP_EVENT(name) \
JDWP_EventKind_ ## name
#define JDWP_THREAD_STATUS(name) \
JDWP_ThreadStatus_ ## name
#define JDWP_SUSPEND_STATUS(name) \
JDWP_SuspendStatus_SUSPEND_STATUS_ ## name
#define JDWP_CLASS_STATUS(name) \
JDWP_ClassStatus_ ## name
#define JDWP_TYPE_TAG(name) \
JDWP_TypeTag_ ## name
#define JDWP_TAG(name) \
JDWP_Tag_ ## name
#define JDWP_STEP_DEPTH(name) \
JDWP_StepDepth_ ## name
#define JDWP_STEP_SIZE(name) \
JDWP_StepSize_ ## name
#define JDWP_SUSPEND_POLICY(name) \
JDWP_SuspendPolicy_ ## name
#define JDWP_INVOKE_OPTIONS(name) \
JDWP_InvokeOptions_INVOKE_ ## name
#define JDWP_ERROR(name) \
JDWP_Error_ ## name
#define JDWP_HIGHEST_COMMAND_SET 17
#define JDWP_REQUEST_NONE -1
/* This typedef helps keep the event and error types straight. */
typedef unsigned short jdwpError;
typedef unsigned char jdwpEvent;
typedef jint jdwpThreadStatus;
#endif

View File

@ -0,0 +1,257 @@
#define JDWP_VirtualMachine 1
#define JDWP_VirtualMachine_Version 1
#define JDWP_VirtualMachine_ClassesBySignature 2
#define JDWP_VirtualMachine_AllClasses 3
#define JDWP_VirtualMachine_AllThreads 4
#define JDWP_VirtualMachine_TopLevelThreadGroups 5
#define JDWP_VirtualMachine_Dispose 6
#define JDWP_VirtualMachine_IDSizes 7
#define JDWP_VirtualMachine_Suspend 8
#define JDWP_VirtualMachine_Resume 9
#define JDWP_VirtualMachine_Exit 10
#define JDWP_VirtualMachine_CreateString 11
#define JDWP_VirtualMachine_Capabilities 12
#define JDWP_VirtualMachine_ClassPaths 13
#define JDWP_VirtualMachine_DisposeObjects 14
#define JDWP_VirtualMachine_HoldEvents 15
#define JDWP_VirtualMachine_ReleaseEvents 16
#define JDWP_VirtualMachine_CapabilitiesNew 17
#define JDWP_VirtualMachine_RedefineClasses 18
#define JDWP_VirtualMachine_SetDefaultStratum 19
#define JDWP_VirtualMachine_AllClassesWithGeneric 20
#define JDWP_VirtualMachine_InstanceCounts 21
#define JDWP_ReferenceType 2
#define JDWP_ReferenceType_Signature 1
#define JDWP_ReferenceType_ClassLoader 2
#define JDWP_ReferenceType_Modifiers 3
#define JDWP_ReferenceType_Fields 4
#define JDWP_ReferenceType_Methods 5
#define JDWP_ReferenceType_GetValues 6
#define JDWP_ReferenceType_SourceFile 7
#define JDWP_ReferenceType_NestedTypes 8
#define JDWP_ReferenceType_Status 9
#define JDWP_ReferenceType_Interfaces 10
#define JDWP_ReferenceType_ClassObject 11
#define JDWP_ReferenceType_SourceDebugExtension 12
#define JDWP_ReferenceType_SignatureWithGeneric 13
#define JDWP_ReferenceType_FieldsWithGeneric 14
#define JDWP_ReferenceType_MethodsWithGeneric 15
#define JDWP_ReferenceType_Instances 16
#define JDWP_ReferenceType_ClassFileVersion 17
#define JDWP_ReferenceType_ConstantPool 18
#define JDWP_ClassType 3
#define JDWP_ClassType_Superclass 1
#define JDWP_ClassType_SetValues 2
#define JDWP_ClassType_InvokeMethod 3
#define JDWP_ClassType_NewInstance 4
#define JDWP_ArrayType 4
#define JDWP_ArrayType_NewInstance 1
#define JDWP_InterfaceType 5
#define JDWP_Method 6
#define JDWP_Method_LineTable 1
#define JDWP_Method_VariableTable 2
#define JDWP_Method_Bytecodes 3
#define JDWP_Method_IsObsolete 4
#define JDWP_Method_VariableTableWithGeneric 5
#define JDWP_Field 8
#define JDWP_ObjectReference 9
#define JDWP_ObjectReference_ReferenceType 1
#define JDWP_ObjectReference_GetValues 2
#define JDWP_ObjectReference_SetValues 3
#define JDWP_ObjectReference_MonitorInfo 5
#define JDWP_ObjectReference_InvokeMethod 6
#define JDWP_ObjectReference_DisableCollection 7
#define JDWP_ObjectReference_EnableCollection 8
#define JDWP_ObjectReference_IsCollected 9
#define JDWP_ObjectReference_ReferringObjects 10
#define JDWP_StringReference 10
#define JDWP_StringReference_Value 1
#define JDWP_ThreadReference 11
#define JDWP_ThreadReference_Name 1
#define JDWP_ThreadReference_Suspend 2
#define JDWP_ThreadReference_Resume 3
#define JDWP_ThreadReference_Status 4
#define JDWP_ThreadReference_ThreadGroup 5
#define JDWP_ThreadReference_Frames 6
#define JDWP_ThreadReference_FrameCount 7
#define JDWP_ThreadReference_OwnedMonitors 8
#define JDWP_ThreadReference_CurrentContendedMonitor 9
#define JDWP_ThreadReference_Stop 10
#define JDWP_ThreadReference_Interrupt 11
#define JDWP_ThreadReference_SuspendCount 12
#define JDWP_ThreadReference_OwnedMonitorsStackDepthInfo 13
#define JDWP_ThreadReference_ForceEarlyReturn 14
#define JDWP_ThreadGroupReference 12
#define JDWP_ThreadGroupReference_Name 1
#define JDWP_ThreadGroupReference_Parent 2
#define JDWP_ThreadGroupReference_Children 3
#define JDWP_ArrayReference 13
#define JDWP_ArrayReference_Length 1
#define JDWP_ArrayReference_GetValues 2
#define JDWP_ArrayReference_SetValues 3
#define JDWP_ClassLoaderReference 14
#define JDWP_ClassLoaderReference_VisibleClasses 1
#define JDWP_EventRequest 15
#define JDWP_EventRequest_Set 1
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_Count 1
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_Conditional 2
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ThreadOnly 3
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassOnly 4
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassMatch 5
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassExclude 6
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly 7
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_ExceptionOnly 8
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_FieldOnly 9
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_Step 10
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_InstanceOnly 11
#define JDWP_EventRequest_Set_Out_modifiers_Modifier_SourceNameMatch 12
#define JDWP_EventRequest_Clear 2
#define JDWP_EventRequest_ClearAllBreakpoints 3
#define JDWP_StackFrame 16
#define JDWP_StackFrame_GetValues 1
#define JDWP_StackFrame_SetValues 2
#define JDWP_StackFrame_ThisObject 3
#define JDWP_StackFrame_PopFrames 4
#define JDWP_ClassObjectReference 17
#define JDWP_ClassObjectReference_ReflectedType 1
#define JDWP_Event 64
#define JDWP_Event_Composite 100
#define JDWP_Event_Composite_Event_events_Events_VMStart JDWP.EventKind.VM_START
#define JDWP_Event_Composite_Event_events_Events_SingleStep JDWP.EventKind.SINGLE_STEP
#define JDWP_Event_Composite_Event_events_Events_Breakpoint JDWP.EventKind.BREAKPOINT
#define JDWP_Event_Composite_Event_events_Events_MethodEntry JDWP.EventKind.METHOD_ENTRY
#define JDWP_Event_Composite_Event_events_Events_MethodExit JDWP.EventKind.METHOD_EXIT
#define JDWP_Event_Composite_Event_events_Events_MethodExitWithReturnValue JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE
#define JDWP_Event_Composite_Event_events_Events_MonitorContendedEnter JDWP.EventKind.MONITOR_CONTENDED_ENTER
#define JDWP_Event_Composite_Event_events_Events_MonitorContendedEntered JDWP.EventKind.MONITOR_CONTENDED_ENTERED
#define JDWP_Event_Composite_Event_events_Events_MonitorWait JDWP.EventKind.MONITOR_WAIT
#define JDWP_Event_Composite_Event_events_Events_MonitorWaited JDWP.EventKind.MONITOR_WAITED
#define JDWP_Event_Composite_Event_events_Events_Exception JDWP.EventKind.EXCEPTION
#define JDWP_Event_Composite_Event_events_Events_ThreadStart JDWP.EventKind.THREAD_START
#define JDWP_Event_Composite_Event_events_Events_ThreadDeath JDWP.EventKind.THREAD_DEATH
#define JDWP_Event_Composite_Event_events_Events_ClassPrepare JDWP.EventKind.CLASS_PREPARE
#define JDWP_Event_Composite_Event_events_Events_ClassUnload JDWP.EventKind.CLASS_UNLOAD
#define JDWP_Event_Composite_Event_events_Events_FieldAccess JDWP.EventKind.FIELD_ACCESS
#define JDWP_Event_Composite_Event_events_Events_FieldModification JDWP.EventKind.FIELD_MODIFICATION
#define JDWP_Event_Composite_Event_events_Events_VMDeath JDWP.EventKind.VM_DEATH
#define JDWP_Error_NONE 0
#define JDWP_Error_INVALID_THREAD 10
#define JDWP_Error_INVALID_THREAD_GROUP 11
#define JDWP_Error_INVALID_PRIORITY 12
#define JDWP_Error_THREAD_NOT_SUSPENDED 13
#define JDWP_Error_THREAD_SUSPENDED 14
#define JDWP_Error_THREAD_NOT_ALIVE 15
#define JDWP_Error_INVALID_OBJECT 20
#define JDWP_Error_INVALID_CLASS 21
#define JDWP_Error_CLASS_NOT_PREPARED 22
#define JDWP_Error_INVALID_METHODID 23
#define JDWP_Error_INVALID_LOCATION 24
#define JDWP_Error_INVALID_FIELDID 25
#define JDWP_Error_INVALID_FRAMEID 30
#define JDWP_Error_NO_MORE_FRAMES 31
#define JDWP_Error_OPAQUE_FRAME 32
#define JDWP_Error_NOT_CURRENT_FRAME 33
#define JDWP_Error_TYPE_MISMATCH 34
#define JDWP_Error_INVALID_SLOT 35
#define JDWP_Error_DUPLICATE 40
#define JDWP_Error_NOT_FOUND 41
#define JDWP_Error_INVALID_MONITOR 50
#define JDWP_Error_NOT_MONITOR_OWNER 51
#define JDWP_Error_INTERRUPT 52
#define JDWP_Error_INVALID_CLASS_FORMAT 60
#define JDWP_Error_CIRCULAR_CLASS_DEFINITION 61
#define JDWP_Error_FAILS_VERIFICATION 62
#define JDWP_Error_ADD_METHOD_NOT_IMPLEMENTED 63
#define JDWP_Error_SCHEMA_CHANGE_NOT_IMPLEMENTED 64
#define JDWP_Error_INVALID_TYPESTATE 65
#define JDWP_Error_HIERARCHY_CHANGE_NOT_IMPLEMENTED 66
#define JDWP_Error_DELETE_METHOD_NOT_IMPLEMENTED 67
#define JDWP_Error_UNSUPPORTED_VERSION 68
#define JDWP_Error_NAMES_DONT_MATCH 69
#define JDWP_Error_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED 70
#define JDWP_Error_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED 71
#define JDWP_Error_NOT_IMPLEMENTED 99
#define JDWP_Error_NULL_POINTER 100
#define JDWP_Error_ABSENT_INFORMATION 101
#define JDWP_Error_INVALID_EVENT_TYPE 102
#define JDWP_Error_ILLEGAL_ARGUMENT 103
#define JDWP_Error_OUT_OF_MEMORY 110
#define JDWP_Error_ACCESS_DENIED 111
#define JDWP_Error_VM_DEAD 112
#define JDWP_Error_INTERNAL 113
#define JDWP_Error_UNATTACHED_THREAD 115
#define JDWP_Error_INVALID_TAG 500
#define JDWP_Error_ALREADY_INVOKING 502
#define JDWP_Error_INVALID_INDEX 503
#define JDWP_Error_INVALID_LENGTH 504
#define JDWP_Error_INVALID_STRING 506
#define JDWP_Error_INVALID_CLASS_LOADER 507
#define JDWP_Error_INVALID_ARRAY 508
#define JDWP_Error_TRANSPORT_LOAD 509
#define JDWP_Error_TRANSPORT_INIT 510
#define JDWP_Error_NATIVE_METHOD 511
#define JDWP_Error_INVALID_COUNT 512
#define JDWP_EventKind_SINGLE_STEP 1
#define JDWP_EventKind_BREAKPOINT 2
#define JDWP_EventKind_FRAME_POP 3
#define JDWP_EventKind_EXCEPTION 4
#define JDWP_EventKind_USER_DEFINED 5
#define JDWP_EventKind_THREAD_START 6
#define JDWP_EventKind_THREAD_DEATH 7
#define JDWP_EventKind_THREAD_END 7
#define JDWP_EventKind_CLASS_PREPARE 8
#define JDWP_EventKind_CLASS_UNLOAD 9
#define JDWP_EventKind_CLASS_LOAD 10
#define JDWP_EventKind_FIELD_ACCESS 20
#define JDWP_EventKind_FIELD_MODIFICATION 21
#define JDWP_EventKind_EXCEPTION_CATCH 30
#define JDWP_EventKind_METHOD_ENTRY 40
#define JDWP_EventKind_METHOD_EXIT 41
#define JDWP_EventKind_METHOD_EXIT_WITH_RETURN_VALUE 42
#define JDWP_EventKind_MONITOR_CONTENDED_ENTER 43
#define JDWP_EventKind_MONITOR_CONTENDED_ENTERED 44
#define JDWP_EventKind_MONITOR_WAIT 45
#define JDWP_EventKind_MONITOR_WAITED 46
#define JDWP_EventKind_VM_START 90
#define JDWP_EventKind_VM_INIT 90
#define JDWP_EventKind_VM_DEATH 99
#define JDWP_EventKind_VM_DISCONNECTED 100
#define JDWP_ThreadStatus_ZOMBIE 0
#define JDWP_ThreadStatus_RUNNING 1
#define JDWP_ThreadStatus_SLEEPING 2
#define JDWP_ThreadStatus_MONITOR 3
#define JDWP_ThreadStatus_WAIT 4
#define JDWP_SuspendStatus_SUSPEND_STATUS_SUSPENDED 0x1
#define JDWP_ClassStatus_VERIFIED 1
#define JDWP_ClassStatus_PREPARED 2
#define JDWP_ClassStatus_INITIALIZED 4
#define JDWP_ClassStatus_ERROR 8
#define JDWP_TypeTag_CLASS 1
#define JDWP_TypeTag_INTERFACE 2
#define JDWP_TypeTag_ARRAY 3
#define JDWP_Tag_ARRAY 91
#define JDWP_Tag_BYTE 66
#define JDWP_Tag_CHAR 67
#define JDWP_Tag_OBJECT 76
#define JDWP_Tag_FLOAT 70
#define JDWP_Tag_DOUBLE 68
#define JDWP_Tag_INT 73
#define JDWP_Tag_LONG 74
#define JDWP_Tag_SHORT 83
#define JDWP_Tag_VOID 86
#define JDWP_Tag_BOOLEAN 90
#define JDWP_Tag_STRING 115
#define JDWP_Tag_THREAD 116
#define JDWP_Tag_THREAD_GROUP 103
#define JDWP_Tag_CLASS_LOADER 108
#define JDWP_Tag_CLASS_OBJECT 99
#define JDWP_StepDepth_INTO 0
#define JDWP_StepDepth_OVER 1
#define JDWP_StepDepth_OUT 2
#define JDWP_StepSize_MIN 0
#define JDWP_StepSize_LINE 1
#define JDWP_SuspendPolicy_NONE 0
#define JDWP_SuspendPolicy_EVENT_THREAD 1
#define JDWP_SuspendPolicy_ALL 2
#define JDWP_InvokeOptions_INVOKE_SINGLE_THREADED 0x01
#define JDWP_InvokeOptions_INVOKE_NONVIRTUAL 0x02

View File

@ -0,0 +1,11 @@
/*
* JavaVM.h
*
* Copyright (C) 1997-2001, Apple Computer, Inc.
* All Rights Reserved.
*
*/
#import <JavaVM/NSJavaVirtualMachine.h>
#import <JavaVM/NSJavaConfiguration.h>

View File

@ -0,0 +1,79 @@
/*
* NSJavaConfiguration.h
*
* Copyright (c) 1997-2001, Apple Computer, Inc.
* All Rights Reserved.
*
* LaurentR- April, 2000
* - added:
* NSDefaultJavaLibraryKey
* NSDefaultJavaDebugLibraryKey
* NSDefaultObjCJavaLibraryKey
* NSDefaultObjCJavaDebugLibraryKey
* NSJavaVMArgumentsKey
*/
#import <Foundation/Foundation.h>
// The configuration dictionary contains a set of vendor-specific key/value
// pairs and a set of default key/value pairs. If no vendor is specified,
// NSJavaConfiguration uses the NSDefaultJavaVendorKey key to determine which
// vendor-specific dictionary should be searched before the top-level dictionary// is searched. eg.:
/*
{
Vendor = sun;
default = {
DefaultClasspath = "/NextLibrary/Java";
};
next = {
Compiler = "/usr/bin/javac";
VM = "/usr/bin/java";
};
sun = {
Compiler = "/NextLibrary/JDK/bin/javac";
VM = "/NextLibrary/JDK/bin/java";
};
}
*/
// In this case, if no vendor is specified, the `sun' mappings will be searched
// first. The value for `VM' would be "/NextLibrary/JDK/bin/java" and the value
// for `DefaultClasspath' would be "/NextLibrary/Java".
//
// This search patter is applied to three dictionaries, in order:
// - the JavaConfiguration dictionary in the defaults for the application
// - the dictionary in the "JavaConfiguration" domain of the user defaults
// - the configuration file (/NextLibrary/Java/JavaConfig.plist).
// This permits per-application, per-user and per-system specifications.
extern NSString *NSDefaultJavaVendorKey;
extern NSString *NSDefaultJavaVMKey;
extern NSString *NSDefaultJavaCompilerKey;
extern NSString *NSDefaultJavaClassPathKey;
extern NSString *NSDefaultJavaLibraryKey;
extern NSString *NSDefaultJavaDebugLibraryKey;
extern NSString *NSDefaultObjCJavaLibraryKey;
extern NSString *NSDefaultObjCJavaDebugLibraryKey;
extern NSString *NSJavaVMArgumentsKey;
@interface NSJavaConfiguration : NSObject
{
NSString *_vendorName;
}
+ (NSJavaConfiguration *) defaultConfiguration;
+ (NSJavaConfiguration *) configurationForVendor:(NSString *)vendorName;
+ (NSArray *) vendorNames;
- init;
- initWithVendor:(NSString *)vendorName;
- (NSString *) vendorName;
- valueForKey:(NSString *)keyName;
- valueForKey:(NSString *)keyName expandEnvironmentVariables:(BOOL)flag;
@end

View File

@ -0,0 +1,61 @@
/*
* NSJavaVirtualMachine.h
*
* Copyright (c) 1997-2001, Apple Computer, Inc.
* All Rights Reserved.
*/
#import <Foundation/Foundation.h>
@interface NSJavaVirtualMachine : NSObject
{
@private
void *_vmdata;
}
// Returns the default virtual machine - if necessary, calls alloc + init
+ (id) defaultVirtualMachine;
// Returns a class path. First checks NSProcessInfo for an environment variable
// called CLASSPATH and if that doesn't exist, uses NSJavaConfiguration to find
// the default class path.
+ (NSString *) defaultClassPath;
// Note that any NSThreads spawned after this method returns will automatically
// be attached to the virtual machine. Likewise, it is not necessary to attach
// the thread that is actually creating the virtual machine. If you spawn a
// thread before creating the virtual machine, or if you use the cthread/pthread
// or any other non-NSThread api for creating a thread, you must explicitly
// attach those threads before messaging any Java object from that thread.
// This is most easily done by using the -attachCurrentThread method.
// Use -detachCurrentThread to detach explicitly attached threads when done.
- initWithClassPath:(NSString *)classPath;
- (void) attachCurrentThread;
- (void) detachCurrentThread;
- (Class)findClass:(NSString *)className;
- (Class)defineClass:(NSData *)javaClassData withName:(NSString *)className;
@end
@interface NSObject (InstantiatingJavaObjects)
// Instantiating java objects for when no -init/constructor mapping works.
// The class these methods are invoked on *must* be a class returned by the
// -findClass: method (or NSClassFromString() function), otherwise
// NSInvalidJavaClassException is raised. The signature is specified using the
// rather counter-intuitive format defined by the Java Virtual Machine
// specification. Try looking in JavaVM/vm-interface.h for help.
+ (id) newWithSignature:(NSString *)signature, ...;
+ (id) newWithSignature:(NSString *)signature arguments:(va_list)args;
@end
extern NSString *NSInvalidJavaClassException;

View File

@ -0,0 +1,66 @@
//
// jawt_md.h
// Copyright (c) 2002-2010 Apple Inc. All rights reserved.
//
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include "jawt.h"
#import <AppKit/NSView.h>
#import <QuartzCore/CALayer.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* JAWT on Mac OS X has two rendering models; legacy NSView, and CALayer.
*
* The CALayer based model returns an object conforming to the JAWT_SurfaceLayers
* protocol in it's JAWT_DrawingSurfaceInfo->platformInfo pointer. A CALayer
* assigned to the "layer" property overlays the rectangle of the java.awt.Component.
* The client CALayer traces the rect of the Java component as it is moved and resized.
*
* If there is a superlayer for the entire window, it is also accessible via
* the "windowLayer" property. This layer is useful for embedding the Java
* window in other layer graphs.
*
*
* The legacy NSView model provides raw access to the NSView hierarchy which
* mirrors the Java component hierarchy. The legacy NSView drawing model is deprecated,
* and will not be available in future versions of Java for Mac OS X.
*
* Clients can opt-into the CALayer model by OR'ing the JAWT_MACOSX_USE_CALAYER into the requested JAWT version.
*
* JAWT awt;
* awt.version = JAWT_VERSION_1_4 | JAWT_MACOSX_USE_CALAYER;
* jboolean success = JAWT_GetAWT(env, &awt);
*
* Future versions of Java for Mac OS X will only support the CALayer model,
* and will not return a JAWT_MacOSXDrawingSurfaceInfo struct.
*/
#define JAWT_MACOSX_USE_CALAYER 0x80000000
// CALayer-based rendering
@protocol JAWT_SurfaceLayers
@property (readwrite, retain) CALayer *layer;
@property (readonly) CALayer *windowLayer;
@end
// Legacy NSView-based rendering
typedef struct JAWT_MacOSXDrawingSurfaceInfo {
NSView *cocoaViewRef; // the view is guaranteed to be valid only for the duration of Component.paint method
}
JAWT_MacOSXDrawingSurfaceInfo;
#ifdef __cplusplus
}
#endif
#endif /* !_JAVASOFT_JAWT_MD_H_ */

View File

@ -0,0 +1,23 @@
/*
* @(#)jni_md.h 1.19 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#define JNIEXPORT __attribute__((visibility("default")))
#define JNIIMPORT
#define JNICALL
#if defined(__LP64__) && __LP64__ /* for -Wundef */
typedef int jint;
#else
typedef long jint;
#endif
typedef long long jlong;
typedef signed char jbyte;
#endif /* !_JAVASOFT_JNI_MD_H_ */

View File

@ -0,0 +1,37 @@
/*
* Whooho. api's and stuff
*/
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include <windows.h>
#include "jawt.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Microsoft win32-specific declarations for using the AWT native interface.
*/
typedef struct jawt_Win32DrawingSurfaceInfo {
/* Tada. The native window, DDB, or DIB handle */
union {
HWND hwnd;
HBITMAP hbitmap;
void* pbits;
};
/*
* This HDC should be the one always used, instead of the one returned from
* BeginPaint() or any particular calls to GetDC().
*/
HDC hdc;
HPALETTE hpalette;
} JAWT_Win32DrawingSurfaceInfo;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,17 @@
/*
* jni_md.h header file
*/
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall
/* stuff and such */
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
#endif

81
make_common.mak Normal file
View File

@ -0,0 +1,81 @@
################################################################################
# Makefile for creating the app launcher program.
#
# This + parent makefiles expect the following environment variables set:
#
# COMPILE_OS - linux, macosx, windows
# COMPILE_OS_ARCH - 32, 64, arm
#
################################################################################
DEPLOY_PATH=../../java_builder/ProjectBuilder/deploy
TARGET_PATH=../../resources/JavaLauncher
JVM=jvm
#setup architecture and path parameters
ifeq ($(COMPILE_OS_ARCH),32)
CCFLAGS +=-DI386
M_ARCH=-m32
DIST_OS_NAME=$(COMPILE_OS)_32
else ifeq ($(COMPILE_OS_ARCH),64)
CCFLAGS +=-DAMD64
M_ARCH=-m64
DIST_OS_NAME=$(COMPILE_OS)_64
else ifeq ($(COMPILE_OS_ARCH),ARM)
#todo finish filling this out
CCFLAGS +=-DARM
endif
# mingw doesn't support the M_ARCH flag.
ifeq ($(COMPILE_OS),windows)
M_ARCH =
endif
CCFLAGS +=${M_ARCH}
#Makes it small AND FAST
CCFLAGS +=-O2
ifneq ($(COMPILE_OS),macosx)
CCFLAGS +=-flto
endif
# warnings and speed/space tricks
FLAGS += \
-P -ftrapv -funroll-loops -fno-strict-aliasing \
-fvisibility=hidden -fvisibility-inlines-hidden -finline-functions \
-Wextra -Wshadow -Wpointer-arith -Wcast-align \
-Wstrict-overflow=5 -Wsign-compare
ifneq ($(COMPILE_OS),windows)
CCFLAGS +=-fPIC
endif
#common path includes
CCFLAGS += \
-isystem$(JVM)/include \
-isystem$(JVM)/include/$(COMPILE_OS) \
-Isrc/
JNI_OBJS = com_barchart_udt_CCC.o com_barchart_udt_SocketUDT.o JNICCC.o JNICCCFactory.o JNIHelpers.o
UDT_OBJS = api.o buffer.o cache.o ccc.o channel.o udtCommon.o core.o epoll.o list.o md5.o packet.o queue.o window.o
$(JNI_OBJS): %.o: src/jni/%.cpp src/jni/%.h
@$(CPP) $(CCFLAGS) $< -c
$(UDT_OBJS): %.o: src/%.cpp src/%.h src/udt.h
@$(CPP) $(CCFLAGS) $< -c
lib: $(UDT_OBJS) $(JNI_OBJS)
@$(CPP) $(CCFLAGS) $(LDFLAGS) -o $(DIST_NAME) $^ $(LIBS)
udt: lib
dist-clean: clean
@rm -f *.dll *.so *.dylib
clean:
@rm -f *.o *.a

34
make_linux.mak Normal file
View File

@ -0,0 +1,34 @@
#*******************************************************************************
# Makefile for creating the GTK launcher program.
#
# This makefile expects the utility "pkg-config" to be in the PATH.
#
# This makefile expect the following environment variables set:
#
# COMPILE_OS - linux, macosx, windows
# COMPILE_OS_ARCH - 32, 64, arm
#*******************************************************************************
include make_common.mak
DIST_NAME=libbarchart-udt-core-2.3.1-mod.so
DIST_PATH=windows_$(COMPILE_OS_ARCH)
CPP=g++
CC=gcc
LDFLAGS = -shared
LIBS = -lpthread -ldl -lm
CCFLAGS += \
-DLINUX \
-isystem/usr/include \
-pthread \
all: dist-clean udt
@echo "\nDONE WITH COMPILE...."
@mkdir -p "bin/$(DIST_OS_NAME)"
@mv "$(DIST_NAME)" "bin/$(DIST_OS_NAME)"
@# now cleanup
@$(MAKE) -s -f make_common.mak clean

41
make_macosx.mak Normal file
View File

@ -0,0 +1,41 @@
#**********************************************************************
# Makefile for creating the Carbon eclipse launcher program.
#
# This makefile expects the following environment variables set:
#
# cross compile libs from : https://launchpad.net/~flosoft/+archive/cross-apple/+packages
#
# This makefile expect the following environment variables set:
#
# COMPILE_OS - linux, macosx, windows
# COMPILE_OS_ARCH - 32, 64, arm
#*******************************************************************************
include make_common.mak
DIST_NAME=libbarchart-udt-core-2.3.1-mod.dylib
DIST_PATH=windows_$(COMPILE_OS_ARCH)
CPP=i686-apple-darwin10-g++
CC=i686-apple-darwin10-gcc
LDFLAGS = -shared -dynamiclib -compatibility_version 1.0 -current_version 1.0 -mmacosx-version-min=10.5
LIBS = -lpthread -lm
#setup architecture parameters
ifeq ($(COMPILE_OS_ARCH),32)
CCFLAGS += -arch i386
else
MACOSX_IS_64BIT=true
CCFLAGS += -arch x86_64
endif
CCFLAGS += -DMACOSX
all: dist-clean udt
@echo "\nDONE WITH COMPILE...."
@mkdir -p "bin/$(DIST_OS_NAME)"
@mv "$(DIST_NAME)" "bin/$(DIST_OS_NAME)"
@# now cleanup
@$(MAKE) -s -f make_common.mak clean

51
make_windows.mak Normal file
View File

@ -0,0 +1,51 @@
#*******************************************************************************
# Makefile for creating the launcher program.
#
# This makefile expects the following environment variables set:
#
# Allow for cross-compiling under linux.
# USES mingw-w64 !!!! (NOT mingw32, which is deprecated)
#
#*******************************************************************************
include make_common.mak
DIST_NAME=libbarchart-udt-core-2.3.1-mod.dll
DIST_PATH=windows_$(COMPILE_OS_ARCH)
ifeq ($(COMPILE_OS_ARCH),32)
MINGVER = i686
#mingw flags
CCFLAGS +=-DWINVER=0x0501
#32 bit support is XP+
CCFLAGS +=-D_WIN32_WINNT=0x0501
else
MINGVER = x86_64
#mingw flags
CCFLAGS +=-DWINVER=0x0600
#64 bit support is vista+ ONLY
CCFLAGS +=-D_WIN32_WINNT=0x0600
endif
CPP = $(shell which $(MINGVER)-w64-mingw32-g++)
STRIP = $(shell which $(MINGVER)-w64-mingw32-strip)
LDFLAGS = -shared -static -static-libgcc -static-libstdc++ -Wl,--kill-at
LIBS = -lkernel32 -luser32 -lws2_32
CCFLAGS += \
-isystem/usr/$(MINGVER)-w64-mingw32/include \
-DWINDOWS \
all: dist-clean udt
@echo "\nDONE WITH COMPILE...."
@# now cleanup
@# now strip the DLL of unneeded, since it can be HUGE
$(STRIP) --strip-debug --strip-unneeded $(DIST_NAME)
@mkdir -p "bin/$(DIST_OS_NAME)"
@mv "$(DIST_NAME)" "bin/$(DIST_OS_NAME)"
@$(MAKE) -s -f make_common.mak clean

2465
src/api.cpp Normal file

File diff suppressed because it is too large Load Diff

273
src/api.h Normal file
View File

@ -0,0 +1,273 @@
/*****************************************************************************
Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 09/28/2010
*****************************************************************************/
#ifndef __UDT_API_H__
#define __UDT_API_H__
#include <map>
#include <vector>
#include "udt.h"
#include "packet.h"
#include "queue.h"
#include "cache.h"
#include "epoll.h"
class CUDT;
class CUDTSocket
{
public:
CUDTSocket();
~CUDTSocket();
UDTSTATUS m_Status; // current socket state
uint64_t m_TimeStamp; // time when the socket is closed
int m_iIPversion; // IP version
sockaddr* m_pSelfAddr; // pointer to the local address of the socket
sockaddr* m_pPeerAddr; // pointer to the peer address of the socket
UDTSOCKET m_SocketID; // socket ID
UDTSOCKET m_ListenSocket; // ID of the listener socket; 0 means this is an independent socket
UDTSOCKET m_PeerID; // peer socket ID
int32_t m_iISN; // initial sequence number, used to tell different connection from same IP:port
CUDT* m_pUDT; // pointer to the UDT entity
std::set<UDTSOCKET>* m_pQueuedSockets; // set of connections waiting for accept()
std::set<UDTSOCKET>* m_pAcceptSockets; // set of accept()ed connections
udt_pthread_cond_t m_AcceptCond; // used to block "accept" call
udt_pthread_mutex_t m_AcceptLock; // mutex associated to m_AcceptCond
unsigned int m_uiBackLog; // maximum number of connections in queue
int m_iMuxID; // multiplexer ID
udt_pthread_mutex_t m_ControlLock; // lock this socket exclusively for control APIs: bind/listen/connect
private:
CUDTSocket(const CUDTSocket&);
CUDTSocket& operator=(const CUDTSocket&);
};
////////////////////////////////////////////////////////////////////////////////
class CUDTUnited
{
friend class CUDT;
friend class CRendezvousQueue;
public:
CUDTUnited();
~CUDTUnited();
public:
// Functionality:
// initialize the UDT library.
// Parameters:
// None.
// Returned value:
// 0 if success, otherwise -1 is returned.
int startup();
// Functionality:
// release the UDT library.
// Parameters:
// None.
// Returned value:
// 0 if success, otherwise -1 is returned.
int cleanup();
// Functionality:
// Create a new UDT socket.
// Parameters:
// 0) [in] af: IP version, IPv4 (AF_INET) or IPv6 (AF_INET6).
// 1) [in] type: socket type, SOCK_STREAM or SOCK_DGRAM
// Returned value:
// The new UDT socket ID, or INVALID_SOCK.
UDTSOCKET newSocket(int af, int type);
// Functionality:
// Create a new UDT connection.
// Parameters:
// 0) [in] listen: the listening UDT socket;
// 1) [in] peer: peer address.
// 2) [in/out] hs: handshake information from peer side (in), negotiated value (out);
// Returned value:
// If the new connection is successfully created: 1 success, 0 already exist, -1 error.
int newConnection(const UDTSOCKET listen, const sockaddr* peer, CHandShake* hs);
// Functionality:
// look up the UDT entity according to its ID.
// Parameters:
// 0) [in] u: the UDT socket ID.
// Returned value:
// Pointer to the UDT entity.
CUDT* lookup(const UDTSOCKET u);
// Functionality:
// Check the status of the UDT socket.
// Parameters:
// 0) [in] u: the UDT socket ID.
// Returned value:
// UDT socket status, or NONEXIST if not found.
UDTSTATUS getStatus(const UDTSOCKET u);
// socket APIs
int bind(const UDTSOCKET u, const sockaddr* name, int namelen);
int bind(const UDTSOCKET u, UDPSOCKET udpsock);
int listen(const UDTSOCKET u, int backlog);
UDTSOCKET accept(const UDTSOCKET listen, sockaddr* addr, int* addrlen);
int connect(const UDTSOCKET u, const sockaddr* name, int namelen);
int close(const UDTSOCKET u);
int getpeername(const UDTSOCKET u, sockaddr* name, int* namelen);
int getsockname(const UDTSOCKET u, sockaddr* name, int* namelen);
int select(ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout);
int selectEx(const std::vector<UDTSOCKET>& fds, std::vector<UDTSOCKET>* readfds, std::vector<UDTSOCKET>* writefds, std::vector<UDTSOCKET>* exceptfds, int64_t msTimeOut);
int epoll_create();
int epoll_add_usock(const int eid, const UDTSOCKET u, const int* events = NULL);
int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
int epoll_remove_usock(const int eid, const UDTSOCKET u);
int epoll_remove_ssock(const int eid, const SYSSOCKET s);
int epoll_wait(const int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds = NULL, std::set<SYSSOCKET>* lwfds = NULL);
int epoll_release(const int eid);
// BARCHART
int epoll_update_usock(const int eid, const UDTSOCKET u, const int* events = NULL);
// BARCHART
int epoll_verify_usock(const int eid, const UDTSOCKET u, int* events);
// Functionality:
// record the UDT exception.
// Parameters:
// 0) [in] e: pointer to a UDT exception instance.
// Returned value:
// None.
void setError(CUDTException* e);
// Functionality:
// look up the most recent UDT exception.
// Parameters:
// None.
// Returned value:
// pointer to a UDT exception instance.
CUDTException* getError();
private:
// void init();
private:
std::map<UDTSOCKET, CUDTSocket*> m_Sockets; // stores all the socket structures
udt_pthread_mutex_t m_ControlLock; // used to synchronize UDT API
udt_pthread_mutex_t m_IDLock; // used to synchronize ID generation
UDTSOCKET m_SocketID; // seed to generate a new unique socket ID
std::map<int64_t, std::set<UDTSOCKET> > m_PeerRec;// record sockets from peers to avoid repeated connection request, int64_t = (socker_id << 30) + isn
private:
udt_pthread_key_t m_TLSError; // thread local error record (last error)
#ifndef WINDOWS
static void TLSDestroy(void* e) {if (NULL != e) delete (CUDTException*)e;}
#else
std::map<DWORD, CUDTException*> m_mTLSRecord;
void checkTLSValue();
udt_pthread_mutex_t m_TLSLock;
#endif
private:
void connect_complete(const UDTSOCKET u);
CUDTSocket* locate(const UDTSOCKET u);
CUDTSocket* locate(const sockaddr* peer, const UDTSOCKET id, int32_t isn);
void updateMux(CUDTSocket* s, const sockaddr* addr = NULL, const UDPSOCKET* = NULL);
void updateMux(CUDTSocket* s, const CUDTSocket* ls);
private:
std::map<int, CMultiplexer> m_mMultiplexer; // UDP multiplexer
udt_pthread_mutex_t m_MultiplexerLock;
private:
CCache<CInfoBlock>* m_pCache; // UDT network information cache
private:
volatile bool m_bClosing;
udt_pthread_mutex_t m_GCStopLock;
udt_pthread_cond_t m_GCStopCond;
udt_pthread_mutex_t m_InitLock;
int m_iInstanceCount; // number of startup() called by application
bool m_bGCStatus; // if the GC thread is working (true)
udt_pthread_t m_GCThread;
#ifndef WINDOWS
static void* garbageCollect(void*);
#else
static DWORD WINAPI garbageCollect(LPVOID);
#endif
std::map<UDTSOCKET, CUDTSocket*> m_ClosedSockets; // temporarily store closed sockets
void checkBrokenSockets();
void removeSocket(const UDTSOCKET u);
private:
CEPoll m_EPoll; // handling epoll data structures and events
private:
CUDTUnited(const CUDTUnited&);
CUDTUnited& operator=(const CUDTUnited&);
};
#endif

652
src/buffer.cpp Normal file
View File

@ -0,0 +1,652 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 03/12/2011
*****************************************************************************/
#include <cstring>
#include <cmath>
#include "buffer.h"
using namespace std;
CSndBuffer::CSndBuffer(int size, int mss):
m_BufLock(),
m_pBlock(NULL),
m_pFirstBlock(NULL),
m_pCurrBlock(NULL),
m_pLastBlock(NULL),
m_pBuffer(NULL),
m_iNextMsgNo(1),
m_iSize(size),
m_iMSS(mss),
m_iCount(0)
{
// initial physical buffer of "size"
m_pBuffer = new Buffer;
m_pBuffer->m_pcData = new char [m_iSize * m_iMSS];
m_pBuffer->m_iSize = m_iSize;
m_pBuffer->m_pNext = NULL;
// circular linked list for out bound packets
m_pBlock = new Block;
Block* pb = m_pBlock;
for (int i = 1; i < m_iSize; ++ i)
{
pb->m_pNext = new Block;
pb->m_iMsgNo = 0;
pb = pb->m_pNext;
}
pb->m_pNext = m_pBlock;
pb = m_pBlock;
char* pc = m_pBuffer->m_pcData;
for (int i = 0; i < m_iSize; ++ i)
{
pb->m_pcData = pc;
pb = pb->m_pNext;
pc += m_iMSS;
}
m_pFirstBlock = m_pCurrBlock = m_pLastBlock = m_pBlock;
#ifndef WINDOWS
pthread_mutex_init(&m_BufLock, NULL);
#else
m_BufLock = CreateMutex(NULL, false, NULL);
#endif
}
CSndBuffer::~CSndBuffer()
{
Block* pb = m_pBlock->m_pNext;
while (pb != m_pBlock)
{
Block* temp = pb;
pb = pb->m_pNext;
delete temp;
}
delete m_pBlock;
while (m_pBuffer != NULL)
{
Buffer* temp = m_pBuffer;
m_pBuffer = m_pBuffer->m_pNext;
delete [] temp->m_pcData;
delete temp;
}
#ifndef WINDOWS
pthread_mutex_destroy(&m_BufLock);
#else
CloseHandle(m_BufLock);
#endif
}
void CSndBuffer::addBuffer(const char* data, int len, int ttl, bool order)
{
int size = len / m_iMSS;
if ((len % m_iMSS) != 0)
size ++;
// dynamically increase sender buffer
while (size + m_iCount >= m_iSize)
increase();
uint64_t time = CTimer::getTime();
int32_t inorder = order;
inorder <<= 29;
Block* s = m_pLastBlock;
for (int i = 0; i < size; ++ i)
{
int pktlen = len - i * m_iMSS;
if (pktlen > m_iMSS)
pktlen = m_iMSS;
memcpy(s->m_pcData, data + i * m_iMSS, pktlen);
s->m_iLength = pktlen;
s->m_iMsgNo = m_iNextMsgNo | inorder;
if (i == 0)
s->m_iMsgNo |= 0x80000000;
if (i == size - 1)
s->m_iMsgNo |= 0x40000000;
s->m_OriginTime = time;
s->m_iTTL = ttl;
s = s->m_pNext;
}
m_pLastBlock = s;
CGuard::enterCS(m_BufLock);
m_iCount += size;
CGuard::leaveCS(m_BufLock);
m_iNextMsgNo ++;
if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo)
m_iNextMsgNo = 1;
}
int CSndBuffer::addBufferFromFile(fstream& ifs, int len)
{
int size = len / m_iMSS;
if ((len % m_iMSS) != 0)
size ++;
// dynamically increase sender buffer
while (size + m_iCount >= m_iSize)
increase();
Block* s = m_pLastBlock;
int total = 0;
for (int i = 0; i < size; ++ i)
{
if (ifs.bad() || ifs.fail() || ifs.eof())
break;
int pktlen = len - i * m_iMSS;
if (pktlen > m_iMSS)
pktlen = m_iMSS;
ifs.read(s->m_pcData, pktlen);
if ((pktlen = ifs.gcount()) <= 0)
break;
// currently file transfer is only available in streaming mode, message is always in order, ttl = infinite
s->m_iMsgNo = m_iNextMsgNo | 0x20000000;
if (i == 0)
s->m_iMsgNo |= 0x80000000;
if (i == size - 1)
s->m_iMsgNo |= 0x40000000;
s->m_iLength = pktlen;
s->m_iTTL = -1;
s = s->m_pNext;
total += pktlen;
}
m_pLastBlock = s;
CGuard::enterCS(m_BufLock);
m_iCount += size;
CGuard::leaveCS(m_BufLock);
m_iNextMsgNo ++;
if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo)
m_iNextMsgNo = 1;
return total;
}
int CSndBuffer::readData(char** data, int32_t& msgno)
{
// No data to read
if (m_pCurrBlock == m_pLastBlock)
return 0;
*data = m_pCurrBlock->m_pcData;
int readlen = m_pCurrBlock->m_iLength;
msgno = m_pCurrBlock->m_iMsgNo;
m_pCurrBlock = m_pCurrBlock->m_pNext;
return readlen;
}
int CSndBuffer::readData(char** data, const int offset, int32_t& msgno, int& msglen)
{
CGuard bufferguard(m_BufLock);
Block* p = m_pFirstBlock;
for (int i = 0; i < offset; ++ i)
p = p->m_pNext;
if ((p->m_iTTL >= 0) && ((CTimer::getTime() - p->m_OriginTime) / 1000 > (uint64_t)p->m_iTTL))
{
msgno = p->m_iMsgNo & 0x1FFFFFFF;
msglen = 1;
p = p->m_pNext;
bool move = false;
while (msgno == (p->m_iMsgNo & 0x1FFFFFFF))
{
if (p == m_pCurrBlock)
move = true;
p = p->m_pNext;
if (move)
m_pCurrBlock = p;
msglen ++;
}
return -1;
}
*data = p->m_pcData;
int readlen = p->m_iLength;
msgno = p->m_iMsgNo;
return readlen;
}
void CSndBuffer::ackData(int offset)
{
CGuard bufferguard(m_BufLock);
for (int i = 0; i < offset; ++ i)
m_pFirstBlock = m_pFirstBlock->m_pNext;
m_iCount -= offset;
CTimer::triggerEvent();
}
int CSndBuffer::getCurrBufSize() const
{
return m_iCount;
}
void CSndBuffer::increase()
{
int unitsize = m_pBuffer->m_iSize;
// new physical buffer
Buffer* nbuf = NULL;
try
{
nbuf = new Buffer;
nbuf->m_pcData = new char [unitsize * m_iMSS];
}
catch (...)
{
delete nbuf;
throw CUDTException(3, 2, 0);
}
nbuf->m_iSize = unitsize;
nbuf->m_pNext = NULL;
// insert the buffer at the end of the buffer list
Buffer* p = m_pBuffer;
while (NULL != p->m_pNext)
p = p->m_pNext;
p->m_pNext = nbuf;
// new packet blocks
Block* nblk = NULL;
try
{
nblk = new Block;
}
catch (...)
{
delete nblk;
throw CUDTException(3, 2, 0);
}
Block* pb = nblk;
for (int i = 1; i < unitsize; ++ i)
{
pb->m_pNext = new Block;
pb = pb->m_pNext;
}
// insert the new blocks onto the existing one
pb->m_pNext = m_pLastBlock->m_pNext;
m_pLastBlock->m_pNext = nblk;
pb = nblk;
char* pc = nbuf->m_pcData;
for (int i = 0; i < unitsize; ++ i)
{
pb->m_pcData = pc;
pb = pb->m_pNext;
pc += m_iMSS;
}
m_iSize += unitsize;
}
////////////////////////////////////////////////////////////////////////////////
CRcvBuffer::CRcvBuffer(CUnitQueue* queue, int bufsize):
m_pUnit(NULL),
m_iSize(bufsize),
m_pUnitQueue(queue),
m_iStartPos(0),
m_iLastAckPos(0),
m_iMaxPos(0),
m_iNotch(0)
{
m_pUnit = new CUnit* [m_iSize];
for (int i = 0; i < m_iSize; ++ i)
m_pUnit[i] = NULL;
}
CRcvBuffer::~CRcvBuffer()
{
for (int i = 0; i < m_iSize; ++ i)
{
if (NULL != m_pUnit[i])
{
m_pUnit[i]->m_iFlag = 0;
-- m_pUnitQueue->m_iCount;
}
}
delete [] m_pUnit;
}
int CRcvBuffer::addData(CUnit* unit, int offset)
{
int pos = (m_iLastAckPos + offset) % m_iSize;
if (offset > m_iMaxPos)
m_iMaxPos = offset;
if (NULL != m_pUnit[pos])
return -1;
m_pUnit[pos] = unit;
unit->m_iFlag = 1;
++ m_pUnitQueue->m_iCount;
return 0;
}
int CRcvBuffer::readBuffer(char* data, int len)
{
int p = m_iStartPos;
int lastack = m_iLastAckPos;
int rs = len;
while ((p != lastack) && (rs > 0))
{
int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch;
if (unitsize > rs)
unitsize = rs;
memcpy(data, m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize);
data += unitsize;
if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch))
{
CUnit* tmp = m_pUnit[p];
m_pUnit[p] = NULL;
tmp->m_iFlag = 0;
-- m_pUnitQueue->m_iCount;
if (++ p == m_iSize)
p = 0;
m_iNotch = 0;
}
else
m_iNotch += rs;
rs -= unitsize;
}
m_iStartPos = p;
return len - rs;
}
int CRcvBuffer::readBufferToFile(fstream& ofs, int len)
{
int p = m_iStartPos;
int lastack = m_iLastAckPos;
int rs = len;
while ((p != lastack) && (rs > 0))
{
int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch;
if (unitsize > rs)
unitsize = rs;
ofs.write(m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize);
if (ofs.fail())
break;
if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch))
{
CUnit* tmp = m_pUnit[p];
m_pUnit[p] = NULL;
tmp->m_iFlag = 0;
-- m_pUnitQueue->m_iCount;
if (++ p == m_iSize)
p = 0;
m_iNotch = 0;
}
else
m_iNotch += rs;
rs -= unitsize;
}
m_iStartPos = p;
return len - rs;
}
void CRcvBuffer::ackData(int len)
{
m_iLastAckPos = (m_iLastAckPos + len) % m_iSize;
m_iMaxPos -= len;
if (m_iMaxPos < 0)
m_iMaxPos = 0;
CTimer::triggerEvent();
}
int CRcvBuffer::getAvailBufSize() const
{
// One slot must be empty in order to tell the difference between "empty buffer" and "full buffer"
return m_iSize - getRcvDataSize() - 1;
}
int CRcvBuffer::getRcvDataSize() const
{
if (m_iLastAckPos >= m_iStartPos)
return m_iLastAckPos - m_iStartPos;
return m_iSize + m_iLastAckPos - m_iStartPos;
}
void CRcvBuffer::dropMsg(int32_t msgno)
{
for (int i = m_iStartPos, n = (m_iLastAckPos + m_iMaxPos) % m_iSize; i != n; i = (i + 1) % m_iSize)
if ((NULL != m_pUnit[i]) && (msgno == m_pUnit[i]->m_Packet.m_iMsgNo))
m_pUnit[i]->m_iFlag = 3;
}
int CRcvBuffer::readMsg(char* data, int len)
{
int p, q;
bool passack;
if (!scanMsg(p, q, passack))
return 0;
int rs = len;
while (p != (q + 1) % m_iSize)
{
int unitsize = m_pUnit[p]->m_Packet.getLength();
if ((rs >= 0) && (unitsize > rs))
unitsize = rs;
if (unitsize > 0)
{
memcpy(data, m_pUnit[p]->m_Packet.m_pcData, unitsize);
data += unitsize;
rs -= unitsize;
}
if (!passack)
{
CUnit* tmp = m_pUnit[p];
m_pUnit[p] = NULL;
tmp->m_iFlag = 0;
-- m_pUnitQueue->m_iCount;
}
else
m_pUnit[p]->m_iFlag = 2;
if (++ p == m_iSize)
p = 0;
}
if (!passack)
m_iStartPos = (q + 1) % m_iSize;
return len - rs;
}
int CRcvBuffer::getRcvMsgNum()
{
int p, q;
bool passack;
return scanMsg(p, q, passack) ? 1 : 0;
}
bool CRcvBuffer::scanMsg(int& p, int& q, bool& passack)
{
// empty buffer
if ((m_iStartPos == m_iLastAckPos) && (m_iMaxPos <= 0))
return false;
//skip all bad msgs at the beginning
while (m_iStartPos != m_iLastAckPos)
{
if (NULL == m_pUnit[m_iStartPos])
{
if (++ m_iStartPos == m_iSize)
m_iStartPos = 0;
continue;
}
if ((1 == m_pUnit[m_iStartPos]->m_iFlag) && (m_pUnit[m_iStartPos]->m_Packet.getMsgBoundary() > 1))
{
bool good = true;
// look ahead for the whole message
for (int i = m_iStartPos; i != m_iLastAckPos;)
{
if ((NULL == m_pUnit[i]) || (1 != m_pUnit[i]->m_iFlag))
{
good = false;
break;
}
if ((m_pUnit[i]->m_Packet.getMsgBoundary() == 1) || (m_pUnit[i]->m_Packet.getMsgBoundary() == 3))
break;
if (++ i == m_iSize)
i = 0;
}
if (good)
break;
}
CUnit* tmp = m_pUnit[m_iStartPos];
m_pUnit[m_iStartPos] = NULL;
tmp->m_iFlag = 0;
-- m_pUnitQueue->m_iCount;
if (++ m_iStartPos == m_iSize)
m_iStartPos = 0;
}
p = -1; // message head
q = m_iStartPos; // message tail
passack = m_iStartPos == m_iLastAckPos;
bool found = false;
// looking for the first message
for (int i = 0, n = m_iMaxPos + getRcvDataSize(); i <= n; ++ i)
{
if ((NULL != m_pUnit[q]) && (1 == m_pUnit[q]->m_iFlag))
{
switch (m_pUnit[q]->m_Packet.getMsgBoundary())
{
case 3: // 11
p = q;
found = true;
break;
case 2: // 10
p = q;
break;
case 1: // 01
if (p != -1)
found = true;
}
}
else
{
// a hole in this message, not valid, restart search
p = -1;
}
if (found)
{
// the msg has to be ack'ed or it is allowed to read out of order, and was not read before
if (!passack || !m_pUnit[q]->m_Packet.getMsgOrderFlag())
break;
found = false;
}
if (++ q == m_iSize)
q = 0;
if (q == m_iLastAckPos)
passack = true;
}
// no msg found
if (!found)
{
// if the message is larger than the receiver buffer, return part of the message
if ((p != -1) && ((q + 1) % m_iSize == p))
found = true;
}
return found;
}

275
src/buffer.h Normal file
View File

@ -0,0 +1,275 @@
/*****************************************************************************
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 05/05/2009
*****************************************************************************/
#ifndef __UDT_BUFFER_H__
#define __UDT_BUFFER_H__
#include "udt.h"
#include "list.h"
#include "queue.h"
#include <fstream>
class CSndBuffer
{
public:
CSndBuffer(int size = 32, int mss = 1500);
~CSndBuffer();
// Functionality:
// Insert a user buffer into the sending list.
// Parameters:
// 0) [in] data: pointer to the user data block.
// 1) [in] len: size of the block.
// 2) [in] ttl: time to live in milliseconds
// 3) [in] order: if the block should be delivered in order, for DGRAM only
// Returned value:
// None.
void addBuffer(const char* data, int len, int ttl = -1, bool order = false);
// Functionality:
// Read a block of data from file and insert it into the sending list.
// Parameters:
// 0) [in] ifs: input file stream.
// 1) [in] len: size of the block.
// Returned value:
// actual size of data added from the file.
int addBufferFromFile(std::fstream& ifs, int len);
// Functionality:
// Find data position to pack a DATA packet from the furthest reading point.
// Parameters:
// 0) [out] data: the pointer to the data position.
// 1) [out] msgno: message number of the packet.
// Returned value:
// Actual length of data read.
int readData(char** data, int32_t& msgno);
// Functionality:
// Find data position to pack a DATA packet for a retransmission.
// Parameters:
// 0) [out] data: the pointer to the data position.
// 1) [in] offset: offset from the last ACK point.
// 2) [out] msgno: message number of the packet.
// 3) [out] msglen: length of the message
// Returned value:
// Actual length of data read.
int readData(char** data, const int offset, int32_t& msgno, int& msglen);
// Functionality:
// Update the ACK point and may release/unmap/return the user data according to the flag.
// Parameters:
// 0) [in] offset: number of packets acknowledged.
// Returned value:
// None.
void ackData(int offset);
// Functionality:
// Read size of data still in the sending list.
// Parameters:
// None.
// Returned value:
// Current size of the data in the sending list.
int getCurrBufSize() const;
private:
void increase();
private:
udt_pthread_mutex_t m_BufLock; // used to synchronize buffer operation
struct Block
{
char* m_pcData; // pointer to the data block
int m_iLength; // length of the block
int32_t m_iMsgNo; // message number
uint64_t m_OriginTime; // original request time
int m_iTTL; // time to live (milliseconds)
Block* m_pNext; // next block
} *m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock;
// m_pBlock: The head pointer
// m_pFirstBlock: The first block
// m_pCurrBlock: The current block
// m_pLastBlock: The last block (if first == last, buffer is empty)
struct Buffer
{
char* m_pcData; // buffer
int m_iSize; // size
Buffer* m_pNext; // next buffer
} *m_pBuffer; // physical buffer
int32_t m_iNextMsgNo; // next message number
int m_iSize; // buffer size (number of packets)
int m_iMSS; // maximum seqment/packet size
int m_iCount; // number of used blocks
private:
CSndBuffer(const CSndBuffer&);
CSndBuffer& operator=(const CSndBuffer&);
};
////////////////////////////////////////////////////////////////////////////////
class CRcvBuffer
{
public:
CRcvBuffer(CUnitQueue* queue, int bufsize = 65536);
~CRcvBuffer();
// Functionality:
// Write data into the buffer.
// Parameters:
// 0) [in] unit: pointer to a data unit containing new packet
// 1) [in] offset: offset from last ACK point.
// Returned value:
// 0 is success, -1 if data is repeated.
int addData(CUnit* unit, int offset);
// Functionality:
// Read data into a user buffer.
// Parameters:
// 0) [in] data: pointer to user buffer.
// 1) [in] len: length of user buffer.
// Returned value:
// size of data read.
int readBuffer(char* data, int len);
// Functionality:
// Read data directly into file.
// Parameters:
// 0) [in] file: C++ file stream.
// 1) [in] len: expected length of data to write into the file.
// Returned value:
// size of data read.
int readBufferToFile(std::fstream& ofs, int len);
// Functionality:
// Update the ACK point of the buffer.
// Parameters:
// 0) [in] len: size of data to be acknowledged.
// Returned value:
// 1 if a user buffer is fulfilled, otherwise 0.
void ackData(int len);
// Functionality:
// Query how many buffer space left for data receiving.
// Parameters:
// None.
// Returned value:
// size of available buffer space (including user buffer) for data receiving.
int getAvailBufSize() const;
// Functionality:
// Query how many data has been continuously received (for reading).
// Parameters:
// None.
// Returned value:
// size of valid (continous) data for reading.
int getRcvDataSize() const;
// Functionality:
// mark the message to be dropped from the message list.
// Parameters:
// 0) [in] msgno: message nuumer.
// Returned value:
// None.
void dropMsg(int32_t msgno);
// Functionality:
// read a message.
// Parameters:
// 0) [out] data: buffer to write the message into.
// 1) [in] len: size of the buffer.
// Returned value:
// actuall size of data read.
int readMsg(char* data, int len);
// Functionality:
// Query how many messages are available now.
// Parameters:
// None.
// Returned value:
// number of messages available for recvmsg.
int getRcvMsgNum();
private:
bool scanMsg(int& start, int& end, bool& passack);
private:
CUnit** m_pUnit; // pointer to the protocol buffer
int m_iSize; // size of the protocol buffer
CUnitQueue* m_pUnitQueue; // the shared unit queue
int m_iStartPos; // the head position for I/O (inclusive)
int m_iLastAckPos; // the last ACKed position (exclusive)
// EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1
int m_iMaxPos; // the furthest data position
int m_iNotch; // the starting read point of the first unit
private:
CRcvBuffer();
CRcvBuffer(const CRcvBuffer&);
CRcvBuffer& operator=(const CRcvBuffer&);
};
#endif

121
src/cache.cpp Normal file
View File

@ -0,0 +1,121 @@
/*****************************************************************************
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 05/05/2009
*****************************************************************************/
#ifdef WINDOWS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#endif
#include <cstring>
#include "cache.h"
#include "core.h"
using namespace std;
CInfoBlock& CInfoBlock::operator=(const CInfoBlock& obj)
{
std::copy(obj.m_piIP, obj.m_piIP + 3, m_piIP);
m_iIPversion = obj.m_iIPversion;
m_ullTimeStamp = obj.m_ullTimeStamp;
m_iRTT = obj.m_iRTT;
m_iBandwidth = obj.m_iBandwidth;
m_iLossRate = obj.m_iLossRate;
m_iReorderDistance = obj.m_iReorderDistance;
m_dInterval = obj.m_dInterval;
m_dCWnd = obj.m_dCWnd;
return *this;
}
bool CInfoBlock::operator==(const CInfoBlock& obj)
{
if (m_iIPversion != obj.m_iIPversion)
return false;
else if (m_iIPversion == AF_INET)
return (m_piIP[0] == obj.m_piIP[0]);
for (int i = 0; i < 4; ++ i)
{
if (m_piIP[i] != obj.m_piIP[i])
return false;
}
return true;
}
CInfoBlock* CInfoBlock::clone()
{
CInfoBlock* obj = new CInfoBlock;
std::copy(m_piIP, m_piIP + 3, obj->m_piIP);
obj->m_iIPversion = m_iIPversion;
obj->m_ullTimeStamp = m_ullTimeStamp;
obj->m_iRTT = m_iRTT;
obj->m_iBandwidth = m_iBandwidth;
obj->m_iLossRate = m_iLossRate;
obj->m_iReorderDistance = m_iReorderDistance;
obj->m_dInterval = m_dInterval;
obj->m_dCWnd = m_dCWnd;
return obj;
}
int CInfoBlock::getKey()
{
if (m_iIPversion == AF_INET)
return m_piIP[0];
return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3];
}
void CInfoBlock::convert(const sockaddr* addr, int ver, uint32_t ip[])
{
if (ver == AF_INET)
{
ip[0] = ((sockaddr_in*)addr)->sin_addr.s_addr;
ip[1] = ip[2] = ip[3] = 0;
}
else
{
memcpy((char*)ip, (char*)((sockaddr_in6*)addr)->sin6_addr.s6_addr, 16);
}
}

293
src/cache.h Normal file
View File

@ -0,0 +1,293 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/27/2011
*****************************************************************************/
#ifndef __UDT_CACHE_H__
#define __UDT_CACHE_H__
#include <list>
#include <vector>
#include "udtCommon.h"
#include "udt.h"
class CCacheItem
{
public:
virtual ~CCacheItem() {}
public:
virtual CCacheItem& operator=(const CCacheItem&) = 0;
// The "==" operator SHOULD only compare key values.
virtual bool operator==(const CCacheItem&) = 0;
// Functionality:
// get a deep copy clone of the current item
// Parameters:
// None.
// Returned value:
// Pointer to the new item, or NULL if failed.
virtual CCacheItem* clone() = 0;
// Functionality:
// get a random key value between 0 and MAX_INT to be used for the hash in cache
// Parameters:
// None.
// Returned value:
// A random hash key.
virtual int getKey() = 0;
// If there is any shared resources between the cache item and its clone,
// the shared resource should be released by this function.
virtual void release() {}
};
template<typename T> class CCache
{
public:
CCache(int size = 1024):
m_iMaxSize(size),
m_iHashSize(size * 3),
m_iCurrSize(0)
{
m_vHashPtr.resize(m_iHashSize);
CGuard::createMutex(m_Lock);
}
~CCache()
{
clear();
CGuard::releaseMutex(m_Lock);
}
public:
// Functionality:
// find the matching item in the cache.
// Parameters:
// 0) [in/out] data: storage for the retrieved item; initially it must carry the key information
// Returned value:
// 0 if found a match, otherwise -1.
int lookup(T* data)
{
CGuard cacheguard(m_Lock);
int key = data->getKey();
if (key < 0)
return -1;
if (key >= m_iMaxSize)
key %= m_iHashSize;
const ItemPtrList& item_list = m_vHashPtr[key];
for (typename ItemPtrList::const_iterator i = item_list.begin(); i != item_list.end(); ++ i)
{
if (*data == ***i)
{
// copy the cached info
*data = ***i;
return 0;
}
}
return -1;
}
// Functionality:
// update an item in the cache, or insert one if it doesn't exist; oldest item may be removed
// Parameters:
// 0) [in] data: the new item to updated/inserted to the cache
// Returned value:
// 0 if success, otherwise -1.
int update(T* data)
{
CGuard cacheguard(m_Lock);
int key = data->getKey();
if (key < 0)
return -1;
if (key >= m_iMaxSize)
key %= m_iHashSize;
T* curr = NULL;
ItemPtrList& item_list = m_vHashPtr[key];
for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i)
{
if (*data == ***i)
{
// update the existing entry with the new value
***i = *data;
curr = **i;
// remove the current entry
m_StorageList.erase(*i);
item_list.erase(i);
// re-insert to the front
m_StorageList.push_front(curr);
item_list.push_front(m_StorageList.begin());
return 0;
}
}
// create new entry and insert to front
curr = data->clone();
m_StorageList.push_front(curr);
item_list.push_front(m_StorageList.begin());
++ m_iCurrSize;
if (m_iCurrSize >= m_iMaxSize)
{
// Cache overflow, remove oldest entry.
T* last_data = m_StorageList.back();
int last_key = last_data->getKey() % m_iHashSize;
item_list = m_vHashPtr[last_key];
for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i)
{
if (*last_data == ***i)
{
item_list.erase(i);
break;
}
}
last_data->release();
delete last_data;
m_StorageList.pop_back();
-- m_iCurrSize;
}
return 0;
}
// Functionality:
// Specify the cache size (i.e., max number of items).
// Parameters:
// 0) [in] size: max cache size.
// Returned value:
// None.
void setSizeLimit(int size)
{
m_iMaxSize = size;
m_iHashSize = size * 3;
m_vHashPtr.resize(m_iHashSize);
}
// Functionality:
// Clear all entries in the cache, restore to initialization state.
// Parameters:
// None.
// Returned value:
// None.
void clear()
{
for (typename std::list<T*>::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i)
{
(*i)->release();
delete *i;
}
m_StorageList.clear();
for (typename std::vector<ItemPtrList>::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i)
i->clear();
m_iCurrSize = 0;
}
private:
std::list<T*> m_StorageList;
typedef typename std::list<T*>::iterator ItemPtr;
typedef std::list<ItemPtr> ItemPtrList;
std::vector<ItemPtrList> m_vHashPtr;
int m_iMaxSize;
int m_iHashSize;
int m_iCurrSize;
udt_pthread_mutex_t m_Lock;
private:
CCache(const CCache&);
CCache& operator=(const CCache&);
};
class CInfoBlock
{
public:
uint32_t m_piIP[4]; // IP address, machine read only, not human readable format
int m_iIPversion; // IP version
uint64_t m_ullTimeStamp; // last update time
int m_iRTT; // RTT
int m_iBandwidth; // estimated bandwidth
int m_iLossRate; // average loss rate
int m_iReorderDistance; // packet reordering distance
double m_dInterval; // inter-packet time, congestion control
double m_dCWnd; // congestion window size, congestion control
public:
virtual ~CInfoBlock() {}
virtual CInfoBlock& operator=(const CInfoBlock& obj);
virtual bool operator==(const CInfoBlock& obj);
virtual CInfoBlock* clone();
virtual int getKey();
virtual void release() {}
public:
// Functionality:
// convert sockaddr structure to an integer array
// Parameters:
// 0) [in] addr: network address
// 1) [in] ver: IP version
// 2) [out] ip: the result machine readable IP address in integer array
// Returned value:
// None.
static void convert(const sockaddr* addr, int ver, uint32_t ip[]);
};
#endif

314
src/ccc.cpp Normal file
View File

@ -0,0 +1,314 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 02/28/2012
*****************************************************************************/
#include "core.h"
#include "ccc.h"
#include <cmath>
#include <cstring>
CCC::CCC():
m_iSYNInterval(CUDT::m_iSYNInterval),
m_dPktSndPeriod(1.0),
m_dCWndSize(16.0),
m_iBandwidth(),
m_dMaxCWndSize(),
m_iMSS(),
m_iSndCurrSeqNo(),
m_iRcvRate(),
m_iRTT(),
m_pcParam(NULL),
m_iPSize(0),
m_UDT(),
m_iACKPeriod(0),
m_iACKInterval(0),
m_bUserDefinedRTO(false),
m_iRTO(-1),
m_PerfInfo()
{
}
CCC::~CCC()
{
delete [] m_pcParam;
}
void CCC::setACKTimer(int msINT)
{
m_iACKPeriod = msINT > m_iSYNInterval ? m_iSYNInterval : msINT;
}
void CCC::setACKInterval(int pktINT)
{
m_iACKInterval = pktINT;
}
void CCC::setRTO(int usRTO)
{
m_bUserDefinedRTO = true;
m_iRTO = usRTO;
}
void CCC::sendCustomMsg(CPacket& pkt) const
{
CUDT* u = CUDT::getUDTHandle(m_UDT);
if (NULL != u)
{
pkt.m_iID = u->m_PeerID;
u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt);
}
}
const CPerfMon* CCC::getPerfInfo()
{
try
{
CUDT* u = CUDT::getUDTHandle(m_UDT);
if (NULL != u)
u->sample(&m_PerfInfo, false);
}
catch (...)
{
return NULL;
}
return &m_PerfInfo;
}
void CCC::setMSS(int mss)
{
m_iMSS = mss;
}
void CCC::setBandwidth(int bw)
{
m_iBandwidth = bw;
}
void CCC::setSndCurrSeqNo(int32_t seqno)
{
m_iSndCurrSeqNo = seqno;
}
void CCC::setRcvRate(int rcvrate)
{
m_iRcvRate = rcvrate;
}
void CCC::setMaxCWndSize(int cwnd)
{
m_dMaxCWndSize = cwnd;
}
void CCC::setRTT(int rtt)
{
m_iRTT = rtt;
}
void CCC::setUserParam(const char* param, int size)
{
delete [] m_pcParam;
m_pcParam = new char[size];
memcpy(m_pcParam, param, size);
m_iPSize = size;
}
//
CUDTCC::CUDTCC():
m_iRCInterval(),
m_LastRCTime(),
m_bSlowStart(),
m_iLastAck(),
m_bLoss(),
m_iLastDecSeq(),
m_dLastDecPeriod(),
m_iNAKCount(),
m_iDecRandom(),
m_iAvgNAKNum(),
m_iDecCount()
{
}
void CUDTCC::init()
{
m_iRCInterval = m_iSYNInterval;
m_LastRCTime = CTimer::getTime();
setACKTimer(m_iRCInterval);
m_bSlowStart = true;
m_iLastAck = m_iSndCurrSeqNo;
m_bLoss = false;
m_iLastDecSeq = CSeqNo::decseq(m_iLastAck);
m_dLastDecPeriod = 1;
m_iAvgNAKNum = 0;
m_iNAKCount = 0;
m_iDecRandom = 1;
m_dCWndSize = 16;
m_dPktSndPeriod = 1;
}
void CUDTCC::onACK(int32_t ack)
{
int64_t B = 0;
double inc = 0;
// Note: 1/24/2012
// The minimum increase parameter is increased from "1.0 / m_iMSS" to 0.01
// because the original was too small and caused sending rate to stay at low level
// for long time.
const double min_inc = 0.01;
uint64_t currtime = CTimer::getTime();
if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval)
return;
m_LastRCTime = currtime;
if (m_bSlowStart)
{
m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack);
m_iLastAck = ack;
if (m_dCWndSize > m_dMaxCWndSize)
{
m_bSlowStart = false;
if (m_iRcvRate > 0)
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
else
m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
}
}
else
m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16;
// During Slow Start, no rate increase
if (m_bSlowStart)
return;
if (m_bLoss)
{
m_bLoss = false;
return;
}
B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod);
if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B))
B = m_iBandwidth / 9;
if (B <= 0)
inc = min_inc;
else
{
// inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS)
// Beta = 1.5 * 10^(-6)
inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS;
if (inc < min_inc)
inc = min_inc;
}
m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc + m_iRCInterval);
}
void CUDTCC::onLoss(const int32_t* losslist, int)
{
//Slow Start stopped, if it hasn't yet
if (m_bSlowStart)
{
m_bSlowStart = false;
if (m_iRcvRate > 0)
{
// Set the sending rate to the receiving rate.
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
return;
}
// If no receiving rate is observed, we have to compute the sending
// rate according to the current window size, and decrease it
// using the method below.
m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
}
m_bLoss = true;
if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0)
{
m_dLastDecPeriod = m_dPktSndPeriod;
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125);
m_iNAKCount = 1;
m_iDecCount = 1;
m_iLastDecSeq = m_iSndCurrSeqNo;
// remove global synchronization using randomization
srand(m_iLastDecSeq);
m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX));
if (m_iDecRandom < 1)
m_iDecRandom = 1;
}
else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom)))
{
// 0.875^5 = 0.51, rate should not be decreased by more than half within a congestion period
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
m_iLastDecSeq = m_iSndCurrSeqNo;
}
}
void CUDTCC::onTimeout()
{
if (m_bSlowStart)
{
m_bSlowStart = false;
if (m_iRcvRate > 0)
m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
else
m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
}
else
{
/*
m_dLastDecPeriod = m_dPktSndPeriod;
m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2);
m_iLastDecSeq = m_iLastAck;
*/
}
}

278
src/ccc.h Normal file
View File

@ -0,0 +1,278 @@
/*****************************************************************************
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 02/28/2012
*****************************************************************************/
#ifndef __UDT_CCC_H__
#define __UDT_CCC_H__
#include "udt.h"
#include "packet.h"
class UDT_API CCC
{
friend class CUDT;
public:
CCC();
virtual ~CCC();
private:
CCC(const CCC&);
CCC& operator=(const CCC&) {return *this;}
public:
// Functionality:
// Callback function to be called (only) at the start of a UDT connection.
// note that this is different from CCC(), which is always called.
// Parameters:
// None.
// Returned value:
// None.
virtual void init() {}
// Functionality:
// Callback function to be called when a UDT connection is closed.
// Parameters:
// None.
// Returned value:
// None.
virtual void close() {}
// Functionality:
// Callback function to be called when an ACK packet is received.
// Parameters:
// 0) [in] ackno: the data sequence number acknowledged by this ACK.
// Returned value:
// None.
virtual void onACK(int32_t) {}
// Functionality:
// Callback function to be called when a loss report is received.
// Parameters:
// 0) [in] losslist: list of sequence number of packets, in the format describled in packet.cpp.
// 1) [in] size: length of the loss list.
// Returned value:
// None.
virtual void onLoss(const int32_t*, int) {}
// Functionality:
// Callback function to be called when a timeout event occurs.
// Parameters:
// None.
// Returned value:
// None.
virtual void onTimeout() {}
// Functionality:
// Callback function to be called when a data is sent.
// Parameters:
// 0) [in] seqno: the data sequence number.
// 1) [in] size: the payload size.
// Returned value:
// None.
virtual void onPktSent(const CPacket*) {}
// Functionality:
// Callback function to be called when a data is received.
// Parameters:
// 0) [in] seqno: the data sequence number.
// 1) [in] size: the payload size.
// Returned value:
// None.
virtual void onPktReceived(const CPacket*) {}
// Functionality:
// Callback function to Process a user defined packet.
// Parameters:
// 0) [in] pkt: the user defined packet.
// Returned value:
// None.
virtual void processCustomMsg(const CPacket*) {}
protected:
// Functionality:
// Set periodical acknowldging and the ACK period.
// Parameters:
// 0) [in] msINT: the period to send an ACK.
// Returned value:
// None.
void setACKTimer(int msINT);
// Functionality:
// Set packet-based acknowldging and the number of packets to send an ACK.
// Parameters:
// 0) [in] pktINT: the number of packets to send an ACK.
// Returned value:
// None.
void setACKInterval(int pktINT);
// Functionality:
// Set RTO value.
// Parameters:
// 0) [in] msRTO: RTO in macroseconds.
// Returned value:
// None.
void setRTO(int usRTO);
// Functionality:
// Send a user defined control packet.
// Parameters:
// 0) [in] pkt: user defined packet.
// Returned value:
// None.
void sendCustomMsg(CPacket& pkt) const;
// Functionality:
// retrieve performance information.
// Parameters:
// None.
// Returned value:
// Pointer to a performance info structure.
const CPerfMon* getPerfInfo();
// Functionality:
// Set user defined parameters.
// Parameters:
// 0) [in] param: the paramters in one buffer.
// 1) [in] size: the size of the buffer.
// Returned value:
// None.
void setUserParam(const char* param, int size);
private:
void setMSS(int mss);
void setMaxCWndSize(int cwnd);
void setBandwidth(int bw);
void setSndCurrSeqNo(int32_t seqno);
void setRcvRate(int rcvrate);
void setRTT(int rtt);
protected:
const int32_t& m_iSYNInterval; // UDT constant parameter, SYN
double m_dPktSndPeriod; // Packet sending period, in microseconds
double m_dCWndSize; // Congestion window size, in packets
int m_iBandwidth; // estimated bandwidth, packets per second
double m_dMaxCWndSize; // maximum cwnd size, in packets
int m_iMSS; // Maximum Packet Size, including all packet headers
int32_t m_iSndCurrSeqNo; // current maximum seq no sent out
int m_iRcvRate; // packet arrive rate at receiver side, packets per second
int m_iRTT; // current estimated RTT, microsecond
char* m_pcParam; // user defined parameter
int m_iPSize; // size of m_pcParam
private:
UDTSOCKET m_UDT; // The UDT entity that this congestion control algorithm is bound to
int m_iACKPeriod; // Periodical timer to send an ACK, in milliseconds
int m_iACKInterval; // How many packets to send one ACK, in packets
bool m_bUserDefinedRTO; // if the RTO value is defined by users
int m_iRTO; // RTO value, microseconds
CPerfMon m_PerfInfo; // protocol statistics information
};
class CCCVirtualFactory
{
public:
virtual ~CCCVirtualFactory() {}
virtual CCC* create() = 0;
virtual CCCVirtualFactory* clone() = 0;
};
template <class T>
class CCCFactory: public CCCVirtualFactory
{
public:
virtual ~CCCFactory() {}
virtual CCC* create() {return new T;}
virtual CCCVirtualFactory* clone() {return new CCCFactory<T>;}
};
class CUDTCC: public CCC
{
public:
CUDTCC();
public:
virtual void init();
virtual void onACK(int32_t);
virtual void onLoss(const int32_t*, int);
virtual void onTimeout();
private:
int m_iRCInterval; // UDT Rate control interval
uint64_t m_LastRCTime; // last rate increase time
bool m_bSlowStart; // if in slow start phase
int32_t m_iLastAck; // last ACKed seq no
bool m_bLoss; // if loss happened since last rate increase
int32_t m_iLastDecSeq; // max pkt seq no sent out when last decrease happened
double m_dLastDecPeriod; // value of pktsndperiod when last decrease happened
int m_iNAKCount; // NAK counter
int m_iDecRandom; // random threshold on decrease by number of loss events
int m_iAvgNAKNum; // average number of NAKs per congestion
int m_iDecCount; // number of decreases in a congestion epoch
};
#endif

338
src/channel.cpp Normal file
View File

@ -0,0 +1,338 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
****************************************************************************/
/****************************************************************************
written by
Yunhong Gu, last updated 01/27/2011
*****************************************************************************/
#ifndef WINDOWS
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <cstdio>
#include <cerrno>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#endif
#include "channel.h"
#include "packet.h"
#ifdef WINDOWS
#define socklen_t int
#endif
#ifndef WINDOWS
#define NET_ERROR errno
#else
#define NET_ERROR WSAGetLastError()
#endif
CChannel::CChannel():
m_iIPversion(AF_INET),
m_iSockAddrSize(sizeof(sockaddr_in)),
m_iSocket(),
m_iSndBufSize(65536),
m_iRcvBufSize(65536)
{
}
CChannel::CChannel(int version):
m_iIPversion(version),
m_iSocket(),
m_iSndBufSize(65536),
m_iRcvBufSize(65536)
{
m_iSockAddrSize = (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
}
CChannel::~CChannel()
{
}
void CChannel::open(const sockaddr* addr)
{
// construct an socket
m_iSocket = ::socket(m_iIPversion, SOCK_DGRAM, 0);
#ifdef WINDOWS
if (INVALID_SOCKET == m_iSocket)
#else
if (m_iSocket < 0)
#endif
throw CUDTException(1, 0, NET_ERROR);
if (NULL != addr)
{
socklen_t namelen = m_iSockAddrSize;
if (0 != ::bind(m_iSocket, addr, namelen))
throw CUDTException(1, 3, NET_ERROR);
}
else
{
//sendto or WSASendTo will also automatically bind the socket
addrinfo hints;
addrinfo* res;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = m_iIPversion;
hints.ai_socktype = SOCK_DGRAM;
if (0 != ::getaddrinfo(NULL, "0", &hints, &res))
throw CUDTException(1, 3, NET_ERROR);
if (0 != ::bind(m_iSocket, res->ai_addr, res->ai_addrlen))
throw CUDTException(1, 3, NET_ERROR);
::freeaddrinfo(res);
}
setUDPSockOpt();
}
void CChannel::open(UDPSOCKET udpsock)
{
m_iSocket = udpsock;
setUDPSockOpt();
}
void CChannel::setUDPSockOpt()
{
#if defined(BSD) || defined(MACOSX)
// BSD system will fail setsockopt if the requested buffer size exceeds system maximum value
int maxsize = 64000;
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int)))
::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&maxsize, sizeof(int));
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int)))
::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&maxsize, sizeof(int));
#else
// for other systems, if requested is greated than maximum, the maximum value will be automactally used
if ((0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int))) ||
(0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int))))
throw CUDTException(1, 3, NET_ERROR);
#endif
timeval tv;
tv.tv_sec = 0;
#if defined (BSD) || defined (MACOSX)
// Known BSD bug as the day I wrote this code.
// A small time out value will cause the socket to block forever.
tv.tv_usec = 10000;
#else
tv.tv_usec = 100;
#endif
#ifdef UNIX
// Set non-blocking I/O
// UNIX does not support SO_RCVTIMEO
int opts = ::fcntl(m_iSocket, F_GETFL);
if (-1 == ::fcntl(m_iSocket, F_SETFL, opts | O_NONBLOCK))
throw CUDTException(1, 3, NET_ERROR);
#elif WINDOWS
DWORD ot = 1; //milliseconds
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&ot, sizeof(DWORD)))
throw CUDTException(1, 3, NET_ERROR);
#else
// Set receiving time-out value
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(timeval)))
throw CUDTException(1, 3, NET_ERROR);
#endif
}
void CChannel::close() const
{
#ifndef WINDOWS
::close(m_iSocket);
#else
::closesocket(m_iSocket);
#endif
}
int CChannel::getSndBufSize()
{
socklen_t size = sizeof(socklen_t);
::getsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char *)&m_iSndBufSize, &size);
return m_iSndBufSize;
}
int CChannel::getRcvBufSize()
{
socklen_t size = sizeof(socklen_t);
::getsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char *)&m_iRcvBufSize, &size);
return m_iRcvBufSize;
}
void CChannel::setSndBufSize(int size)
{
m_iSndBufSize = size;
}
void CChannel::setRcvBufSize(int size)
{
m_iRcvBufSize = size;
}
void CChannel::getSockAddr(sockaddr* addr) const
{
socklen_t namelen = m_iSockAddrSize;
::getsockname(m_iSocket, addr, &namelen);
}
void CChannel::getPeerAddr(sockaddr* addr) const
{
socklen_t namelen = m_iSockAddrSize;
::getpeername(m_iSocket, addr, &namelen);
}
int CChannel::sendto(const sockaddr* addr, CPacket& packet) const
{
// convert control information into network order
if (packet.getFlag())
for (int i = 0, n = packet.getLength() / 4; i < n; ++ i)
*((uint32_t *)packet.m_pcData + i) = htonl(*((uint32_t *)packet.m_pcData + i));
// convert packet header into network order
//for (int j = 0; j < 4; ++ j)
// packet.m_nHeader[j] = htonl(packet.m_nHeader[j]);
uint32_t* p = packet.m_nHeader;
for (int j = 0; j < 4; ++ j)
{
*p = htonl(*p);
++ p;
}
#ifndef WINDOWS
msghdr mh;
mh.msg_name = (sockaddr*)addr;
mh.msg_namelen = m_iSockAddrSize;
mh.msg_iov = (iovec*)packet.m_PacketVector;
mh.msg_iovlen = 2;
mh.msg_control = NULL;
mh.msg_controllen = 0;
mh.msg_flags = 0;
int res = ::sendmsg(m_iSocket, &mh, 0);
#else
DWORD size = CPacket::m_iPktHdrSize + packet.getLength();
int addrsize = m_iSockAddrSize;
int res = ::WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr, addrsize, NULL, NULL);
res = (0 == res) ? size : -1;
#endif
// convert back into local host order
//for (int k = 0; k < 4; ++ k)
// packet.m_nHeader[k] = ntohl(packet.m_nHeader[k]);
p = packet.m_nHeader;
for (int k = 0; k < 4; ++ k)
{
*p = ntohl(*p);
++ p;
}
if (packet.getFlag())
{
for (int l = 0, n = packet.getLength() / 4; l < n; ++ l)
*((uint32_t *)packet.m_pcData + l) = ntohl(*((uint32_t *)packet.m_pcData + l));
}
return res;
}
int CChannel::recvfrom(sockaddr* addr, CPacket& packet) const
{
#ifndef WINDOWS
msghdr mh;
mh.msg_name = addr;
mh.msg_namelen = m_iSockAddrSize;
mh.msg_iov = packet.m_PacketVector;
mh.msg_iovlen = 2;
mh.msg_control = NULL;
mh.msg_controllen = 0;
mh.msg_flags = 0;
#ifdef UNIX
fd_set set;
timeval tv;
FD_ZERO(&set);
FD_SET(m_iSocket, &set);
tv.tv_sec = 0;
tv.tv_usec = 10000;
::select(m_iSocket+1, &set, NULL, &set, &tv);
#endif
int res = ::recvmsg(m_iSocket, &mh, 0);
#else
DWORD size = CPacket::m_iPktHdrSize + packet.getLength();
DWORD flag = 0;
int addrsize = m_iSockAddrSize;
int res = ::WSARecvFrom(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, &flag, addr, &addrsize, NULL, NULL);
res = (0 == res) ? size : -1;
#endif
if (res <= 0)
{
packet.setLength(-1);
return -1;
}
packet.setLength(res - CPacket::m_iPktHdrSize);
// convert back into local host order
//for (int i = 0; i < 4; ++ i)
// packet.m_nHeader[i] = ntohl(packet.m_nHeader[i]);
uint32_t* p = packet.m_nHeader;
for (int i = 0; i < 4; ++ i)
{
*p = ntohl(*p);
++ p;
}
if (packet.getFlag())
{
for (int j = 0, n = packet.getLength() / 4; j < n; ++ j)
*((uint32_t *)packet.m_pcData + j) = ntohl(*((uint32_t *)packet.m_pcData + j));
}
return packet.getLength();
}

171
src/channel.h Normal file
View File

@ -0,0 +1,171 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/27/2011
*****************************************************************************/
#ifndef __UDT_CHANNEL_H__
#define __UDT_CHANNEL_H__
#include "udt.h"
#include "packet.h"
class CChannel
{
public:
CChannel();
CChannel(int version);
~CChannel();
// Functionality:
// Open a UDP channel.
// Parameters:
// 0) [in] addr: The local address that UDP will use.
// Returned value:
// None.
void open(const sockaddr* addr = NULL);
// Functionality:
// Open a UDP channel based on an existing UDP socket.
// Parameters:
// 0) [in] udpsock: UDP socket descriptor.
// Returned value:
// None.
void open(UDPSOCKET udpsock);
// Functionality:
// Disconnect and close the UDP entity.
// Parameters:
// None.
// Returned value:
// None.
void close() const;
// Functionality:
// Get the UDP sending buffer size.
// Parameters:
// None.
// Returned value:
// Current UDP sending buffer size.
int getSndBufSize();
// Functionality:
// Get the UDP receiving buffer size.
// Parameters:
// None.
// Returned value:
// Current UDP receiving buffer size.
int getRcvBufSize();
// Functionality:
// Set the UDP sending buffer size.
// Parameters:
// 0) [in] size: expected UDP sending buffer size.
// Returned value:
// None.
void setSndBufSize(int size);
// Functionality:
// Set the UDP receiving buffer size.
// Parameters:
// 0) [in] size: expected UDP receiving buffer size.
// Returned value:
// None.
void setRcvBufSize(int size);
// Functionality:
// Query the socket address that the channel is using.
// Parameters:
// 0) [out] addr: pointer to store the returned socket address.
// Returned value:
// None.
void getSockAddr(sockaddr* addr) const;
// Functionality:
// Query the peer side socket address that the channel is connect to.
// Parameters:
// 0) [out] addr: pointer to store the returned socket address.
// Returned value:
// None.
void getPeerAddr(sockaddr* addr) const;
// Functionality:
// Send a packet to the given address.
// Parameters:
// 0) [in] addr: pointer to the destination address.
// 1) [in] packet: reference to a CPacket entity.
// Returned value:
// Actual size of data sent.
int sendto(const sockaddr* addr, CPacket& packet) const;
// Functionality:
// Receive a packet from the channel and record the source address.
// Parameters:
// 0) [in] addr: pointer to the source address.
// 1) [in] packet: reference to a CPacket entity.
// Returned value:
// Actual size of data received.
int recvfrom(sockaddr* addr, CPacket& packet) const;
private:
void setUDPSockOpt();
private:
int m_iIPversion; // IP version
int m_iSockAddrSize; // socket address structure size (pre-defined to avoid run-time test)
UDPSOCKET m_iSocket; // socket descriptor
int m_iSndBufSize; // UDP sending buffer size
int m_iRcvBufSize; // UDP receiving buffer size
};
#endif

2677
src/core.cpp Normal file

File diff suppressed because it is too large Load Diff

463
src/core.h Normal file
View File

@ -0,0 +1,463 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 02/28/2012
*****************************************************************************/
#ifndef __UDT_CORE_H__
#define __UDT_CORE_H__
#include "udt.h"
#include "udtCommon.h"
#include "list.h"
#include "buffer.h"
#include "window.h"
#include "packet.h"
#include "channel.h"
#include "api.h"
#include "ccc.h"
#include "cache.h"
#include "queue.h"
enum UDTSockType {UDT_STREAM = 1, UDT_DGRAM};
class CUDT
{
friend class CUDTSocket;
friend class CUDTUnited;
friend class CCC;
friend struct CUDTComp;
friend class CCache<CInfoBlock>;
friend class CRendezvousQueue;
friend class CSndQueue;
friend class CRcvQueue;
friend class CSndUList;
friend class CRcvUList;
private: // constructor and desctructor
CUDT();
CUDT(const CUDT& ancestor);
const CUDT& operator=(const CUDT&) {return *this;}
~CUDT();
public: //API
static int startup();
static int cleanup();
static UDTSOCKET socket(int af, int type = SOCK_STREAM, int protocol = 0);
static int bind(UDTSOCKET u, const sockaddr* name, int namelen);
static int bind(UDTSOCKET u, UDPSOCKET udpsock);
static int listen(UDTSOCKET u, int backlog);
static UDTSOCKET accept(UDTSOCKET u, sockaddr* addr, int* addrlen);
static int connect(UDTSOCKET u, const sockaddr* name, int namelen);
static int close(UDTSOCKET u);
static int getpeername(UDTSOCKET u, sockaddr* name, int* namelen);
static int getsockname(UDTSOCKET u, sockaddr* name, int* namelen);
static int getsockopt(UDTSOCKET u, int level, UDTOpt optname, void* optval, int* optlen);
static int setsockopt(UDTSOCKET u, int level, UDTOpt optname, const void* optval, int optlen);
static int send(UDTSOCKET u, const char* buf, int len, int flags);
static int recv(UDTSOCKET u, char* buf, int len, int flags);
static int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false);
static int recvmsg(UDTSOCKET u, char* buf, int len);
static int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000);
static int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000);
static int select(int nfds, ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout);
static int selectEx(const std::vector<UDTSOCKET>& fds, std::vector<UDTSOCKET>* readfds, std::vector<UDTSOCKET>* writefds, std::vector<UDTSOCKET>* exceptfds, int64_t msTimeOut);
static int epoll_create();
static int epoll_add_usock(const int eid, const UDTSOCKET u, const int* events = NULL);
static int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL);
static int epoll_remove_usock(const int eid, const UDTSOCKET u);
static int epoll_remove_ssock(const int eid, const SYSSOCKET s);
static int epoll_wait(const int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds = NULL, std::set<SYSSOCKET>* wrfds = NULL);
static int epoll_release(const int eid);
static CUDTException& getlasterror();
static int perfmon(UDTSOCKET u, CPerfMon* perf, bool clear = true);
static UDTSTATUS getsockstate(UDTSOCKET u);
// BARCHART
static int epoll_update_usock(const int eid, const UDTSOCKET u, const int* events = NULL);
// BARCHART
static int epoll_verify_usock(const int eid, const UDTSOCKET u, int* events);
public: // internal API
static CUDT* getUDTHandle(UDTSOCKET u);
private:
// Functionality:
// initialize a UDT entity and bind to a local address.
// Parameters:
// None.
// Returned value:
// None.
void open();
// Functionality:
// Start listening to any connection request.
// Parameters:
// None.
// Returned value:
// None.
void listen();
// Functionality:
// Connect to a UDT entity listening at address "peer".
// Parameters:
// 0) [in] peer: The address of the listening UDT entity.
// Returned value:
// None.
void connect(const sockaddr* peer);
// Functionality:
// Process the response handshake packet.
// Parameters:
// 0) [in] pkt: handshake packet.
// Returned value:
// Return 0 if connected, positive value if connection is in progress, otherwise error code.
int connect(const CPacket& pkt) throw ();
// Functionality:
// Connect to a UDT entity listening at address "peer", which has sent "hs" request.
// Parameters:
// 0) [in] peer: The address of the listening UDT entity.
// 1) [in/out] hs: The handshake information sent by the peer side (in), negotiated value (out).
// Returned value:
// None.
void connect(const sockaddr* peer, CHandShake* hs);
// Functionality:
// Close the opened UDT entity.
// Parameters:
// None.
// Returned value:
// None.
void close();
// Functionality:
// Request UDT to send out a data block "data" with size of "len".
// Parameters:
// 0) [in] data: The address of the application data to be sent.
// 1) [in] len: The size of the data block.
// Returned value:
// Actual size of data sent.
int send(const char* data, int len);
// Functionality:
// Request UDT to receive data to a memory block "data" with size of "len".
// Parameters:
// 0) [out] data: data received.
// 1) [in] len: The desired size of data to be received.
// Returned value:
// Actual size of data received.
int recv(char* data, int len);
// Functionality:
// send a message of a memory block "data" with size of "len".
// Parameters:
// 0) [out] data: data received.
// 1) [in] len: The desired size of data to be received.
// 2) [in] ttl: the time-to-live of the message.
// 3) [in] inorder: if the message should be delivered in order.
// Returned value:
// Actual size of data sent.
int sendmsg(const char* data, int len, int ttl, bool inorder);
// Functionality:
// Receive a message to buffer "data".
// Parameters:
// 0) [out] data: data received.
// 1) [in] len: size of the buffer.
// Returned value:
// Actual size of data received.
int recvmsg(char* data, int len);
// Functionality:
// Request UDT to send out a file described as "fd", starting from "offset", with size of "size".
// Parameters:
// 0) [in] ifs: The input file stream.
// 1) [in, out] offset: From where to read and send data; output is the new offset when the call returns.
// 2) [in] size: How many data to be sent.
// 3) [in] block: size of block per read from disk
// Returned value:
// Actual size of data sent.
int64_t sendfile(std::fstream& ifs, int64_t& offset, int64_t size, int block = 366000);
// Functionality:
// Request UDT to receive data into a file described as "fd", starting from "offset", with expected size of "size".
// Parameters:
// 0) [out] ofs: The output file stream.
// 1) [in, out] offset: From where to write data; output is the new offset when the call returns.
// 2) [in] size: How many data to be received.
// 3) [in] block: size of block per write to disk
// Returned value:
// Actual size of data received.
int64_t recvfile(std::fstream& ofs, int64_t& offset, int64_t size, int block = 7320000);
// Functionality:
// Configure UDT options.
// Parameters:
// 0) [in] optName: The enum name of a UDT option.
// 1) [in] optval: The value to be set.
// 2) [in] optlen: size of "optval".
// Returned value:
// None.
void setOpt(UDTOpt optName, const void* optval, int optlen);
// Functionality:
// Read UDT options.
// Parameters:
// 0) [in] optName: The enum name of a UDT option.
// 1) [in] optval: The value to be returned.
// 2) [out] optlen: size of "optval".
// Returned value:
// None.
void getOpt(UDTOpt optName, void* optval, int& optlen);
// Functionality:
// read the performance data since last sample() call.
// Parameters:
// 0) [in, out] perf: pointer to a CPerfMon structure to record the performance data.
// 1) [in] clear: flag to decide if the local performance trace should be cleared.
// Returned value:
// None.
void sample(CPerfMon* perf, bool clear = true);
private:
static CUDTUnited s_UDTUnited; // UDT global management base
public:
static const UDTSOCKET INVALID_SOCK; // invalid socket descriptor
static const int ERROR; // socket api error returned value
private: // Identification
UDTSOCKET m_SocketID; // UDT socket number
UDTSockType m_iSockType; // Type of the UDT connection (SOCK_STREAM or SOCK_DGRAM)
UDTSOCKET m_PeerID; // peer id, for multiplexer
static const int m_iVersion; // UDT version, for compatibility use
private: // Packet sizes
int m_iPktSize; // Maximum/regular packet size, in bytes
int m_iPayloadSize; // Maximum/regular payload size, in bytes
private: // Options
int m_iMSS; // Maximum Segment Size, in bytes
bool m_bSynSending; // Sending syncronization mode
bool m_bSynRecving; // Receiving syncronization mode
int m_iFlightFlagSize; // Maximum number of packets in flight from the peer side
int m_iSndBufSize; // Maximum UDT sender buffer size
int m_iRcvBufSize; // Maximum UDT receiver buffer size
linger m_Linger; // Linger information on close
int m_iUDPSndBufSize; // UDP sending buffer size
int m_iUDPRcvBufSize; // UDP receiving buffer size
int m_iIPversion; // IP version
bool m_bRendezvous; // Rendezvous connection mode
int m_iSndTimeOut; // sending timeout in milliseconds
int m_iRcvTimeOut; // receiving timeout in milliseconds
bool m_bReuseAddr; // reuse an exiting port or not, for UDP multiplexer
int64_t m_llMaxBW; // maximum data transfer rate (threshold)
private: // congestion control
CCCVirtualFactory* m_pCCFactory; // Factory class to create a specific CC instance
CCC* m_pCC; // congestion control class
CCache<CInfoBlock>* m_pCache; // network information cache
private: // Status
volatile bool m_bListening; // If the UDT entit is listening to connection
volatile bool m_bConnecting; // The short phase when connect() is called but not yet completed
volatile bool m_bConnected; // Whether the connection is on or off
volatile bool m_bClosing; // If the UDT entity is closing
volatile bool m_bShutdown; // If the peer side has shutdown the connection
volatile bool m_bBroken; // If the connection has been broken
volatile bool m_bPeerHealth; // If the peer status is normal
bool m_bOpened; // If the UDT entity has been opened
int m_iBrokenCounter; // a counter (number of GC checks) to let the GC tag this socket as disconnected
int m_iEXPCount; // Expiration counter
int m_iBandwidth; // Estimated bandwidth, number of packets per second
int m_iRTT; // RTT, in microseconds
int m_iRTTVar; // RTT variance
int m_iDeliveryRate; // Packet arrival rate at the receiver side
uint64_t m_ullLingerExpiration; // Linger expiration time (for GC to close a socket with data in sending buffer)
CHandShake m_ConnReq; // connection request
CHandShake m_ConnRes; // connection response
int64_t m_llLastReqTime; // last time when a connection request is sent
private: // Sending related data
CSndBuffer* m_pSndBuffer; // Sender buffer
CSndLossList* m_pSndLossList; // Sender loss list
CPktTimeWindow* m_pSndTimeWindow; // Packet sending time window
volatile uint64_t m_ullInterval; // Inter-packet time, in CPU clock cycles
uint64_t m_ullTimeDiff; // aggregate difference in inter-packet time
volatile int m_iFlowWindowSize; // Flow control window size
volatile double m_dCongestionWindow; // congestion window size
volatile int32_t m_iSndLastAck; // Last ACK received
volatile int32_t m_iSndLastDataAck; // The real last ACK that updates the sender buffer and loss list
volatile int32_t m_iSndCurrSeqNo; // The largest sequence number that has been sent
int32_t m_iLastDecSeq; // Sequence number sent last decrease occurs
int32_t m_iSndLastAck2; // Last ACK2 sent back
uint64_t m_ullSndLastAck2Time; // The time when last ACK2 was sent back
int32_t m_iISN; // Initial Sequence Number
void CCUpdate();
private: // Receiving related data
CRcvBuffer* m_pRcvBuffer; // Receiver buffer
CRcvLossList* m_pRcvLossList; // Receiver loss list
CACKWindow* m_pACKWindow; // ACK history window
CPktTimeWindow* m_pRcvTimeWindow; // Packet arrival time window
int32_t m_iRcvLastAck; // Last sent ACK
uint64_t m_ullLastAckTime; // Timestamp of last ACK
int32_t m_iRcvLastAckAck; // Last sent ACK that has been acknowledged
int32_t m_iAckSeqNo; // Last ACK sequence number
int32_t m_iRcvCurrSeqNo; // Largest received sequence number
uint64_t m_ullLastWarningTime; // Last time that a warning message is sent
int32_t m_iPeerISN; // Initial Sequence Number of the peer side
private: // synchronization: mutexes and conditions
udt_pthread_mutex_t m_ConnectionLock; // used to synchronize connection operation
udt_pthread_cond_t m_SendBlockCond; // used to block "send" call
udt_pthread_mutex_t m_SendBlockLock; // lock associated to m_SendBlockCond
udt_pthread_mutex_t m_AckLock; // used to protected sender's loss list when processing ACK
udt_pthread_cond_t m_RecvDataCond; // used to block "recv" when there is no data
udt_pthread_mutex_t m_RecvDataLock; // lock associated to m_RecvDataCond
udt_pthread_mutex_t m_SendLock; // used to synchronize "send" call
udt_pthread_mutex_t m_RecvLock; // used to synchronize "recv" call
void initSynch();
void destroySynch();
void releaseSynch();
private: // Generation and processing of packets
void sendCtrl(int pkttype, void* lparam = NULL, void* rparam = NULL, int size = 0);
void processCtrl(CPacket& ctrlpkt);
int packData(CPacket& packet, uint64_t& ts);
int processData(CUnit* unit);
int listen(sockaddr* addr, CPacket& packet);
private: // Trace
uint64_t m_StartTime; // timestamp when the UDT entity is started
int64_t m_llSentTotal; // total number of sent data packets, including retransmissions
int64_t m_llRecvTotal; // total number of received packets
int m_iSndLossTotal; // total number of lost packets (sender side)
int m_iRcvLossTotal; // total number of lost packets (receiver side)
int m_iRetransTotal; // total number of retransmitted packets
int m_iSentACKTotal; // total number of sent ACK packets
int m_iRecvACKTotal; // total number of received ACK packets
int m_iSentNAKTotal; // total number of sent NAK packets
int m_iRecvNAKTotal; // total number of received NAK packets
int64_t m_llSndDurationTotal; // total real time for sending
uint64_t m_LastSampleTime; // last performance sample time
int64_t m_llTraceSent; // number of pakctes sent in the last trace interval
int64_t m_llTraceRecv; // number of pakctes received in the last trace interval
int m_iTraceSndLoss; // number of lost packets in the last trace interval (sender side)
int m_iTraceRcvLoss; // number of lost packets in the last trace interval (receiver side)
int m_iTraceRetrans; // number of retransmitted packets in the last trace interval
int m_iSentACK; // number of ACKs sent in the last trace interval
int m_iRecvACK; // number of ACKs received in the last trace interval
int m_iSentNAK; // number of NAKs sent in the last trace interval
int m_iRecvNAK; // number of NAKs received in the last trace interval
int64_t m_llSndDuration; // real time for sending
int64_t m_llSndDurationCounter; // timers to record the sending duration
private: // Timers
uint64_t m_ullCPUFrequency; // CPU clock frequency, used for Timer, ticks per microsecond
static const int m_iSYNInterval; // Periodical Rate Control Interval, 10000 microsecond
static const int m_iSelfClockInterval; // ACK interval for self-clocking
uint64_t m_ullNextACKTime; // Next ACK time, in CPU clock cycles, same below
uint64_t m_ullNextNAKTime; // Next NAK time
volatile uint64_t m_ullSYNInt; // SYN interval
volatile uint64_t m_ullACKInt; // ACK interval
volatile uint64_t m_ullNAKInt; // NAK interval
volatile uint64_t m_ullLastRspTime; // time stamp of last response from the peer
uint64_t m_ullMinNakInt; // NAK timeout lower bound; too small value can cause unnecessary retransmission
uint64_t m_ullMinExpInt; // timeout lower bound threshold: too small timeout can cause problem
int m_iPktCount; // packet counter for ACK
int m_iLightACKCount; // light ACK counter
uint64_t m_ullTargetTime; // scheduled time of next packet sending
void checkTimers();
private: // for UDP multiplexer
CSndQueue* m_pSndQueue; // packet sending queue
CRcvQueue* m_pRcvQueue; // packet receiving queue
sockaddr* m_pPeerAddr; // peer address
uint32_t m_piSelfIP[4]; // local UDP IP address
CSNode* m_pSNode; // node information for UDT list used in snd queue
CRNode* m_pRNode; // node information for UDT list used in rcv queue
private: // for epoll
std::set<int> m_sPollID; // set of epoll ID to trigger
void addEPoll(const int eid);
void removeEPoll(const int eid);
};
#endif

427
src/epoll.cpp Normal file
View File

@ -0,0 +1,427 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/01/2011
*****************************************************************************/
#ifdef LINUX
#include <sys/epoll.h>
#include <unistd.h>
#endif
#include <algorithm>
#include <cerrno>
#include <cstring>
#include <iterator>
#include "udtCommon.h"
#include "epoll.h"
#include "udt.h"
using namespace std;
CEPoll::CEPoll():
m_iIDSeed(0)
{
CGuard::createMutex(m_EPollLock);
}
CEPoll::~CEPoll()
{
CGuard::releaseMutex(m_EPollLock);
}
int CEPoll::create()
{
CGuard pg(m_EPollLock);
int localid = 0;
#ifdef LINUX
localid = epoll_create(1024);
if (localid < 0)
throw CUDTException(-1, 0, errno);
#else
// on BSD, use kqueue
// on Solaris, use /dev/poll
// on Windows, select
#endif
if (++ m_iIDSeed >= 0x7FFFFFFF)
m_iIDSeed = 0;
CEPollDesc desc;
desc.m_iID = m_iIDSeed;
desc.m_iLocalID = localid;
m_mPolls[desc.m_iID] = desc;
return desc.m_iID;
}
int CEPoll::add_usock(const int eid, const UDTSOCKET& u, const int* events)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
if (p == m_mPolls.end())
throw CUDTException(5, 13);
// BARCHART: Manage all event types.
if (!events || (*events & UDT_EPOLL_IN))
p->second.m_sUDTSocksIn.insert(u);
if (!events || (*events & UDT_EPOLL_OUT))
p->second.m_sUDTSocksOut.insert(u);
if (!events || (*events & UDT_EPOLL_ERR))
p->second.m_sUDTSocksEx.insert(u);
return 0;
}
// BARCHART
int CEPoll::update_usock(const int eid, const UDTSOCKET& u, const int* events)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
if (p == m_mPolls.end()){
throw CUDTException(5, 13);
}
if(events){
if (*events & UDT_EPOLL_IN){
p->second.m_sUDTSocksIn.insert(u);
}else{
p->second.m_sUDTSocksIn.erase(u);
}
if (*events & UDT_EPOLL_OUT){
p->second.m_sUDTSocksOut.insert(u);
} else{
p->second.m_sUDTSocksOut.erase(u);
}
}
return 0;
}
// BARCHART
int CEPoll::verify_usock(const int eid, const UDTSOCKET& u, int* events)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
if (p == m_mPolls.end()){
throw CUDTException(5, 13);
}
if(events){
if(p->second.m_sUDTSocksIn.find(u) != p->second.m_sUDTSocksIn.end()){
*events |= UDT_EPOLL_IN;
}
if(p->second.m_sUDTSocksOut.find(u) != p->second.m_sUDTSocksOut.end()){
*events |= UDT_EPOLL_OUT;
}
}
return 0;
}
int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
if (p == m_mPolls.end())
throw CUDTException(5, 13);
#ifdef LINUX
epoll_event ev;
if (NULL == events)
ev.events = EPOLLIN | EPOLLOUT | EPOLLERR;
else
{
ev.events = 0;
if (*events & UDT_EPOLL_IN)
ev.events |= EPOLLIN;
if (*events & UDT_EPOLL_OUT)
ev.events |= EPOLLOUT;
if (*events & UDT_EPOLL_ERR)
ev.events |= EPOLLERR;
}
ev.data.fd = s;
if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_ADD, s, &ev) < 0)
throw CUDTException();
#endif
p->second.m_sLocals.insert(s);
return 0;
}
int CEPoll::remove_usock(const int eid, const UDTSOCKET& u)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
if (p == m_mPolls.end())
throw CUDTException(5, 13);
p->second.m_sUDTSocksIn.erase(u);
p->second.m_sUDTSocksOut.erase(u);
// when the socket is removed from a monitoring, it is not available anymore for any IO notification
p->second.m_sUDTReads.erase(u);
p->second.m_sUDTWrites.erase(u);
return 0;
}
int CEPoll::remove_ssock(const int eid, const SYSSOCKET& s)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
if (p == m_mPolls.end())
throw CUDTException(5, 13);
#ifdef LINUX
epoll_event ev; // ev is ignored, for compatibility with old Linux kernel only.
if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_DEL, s, &ev) < 0)
throw CUDTException();
#endif
p->second.m_sLocals.erase(s);
return 0;
}
int CEPoll::wait(const int eid, set<UDTSOCKET>* readfds, set<UDTSOCKET>* writefds, int64_t msTimeOut, set<SYSSOCKET>* lrfds, set<SYSSOCKET>* lwfds)
{
// if all fields is NULL and waiting time is infinite, then this would be a deadlock
if (!readfds && !writefds && !lrfds && lwfds && (msTimeOut < 0))
throw CUDTException(5, 3, 0);
// Clear these sets in case the app forget to do it.
if (readfds) readfds->clear();
if (writefds) writefds->clear();
if (lrfds) lrfds->clear();
if (lwfds) lwfds->clear();
int total = 0;
int64_t entertime = CTimer::getTime();
while (true)
{
CGuard::enterCS(m_EPollLock);
map<int, CEPollDesc>::iterator p = m_mPolls.find(eid);
if (p == m_mPolls.end())
{
CGuard::leaveCS(m_EPollLock);
throw CUDTException(5, 13);
}
if (p->second.m_sUDTSocksIn.empty() && p->second.m_sUDTSocksOut.empty() && p->second.m_sLocals.empty() && (msTimeOut < 0))
{
// no socket is being monitored, this may be a deadlock
CGuard::leaveCS(m_EPollLock);
throw CUDTException(5, 3);
}
// Sockets with exceptions are returned to both read and write sets.
if ((NULL != readfds) && (!p->second.m_sUDTReads.empty() || !p->second.m_sUDTExcepts.empty()))
{
*readfds = p->second.m_sUDTReads;
for (set<UDTSOCKET>::const_iterator i = p->second.m_sUDTExcepts.begin(); i != p->second.m_sUDTExcepts.end(); ++ i)
readfds->insert(*i);
total += p->second.m_sUDTReads.size() + p->second.m_sUDTExcepts.size();
}
if ((NULL != writefds) && (!p->second.m_sUDTWrites.empty() || !p->second.m_sUDTExcepts.empty()))
{
*writefds = p->second.m_sUDTWrites;
for (set<UDTSOCKET>::const_iterator i = p->second.m_sUDTExcepts.begin(); i != p->second.m_sUDTExcepts.end(); ++ i)
writefds->insert(*i);
total += p->second.m_sUDTWrites.size() + p->second.m_sUDTExcepts.size();
}
// BARCHART: Remove errors when reported.
if(total > 0 && !p->second.m_sUDTExcepts.empty()){
p->second.m_sUDTExcepts.clear();
}
if (lrfds || lwfds)
{
#ifdef LINUX
const int max_events = p->second.m_sLocals.size();
epoll_event ev[max_events];
int nfds = ::epoll_wait(p->second.m_iLocalID, ev, max_events, 0);
for (int i = 0; i < nfds; ++ i)
{
if ((NULL != lrfds) && (ev[i].events & EPOLLIN))
{
lrfds->insert(ev[i].data.fd);
++ total;
}
if ((NULL != lwfds) && (ev[i].events & EPOLLOUT))
{
lwfds->insert(ev[i].data.fd);
++ total;
}
}
#else
//currently "select" is used for all non-Linux platforms.
//faster approaches can be applied for specific systems in the future.
//"select" has a limitation on the number of sockets
fd_set readfds2;
fd_set writefds2;
FD_ZERO(&readfds2);
FD_ZERO(&writefds2);
for (set<SYSSOCKET>::const_iterator i = p->second.m_sLocals.begin(); i != p->second.m_sLocals.end(); ++ i)
{
if (lrfds)
FD_SET(*i, &readfds2);
if (lwfds)
FD_SET(*i, &writefds2);
}
timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
if (::select(0, &readfds2, &writefds2, NULL, &tv) > 0)
{
for (set<SYSSOCKET>::const_iterator i = p->second.m_sLocals.begin(); i != p->second.m_sLocals.end(); ++ i)
{
if (lrfds && FD_ISSET(*i, &readfds2))
{
lrfds->insert(*i);
++ total;
}
if (lwfds && FD_ISSET(*i, &writefds2))
{
lwfds->insert(*i);
++ total;
}
}
}
#endif
}
CGuard::leaveCS(m_EPollLock);
if (total > 0)
return total;
if ((msTimeOut >= 0) && (int64_t(CTimer::getTime() - entertime) >= msTimeOut * 1000LL))
throw CUDTException(6, 3, 0);
CTimer::waitForEvent();
}
return 0;
}
int CEPoll::release(const int eid)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator i = m_mPolls.find(eid);
if (i == m_mPolls.end())
throw CUDTException(5, 13);
#ifdef LINUX
// release local/system epoll descriptor
::close(i->second.m_iLocalID);
#endif
m_mPolls.erase(i);
return 0;
}
namespace
{
void update_epoll_sets(const UDTSOCKET& uid, const set<UDTSOCKET>& watch, set<UDTSOCKET>& result, bool enable)
{
if (enable && (watch.find(uid) != watch.end()))
{
result.insert(uid);
}
else if (!enable)
{
result.erase(uid);
}
}
} // namespace
int CEPoll::update_events(const UDTSOCKET& uid, std::set<int>& eids, int events, bool enable)
{
CGuard pg(m_EPollLock);
map<int, CEPollDesc>::iterator p;
vector<int> lost;
for (set<int>::iterator i = eids.begin(); i != eids.end(); ++ i)
{
p = m_mPolls.find(*i);
if (p == m_mPolls.end())
{
lost.push_back(*i);
}
else
{
if ((events & UDT_EPOLL_IN) != 0)
update_epoll_sets(uid, p->second.m_sUDTSocksIn, p->second.m_sUDTReads, enable);
if ((events & UDT_EPOLL_OUT) != 0)
update_epoll_sets(uid, p->second.m_sUDTSocksOut, p->second.m_sUDTWrites, enable);
if ((events & UDT_EPOLL_ERR) != 0)
update_epoll_sets(uid, p->second.m_sUDTSocksEx, p->second.m_sUDTExcepts, enable);
}
}
for (vector<int>::iterator i = lost.begin(); i != lost.end(); ++ i)
eids.erase(*i);
return 0;
}

178
src/epoll.h Normal file
View File

@ -0,0 +1,178 @@
/*****************************************************************************
Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 08/20/2010
*****************************************************************************/
#ifndef __UDT_EPOLL_H__
#define __UDT_EPOLL_H__
#include <map>
#include <set>
#include "udt.h"
struct CEPollDesc
{
int m_iID; // epoll ID
std::set<UDTSOCKET> m_sUDTSocksOut; // set of UDT sockets waiting for write events
std::set<UDTSOCKET> m_sUDTSocksIn; // set of UDT sockets waiting for read events
std::set<UDTSOCKET> m_sUDTSocksEx; // set of UDT sockets waiting for exceptions
int m_iLocalID; // local system epoll ID
std::set<SYSSOCKET> m_sLocals; // set of local (non-UDT) descriptors
std::set<UDTSOCKET> m_sUDTWrites; // UDT sockets ready for write
std::set<UDTSOCKET> m_sUDTReads; // UDT sockets ready for read
std::set<UDTSOCKET> m_sUDTExcepts; // UDT sockets with exceptions (connection broken, etc.)
};
class CEPoll
{
friend class CUDT;
friend class CRendezvousQueue;
public:
CEPoll();
~CEPoll();
public: // for CUDTUnited API
// Functionality:
// create a new EPoll.
// Parameters:
// None.
// Returned value:
// new EPoll ID if success, otherwise an error number.
int create();
// Functionality:
// add a UDT socket to an EPoll.
// Parameters:
// 0) [in] eid: EPoll ID.
// 1) [in] u: UDT Socket ID.
// 2) [in] events: events to watch.
// Returned value:
// 0 if success, otherwise an error number.
int add_usock(const int eid, const UDTSOCKET& u, const int* events = NULL);
// BARCHART
int update_usock(const int eid, const UDTSOCKET& u, const int* events = NULL);
// BARCHART
int verify_usock(const int eid, const UDTSOCKET& u, int* events);
// Functionality:
// add a system socket to an EPoll.
// Parameters:
// 0) [in] eid: EPoll ID.
// 1) [in] s: system Socket ID.
// 2) [in] events: events to watch.
// Returned value:
// 0 if success, otherwise an error number.
int add_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL);
// Functionality:
// remove a UDT socket event from an EPoll; socket will be removed if no events to watch
// Parameters:
// 0) [in] eid: EPoll ID.
// 1) [in] u: UDT socket ID.
// Returned value:
// 0 if success, otherwise an error number.
int remove_usock(const int eid, const UDTSOCKET& u);
// Functionality:
// remove a system socket event from an EPoll; socket will be removed if no events to watch
// Parameters:
// 0) [in] eid: EPoll ID.
// 1) [in] s: system socket ID.
// Returned value:
// 0 if success, otherwise an error number.
int remove_ssock(const int eid, const SYSSOCKET& s);
// Functionality:
// wait for EPoll events or timeout.
// Parameters:
// 0) [in] eid: EPoll ID.
// 1) [out] readfds: UDT sockets available for reading.
// 2) [out] writefds: UDT sockets available for writing.
// 3) [in] msTimeOut: timeout threshold, in milliseconds.
// 4) [out] lrfds: system file descriptors for reading.
// 5) [out] lwfds: system file descriptors for writing.
// Returned value:
// number of sockets available for IO.
int wait(const int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds, std::set<SYSSOCKET>* lwfds);
// Functionality:
// close and release an EPoll.
// Parameters:
// 0) [in] eid: EPoll ID.
// Returned value:
// 0 if success, otherwise an error number.
int release(const int eid);
public: // for CUDT to acknowledge IO status
// Functionality:
// Update events available for a UDT socket.
// Parameters:
// 0) [in] uid: UDT socket ID.
// 1) [in] eids: EPoll IDs to be set
// 1) [in] events: Combination of events to update
// 1) [in] enable: true -> enable, otherwise disable
// Returned value:
// 0 if success, otherwise an error number
int update_events(const UDTSOCKET& uid, std::set<int>& eids, int events, bool enable);
private:
int m_iIDSeed; // seed to generate a new ID
udt_pthread_mutex_t m_SeedLock;
std::map<int, CEPollDesc> m_mPolls; // all epolls
udt_pthread_mutex_t m_EPollLock;
};
#endif

172
src/jni/JNICCC.cpp Normal file
View File

@ -0,0 +1,172 @@
/**
* =================================================================================
*
* BSD LICENCE (http://en.wikipedia.org/wiki/BSD_licenses)
*
* Copyright (C) 2009-2013, Barchart, Inc. (http://www.barchart.com/)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the Barchart, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Developers: Andrei Pozolotin, CCob
*
* =================================================================================
*/
#include "../jni/JNICCC.h"
#include "../jni/JNICCCFactory.h"
#include "../jni/JNIHelpers.h"
JNIEnv* AttachToJVM(JavaVM* vm)
{
JNIEnv* env = NULL;
jint result = vm->GetEnv(reinterpret_cast<void**>(&env),JNI_VERSION_1_4);
if(result == JNI_EDETACHED)
vm->AttachCurrentThread(reinterpret_cast<void**>(&env),NULL);
return env;
}
JNICCC::JNICCC(JNIEnv* env, jobject objCCC) :
_objCCC( env->NewGlobalRef(objCCC)){
env->GetJavaVM(&_javaVM);
if(_objCCC != NULL){
jclass cccClass = env->GetObjectClass(_objCCC);
//We cannot statically store the methodid's as the objCCC
//class maybe a subclass of CCC which means the method id's would differ
_methodInit = env->GetMethodID(cccClass, "init", "()V" );
_methodClose = env->GetMethodID(cccClass, "close", "()V" );
_methodOnACK = env->GetMethodID(cccClass, "onACK", "(I)V" );
_methodOnLoss = env->GetMethodID(cccClass, "onLoss", "([I)V" );
_methodTimeout = env->GetMethodID(cccClass, "onTimeout", "()V" );
_methodOnPktSent = NULL;
_methodProcessCustomMsg = NULL;
env->SetLongField(objCCC,udt_CCC_fld_nativeHandleID,(jlong)(intptr_t)this);
}
}
JNICCC::~JNICCC() {
JNIEnv* env = AttachToJVM(_javaVM);
if(_objCCC)
env->DeleteGlobalRef(_objCCC);
}
jobject JNICCC::getJavaCCC(){
return _objCCC;
}
void JNICCC::init(){
CCC::init();
if(_objCCC){
JNIEnv* env = AttachToJVM(_javaVM);
env->CallVoidMethod(_objCCC, _methodInit);
}
}
void JNICCC::close(){
CCC::close();
if(_objCCC){
JNIEnv* env = AttachToJVM(_javaVM);
env->CallVoidMethod(_objCCC, _methodClose);
}
}
void JNICCC::onACK(const int32_t& ack){
CCC::onACK(ack);
if(_objCCC){
JNIEnv* env = AttachToJVM(_javaVM);
env->CallVoidMethod(_objCCC, _methodOnACK, ack);
}
}
void JNICCC::onLoss(const int32_t* losslist, const int& size){
//TODO: map to Java CCC class;
CCC::onLoss(losslist,size);
}
void JNICCC::onTimeout(){
CCC::onTimeout();
if(_objCCC){
JNIEnv* env = AttachToJVM(_javaVM);
env->CallVoidMethod(_objCCC, _methodTimeout);
}
}
void JNICCC::onPktSent(const CPacket* pkt){
CCC::onPktSent(pkt);
}
void JNICCC::onPktReceived(const CPacket* pkt){
CCC::onPktReceived(pkt);
}
void JNICCC::processCustomMsg(const CPacket* pkt){
CCC::processCustomMsg(pkt);
}
void JNICCC::setACKTimer(const int& msINT){
CCC::setACKTimer(msINT);
}
void JNICCC::setACKInterval(const int& pktINT){
CCC::setACKInterval(pktINT);
}
void JNICCC::setRTO(const int& usRTO){
CCC::setRTO(usRTO);
}
void JNICCC::setPacketSndPeriod(const double sndPeriod){
m_dPktSndPeriod = sndPeriod;
}
void JNICCC::setCWndSize(const double cWndSize){
m_dCWndSize = cWndSize;
}
const CPerfMon* JNICCC::getPerfInfo(){
return CCC::getPerfInfo();
}

110
src/jni/JNICCC.h Normal file
View File

@ -0,0 +1,110 @@
/**
* =================================================================================
*
* BSD LICENCE (http://en.wikipedia.org/wiki/BSD_licenses)
*
* Copyright (C) 2009-2013, Barchart, Inc. (http://www.barchart.com/)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the Barchart, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Developers: Andrei Pozolotin, CCob
*
* =================================================================================
*/
#ifndef JNICCC_H_
#define JNICCC_H_
#include "ccc.h"
#include <jni.h>
class JNICCCFactory;
class JNICCC: public CCC {
friend JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_initNative (JNIEnv *env, jobject self);
private:
jobject _objCCC;
JavaVM* _javaVM;
jmethodID _methodInit;
jmethodID _methodClose;
jmethodID _methodOnACK;
jmethodID _methodOnLoss;
jmethodID _methodTimeout;
jmethodID _methodOnPktSent;
jmethodID _methodProcessCustomMsg;
public:
virtual ~JNICCC();
jobject getJavaCCC();
//we need to override the visibility
//of the setXXX calls since we are
//emulating class inheritance from Java
void setACKTimer(const int& msINT);
void setACKInterval(const int& pktINT);
void setRTO(const int& usRTO);
void setPacketSndPeriod(const double sndPeriod);
void setCWndSize(const double cWndSize);
const CPerfMon* getPerfInfo();
private:
//we don't want to allow any overrides on this
//class since it will be emulated in the Java layer
JNICCC(JNIEnv* env, jobject objCCC);
void init();
void close();
void onACK(const int32_t&);
void onLoss(const int32_t*, const int&);
void onTimeout();
void onPktSent(const CPacket*);
void onPktReceived(const CPacket*);
void processCustomMsg(const CPacket*);
};
#endif /* JNICCC_H_ */

122
src/jni/JNICCCFactory.cpp Normal file
View File

@ -0,0 +1,122 @@
/**
* =================================================================================
*
* BSD LICENCE (http://en.wikipedia.org/wiki/BSD_licenses)
*
* Copyright (C) 2009-2013, Barchart, Inc. (http://www.barchart.com/)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the Barchart, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Developers: Andrei Pozolotin, CCob
*
* =================================================================================
*/
#include "../jni/JNICCCFactory.h"
#include "../jni/JNICCC.h"
#include "../jni/JNIHelpers.h"
jmethodID JNICCCFactory::_udt_clsFactoryInterfaceUDT_create = NULL;
jmethodID JNICCCFactory::_udt_clsFactoryInterfaceUDT_cloneFactory = NULL;
bool JNICCCFactory::initJNITypes(JNIEnv* env){
if(_udt_clsFactoryInterfaceUDT_create != NULL)
return true;
if(udt_FactoryInterfaceUDT==NULL)
return false;
_udt_clsFactoryInterfaceUDT_cloneFactory = env->GetMethodID(udt_FactoryInterfaceUDT, "cloneFactory", "()Lcom/barchart/udt/FactoryInterfaceUDT;");
_udt_clsFactoryInterfaceUDT_create = env->GetMethodID(udt_FactoryInterfaceUDT, "create", "()Lcom/barchart/udt/CCC;");
return true;
}
JNIEnv* JNICCCFactory::AttachToJVM()
{
JNIEnv* env = NULL;
jint result = _javaVM->GetEnv(reinterpret_cast<void**>(&env),JNI_VERSION_1_4);
if(result == JNI_EDETACHED)
_javaVM->AttachCurrentThread(reinterpret_cast<void**>(&env),NULL);
return env;
}
JNICCCFactory::JNICCCFactory(JNIEnv* env, jobject factoryUDT) {
initJNITypes(env);
if(factoryUDT==NULL){
;//TODO create new exception
}
env->GetJavaVM(&_javaVM);
//We need to create a global JNI ref since
//we are storing the jobject as a member variable
//for use later on
_factoryUDT = env->NewGlobalRef(factoryUDT);
}
JNICCCFactory::~JNICCCFactory(){
JNIEnv* env = AttachToJVM();
if(_factoryUDT != NULL){
env->DeleteLocalRef(_factoryUDT);
}
}
CCC* JNICCCFactory::create(){
JNIEnv* env = AttachToJVM();
jobject objCCC = env->CallObjectMethod(_factoryUDT,_udt_clsFactoryInterfaceUDT_create);
if(objCCC==NULL && !env->ExceptionCheck() ){
UDT_ThrowExceptionUDT_Message(env, 0, "failed to allocate CCC class via com.barchart.udt.FactoryInterfaceUDT");
}
return reinterpret_cast<CCC*> ((intptr_t) env->GetLongField(objCCC,udt_CCC_fld_nativeHandleID));
}
CCCVirtualFactory* JNICCCFactory::clone(){
JNIEnv* env = AttachToJVM();
jobject objFactoryUDT = env->CallObjectMethod(_factoryUDT,_udt_clsFactoryInterfaceUDT_cloneFactory);
return new JNICCCFactory(env,objFactoryUDT);
}

68
src/jni/JNICCCFactory.h Normal file
View File

@ -0,0 +1,68 @@
/**
* =================================================================================
*
* BSD LICENCE (http://en.wikipedia.org/wiki/BSD_licenses)
*
* Copyright (C) 2009-2013, Barchart, Inc. (http://www.barchart.com/)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the Barchart, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Developers: Andrei Pozolotin, CCob
*
* =================================================================================
*/
#ifndef JNICCCFACTORY_H_
#define JNICCCFACTORY_H_
#include "ccc.h"
#include <jni.h>
class JNICCCFactory: public CCCVirtualFactory {
private:
static jmethodID _udt_clsFactoryInterfaceUDT_create;
static jmethodID _udt_clsFactoryInterfaceUDT_cloneFactory;
JavaVM* _javaVM;
jobject _factoryUDT;
static bool initJNITypes(JNIEnv* env);
JNIEnv* AttachToJVM();
public:
JNICCCFactory(JNIEnv* env, jobject factoryUDT);
virtual ~JNICCCFactory();
CCC* create();
CCCVirtualFactory* clone();
};
#endif /* JNICCCFACTORY_H_ */

301
src/jni/JNIHelpers.cpp Normal file
View File

@ -0,0 +1,301 @@
/**
* =================================================================================
*
* BSD LICENCE (http://en.wikipedia.org/wiki/BSD_licenses)
*
* Copyright (C) 2009-2013, Barchart, Inc. (http://www.barchart.com/)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the Barchart, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Developers: Andrei Pozolotin, CCob
*
* =================================================================================
*/
#include "../jni/JNIHelpers.h"
#include "jni.h"
// ### JNI
#define JNI_UPDATE 0 // jni object release with copy
//
// ### JDK references
// JDK classes
jclass jdk_Boolean; // java.lang.Boolean
jclass jdk_Integer; // java.lang.Integer
jclass jdk_Long; // java.lang.Long
jclass jdk_InetAddress; // java.net.InetAddress
jclass jdk_InetSocketAddress; // java.net.InetSocketAddress
jclass jdk_SocketException; // java.net.SocketException
jclass jdk_Set; // java.util.Set
jclass jdk_Iterator; // java.util.Iterator
// JDK methods
jmethodID jdk_Boolean_init; // new Boolean(boolean x)
jmethodID jdk_Integer_init; // new Integer(int x)
jmethodID jdk_Long_init; // new Long(long x)
jmethodID jdk_InetAddress_getAddress; // byte[] getAddress()
jmethodID jdk_InetAddress_getByAddress; // static InetAddress getByAddress(byte[])
jmethodID jdk_InetSocketAddress_init; // new InetSocketAddress(InetAddress x)
jmethodID jdk_InetSocketAddress_getAddress; //
jmethodID jdk_InetSocketAddress_getPort; //
jmethodID jdk_Set_iterator; // Iterator set.iterator()
jmethodID jdk_Set_add; // boolean set.add(Object)
jmethodID jdk_Set_contains; // boolean set.contains(Object)
jmethodID jdk_Iterator_hasNext; // boolean iterator.hasNext()
jmethodID jdk_Iterator_next; // Object iterator.next()
// UDT classes
jclass udt_FactoryInterfaceUDT; //com.barchart.udt.FactoryInterfaceUDT
// UDT methods
jfieldID udt_CCC_fld_nativeHandleID;
void X_InitClassReference(JNIEnv *env, jclass *classReference,
const char *className) {
CHK_NUL_RET_RET(env, "env");
CHK_NUL_RET_RET(className, "className");
CHK_NUL_RET_RET(classReference, "classReference");
jclass klaz = env->FindClass(className);
CHK_NUL_RET_RET(klaz, "klaz");
*classReference = static_cast<jclass>(env->NewGlobalRef((jobject) klaz));
CHK_NUL_RET_RET(*classReference, "*classReference");
}
void X_FreeClassReference(JNIEnv *env, jclass* globalRef) {
CHK_NUL_RET_RET(env, "env");
CHK_NUL_RET_RET(globalRef, "globalRef");
env->DeleteGlobalRef(*globalRef);
*globalRef = NULL;
}
// use native bool parameter
jobject X_NewBoolean(JNIEnv *env, bool value) {
CHK_NUL_RET_NUL(env, "env");
return env->NewObject(jdk_Boolean, jdk_Boolean_init,
BOOLEAN(value) );
}
// use native 32 bit int parameter
jobject X_NewInteger(JNIEnv *env, int value) {
CHK_NUL_RET_NUL(env, "env");
return env->NewObject(jdk_Integer, jdk_Integer_init, (jint) value);
}
// use native 64 bit long parameter
jobject X_NewLong(JNIEnv* env, int64_t value) {
CHK_NUL_RET_NUL(env, "env");
return env->NewObject(jdk_Long, jdk_Long_init, (jlong) value);
}
// NOTE: ipv4 only
int X_InitSockAddr(sockaddr* sockAddr) {
CHK_NUL_RET_ERR(sockAddr, "sockAddr");
sockaddr_in* sockAddrIn = (sockaddr_in*) sockAddr;
sockAddrIn->sin_family = AF_INET;
memset(&(sockAddrIn->sin_zero), '\0', 8);
return JNI_OK;
}
// NOTE: ipv4 only
int X_ConvertInetAddressToInteger( //
JNIEnv* env, //
jobject objInetAddress, //
jint* address //
) {
CHK_NUL_RET_ERR(env, "env");
CHK_NUL_RET_ERR(objInetAddress, "objInetAddress");
CHK_NUL_RET_ERR(address, "address");
const jbyteArray objArray = (jbyteArray) env->CallObjectMethod(
objInetAddress, jdk_InetAddress_getAddress);
CHK_NUL_RET_ERR(objArray, "objArray");
const int sizeArray = env->GetArrayLength(objArray);
switch (sizeArray) {
case 4:
// IPV4
break;
case 16:
// IPV6
default:
CHK_LOG("unsupported address size", "sizeArray");
return JNI_ERR;
}
jbyte* refArray = env->GetByteArrayElements(objArray, NULL);
int value = 0;
value |= (0xFF000000 & (refArray[0] << 24));
value |= (0x00FF0000 & (refArray[1] << 16));
value |= (0x0000FF00 & (refArray[2] << 8));
value |= (0x000000FF & (refArray[3]));
env->ReleaseByteArrayElements(objArray, refArray, 0);
*address = value;
return JNI_OK;
}
// NOTE: ipv4 only
int X_ConvertInetSocketAddressToSockaddr( //
JNIEnv* env, //
jobject objInetSocketAddress, //
sockaddr* sockAddr //
) {
CHK_NUL_RET_ERR(env, "env");
CHK_NUL_RET_ERR(sockAddr, "sockAddr");
CHK_NUL_RET_ERR(objInetSocketAddress, "objInetSocketAddress");
const jobject objInetAddress = env->CallObjectMethod(objInetSocketAddress,
jdk_InetSocketAddress_getAddress);
CHK_NUL_RET_ERR(objInetAddress, "objInetAddress");
jint address = 0;
jint port = env->CallIntMethod(objInetSocketAddress,
jdk_InetSocketAddress_getPort);
const int rv = X_ConvertInetAddressToInteger(env, objInetAddress, &address);
if (rv == JNI_ERR) {
return JNI_ERR;
}
sockaddr_in* sockAddrIn = (sockaddr_in*) sockAddr;
sockAddrIn->sin_addr.s_addr = htonl(address);
sockAddrIn->sin_port = htons(port);
return JNI_OK;
}
// NOTE: only ipv4
jobject X_NewInetAddress( //
JNIEnv* env, //
const jint address //
) {
CHK_NUL_RET_NUL(env, "env");
char valArray[4];
valArray[0] = (address & 0xFF000000) >> 24;
valArray[1] = (address & 0x00FF0000) >> 16;
valArray[2] = (address & 0x0000FF00) >> 8;
valArray[3] = (address & 0x000000FF);
const jbyteArray objArray = env->NewByteArray(4);
env->SetByteArrayRegion(objArray, (jint) 0, (jint) 4, (jbyte*) valArray);
const jobject objInetAddress = env->CallStaticObjectMethod(
jdk_InetAddress, jdk_InetAddress_getByAddress, objArray);
CHK_NUL_RET_NUL(objInetAddress, "objInetAddress");
return objInetAddress;
}
// NOTE: ipv4 only
jobject X_NewInetSocketAddress( //
JNIEnv* env, //
sockaddr* sockAddr //
) {
CHK_NUL_RET_NUL(env, "env");
CHK_NUL_RET_NUL(sockAddr, "sockAddr");
sockaddr_in* sockAddrIn = (sockaddr_in*) sockAddr;
const jint address = ntohl(sockAddrIn->sin_addr.s_addr);
const jint port = ntohs(sockAddrIn->sin_port);
const jobject objInetAddress = X_NewInetAddress(env, address);
CHK_NUL_RET_NUL(objInetAddress, "objInetAddress");
const jobject objInetSocketAddress = env->NewObject(
jdk_InetSocketAddress, jdk_InetSocketAddress_init,
objInetAddress, port);
CHK_NUL_RET_NUL(objInetSocketAddress, "objInetSocketAddress");
return objInetSocketAddress;
}
bool X_IsSockaddrEqualsInetSocketAddress( //
JNIEnv* env, //
sockaddr* sockAddr, //
jobject objSocketAddress //
) {
CHK_NUL_RET_FLS(env, "env");
CHK_NUL_RET_FLS(sockAddr, "sockAddr");
CHK_NUL_RET_FLS(objSocketAddress, "objSocketAddress");
sockaddr_in* sockAddrIn = (sockaddr_in*) sockAddr;
jint address1 = ntohl(sockAddrIn->sin_addr.s_addr);
jint port1 = ntohs(sockAddrIn->sin_port);
jint address2 = 0;
jint port2 = env->CallIntMethod(objSocketAddress,
jdk_InetSocketAddress_getPort);
jobject objInetAddress = env->CallObjectMethod(objSocketAddress,
jdk_InetSocketAddress_getAddress);
CHK_NUL_RET_ERR(objInetAddress, "objInetAddress");
const int rv = X_ConvertInetAddressToInteger(env, objInetAddress,
&address2);
if (rv == JNI_ERR) {
return false;
}
if (address1 == address2 && port1 == port2) {
return true;
}
return false;
}

198
src/jni/JNIHelpers.h Normal file
View File

@ -0,0 +1,198 @@
/**
* =================================================================================
*
* BSD LICENCE (http://en.wikipedia.org/wiki/BSD_licenses)
*
* Copyright (C) 2009-2013, Barchart, Inc. (http://www.barchart.com/)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the Barchart, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Developers: Andrei Pozolotin, CCob
*
* =================================================================================
*/
#ifndef JNIHELPERS_H_
#define JNIHELPERS_H_
#include "udt.h"
#include <cassert>
#include <climits>
#include <cstring>
#include <vector>
#include <algorithm>
#include "jni.h"
// ### JNI
#define JNI_UPDATE 0 // jni object release with copy
//
extern "C"{
// ### JDK references
// JDK classes
extern jclass jdk_Boolean; // java.lang.Boolean
extern jclass jdk_Integer; // java.lang.Integer
extern jclass jdk_Long; // java.lang.Long
extern jclass jdk_InetAddress; // java.net.InetAddress
extern jclass jdk_InetSocketAddress; // java.net.InetSocketAddress
extern jclass jdk_SocketException; // java.net.SocketException
extern jclass jdk_Set; // java.util.Set
extern jclass jdk_Iterator; // java.util.Iterator
// JDK methods
extern jmethodID jdk_Boolean_init; // new Boolean(boolean x)
extern jmethodID jdk_Integer_init; // new Integer(int x)
extern jmethodID jdk_Long_init; // new Long(long x)
extern jmethodID jdk_InetAddress_getAddress; // byte[] getAddress()
extern jmethodID jdk_InetAddress_getByAddress; // static InetAddress getByAddress(byte[])
extern jmethodID jdk_InetSocketAddress_init; // new InetSocketAddress(InetAddress x)
extern jmethodID jdk_InetSocketAddress_getAddress; // InetAddress InetSocketAddress.getAddress()
extern jmethodID jdk_InetSocketAddress_getPort; // int InetSocketAddress.getPort()
extern jmethodID jdk_Set_iterator; // Iterator Set.iterator()
extern jmethodID jdk_Set_add; // boolean Set.add(Object)
extern jmethodID jdk_Set_contains; // boolean Set.contains(Object)
extern jmethodID jdk_Iterator_hasNext; // boolean Iterator.hasNext()
extern jmethodID jdk_Iterator_next; // Object Iterator.next()
// UDT classes
extern jclass udt_FactoryInterfaceUDT;
// UDT methods
extern jfieldID udt_CCC_fld_nativeHandleID;
//#define EOL "\n"
// special UDT method return value
#define UDT_TIMEOUT 0
// TODO make more portable mingw / msvc
#ifdef _MSC_VER
#define __func__ __FUNCTION__
#endif
//
// null pointer safety
//
#define CHK_LOG(title,comment) printf ("%s function: %s comment: %s", title, __func__, comment);
//
#define CHK_NUL_RET_RET(reference,comment) if ((reference) == NULL) \
{ CHK_LOG("CHK_NUL_RET_RET;",comment); return; }
//
#define CHK_NUL_RET_NUL(reference,comment) if ((reference) == NULL) \
{ CHK_LOG("CHK_NUL_RET_NUL;",comment); return NULL; }
//
#define CHK_NUL_RET_FLS(reference,comment) if ((reference) == NULL) \
{ CHK_LOG("CHK_NUL_RET_FLS;",comment); return false; }
//
#define CHK_NUL_RET_ERR(reference,comment) if ((reference) == NULL) \
{ CHK_LOG("CHK_NUL_RET_ERR;",comment); return JNI_ERR; }
//
// c++ <-> java, bool <-> boolean conversions
#define BOOL(x) (((x) == JNI_TRUE) ? true : false) // from java to c++
#define BOOLEAN(x) ((jboolean) ( ((x) == true) ? JNI_TRUE : JNI_FALSE )) // from c++ to java
//
// free/malloc convenience
#define FREE(x) if ((x) != NULL) { free(x); x = NULL; }
#define MALLOC(var,type,size) type* var = (type*) malloc(sizeof(type) * size);
// declare unused explicitly or else see compiler warnings
#define UNUSED(x) ((void)(x))
void X_InitClassReference(JNIEnv *env, jclass *classReference,
const char *className);
void X_FreeClassReference(JNIEnv *env, jclass* globalRef);
jobject X_NewBoolean(JNIEnv *env, bool value);
jobject X_NewInteger(JNIEnv *env, int value);
jobject X_NewLong(JNIEnv* env, int64_t value);
int X_InitSockAddr(sockaddr* sockAddr);
inline bool X_IsInRange(jlong min, jlong var, jlong max) {
if (min <= var && var <= max) {
return true;
} else {
return false;
}
}
inline void X_ConvertMillisIntoTimeValue(const jlong millisTimeout,
timeval* timeValue) {
if (millisTimeout < 0) { // infinite wait
timeValue->tv_sec = INT_MAX;
timeValue->tv_usec = 0;
} else if (millisTimeout > 0) { // finite wait
timeValue->tv_sec = millisTimeout / 1000; // msvc C4244
timeValue->tv_usec = (millisTimeout % 1000) * 1000;
} else { // immediate return (not less the UDT event slice of 10 ms)
timeValue->tv_sec = 0;
timeValue->tv_usec = 0;
}
}
// NOTE: ipv4 only
int X_ConvertInetSocketAddressToSockaddr(JNIEnv* env,
jobject objInetSocketAddress, sockaddr* sockAddr);
// NOTE: only ipv4
jobject X_NewInetAddress(JNIEnv* env, jint address);
// NOTE: ipv4 only
jobject X_NewInetSocketAddress(JNIEnv* env, sockaddr* sockAddr);
// NOTE: ipv4 only
bool X_IsSockaddrEqualsInetSocketAddress(JNIEnv* env, sockaddr* sockAddr,
jobject socketAddress);
void UDT_ThrowExceptionUDT_Message(JNIEnv* env, const jint socketID,
const char *comment);
}//extern "C"
#endif /* JNIHELPERS_H_ */

View File

@ -0,0 +1,186 @@
/**
* =================================================================================
*
* BSD LICENCE (http://en.wikipedia.org/wiki/BSD_licenses)
*
* Copyright (C) 2009-2013, Barchart, Inc. (http://www.barchart.com/)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the Barchart, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Developers: Andrei Pozolotin, CCob
*
* =================================================================================
*/
#include "../jni/com_barchart_udt_CCC.h"
#include "../jni/JNICCC.h"
#include "../jni/JNIHelpers.h"
extern "C" {
JNICCC* getNativeJNICCC(JNIEnv* env, jobject javaCCC){
CHK_NUL_RET_NUL(env, "env");
CHK_NUL_RET_NUL(env, "javaCCC");
JNICCC* jniCCC = reinterpret_cast<JNICCC*>( (intptr_t) env->GetLongField(javaCCC,udt_CCC_fld_nativeHandleID)) ;
if(jniCCC==NULL){
UDT_ThrowExceptionUDT_Message(env,0,"illegal state, nativeHandle not set to instance of native JNICCC* class");
return NULL;
}
return jniCCC;
}
/*
* Class: com_barchart_udt_CCC
* Method: initNative
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_initNative (JNIEnv *env, jobject self){
JNICCC* jniCCC = new JNICCC(env, self);
if(jniCCC==NULL)
UDT_ThrowExceptionUDT_Message(env,0,"failed to allocate native JNICCC* class");
return;
}
/*
* Class: com_barchart_udt_CCC
* Method: setACKTimer
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setACKTimer
(JNIEnv * env, jobject obj, jint msINT){
JNICCC* jniCCC = getNativeJNICCC(env,obj);
if(jniCCC==NULL){
return;
}
jniCCC->setACKTimer(msINT);
}
/*
* Class: com_barchart_udt_CCC
* Method: setACKInterval
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setACKInterval
(JNIEnv * env, jobject obj, jint pktINT){
JNICCC* jniCCC = getNativeJNICCC(env,obj);
if(jniCCC==NULL)
return;
jniCCC->setACKInterval(pktINT);
}
/*
* Class: com_barchart_udt_CCC
* Method: setRTO
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setRTO
(JNIEnv * env, jobject obj, jint usRTO){
JNICCC* jniCCC = getNativeJNICCC(env,obj);
if(jniCCC==NULL)
return;
jniCCC->setRTO(usRTO);
}
/*
* Class: com_barchart_udt_CCC
* Method: setPacketSndPeriod
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setPacketSndPeriod
(JNIEnv *env, jobject obj, jdouble sndPeriod){
JNICCC* jniCCC = getNativeJNICCC(env,obj);
if(jniCCC==NULL)
return;
jniCCC->setPacketSndPeriod(sndPeriod);
}
/*
* Class: com_barchart_udt_CCC
* Method: setCWndSize
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setCWndSize
(JNIEnv *env, jobject obj, jdouble cWndSize){
JNICCC* jniCCC = getNativeJNICCC(env,obj);
if(jniCCC==NULL)
return;
jniCCC->setCWndSize(cWndSize);
}
/*
* Class: com_barchart_udt_CCC
* Method: getPerfInfo
* Signature: ()Lcom/barchart/udt/MonitorUDT;
*/
JNIEXPORT jobject JNICALL Java_com_barchart_udt_CCC_getPerfInfo
(JNIEnv *env, jobject obj){
JNICCC* jniCCC = getNativeJNICCC(env,obj);
const CPerfMon* perfMon = jniCCC->getPerfInfo();
UNUSED(perfMon);
UDT_ThrowExceptionUDT_Message(env,0,"TODO: implement CPerfMon -> MonitorUDT mapping");
return NULL;
}
} // __cplusplus defined.

View File

@ -0,0 +1,71 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <jvmti.h>
/* Header for class com_barchart_udt_CCC */
#ifndef _Included_com_barchart_udt_CCC
#define _Included_com_barchart_udt_CCC
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_barchart_udt_CCC
* Method: initNative
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_initNative
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_CCC
* Method: setACKTimer
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setACKTimer
(JNIEnv *, jobject, jint);
/*
* Class: com_barchart_udt_CCC
* Method: setACKInterval
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setACKInterval
(JNIEnv *, jobject, jint);
/*
* Class: com_barchart_udt_CCC
* Method: setRTO
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setRTO
(JNIEnv *, jobject, jint);
/*
* Class: com_barchart_udt_CCC
* Method: setPacketSndPeriod
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setPacketSndPeriod
(JNIEnv *, jobject, jdouble);
/*
* Class: com_barchart_udt_CCC
* Method: setCWndSize
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_CCC_setCWndSize
(JNIEnv *, jobject, jdouble);
/*
* Class: com_barchart_udt_CCC
* Method: getPerfInfo
* Signature: ()Lcom/barchart/udt/MonitorUDT;
*/
JNIEXPORT jobject JNICALL Java_com_barchart_udt_CCC_getPerfInfo
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,416 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <jvmti.h>
/* Header for class com_barchart_udt_SocketUDT */
#ifndef _Included_com_barchart_udt_SocketUDT
#define _Included_com_barchart_udt_SocketUDT
#ifdef __cplusplus
extern "C" {
#endif
#undef com_barchart_udt_SocketUDT_DEFAULT_ACCEPT_QUEUE_SIZE
#define com_barchart_udt_SocketUDT_DEFAULT_ACCEPT_QUEUE_SIZE 256L
#undef com_barchart_udt_SocketUDT_DEFAULT_FILE_BLOCK_SIZE
#define com_barchart_udt_SocketUDT_DEFAULT_FILE_BLOCK_SIZE 1048576L
#undef com_barchart_udt_SocketUDT_DEFAULT_MAX_SELECTOR_SIZE
#define com_barchart_udt_SocketUDT_DEFAULT_MAX_SELECTOR_SIZE 1024L
#undef com_barchart_udt_SocketUDT_DEFAULT_MIN_SELECTOR_TIMEOUT
#define com_barchart_udt_SocketUDT_DEFAULT_MIN_SELECTOR_TIMEOUT 10L
#undef com_barchart_udt_SocketUDT_INFINITE_TTL
#define com_barchart_udt_SocketUDT_INFINITE_TTL -1L
#undef com_barchart_udt_SocketUDT_SIGNATURE_JNI
#define com_barchart_udt_SocketUDT_SIGNATURE_JNI 20130512L
#undef com_barchart_udt_SocketUDT_TIMEOUT_INFINITE
#define com_barchart_udt_SocketUDT_TIMEOUT_INFINITE -1L
#undef com_barchart_udt_SocketUDT_UDT_EXCEPT_INDEX
#define com_barchart_udt_SocketUDT_UDT_EXCEPT_INDEX 2L
#undef com_barchart_udt_SocketUDT_UDT_READ_INDEX
#define com_barchart_udt_SocketUDT_UDT_READ_INDEX 0L
#undef com_barchart_udt_SocketUDT_UDT_SIZE_COUNT
#define com_barchart_udt_SocketUDT_UDT_SIZE_COUNT 3L
#undef com_barchart_udt_SocketUDT_UDT_WRITE_INDEX
#define com_barchart_udt_SocketUDT_UDT_WRITE_INDEX 1L
/*
* Class: com_barchart_udt_SocketUDT
* Method: epollAdd0
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollAdd0
(JNIEnv *, jclass, jint, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: epollCreate0
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_epollCreate0
(JNIEnv *, jclass);
/*
* Class: com_barchart_udt_SocketUDT
* Method: epollRelease0
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollRelease0
(JNIEnv *, jclass, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: epollRemove0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollRemove0
(JNIEnv *, jclass, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: epollUpdate0
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollUpdate0
(JNIEnv *, jclass, jint, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: epollVerify0
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_epollVerify0
(JNIEnv *, jclass, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: epollWait0
* Signature: (ILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;J)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_epollWait0
(JNIEnv *, jclass, jint, jobject, jobject, jobject, jlong);
/*
* Class: com_barchart_udt_SocketUDT
* Method: getSignatureJNI0
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_getSignatureJNI0
(JNIEnv *, jclass);
/*
* Class: com_barchart_udt_SocketUDT
* Method: initClass0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_initClass0
(JNIEnv *, jclass);
/*
* Class: com_barchart_udt_SocketUDT
* Method: receive0
* Signature: (II[B)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_receive0
(JNIEnv *, jclass, jint, jint, jbyteArray);
/*
* Class: com_barchart_udt_SocketUDT
* Method: receive1
* Signature: (II[BII)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_receive1
(JNIEnv *, jclass, jint, jint, jbyteArray, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: receive2
* Signature: (IILjava/nio/ByteBuffer;II)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_receive2
(JNIEnv *, jclass, jint, jint, jobject, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: receiveFile0
* Signature: (ILjava/lang/String;JJI)J
*/
JNIEXPORT jlong JNICALL Java_com_barchart_udt_SocketUDT_receiveFile0
(JNIEnv *, jclass, jint, jstring, jlong, jlong, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: send0
* Signature: (IIIZ[B)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_send0
(JNIEnv *, jclass, jint, jint, jint, jboolean, jbyteArray);
/*
* Class: com_barchart_udt_SocketUDT
* Method: send1
* Signature: (IIIZ[BII)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_send1
(JNIEnv *, jclass, jint, jint, jint, jboolean, jbyteArray, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: send2
* Signature: (IIIZLjava/nio/ByteBuffer;II)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_send2
(JNIEnv *, jclass, jint, jint, jint, jboolean, jobject, jint, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: sendFile0
* Signature: (ILjava/lang/String;JJI)J
*/
JNIEXPORT jlong JNICALL Java_com_barchart_udt_SocketUDT_sendFile0
(JNIEnv *, jclass, jint, jstring, jlong, jlong, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: stopClass0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_stopClass0
(JNIEnv *, jclass);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testCrashJVM0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testCrashJVM0
(JNIEnv *, jclass);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testDirectByteBufferAccess0
* Signature: (Ljava/nio/ByteBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testDirectByteBufferAccess0
(JNIEnv *, jclass, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testDirectIntBufferAccess0
* Signature: (Ljava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testDirectIntBufferAccess0
(JNIEnv *, jclass, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testDirectIntBufferLoad0
* Signature: (Ljava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testDirectIntBufferLoad0
(JNIEnv *, jclass, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testEmptyCall0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testEmptyCall0
(JNIEnv *, jclass);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testFillArray0
* Signature: ([B)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testFillArray0
(JNIEnv *, jclass, jbyteArray);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testFillBuffer0
* Signature: (Ljava/nio/ByteBuffer;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testFillBuffer0
(JNIEnv *, jclass, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testGetSetArray0
* Signature: ([IZ)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testGetSetArray0
(JNIEnv *, jclass, jintArray, jboolean);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testInvalidClose0
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testInvalidClose0
(JNIEnv *, jclass, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testIterateArray0
* Signature: ([Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testIterateArray0
(JNIEnv *, jclass, jobjectArray);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testIterateSet0
* Signature: (Ljava/util/Set;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testIterateSet0
(JNIEnv *, jclass, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: testMakeArray0
* Signature: (I)[I
*/
JNIEXPORT jintArray JNICALL Java_com_barchart_udt_SocketUDT_testMakeArray0
(JNIEnv *, jclass, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: accept0
* Signature: ()Lcom/barchart/udt/SocketUDT;
*/
JNIEXPORT jobject JNICALL Java_com_barchart_udt_SocketUDT_accept0
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: bind0
* Signature: (Ljava/net/InetSocketAddress;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_bind0
(JNIEnv *, jobject, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: clearError0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_clearError0
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: close0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_close0
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: connect0
* Signature: (Ljava/net/InetSocketAddress;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_connect0
(JNIEnv *, jobject, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: getErrorCode0
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_getErrorCode0
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: getErrorMessage0
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_barchart_udt_SocketUDT_getErrorMessage0
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: getOption0
* Signature: (ILjava/lang/Class;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_com_barchart_udt_SocketUDT_getOption0
(JNIEnv *, jobject, jint, jclass);
/*
* Class: com_barchart_udt_SocketUDT
* Method: getStatus0
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_getStatus0
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: hasLoadedLocalSocketAddress
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_barchart_udt_SocketUDT_hasLoadedLocalSocketAddress
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: hasLoadedRemoteSocketAddress
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_barchart_udt_SocketUDT_hasLoadedRemoteSocketAddress
(JNIEnv *, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: initInstance0
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_initInstance0
(JNIEnv *, jobject, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: initInstance1
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_initInstance1
(JNIEnv *, jobject, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: listen0
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_listen0
(JNIEnv *, jobject, jint);
/*
* Class: com_barchart_udt_SocketUDT
* Method: setOption0
* Signature: (ILjava/lang/Class;Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_setOption0
(JNIEnv *, jobject, jint, jclass, jobject);
/*
* Class: com_barchart_udt_SocketUDT
* Method: updateMonitor0
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_updateMonitor0
(JNIEnv *, jobject, jboolean);
#ifdef __cplusplus
}
#endif
#endif

703
src/list.cpp Normal file
View File

@ -0,0 +1,703 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/22/2011
*****************************************************************************/
#include "list.h"
CSndLossList::CSndLossList(int size):
m_piData1(NULL),
m_piData2(NULL),
m_piNext(NULL),
m_iHead(-1),
m_iLength(0),
m_iSize(size),
m_iLastInsertPos(-1),
m_ListLock()
{
m_piData1 = new int32_t [m_iSize];
m_piData2 = new int32_t [m_iSize];
m_piNext = new int [m_iSize];
// -1 means there is no data in the node
for (int i = 0; i < size; ++ i)
{
m_piData1[i] = -1;
m_piData2[i] = -1;
}
// sender list needs mutex protection
#ifndef WINDOWS
pthread_mutex_init(&m_ListLock, 0);
#else
m_ListLock = CreateMutex(NULL, false, NULL);
#endif
}
CSndLossList::~CSndLossList()
{
delete [] m_piData1;
delete [] m_piData2;
delete [] m_piNext;
#ifndef WINDOWS
pthread_mutex_destroy(&m_ListLock);
#else
CloseHandle(m_ListLock);
#endif
}
int CSndLossList::insert(int32_t seqno1, int32_t seqno2)
{
CGuard listguard(m_ListLock);
if (0 == m_iLength)
{
// insert data into an empty list
m_iHead = 0;
m_piData1[m_iHead] = seqno1;
if (seqno2 != seqno1)
m_piData2[m_iHead] = seqno2;
m_piNext[m_iHead] = -1;
m_iLastInsertPos = m_iHead;
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
return m_iLength;
}
// otherwise find the position where the data can be inserted
int origlen = m_iLength;
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1);
int loc = (m_iHead + offset + m_iSize) % m_iSize;
if (offset < 0)
{
// Insert data prior to the head pointer
m_piData1[loc] = seqno1;
if (seqno2 != seqno1)
m_piData2[loc] = seqno2;
// new node becomes head
m_piNext[loc] = m_iHead;
m_iHead = loc;
m_iLastInsertPos = loc;
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
}
else if (offset > 0)
{
if (seqno1 == m_piData1[loc])
{
m_iLastInsertPos = loc;
// first seqno is equivlent, compare the second
if (-1 == m_piData2[loc])
{
if (seqno2 != seqno1)
{
m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1;
m_piData2[loc] = seqno2;
}
}
else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0)
{
// new seq pair is longer than old pair, e.g., insert [3, 7] to [3, 5], becomes [3, 7]
m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1;
m_piData2[loc] = seqno2;
}
else
// Do nothing if it is already there
return 0;
}
else
{
// searching the prior node
int i;
if ((-1 != m_iLastInsertPos) && (CSeqNo::seqcmp(m_piData1[m_iLastInsertPos], seqno1) < 0))
i = m_iLastInsertPos;
else
i = m_iHead;
while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno1) < 0))
i = m_piNext[i];
if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(m_piData2[i], seqno1) < 0))
{
m_iLastInsertPos = loc;
// no overlap, create new node
m_piData1[loc] = seqno1;
if (seqno2 != seqno1)
m_piData2[loc] = seqno2;
m_piNext[loc] = m_piNext[i];
m_piNext[i] = loc;
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
}
else
{
m_iLastInsertPos = i;
// overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... becomes [2, 7]
if (CSeqNo::seqcmp(m_piData2[i], seqno2) < 0)
{
m_iLength += CSeqNo::seqlen(m_piData2[i], seqno2) - 1;
m_piData2[i] = seqno2;
loc = i;
}
else
return 0;
}
}
}
else
{
m_iLastInsertPos = m_iHead;
// insert to head node
if (seqno2 != seqno1)
{
if (-1 == m_piData2[loc])
{
m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1;
m_piData2[loc] = seqno2;
}
else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0)
{
m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1;
m_piData2[loc] = seqno2;
}
else
return 0;
}
else
return 0;
}
// coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9]
while ((-1 != m_piNext[loc]) && (-1 != m_piData2[loc]))
{
int i = m_piNext[loc];
if (CSeqNo::seqcmp(m_piData1[i], CSeqNo::incseq(m_piData2[loc])) <= 0)
{
// coalesce if there is overlap
if (-1 != m_piData2[i])
{
if (CSeqNo::seqcmp(m_piData2[i], m_piData2[loc]) > 0)
{
if (CSeqNo::seqcmp(m_piData2[loc], m_piData1[i]) >= 0)
m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[loc]);
m_piData2[loc] = m_piData2[i];
}
else
m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[i]);
}
else
{
if (m_piData1[i] == CSeqNo::incseq(m_piData2[loc]))
m_piData2[loc] = m_piData1[i];
else
m_iLength --;
}
m_piData1[i] = -1;
m_piData2[i] = -1;
m_piNext[loc] = m_piNext[i];
}
else
break;
}
return m_iLength - origlen;
}
void CSndLossList::remove(int32_t seqno)
{
CGuard listguard(m_ListLock);
if (0 == m_iLength)
return;
// Remove all from the head pointer to a node with a larger seq. no. or the list is empty
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno);
int loc = (m_iHead + offset + m_iSize) % m_iSize;
if (0 == offset)
{
// It is the head. Remove the head and point to the next node
loc = (loc + 1) % m_iSize;
if (-1 == m_piData2[m_iHead])
loc = m_piNext[m_iHead];
else
{
m_piData1[loc] = CSeqNo::incseq(seqno);
if (CSeqNo::seqcmp(m_piData2[m_iHead], CSeqNo::incseq(seqno)) > 0)
m_piData2[loc] = m_piData2[m_iHead];
m_piData2[m_iHead] = -1;
m_piNext[loc] = m_piNext[m_iHead];
}
m_piData1[m_iHead] = -1;
if (m_iLastInsertPos == m_iHead)
m_iLastInsertPos = -1;
m_iHead = loc;
m_iLength --;
}
else if (offset > 0)
{
int h = m_iHead;
if (seqno == m_piData1[loc])
{
// target node is not empty, remove part/all of the seqno in the node.
int temp = loc;
loc = (loc + 1) % m_iSize;
if (-1 == m_piData2[temp])
m_iHead = m_piNext[temp];
else
{
// remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3)
m_piData1[loc] = CSeqNo::incseq(seqno);
if (CSeqNo::seqcmp(m_piData2[temp], m_piData1[loc]) > 0)
m_piData2[loc] = m_piData2[temp];
m_iHead = loc;
m_piNext[loc] = m_piNext[temp];
m_piNext[temp] = loc;
m_piData2[temp] = -1;
}
}
else
{
// target node is empty, check prior node
int i = m_iHead;
while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno) < 0))
i = m_piNext[i];
loc = (loc + 1) % m_iSize;
if (-1 == m_piData2[i])
m_iHead = m_piNext[i];
else if (CSeqNo::seqcmp(m_piData2[i], seqno) > 0)
{
// remove part/all seqno in the prior node
m_piData1[loc] = CSeqNo::incseq(seqno);
if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0)
m_piData2[loc] = m_piData2[i];
m_piData2[i] = seqno;
m_piNext[loc] = m_piNext[i];
m_piNext[i] = loc;
m_iHead = loc;
}
else
m_iHead = m_piNext[i];
}
// Remove all nodes prior to the new head
while (h != m_iHead)
{
if (m_piData2[h] != -1)
{
m_iLength -= CSeqNo::seqlen(m_piData1[h], m_piData2[h]);
m_piData2[h] = -1;
}
else
m_iLength --;
m_piData1[h] = -1;
if (m_iLastInsertPos == h)
m_iLastInsertPos = -1;
h = m_piNext[h];
}
}
}
int CSndLossList::getLossLength()
{
CGuard listguard(m_ListLock);
return m_iLength;
}
int32_t CSndLossList::getLostSeq()
{
if (0 == m_iLength)
return -1;
CGuard listguard(m_ListLock);
if (0 == m_iLength)
return -1;
if (m_iLastInsertPos == m_iHead)
m_iLastInsertPos = -1;
// return the first loss seq. no.
int32_t seqno = m_piData1[m_iHead];
// head moves to the next node
if (-1 == m_piData2[m_iHead])
{
//[3, -1] becomes [], and head moves to next node in the list
m_piData1[m_iHead] = -1;
m_iHead = m_piNext[m_iHead];
}
else
{
// shift to next node, e.g., [3, 7] becomes [], [4, 7]
int loc = (m_iHead + 1) % m_iSize;
m_piData1[loc] = CSeqNo::incseq(seqno);
if (CSeqNo::seqcmp(m_piData2[m_iHead], m_piData1[loc]) > 0)
m_piData2[loc] = m_piData2[m_iHead];
m_piData1[m_iHead] = -1;
m_piData2[m_iHead] = -1;
m_piNext[loc] = m_piNext[m_iHead];
m_iHead = loc;
}
m_iLength --;
return seqno;
}
////////////////////////////////////////////////////////////////////////////////
CRcvLossList::CRcvLossList(int size):
m_piData1(NULL),
m_piData2(NULL),
m_piNext(NULL),
m_piPrior(NULL),
m_iHead(-1),
m_iTail(-1),
m_iLength(0),
m_iSize(size)
{
m_piData1 = new int32_t [m_iSize];
m_piData2 = new int32_t [m_iSize];
m_piNext = new int [m_iSize];
m_piPrior = new int [m_iSize];
// -1 means there is no data in the node
for (int i = 0; i < size; ++ i)
{
m_piData1[i] = -1;
m_piData2[i] = -1;
}
}
CRcvLossList::~CRcvLossList()
{
delete [] m_piData1;
delete [] m_piData2;
delete [] m_piNext;
delete [] m_piPrior;
}
void CRcvLossList::insert(int32_t seqno1, int32_t seqno2)
{
// Data to be inserted must be larger than all those in the list
// guaranteed by the UDT receiver
if (0 == m_iLength)
{
// insert data into an empty list
m_iHead = 0;
m_iTail = 0;
m_piData1[m_iHead] = seqno1;
if (seqno2 != seqno1)
m_piData2[m_iHead] = seqno2;
m_piNext[m_iHead] = -1;
m_piPrior[m_iHead] = -1;
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
return;
}
// otherwise searching for the position where the node should be
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1);
int loc = (m_iHead + offset) % m_iSize;
if ((-1 != m_piData2[m_iTail]) && (CSeqNo::incseq(m_piData2[m_iTail]) == seqno1))
{
// coalesce with prior node, e.g., [2, 5], [6, 7] becomes [2, 7]
loc = m_iTail;
m_piData2[loc] = seqno2;
}
else
{
// create new node
m_piData1[loc] = seqno1;
if (seqno2 != seqno1)
m_piData2[loc] = seqno2;
m_piNext[m_iTail] = loc;
m_piPrior[loc] = m_iTail;
m_piNext[loc] = -1;
m_iTail = loc;
}
m_iLength += CSeqNo::seqlen(seqno1, seqno2);
}
bool CRcvLossList::remove(int32_t seqno)
{
if (0 == m_iLength)
return false;
// locate the position of "seqno" in the list
int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno);
if (offset < 0)
return false;
int loc = (m_iHead + offset) % m_iSize;
if (seqno == m_piData1[loc])
{
// This is a seq. no. that starts the loss sequence
if (-1 == m_piData2[loc])
{
// there is only 1 loss in the sequence, delete it from the node
if (m_iHead == loc)
{
m_iHead = m_piNext[m_iHead];
if (-1 != m_iHead)
m_piPrior[m_iHead] = -1;
}
else
{
m_piNext[m_piPrior[loc]] = m_piNext[loc];
if (-1 != m_piNext[loc])
m_piPrior[m_piNext[loc]] = m_piPrior[loc];
else
m_iTail = m_piPrior[loc];
}
m_piData1[loc] = -1;
}
else
{
// there are more than 1 loss in the sequence
// move the node to the next and update the starter as the next loss inSeqNo(seqno)
// find next node
int i = (loc + 1) % m_iSize;
// remove the "seqno" and change the starter as next seq. no.
m_piData1[i] = CSeqNo::incseq(m_piData1[loc]);
// process the sequence end
if (CSeqNo::seqcmp(m_piData2[loc], CSeqNo::incseq(m_piData1[loc])) > 0)
m_piData2[i] = m_piData2[loc];
// remove the current node
m_piData1[loc] = -1;
m_piData2[loc] = -1;
// update list pointer
m_piNext[i] = m_piNext[loc];
m_piPrior[i] = m_piPrior[loc];
if (m_iHead == loc)
m_iHead = i;
else
m_piNext[m_piPrior[i]] = i;
if (m_iTail == loc)
m_iTail = i;
else
m_piPrior[m_piNext[i]] = i;
}
m_iLength --;
return true;
}
// There is no loss sequence in the current position
// the "seqno" may be contained in a previous node
// searching previous node
int i = (loc - 1 + m_iSize) % m_iSize;
while (-1 == m_piData1[i])
i = (i - 1 + m_iSize) % m_iSize;
// not contained in this node, return
if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(seqno, m_piData2[i]) > 0))
return false;
if (seqno == m_piData2[i])
{
// it is the sequence end
if (seqno == CSeqNo::incseq(m_piData1[i]))
m_piData2[i] = -1;
else
m_piData2[i] = CSeqNo::decseq(seqno);
}
else
{
// split the sequence
// construct the second sequence from CSeqNo::incseq(seqno) to the original sequence end
// located at "loc + 1"
loc = (loc + 1) % m_iSize;
m_piData1[loc] = CSeqNo::incseq(seqno);
if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0)
m_piData2[loc] = m_piData2[i];
// the first (original) sequence is between the original sequence start to CSeqNo::decseq(seqno)
if (seqno == CSeqNo::incseq(m_piData1[i]))
m_piData2[i] = -1;
else
m_piData2[i] = CSeqNo::decseq(seqno);
// update the list pointer
m_piNext[loc] = m_piNext[i];
m_piNext[i] = loc;
m_piPrior[loc] = i;
if (m_iTail == i)
m_iTail = loc;
else
m_piPrior[m_piNext[loc]] = loc;
}
m_iLength --;
return true;
}
bool CRcvLossList::remove(int32_t seqno1, int32_t seqno2)
{
if (seqno1 <= seqno2)
{
for (int32_t i = seqno1; i <= seqno2; ++ i)
remove(i);
}
else
{
for (int32_t j = seqno1; j < CSeqNo::m_iMaxSeqNo; ++ j)
remove(j);
for (int32_t k = 0; k <= seqno2; ++ k)
remove(k);
}
return true;
}
bool CRcvLossList::find(int32_t seqno1, int32_t seqno2) const
{
if (0 == m_iLength)
return false;
int p = m_iHead;
while (-1 != p)
{
if ((CSeqNo::seqcmp(m_piData1[p], seqno1) == 0) ||
((CSeqNo::seqcmp(m_piData1[p], seqno1) > 0) && (CSeqNo::seqcmp(m_piData1[p], seqno2) <= 0)) ||
((CSeqNo::seqcmp(m_piData1[p], seqno1) < 0) && (m_piData2[p] != -1) && CSeqNo::seqcmp(m_piData2[p], seqno1) >= 0))
return true;
p = m_piNext[p];
}
return false;
}
int CRcvLossList::getLossLength() const
{
return m_iLength;
}
int CRcvLossList::getFirstLostSeq() const
{
if (0 == m_iLength)
return -1;
return m_piData1[m_iHead];
}
void CRcvLossList::getLossArray(int32_t* array, int& len, int limit)
{
len = 0;
int i = m_iHead;
while ((len < limit - 1) && (-1 != i))
{
array[len] = m_piData1[i];
if (-1 != m_piData2[i])
{
// there are more than 1 loss in the sequence
array[len] |= 0x80000000;
++ len;
array[len] = m_piData2[i];
}
++ len;
i = m_piNext[i];
}
}

202
src/list.h Normal file
View File

@ -0,0 +1,202 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/22/2011
*****************************************************************************/
#ifndef __UDT_LIST_H__
#define __UDT_LIST_H__
#include "udt.h"
#include "udtCommon.h"
class CSndLossList
{
public:
CSndLossList(int size = 1024);
~CSndLossList();
// Functionality:
// Insert a seq. no. into the sender loss list.
// Parameters:
// 0) [in] seqno1: sequence number starts.
// 1) [in] seqno2: sequence number ends.
// Returned value:
// number of packets that are not in the list previously.
int insert(int32_t seqno1, int32_t seqno2);
// Functionality:
// Remove ALL the seq. no. that are not greater than the parameter.
// Parameters:
// 0) [in] seqno: sequence number.
// Returned value:
// None.
void remove(int32_t seqno);
// Functionality:
// Read the loss length.
// Parameters:
// None.
// Returned value:
// The length of the list.
int getLossLength();
// Functionality:
// Read the first (smallest) loss seq. no. in the list and remove it.
// Parameters:
// None.
// Returned value:
// The seq. no. or -1 if the list is empty.
int32_t getLostSeq();
private:
int32_t* m_piData1; // sequence number starts
int32_t* m_piData2; // seqnence number ends
int* m_piNext; // next node in the list
int m_iHead; // first node
int m_iLength; // loss length
int m_iSize; // size of the static array
int m_iLastInsertPos; // position of last insert node
udt_pthread_mutex_t m_ListLock; // used to synchronize list operation
private:
CSndLossList(const CSndLossList&);
CSndLossList& operator=(const CSndLossList&);
};
////////////////////////////////////////////////////////////////////////////////
class CRcvLossList
{
public:
CRcvLossList(int size = 1024);
~CRcvLossList();
// Functionality:
// Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list.
// Parameters:
// 0) [in] seqno1: sequence number starts.
// 1) [in] seqno2: seqeunce number ends.
// Returned value:
// None.
void insert(int32_t seqno1, int32_t seqno2);
// Functionality:
// Remove a loss seq. no. from the receiver's loss list.
// Parameters:
// 0) [in] seqno: sequence number.
// Returned value:
// if the packet is removed (true) or no such lost packet is found (false).
bool remove(int32_t seqno);
// Functionality:
// Remove all packets between seqno1 and seqno2.
// Parameters:
// 0) [in] seqno1: start sequence number.
// 1) [in] seqno2: end sequence number.
// Returned value:
// if the packet is removed (true) or no such lost packet is found (false).
bool remove(int32_t seqno1, int32_t seqno2);
// Functionality:
// Find if there is any lost packets whose sequence number falling seqno1 and seqno2.
// Parameters:
// 0) [in] seqno1: start sequence number.
// 1) [in] seqno2: end sequence number.
// Returned value:
// True if found; otherwise false.
bool find(int32_t seqno1, int32_t seqno2) const;
// Functionality:
// Read the loss length.
// Parameters:
// None.
// Returned value:
// the length of the list.
int getLossLength() const;
// Functionality:
// Read the first (smallest) seq. no. in the list.
// Parameters:
// None.
// Returned value:
// the sequence number or -1 if the list is empty.
int getFirstLostSeq() const;
// Functionality:
// Get a encoded loss array for NAK report.
// Parameters:
// 0) [out] array: the result list of seq. no. to be included in NAK.
// 1) [out] physical length of the result array.
// 2) [in] limit: maximum length of the array.
// Returned value:
// None.
void getLossArray(int32_t* array, int& len, int limit);
private:
int32_t* m_piData1; // sequence number starts
int32_t* m_piData2; // sequence number ends
int* m_piNext; // next node in the list
int* m_piPrior; // prior node in the list;
int m_iHead; // first node in the list
int m_iTail; // last node in the list;
int m_iLength; // loss length
int m_iSize; // size of the static array
private:
CRcvLossList(const CRcvLossList&);
CRcvLossList& operator=(const CRcvLossList&);
};
#endif

381
src/md5.cpp Normal file
View File

@ -0,0 +1,381 @@
/*
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.cpp,v 1.3 2008/01/20 22:52:04 lilyco Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.c is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
either statically or dynamically; added missing #include <string.h>
in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
unsigned in ANSI C, signed in traditional"; made test program
self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
*/
#include "md5.h"
#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int w = 1;
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
# else
# define xbuf X /* (static only) */
# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void
md5_init(md5_state_t *pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
{
const md5_byte_t *p = data;
int left = nbytes;
int offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}

91
src/md5.h Normal file
View File

@ -0,0 +1,91 @@
/*
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.h,v 1.2 2007/12/24 05:58:37 lilyco Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

411
src/packet.cpp Normal file
View File

@ -0,0 +1,411 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 02/12/2011
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Packet Header |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// ~ Data / Control Information Field ~
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0| Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |ff |o| Message Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time Stamp |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Destination Socket ID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// bit 0:
// 0: Data Packet
// 1: Control Packet
// bit ff:
// 11: solo message packet
// 10: first packet of a message
// 01: last packet of a message
// bit o:
// 0: in order delivery not required
// 1: in order delivery required
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |1| Type | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Additional Info |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time Stamp |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Destination Socket ID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// bit 1-15:
// 0: Protocol Connection Handshake
// Add. Info: Undefined
// Control Info: Handshake information (see CHandShake)
// 1: Keep-alive
// Add. Info: Undefined
// Control Info: None
// 2: Acknowledgement (ACK)
// Add. Info: The ACK sequence number
// Control Info: The sequence number to which (but not include) all the previous packets have beed received
// Optional: RTT
// RTT Variance
// available receiver buffer size (in bytes)
// advertised flow window size (number of packets)
// estimated bandwidth (number of packets per second)
// 3: Negative Acknowledgement (NAK)
// Add. Info: Undefined
// Control Info: Loss list (see loss list coding below)
// 4: Congestion/Delay Warning
// Add. Info: Undefined
// Control Info: None
// 5: Shutdown
// Add. Info: Undefined
// Control Info: None
// 6: Acknowledgement of Acknowledement (ACK-square)
// Add. Info: The ACK sequence number
// Control Info: None
// 7: Message Drop Request
// Add. Info: Message ID
// Control Info: first sequence number of the message
// last seqeunce number of the message
// 8: Error Signal from the Peer Side
// Add. Info: Error code
// Control Info: None
// 0x7FFF: Explained by bits 16 - 31
//
// bit 16 - 31:
// This space is used for future expansion or user defined control packets.
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |1| Sequence Number a (first) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0| Sequence Number b (last) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0| Sequence Number (single) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Loss List Field Coding:
// For any consectutive lost seqeunce numbers that the differnece between
// the last and first is more than 1, only record the first (a) and the
// the last (b) sequence numbers in the loss list field, and modify the
// the first bit of a to 1.
// For any single loss or consectutive loss less than 2 packets, use
// the original sequence numbers in the field.
#include <cstring>
#include "packet.h"
const int CPacket::m_iPktHdrSize = 16;
const int CHandShake::m_iContentSize = 48;
// Set up the aliases in the constructure
CPacket::CPacket():
m_iSeqNo((int32_t&)(m_nHeader[0])),
m_iMsgNo((int32_t&)(m_nHeader[1])),
m_iTimeStamp((int32_t&)(m_nHeader[2])),
m_iID((int32_t&)(m_nHeader[3])),
m_pcData((char*&)(m_PacketVector[1].iov_base)),
__pad()
{
for (int i = 0; i < 4; ++ i)
m_nHeader[i] = 0;
m_PacketVector[0].iov_base = (char *)m_nHeader;
m_PacketVector[0].iov_len = CPacket::m_iPktHdrSize;
m_PacketVector[1].iov_base = NULL;
m_PacketVector[1].iov_len = 0;
}
CPacket::~CPacket()
{
}
int CPacket::getLength() const
{
return m_PacketVector[1].iov_len;
}
void CPacket::setLength(int len)
{
m_PacketVector[1].iov_len = len;
}
void CPacket::pack(int pkttype, void* lparam, void* rparam, int size)
{
// Set (bit-0 = 1) and (bit-1~15 = type)
m_nHeader[0] = 0x80000000 | (pkttype << 16);
// Set additional information and control information field
switch (pkttype)
{
case 2: //0010 - Acknowledgement (ACK)
// ACK packet seq. no.
if (NULL != lparam)
m_nHeader[1] = *(int32_t *)lparam;
// data ACK seq. no.
// optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated link capacity (packets per second)
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
break;
case 6: //0110 - Acknowledgement of Acknowledgement (ACK-2)
// ACK packet seq. no.
m_nHeader[1] = *(int32_t *)lparam;
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 3: //0011 - Loss Report (NAK)
// loss list
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
break;
case 4: //0100 - Congestion Warning
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 1: //0001 - Keep-alive
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 0: //0000 - Handshake
// control info filed is handshake info
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size; //sizeof(CHandShake);
break;
case 5: //0101 - Shutdown
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 7: //0111 - Message Drop Request
// msg id
m_nHeader[1] = *(int32_t *)lparam;
//first seq no, last seq no
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
break;
case 8: //1000 - Error Signal from the Peer Side
// Error type
m_nHeader[1] = *(int32_t *)lparam;
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 32767: //0x7FFF - Reserved for user defined control packets
// for extended control packet
// "lparam" contains the extended type information for bit 16 - 31
// "rparam" is the control information
m_nHeader[0] |= *(int32_t *)lparam;
if (NULL != rparam)
{
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
}
else
{
m_PacketVector[1].iov_base = (char *)&__pad;
m_PacketVector[1].iov_len = 4;
}
break;
default:
break;
}
}
iovec* CPacket::getPacketVector()
{
return m_PacketVector;
}
int CPacket::getFlag() const
{
// read bit 0
return m_nHeader[0] >> 31;
}
int CPacket::getType() const
{
// read bit 1~15
return (m_nHeader[0] >> 16) & 0x00007FFF;
}
int CPacket::getExtendedType() const
{
// read bit 16~31
return m_nHeader[0] & 0x0000FFFF;
}
int32_t CPacket::getAckSeqNo() const
{
// read additional information field
return m_nHeader[1];
}
int CPacket::getMsgBoundary() const
{
// read [1] bit 0~1
return m_nHeader[1] >> 30;
}
bool CPacket::getMsgOrderFlag() const
{
// read [1] bit 2
return (1 == ((m_nHeader[1] >> 29) & 1));
}
int32_t CPacket::getMsgSeq() const
{
// read [1] bit 3~31
return m_nHeader[1] & 0x1FFFFFFF;
}
CPacket* CPacket::clone() const
{
CPacket* pkt = new CPacket;
memcpy(pkt->m_nHeader, m_nHeader, m_iPktHdrSize);
pkt->m_pcData = new char[m_PacketVector[1].iov_len];
memcpy(pkt->m_pcData, m_pcData, m_PacketVector[1].iov_len);
pkt->m_PacketVector[1].iov_len = m_PacketVector[1].iov_len;
return pkt;
}
CHandShake::CHandShake():
m_iVersion(0),
m_iType(0),
m_iISN(0),
m_iMSS(0),
m_iFlightFlagSize(0),
m_iReqType(0),
m_iID(0),
m_iCookie(0)
{
for (int i = 0; i < 4; ++ i)
m_piPeerIP[i] = 0;
}
int CHandShake::serialize(char* buf, int& size)
{
if (size < m_iContentSize)
return -1;
int32_t* p = (int32_t*)buf;
*p++ = m_iVersion;
*p++ = m_iType;
*p++ = m_iISN;
*p++ = m_iMSS;
*p++ = m_iFlightFlagSize;
*p++ = m_iReqType;
*p++ = m_iID;
*p++ = m_iCookie;
for (int i = 0; i < 4; ++ i)
*p++ = m_piPeerIP[i];
size = m_iContentSize;
return 0;
}
int CHandShake::deserialize(const char* buf, int size)
{
if (size < m_iContentSize)
return -1;
int32_t* p = (int32_t*)buf;
m_iVersion = *p++;
m_iType = *p++;
m_iISN = *p++;
m_iMSS = *p++;
m_iFlightFlagSize = *p++;
m_iReqType = *p++;
m_iID = *p++;
m_iCookie = *p++;
for (int i = 0; i < 4; ++ i)
m_piPeerIP[i] = *p++;
return 0;
}

223
src/packet.h Normal file
View File

@ -0,0 +1,223 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/02/2011
*****************************************************************************/
#ifndef __UDT_PACKET_H__
#define __UDT_PACKET_H__
#include "udt.h"
#ifdef WINDOWS
struct iovec
{
int iov_len;
char* iov_base;
};
#endif
class CChannel;
class CPacket
{
friend class CChannel;
friend class CSndQueue;
friend class CRcvQueue;
public:
int32_t& m_iSeqNo; // alias: sequence number
int32_t& m_iMsgNo; // alias: message number
int32_t& m_iTimeStamp; // alias: timestamp
int32_t& m_iID; // alias: socket ID
char*& m_pcData; // alias: data/control information
static const int m_iPktHdrSize; // packet header size
public:
CPacket();
~CPacket();
// Functionality:
// Get the payload or the control information field length.
// Parameters:
// None.
// Returned value:
// the payload or the control information field length.
int getLength() const;
// Functionality:
// Set the payload or the control information field length.
// Parameters:
// 0) [in] len: the payload or the control information field length.
// Returned value:
// None.
void setLength(int len);
// Functionality:
// Pack a Control packet.
// Parameters:
// 0) [in] pkttype: packet type filed.
// 1) [in] lparam: pointer to the first data structure, explained by the packet type.
// 2) [in] rparam: pointer to the second data structure, explained by the packet type.
// 3) [in] size: size of rparam, in number of bytes;
// Returned value:
// None.
void pack(int pkttype, void* lparam = NULL, void* rparam = NULL, int size = 0);
// Functionality:
// Read the packet vector.
// Parameters:
// None.
// Returned value:
// Pointer to the packet vector.
iovec* getPacketVector();
// Functionality:
// Read the packet flag.
// Parameters:
// None.
// Returned value:
// packet flag (0 or 1).
int getFlag() const;
// Functionality:
// Read the packet type.
// Parameters:
// None.
// Returned value:
// packet type filed (000 ~ 111).
int getType() const;
// Functionality:
// Read the extended packet type.
// Parameters:
// None.
// Returned value:
// extended packet type filed (0x000 ~ 0xFFF).
int getExtendedType() const;
// Functionality:
// Read the ACK-2 seq. no.
// Parameters:
// None.
// Returned value:
// packet header field (bit 16~31).
int32_t getAckSeqNo() const;
// Functionality:
// Read the message boundary flag bit.
// Parameters:
// None.
// Returned value:
// packet header field [1] (bit 0~1).
int getMsgBoundary() const;
// Functionality:
// Read the message inorder delivery flag bit.
// Parameters:
// None.
// Returned value:
// packet header field [1] (bit 2).
bool getMsgOrderFlag() const;
// Functionality:
// Read the message sequence number.
// Parameters:
// None.
// Returned value:
// packet header field [1] (bit 3~31).
int32_t getMsgSeq() const;
// Functionality:
// Clone this packet.
// Parameters:
// None.
// Returned value:
// Pointer to the new packet.
CPacket* clone() const;
protected:
uint32_t m_nHeader[4]; // The 128-bit header field
iovec m_PacketVector[2]; // The 2-demension vector of UDT packet [header, data]
int32_t __pad;
protected:
CPacket& operator=(const CPacket&);
};
////////////////////////////////////////////////////////////////////////////////
class CHandShake
{
public:
CHandShake();
int serialize(char* buf, int& size);
int deserialize(const char* buf, int size);
public:
static const int m_iContentSize; // Size of hand shake data
public:
int32_t m_iVersion; // UDT version
int32_t m_iType; // UDT socket type
int32_t m_iISN; // random initial sequence number
int32_t m_iMSS; // maximum segment size
int32_t m_iFlightFlagSize; // flow control window size
int32_t m_iReqType; // connection request type: 1: regular connection request, 0: rendezvous connection request, -1/-2: response
int32_t m_iID; // socket ID
int32_t m_iCookie; // cookie
uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to
};
#endif

1251
src/queue.cpp Normal file

File diff suppressed because it is too large Load Diff

527
src/queue.h Normal file
View File

@ -0,0 +1,527 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/12/2011
*****************************************************************************/
#ifndef __UDT_QUEUE_H__
#define __UDT_QUEUE_H__
#include "channel.h"
#include "packet.h"
#include <list>
#include <map>
#include <queue>
#include <vector>
#include "udtCommon.h"
class CUDT;
struct CUnit
{
CPacket m_Packet; // packet
int m_iFlag; // 0: free, 1: occupied, 2: msg read but not freed (out-of-order), 3: msg dropped
};
class CUnitQueue
{
friend class CRcvQueue;
friend class CRcvBuffer;
public:
CUnitQueue();
~CUnitQueue();
public:
// Functionality:
// Initialize the unit queue.
// Parameters:
// 1) [in] size: queue size
// 2) [in] mss: maximum segament size
// 3) [in] version: IP version
// Returned value:
// 0: success, -1: failure.
int init(int size, int mss, int version);
// Functionality:
// Increase (double) the unit queue size.
// Parameters:
// None.
// Returned value:
// 0: success, -1: failure.
int increase();
// Functionality:
// Decrease (halve) the unit queue size.
// Parameters:
// None.
// Returned value:
// 0: success, -1: failure.
int shrink();
// Functionality:
// find an available unit for incoming packet.
// Parameters:
// None.
// Returned value:
// Pointer to the available unit, NULL if not found.
CUnit* getNextAvailUnit();
private:
struct CQEntry
{
CUnit* m_pUnit; // unit queue
char* m_pBuffer; // data buffer
int m_iSize; // size of each queue
CQEntry* m_pNext;
}
*m_pQEntry, // pointer to the first unit queue
*m_pCurrQueue, // pointer to the current available queue
*m_pLastQueue; // pointer to the last unit queue
CUnit* m_pAvailUnit; // recent available unit
int m_iSize; // total size of the unit queue, in number of packets
int m_iCount; // total number of valid packets in the queue
int m_iMSS; // unit buffer size
int m_iIPversion; // IP version
private:
CUnitQueue(const CUnitQueue&);
CUnitQueue& operator=(const CUnitQueue&);
};
struct CSNode
{
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
uint64_t m_llTimeStamp; // Time Stamp
int m_iHeapLoc; // location on the heap, -1 means not on the heap
};
class CSndUList
{
friend class CSndQueue;
public:
CSndUList();
~CSndUList();
public:
// Functionality:
// Insert a new UDT instance into the list.
// Parameters:
// 1) [in] ts: time stamp: next processing time
// 2) [in] u: pointer to the UDT instance
// Returned value:
// None.
void insert(int64_t ts, const CUDT* u);
// Functionality:
// Update the timestamp of the UDT instance on the list.
// Parameters:
// 1) [in] u: pointer to the UDT instance
// 2) [in] resechedule: if the timestampe shoudl be rescheduled
// Returned value:
// None.
void update(const CUDT* u, bool reschedule = true);
// Functionality:
// Retrieve the next packet and peer address from the first entry, and reschedule it in the queue.
// Parameters:
// 0) [out] addr: destination address of the next packet
// 1) [out] pkt: the next packet to be sent
// Returned value:
// 1 if successfully retrieved, -1 if no packet found.
int pop(sockaddr*& addr, CPacket& pkt);
// Functionality:
// Remove UDT instance from the list.
// Parameters:
// 1) [in] u: pointer to the UDT instance
// Returned value:
// None.
void remove(const CUDT* u);
// Functionality:
// Retrieve the next scheduled processing time.
// Parameters:
// None.
// Returned value:
// Scheduled processing time of the first UDT socket in the list.
uint64_t getNextProcTime();
private:
void insert_(int64_t ts, const CUDT* u);
void remove_(const CUDT* u);
private:
CSNode** m_pHeap; // The heap array
int m_iArrayLength; // physical length of the array
int m_iLastEntry; // position of last entry on the heap array
udt_pthread_mutex_t m_ListLock;
udt_pthread_mutex_t* m_pWindowLock;
udt_pthread_cond_t* m_pWindowCond;
CTimer* m_pTimer;
private:
CSndUList(const CSndUList&);
CSndUList& operator=(const CSndUList&);
};
struct CRNode
{
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
uint64_t m_llTimeStamp; // Time Stamp
CRNode* m_pPrev; // previous link
CRNode* m_pNext; // next link
bool m_bOnList; // if the node is already on the list
};
class CRcvUList
{
public:
CRcvUList();
~CRcvUList();
public:
// Functionality:
// Insert a new UDT instance to the list.
// Parameters:
// 1) [in] u: pointer to the UDT instance
// Returned value:
// None.
void insert(const CUDT* u);
// Functionality:
// Remove the UDT instance from the list.
// Parameters:
// 1) [in] u: pointer to the UDT instance
// Returned value:
// None.
void remove(const CUDT* u);
// Functionality:
// Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing.
// Parameters:
// 1) [in] u: pointer to the UDT instance
// Returned value:
// None.
void update(const CUDT* u);
public:
CRNode* m_pUList; // the head node
private:
CRNode* m_pLast; // the last node
private:
CRcvUList(const CRcvUList&);
CRcvUList& operator=(const CRcvUList&);
};
class CHash
{
public:
CHash();
~CHash();
public:
// Functionality:
// Initialize the hash table.
// Parameters:
// 1) [in] size: hash table size
// Returned value:
// None.
void init(int size);
// Functionality:
// Look for a UDT instance from the hash table.
// Parameters:
// 1) [in] id: socket ID
// Returned value:
// Pointer to a UDT instance, or NULL if not found.
CUDT* lookup(int32_t id);
// Functionality:
// Insert an entry to the hash table.
// Parameters:
// 1) [in] id: socket ID
// 2) [in] u: pointer to the UDT instance
// Returned value:
// None.
void insert(int32_t id, CUDT* u);
// Functionality:
// Remove an entry from the hash table.
// Parameters:
// 1) [in] id: socket ID
// Returned value:
// None.
void remove(int32_t id);
private:
struct CBucket
{
int32_t m_iID; // Socket ID
CUDT* m_pUDT; // Socket instance
CBucket* m_pNext; // next bucket
} **m_pBucket; // list of buckets (the hash table)
int m_iHashSize; // size of hash table
private:
CHash(const CHash&);
CHash& operator=(const CHash&);
};
class CRendezvousQueue
{
public:
CRendezvousQueue();
~CRendezvousQueue();
public:
void insert(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl);
void remove(const UDTSOCKET& id);
CUDT* retrieve(const sockaddr* addr, UDTSOCKET& id);
void updateConnStatus();
private:
struct CRL
{
UDTSOCKET m_iID; // UDT socket ID (self)
CUDT* m_pUDT; // UDT instance
int m_iIPversion; // IP version
sockaddr* m_pPeerAddr; // UDT sonnection peer address
uint64_t m_ullTTL; // the time that this request expires
};
std::list<CRL> m_lRendezvousID; // The sockets currently in rendezvous mode
udt_pthread_mutex_t m_RIDVectorLock;
};
class CSndQueue
{
friend class CUDT;
friend class CUDTUnited;
public:
CSndQueue();
~CSndQueue();
public:
// Functionality:
// Initialize the sending queue.
// Parameters:
// 1) [in] c: UDP channel to be associated to the queue
// 2) [in] t: Timer
// Returned value:
// None.
void init(CChannel* c, CTimer* t);
// Functionality:
// Send out a packet to a given address.
// Parameters:
// 1) [in] addr: destination address
// 2) [in] packet: packet to be sent out
// Returned value:
// Size of data sent out.
int sendto(const sockaddr* addr, CPacket& packet);
private:
#ifndef WINDOWS
static void* worker(void* param);
#else
static DWORD WINAPI worker(LPVOID param);
#endif
udt_pthread_t m_WorkerThread;
private:
CSndUList* m_pSndUList; // List of UDT instances for data sending
CChannel* m_pChannel; // The UDP channel for data sending
CTimer* m_pTimer; // Timing facility
udt_pthread_mutex_t m_WindowLock;
udt_pthread_cond_t m_WindowCond;
volatile bool m_bClosing; // closing the worker
udt_pthread_cond_t m_ExitCond;
private:
CSndQueue(const CSndQueue&);
CSndQueue& operator=(const CSndQueue&);
};
class CRcvQueue
{
friend class CUDT;
friend class CUDTUnited;
public:
CRcvQueue();
~CRcvQueue();
public:
// Functionality:
// Initialize the receiving queue.
// Parameters:
// 1) [in] size: queue size
// 2) [in] mss: maximum packet size
// 3) [in] version: IP version
// 4) [in] hsize: hash table size
// 5) [in] c: UDP channel to be associated to the queue
// 6) [in] t: timer
// Returned value:
// None.
void init(int size, int payload, int version, int hsize, CChannel* c, CTimer* t);
// Functionality:
// Read a packet for a specific UDT socket id.
// Parameters:
// 1) [in] id: Socket ID
// 2) [out] packet: received packet
// Returned value:
// Data size of the packet
int recvfrom(int32_t id, CPacket& packet);
private:
#ifndef WINDOWS
static void* worker(void* param);
#else
static DWORD WINAPI worker(LPVOID param);
#endif
udt_pthread_t m_WorkerThread;
private:
CUnitQueue m_UnitQueue; // The received packet queue
CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue
CHash* m_pHash; // Hash table for UDT socket looking up
CChannel* m_pChannel; // UDP channel for receving packets
CTimer* m_pTimer; // shared timer with the snd queue
int m_iPayloadSize; // packet payload size
volatile bool m_bClosing; // closing the workder
udt_pthread_cond_t m_ExitCond;
private:
int setListener(CUDT* u);
void removeListener(const CUDT* u);
void registerConnector(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl);
void removeConnector(const UDTSOCKET& id);
void setNewEntry(CUDT* u);
bool ifNewEntry();
CUDT* getNewEntry();
void storePkt(int32_t id, CPacket* pkt);
private:
udt_pthread_mutex_t m_LSLock;
CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity
CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode
std::vector<CUDT*> m_vNewEntry; // newly added entries, to be inserted
udt_pthread_mutex_t m_IDLock;
std::map<int32_t, std::queue<CPacket*> > m_mBuffer; // temporary buffer for rendezvous connection request
udt_pthread_mutex_t m_PassLock;
udt_pthread_cond_t m_PassCond;
private:
CRcvQueue(const CRcvQueue&);
CRcvQueue& operator=(const CRcvQueue&);
};
struct CMultiplexer
{
CSndQueue* m_pSndQueue; // The sending queue
CRcvQueue* m_pRcvQueue; // The receiving queue
CChannel* m_pChannel; // The UDP channel for sending and receiving
CTimer* m_pTimer; // The timer
int m_iPort; // The UDP port number of this multiplexer
int m_iIPversion; // IP version
int m_iMSS; // Maximum Segment Size
int m_iRefCount; // number of UDT instances that are associated with this multiplexer
bool m_bReusable; // if this one can be shared with others
int m_iID; // multiplexer ID
};
#endif

326
src/udt.h Normal file
View File

@ -0,0 +1,326 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/18/2011
*****************************************************************************/
#ifndef __UDT_H__
#define __UDT_H__
#ifndef WINDOWS
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#else
#include <stdint.h>
#include <ws2tcpip.h>
#include <windows.h>
#endif
#include <fstream>
#include <set>
#include <string>
#include <vector>
////////////////////////////////////////////////////////////////////////////////
#ifdef WINDOWS
typedef SOCKET SYSSOCKET;
#define UDT_API
#else
typedef int SYSSOCKET;
#define UDT_API __attribute__ ((visibility("default")))
#endif
#define NO_BUSY_WAITING
typedef SYSSOCKET UDPSOCKET;
typedef int UDTSOCKET;
////////////////////////////////////////////////////////////////////////////////
typedef std::set<UDTSOCKET> ud_set;
#define UD_CLR(u, uset) ((uset)->erase(u))
#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end())
#define UD_SET(u, uset) ((uset)->insert(u))
#define UD_ZERO(uset) ((uset)->clear())
enum EPOLLOpt
{
// this values are defined same as linux epoll.h
// so that if system values are used by mistake, they should have the same effect
UDT_EPOLL_IN = 0x1,
UDT_EPOLL_OUT = 0x4,
UDT_EPOLL_ERR = 0x8
};
enum UDTSTATUS {INIT = 1, OPENED, LISTENING, CONNECTING, CONNECTED, BROKEN, CLOSING, CLOSED, NONEXIST};
////////////////////////////////////////////////////////////////////////////////
enum UDTOpt
{
UDT_MSS, // the Maximum Transfer Unit
UDT_SNDSYN, // if sending is blocking
UDT_RCVSYN, // if receiving is blocking
UDT_CC, // custom congestion control algorithm
UDT_FC, // Flight flag size (window size)
UDT_SNDBUF, // maximum buffer in sending queue
UDT_RCVBUF, // UDT receiving buffer size
UDT_LINGER, // waiting for unsent data when closing
UDP_SNDBUF, // UDP sending buffer size
UDP_RCVBUF, // UDP receiving buffer size
UDT_MAXMSG, // maximum datagram message size
UDT_MSGTTL, // time-to-live of a datagram message
UDT_RENDEZVOUS, // rendezvous connection mode
UDT_SNDTIMEO, // send() timeout
UDT_RCVTIMEO, // recv() timeout
UDT_REUSEADDR, // reuse an existing port or create a new one
UDT_MAXBW, // maximum bandwidth (bytes per second) that the connection can use
UDT_STATE, // current socket state, see UDTSTATUS, read only
UDT_EVENT, // current avalable events associated with the socket
UDT_SNDDATA, // size of data in the sending buffer
UDT_RCVDATA // size of data available for recv
};
////////////////////////////////////////////////////////////////////////////////
struct CPerfMon
{
// global measurements
int64_t msTimeStamp; // time since the UDT entity is started, in milliseconds
int64_t pktSentTotal; // total number of sent data packets, including retransmissions
int64_t pktRecvTotal; // total number of received packets
int pktSndLossTotal; // total number of lost packets (sender side)
int pktRcvLossTotal; // total number of lost packets (receiver side)
int pktRetransTotal; // total number of retransmitted packets
int pktSentACKTotal; // total number of sent ACK packets
int pktRecvACKTotal; // total number of received ACK packets
int pktSentNAKTotal; // total number of sent NAK packets
int pktRecvNAKTotal; // total number of received NAK packets
int64_t usSndDurationTotal; // total time duration when UDT is sending data (idle time exclusive)
// local measurements
int64_t pktSent; // number of sent data packets, including retransmissions
int64_t pktRecv; // number of received packets
int pktSndLoss; // number of lost packets (sender side)
int pktRcvLoss; // number of lost packets (receiver side)
int pktRetrans; // number of retransmitted packets
int pktSentACK; // number of sent ACK packets
int pktRecvACK; // number of received ACK packets
int pktSentNAK; // number of sent NAK packets
int pktRecvNAK; // number of received NAK packets
double mbpsSendRate; // sending rate in Mb/s
double mbpsRecvRate; // receiving rate in Mb/s
int64_t usSndDuration; // busy sending time (i.e., idle time exclusive)
// instant measurements
double usPktSndPeriod; // packet sending period, in microseconds
int pktFlowWindow; // flow window size, in number of packets
int pktCongestionWindow; // congestion window size, in number of packets
int pktFlightSize; // number of packets on flight
double msRTT; // RTT, in milliseconds
double mbpsBandwidth; // estimated bandwidth, in Mb/s
int byteAvailSndBuf; // available UDT sender buffer size
int byteAvailRcvBuf; // available UDT receiver buffer size
};
////////////////////////////////////////////////////////////////////////////////
class UDT_API CUDTException
{
public:
CUDTException(int major = 0, int minor = 0, int err = -1);
CUDTException(const CUDTException& e);
virtual ~CUDTException();
// Functionality:
// Get the description of the exception.
// Parameters:
// None.
// Returned value:
// Text message for the exception description.
virtual const char* getErrorMessage();
// Functionality:
// Get the system errno for the exception.
// Parameters:
// None.
// Returned value:
// errno.
virtual int getErrorCode() const;
// Functionality:
// Clear the error code.
// Parameters:
// None.
// Returned value:
// None.
virtual void clear();
private:
int m_iMajor; // major exception categories
// 0: correct condition
// 1: network setup exception
// 2: network connection broken
// 3: memory exception
// 4: file exception
// 5: method not supported
// 6+: undefined error
int m_iMinor; // for specific error reasons
int m_iErrno; // errno returned by the system if there is any
std::string m_strMsg; // text error message
std::string m_strAPI; // the name of UDT function that returns the error
std::string m_strDebug; // debug information, set to the original place that causes the error
public: // Error Code
static const int SUCCESS;
static const int ECONNSETUP;
static const int ENOSERVER;
static const int ECONNREJ;
static const int ESOCKFAIL;
static const int ESECFAIL;
static const int ECONNFAIL;
static const int ECONNLOST;
static const int ENOCONN;
static const int ERESOURCE;
static const int ETHREAD;
static const int ENOBUF;
static const int EFILE;
static const int EINVRDOFF;
static const int ERDPERM;
static const int EINVWROFF;
static const int EWRPERM;
static const int EINVOP;
static const int EBOUNDSOCK;
static const int ECONNSOCK;
static const int EINVPARAM;
static const int EINVSOCK;
static const int EUNBOUNDSOCK;
static const int ENOLISTEN;
static const int ERDVNOSERV;
static const int ERDVUNBOUND;
static const int ESTREAMILL;
static const int EDGRAMILL;
static const int EDUPLISTEN;
static const int ELARGEMSG;
static const int EINVPOLLID;
static const int EASYNCFAIL;
static const int EASYNCSND;
static const int EASYNCRCV;
static const int ETIMEOUT;
static const int EPEERERR;
static const int EUNKNOWN;
};
////////////////////////////////////////////////////////////////////////////////
// If you need to export these APIs to be used by a different language,
// declare extern "C" for them, and add a "udt_" prefix to each API.
// The following APIs: sendfile(), recvfile(), epoll_wait(), geterrormsg(),
// include C++ specific feature, please use the corresponding sendfile2(), etc.
namespace UDT
{
typedef CUDTException ERRORINFO;
typedef UDTOpt SOCKOPT;
typedef CPerfMon TRACEINFO;
typedef ud_set UDSET;
UDT_API extern const UDTSOCKET INVALID_SOCK;
#undef ERROR
UDT_API extern const int ERROR;
UDT_API int startup();
UDT_API int cleanup();
UDT_API UDTSOCKET socket(int af, int type, int protocol);
UDT_API int bind(UDTSOCKET u, const struct sockaddr* name, int namelen);
UDT_API int bind2(UDTSOCKET u, UDPSOCKET udpsock);
UDT_API int listen(UDTSOCKET u, int backlog);
UDT_API UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen);
UDT_API int connect(UDTSOCKET u, const struct sockaddr* name, int namelen);
UDT_API int close(UDTSOCKET u);
UDT_API int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen);
UDT_API int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen);
UDT_API int getsockopt(UDTSOCKET u, int level, SOCKOPT optname, void* optval, int* optlen);
UDT_API int setsockopt(UDTSOCKET u, int level, SOCKOPT optname, const void* optval, int optlen);
UDT_API int send(UDTSOCKET u, const char* buf, int len, int flags);
UDT_API int recv(UDTSOCKET u, char* buf, int len, int flags);
UDT_API int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false);
UDT_API int recvmsg(UDTSOCKET u, char* buf, int len);
UDT_API int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000);
UDT_API int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000);
UDT_API int64_t sendfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000);
UDT_API int64_t recvfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000);
// select and selectEX are DEPRECATED; please use epoll.
UDT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout);
UDT_API int selectEx(const std::vector<UDTSOCKET>& fds, std::vector<UDTSOCKET>* readfds,
std::vector<UDTSOCKET>* writefds, std::vector<UDTSOCKET>* exceptfds, int64_t msTimeOut);
// BARCHART
UDT_API int epoll_update_usock(int eid, UDTSOCKET u, const int* events = NULL);
// BARCHART
UDT_API int epoll_verify_usock(int eid, UDTSOCKET u, int* events);
UDT_API int epoll_create();
UDT_API int epoll_add_usock(int eid, UDTSOCKET u, const int* events = NULL);
UDT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL);
UDT_API int epoll_remove_usock(int eid, UDTSOCKET u);
UDT_API int epoll_remove_ssock(int eid, SYSSOCKET s);
UDT_API int epoll_wait(int eid, std::set<UDTSOCKET>* readfds, std::set<UDTSOCKET>* writefds, int64_t msTimeOut,
std::set<SYSSOCKET>* lrfds = NULL, std::set<SYSSOCKET>* wrfds = NULL);
UDT_API int epoll_wait2(int eid, UDTSOCKET* readfds, int* rnum, UDTSOCKET* writefds, int* wnum, int64_t msTimeOut,
SYSSOCKET* lrfds = NULL, int* lrnum = NULL, SYSSOCKET* lwfds = NULL, int* lwnum = NULL);
UDT_API int epoll_release(int eid);
UDT_API ERRORINFO& getlasterror();
UDT_API int getlasterror_code();
UDT_API const char* getlasterror_desc();
UDT_API int perfmon(UDTSOCKET u, TRACEINFO* perf, bool clear = true);
UDT_API UDTSTATUS getsockstate(UDTSOCKET u);
} // namespace UDT
#endif

759
src/udtCommon.cpp Normal file
View File

@ -0,0 +1,759 @@
/*****************************************************************************
Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 07/25/2010
*****************************************************************************/
#ifndef WINDOWS
#include <cstring>
#include <cerrno>
#include <unistd.h>
#ifdef MACOSX
#include <mach/mach_time.h>
#endif
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#endif
#include <cmath>
#include "md5.h"
#include "udtCommon.h"
bool CTimer::m_bUseMicroSecond = false;
uint64_t CTimer::s_ullCPUFrequency = CTimer::readCPUFrequency();
#ifndef WINDOWS
udt_pthread_mutex_t CTimer::m_EventLock = PTHREAD_MUTEX_INITIALIZER;
udt_pthread_cond_t CTimer::m_EventCond = PTHREAD_COND_INITIALIZER;
#else
udt_pthread_mutex_t CTimer::m_EventLock = CreateMutex(NULL, false, NULL);
udt_pthread_cond_t CTimer::m_EventCond = CreateEvent(NULL, false, false, NULL);
#endif
CTimer::CTimer():
m_ullSchedTime(),
m_TickCond(),
m_TickLock()
{
#ifndef WINDOWS
pthread_mutex_init(&m_TickLock, NULL);
pthread_cond_init(&m_TickCond, NULL);
#else
m_TickLock = CreateMutex(NULL, false, NULL);
m_TickCond = CreateEvent(NULL, false, false, NULL);
#endif
}
CTimer::~CTimer()
{
#ifndef WINDOWS
pthread_mutex_destroy(&m_TickLock);
pthread_cond_destroy(&m_TickCond);
#else
CloseHandle(m_TickLock);
CloseHandle(m_TickCond);
#endif
}
void CTimer::rdtsc(uint64_t &x)
{
if (m_bUseMicroSecond)
{
x = getTime();
return;
}
#if defined(LINUX) && defined(I386)
uint32_t lval, hval;
//asm volatile ("push %eax; push %ebx; push %ecx; push %edx");
//asm volatile ("xor %eax, %eax; cpuid");
asm volatile ("rdtsc" : "=a" (lval), "=d" (hval));
//asm volatile ("pop %edx; pop %ecx; pop %ebx; pop %eax");
x = hval;
x = (x << 32) | lval;
#elif defined(LINUX) && defined(AMD64)
uint32_t lval, hval;
asm ("rdtsc" : "=a" (lval), "=d" (hval));
x = hval;
x = (x << 32) | lval;
#elif defined(WINDOWS)
//HANDLE hCurThread = ::GetCurrentThread();
//DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1);
BOOL ret = QueryPerformanceCounter((LARGE_INTEGER *)&x);
//SetThreadAffinityMask(hCurThread, dwOldMask);
if (!ret)
x = getTime() * s_ullCPUFrequency;
#elif defined(MACOSX)
x = mach_absolute_time();
#else
// use system call to read time clock for other archs
x = getTime();
#endif
}
uint64_t CTimer::readCPUFrequency()
{
uint64_t frequency = 1; // 1 tick per microsecond.
#if defined(LINUX) && (defined(I386) || defined(AMD64))
uint64_t t1, t2;
rdtsc(t1);
timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 100000000;
nanosleep(&ts, NULL);
rdtsc(t2);
// CPU clocks per microsecond
frequency = (t2 - t1) / 100000;
#elif defined(WINDOWS)
int64_t ccf;
if (QueryPerformanceFrequency((LARGE_INTEGER *)&ccf))
frequency = ccf / 1000000;
#elif defined(MACOSX)
mach_timebase_info_data_t info;
mach_timebase_info(&info);
frequency = info.denom * 1000ULL / info.numer;
#endif
// Fall back to microsecond if the resolution is not high enough.
if (frequency < 10)
{
frequency = 1;
m_bUseMicroSecond = true;
}
return frequency;
}
uint64_t CTimer::getCPUFrequency()
{
return s_ullCPUFrequency;
}
void CTimer::sleep(uint64_t interval)
{
uint64_t t;
rdtsc(t);
// sleep next "interval" time
sleepto(t + interval);
}
void CTimer::sleepto(uint64_t nexttime)
{
// Use class member such that the method can be interrupted by others
m_ullSchedTime = nexttime;
uint64_t t;
rdtsc(t);
while (t < m_ullSchedTime)
{
#ifndef NO_BUSY_WAITING
#if defined(LINUX) && defined(I386)
__asm__ volatile ("pause; rep; nop; nop; nop; nop; nop;");
#elif defined(LINUX) && defined(AMD64)
__asm__ volatile ("nop; nop; nop; nop; nop;");
#endif
#else
#ifndef WINDOWS
timeval now;
timespec timeout;
gettimeofday(&now, 0);
if (now.tv_usec < 990000)
{
timeout.tv_sec = now.tv_sec;
timeout.tv_nsec = (now.tv_usec + 10000) * 1000;
}
else
{
timeout.tv_sec = now.tv_sec + 1;
timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000;
}
pthread_mutex_lock(&m_TickLock);
pthread_cond_timedwait(&m_TickCond, &m_TickLock, &timeout);
pthread_mutex_unlock(&m_TickLock);
#else
WaitForSingleObject(m_TickCond, 1);
#endif
#endif
rdtsc(t);
}
}
void CTimer::interrupt()
{
// schedule the sleepto time to the current CCs, so that it will stop
rdtsc(m_ullSchedTime);
tick();
}
void CTimer::tick()
{
#ifndef WINDOWS
pthread_cond_signal(&m_TickCond);
#else
SetEvent(m_TickCond);
#endif
}
uint64_t CTimer::getTime()
{
//For Cygwin and other systems without microsecond level resolution, uncomment the following three lines
//uint64_t x;
//rdtsc(x);
//return x / s_ullCPUFrequency;
//Specific fix may be necessary if rdtsc is not available either.
#ifndef WINDOWS
timeval t;
gettimeofday(&t, 0);
return t.tv_sec * 1000000ULL + t.tv_usec;
#else
LARGE_INTEGER ccf;
HANDLE hCurThread = ::GetCurrentThread();
DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1);
if (QueryPerformanceFrequency(&ccf))
{
LARGE_INTEGER cc;
if (QueryPerformanceCounter(&cc))
{
SetThreadAffinityMask(hCurThread, dwOldMask);
return (cc.QuadPart * 1000000ULL / ccf.QuadPart);
}
}
SetThreadAffinityMask(hCurThread, dwOldMask);
return GetTickCount() * 1000ULL;
#endif
}
void CTimer::triggerEvent()
{
#ifndef WINDOWS
pthread_cond_signal(&m_EventCond);
#else
SetEvent(m_EventCond);
#endif
}
void CTimer::waitForEvent()
{
#ifndef WINDOWS
timeval now;
timespec timeout;
gettimeofday(&now, 0);
if (now.tv_usec < 990000)
{
timeout.tv_sec = now.tv_sec;
timeout.tv_nsec = (now.tv_usec + 10000) * 1000;
}
else
{
timeout.tv_sec = now.tv_sec + 1;
timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000;
}
pthread_mutex_lock(&m_EventLock);
pthread_cond_timedwait(&m_EventCond, &m_EventLock, &timeout);
pthread_mutex_unlock(&m_EventLock);
#else
WaitForSingleObject(m_EventCond, 1);
#endif
}
void CTimer::sleep()
{
#ifndef WINDOWS
usleep(10);
#else
Sleep(1);
#endif
}
//
// Automatically lock in constructor
CGuard::CGuard(udt_pthread_mutex_t& lock):
m_Mutex(lock),
m_iLocked()
{
#ifndef WINDOWS
m_iLocked = pthread_mutex_lock(&m_Mutex);
#else
m_iLocked = WaitForSingleObject(m_Mutex, INFINITE);
#endif
}
// Automatically unlock in destructor
CGuard::~CGuard()
{
#ifndef WINDOWS
if (0 == m_iLocked)
pthread_mutex_unlock(&m_Mutex);
#else
if (WAIT_FAILED != m_iLocked)
ReleaseMutex(m_Mutex);
#endif
}
void CGuard::enterCS(udt_pthread_mutex_t& lock)
{
#ifndef WINDOWS
pthread_mutex_lock(&lock);
#else
WaitForSingleObject(lock, INFINITE);
#endif
}
void CGuard::leaveCS(udt_pthread_mutex_t& lock)
{
#ifndef WINDOWS
pthread_mutex_unlock(&lock);
#else
ReleaseMutex(lock);
#endif
}
void CGuard::createMutex(udt_pthread_mutex_t& lock)
{
#ifndef WINDOWS
pthread_mutex_init(&lock, NULL);
#else
lock = CreateMutex(NULL, false, NULL);
#endif
}
void CGuard::releaseMutex(udt_pthread_mutex_t& lock)
{
#ifndef WINDOWS
pthread_mutex_destroy(&lock);
#else
CloseHandle(lock);
#endif
}
void CGuard::createCond(udt_pthread_cond_t& cond)
{
#ifndef WINDOWS
pthread_cond_init(&cond, NULL);
#else
cond = CreateEvent(NULL, false, false, NULL);
#endif
}
void CGuard::releaseCond(udt_pthread_cond_t& cond)
{
#ifndef WINDOWS
pthread_cond_destroy(&cond);
#else
CloseHandle(cond);
#endif
}
//
CUDTException::CUDTException(int major, int minor, int err):
m_iMajor(major),
m_iMinor(minor)
{
if (-1 == err)
#ifndef WINDOWS
m_iErrno = errno;
#else
m_iErrno = GetLastError();
#endif
else
m_iErrno = err;
}
CUDTException::CUDTException(const CUDTException& e):
m_iMajor(e.m_iMajor),
m_iMinor(e.m_iMinor),
m_iErrno(e.m_iErrno),
m_strMsg()
{
}
CUDTException::~CUDTException()
{
}
const char* CUDTException::getErrorMessage()
{
// translate "Major:Minor" code into text message.
switch (m_iMajor)
{
case 0:
m_strMsg = "Success";
break;
case 1:
m_strMsg = "Connection setup failure";
switch (m_iMinor)
{
case 1:
m_strMsg += ": connection time out";
break;
case 2:
m_strMsg += ": connection rejected";
break;
case 3:
m_strMsg += ": unable to create/configure UDP socket";
break;
case 4:
m_strMsg += ": abort for security reasons";
break;
default:
break;
}
break;
case 2:
switch (m_iMinor)
{
case 1:
m_strMsg = "Connection was broken";
break;
case 2:
m_strMsg = "Connection does not exist";
break;
default:
break;
}
break;
case 3:
m_strMsg = "System resource failure";
switch (m_iMinor)
{
case 1:
m_strMsg += ": unable to create new threads";
break;
case 2:
m_strMsg += ": unable to allocate buffers";
break;
default:
break;
}
break;
case 4:
m_strMsg = "File system failure";
switch (m_iMinor)
{
case 1:
m_strMsg += ": cannot seek read position";
break;
case 2:
m_strMsg += ": failure in read";
break;
case 3:
m_strMsg += ": cannot seek write position";
break;
case 4:
m_strMsg += ": failure in write";
break;
default:
break;
}
break;
case 5:
m_strMsg = "Operation not supported";
switch (m_iMinor)
{
case 1:
m_strMsg += ": Cannot do this operation on a BOUND socket";
break;
case 2:
m_strMsg += ": Cannot do this operation on a CONNECTED socket";
break;
case 3:
m_strMsg += ": Bad parameters";
break;
case 4:
m_strMsg += ": Invalid socket ID";
break;
case 5:
m_strMsg += ": Cannot do this operation on an UNBOUND socket";
break;
case 6:
m_strMsg += ": Socket is not in listening state";
break;
case 7:
m_strMsg += ": Listen/accept is not supported in rendezous connection setup";
break;
case 8:
m_strMsg += ": Cannot call connect on UNBOUND socket in rendezvous connection setup";
break;
case 9:
m_strMsg += ": This operation is not supported in SOCK_STREAM mode";
break;
case 10:
m_strMsg += ": This operation is not supported in SOCK_DGRAM mode";
break;
case 11:
m_strMsg += ": Another socket is already listening on the same port";
break;
case 12:
m_strMsg += ": Message is too large to send (it must be less than the UDT send buffer size)";
break;
case 13:
m_strMsg += ": Invalid epoll ID";
break;
default:
break;
}
break;
case 6:
m_strMsg = "Non-blocking call failure";
switch (m_iMinor)
{
case 1:
m_strMsg += ": no buffer available for sending";
break;
case 2:
m_strMsg += ": no data available for reading";
break;
default:
break;
}
break;
case 7:
m_strMsg = "The peer side has signalled an error";
break;
default:
m_strMsg = "Unknown error";
}
// Adding "errno" information
if ((0 != m_iMajor) && (0 < m_iErrno))
{
m_strMsg += ": ";
#ifndef WINDOWS
char errmsg[1024];
if (strerror_r(m_iErrno, errmsg, 1024) == 0)
m_strMsg += errmsg;
#else
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_iErrno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
m_strMsg += (char*)lpMsgBuf;
LocalFree(lpMsgBuf);
#endif
}
// period
#ifndef WINDOWS
m_strMsg += ".";
#endif
return m_strMsg.c_str();
}
int CUDTException::getErrorCode() const
{
return m_iMajor * 1000 + m_iMinor;
}
void CUDTException::clear()
{
m_iMajor = 0;
m_iMinor = 0;
m_iErrno = 0;
}
const int CUDTException::SUCCESS = 0;
const int CUDTException::ECONNSETUP = 1000;
const int CUDTException::ENOSERVER = 1001;
const int CUDTException::ECONNREJ = 1002;
const int CUDTException::ESOCKFAIL = 1003;
const int CUDTException::ESECFAIL = 1004;
const int CUDTException::ECONNFAIL = 2000;
const int CUDTException::ECONNLOST = 2001;
const int CUDTException::ENOCONN = 2002;
const int CUDTException::ERESOURCE = 3000;
const int CUDTException::ETHREAD = 3001;
const int CUDTException::ENOBUF = 3002;
const int CUDTException::EFILE = 4000;
const int CUDTException::EINVRDOFF = 4001;
const int CUDTException::ERDPERM = 4002;
const int CUDTException::EINVWROFF = 4003;
const int CUDTException::EWRPERM = 4004;
const int CUDTException::EINVOP = 5000;
const int CUDTException::EBOUNDSOCK = 5001;
const int CUDTException::ECONNSOCK = 5002;
const int CUDTException::EINVPARAM = 5003;
const int CUDTException::EINVSOCK = 5004;
const int CUDTException::EUNBOUNDSOCK = 5005;
const int CUDTException::ENOLISTEN = 5006;
const int CUDTException::ERDVNOSERV = 5007;
const int CUDTException::ERDVUNBOUND = 5008;
const int CUDTException::ESTREAMILL = 5009;
const int CUDTException::EDGRAMILL = 5010;
const int CUDTException::EDUPLISTEN = 5011;
const int CUDTException::ELARGEMSG = 5012;
const int CUDTException::EINVPOLLID = 5013;
const int CUDTException::EASYNCFAIL = 6000;
const int CUDTException::EASYNCSND = 6001;
const int CUDTException::EASYNCRCV = 6002;
const int CUDTException::ETIMEOUT = 6003;
const int CUDTException::EPEERERR = 7000;
const int CUDTException::EUNKNOWN = -1;
//
bool CIPAddress::ipcmp(const sockaddr* addr1, const sockaddr* addr2, int ver)
{
if (AF_INET == ver)
{
sockaddr_in* a1 = (sockaddr_in*)addr1;
sockaddr_in* a2 = (sockaddr_in*)addr2;
if ((a1->sin_port == a2->sin_port) && (a1->sin_addr.s_addr == a2->sin_addr.s_addr))
return true;
}
else
{
sockaddr_in6* a1 = (sockaddr_in6*)addr1;
sockaddr_in6* a2 = (sockaddr_in6*)addr2;
if (a1->sin6_port == a2->sin6_port)
{
for (int i = 0; i < 16; ++ i)
if (*((char*)&(a1->sin6_addr) + i) != *((char*)&(a2->sin6_addr) + i))
return false;
return true;
}
}
return false;
}
void CIPAddress::ntop(const sockaddr* addr, uint32_t ip[4], int ver)
{
if (AF_INET == ver)
{
sockaddr_in* a = (sockaddr_in*)addr;
ip[0] = a->sin_addr.s_addr;
}
else
{
sockaddr_in6* a = (sockaddr_in6*)addr;
ip[3] = (a->sin6_addr.s6_addr[15] << 24) + (a->sin6_addr.s6_addr[14] << 16) + (a->sin6_addr.s6_addr[13] << 8) + a->sin6_addr.s6_addr[12];
ip[2] = (a->sin6_addr.s6_addr[11] << 24) + (a->sin6_addr.s6_addr[10] << 16) + (a->sin6_addr.s6_addr[9] << 8) + a->sin6_addr.s6_addr[8];
ip[1] = (a->sin6_addr.s6_addr[7] << 24) + (a->sin6_addr.s6_addr[6] << 16) + (a->sin6_addr.s6_addr[5] << 8) + a->sin6_addr.s6_addr[4];
ip[0] = (a->sin6_addr.s6_addr[3] << 24) + (a->sin6_addr.s6_addr[2] << 16) + (a->sin6_addr.s6_addr[1] << 8) + a->sin6_addr.s6_addr[0];
}
}
void CIPAddress::pton(sockaddr* addr, const uint32_t ip[4], int ver)
{
if (AF_INET == ver)
{
sockaddr_in* a = (sockaddr_in*)addr;
a->sin_addr.s_addr = ip[0];
}
else
{
sockaddr_in6* a = (sockaddr_in6*)addr;
for (int i = 0; i < 4; ++ i)
{
a->sin6_addr.s6_addr[i * 4] = ip[i] & 0xFF;
a->sin6_addr.s6_addr[i * 4 + 1] = (unsigned char)((ip[i] & 0xFF00) >> 8);
a->sin6_addr.s6_addr[i * 4 + 2] = (unsigned char)((ip[i] & 0xFF0000) >> 16);
a->sin6_addr.s6_addr[i * 4 + 3] = (unsigned char)((ip[i] & 0xFF000000) >> 24);
}
}
}
//
void CMD5::compute(const char* input, unsigned char result[16])
{
md5_state_t state;
md5_init(&state);
md5_append(&state, (const md5_byte_t *)input, strlen(input));
md5_finish(&state, result);
}

327
src/udtCommon.h Normal file
View File

@ -0,0 +1,327 @@
/*****************************************************************************
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 08/01/2009
*****************************************************************************/
#ifndef __UDT_COMMON_H__
#define __UDT_COMMON_H__
#ifndef WINDOWS
#include <sys/time.h>
#include <sys/uio.h>
#include <pthread.h>
#else
#include <stdint.h>
#include <ws2tcpip.h>
#include <windows.h>
#endif
#include <cstdlib>
#include "udt.h"
#ifdef WINDOWS
// Windows compatibility
typedef HANDLE udt_pthread_t;
typedef HANDLE udt_pthread_mutex_t;
typedef HANDLE udt_pthread_cond_t;
typedef DWORD udt_pthread_key_t;
#else
typedef pthread_t udt_pthread_t;
typedef pthread_mutex_t udt_pthread_mutex_t;
typedef pthread_cond_t udt_pthread_cond_t;
typedef pthread_key_t udt_pthread_key_t;
#endif
////////////////////////////////////////////////////////////////////////////////
class CTimer
{
public:
CTimer();
~CTimer();
public:
// Functionality:
// Sleep for "interval" CCs.
// Parameters:
// 0) [in] interval: CCs to sleep.
// Returned value:
// None.
void sleep(uint64_t interval);
// Functionality:
// Seelp until CC "nexttime".
// Parameters:
// 0) [in] nexttime: next time the caller is waken up.
// Returned value:
// None.
void sleepto(uint64_t nexttime);
// Functionality:
// Stop the sleep() or sleepto() methods.
// Parameters:
// None.
// Returned value:
// None.
void interrupt();
// Functionality:
// trigger the clock for a tick, for better granuality in no_busy_waiting timer.
// Parameters:
// None.
// Returned value:
// None.
void tick();
public:
// Functionality:
// Read the CPU clock cycle into x.
// Parameters:
// 0) [out] x: to record cpu clock cycles.
// Returned value:
// None.
static void rdtsc(uint64_t &x);
// Functionality:
// return the CPU frequency.
// Parameters:
// None.
// Returned value:
// CPU frequency.
static uint64_t getCPUFrequency();
// Functionality:
// check the current time, 64bit, in microseconds.
// Parameters:
// None.
// Returned value:
// current time in microseconds.
static uint64_t getTime();
// Functionality:
// trigger an event such as new connection, close, new data, etc. for "select" call.
// Parameters:
// None.
// Returned value:
// None.
static void triggerEvent();
// Functionality:
// wait for an event to br triggered by "triggerEvent".
// Parameters:
// None.
// Returned value:
// None.
static void waitForEvent();
// Functionality:
// sleep for a short interval. exact sleep time does not matter
// Parameters:
// None.
// Returned value:
// None.
static void sleep();
private:
uint64_t getTimeInMicroSec();
private:
uint64_t m_ullSchedTime; // next schedulled time
pthread_cond_t m_TickCond;
udt_pthread_mutex_t m_TickLock;
static udt_pthread_cond_t m_EventCond;
static udt_pthread_mutex_t m_EventLock;
private:
static uint64_t s_ullCPUFrequency; // CPU frequency : clock cycles per microsecond
static uint64_t readCPUFrequency();
static bool m_bUseMicroSecond; // No higher resolution timer available, use gettimeofday().
};
////////////////////////////////////////////////////////////////////////////////
class CGuard
{
public:
CGuard(udt_pthread_mutex_t& lock);
~CGuard();
public:
static void enterCS(udt_pthread_mutex_t& lock);
static void leaveCS(udt_pthread_mutex_t& lock);
static void createMutex(udt_pthread_mutex_t& lock);
static void releaseMutex(udt_pthread_mutex_t& lock);
static void createCond(udt_pthread_cond_t& cond);
static void releaseCond(udt_pthread_cond_t& cond);
private:
udt_pthread_mutex_t& m_Mutex; // Alias name of the mutex to be protected
unsigned int m_iLocked; // Locking status
CGuard& operator=(const CGuard&);
};
////////////////////////////////////////////////////////////////////////////////
// UDT Sequence Number 0 - (2^31 - 1)
// seqcmp: compare two seq#, considering the wraping
// seqlen: length from the 1st to the 2nd seq#, including both
// seqoff: offset from the 2nd to the 1st seq#
// incseq: increase the seq# by 1
// decseq: decrease the seq# by 1
// incseq: increase the seq# by a given offset
class CSeqNo
{
public:
inline static int seqcmp(int32_t seq1, int32_t seq2)
{return (abs(seq1 - seq2) < m_iSeqNoTH) ? (seq1 - seq2) : (seq2 - seq1);}
inline static int seqlen(int32_t seq1, int32_t seq2)
{return (seq1 <= seq2) ? (seq2 - seq1 + 1) : (seq2 - seq1 + m_iMaxSeqNo + 2);}
inline static int seqoff(int32_t seq1, int32_t seq2)
{
if (abs(seq1 - seq2) < m_iSeqNoTH)
return seq2 - seq1;
if (seq1 < seq2)
return seq2 - seq1 - m_iMaxSeqNo - 1;
return seq2 - seq1 + m_iMaxSeqNo + 1;
}
inline static int32_t incseq(int32_t seq)
{return (seq == m_iMaxSeqNo) ? 0 : seq + 1;}
inline static int32_t decseq(int32_t seq)
{return (seq == 0) ? m_iMaxSeqNo : seq - 1;}
inline static int32_t incseq(int32_t seq, int32_t inc)
{return (m_iMaxSeqNo - seq >= inc) ? seq + inc : seq - m_iMaxSeqNo + inc - 1;}
public:
static const int32_t m_iSeqNoTH; // threshold for comparing seq. no.
static const int32_t m_iMaxSeqNo; // maximum sequence number used in UDT
};
////////////////////////////////////////////////////////////////////////////////
// UDT ACK Sub-sequence Number: 0 - (2^31 - 1)
class CAckNo
{
public:
inline static int32_t incack(int32_t ackno)
{return (ackno == m_iMaxAckSeqNo) ? 0 : ackno + 1;}
public:
static const int32_t m_iMaxAckSeqNo; // maximum ACK sub-sequence number used in UDT
};
////////////////////////////////////////////////////////////////////////////////
// UDT Message Number: 0 - (2^29 - 1)
class CMsgNo
{
public:
inline static int msgcmp(int32_t msgno1, int32_t msgno2)
{return (abs(msgno1 - msgno2) < m_iMsgNoTH) ? (msgno1 - msgno2) : (msgno2 - msgno1);}
inline static int msglen(int32_t msgno1, int32_t msgno2)
{return (msgno1 <= msgno2) ? (msgno2 - msgno1 + 1) : (msgno2 - msgno1 + m_iMaxMsgNo + 2);}
inline static int msgoff(int32_t msgno1, int32_t msgno2)
{
if (abs(msgno1 - msgno2) < m_iMsgNoTH)
return msgno2 - msgno1;
if (msgno1 < msgno2)
return msgno2 - msgno1 - m_iMaxMsgNo - 1;
return msgno2 - msgno1 + m_iMaxMsgNo + 1;
}
inline static int32_t incmsg(int32_t msgno)
{return (msgno == m_iMaxMsgNo) ? 0 : msgno + 1;}
public:
static const int32_t m_iMsgNoTH; // threshold for comparing msg. no.
static const int32_t m_iMaxMsgNo; // maximum message number used in UDT
};
////////////////////////////////////////////////////////////////////////////////
struct CIPAddress
{
static bool ipcmp(const sockaddr* addr1, const sockaddr* addr2, int ver = AF_INET);
static void ntop(const sockaddr* addr, uint32_t ip[4], int ver = AF_INET);
static void pton(sockaddr* addr, const uint32_t ip[4], int ver = AF_INET);
};
////////////////////////////////////////////////////////////////////////////////
struct CMD5
{
static void compute(const char* input, unsigned char result[16]);
};
#endif

286
src/window.cpp Normal file
View File

@ -0,0 +1,286 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/22/2011
*****************************************************************************/
#include <cmath>
#include "udtCommon.h"
#include "window.h"
#include <algorithm>
using namespace std;
CACKWindow::CACKWindow(int size):
m_piACKSeqNo(NULL),
m_piACK(NULL),
m_pTimeStamp(NULL),
m_iSize(size),
m_iHead(0),
m_iTail(0)
{
m_piACKSeqNo = new int32_t[m_iSize];
m_piACK = new int32_t[m_iSize];
m_pTimeStamp = new uint64_t[m_iSize];
m_piACKSeqNo[0] = -1;
}
CACKWindow::~CACKWindow()
{
delete [] m_piACKSeqNo;
delete [] m_piACK;
delete [] m_pTimeStamp;
}
void CACKWindow::store(int32_t seq, int32_t ack)
{
m_piACKSeqNo[m_iHead] = seq;
m_piACK[m_iHead] = ack;
m_pTimeStamp[m_iHead] = CTimer::getTime();
m_iHead = (m_iHead + 1) % m_iSize;
// overwrite the oldest ACK since it is not likely to be acknowledged
if (m_iHead == m_iTail)
m_iTail = (m_iTail + 1) % m_iSize;
}
int CACKWindow::acknowledge(int32_t seq, int32_t& ack)
{
if (m_iHead >= m_iTail)
{
// Head has not exceeded the physical boundary of the window
for (int i = m_iTail, n = m_iHead; i < n; ++ i)
{
// looking for indentical ACK Seq. No.
if (seq == m_piACKSeqNo[i])
{
// return the Data ACK it carried
ack = m_piACK[i];
// calculate RTT
int rtt = int(CTimer::getTime() - m_pTimeStamp[i]);
if (i + 1 == m_iHead)
{
m_iTail = m_iHead = 0;
m_piACKSeqNo[0] = -1;
}
else
m_iTail = (i + 1) % m_iSize;
return rtt;
}
}
// Bad input, the ACK node has been overwritten
return -1;
}
// Head has exceeded the physical window boundary, so it is behind tail
for (int j = m_iTail, n = m_iHead + m_iSize; j < n; ++ j)
{
// looking for indentical ACK seq. no.
if (seq == m_piACKSeqNo[j % m_iSize])
{
// return Data ACK
j %= m_iSize;
ack = m_piACK[j];
// calculate RTT
int rtt = int(CTimer::getTime() - m_pTimeStamp[j]);
if (j == m_iHead)
{
m_iTail = m_iHead = 0;
m_piACKSeqNo[0] = -1;
}
else
m_iTail = (j + 1) % m_iSize;
return rtt;
}
}
// bad input, the ACK node has been overwritten
return -1;
}
////////////////////////////////////////////////////////////////////////////////
CPktTimeWindow::CPktTimeWindow(int asize, int psize):
m_iAWSize(asize),
m_piPktWindow(NULL),
m_iPktWindowPtr(0),
m_iPWSize(psize),
m_piProbeWindow(NULL),
m_iProbeWindowPtr(0),
m_iLastSentTime(0),
m_iMinPktSndInt(1000000),
m_LastArrTime(),
m_CurrArrTime(),
m_ProbeTime()
{
m_piPktWindow = new int[m_iAWSize];
m_piPktReplica = new int[m_iAWSize];
m_piProbeWindow = new int[m_iPWSize];
m_piProbeReplica = new int[m_iPWSize];
m_LastArrTime = CTimer::getTime();
for (int i = 0; i < m_iAWSize; ++ i)
m_piPktWindow[i] = 1000000;
for (int k = 0; k < m_iPWSize; ++ k)
m_piProbeWindow[k] = 1000;
}
CPktTimeWindow::~CPktTimeWindow()
{
delete [] m_piPktWindow;
delete [] m_piPktReplica;
delete [] m_piProbeWindow;
delete [] m_piProbeReplica;
}
int CPktTimeWindow::getMinPktSndInt() const
{
return m_iMinPktSndInt;
}
int CPktTimeWindow::getPktRcvSpeed() const
{
// get median value, but cannot change the original value order in the window
std::copy(m_piPktWindow, m_piPktWindow + m_iAWSize - 1, m_piPktReplica);
std::nth_element(m_piPktReplica, m_piPktReplica + (m_iAWSize / 2), m_piPktReplica + m_iAWSize - 1);
int median = m_piPktReplica[m_iAWSize / 2];
int count = 0;
int sum = 0;
int upper = median << 3;
int lower = median >> 3;
// median filtering
int* p = m_piPktWindow;
for (int i = 0, n = m_iAWSize; i < n; ++ i)
{
if ((*p < upper) && (*p > lower))
{
++ count;
sum += *p;
}
++ p;
}
// claculate speed, or return 0 if not enough valid value
if (count > (m_iAWSize >> 1))
return (int)ceil(1000000.0 / (sum / count));
else
return 0;
}
int CPktTimeWindow::getBandwidth() const
{
// get median value, but cannot change the original value order in the window
std::copy(m_piProbeWindow, m_piProbeWindow + m_iPWSize - 1, m_piProbeReplica);
std::nth_element(m_piProbeReplica, m_piProbeReplica + (m_iPWSize / 2), m_piProbeReplica + m_iPWSize - 1);
int median = m_piProbeReplica[m_iPWSize / 2];
int count = 1;
int sum = median;
int upper = median << 3;
int lower = median >> 3;
// median filtering
int* p = m_piProbeWindow;
for (int i = 0, n = m_iPWSize; i < n; ++ i)
{
if ((*p < upper) && (*p > lower))
{
++ count;
sum += *p;
}
++ p;
}
return (int)ceil(1000000.0 / (double(sum) / double(count)));
}
void CPktTimeWindow::onPktSent(int currtime)
{
int interval = currtime - m_iLastSentTime;
if ((interval < m_iMinPktSndInt) && (interval > 0))
m_iMinPktSndInt = interval;
m_iLastSentTime = currtime;
}
void CPktTimeWindow::onPktArrival()
{
m_CurrArrTime = CTimer::getTime();
// record the packet interval between the current and the last one
*(m_piPktWindow + m_iPktWindowPtr) = int(m_CurrArrTime - m_LastArrTime);
// the window is logically circular
++ m_iPktWindowPtr;
if (m_iPktWindowPtr == m_iAWSize)
m_iPktWindowPtr = 0;
// remember last packet arrival time
m_LastArrTime = m_CurrArrTime;
}
void CPktTimeWindow::probe1Arrival()
{
m_ProbeTime = CTimer::getTime();
}
void CPktTimeWindow::probe2Arrival()
{
m_CurrArrTime = CTimer::getTime();
// record the probing packets interval
*(m_piProbeWindow + m_iProbeWindowPtr) = int(m_CurrArrTime - m_ProbeTime);
// the window is logically circular
++ m_iProbeWindowPtr;
if (m_iProbeWindowPtr == m_iPWSize)
m_iProbeWindowPtr = 0;
}

187
src/window.h Normal file
View File

@ -0,0 +1,187 @@
/*****************************************************************************
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 01/22/2011
*****************************************************************************/
#ifndef __UDT_WINDOW_H__
#define __UDT_WINDOW_H__
#ifndef WINDOWS
#include <sys/time.h>
#include <time.h>
#endif
#include "udt.h"
class CACKWindow
{
public:
CACKWindow(int size = 1024);
~CACKWindow();
// Functionality:
// Write an ACK record into the window.
// Parameters:
// 0) [in] seq: ACK seq. no.
// 1) [in] ack: DATA ACK no.
// Returned value:
// None.
void store(int32_t seq, int32_t ack);
// Functionality:
// Search the ACK-2 "seq" in the window, find out the DATA "ack" and caluclate RTT .
// Parameters:
// 0) [in] seq: ACK-2 seq. no.
// 1) [out] ack: the DATA ACK no. that matches the ACK-2 no.
// Returned value:
// RTT.
int acknowledge(int32_t seq, int32_t& ack);
private:
int32_t* m_piACKSeqNo; // Seq. No. for the ACK packet
int32_t* m_piACK; // Data Seq. No. carried by the ACK packet
uint64_t* m_pTimeStamp; // The timestamp when the ACK was sent
int m_iSize; // Size of the ACK history window
int m_iHead; // Pointer to the lastest ACK record
int m_iTail; // Pointer to the oldest ACK record
private:
CACKWindow(const CACKWindow&);
CACKWindow& operator=(const CACKWindow&);
};
////////////////////////////////////////////////////////////////////////////////
class CPktTimeWindow
{
public:
CPktTimeWindow(int asize = 16, int psize = 16);
~CPktTimeWindow();
// Functionality:
// read the minimum packet sending interval.
// Parameters:
// None.
// Returned value:
// minimum packet sending interval (microseconds).
int getMinPktSndInt() const;
// Functionality:
// Calculate the packes arrival speed.
// Parameters:
// None.
// Returned value:
// Packet arrival speed (packets per second).
int getPktRcvSpeed() const;
// Functionality:
// Estimate the bandwidth.
// Parameters:
// None.
// Returned value:
// Estimated bandwidth (packets per second).
int getBandwidth() const;
// Functionality:
// Record time information of a packet sending.
// Parameters:
// 0) currtime: timestamp of the packet sending.
// Returned value:
// None.
void onPktSent(int currtime);
// Functionality:
// Record time information of an arrived packet.
// Parameters:
// None.
// Returned value:
// None.
void onPktArrival();
// Functionality:
// Record the arrival time of the first probing packet.
// Parameters:
// None.
// Returned value:
// None.
void probe1Arrival();
// Functionality:
// Record the arrival time of the second probing packet and the interval between packet pairs.
// Parameters:
// None.
// Returned value:
// None.
void probe2Arrival();
private:
int m_iAWSize; // size of the packet arrival history window
int* m_piPktWindow; // packet information window
int* m_piPktReplica;
int m_iPktWindowPtr; // position pointer of the packet info. window.
int m_iPWSize; // size of probe history window size
int* m_piProbeWindow; // record inter-packet time for probing packet pairs
int* m_piProbeReplica;
int m_iProbeWindowPtr; // position pointer to the probing window
int m_iLastSentTime; // last packet sending time
int m_iMinPktSndInt; // Minimum packet sending interval
uint64_t m_LastArrTime; // last packet arrival time
uint64_t m_CurrArrTime; // current packet arrival time
uint64_t m_ProbeTime; // arrival time of the first probing packet
private:
CPktTimeWindow(const CPktTimeWindow&);
CPktTimeWindow &operator=(const CPktTimeWindow&);
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
From 60a91b17be591edad3c10df0b26d45c79dff7def Mon Sep 17 00:00:00 2001
From: nathan <nathan@dorkbox.com>
Date: Thu, 8 Jan 2015 23:31:27 +0100
Subject: [PATCH 3/5] Code polish. removed unnecessary preprocessor symbols
---
JavaLauncherApp/make_common.mak | 5 +----
JavaLauncherApp/src/common.c | 10 +++++-----
2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/JavaLauncherApp/make_common.mak b/JavaLauncherApp/make_common.mak
index 65536b0..1b55a95 100644
--- a/JavaLauncherApp/make_common.mak
+++ b/JavaLauncherApp/make_common.mak
@@ -181,11 +181,8 @@ ifeq ($(COMPILE_OS_ARCH),32)
PROGRAM_PATH+=bin/$(DIST_OS_NAME)
endif
-
- #udt config
- FLAGS +=-DIA32
else ifeq ($(COMPILE_OS_ARCH),64)
- FLAGS +=-DAMD64 -D_AMD64_ -D__AMD64__
+ FLAGS +=-DAMD64
M_ARCH=-m64
DIST_OS_NAME=$(COMPILE_OS)_64
diff --git a/JavaLauncherApp/src/common.c b/JavaLauncherApp/src/common.c
index 20f55ee..51a0e51 100644
--- a/JavaLauncherApp/src/common.c
+++ b/JavaLauncherApp/src/common.c
@@ -123,7 +123,7 @@ _TCHAR* findSymlinkCommand(_TCHAR* command, int resolve) {
else {
/* Get the directory PATH where executables reside. */
path = _tgetenv(_T_STRING("PATH"));
- #ifdef WINDOWS
+ #ifdef WINDOWS
/* on windows, prepend the current directory */
if (path == NULL)
path = _T_STRING("");
@@ -133,7 +133,7 @@ _TCHAR* findSymlinkCommand(_TCHAR* command, int resolve) {
ch[length] = PATH_SEPARATOR;
_tcscpy(&ch[length + 1], path);
path = ch;
- #endif
+ #endif
if (!path) {
return NULL;
} else {
@@ -306,9 +306,9 @@ _TCHAR* fixupPath(_TCHAR* path, _TCHAR* programDir, bool programDirFirst, bool a
}
_TCHAR * lastDirSeparator(_TCHAR* str) {
- #ifndef WINDOWS
+ #ifndef WINDOWS
return _tcsrchr(str, DIR_SEPARATOR);
- #else
+ #else
int i = -1;
_TCHAR * c = NULL;
while (str[++i] != 0) {
@@ -316,7 +316,7 @@ _TCHAR * lastDirSeparator(_TCHAR* str) {
c = &str[i];
}
return c;
- #endif
+ #endif
}
_TCHAR * firstDirSeparator(_TCHAR* str) {
--
1.9.1

View File

@ -0,0 +1,25 @@
From fc0f8e2f8f8abeae9cd71a4fe9c0244981e12d64 Mon Sep 17 00:00:00 2001
From: nathan <nathan@dorkbox.com>
Date: Fri, 9 Jan 2015 01:22:45 +0100
Subject: [PATCH 4/5] Fixed unitialized variable
---
JavaLauncherApp/src/udt/core.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/JavaLauncherApp/src/udt/core.cpp b/JavaLauncherApp/src/udt/core.cpp
index c1c8d03..a5acfa7 100644
--- a/JavaLauncherApp/src/udt/core.cpp
+++ b/JavaLauncherApp/src/udt/core.cpp
@@ -2285,7 +2285,7 @@ int CUDT::packData(CPacket& packet, uint64_t& ts)
if (offset < 0)
return 0;
- int msglen;
+ int msglen = 0;
payload = m_pSndBuffer->readData(&(packet.m_pcData), offset, packet.m_iMsgNo, msglen);
--
1.9.1

32
udt-doc/LICENSE.txt Normal file
View File

@ -0,0 +1,32 @@
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

7
udt-doc/Makefile Normal file
View File

@ -0,0 +1,7 @@
DIRS = src app
TARGETS = all clean install
$(TARGETS): %: $(patsubst %, %.%, $(DIRS))
$(foreach TGT, $(TARGETS), $(patsubst %, %.$(TGT), $(DIRS))):
$(MAKE) -C $(subst ., , $@)

14
udt-doc/README.txt Normal file
View File

@ -0,0 +1,14 @@
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
All Rights Reserved.
Copyright (c) 2011 - 2012, Google, Inc. All Rights Reserved.
UDP-based Data Transfer (UDT) Library - version 4
Author: Yunhong Gu [yunhong.gu @ gmail.com]
UDT version 4 is free software under BSD License. See ./LICENSE.txt.
============================================================================
UDT Website:
http://udt.sf.net
http://sf.net/projects/udt/

36
udt-doc/RELEASE_NOTES.txt Normal file
View File

@ -0,0 +1,36 @@
version 4.11
mostly bug fixes since last version.
version 4.10
added UDT_SNDDATA and UDT_RCVDATA options
fixed a bug that causes unnecessary connection timeout
improved epoll UDT event handling
version 4.9
asynchronous close
asynchronous connect
some bug fixes, especially on EPOLL
improved cache code
removed unnecessary NAK (reduced loss retransmission)
receiver side error can unblock a blocked sender
version 4.8
fix a bug that may cause seg fault on concurrent close on the same socket
add epoll support
increase the listener's scalability to 100K concurrent connections
fix a bug that may cause accept/select to return positively when an accepted socket is closed immediately after accept returns
fix a bug that may cause connect to fail if the server closes listening socket immediately after accept returns
fix recvfile fstream write status bug (e.g., when disk is full, recvfile should handle properly now)
version 4.7a
fix timeout bug introduced in 4.7
initialize CHandShake
version 4.7
Fix several related bugs that can cause hang/memory leak/segmentation fault during cleanup()

1049
udt-doc/draft-gg-udt-xx.txt Normal file

File diff suppressed because it is too large Load Diff