Compare commits

..

No commits in common. "master" and "v1.5.8" have entirely different histories.

341 changed files with 4277 additions and 33631 deletions

View File

@ -1,39 +0,0 @@
{
"image": "mcr.microsoft.com/devcontainers/cpp:1.0.0-buster",
"features": {
"ghcr.io/devcontainers/features/python:1": {
"version": "3.11"
},
"ghcr.io/devcontainers/features/dotnet:1": {
"version": "6"
},
"ghcr.io/devcontainers/features/java:1": {
"version": "17",
"installAnt": true,
"antVersion": "1.10.12"
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "20.10"
},
"ghcr.io/devcontainers/features/powershell:1": {
"version": "7.3"
}
},
"customizations": {
"vscode": {
"extensions": [
"DavidAnson.vscode-markdownlint",
"eamodio.gitlens",
"github.vscode-github-actions",
"GitHub.codespaces",
"jebbs.plantuml",
"ms-python.isort",
"ms-vscode-remote.remote-containers",
"ms-vscode.cpptools-themes",
"ms-vscode.PowerShell",
"tomoki1207.pdf",
"yzhang.markdown-all-in-one"
]
}
}
}

1
.gitattributes vendored
View File

@ -1 +0,0 @@
*.sh text eol=lf

View File

@ -1,183 +0,0 @@
name: CMake build
on: [push, pull_request]
env:
CMAKE_VERSION: 3.16.2
NINJA_VERSION: 1.9.0
BUILD_TYPE: Release
CCACHE_VERSION: 3.7.7
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Windows 2022 MSVC Shared", artifact: "Windows-MSVC-shared.tar.xz",
os: windows-2022,
cc: "cl", cxx: "cl",
shared: "ON",
environment_script: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat"
}
- {
name: "Windows 2022 MSVC", artifact: "Windows-MSVC.tar.xz",
os: windows-2022,
cc: "cl", cxx: "cl",
shared: "OFF",
environment_script: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat"
}
- {
name: "Windows Latest MinGW", artifact: "Windows-MinGW.tar.xz",
os: windows-latest,
cc: "gcc", cxx: "g++",
shared: "OFF"
}
- {
name: "Ubuntu Latest GCC", artifact: "Linux.tar.xz",
os: ubuntu-latest,
cc: "gcc", cxx: "g++",
shared: "OFF"
}
- {
name: "macOS Latest Clang", artifact: "macOS.tar.xz",
os: macos-latest,
cc: "clang", cxx: "clang++",
shared: "OFF"
}
steps:
- uses: actions/checkout@v4
- name: Download Ninja and CMake
id: cmake_and_ninja
shell: cmake -P {0}
run: |
set(cmake_version $ENV{CMAKE_VERSION})
set(ninja_version $ENV{NINJA_VERSION})
message(STATUS "Using host CMake version: ${CMAKE_VERSION}")
if ("${{ runner.os }}" STREQUAL "Windows")
set(ninja_suffix "win.zip")
set(cmake_suffix "win64-x64.zip")
set(cmake_dir "cmake-${cmake_version}-win64-x64/bin")
elseif ("${{ runner.os }}" STREQUAL "Linux")
set(ninja_suffix "linux.zip")
set(cmake_suffix "Linux-x86_64.tar.gz")
set(cmake_dir "cmake-${cmake_version}-Linux-x86_64/bin")
elseif ("${{ runner.os }}" STREQUAL "macOS")
set(ninja_suffix "mac.zip")
set(cmake_suffix "Darwin-x86_64.tar.gz")
set(cmake_dir "cmake-${cmake_version}-Darwin-x86_64/CMake.app/Contents/bin")
endif()
set(ninja_url "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}")
file(DOWNLOAD "${ninja_url}" ./ninja.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip)
set(cmake_url "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}")
file(DOWNLOAD "${cmake_url}" ./cmake.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip)
# Save the path for other steps
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/${cmake_dir}" cmake_dir)
message("::set-output name=cmake_dir::${cmake_dir}")
if (NOT "${{ runner.os }}" STREQUAL "Windows")
execute_process(
COMMAND chmod +x ninja
COMMAND chmod +x ${cmake_dir}/cmake
)
endif()
- name: Download ccache
id: ccache
shell: cmake -P {0}
run: |
set(ccache_url "https://github.com/cristianadam/ccache/releases/download/v$ENV{CCACHE_VERSION}/${{ runner.os }}.tar.xz")
file(DOWNLOAD "${ccache_url}" ./ccache.tar.xz SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ccache.tar.xz)
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
shell: cmake -P {0}
run: |
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
message("::set-output name=timestamp::${current_date}")
- name: ccache cache files
uses: actions/cache@v4
with:
path: .ccache
key: ${{ matrix.config.name }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}
restore-keys: |
${{ matrix.config.name }}-ccache-
- name: Configure
shell: cmake -P {0}
run: |
set(ENV{CC} ${{ matrix.config.cc }})
set(ENV{CXX} ${{ matrix.config.cxx }})
if ("${{ runner.os }}" STREQUAL "Windows" AND NOT "x${{ matrix.config.environment_script }}" STREQUAL "x")
execute_process(
COMMAND "${{ matrix.config.environment_script }}" && set
OUTPUT_FILE environment_script_output.txt
)
file(STRINGS environment_script_output.txt output_lines)
foreach(line IN LISTS output_lines)
if (line MATCHES "^([a-zA-Z0-9_-]+)=(.*)$")
set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}")
endif()
endforeach()
endif()
set(path_separator ":")
if ("${{ runner.os }}" STREQUAL "Windows")
set(path_separator ";")
endif()
set(ENV{PATH} "$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}")
execute_process(
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-S .
-B build
-D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}
-G Ninja
-D CMAKE_MAKE_PROGRAM=ninja
-D CMAKE_C_COMPILER_LAUNCHER=ccache
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache
-D BUILD_SHARED_LIBS=${{ matrix.config.shared }}
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Bad exit status")
endif()
- name: Build
shell: cmake -P {0}
run: |
set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")
if ("${{ runner.os }}" STREQUAL "Windows" AND NOT "x${{ matrix.config.environment_script }}" STREQUAL "x")
file(STRINGS environment_script_output.txt output_lines)
foreach(line IN LISTS output_lines)
if (line MATCHES "^([a-zA-Z0-9_-]+)=(.*)$")
set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}")
endif()
endforeach()
endif()
set(path_separator ":")
if ("${{ runner.os }}" STREQUAL "Windows")
set(path_separator ";")
endif()
set(ENV{PATH} "$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}")
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}" ccache_basedir)
set(ENV{CCACHE_BASEDIR} "${ccache_basedir}")
set(ENV{CCACHE_DIR} "${ccache_basedir}/.ccache")
set(ENV{CCACHE_COMPRESS} "true")
set(ENV{CCACHE_COMPRESSLEVEL} "6")
set(ENV{CCACHE_MAXSIZE} "400M")
if ("${{ matrix.config.cxx }}" STREQUAL "cl")
set(ENV{CCACHE_MAXSIZE} "600M")
endif()
execute_process(COMMAND ccache -p)
execute_process(COMMAND ccache -z)
execute_process(
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake --build build
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Bad exit status")
endif()
execute_process(COMMAND ccache -s)

View File

@ -1,142 +0,0 @@
name: ".NET Publish"
on:
workflow_run:
workflows: ['.NET']
types:
- completed
branches:
- master
- main
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
permissions:
packages: write
defaults:
run:
working-directory: ./src/dotnet
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 6.0.x
source-url: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Package .NET
run: dotnet pack . -c Release
- name: Publish .NET
run: |
package=$(find . -type f -name "*.nupkg")
dotnet nuget push "$package" --skip-duplicate
publish-linux-x64:
runs-on: ubuntu-latest
permissions:
packages: write
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Package .NET
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: |
cd ./src/dotnet
chmod 755 *.sh
./pack-linux-x64.sh
- name: Set up .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '6.0.x'
source-url: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Publish .NET
run: |
package=$(find . -type f -name "*linux-x64*.nupkg")
dotnet nuget push "$package" --skip-duplicate
publish-win-x64:
runs-on: windows-latest
permissions:
packages: write
defaults:
run:
working-directory: ./src/dotnet
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Python
uses: actions/setup-python@v5.1.0
with:
python-version: 3.x
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 6.0.x
source-url: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Package .NET
run: .\pack-win-x64.bat
- name: Publish .NET
run: |
$package=Get-ChildItem -Path .\ -Filter *win-x64*.nupkg -Recurse -File | ForEach-Object { $_.FullName }
dotnet nuget push "$package" --skip-duplicate
publish-win-x86:
runs-on: windows-latest
permissions:
packages: write
defaults:
run:
working-directory: ./src/dotnet
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Python
uses: actions/setup-python@v5.1.0
with:
python-version: 3.x
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 6.0.x
source-url: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Package .NET
run: .\pack-win-x86.bat
- name: Publish .NET
run: |
$package=Get-ChildItem -Path .\ -Filter *win-x86*.nupkg -Recurse -File | ForEach-Object { $_.FullName }
dotnet nuget push "$package" --skip-duplicate

View File

@ -1,49 +0,0 @@
name: .NET
on: [push, pull_request, workflow_dispatch]
jobs:
build:
runs-on: ubuntu-latest
permissions:
checks: write
pull-requests: write
defaults:
run:
working-directory: ./src/dotnet
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Python
uses: actions/setup-python@v5.1.0
with:
python-version: 3.x
- name: Build NORM
run: ./waf
working-directory: .
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 6.0.x
- name: Restore dependencies
run: dotnet restore /property:Configuration=Release
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Test
run: dotnet test --no-build --verbosity normal --configuration Release --logger trx --results-directory TestResults
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: dotnet-results
path: ./src/dotnet/TestResults
if: ${{ always() }}
- name: Publish test results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
files: ./src/dotnet/TestResults/*.trx
if: ${{ always() }}

301
.gitignore vendored Executable file → Normal file
View File

@ -1,37 +1,14 @@
# protolib
protolib/
# build executables
build/
bin/
lib/
makefiles/norm
makefiles/normMsgr
makefiles/normStreamer
makefiles/normCast
makefiles/normCastApp
makefiles/normClient
makefiles/normServer
makefiles/npc
makefiles/raft
makefiles/pcap2norm
norp/makefiles/norp
# build object files
*.o
*.a
# python build files
src/pynorm.egg-info
**/__pycache__/
# build java files
*.class
#build android files
android/.gradle
# waf cruft
.waf*
.lock-waf*
waf*/*
# OS generated files #
.DS_Store
@ -41,275 +18,3 @@ waf*/*
.Trashes
ehthumbs.db
Thumbs.db
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
*.sqlite
*.sqlite-shm
*.sqlite-wal
# Nuget files
DeploymentSettings.props
Directory.Build.props
Directory.Build.targets
Packages.props
#Local Log Files
log*.txt
#.NET Extension Library Files
/src/dotnet/lib

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "protolib"]
path = protolib
url = https://github.com/USNavalResearchLaboratory/protolib.git

View File

@ -1,5 +0,0 @@
{
"recommendations": [
"github.vscode-pull-request-github"
]
}

25
BUILD.TXT Executable file → Normal file
View File

@ -6,26 +6,11 @@ To see a full list of options, run:
./waf -h
Note: if attempting to run waf as an executable as shown above results in a
message like this:
/usr/bin/env: python: No such file or directory
then try calling python directly:
python waf <args>
or
python3 waf <args>
For more background information about waf, visit the gitlab page at
https://gitlab.com/ita1024/./waf/
Configuring
-----------
To perform the configuration checks, run:
To perform the configure checks, run:
./waf configure
@ -66,9 +51,6 @@ To install, run:
This will install the compiled library and headers to wherever your prefix was
specified. (See configure flags)
This command may have to be run with root priviledges for certain prefix
directories depending on your system setup.
Uninstalling
------------
@ -88,8 +70,3 @@ will delete all compiled files and configuration settings.
./waf distclean
will do the same as clean, and additionally delete the waf cache files.
ANDROID Build
-------------
See the "android" directory README for instructions.

View File

@ -1,226 +0,0 @@
cmake_minimum_required(VERSION 3.14)
cmake_policy(SET CMP0077 NEW)
# set the project name
project(norm VERSION 1.5.10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(COMMON src/common)
option(NORM_BUILD_EXAMPLES "Enables building of the examples in /examples." OFF)
set(NORM_CUSTOM_PROTOLIB_VERSION OFF CACHE STRING "Set a custom protolib version to use, ./protolib to use the local version")
include(CheckCXXSymbolExists)
check_cxx_symbol_exists(dirfd "dirent.h" HAVE_DIRFD)
if(HAVE_DIRFD)
list(APPEND PLATFORM_DEFINITIONS HAVE_DIRFD)
endif()
check_cxx_symbol_exists(lockf "unistd.h" HAVE_LOCKF)
if(HAVE_LOCKF)
list(APPEND PLATFORM_DEFINITIONS HAVE_LOCKF)
endif()
check_cxx_symbol_exists(flock "sys/file.h" HAVE_FLOCK)
if(HAVE_FLOCK)
list(APPEND PLATFORM_DEFINITIONS HAVE_FLOCK)
endif()
if(NOT NORM_CUSTOM_PROTOLIB_VERSION)
find_package(Git)
if(Git_FOUND)
message("Git found: ${GIT_EXECUTABLE}")
execute_process(
COMMAND
${GIT_EXECUTABLE} ls-tree HEAD
RESULT_VARIABLE
GIT_SUBMODULE_STATUS
OUTPUT_VARIABLE
GIT_SUBMODULE
WORKING_DIRECTORY
${CMAKE_CURRENT_LIST_DIR}
)
string(REGEX MATCH "commit[ \t\r\n]*([a-z0-9]+)[ \t\r\n]*protolib" GIT_SUBMODULE_HASH_MATCH ${GIT_SUBMODULE})
if(GIT_SUBMODULE_HASH_MATCH)
set(NORM_PROTOKIT_GIT_TAG ${CMAKE_MATCH_1})
endif()
endif()
elseif(NOT NORM_CUSTOM_PROTOLIB_VERSION STREQUAL "./protolib")
set(NORM_PROTOKIT_GIT_TAG ${NORM_CUSTOM_PROTOLIB_VERSION})
endif()
if(NORM_PROTOKIT_GIT_TAG)
message(STATUS "Building protokit from ${NORM_PROTOKIT_GIT_TAG}")
include(FetchContent)
FetchContent_Declare(
protokit
GIT_REPOSITORY https://github.com/USNavalResearchLaboratory/protolib.git
GIT_TAG ${NORM_PROTOKIT_GIT_TAG}
)
FetchContent_MakeAvailable(protokit)
else()
message(STATUS "Building protokit from ${NORM_CUSTOM_PROTOLIB_VERSION}")
add_subdirectory(protolib)
endif()
# List header files
list(APPEND PUBLIC_HEADER_FILES
include/galois.h
include/normApi.h
include/normEncoder.h
include/normEncoderMDP.h
include/normEncoderRS16.h
include/normEncoderRS8.h
include/normFile.h
include/normMessage.h
include/normNode.h
include/normObject.h
include/normPostProcess.h
include/normSegment.h
include/normSession.h
include/normSimAgent.h
include/normVersion.h
)
# List platform-independent source files
list(APPEND COMMON_SOURCE_FILES
${COMMON}/galois.cpp
${COMMON}/normApi.cpp
${COMMON}/normEncoder.cpp
${COMMON}/normEncoderMDP.cpp
${COMMON}/normEncoderRS16.cpp
${COMMON}/normEncoderRS8.cpp
${COMMON}/normFile.cpp
${COMMON}/normMessage.cpp
${COMMON}/normNode.cpp
${COMMON}/normObject.cpp
${COMMON}/normSegment.cpp
${COMMON}/normSession.cpp )
# Setup platform independent include directory
list(APPEND INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/include )
# Setup platform dependent libraries, defines, source file and compiler flags
# (The "post processing" helper source is only needed for normApp build)
#if(MSVC)
# list(APPEND PLATFORM_LIBS Shell32)
# list(APPEND PLATFORM_DEFINITIONS _CONSOLE)
# list(APPEND PLATFORM_SOURCE_FILES src/win32/win32PostProcess.cpp)
#elseif(UNIX)
# list(APPEND PLATFORM_SOURCE_FILES src/unix/unixPostProcess.cpp)
#endif()
include(GNUInstallDirs)
# Setup target
add_library(norm ${PLATFORM_SOURCE_FILES} ${COMMON_SOURCE_FILES} ${PUBLIC_HEADER_FILES})
target_link_libraries(norm PRIVATE protokit::protokit)
target_link_libraries(norm PUBLIC ${PLATFORM_LIBS})
target_compile_definitions(norm PUBLIC ${PLATFORM_DEFINITIONS})
target_compile_options(norm PUBLIC ${PLATFORM_FLAGS})
target_include_directories(norm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(norm PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
if(BUILD_SHARED_LIBS)
set_target_properties(norm PROPERTIES SOVERSION 1.5.10)
if(WIN32)
target_compile_definitions(norm PUBLIC NORM_USE_DLL)
endif()
endif()
if(BUILD_SHARED_LIBS AND BUILD_STATIC_LIBS)
add_library(norm-static STATIC ${PLATFORM_SOURCE_FILES} ${COMMON_SOURCE_FILES} ${PUBLIC_HEADER_FILES})
target_link_libraries(norm-static PRIVATE protokit::protokit)
target_compile_definitions(norm-static PUBLIC ${PLATFORM_DEFINITIONS})
target_compile_options(norm-static PUBLIC ${PLATFORM_FLAGS})
target_include_directories(norm-static PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(norm-static PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
set_target_properties(norm-static PROPERTIES OUTPUT_NAME "norm" PREFIX "lib")
set(NORM_STATIC "norm-static")
endif()
# Install target
install( TARGETS norm ${NORM_STATIC} protokit EXPORT normTargets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} )
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/norm)
install( EXPORT normTargets
FILE normTargets.cmake
NAMESPACE norm::
DESTINATION ${INSTALL_CONFIGDIR}
)
install(FILES include/normApi.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# Create pkg-config file norm.pc
# TODO: once waf is removed, norm.pc.in can be edited to use the variables CMake sets directly, and
# remove these re-definitions
set(VERSION ${PROJECT_VERSION})
set(PREFIX ${CMAKE_INSTALL_PREFIX})
set(LIBDIR ${CMAKE_INSTALL_LIBDIR})
set(STATIC_LIBS "libprotokit.a")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/norm.pc.in ${CMAKE_CURRENT_BINARY_DIR}/norm.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/norm.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Create a ConfigVersion.cmake file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/normConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/cmake/normConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/normConfig.cmake
INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
)
# Install the config, configversion and custom find modules
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/normConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/normConfigVersion.cmake
DESTINATION ${INSTALL_CONFIGDIR}
)
##############################################
# Exporting from the build tree
export(EXPORT normTargets
FILE ${CMAKE_CURRENT_BINARY_DIR}/normTargets.cmake
NAMESPACE norm::)
# Register package in user's package registry
export(PACKAGE norm)
if(NORM_BUILD_EXAMPLES)
# Setup examples
list(APPEND examples
#normDataExample
normDataRecv
normDataSend
normFileRecv
normFileSend
normStreamRecv
normStreamSend
normMsgr
normStreamer
normCast
chant
normClient
normServer
#wintest
)
foreach(example ${examples})
add_executable(${example} examples/${example}.cpp examples/normSocket.cpp)
target_link_libraries(${example} PRIVATE norm protokit::protokit)
endforeach()
endif()

View File

@ -1,27 +0,0 @@
ARG platformName=ubuntu
ARG platformVersion=latest
FROM ${platformName}:${platformVersion}
ARG version
ARG configure
ARG build="--targets=*"
ENV NORM_DIR=/norm-staging
ENV NORM_BUILD=$NORM_DIR/build
ENV WAF_CONFIGURE=${configure}
ENV WAF_BUILD=${build}
ADD ./ ${NORM_DIR}
# Step 1: dependencies
RUN VERSION=${version} ${NORM_DIR}/docker/setup.sh
# Step 2: build
RUN cd ${NORM_DIR} && ./waf ${WAF_BUILD}
# Step 3: install
RUN cd ${NORM_DIR} && ./waf install
# Step 4: expose
COPY ./docker/run.sh /usr/bin/run-norm-example
ENTRYPOINT [ "run-norm-example" ]

0
LICENSE Executable file → Normal file
View File

0
NormSocketBindingNotes.txt Executable file → Normal file
View File

View File

@ -1,72 +0,0 @@
.NET extension for NORM
==========================
By:
Jeff Muller <jeffrey.muller3.ctr@us.navy.mil>
Sylvester Freeman <sylvester.freeman18.civ@us.navy.mil>
Sergiy Yermak <sergiy.yermak.ctr@us.navy.mil>
The .NET extension for NORM provides a .NET wrapper for the NORM C API.
For documentation about the main NORM API calls, refer to the NORM Developers
guide in the regular NORM distribution.
The .NET extension can be built using the .NET CLI.
------------
Requirements
------------
The .NET extension for NORM requires at least .NET SDK 6.0.
The NORM library should be built prior to building the .NET extension since it is invoked by the .NET extension.
------------
Building
------------
To build the .NET extension for NORM, execute the .NET CLI command in the src/dotnet directory:
```
dotnet build .
```
------------
Testing
------------
To test the .NET extension for NORM, execute the .NET CLI command in the src/dotnet directory:
```
dotnet test .
```
The test command results should show that all tests have passed.
Some tests might be skipped due to IO exception.
------------
Packaging
------------
To package the .NET extension for NORM, execute the .NET CLI command in the src/dotnet directory:
```
dotnet pack . -c Release
```
To package the .NET extension for NORM that targets 64-bit Windows, execute the command in the src/dotnet directory:
```
pack-win-x64.bat
```
To package the .NET extension for NORM that targets 32-bit Windows, execute the command in the src/dotnet directory:
```
pack-win-x86.bat
```
To package the .NET extension for NORM that targets 64-bit Linux, execute the command in the src/dotnet directory:
```
./pack-linux-x64.sh
```

0
README-Java.txt Executable file → Normal file
View File

2
README-PyNorm.txt Executable file → Normal file
View File

@ -28,7 +28,7 @@ in similar places as your system's compiler. On UNIX systems, this is usually
PATH environment variable.
On Windows, PyNORM requires the "PyWin32" module, available at:
https://sourceforge.net/projects/pywin32
http://sf.net/projects/pywin32
-------------
Installation

149
README.md Executable file → Normal file
View File

@ -1,55 +1,50 @@
# norm
```
NORM SOURCE CODE RELEASE
/*********************************************************************
*
* AUTHORIZATION TO USE AND DISTRIBUTE
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that:
*
* (1) source code distributions retain this paragraph in its entirety,
*
* (2) distributions including binary code include this paragraph in
* its entirety in the documentation or other materials provided
* with the distribution.
*
* "This product includes software written and developed
* by Code 5520 of the Naval Research Laboratory (NRL)."
*
* The name of NRL, the name(s) of NRL employee(s), or any entity
* of the United States Government may not be used to endorse or
* promote products derived from this software, nor does the
* inclusion of the NRL written and developed software directly or
* indirectly suggest NRL or United States Government endorsement
* of this product.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
********************************************************************/
```
AUTHORIZATION TO USE AND DISTRIBUTE
This is the NRL NORM source code repository.
By receiving this distribution, you have agreed to the following
terms governing the use and redistribution of the prototype NRL
NORM software release written and developed by Brian Adamson and
Joe Macker:
The Github "Discussions" feature is available here for comment and question in addition
to the regular code issue reporting:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that:
https://github.com/USNavalResearchLaboratory/norm/discussions
(1) source code distributions retain this paragraph in its entirety,
(2) all advertising materials mentioning features or use of this
software display the following acknowledgment:
"This product includes software written and developed
by the Naval Research Laboratory (NRL)."
The name of NRL, the name(s) of NRL employee(s), or any entity
of the United States Government may not be used to endorse or
promote products derived from this software, nor does the
inclusion of the NRL written and developed software directly or
indirectly suggest NRL or United States Government endorsement
of this product.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
---------------------------------------------------------------------
This is a release of the NRL MDP source code. For most
purposes, the authors would prefer that the code not be
re-distributed so that users will obtain the latest (and most
debugged/improved) release from the official NORM web site:
<http://cs.itd.nrl.navy.mil/work/norm>
SOURCE CODE
===========
The "norm" source Git repository includes "protolib" as a git submodule. You can
add the "--recurse-submodules" to your git clone command to automate inclusion:
git clone --recurse-submodules https://github.com/USNavalResearchLaboratory/norm.git
The following items can be built from this source code release:
The following items can be build from this source code release:
1) libnorm.a - static NORM library for Unix platforms, or
@ -91,45 +86,8 @@ A) A reliable multicast "chat" application (users can share files
B) An application for reliably "tunneling" real-time UDP packet
streams (like RTP video or audio) using NORM's streaming
capability.
NACK-Oriented Proxy (NORP)
==========================
NORM Proxy code is also included in the 'norp' directory.
More info is available in the norp/doc directory, as well as the
NORP website: https://www.nrl.navy.mil/itd/ncs/products/norp
Docker
======
A `Dockerfile` is provided to facilitate containerized NORM environment testing. Notable
build arguments passed to `docker build` will influence how the image is created.
- `platformName` represents the base image name (defaults to `ubuntu`)
- `platformVersion` represents the tagged version for the base image (defaults to `latest`)
- `version` is a 1:1 mapping to this repo's tag (defaults to `v1.5.9`)
- `configure` is piped to `./waf configure` (defaults to "")
- `build` is piped to `./waf` (defaults to `--targets=*`)
Example usage:
CentOS7 build
```
docker build --build-arg platformName=centos \
--build-arg platformVersion=7 \
--build-arg="--build-java" \
-t norm:centos-1.5.9 .
```
Running the data send and recv examples:
```
# Sender in one terminal
docker run -it --rm --name norm-send <norm:image> normDataSend
# Receiver in another terminal
docker run -it --rm --name norm-recv <norm:image> normDataRecv
```
OTHER FILES:
============
@ -144,33 +102,14 @@ NormUserGuide.pdf - Guide to "norm" demo app usage
VERSION.TXT - NORM version history notes
README.md - this file
docker - directory containing docker container support
README.TXT - this file
NOTES:
======
The NORM code depends upon the current "Protolib" release:
https://github.com/USNavalResearchLaboratory/protolib
It has been addded as a git submodule to the NORM git repository. So, to
to build you will need to do the following steps to download the protolib code:
git clone --recurse-submodules https://github.com/USNavalResearchLaboratory/norm.git
Alternatively after a basic "git clone" you can do the folowing to pull in the protolib source:
cd norm
git submodule update --init
To keep the 'protolib' submodule up to date, you will need to do the
following:
cd norm/protolib
git checkout master
This will enable you to issue 'git pull', etc to treat the 'protolib'
sub-directory as its own (sub-) repository.
The NORM code depends upon the current "Protolib" release. The NORM
source code tarballs contain an appropriate release of "Protolib" as
part of the NORM source tree. If the NORM code is checked out from
our CVS server, it is necessary to also check out "protolib" separately
and provide paths to it for NORM to build.

0
TODO.TXT Executable file → Normal file
View File

14
VERSION.TXT Executable file → Normal file
View File

@ -1,19 +1,9 @@
NORM Version History
Version 1.5.10 (in progress)
=============
- NormSocket API improvements
Version 1.5.9
=============
- Added "normCast" file send/receive example
- Protolib ProtoTimer fix for "long" timeout intervals
Version 1.5.8
=============
- Modified waf build to build pkg-config file.cThanks to Luca Boccassi
for this and some other patches for Gnu/Hurd, etc.)
- Corrections to eliminate compiler warnings and suport kfreebsd builds
(Thanks to Luca Buccassi)
Version 1.5.7
=============

View File

@ -1,61 +0,0 @@
This directory contains Android Studio project files for building the NORM
library for Android.
REQUIREMENTS:
Ninja is required in order to run the ant build for the java .jar file
Download and install ndk and cmake using the SDK manager within Android Studio. To do this:
-> Tools -> SDK Manager -> System Settings -> Android SDK -> SDK Tools -> Select 'Show Package Details' at the bottom
The latest compatible versions are ndk version 20.0.5594570 and cmake version 3.10.2.4988404
* Important *
If you decide to install different version of the SDK Tools above, make sure to edit the path locations in the local.properties file
TO BUILD:
./gradlew build
The lib/build/ directory will contain the binary libraries built.
The "./gradlew clean" command can be used to delete the files built.
This directory may also be opened as an Android Studio project and built from
the IDE GUI.
This will evolve as we update NORM and associated projects to the newer Android
Studio tool chain.
USAGE:
Copy the .aar file into your ${project.rootDir}/app/libs/ folder
Within your app level build.gradle include the following two tasks before your dependencies section:
```
task extractSo(type: Copy) {
println 'Extracting *.so file(s)....'
from zipTree("${project.rootDir}/app/libs/lib-release_-release.aar")
into "${project.rootDir}/app/src/main/jniLibs"
include "jni/**/*.so"
eachFile {
def segments = it.getRelativePath().getSegments() as List
println segments
it.setPath(segments.tail().join("/"))
return it
}
includeEmptyDirs = false
}
task extractJar(type: Copy, dependsOn: extractSo) {
println 'Extracting *.jar file(s)....'
from zipTree("${project.rootDir}/app/libs/lib-release_-release.aar")
into "${project.rootDir}/app/libs/"
include "norm-*.jar"
}
```

View File

@ -1,16 +0,0 @@
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.1'
}
}
allprojects {
repositories {
google()
jcenter()
}
}

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Binary file not shown.

View File

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
android/gradlew vendored
View File

@ -1,234 +0,0 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
android/gradlew.bat vendored
View File

@ -1,89 +0,0 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,80 +0,0 @@
cmake_minimum_required(VERSION 3.4.1)
project("norm")
add_definitions("-DANDROID=1" "-DANDROID_API_VERSION=24" "-DPUSH_NOTIFICATIONS=1" "-DANDROID" "-DLINUX" "-DUNIX" "-DHAVE_IPV6" "-DHAVE_DIRFD" "-DPROTO_DEBUG" "-DHAVE_ASSERT" "-DHAVE_GETLOGIN" "-DUSE_SELECT" "-D_FILE_OFFSET_BITS=64" "-DHAVE_OLD_SIGNALHANDLER" "-DHAVE_SCHED" "-DNO_SCM_RIGHTS" "-Wno-attributes" "-DAPP_VERSION=1.0.0" "-DAPP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../OID_NDK}/sources/android/cpufeatures"
"../../include"
"../../protolib/include"
)
find_program(ANTPATH ant)
execute_process(
COMMAND ${ANTPATH}
WORKING_DIRECTORY "$ENV{HOME}/norm/makefiles/java/"
)
enable_language(ASM)
IF(BUILD_CONFIGURATION MATCHES "DEBUG")
SET(BINARY_NAME "norm")
add_definitions("-DDEBUG=1" "-D_DEBUG=1")
ELSEIF(BUILD_CONFIGURATION MATCHES "RELEASE")
SET(BINARY_NAME "norm")
add_definitions("-DNDEBUG=1")
ELSE(BUILD_CONFIGURATION MATCHES "DEBUG")
MESSAGE( FATAL_ERROR "No matching build-configuration found." )
ENDIF(BUILD_CONFIGURATION MATCHES "DEBUG")
add_subdirectory("../../protolib/android/lib" ./protolib)
add_library( ${BINARY_NAME}
STATIC
"../../src/common/galois.cpp"
"../../src/common/normApi.cpp"
"../../src/common/normEncoder.cpp"
"../../src/common/normEncoderMDP.cpp"
"../../src/common/normEncoderRS16.cpp"
"../../src/common/normEncoderRS8.cpp"
"../../src/common/normFile.cpp"
"../../src/common/normMessage.cpp"
"../../src/common/normNode.cpp"
"../../src/common/normObject.cpp"
"../../src/common/normSegment.cpp"
"../../src/common/normSession.cpp"
)
add_library( mil_navy_nrl_norm
SHARED
"../../src/java/jni/normDataJni.cpp"
"../../src/java/jni/normEventJni.cpp"
"../../src/java/jni/normFileJni.cpp"
"../../src/java/jni/normInstanceJni.cpp"
"../../src/java/jni/normJni.cpp"
"../../src/java/jni/normNodeJni.cpp"
"../../src/java/jni/normObjectJni.cpp"
"../../src/java/jni/normSessionJni.cpp"
"../../src/java/jni/normStreamJni.cpp"
)
find_library(log "log")
find_library(android "android")
find_library(glesv2 "GLESv2")
find_library(egl "EGL")
target_link_libraries(mil_navy_nrl_norm
norm
protokit
${log}
${android}
${glesv2}
${egl}
)

View File

@ -1,142 +0,0 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 34
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
signingConfigs {
normSigning {
storeFile file("${System.properties['user.home']}${File.separator}.android${File.separator}debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
storeType "jks"
}
}
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-24", "-DCMAKE_MAKE_PROGRAM=/usr/local/bin/ninja", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE"
cFlags "-fsigned-char"
cppFlags "-fsigned-char", "-std=c++14"
}
}
}
buildTypes {
debug {
initWith debug
debuggable true
jniDebuggable true
signingConfig signingConfigs.normSigning
}
release {
initWith release
debuggable false
jniDebuggable false
signingConfig signingConfigs.normSigning
}
}
flavorDimensions "default"
productFlavors {
debug_ {
ndk {
abiFilters "armeabi-v7a", "x86"
}
externalNativeBuild {
cmake {
targets "norm", "mil_navy_nrl_norm"
arguments "-DBUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0"
}
}
dimension "default"
}
release_ {
externalNativeBuild {
cmake {
targets "norm", "mil_navy_nrl_norm"
arguments "-DBUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3"
}
}
dimension "default"
}
}
variantFilter { variant ->
def names = variant.flavors*.name
if (names.contains ("debug_")
&& variant.buildType.name != "debug") {
setIgnore(true)
}
if (names.contains ("release_")
&& variant.buildType.name != "release") {
setIgnore(true)
}
}
repositories {
}
dependencies {
}
}
task copyReleaseJar(type: Copy) {
println 'Unzipping release .aar and including .jar....'
if (file("${project.rootDir}/lib/build/outputs/aar/lib-release_-release.aar").exists()) {
from zipTree("${project.rootDir}/lib/build/outputs/aar/lib-release_-release.aar")
into "${project.rootDir}/lib/build/outputs/aar/lib-release_-release"
from "${System.env.HOME}/norm/lib/norm-1.0.0.jar"
into "${project.rootDir}/lib/build/outputs/aar/lib-release_-release/"
}
}
task copyDebugJar(type: Copy, dependsOn: copyReleaseJar) {
println 'Unzipping debug .aar and including .jar....'
if (file("${project.rootDir}/lib/build/outputs/aar/lib-debug_-debug.aar").exists()){
from zipTree("${project.rootDir}/lib/build/outputs/aar/lib-debug_-debug.aar")
into "${project.rootDir}/lib/build/outputs/aar/lib-debug_-debug"
from "${System.env.HOME}/norm/lib/norm-1.0.0.jar"
into "${project.rootDir}/lib/build/outputs/aar/lib-debug_-debug/"
}
}
task zipReleaseAAR(type: Exec, dependsOn: copyDebugJar) {
println 'Creating new release .aar..'
ignoreExitValue true
workingDir "${project.rootDir}/lib/build/outputs/aar/"
executable 'jar'
def releaseArgsList = ['cvf', 'lib-release_-release.aar', '-C', 'lib-release_-release/', '.']
args releaseArgsList
}
task zipDebugAAR(type: Exec, dependsOn: zipReleaseAAR) {
println 'Creating new debug .aar..'
ignoreExitValue true
workingDir "${project.rootDir}/lib/build/outputs/aar/"
executable 'jar'
def debugArgsList = ['cvf', 'lib-debug_-debug.aar', '-C', 'lib-debug_-debug/', '.']
args debugArgsList
}
task deleteAARAssets(type: Delete, dependsOn: zipDebugAAR) {
delete "${project.rootDir}/lib/build/outputs/aar/lib-release_-release"
delete "${project.rootDir}/lib/build/outputs/aar/lib-debug_-debug"
}
this.build.finalizedBy(deleteAARAssets)

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0"
package="mil.navy.nrl.norm">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1 +0,0 @@
include ':lib'

View File

@ -1,7 +0,0 @@
include(GNUInstallDirs)
include(CMakeFindDependencyMacro)
# Add the targets file
include("${CMAKE_CURRENT_LIST_DIR}/normTargets.cmake")

0
doc/NormDeveloperGuide.html Executable file → Normal file
View File

0
doc/NormDeveloperGuide.pdf Executable file → Normal file
View File

43
doc/NormDeveloperGuide.xml Executable file → Normal file
View File

@ -13,19 +13,19 @@
<abstract>
<para>This document describes an application programming interface (API)
for the <ulink url="https://www.nrl.navy.mil/Our-Work/Areas-of-Research/Information-Technology/NCS/NORM/">Nack-Oriented
for the <ulink url="http://norm.pf.itd.nrl.navy.mil/">Nack-Oriented
Reliable Multicast (NORM)</ulink> protocol implementation developed by
the Protocol Engineering and Advance Networking (<ulink
url="https://www.nrl.navy.mil/itd/ncs/">PROTEAN</ulink>) Research Group of the
United States <ulink url="https://www.nrl.navy.mil/">Naval Research
url="http://cs.itd.nrl.navy.mil/">PROTEAN</ulink>) Research Group of the
United States <ulink url="http://www.nrl.navy.mil/">Naval Research
Laboratory</ulink> (NRL). The NORM protocol provides general purpose
reliable data transport for applications wishing to use Internet
Protocol (IP) Multicast services for group data delivery. NORM can also
support unicast (point-to-point) data communication and may be used for
such when deemed appropriate. The current NORM protocol specification is
given in the <ulink url="https://www.ietf.org/">Internet Engineering Task
given in the <ulink url="http://www.ietf.org/">Internet Engineering Task
Force</ulink> (IETF) <ulink
url="https://datatracker.ietf.org/doc/html/rfc5740">RFC 5740</ulink>. This
url="http://norm.pf.itd.nrl.navy.mil/rfc3940.pdf">RFC 3940</ulink>. This
document is currently a reference guide to the NORM API of the NRL
reference implementation. More tutorial material may be include in a
future version of this document or a separate developer's tutorial may
@ -37,19 +37,19 @@
<title>Background</title>
<para>This document describes an application programming interface (API)
for the <ulink url="https://www.nrl.navy.mil/Our-Work/Areas-of-Research/Information-Technology/NCS/NORM/">Nack-Oriented
for the <ulink url="http://norm.pf.itd.nrl.navy.mil/">Nack-Oriented
Reliable Multicast (NORM)</ulink> protocol implementation developed by the
Protocol Engineering and Advance Networking (<ulink
url="https://www.nrl.navy.mil/itd/ncs/">PROTEAN</ulink>) Research Group of the
United States <ulink url="https://www.nrl.navy.mil/">Naval Research
url="http://cs.itd.nrl.navy.mil/">PROTEAN</ulink>) Research Group of the
United States <ulink url="http://www.nrl.navy.mil/">Naval Research
Laboratory</ulink> (NRL). The NORM protocol provides general purpose
reliable data transport for applications wishing to use Internet Protocol
(IP) Multicast services for group data delivery. NORM can also support
unicast (point-to-point) data communication and may be used for such when
deemed appropriate. The current NORM protocol specification is given in
the <ulink url="https://www.ietf.org/">Internet Engineering Task
the <ulink url="http://www.ietf.org/">Internet Engineering Task
Force</ulink> (IETF) <ulink
url="https://datatracker.ietf.org/doc/html/rfc5740">RFC 5740</ulink>.</para>
url="http://norm.pf.itd.nrl.navy.mil/rfc5740.pdf">RFC 5740</ulink>.</para>
<para>The NORM protocol is designed to provide end-to-end reliable
transport of bulk data objects or streams over generic IP multicast
@ -134,7 +134,7 @@
may participate as senders and/or receivers within a NORM session. NORM
senders transmit data to the session destination address (usually an IP
multicast group) while receivers are notified of incoming data. The NORM
API provides an event notification scheme to notify the application of
API provides and event notification scheme to notify the application of
significant sender and receiver events. There are also a number support
functions provided for the application to control and monitor its
participation within a NORM transport session.</para>
@ -159,7 +159,7 @@
linkend="NormCreateInstance"><literal>NormCreateInstance()</literal></link>)
as needed for applications with specific requirements for accessing and
controlling participation in multiple <emphasis>NormSessions</emphasis>
from separate operating system threads. Or, alternatively, a
from separate operating system multiple threads. Or, alternatively, a
single <emphasis>NormInstance</emphasis> could be used, with a "master
thread" serving as an intermediary between the <link
linkend="NormGetNextEvent"><literal>NormGetNextEvent()</literal></link>
@ -194,7 +194,7 @@
number of concurrently active senders, this may translate to significant
memory allocation on receiver nodes. Currently, the API allows the
application to control how much buffer space is allocated for each
active sender (NOTE: In the future, API functions may be provided to limit
active sender (NOTE: In the future, API functions may be provided limit
the number of active senders monitored and/or provide the application
with finer control over receive buffer allocation, perhaps on a per
sender basis).</para>
@ -227,7 +227,7 @@
<title>Data Transmission</title>
<para>The behavior of data transport operation is largely placed in
the control of the NORM sender(s). NORM senders control their data
the control of the NORM sender(s). NORM senders controls their data
transmission rate, forward error correction (FEC) encoding settings,
and parameters controlling feedback from the receiver group. Multiple
senders may operate in a session, each with independent transmission
@ -253,7 +253,7 @@
be called before any calls to <link
linkend="NormStartReceiver"><literal>NormStartReceiver()</literal></link>
are made. However, note that the cache directory may be changed even
during active NORM reception. In this case, the newly specified
during active NORM reception. In this case, the new specified
directory path will be used for subsequently-received files. Any files
received before a directory path change will remain in the previous
cache location. Note that the <link
@ -477,14 +477,15 @@
Protokit. These are described below.</para>
<para>The "makefiles" directory contains Unix Makefiles for various
platforms. The "win32" and "wince" sub-directories there contain Microsoft
platforms the "win32" and "wince" sub-directories there contain Microsoft
Visual C++ (VC++) and Embedded VC++ project files for building the NORM
implementation. Additionally, a "waf" (Python-based build tool) build
option is supported that can be used to build and install the NORM library
code on the supported platforms. Finally, Python and Java bindings to the
NORM API are included in the "src/python" and "src/java" directories and the
"makefiles/java" directory contains Makefiles to build the NORM Java JNI bindings.
Note the "waf" tool can also be used to build the Java and Python bindings.</para>
NORM API are included and "src/python" and "src/java" directories contain
the code for these and the "makefiles/java" directory contains Makefiles
to build the NORM Java JNI bindings. Note the "waf" tool can also be used
to build the Java and Python bindings.</para>
<sect2>
<title>Unix Platforms</title>
@ -790,7 +791,7 @@
{
NormEventType type;
<link linkend="NormSessionHandle"><literal>NormSessionHandle</literal></link> session;
<link linkend="NormNodeHandle"><literal>NormNodeHandle</literal></link> sender;
<link linkend="NormNodeHandle"><literal>NormNodeHandle</literal></link> node;
<link linkend="NormObjectHandle"><literal>NormObjectHandle</literal></link> object;
} <link linkend="NormEvent"><literal>NormEvent</literal></link>;</programlisting></para>
@ -800,7 +801,7 @@
all <link
linkend="NormEventType"><literal>NormEventType</literal></link> fields
are relevant to all events. The <parameter>session</parameter>,
<parameter>sender</parameter>, and <parameter>object</parameter> fields
<parameter>node</parameter>, and <parameter>object</parameter> fields
indicate the applicable <link
linkend="NormSessionHandle"><literal>NormSessionHandle</literal></link>,
<link

0
doc/NormLogo.gif Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
doc/NormUserGuide.pdf Executable file → Normal file
View File

22
doc/NormUserGuide.xml Executable file → Normal file
View File

@ -96,13 +96,11 @@
<orderedlist>
<listitem>
<para>Download and unpack the NORM source code tarball or clone the github
repository using
<literal>git clone --recurse-submodules https://github.com/USNavalResearchLaboratory/norm.git</literal></para>
<para>Download and unpack the NORM source code tarball.</para>
</listitem>
<listitem>
<para><literal>cd norm/makefiles</literal></para>
<para><literal>cd norm/unix</literal></para>
</listitem>
<listitem>
@ -120,8 +118,7 @@
<orderedlist>
<listitem>
<para>Download and unpack the NORM source code tarball or clone the
repository as described in the section above.</para>
<para>Download and unpack the NORM source code tarball</para>
</listitem>
<listitem>
@ -131,7 +128,7 @@
</listitem>
<listitem>
<para>Inside the "<filename>norm/makefiles/win32</filename>" directory, open the "<filename>norm.sln</filename>" (VC++ .Net),
<para>Open the "<filename>norm.sln</filename>" (VC++ .Net),
"<filename>norm.dsw</filename>" (VC++ 6.0), or
"<filename>norm.vcw</filename>" (Embedded VC++) workspace
file.</para>
@ -140,14 +137,9 @@
<listitem>
<para>The "<emphasis>norm</emphasis>" project can be selected and
built.  The "<filename>norm.exe</filename>" file will be found in
the "<filename>norm/Win32/norm/Release</filename>" directory.</para>
the "<filename>norm/win32/norm/Release</filename>" directory.</para>
</listitem>
</orderedlist>
<para>The easiest way to run these builds is with Visual Studio. If you do not already have Visual Studio installed, then it can
be downloaded for free <ulink url="https://visualstudio.microsoft.com/downloads/?cid=learn-onpage-download-cta">here</ulink>.
When you launch Visual Studio, make sure to select "Visual C++" and open the "<filename>norm.sln</filename>" file.
This should load all of the project files and allow you to right-click on any of them in the Solution Explorer on the
left side and select "build".</para>
</sect2>
</sect1>
@ -388,7 +380,7 @@
<para>A minimal example <emphasis>norm</emphasis> sender command-line
syntax is:</para>
<para><literal>norm addr &lt;addr/port&gt; sendfile
<para><literal>norm addr &lt;addr/port&gt; sendFile
&lt;fileName&gt;</literal></para>
<para>The corresponding minimal <emphasis>norm</emphasis> receiver
@ -1168,4 +1160,4 @@
use with norm</emphasis>
</para>
</appendix>
</article>
</article>

0
doc/npcUsage.pdf Executable file → Normal file
View File

Binary file not shown.

View File

@ -1,413 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<article lang="">
<articleinfo>
<title><inlinemediaobject>
<imageobject>
<imagedata align="center" fileref="NormLogo.gif" scale="50"/>
</imageobject>
</inlinemediaobject> <command>npc</command> User Guide</title>
<subtitle>(NORM Precoder User Guide)</subtitle>
<titleabbrev><command>npc</command> User Guide</titleabbrev>
</articleinfo>
<sect1>
<title>Background</title>
<para>The NACK-Oriented Reliable Multicast (NORM) protocol is capable of
supporting robust transmission of content to "silent" receivers that are
required or only capable of operating in an emission-controlled (EMCON)
manner. This capability is enabled when the NORM sender is configured to
proactively transmit Forward Error Correction (FEC) erasure coding content
as part of its original data transmission. For NACK-based operation, the
FEC repair packets are usually sent only reactively, in response to repair
requests (NACKs) from the receiver group. However, hybrid operation with a
combination of proactive FEC content and additional reactive FEC repairs
as needed is also supported. Similarly, a mix of nacking and silent
receivers may be supported with silent receivers capitalizing on the FEC
repair information sent proactively and/or reactively. The purpose of the
NORM Pre-Coder (<command>npc</command>) software utility described here is
to support additional robustness for purely-proactive sessions, where the
receivers are unable to request repair or retransmission of
content.</para>
<para>The Naval Research Laboratory (NRL) reference implementation of the
NORM protocol includes support for 8-bit and 16-bit Reed-Solomon FEC
encoding with additional support for other coding algorithms (e.g.,
Low-Density Parity Check (LDPC)) planned for the future. The NORM
specification allows for different FEC algorithms to be applied within the
protocol. The current Reed-Solomon NORM FEC algorithms in the NRL
implementation are limited to modest code block sizes (With 16-bit
Reed-Solomon coding, larger block sizes will be allowed but very high data
rates may not be possible). For channels with random errors, the current
NORM FEC codecs are often adequate as there is flexibility in how the
encoded data can be partitioned into FEC blocks (a block consists of some
number of data segments (packets)) and the number of FEC parity packets
that can computed and possibly transmitted per source data block. For
channels with large bursts of packet loss (with respect to the configured
NORM FEC block size), it is quite possible that the number of lost packets
(erasures) that occur within a NORM FEC block may exceed the configured
erasure-filling capability. The <command>npc</command> utility was created
to "pre-encode" (and "post-decode") files for NORM transmission to silent
(non- NACKing) receivers by adding additional FEC encoding, and
importantly, interleaving of the FEC segments (packets) to re-distribute
bursts of packet losses as random losses over the entire file. It is thus
most applicable to very large files (with respect to FEC block
sizes).</para>
<para>The NORM protocol is described in Internet Engineering Task Force
(IETF) Request For Comments (RFC) RFC 5740 and RFC 5741. NRL provides a
NORM protocol library with a well-defined API that it is suitable for
application development. Refer to the NORM website &lt;<ulink
url="https://github.com/USNavalResearchLaboratory/norm">https://github.com/USNavalResearchLaboratory/norm</ulink>&gt;
for these other components as well as up-to-date versions of this
demonstration application and documentation.</para>
<para>The <command>npc</command> tool is designed to use in conjunction
with the NORM protocol and accompanying NORM file transfer examples that
are part of the NORM source code distribution. However, the encoded file
format that <command>npc</command> creates can be use with other
transports as well. The key is to align the segmentation parameters of the
<command>npc</command> configuration with that of the intended transport
mechanism.</para>
</sect1>
<sect1>
<title>Overview</title>
<para>The <command>npc</command> utility takes, as input", a file and
logically divides it into segments, adding cyclic-redundancy checksum
(CRC) to the segments, encoding the source segments with Reeed-Solomon
encoding (adding a configurable number of parity segments per FEC source
block), and interleaves the source and encoding segments to an output
file. The use of the CRC allows erasure to be detected and also provides
additional assurance of correct content delivery by possibly detecting bit
errors that may have been undetected during transport (i.e., link-layer
framing, Internet Protocol (IP), and/or User Datagram Protocol (UDP)
checksums). The interleaving by default is a block interleaver using the
entire file as a logical block, but a limit on the interleaving size can
be set to help increase the speed of the <command>npc</command>
encoding/decoding process. This may be useful for extremely large file
sizes.</para>
</sect1>
<sect1>
<title>Usage</title>
<para>The following is a synopsis of <command>npc</command> usage:</para>
<programlisting>npc {encode|decode} input &lt;inFile&gt; [output &lt;outFile&gt;][segment &lt;segmentSize&gt;]
{[[block &lt;numData&gt;][parity &lt;numParity&gt;]] |
[auto &lt;parityPercentage&gt;][bmax &lt;maxBlockSize&gt;]}
[imax &lt;widthLimit&gt;][ibuffer &lt;bytes&gt;][background][help][debug &lt;debugLevel&gt;]</programlisting>
<para>The <command>npc</command> utility may be instructed to either
"encode" a file (add FEC content and interleaving to the given
&lt;inFile&gt;) or "decode" a file that was previously encoded with
<command>npc</command>. The ".npc" file extension is suggested to
delineate files that are of the <command>npc</command> encoded format.
Note the "output" filename is optional. By default, <command>npc</command>
will use the filename of the &lt;inFile&gt; as the output filename,
replacing the '.' extension delimiter with a '_' (underscore) and adding
the ".npc" extension suffix. The <command>npc</command> format includes
some minimal "meta-data" in the first encoded &lt;segmentSize&gt; to
convey the file size and name of the original file. On decoding, if the
"output" file option is omitted, this "meta-data" is used to name the
decoded output file.</para>
<para>The optional FEC parameters,
<parameter>&lt;segmentSize&gt;</parameter>,
<parameter>&lt;numData&gt;</parameter>, and
<parameter>&lt;numParity&gt;</parameter> control the logical segmentation,
blocking, and amount of FEC parity content added to the file. For use with
NORM, it is recommended that the
<parameter>&lt;segmentSize&gt;</parameter> value correspond to the same
segmentation size used for NORM transmission. The
<parameter>&lt;numData&gt;</parameter> (source segments per FEC encoding
block) and <parameter>&lt;numParity&gt;</parameter> parameters should be
selected to provide erasure filling coverage for the expected transmission
packet loss characteristics. Note that when used with proactive NORM FEC
transmission, the <command>npc</command> encoding provides an "inner" FEC
code and interleaving and the NORM protocol provides an "outer" FEC
encoding. The "outer" NORM code might be configured to deal with typical
random packet loss due to channel BER, etc and the "inner"
<command>npc</command> interleaving and coding could be correspondingly
configured to handle expected burst losses (e.g. outages) that might
occur.</para>
<para>The <parameter>&lt;auto&gt;</parameter> option provides an
alternative means for setting the FEC encoding protection level instead of
using the <parameter>&lt;block&gt;</parameter> and
<parameter>&lt;parity&gt;</parameter> options. First the
<parameter>&lt;auto&gt;</parameter> option causes <command>npc</command>
to select a block size corresponding to the entire input file size (plus
the segment of meta data information that npc adds). Then, the
<parameter>&lt;auto&gt;</parameter> option
<parameter>&lt;parityPercentage&gt;</parameter> value is used to set the
number of parity packets per encoding block to the given percentage of the
automatically determined block size. For exanple, the command
"<option>auto 100"</option> causes <command>npc</command> to set an
encoding rate of 100%. I.e., the parity segments sent will equal the
number of segments in a bock. Note that the
<parameter>&lt;parityPercentage&gt;</parameter> can even exceed 100% if
desired for high levels of loss protection. Also note that the percentage
here is _not_ a loss protection percentage with a 100%
<parameter>&lt;parityPercentage&gt;</parameter> value being able to
correct up to 50% errored or lost packets within a coding block. With 50%
uniform random packet loss, this would result in successful file transfer
about 50% of the time as, per Gaussian distribution, burst error
probabilities would result in half of blocks arriving with greater than
50% packet loss and half with less than 50% packet loss.</para>
<para>When the <command>npc</command> encoder uses the
"<option>auto</option>" command the <command>npc</command> decoder MUST
also use the "<option>auto</option>" command and be configured with the
same <parameter>&lt;segmentSize&gt;</parameter> and
<parameter>&lt;parityPercentage&gt;</parameter> values. Similarly when the
"<option>block</option>" and "<option>parity</option>" commands are used
to explicitly set the <parameter>&lt;numdData&gt;</parameter> and
<parameter>&lt;numParity&gt;</parameter> at the encoder, the decoder MUST
be configured with the same corresponding options and values, again
including <parameter>&lt;segmentSize&gt;</parameter>. And for use with
NORM protocol transport, the <parameter>&lt;segmentSize&gt;</parameter>
parameter SHOULD be matched for best coding gain performance. The NORM
block size (numData) and parity (numParity) parameters may be set
indepedently. Basically, the NORM protocol proactive erasure coding can be
configured to deal with expected short term random packet loss while the
<command>npc</command> parameters can be configured to counter large burst
(or outage) losses. The inner/outer encoding approach that the combination
of <command>npc</command> and NORM provides, can allow for a sort of
multiplicative coding gain to deal well with both random packet loss and
bursts or outages with lower FEC overhead. However, when the
<command>npc</command> coding is configured (e.g., via the "auto" option)
to encapsulate an entire file into a single logical coding block, the
desired level of loss protection can be simply "dialed into" the
<command>npc</command> <parameter>&lt;parityPercentage&gt;</parameter>
option. The tradeoff is that the larger FEC block size increases the
computational requirement for file encoding and decoding. Future versions
of <command>npc</command> may provide additional FEC code types</para>
<para>As basic example usage, to encode a file name "originalFile.txt"
with the default <command>npc</command> naming convention, FEC, and
interleaving parameters, use the following syntax:</para>
<programlisting>npc encode input originalFile.txt</programlisting>
<para>This will produce and output file named
"<filename>originalFile_txt.npc</filename>" in the current working
directory. The default <command>npc</command> configuration is
"<command>auto 100.0</command>" providing 100% parity content which makes
the encoded file size roughly double the input file. The original file can
be recovered (decoded) using the syntax:</para>
<programlisting>npc decode input originalFile_txt.npc</programlisting>
<para>This will decode the ".npc" file, and in this case produce a file
named "<filename>originalFile.txt"</filename> in the current working
directory. (The file name information was stored in first "meta data"
segment of the ".npc" file). This default naming convention can be
overridden by using the <command>npc</command> "<option>output</option>"
command. For example, the syntax:</para>
<programlisting>npc decode input originalFile_txt.npc output file.txt</programlisting>
<para>will produce a file named "<filename>file.txt</filename>" that is
identical in content to "<filename>originalFile.txt</filename>".</para>
<sect2>
<title>Notes</title>
<para>The FEC and interleaving parameters that are used for
<command>npc</command> encoding MUST be exactly matched to successfully
decode the encoded file. I.e., if the defaults are used for encoding,
the defaults must be used for decoding. The parameters that must match
include <parameter>&lt;segmentSize&gt;</parameter>,
<parameter>&lt;parityPercentage&gt;</parameter> and
<parameter>&lt;maxBlockSize&gt;</parameter> (or
<parameter>&lt;numData&gt;</parameter> and
<parameter>&lt;numParity&gt;</parameter>), and
<parameter>&lt;widthMax&gt;</parameter>.</para>
<para>It is possible that in some cases it may be beneficial to apply
more proactive FEC content with the <command>npc</command> program
instead of with the NORM transport. The trade-offs are
scenario-specific.</para>
<para>The NRL "<command>norm</command>" demonstration application has
commands included to support transport of <command>npc</command> encoded
files. The distinction here is that a file that _fails_ NORM transport
might still be successfully decoded with <command>npc</command>. There
are two receiver-side <command>norm</command> demo application options
that apply here:</para>
<orderedlist>
<listitem>
<para>The "<option>saveAborts</option>" command causes
<command>norm</command> to not delete (and attempt to postprocess)
"aborted" files (files that failed reliable NORM transport).</para>
</listitem>
<listitem>
<para>The <command>norm</command> "<option>lowDelay</option>"
command should be applied for silent-receivers to more immediately
deliver "failed" files to the application for post-processing (i.e.,
attempted <command>npc</command> decoding)</para>
</listitem>
</orderedlist>
</sect2>
</sect1>
<sect1>
<title><command>npc</command> Command Reference</title>
<para>The following table describes each of the <command>npc</command>
commands available in the command-line syntax.</para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colnum="1" colwidth="1*"/>
<colspec colname="2" colwidth="2*"/>
<tbody>
<row>
<entry><para><option>encode</option> |
<option>decode</option></para></entry>
<entry><para>Determine whether <command>npc</command> is to encode
or decode the given <parameter>&lt;inFile&gt;</parameter>. This
option is required and only one should be given.</para></entry>
</row>
<row>
<entry><para><option>input
</option><parameter>&lt;inFile&gt;</parameter></para></entry>
<entry><para>Specifies the file to be processed. Required
command.</para></entry>
</row>
<row>
<entry><para><option>output
</option><parameter>&lt;outFile&gt;</parameter></para></entry>
<entry><para>Specifies the name of the output file to be produced.
Overrides the default <command>npc</command> output file naming
convention. Optional.</para></entry>
</row>
<row>
<entry><para><option>segment
</option><parameter>&lt;segmentSize&gt;</parameter></para></entry>
<entry><para>Sets the segmentation size (e.g., packet payload
size) in bytes. Note four bytes of the
<parameter>&lt;segmentSize&gt;</parameter> are used for a 32-bit
CRC that <command>npc</command> applies to each segment. (Default
<parameter>&lt;segmentSize&gt;</parameter> is 1024
bytes)</para></entry>
</row>
<row>
<entry><para><option>block
</option><parameter>&lt;numData&gt;</parameter></para></entry>
<entry><para>Specify the number of source data segments (packets)
per <command>npc</command> FEC coding block. (Default block sizing
is auto)</para></entry>
</row>
<row>
<entry><para><option>parity
</option><parameter>&lt;numParity&gt;</parameter></para></entry>
<entry><para>Specify the number of FEC parity segments (packets)
added per <command>npc</command> FEC coding block. (Default is 2
segments).</para></entry>
</row>
<row>
<entry><para><option>auto
</option><parameter>&lt;parityPercentage&gt;</parameter></para></entry>
<entry><para>Specifies automatic FEC block sizing with
<parameter>&lt;parityPercentage&gt;</parameter> indicating the
percentage of FEC parity segments to include per block. The "auto"
block sizing sets the block size as large as possible to treat the
entire files as one logical FEC block to maximize FEC performance.
The maximum possible block size currently supported by
<command>npc</command> are blocks where (numData + numParity) is
less than or equal to 65536. The maximum buffer size can be
limited by using the <option>bmax</option> command.</para></entry>
</row>
<row>
<entry><para><option>bmax
</option><parameter>&lt;maxBlockSize&gt;</parameter></para></entry>
<entry><para>Limits the maximum block size when the
<option>auto</option> command is used for automatic block sizing
(Default is 65536)</para></entry>
</row>
<row>
<entry><para><option>imax
</option><parameter>&lt;widthMax&gt;</parameter></para></entry>
<entry><para>Limits interleaving of encoded file to a maximum
interleaver width of <parameter>&lt;widthMax&gt;</parameter>
segments. A value of ZERO (or less) defaults to
<command>npc</command> calculating a block interleaver that
encompasses the entire encoded file size. For extremely large
files, this option may be beneficial to limit file seeking
operations required to interleave the file. If the encoded file
size is less than
<parameter>&lt;widthMax&gt;</parameter>*<parameter>&lt;widthMax&gt;</parameter>
segments, <command>npc</command> will again calculate its own
maximum block size. (Default is 1000 segments interleaver depth
(i.e., about 1 Gbyte interleaver size with the default 1024 byte
<parameter>&lt;segmentSize&gt;</parameter> value))</para></entry>
</row>
<row>
<entry><para><option>ibuffer
</option><parameter>&lt;bufferSize&gt;</parameter></para></entry>
<entry><para>This sets the maximum memory (in bytes) that
<command>npc</command> allocates for encoding. A larger value
allows <command>npc</command> to perform file input/output with
less seeking and improved encoding/decoding times can be achieved.
(Default is 1.5 GByte)</para></entry>
</row>
<row>
<entry><para><option>debug
</option><parameter>&lt;debugLevel&gt;</parameter></para></entry>
<entry><para>Specifies debug output verbosity. Higher number is
more verbose debugging information. (Default is
ZERO).</para></entry>
</row>
<row>
<entry><para><option>background</option></para></entry>
<entry><para>Sets percentage of received messages that are
randomly dropped (for testing purposes). Default = 0.0
percent.</para></entry>
</row>
<row>
<entry><para><option>help</option></para></entry>
<entry><para>Displays <command>npc</command> usage
statement.</para></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect1>
</article>

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -e
echo Running example $@
exec "$NORM_BUILD/$@"

View File

@ -1,59 +0,0 @@
#!/usr/bin/env bash
set -eux
install_debian()
{
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -yq \
python2.7 \
g++ \
libxml2-dev \
libnetfilter-queue-dev
ln -s /usr/bin/python2.7 /usr/bin/python
if [ "$VERSION" != "" ]; then
apt-get install -yq git-core
cd $NORM_DIR && git checkout $VERSION && git submodule update --checkout --init --force
fi
if [[ "$WAF_CONFIGURE" =~ "java" && -z `which java` ]]; then
apt-get install -yq default-jdk-headless
export JAVA_HOME=$(readlink -f `which java` | sed 's/\/bin\/java//')
fi
}
install_redhat()
{
yum update -y
yum install -y \
which \
centos-release-scl
yum install -y \
gcc-c++ \
libxml2-devel \
libnetfilter_queue-devel
if [ "$VERSION" != "" ]; then
yum install -y git
cd $NORM_DIR && git checkout $VERSION && git submodule update --checkout --init --force
fi
if [[ "$WAF_CONFIGURE" =~ "java" && -z `which java` ]]; then
yum install -y java-1.8.0-openjdk-devel
export JAVA_HOME=$(readlink -f `which java` | sed 's/\/jre\/bin\/java//')
fi
}
configure_norm()
{
cd $NORM_DIR && ./waf configure ${WAF_CONFIGURE}
}
if [ ! -z `which apt` ]; then
install_debian
elif [ ! -z $(which yum) ] || [ "$?" = "1" ]; then
install_redhat
fi
configure_norm

78
examples/README.TXT Executable file → Normal file
View File

@ -2,45 +2,16 @@
This directory contains some purposely simplified examples of NORM
API usage. See comments in the source code files on how to build
these on Unix platforms. Most of these can be built with either the
Makefiles or Visual Studio projects, but the 'waf' build option is more
straightforward to use, particularly for Java and Python builds.
these on Unix platforms. Eventually, "Makefiles" (and hopefully
"waf" configure/build scripts) will be provided as well as Visual
C++ project files for Win32 builds.
The most complete examples are the following:
The following example programs are included:
normMsgr.cpp - Also java/NormMsgr.java and python/normMsgr.py
implementations are available with same functionality.
This sends messages piped to STDIN and receiver
instances can pipe received messages to STDOUT.
"Messages" are binary with a two-byte (Big Endian)
message length header. A normMsgr instnace can act
as a sender and/or receiver. This program uses
NORM_OBJECT_DATA as its transport mode. It has options
to illustrate ACK-based flow control, and passive/active
flushing of NORM transmission stream.
normStreamer.cpp - Similar to normMsgr, but uses NORM_OBJECT_STREAM.
It can support byte- and message-stream transport
with the same 2-byte message length header.
(TBD - implement Java and Python versions of this)
normCast.cpp - Similar to above two, but uses NORM_OBEJCT_FILE
to transmit files and/or or directories of files.
This will eventually have the same file casting
options as the "norm" demo app has such as
repeat iterations through the file/directory list
and ability to monitor one or more directories
as live "outboxes" where files can be deposited
for transmission.
normClient/normServer - illustrate use of the NormSocket API extension
that is a work in progress, but fully functional
for TCP-like byte-streaming applications.
The following example programs are mainly "sketches" that illustrate
the NORM API at a high level. These programs primarily use a hard-coded
multicast address and port, but some have simple options:
(These two programs use a hard-coded multicast address and port,
but take a file name and directory name, respectively, as a
command-line argument to determine the file sent and the directory
to which receive files are stored.)
normFileSend.cpp - simple file transmission program. Sends one
file and exits.
@ -63,15 +34,32 @@ normDataRecv.cpp - simple NORM_OBJECT_DATA reception program. This
java - There is a README.TXT in the java directory.
It explains the java examples, how to build
them, and how to run them. Other than
'NormMsgr.java', the examples there
haven't been tested thoroughly/recently.
python - Other than 'normMsgr.py', the examples there
haven't been tested thoroughly/recently.
them, and how to run them.
NOTES:
Althought the normDataSend/Recv example use relatively small data
object sizes, the _intended_ use of NORM_OBJECT_DATA is for bulkier
content stored in application memory space.
For "messaging" applications that use modestly small message
sizes, the NORM_OBJECT_STREAM transport option in NORM is likely
to provide more efficient service than NORM_OBJECT_DATA for small
objects due to the packet level Forward Error Correction (FEC)
based packet recovery mechanism that NORM uses.
In the future, a similar "simple" example pair will be provided to
illustrate the NORM_OBJECT_STREAM form of transport. Meanwhile,
the "normTest.cpp" file in the "norm/src/common" directory
provides an example of the NORM API calls related to this.
Other examples will be added later including examples using the
"NormGetDescriptor()" function to allow NORM API events to be
multiplexed with other possible application events (e.g. other I/O
or Windows messages, etc).
Brian Adamson
<mailto: badamson@gmail.com>
27 December 2019
<mailto:adamson@itd.nrl.navy.mil>
20 August 2010

File diff suppressed because it is too large Load Diff

0
examples/java/NormFileRecv.java Executable file → Normal file
View File

0
examples/java/NormFileSend.java Executable file → Normal file
View File

0
examples/java/NormFileSendRecv.java Executable file → Normal file
View File

0
examples/java/NormMsgr.java Executable file → Normal file
View File

0
examples/java/NormStreamRecv.java Executable file → Normal file
View File

4
examples/java/NormStreamSend.java Executable file → Normal file
View File

@ -10,8 +10,8 @@ public class NormStreamSend {
static final long REPAIR_WINDOW_SIZE = 1024 * 1024;
static final long SESSION_BUFFER_SIZE = 1024 * 1024;
static final int SEGMENT_SIZE = 1400;
static final short BLOCK_SIZE = 64;
static final short PARITY_SEGMENTS = 16;
static final int BLOCK_SIZE = 64;
static final int PARITY_SEGMENTS = 16;
static final String DEST_ADDRESS = "224.1.2.3";
static final int DEST_PORT = 6003;

0
examples/java/README.TXT Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

48
examples/normClient.cpp Executable file → Normal file
View File

@ -27,7 +27,7 @@
void Usage()
{
fprintf(stderr, "Usage: normClient [connect <serverAddr>/<port>[,<groupAddr>]][debug <level>][trace]\n");
fprintf(stderr, "Usage: normClient [connect <serverAddr>[/<port>][,<groupAddr>]][debug <level>][trace]\n");
}
const unsigned int MSG_LENGTH_MAX = 64;
@ -136,21 +136,11 @@ int main(int argc, char* argv[])
}
NormInstanceHandle instance = NormCreateInstance();
NormSocketHandle normSocket = NormOpen(instance);
if (trace)
{
NormSetMessageTrace(NormGetSocketSession(normSocket), true);
if (NULL != groupAddrPtr)
NormSetMessageTrace(NormGetSocketMulticastSession(normSocket), true);
}
if (0 != debugLevel) NormSetDebugLevel(debugLevel);
//NormSetDebugLevel(3);
//NormSetMessageTrace(NormGetSocketSession(normSocket), true);
// Initate connection to server ...
fprintf(stderr, "normClient: connecting to %s/%hu ...\n", serverAddr, serverPort);
fprintf(stderr, "normClient: connecting to %s/%hu ...\n", serverAddr, serverPort);
NormSocketHandle normSocket = NormOpen(instance);
// setting 'localPort' param here to zero lets an ephemeral port be picked
NormConnect(normSocket, serverAddr, serverPort, 0, groupAddrPtr, clientId);
/* // Optional code to test NormWrite() immediately after NormConnect() call
@ -160,7 +150,16 @@ int main(int argc, char* argv[])
NormWrite(normSocket, helloStr, helloLen);
NormFlush(normSocket);*/
if (trace)
{
NormSetMessageTrace(NormGetSocketSession(normSocket), true);
if (NULL != groupAddrPtr)
NormSetMessageTrace(NormGetSocketMulticastSession(normSocket), true);
}
if (0 != debugLevel) NormSetDebugLevel(debugLevel);
//NormSetDebugLevel(3);
//NormSetMessageTrace(NormGetSocketSession(normSocket), true);
#ifdef WIN32
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
@ -257,10 +256,9 @@ int main(int argc, char* argv[])
{
// Input stream has likely closed, initiate client shutown
// TBD - initiate client shutdown
//if (NULL == groupAddrPtr)
if (NULL == groupAddrPtr)
{
fprintf(stderr, "normClient: CLOSING connection to %sserver ...\n",
(NULL != groupAddrPtr) ? : "multicast " : "");
fprintf(stderr, "normClient: CLOSING connection to server ...\n");
NormShutdown(normSocket);
}
inputNeeded = false; // TBD -should we also fclose(inputFile)???
@ -278,10 +276,9 @@ int main(int argc, char* argv[])
else if (feof(inputFile))
{
// TBD - initiate client shutdown
//if (NULL == groupAddrPtr)
if (NULL == groupAddrPtr)
{
fprintf(stderr, "normClient: CLOSING connection to %sserver ...\n",
(NULL != groupAddrPtr) ? "multicast " : "");
fprintf(stderr, "normClient: CLOSING connection to server ...\n");
NormShutdown(normSocket);
}
inputNeeded = false; // TBD -should we also fclose(inputFile)???
@ -328,12 +325,9 @@ int main(int argc, char* argv[])
unsigned int addrLen = 16;
UINT16 remotePort;
NormGetPeerName(normSocket, remoteAddr, &addrLen, &remotePort);
fprintf(stderr, "normClient: CONNECTED to %sserver %s/%hu\n",
(NULL != groupAddrPtr) ? "multicast " : "", serverAddr, remotePort);
fprintf(stderr, "normClient: CONNECTED to server %s/%hu\n", serverAddr, remotePort);
inputNeeded = true;
writeReady = true;
if (trace && (NULL != groupAddrPtr))
NormSetMessageTrace(NormGetSocketMulticastSession(normSocket), true);
break;
}
case NORM_SOCKET_READ:
@ -371,15 +365,13 @@ int main(int argc, char* argv[])
writeReady = true;
break;
case NORM_SOCKET_CLOSING:
fprintf(stderr, "normClient: %sserver CLOSING connection ...\n",
(NULL != groupAddrPtr) ? "multicast " : "");
fprintf(stderr, "normClient: server CLOSING connection ...\n");
writeReady = false;
inputNeeded = false;
break;
case NORM_SOCKET_CLOSE:
{
fprintf(stderr, "normClient: connection to %sserver CLOSED.\n",
(NULL != groupAddrPtr) ? "multicast " : "");
fprintf(stderr, "normClient: connection to server CLOSED.\n");
writeReady = false;
inputNeeded = false;
keepGoing = false;

4
examples/normDataExample.cpp Executable file → Normal file
View File

@ -3,7 +3,7 @@
// The "data" sent and received are simple text messages
// of randomly-varying length.
XXX - THIS CODE IS NOT YET A COMPLETE EXAMPLE !!!!!
XXXX - THIS CODE IS NOT YET COMPLETE !!!!!
#include <normApi.h>
@ -12,8 +12,6 @@ XXX - THIS CODE IS NOT YET A COMPLETE EXAMPLE !!!!!
#include <protoDebug.h>
#include <protoTime.h>
#include <stdlib.h> // for rand(), srand()
void Usage()
{
fprintf(stderr, "Usage: normDataExample [send][recv]\n");

0
examples/normDataRecv.cpp Executable file → Normal file
View File

0
examples/normDataSend.cpp Executable file → Normal file
View File

2
examples/normFileRecv.cpp Executable file → Normal file
View File

@ -63,7 +63,7 @@ int main(int argc, char* argv[])
// NOTE: These are debugging routines available
// (not necessary for normal app use)
// (Need to include "common/protoDebug.h" for this
// (Need to include "protolib/common/protoDebug.h" for this
//SetDebugLevel(2);
// Uncomment to turn on debug NORM message tracing
//NormSetMessageTrace(session, true);

2
examples/normFileSend.cpp Executable file → Normal file
View File

@ -71,7 +71,7 @@ int main(int argc, char* argv[])
// NOTE: These are some debugging routines available
// (not necessary for normal app use)
// (Need to include "common/protoDebug.h" for this
// (Need to include "protolib/common/protoDebug.h" for this
//SetDebugLevel(2);
// Uncomment to turn on debug NORM message tracing
NormSetMessageTrace(session, true);

75
examples/normMsgr.cpp Executable file → Normal file
View File

@ -192,18 +192,10 @@ class NormMsgr
{omit_header = state;}
// These can only be called post-OpenNormSession
void SetAutoAck(bool enable)
{
NormTrackingStatus trackingMode = enable? NORM_TRACK_RECEIVERS : NORM_TRACK_NONE;
NormSetAutoAckingNodes(norm_session, trackingMode);
norm_acking = enable;
}
void SetSilentReceiver(bool state)
{NormSetSilentReceiver(norm_session, state);}
{NormSetSilentReceiver(norm_session, true);}
void SetTxLoss(double txloss)
{NormSetTxLoss(norm_session, txloss);}
void SetRxLoss(double rxloss)
{NormSetRxLoss(norm_session, rxloss);}
private:
bool is_running;
@ -781,12 +773,9 @@ void NormMsgr::HandleNormEvent(const NormEvent& event)
void Usage()
{
fprintf(stderr, "Usage: normMsgr id <nodeIdInteger> {send &| recv} [addr <addr>[/<port>]]\n"
" [ack auto|<node1>[,<node2>,...]] [output <outFile>]\n"
" [cc|cce|ccl|rate <bitsPerSecond>] [interface <name>] [loopback]\n"
" [debug <level>] [trace] [log <logfile>] [silent]\n"
" [flush {none|passive|active}] [omit] [txloss <lossFraction>]\n"
" [rxloss <lossFraction>]\n");
fprintf(stderr, "Usage: normMsgr id <nodeId> {send &| recv} [addr <addr>[/<port>]][ack <node1>[,<node2>,...]\n"
" [cc|cce|ccl|rate <bitsPerSecond>][interface <name>][debug <level>][trace]\n"
" [flush {none|active}][omit][silent][txloss <lossFraction>]\n");
}
int main(int argc, char* argv[])
{
@ -799,7 +788,6 @@ int main(int argc, char* argv[])
strcpy(sessionAddr, "224.1.2.3");
unsigned int sessionPort = 6003;
bool autoAck = false;
NormNodeId ackingNodeList[256];
unsigned int ackingNodeCount = 0;
bool flushing = false;
@ -814,7 +802,6 @@ int main(int argc, char* argv[])
bool omitHeaderOnOutput = false;
bool silentReceiver = false;
double txloss = 0.0;
double rxloss = 0.0;
bool loopback = false;
NormMsgr normMsgr;
@ -899,28 +886,20 @@ int main(int argc, char* argv[])
return -1;
}
const char* alist = argv[i++];
if (0 == strcmp("auto", alist))
while ((NULL != alist) && (*alist != '\0'))
{
autoAck = true;
}
else
{
autoAck = false;
while ((NULL != alist) && (*alist != '\0'))
// TBD - Do we need to skip leading white space?
int id;
if (1 != sscanf(alist, "%d", &id))
{
// TBD - Do we need to skip leading white space?
int id;
if (1 != sscanf(alist, "%d", &id))
{
fprintf(stderr, "nodeMsgr error: invalid acking node list!\n");
Usage();
return -1;
}
ackingNodeList[ackingNodeCount] = NormNodeId(id);
ackingNodeCount++;
alist = strchr(alist, ',');
if (NULL != alist) alist++; // point past comma
fprintf(stderr, "nodeMsgr error: invalid acking node list!\n");
Usage();
return -1;
}
ackingNodeList[ackingNodeCount] = NormNodeId(id);
ackingNodeCount++;
alist = strchr(alist, ',');
if (NULL != alist) alist++; // point past comma
}
}
else if (0 == strncmp(cmd, "flush", len))
@ -1007,15 +986,6 @@ int main(int argc, char* argv[])
return -1;
}
}
else if (0 == strncmp(cmd, "rxloss", len))
{
if (1 != sscanf(argv[i++], "%lf", &rxloss))
{
fprintf(stderr, "nodeMsgr error: invalid 'rxloss' value!\n");
Usage();
return -1;
}
}
else if (0 == strncmp(cmd, "debug", len))
{
if (i >= argc)
@ -1081,22 +1051,15 @@ int main(int argc, char* argv[])
{
fprintf(stderr, "normMsgr error: unable to open NORM session\n");
NormDestroyInstance(normInstance);
return -1;
return false;
}
if (silentReceiver) normMsgr.SetSilentReceiver(true);
if (txloss > 0.0) normMsgr.SetTxLoss(txloss);
if (rxloss > 0.0) normMsgr.SetRxLoss(rxloss);
if (autoAck)
{
normMsgr.SetAutoAck(true);
}
else
{
for (unsigned int i = 0; i < ackingNodeCount; i++)
normMsgr.AddAckingNode(ackingNodeList[i]);
}
for (unsigned int i = 0; i < ackingNodeCount; i++)
normMsgr.AddAckingNode(ackingNodeList[i]);
normMsgr.SetNormCongestionControl(ccMode);
if (NormMsgr::NORM_FIXED == ccMode)

7
examples/normServer.cpp Executable file → Normal file
View File

@ -203,7 +203,7 @@ ClientInfo NormGetClientInfo(NormNodeHandle client)
return ClientInfo(version, addr, port);
} // end NormGetClientInfo(NormNodeHandle)
static ClientInfo NormGetSocketInfo(NormSocketHandle socket)
ClientInfo NormGetSocketInfo(NormSocketHandle socket)
{
char addr[16]; // big enough for IPv6
unsigned int addrLen = 16;
@ -490,11 +490,6 @@ int main(int argc, char* argv[])
{
if (event.socket == serverSocket)
{
// TBD - now that the NormSocket code manages its own client_table by remote addr/port
// and should eliminate the 'duplicative' connect itself, we can just keep track
// of client sockets by their NormSocketHandle
// Possibly a new "client" connecting to our "server"
// First confirm that this really is a new client.
if (NORM_SOCKET_INVALID != FindClientSocket(clientMap, clientInfo))

428
examples/normSocket.cpp Executable file → Normal file
View File

@ -4,9 +4,6 @@
#include <assert.h> // for assert()
#include <string.h> // for strlen()
#include "protoTree.h"
#include "protoAddress.h"
#ifdef WIN32
#include <Winsock2.h> // for inet_ntoa() (TBD - change to use Protolib routines?)
#include <Ws2tcpip.h> // for inet_ntop()
@ -41,13 +38,6 @@ enum NormSocketCommand
NORM_SOCKET_CMD_REJECT, // sent by server-listener to reject invalid connection messages
NORM_SOCKET_CMD_ALIVE // TBD - for NormSocket "keep-alive" option?
};
// Default socket option values. Can be overrided with NormSetSocketOptions()
const UINT16 DEFAULT_NUM_DATA = 32;
const UINT16 DEFAULT_NUM_PARITY = 4;
const UINT16 DEFAULT_NUM_AUTO = 0;
const UINT16 DEFAULT_SEGMENT_SIZE = 1400;
const unsigned int DEFAULT_BUFFER_SIZE = 2*1024*1024;
// a 'helper' function we use for debugging
const char* NormNodeGetAddressString(NormNodeHandle node)
@ -65,7 +55,7 @@ const char* NormNodeGetAddressString(NormNodeHandle node)
else
addrFamily = AF_INET6;
inet_ntop(addrFamily, addr, text, 31);
snprintf(text + strlen(text), 64 - strlen(text), "/%hu", port);
sprintf(text + strlen(text), "/%hu", port);
return text;
}
else
@ -74,110 +64,6 @@ const char* NormNodeGetAddressString(NormNodeHandle node)
}
} // end NormNodeGetAddressString()
class NormSocketInfo : public ProtoTree::Item
{
public:
NormSocketInfo(unsigned int remoteAddrLen, const char* remoteAddr, UINT16 remotePort)
: norm_socket(NULL)
{
info_keysize = MakeKey(info_key, remoteAddrLen, remoteAddr, remotePort);
}
// copy constructor
NormSocketInfo(const NormSocketInfo& s)
{*this = s;}
~NormSocketInfo() {}
void SetSocket(class NormSocket* theSocket)
{norm_socket = theSocket;}
class NormSocket* GetSocket()
{return norm_socket;}
static unsigned int MakeKey(unsigned char* key, unsigned int remoteAddrLen, const char* remoteAddr, UINT16 remotePort)
{
key[0] = remoteAddrLen;
memcpy(key + 1, remoteAddr, remoteAddrLen);
unsigned int keysize = remoteAddrLen + 1;
memcpy(key + keysize, &remotePort, 2);
keysize += 2;
keysize <<= 3; // to size in 'bits'
return keysize;
}
void GetRemoteAddress(ProtoAddress& theAddr) const
{
int remoteAddrLen = info_key[0];
const char* remoteAddrPtr = (char*)info_key + 1;
ProtoAddress::Type addrType;
switch (remoteAddrLen)
{
case 4:
addrType = ProtoAddress::IPv4;
break;
case 16:
addrType = ProtoAddress::IPv6;
break;
default:
theAddr.Invalidate();
ASSERT(0);
return;
}
theAddr.SetRawHostAddress(addrType, remoteAddrPtr, remoteAddrLen);
UINT16 remotePort;
memcpy(&remotePort, remoteAddrPtr + remoteAddrLen, 2);
theAddr.SetPort(remotePort);
}
const char* GetKey() const
{return (const char*)info_key;}
unsigned int GetKeysize() const
{return info_keysize;}
private:
// remoteAddrLen + remoteAddr + remotePort
// 1 + 16 max + 2
unsigned char info_key[19];
unsigned int info_keysize;
class NormSocket* norm_socket; // may be NULL if it is pending acceptance
}; // end class NormSocketInfo
// helper function
NormSocketInfo NormGetSocketInfo(NormNodeHandle client)
{
char remoteAddr[16]; // big enough for IPv6
unsigned int remoteAddrLen = 16;
UINT16 remotePort;
NormNodeGetAddress(client, remoteAddr, &remoteAddrLen, &remotePort);
return NormSocketInfo(remoteAddrLen, remoteAddr, remotePort);
} // end NormGetSocketInfo()
class NormSocketTable : public ProtoTreeTemplate<NormSocketInfo>
{
public:
NormSocketInfo* FindSocketInfo(UINT16 remotePort, unsigned int remoteAddrLen, const char* remoteAddr)
{
unsigned char key[19];
unsigned int keysize = NormSocketInfo::MakeKey(key, remoteAddrLen, remoteAddr, remotePort);
return Find((char*)key, keysize);
}
NormSocketInfo* FindSocketInfo(NormNodeHandle client)
{
NormSocketInfo socketInfo = NormGetSocketInfo(client);
return Find(socketInfo.GetKey(), socketInfo.GetKeysize());
}
void RemoveSocketInfo(NormSocketInfo& socketInfo)
{
// safety dance
if (NULL == Find(socketInfo.GetKey(), socketInfo.GetKeysize())) return; // not on the dance floor
Remove(socketInfo);
}
}; // end class NormSocketTable
class NormSocket
{
public:
@ -203,9 +89,6 @@ class NormSocket
{return (NULL != server_socket);}
bool IsClientSide() const
{return (NULL == server_socket);}
NormSocket* GetServerSocket()
{return server_socket;}
NormInstanceHandle GetInstance() const
{return NormGetInstance(norm_session);}
@ -214,22 +97,12 @@ class NormSocket
NormSessionHandle GetMulticastSession() const
{return mcast_session;}
NormObjectHandle GetTxStream() const
{return tx_stream;}
void InitRxStream(NormObjectHandle rxStream)
{rx_stream = rxStream;}
NormObjectHandle GetRxStream() const
{return rx_stream;}
void SetFlowControl(bool state)
{
tx_flow_control = state;
if (NORM_OBJECT_INVALID != tx_stream)
NormStreamSetPushEnable(tx_stream, state ? false : true);
}
void InitTxStream(NormObjectHandle txStream, unsigned int bufferSize, UINT16 segmentSize, UINT16 blockSize)
{
tx_stream = txStream;
@ -240,7 +113,6 @@ class NormSocket
tx_stream_bytes_remain = 0;
tx_watermark_pending = false;
tx_ready = true;
NormStreamSetPushEnable(tx_stream, tx_flow_control ? false : true);
}
bool Open(NormInstanceHandle instance = NORM_INSTANCE_INVALID);
@ -261,26 +133,6 @@ class NormSocket
// hard, immediate closure
void Close();
void GetOptions(NormSocketOptions* options)
{
if (NULL != options) *options = socket_option;
}
bool SetOptions(NormSocketOptions* options)
{
// TBD - do validity checking and perhaps reset to defaults if (NULL == options)
if (NULL != options) socket_option = *options;
return true;
}
void SetSocketInfo(NormSocketInfo* socketInfo) // for server-side, client sockets only
{socket_info = socketInfo;}
NormSocketInfo* FindSocketInfo(NormNodeHandle client)
{return client_table.FindSocketInfo(client);}
void RemoveSocketInfo(NormSocketInfo& socketInfo) // for server sockets only
{client_table.RemoveSocketInfo(socketInfo);}
void SetUserData(const void* userData)
{user_data = userData;}
@ -317,12 +169,6 @@ class NormSocket
void RemoveAckingNode(NormNodeId nodeId)
{NormRemoveAckingNode(norm_session, nodeId);}
UINT16 GetLocalPort() const
{return (NORM_SESSION_INVALID != norm_session) ? NormGetRxPort(norm_session) : 0;}
//bool GetLocalAddress(char* addr, unsigned int& addrLen, UINT16& port)
// {return NormGetRxBindAddress(norm_session, addr, addrLen, port)}
void GetPeerName(char* addr, unsigned int* addrLen, UINT16* port)
{
if (NULL == addrLen) return;
@ -356,13 +202,10 @@ class NormSocket
remote_version = 6;
}
NormSocketOptions socket_option;
State socket_state;
NormSessionHandle norm_session;
NormSessionHandle mcast_session; // equals norm_session for a multicast server
NormSocket* server_socket; // only applies to server-side sockets
NormSocketTable client_table; // only applies to server sockets
NormSocketInfo* socket_info; // only applies to server-side, client sockets
unsigned int client_count; // only applies to mcast server sockets
NormNodeId client_id; // only applies to mcast client socket
NormNodeHandle remote_node; // client socket peer info
@ -377,7 +220,6 @@ class NormSocket
unsigned int tx_stream_buffer_count;
unsigned int tx_stream_bytes_remain;
bool tx_watermark_pending;
bool tx_flow_control;
// Receive stream state
NormObjectHandle rx_stream;
const void* user_data; // for use by user application
@ -388,23 +230,13 @@ class NormSocket
NormSocket::NormSocket(NormSessionHandle normSession)
: socket_state(CLOSED), norm_session(normSession),
mcast_session(NORM_SESSION_INVALID), server_socket(NULL),
socket_info(NULL), client_count(0), client_id(NORM_NODE_NONE),
client_count(0), client_id(NORM_NODE_NONE),
remote_node(NORM_NODE_INVALID), remote_version(0), remote_port(0),
tx_stream(NORM_OBJECT_INVALID), tx_ready(false), tx_segment_size(0),
tx_stream_buffer_max(0), tx_stream_buffer_count(0),
tx_stream_bytes_remain(0), tx_watermark_pending(false),
tx_flow_control(true),
rx_stream(NORM_OBJECT_INVALID), user_data(NULL)
{
// Initialize socket_option with default values
socket_option.num_data = DEFAULT_NUM_DATA;
socket_option.num_parity = DEFAULT_NUM_PARITY;
socket_option.num_auto = DEFAULT_NUM_AUTO;
socket_option.segment_size = DEFAULT_SEGMENT_SIZE;
socket_option.buffer_size = DEFAULT_BUFFER_SIZE;
socket_option.silent_receiver = false;
socket_option.max_delay = -1;
// For now we use the NormSession "user data" option to associate
// the session with a "socket". In the future we may add a
// dedicated NormSetSocket(NormSessionHandle session, NormSocketHandle normSocket) API
@ -445,30 +277,10 @@ bool NormSocket::Listen(UINT16 serverPort, const char* groupAddr, const char* se
{
if (OPEN != socket_state)
{
/* This wasn't a good idea (yet and maybe never)
if ((CLOSED == socket_state) && (NORM_SESSION_INVALID != norm_session))
{
// closed socekt, not in use, so re-open socket ..
NormInstanceHandle instance = NormGetInstance(norm_session);
NormSessionHandle oldSession = norm_session;
if (!Open(instance))
{
norm_session = oldSession;
perror("NormSocket::Listen() error: unable to reopen socket");
return false;
}
else
{
NormDestroySession(oldSession);
}
}
else*/
{
fprintf(stderr, "NormSocket::Listen() error: socket not open!?\n");
return false;
}
fprintf(stderr, "NormSocket::Listen() error: socket not open?!\n");
return false;
}
// The code below will be cleaned/tightened up somewhat once all is working
// THe code below will be cleaned/tightened up somewhat once all is working
// Note that port reuse here lets us manage our "client" rx-only unicast connections the
// way we need, but does allow a second multicast server to be started on this group which leads
@ -521,9 +333,9 @@ bool NormSocket::Listen(UINT16 serverPort, const char* groupAddr, const char* se
// So that the listener can construct (unsent) ACKs without failure
NormSetDefaultUnicastNack(norm_session, true);
// Note we use a _small_ buffer size here since a "listening" socket isn't
// Note we use a small buffer size here since a "listening" socket isn't
// going to be receiving data (TBD - implement a mechanism to handoff remote
// sender (i.e. "client") from parent directly?)
// sender (i.e. "client") from parent
if (!NormStartReceiver(norm_session, 2048))
{
fprintf(stderr, "NormSocket::Listen() error: NormStartReceiver() failure (perhaps port already in use)\n");
@ -580,7 +392,7 @@ NormSocket* NormSocket::Accept(NormNodeHandle client, NormInstanceHandle instanc
// However, note that even though we've "connected" this sender,
// there is a chance that additional packets in the "serverSession"
// rx socket buffer may look like a new sender if deleted now, so
// we wait for NORM_REMOTE_SENDER_INACTIVE to delete the remote sender from the listener sesssion
// we wait for NORM_REMOTE_SENDER_INACTIVE to delete
#ifndef WIN32
// Enable rx port reuse since it's the server port, and connect
@ -604,7 +416,6 @@ NormSocket* NormSocket::Accept(NormNodeHandle client, NormInstanceHandle instanc
clientSocket->remote_node = client;
clientSocket->UpdateRemoteAddress();
NormNodeSetUserData(client, clientSocket);
clientSocket->socket_option = socket_option; // inherit server_socket options (TBD - allow alt options passed into NormAccept()?)
NormNodeId clientId = NormNodeGetId(client);
@ -614,10 +425,7 @@ NormSocket* NormSocket::Accept(NormNodeHandle client, NormInstanceHandle instanc
// The clientSession is bi-directional so we need to NormStartSender(), etc
NormAddAckingNode(clientSession, 2); //clientId);
NormSetFlowControl(clientSession, 0); // disable timer-based flow control since we do explicit, ACK-based flow control
NormStartSender(clientSession, NormGetRandomSessionId(),
socket_option.buffer_size, socket_option.segment_size,
socket_option.num_data, socket_option.num_parity);
NormSetAutoParity(clientSession, socket_option.num_auto);
NormStartSender(clientSession, NormGetRandomSessionId(), 2*1024*1024, 1400, 16, 4);
}
else // if IsMulticastSocket()
{
@ -633,16 +441,14 @@ NormSocket* NormSocket::Accept(NormNodeHandle client, NormInstanceHandle instanc
if (LISTENING == socket_state)
{
NormSetFlowControl(norm_session, 0); // disable timer-based flow control since we do explicit, ACK-based flow control
NormStartSender(norm_session, NormGetRandomSessionId(),
socket_option.buffer_size, socket_option.segment_size,
socket_option.num_data, socket_option.num_parity);
NormSetAutoParity(norm_session, socket_option.num_auto);
NormStartSender(norm_session, NormGetRandomSessionId(), 2*1024*1024, 1400, 16, 4);
socket_state = CONNECTED;
if (NORM_OBJECT_INVALID == tx_stream)
{
tx_stream = NormStreamOpen(norm_session,socket_option.buffer_size);
InitTxStream(tx_stream, socket_option.buffer_size, socket_option.segment_size, socket_option.num_data);
tx_stream = NormStreamOpen(norm_session, 2*1024*1024);
InitTxStream(tx_stream, 2*1024*1024, 1400, 16);
}
}
/* The code below would be invoked for "heavyweight" mcast client admission
(for the moment we go with a "lightweight" model - this might be invokable upon
@ -673,32 +479,6 @@ bool NormSocket::Connect(const char* serverAddr,
const char* groupAddr,
NormNodeId clientId)
{
if (OPEN != socket_state)
{
/* Not a good idea (yet and maybe never)
if ((CLOSED == socket_state) && (NORM_SESSION_INVALID != norm_session))
{
// closed socekt, not in use, so re-open socket ..
NormInstanceHandle instance = NormGetInstance(norm_session);
NormSessionHandle oldSession = norm_session;
if (!Open(instance))
{
norm_session = oldSession;
perror("NormSocket::Connect() error: unable to reopen socket");
return false;
}
else
{
NormDestroySession(oldSession);
}
}
else
*/
{
fprintf(stderr, "NormSocket::Connect() error: socket not open!?\n");
return false;
}
}
// For unicast connections, the "client" manages a single NormSession for send and receive
// (For multicast connections, there are two sessions: The same unicast session that will
// be set to txOnly upon CONNECT and a separate NormSession for multicast reception)
@ -728,6 +508,7 @@ bool NormSocket::Connect(const char* serverAddr,
fprintf(stderr, "NormSocket::Connect() error: unicast NormStartReceiver() failure\n");
return false;
}
NormSetSynStatus(norm_session, true);
// Point our unicast socket at the unicast server addr/port
@ -736,12 +517,12 @@ bool NormSocket::Connect(const char* serverAddr,
//NormAddAckingNode(norm_session, 1); // servers always have NormNodeId '1' for unicast sessions
NormSetAutoAckingNodes(norm_session, NORM_TRACK_RECEIVERS); // this way we get informed upon first ACK
NormSetFlowControl(norm_session, 0); // since we do explicit, ACK-based flow control
if (!NormStartSender(norm_session, sessionId, 2*1024*1024, 1400, socket_option.num_data, socket_option.num_parity))
if (!NormStartSender(norm_session, sessionId, 2*1024*1024, 1400, 16, 4))
{
fprintf(stderr, "NormSocket::Connect() error: NormStartSender() failure\n");
return false;
}
NormSetAutoParity(norm_session, socket_option.num_auto);
if (NULL != groupAddr)
{
// Create the "mcast_session" for multicast reception
@ -779,8 +560,8 @@ bool NormSocket::Connect(const char* serverAddr,
server_socket = NULL; // this is a client-side socket
if (NORM_OBJECT_INVALID == tx_stream)
{
tx_stream = NormStreamOpen(norm_session, socket_option.buffer_size);
InitTxStream(tx_stream, socket_option.buffer_size, socket_option.segment_size, socket_option.num_data);
tx_stream = NormStreamOpen(norm_session, 2*1024*1024);
InitTxStream(tx_stream, 2*1024*1024, 1400, 16);
}
socket_state = CONNECTING;
@ -806,18 +587,13 @@ unsigned int NormSocket::Write(const char* buffer, unsigned int numBytes)
// TBD - if tx_stream not yet open, open it!!!
if (NORM_OBJECT_INVALID == tx_stream)
{
tx_stream = NormStreamOpen(norm_session, socket_option.buffer_size);
InitTxStream(tx_stream, socket_option.buffer_size, socket_option.segment_size, socket_option.num_data);
tx_stream = NormStreamOpen(norm_session, 2*1024*1024);
InitTxStream(tx_stream, 2*1024*1024, 1400, 16);
}
if (!tx_flow_control)
// This method uses NormStreamWrite(), but limits writes by explicit ACK-based flow control status
if (tx_stream_buffer_count < tx_stream_buffer_max)
{
unsigned int bytesWritten = NormStreamWrite(tx_stream, buffer, numBytes);
return bytesWritten;
}
else if (tx_stream_buffer_count < tx_stream_buffer_max)
{
// This method uses NormStreamWrite(), but limits writes by explicit ACK-based flow control status
// 1) How many buffer bytes are available?
unsigned int bytesAvailable = tx_segment_size * (tx_stream_buffer_max - tx_stream_buffer_count);
bytesAvailable -= tx_stream_bytes_remain; // unflushed segment portiomn
@ -934,11 +710,6 @@ void NormSocket::Shutdown()
}
socket_state = CLOSING;
}
else
{
// Use a zero-timeout to immediately post NORM_SOCKET_CLOSE notification
NormSetUserTimer(norm_session, 0.0);
}
} // end NormSocket::Shutdown()
void NormSocket::Close()
@ -979,30 +750,9 @@ void NormSocket::Close()
}
if (NORM_SESSION_INVALID != norm_session)
{
NormCancelUserTimer(norm_session);
NormStopSender(norm_session);
NormStopReceiver(norm_session);
}
if (NULL != socket_info)
{
if (NULL != server_socket)
server_socket->RemoveSocketInfo(*socket_info);
delete socket_info;
socket_info = NULL;
}
// Iterate through remaining socket info and disassociate from any clients remaining
NormSocketTable::Iterator iterator(client_table);
NormSocketInfo* socketInfo;
while (NULL != (socketInfo = iterator.GetNextItem()))
{
NormSocket* clientSocket = socketInfo->GetSocket();
if (NULL != clientSocket)
clientSocket->SetSocketInfo(NULL);
client_table.Remove(*socketInfo);
delete socketInfo;
}
server_socket = NULL;
remote_node = NORM_NODE_INVALID;
tx_stream = NORM_OBJECT_INVALID;
@ -1141,33 +891,8 @@ void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketE
switch (socket_state)
{
case LISTENING:
{
NormSocketInfo* socketInfo = client_table.FindSocketInfo(event.sender);
if (NULL == socketInfo)
{
// Add info for client socket pending acceptance
socketInfo = new NormSocketInfo(NormGetSocketInfo(event.sender));
if (NULL != socketInfo)
{
client_table.Insert(*socketInfo);
socketEvent.type = NORM_SOCKET_ACCEPT;
}
else
{
perror("NormSocket::GetSocketEvent() error: unable to add pending client info to server socket:\n");
}
}
else // duplicative accept event for existing socket, so ignore
{
ProtoAddress remoteAddr;
socketInfo->GetRemoteAddress(remoteAddr);
fprintf(stderr, "NormSocket::GetSocketEvent() warning: duplicative %s from client %s/%hu...\n",
(NORM_REMOTE_SENDER_NEW == event.type) ? "new" : "reset",
remoteAddr.GetHostString(), remoteAddr.GetPort());
// TBD - should we go ahead and delete this event.sender???
}
socketEvent.type = NORM_SOCKET_ACCEPT;
break;
}
case ACCEPTING:
if (IsServerSide() && IsClientSocket() && (NORM_NODE_INVALID != remote_node))
{
@ -1180,7 +905,6 @@ void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketE
socketEvent.type = NORM_SOCKET_CONNECT;
NormSetSynStatus(norm_session, false);
socket_state = CONNECTED;
// Since UDP connect/bind doesn't really work properly on
// Windows, the Windows NormSocket server farms out client connections
// to new ephemeral port numbers, so we need to update
@ -1188,11 +912,12 @@ void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketE
remote_node = event.sender;
UpdateRemoteAddress();
NormChangeDestination(norm_session, NULL, remote_port);
if ((NORM_OBJECT_INVALID == tx_stream) && !(IsMulticastClient() && IsServerSide()))
if (NORM_OBJECT_INVALID == tx_stream)
{
tx_stream = NormStreamOpen(norm_session, socket_option.buffer_size);
InitTxStream(tx_stream, socket_option.buffer_size, socket_option.segment_size, socket_option.num_data);
tx_stream = NormStreamOpen(norm_session, 2*1024*1024);
InitTxStream(tx_stream, 2*1024*1024, 1400, 16);
}
break;
case CONNECTED:
if (IsMulticastSocket())
@ -1200,31 +925,7 @@ void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketE
if (IsServerSocket())
{
// New client showing up at our multicast party
NormSocketInfo* socketInfo = client_table.FindSocketInfo(event.sender);
if (NULL == socketInfo)
{
// Add info for client socket pending acceptance
socketInfo = new NormSocketInfo(NormGetSocketInfo(event.sender));
if (NULL != socketInfo)
{
client_table.Insert(*socketInfo);
socketEvent.type = NORM_SOCKET_ACCEPT;
}
else
{
perror("NormSocket::GetSocketEvent() error: unable to add pending client info to server socket:\n");
}
}
else // duplicative accept event for existing socket, so ignore
{
ProtoAddress remoteAddr;
socketInfo->GetRemoteAddress(remoteAddr);
fprintf(stderr, "NormSocket::GetSocketEvent() warning: duplicative %s from client %s/%hu...\n",
(NORM_REMOTE_SENDER_NEW == event.type) ? "new" : "reset",
remoteAddr.GetHostString(), remoteAddr.GetPort());
// TBD - should we go ahead and delete this event.sender???
}
socketEvent.type = NORM_SOCKET_ACCEPT;
}
else
{
@ -1282,7 +983,6 @@ void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketE
case NORM_SEND_ERROR:
{
TRACE("NormSocket got SEND ERROR\n");
switch (socket_state)
{
case CONNECTING:
@ -1524,44 +1224,10 @@ NormSocketHandle NormAccept(NormSocketHandle serverSocket, NormNodeHandle client
NormSuspendInstance(serverInstance);
NormSocketHandle clientSocket = s->Accept(client, instance);
NormResumeInstance(serverInstance);
if (NORM_SOCKET_INVALID != clientSocket)
{
// Keep track of this client socket in our serverSocket socket_table
NormSocketInfo* socketInfo = s->FindSocketInfo(client);
ASSERT(NULL != socketInfo);
NormSocket* c = (NormSocket*)clientSocket;
socketInfo->SetSocket(c);
c->SetSocketInfo(socketInfo);
}
return clientSocket;
} // end NormAccept()
NORM_API_LINKAGE
extern bool NormSendCommandTo(NormSessionHandle sessionHandle,
const char* cmdBuffer,
unsigned int cmdLength,
const char* addr,
UINT16 port);
void NormReject(NormSocketHandle serverSocket,
NormNodeHandle clientNode)
{
// Simple, single "reject" command for moment (TBD - do something more stateful so app will be bothered less)
// Send "reject" command to source
char buffer[2];
buffer[0] = NORM_SOCKET_VERSION;
buffer[1] = NORM_SOCKET_CMD_REJECT;
NormSocket* s = (NormSocket*)serverSocket;
NormSocketInfo socketInfo = NormGetSocketInfo(clientNode);
ProtoAddress dest;
socketInfo.GetRemoteAddress(dest);
char destString[64];
destString[63] = '\0';
dest.GetHostString(destString, 63);
NormSendCommandTo(s->GetSession(), buffer, 2,destString, dest.GetPort());
} // end NormReject()
// TBD - provide options for binding to a specific local address, interface, etc
bool NormConnect(NormSocketHandle normSocket, const char* serverAddr, UINT16 serverPort, UINT16 localPort, const char* groupAddr, NormNodeId clientId)
{
@ -1582,7 +1248,7 @@ ssize_t NormWrite(NormSocketHandle normSocket, const void *buf, size_t nbyte)
NormSocket* s = (NormSocket*)normSocket;
NormInstanceHandle instance = s->GetInstance();
NormSuspendInstance(instance);
ssize_t result = (ssize_t)s->Write((const char*)buf, (unsigned int)nbyte);
ssize_t result = (ssize_t)s->Write((const char*)buf, nbyte);
NormResumeInstance(instance);
return result;
} // end NormWrite()
@ -1605,7 +1271,7 @@ ssize_t NormRead(NormSocketHandle normSocket, void *buf, size_t nbyte)
NormInstanceHandle instance = s->GetInstance();
NormSuspendInstance(instance);
// TBD - make sure s->rx_stream is valid
unsigned int numBytes = (unsigned int)nbyte;
unsigned int numBytes = nbyte;
ssize_t result;
if (s->Read((char*)buf, numBytes))
result = numBytes;
@ -1634,19 +1300,6 @@ void NormClose(NormSocketHandle normSocket)
delete s;
} // end NormClose()
void NormGetSocketOptions(NormSocketHandle normSocket, NormSocketOptions* options)
{
NormSocket* s = (NormSocket*)normSocket;
s->GetOptions(options);
} // end NormGetSocketOptions()
bool NormSetSocketOptions(NormSocketHandle normSocket, NormSocketOptions* options)
{
// TBD - do some validity checking, perhaps reset to defaults if (options == NULL)
NormSocket* s = (NormSocket*)normSocket;
return s->SetOptions(options);
} // end NormSetSocketOptions()
void NormSetSocketUserData(NormSocketHandle normSocket, const void* userData)
{
if (NORM_SOCKET_INVALID != normSocket)
@ -1705,32 +1358,15 @@ NormSessionHandle NormGetSocketSession(NormSocketHandle normSocket)
return s->GetSession();
} // end NormGetSocketSession()
NormObjectHandle NormGetSocketTxStream(NormSocketHandle normSocket)
{
NormSocket* s = (NormSocket*)normSocket;
return s->GetTxStream();
} // end NormGetSocketTxStream()
NormObjectHandle NormGetSocketRxStream(NormSocketHandle normSocket)
{
NormSocket* s = (NormSocket*)normSocket;
return s->GetRxStream();
} // end NormGetSocketRxStream()
NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket)
{
NormSocket* s = (NormSocket*)normSocket;
return s->GetMulticastSession();
} // end NormGetSocketMulticastSession()
void NormSetSocketTrace(NormSocketHandle normSocket, bool enable)
{
NormSocket* s = (NormSocket*)normSocket;
s->SetTrace(enable);
} // end NormSetSocketTrace()
void NormSetSocketFlowControl(NormSocketHandle normSocket, bool enable)
{
NormSocket* s = (NormSocket*)normSocket;
s->SetFlowControl(enable);
} // end NormSetSocketFlowControl()
}

68
examples/normSocket.h Executable file → Normal file
View File

@ -63,24 +63,21 @@ extern const double NORM_DEFAULT_CONNECT_TIMEOUT;
NormSocketHandle NormOpen(NormInstanceHandle instance);
bool NormListen(NormSocketHandle normSocket,
UINT16 serverPort,
bool NormListen(NormSocketHandle normSocket,
UINT16 serverPort,
const char* groupAddr = NULL,
const char* serverAddr = NULL);
const char* serverAddr = NULL);
bool NormConnect(NormSocketHandle normSocket,
const char* serverAddr,
UINT16 serverPort,
bool NormConnect(NormSocketHandle normSocket,
const char* serverAddr,
UINT16 serverPort,
UINT16 localPort = 0,
const char* groupAddr = NULL,
NormNodeId clientId = NORM_NODE_ANY);
NormSocketHandle NormAccept(NormSocketHandle serverSocket,
NormNodeHandle clientNode,
NormSocketHandle NormAccept(NormSocketHandle serverSocket,
NormNodeHandle clientNode,
NormInstanceHandle instance = NORM_INSTANCE_INVALID);
void NormReject(NormSocketHandle serverSocket,
NormNodeHandle clientNode);
void NormShutdown(NormSocketHandle normSocket);
@ -92,30 +89,6 @@ ssize_t NormWrite(NormSocketHandle normSocket, const void* buf, size_t nbyte);
int NormFlush(NormSocketHandle normSocket);
/*
// These calls _will_ be used for file/data object and message-stream delivery. (Sketching the calls out for now)
NormObject NormSendFile(NormSocketHandle normSocket,
const char* filePath,
const char* infoPtr,
ssize_t infoLen);
NormObject NormSendData(NormSocketHandle normSocket,
const char* data, // NormSocket will copy the "data" unlike NORM low-level API
ssize_t nbyte,
const char* infoPtr,
ssize_t infoLen);
// Notification events will indicate receipt of file/data objects. Are additional NormSocket API calls
// needed to manage receipt?
ssize_t NormSendMsg(NormSocketHandle normSocket, const char* data, ssize_t nbyte, bool flush);
ssize_t NormRecvMsg(NormSocketHandle normSocket, const char* data, ssize_t nbyte);
*/
// NormSocket helper functions
void NormSetSocketUserData(NormSocketHandle normSocket, const void* userData);
@ -125,10 +98,7 @@ NormInstanceHandle NormGetSocketInstance(NormSocketHandle normSocket);
NormSessionHandle NormGetSocketSession(NormSocketHandle normSocket);
NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket);
void NormGetPeerName(NormSocketHandle normSocket, char* addr, unsigned int* addrLen, UINT16* port);
NormObjectHandle NormGetSocketTxStream(NormSocketHandle normSocket);
NormObjectHandle NormGetSocketRxStream(NormSocketHandle normSocket);
void NormSetSocketFlowControl(NormSocketHandle normSocket, bool enable);
void NormSetSocketTrace(NormSocketHandle normSocket, bool enable);
typedef enum NormSocketEventType
@ -141,28 +111,7 @@ typedef enum NormSocketEventType
NORM_SOCKET_CLOSING, // indicates remote endpoint is closing socket (only read data at this point)
NORM_SOCKET_CLOSE // indicates socket is now closed (invalid for further operations)
} NormSocketEventType;
// Right now, these options MUST be set _after_ NormOpen()
// but _before_ NormConnect() or NormListen()
// (This will be expanded, perhaps to include parameters
// that can be changed after connection setup)
typedef struct
{
UINT16 num_data;
UINT16 num_parity;
UINT16 num_auto;
UINT16 segment_size;
unsigned int buffer_size; // used for both FEC and stream buffer sizing
bool silent_receiver; // not yet used (maybe should be nack_mode instead)
int max_delay; // not yet used
} NormSocketOptions;
void NormGetSocketOptions(NormSocketHandle normSocket, NormSocketOptions* options);
bool NormSetSocketOptions(NormSocketHandle normSocket, NormSocketOptions* options);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
typedef struct
{
NormSocketEventType type;
@ -182,7 +131,6 @@ typedef struct
};
};
} NormSocketEvent;
#pragma GCC diagnostic pop
bool NormGetSocketEvent(NormInstanceHandle normInstance, NormSocketEvent* event, bool waitForEvent = true);

0
examples/normSocketNotes.txt Executable file → Normal file
View File

2
examples/normStreamRecv.cpp Executable file → Normal file
View File

@ -48,7 +48,7 @@ int main(int argc, char* argv[])
// NOTE: These are debugging routines available
// (not necessary for normal app use)
// (Need to include "common/protoDebug.h" for this
// (Need to include "protolib/common/protoDebug.h" for this
NormSetDebugLevel(3);
// Uncomment to turn on debug NORM message tracing
NormSetMessageTrace(session, true);

0
examples/normStreamSend.cpp Executable file → Normal file
View File

713
examples/normStreamer.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ def main(argv):
(opts, args) = get_option_parser().parse_args(argv)
if len(args) != 1:
print(USAGE)
print USAGE
return 1
pipep = PipeParser(opts.pipe)
@ -53,7 +53,7 @@ def main(argv):
except IndexError:
continue
pipep.reports.task_done()
print("Exiting...")
print "Exiting..."
# g.reset()
# g.close()
# del g

View File

@ -1,425 +0,0 @@
'''
LD_LIBRARY_PATH=/home/honglei/norm_test/
'''
# sender/Win10:
#--id 34252 --send "C:\Users\Admin\AppData\Roaming\Wing Pro 9" --repeat 1 --addr 224.1.2.4/6003 --txaddr 10.65.39.191/8002 --cc rate 5000 --ack auto --grttprobing active --debug 4
# receiver/Debian10
#--id 172042016 --recv "~/recvFiles" --addr 224.1.2.4/6003 --interface ens33 --unicast_nack --debug 4
import sys
import os
if os.name =='nt':
os.add_dll_directory(os.path.dirname(__file__))
import argparse
import traceback
import logging
from typing import Optional
import enum
class CCEnum(enum.Enum):
CC = "cc"
CCE = "cce"
CCL = "ccl"
Fixed = "rate"
class FlushEnum(enum.Enum):
none='none'
passive='passive'
active='active'
class GrttEnum(enum.Enum):
none='none'
passive='passive'
active='active'
class EnumAction(argparse.Action):
"""
Argparse action for handling Enums
from https://stackoverflow.com/questions/43968006/support-for-enum-arguments-in-argparse
"""
def __init__(self, **kwargs):
# Pop off the type value
enum_type = kwargs.pop("type", None)
# Ensure an Enum subclass is provided
if enum_type is None:
raise ValueError("type must be assigned an Enum when using EnumAction")
if not issubclass(enum_type, enum.Enum):
raise TypeError("type must be an Enum when using EnumAction")
# Generate choices from the Enum
#kwargs.setdefault("choices", tuple(e.value for e in enum_type)) #if e!=CCEnum.rate else "rate <bitsPerSecond>"
super(EnumAction, self).__init__(**kwargs)
self._enum = enum_type
def __call__(self, parser, namespace, values:list|str, option_string=None):
# Convert value back into an Enum
if isinstance(values,list):
if len(values) ==2:
value = int(values[1])
elif len(values) ==1:
value = self._enum( values[0].lower())
else:
value = self._enum(values.lower() )
setattr(namespace, self.dest, value)
'''
norm.cpp:
fprintf(stderr, "Usage: normCast {send <file/dir list> &| recv <rxCacheDir>} [silent {on|off}]\n"
" [repeat <interval> [updatesOnly]] [id <nodeIdInteger>]\n"
" [addr <addr>[/<port>]][txaddr <addr>[/<port>]][txport <port>]\n"
" [interface <name>][reuse][loopback]\n"
" [ack auto|<node1>[,<node2>,...]] [segment <bytes>]\n"
" [block <count>] [parity <count>] [auto <count>]\n"
" [cc|cce|ccl|rate <bitsPerSecond>] [rxloss <lossFraction>]\n"
" [txloss <lossFraction>] [flush {none|passive|active}]\n"
" [grttprobing {none|passive|active}] [grtt <secs>]\n"
" [ptos <value>] [processor <processorCmdLine>] [saveaborts]\n"
" [sentprocessor <processorCmdLine>]\n"
" [purgeprocessor <processorCmdLine>] [buffer <bytes>]\n"
" [txsockbuffer <bytes>] [rxsockbuffer <bytes>]\n"
" [debug <level>] [trace] [log <logfile>]\n");
'''
# Instantiate the parser
def get_arg_options():
parser = argparse.ArgumentParser(description='Optional app description')
## Required positional argument
parser.add_argument('--id', type=int, required=True,
help='id <nodeIdInteger>')
parser.add_argument('--send', '-S',nargs='+',
help='send <file/dir list>')
parser.add_argument('--recv', '-R',
help='recv <rxCacheDir>')
parser.add_argument('--repeat','-r', type=int, default=60,
help='[repeat <interval> [updatesOnly]]')
parser.add_argument('--interface', '-i',
help='addr <addr>[/<port>]')
parser.add_argument('--addr', '-a',
help='addr <addr>[/<port>]')
parser.add_argument('--txaddr', '-t',
help='txaddr <addr>[/<port>]')
parser.add_argument('--txport', type=int,
help='txport <port>')
parser.add_argument('--ack', nargs='+', #nargs='?',
help='ack auto|<node1>[,<node2>,...')
#To create an option that needs no value, set the action [docs] of it to 'store_const', 'store_true' or 'store_false'
parser.add_argument('--loopback', action='store_true',help='')
parser.add_argument('--segment', type=int,
help='segment <bytes>')
parser.add_argument('--block', type=int,
help='[block <count>] ')
parser.add_argument('--parity', type=int,
help='[parity <count>]')
parser.add_argument('--auto', type=int,
help='[auto <count>]')
parser.add_argument('--grttprobing', type=GrttEnum, action=EnumAction,
help='[grttprobing {none|passive|active}]')
parser.add_argument('--grtt', type=int, help='[grtt <secs>]')
parser.add_argument('--ptos', type=int,
help='[ptos <value>]')
parser.add_argument('--flush', type=FlushEnum, action=EnumAction,
help='[flush {none|passive|active}]')
parser.add_argument('--silent', action='store_true',help='')
parser.add_argument('--unicast_nack', action='store_true', help='')
parser.add_argument('--txloss', type=float, help='[txloss <lossFraction>]')
parser.add_argument('--rxloss', type=float, help='[rxloss <lossFraction>]')
parser.add_argument('--buffer', type=int, help='[buffer <bytes>]')
parser.add_argument('--txsockbuffer', type=int, help=' [txsockbuffer <bytes>]')
parser.add_argument('--rxsockbuffer', type=int, help='[rxsockbuffer <bytes>]')
parser.add_argument('--debug', type=int, help='[debug <level>]')
parser.add_argument('--cc',type=CCEnum, nargs='+', action=EnumAction,
help='[cc|cce|ccl|rate <bitsPerSecond>] '
)
args = parser.parse_args()
return args
import pynorm
def create_session(instance:pynorm.Instance, opts:argparse.Namespace):
'''
use opts to create a NORM session
'''
sessionAddr ='224.1.2.3'
sessionPort = 6003
if opts.addr:
args = opts.addr.split('/')
if len(args) >0:
sessionAddr = args[0]
if len(args) ==2:
sessionPort = int(args[1])
session = instance.createSession(sessionAddr, sessionPort, localId=opts.id)
sessionTxAddr:str = None
sessionTxPort = 8002
if opts.txaddr:
args = opts.txaddr.split('/')
if len(args) >0:
sessionTxAddr = args[0]
if len(args) ==2:
sessionTxPort = int(args[1])
if sessionTxAddr:
session.setTxPort(txPort=sessionTxPort, txBindAddr=sessionTxAddr)
if opts.interface:
session.setMulticastInterface(opts.interface)
if opts.loopback:
session.setLoopback(loopbackEnable=True)
if opts.silent:
session.setSilentReceiver(True)
if opts.unicast_nack:
session.setDefaultUnicastNack(enable=True)
autoAck:bool = False
ackingNodeList:list[int] =[]
if opts.ack:
if 'auto' == opts.ack[0]:
autoAck = True
session.setAutoAckingNodes(pynorm.TrackingStatus.RECEIVERS)
else:
ackingNodeList = [ int(i) for i in opts.ack]
for ackingNondeID in ackingNodeList:
session.addAckingNode(ackingNondeID)
if opts.txloss and opts.txloss>0:
session.setTxLoss(opts.txloss)
if opts.rxloss and opts.rxloss>0:
session.setRxLoss(opts.rxloss)
# Congestion Control
if opts.cc:
if isinstance(opts.cc,int):
session.setTxRate(opts.cc)
session.setEcnSupport(ecnEnable=False)
else:
if opts.cc == CCEnum.CC: # default TCP-friendly congestion control
session.setEcnSupport(ecnEnable=False)
elif opts.cc == CCEnum.CCE: #"wireless-ready" ECN-only congestion control
session.setEcnSupport(ecnEnable=True, ignoreLoss=True)
elif opts.cc == CCEnum.CCL: # "loss tolerant", non-ECN congestion control
session.setEcnSupport(ecnEnable=False, ignoreLoss=False, tolerateLoss=True)
defaultBufferSpace = 64*1024*1024
defaultTxSocketBufferSize = 4*1024*1024
defaultRxSocketBufferSize = 6*1024*1024
bufferSpace = opts.buffer if opts.buffer else defaultBufferSpace
if opts.send:
if opts.ack:
session.setFlowControl(flowControlFactor=0) #// ack-based flow control enabled on command-line, so disable timer-based flow control
session.setBackoffFactor(0)
#FEC
session.startSender(sessionId=opts.id,
bufferSpace=bufferSpace,
segmentSize=opts.segment if opts.segment else 1400,
blockSize=opts.block if opts.block else 64,
numParity=opts.parity if opts.parity else 0,
fecId=0)
if opts.auto:
session.setAutoParity(opts.auto)
session.setTxSocketBuffer(opts.txsockbuffer if opts.txsockbuffer else defaultTxSocketBufferSize )
if opts.recv:
session.startReceiver(bufferSpace=bufferSpace)
session.setRxSocketBuffer(opts.rxsockbuffer if opts.rxsockbuffer else defaultRxSocketBufferSize )
if opts.grttprobing:
session.setGrttProbingMode(pynorm.ProbingMode[ opts.grttprobing.value.upper() ] )
return session
from pynorm import EventType
from typing import Iterable
def listFiles( dirFileList:list[str]) -> Iterable[str]:
for dirFile in dirFileList:
if os.path.isfile(dirFile):
yield dirFile
elif os.path.isdir(dirFile):
for filename in os.scandir(dirFile):
if filename.is_file():
yield filename.path
else:
raise FileExistsError(f"{dirFile} is not a valid file/dir")
import logging
import ipaddress
class NormCaster():
def __init__(self,instance:pynorm.Instance, opts:argparse.Namespace ):
self.opts:argparse.Namespace = opts
self.recvDir:Optional[str] = os.path.expanduser(opts.recv) if opts.recv else None
self.instance:pynorm.Instance = instance
self.session:pynorm.Session = create_session(instance, opts)
self.fileIterator:Iterable[str] = listFiles(opts.send)
self.is_running:bool = True
self.pendingSendFilePath:Optional[str] = None #
def addOneFile(self,session):
'''
'''
if self.pendingSendFilePath is None:
try:
self.pendingSendFilePath:str = self.fileIterator.__next__()
except StopIteration:
self.is_running = False
return
lastSlash = self.pendingSendFilePath.rfind('/')
filename = self.pendingSendFilePath[lastSlash+1:]
obj:Optional[pynorm.Object] = session.fileEnqueue(self.pendingSendFilePath, info= filename.encode() )
if obj:
if self.opts.ack:
session.setWatermark(obj,True)
logging.info(f"add file:{self.pendingSendFilePath} {obj._object}")
self.pendingSendFilePath = None # succeed enqued
else:
logging.warning(f"fileEnqueue: {self.pendingSendFilePath} failure!")
def handle_norm_event(self, event:pynorm.Event):
session:pynorm.Session = event.session
evtType:pynorm.EventType = event.type
logging.info(evtType )
if evtType in (EventType.TX_QUEUE_EMPTY, EventType.TX_QUEUE_VACANCY):
self.addOneFile(session)
elif evtType == EventType.GRTT_UPDATED:
pass
elif evtType == EventType.TX_WATERMARK_COMPLETED:
if pynorm.AckingStatus.SUCCESS == session.getAckingStatus():
logging.warning( "normCast: NORM_TX_WATERMARK_COMPLETED, NORM_ACK_SUCCESS");
self.addOneFile(session)
else:
logging.warning( "normCast: NORM_TX_WATERMARK_COMPLETED, _NOT_ NORM_ACK_SUCCESS");
obj = event.object
if obj is None:
session.resetWatermark()
elif evtType == EventType.TX_FLUSH_COMPLETED:
pass
elif evtType == EventType.TX_OBJECT_PURGED:
obj = event.object
if obj and obj.type== pynorm.ObjectType.FILE:
logging.info(f"normCast: send file purged: {obj.info.decode()}")
elif evtType == EventType.TX_OBJECT_SENT:
obj = event.object
if obj and obj.type== pynorm.ObjectType.FILE:
logging.info(f"initial send complete: {obj.info.decode()}")
self.addOneFile(session)
elif evtType == EventType.ACKING_NODE_NEW:
sender = event.sender
logging.info(f"normCast: new acking node: {sender.id} IP address{sender.address}")
elif evtType == EventType.REMOTE_SENDER_INACTIVE:
pass
elif evtType == EventType.RX_OBJECT_ABORTED:
obj = event.object
if obj and obj.type is not pynorm.ObjectType.FILE:
logging.error("normCast: received invalid object type?!")
return
filePath = event.object.filename
event.object.cancel()
#remove temparary file if recv aborted.
os.remove(filePath)
logging.info("")
elif evtType == EventType.RX_OBJECT_INFO:
pass
elif evtType == EventType.RX_OBJECT_COMPLETED:
obj = event.object
if obj and obj.type is not pynorm.ObjectType.FILE:
logging.error("normCast: received invalid object type?!")
return
file_path = event.object.info.decode()
fileName = os.path.split(file_path)[-1]
path = os.path.join( self.recvDir, fileName )
oldPath = event.object.filename
logging.debug (f"{oldPath=}")
try:
if os.path.isfile(path):
os.remove(path)
os.rename(src=oldPath, dst=path)
except Exception as e:
logging.error ( traceback.format_exc() )
def getAckNodesStatus(self,session):
isSuccess, nodeID, nodeAckStatus = session.getNextAckingNode()
while isSuccess:
ip=ipaddress.IPv4Address(nodeID)
if pynorm.AckingStatus.SUCCESS == nodeAckStatus:
logging.info( f"normCast: node {nodeID} (IP address: {str(ip)}) acnkowledged.")
else:
logging.info( f"normCast: node {nodeID} (IP address: {str(ip)}) failed to acnkowledge.")
isSuccess, nodeID, nodeAckStatus = session.getNextAckingNode()
def run(self):
while self.is_running:
event: Optional[pynorm.Event,bool,None] = self.instance.getNextEvent(timeout=self.opts.repeat)
while event:
self.handle_norm_event(event)
event = self.instance.getNextEvent(timeout=self.opts.repeat)
if event is None and self.opts.send:
self.addOneFile(self.session) # means timeout
logging.warning("normCast exits!")
def main(argv):
opts:argparse.Namespace = get_arg_options()
instance = pynorm.Instance()
if opts.debug:
instance.setDebugLevel(level=pynorm.DebugLevel(opts.debug) )
if opts.recv:
recvPath:str = os.path.expanduser( opts.recv )
if not os.path.isdir(recvPath): #create is not exists!
os.makedirs( recvPath )
instance.setCacheDirectory( recvPath )
normCast:NormCaster = NormCaster(instance, opts)
if opts.send:
normCast.addOneFile(normCast.session)
normCast.run()
if __name__ == '__main__':
logging.getLogger().setLevel(logging.INFO)
sys.exit(main(sys.argv))

View File

@ -28,7 +28,7 @@ def main(argv):
(opts, args) = get_option_parser().parse_args(argv)
if len(args) != 2:
print(get_option_parser().get_usage())
print get_option_parser().get_usage()
return 1
path = os.path.abspath(args[1])
@ -45,26 +45,26 @@ def main(argv):
for event in instance:
if event == 'NORM_RX_OBJECT_INFO':
event.object.filename = os.path.join(path, event.object.info)
print('Downloading file %s' % event.object.filename)
print 'Downloading file %s' % event.object.filename
elif event == 'NORM_RX_OBJECT_UPDATED':
print('File %s - %i bytes left to download' % (
event.object.filename, event.object.bytesPending))
print 'File %s - %i bytes left to download' % (
event.object.filename, event.object.bytesPending)
elif event == 'NORM_RX_OBJECT_COMPLETED':
print('File %s completed' % event.object.filename)
print 'File %s completed' % event.object.filename
return 0
elif event == 'NORM_RX_OBJECT_ABORTED':
print('File %s aborted' % event.object.filename)
print 'File %s aborted' % event.object.filename
return 1
else:
print(event)
print event
except KeyboardInterrupt:
pass
print('Exiting.')
print 'Exiting.'
return 0
if __name__ == '__main__':

View File

@ -10,7 +10,7 @@ from random import randint
import pynorm
USAGE = 'usage: %s [options] <file>' % sys.argv[0]
DEFAULT_ADDR = u'224.1.2.3'
DEFAULT_ADDR = '224.1.2.3'
DEFAULT_PORT = 6003
def get_option_parser():
@ -29,7 +29,7 @@ def main(argv):
(opts, args) = get_option_parser().parse_args(argv)
if len(args) != 2:
print(get_option_parser().get_usage())
print get_option_parser().get_usage()
return 1
filepath = os.path.abspath(args[1])
@ -40,23 +40,23 @@ def main(argv):
session = instance.createSession(opts.address, opts.port)
if opts.iface:
session.setMulticastInterface(opts.iface)
session.setTxRate(1.0e+06)
session.setTxRate(256e10)
session.startSender(randint(0, 1000), 1024**2, 1400, 64, 16)
print(('Sending file %s' % filename))
session.fileEnqueue(filepath, info=filename.encode())
print 'Sending file %s' % filename
session.fileEnqueue(filepath, filename)
try:
for event in instance:
print(event)
if str(event) == 'NORM_TX_FLUSH_COMPLETED':
print('Flush completed, exiting.')
if event == 'NORM_TX_FLUSH_COMPLETED':
print 'Flush completed, exiting.'
return 0
else:
print event
except KeyboardInterrupt:
pass
print('Exiting.')
print 'Exiting.'
return 0
# end main

46
examples/python/normMsgr.py Executable file → Normal file
View File

@ -14,19 +14,19 @@ class InputThread(Thread):
def __init__(self, parent, *args, **kwargs):
super(InputThread, self).__init__(*args, **kwargs)
self.daemon = True
self.setDaemon(True) ;# this is "child" daemon thread
self.msgr = parent
def run(self):
while True:
try:
msgHdr = sys.stdin.buffer.read(MSG_HDR_SIZE)
msgHdr = bytearray(sys.stdin.read(MSG_HDR_SIZE))
except:
sys.stderr.write("normMsgr: input thread end-of-file 1 ...\n")
return
try:
msgSize = 256*int(msgHdr[0]) + int(msgHdr[1])
msgBuffer = sys.stdin.buffer.read(msgSize - 2)
msgBuffer = sys.stdin.read(msgSize - 2)
except:
sys.stderr.write("normMsgr: input thread end-of-file 2 ...\n")
return
@ -37,7 +37,7 @@ class OutputThread(Thread):
def __init__(self, parent, *args, **kwargs):
super(OutputThread, self).__init__(*args, **kwargs)
self.daemon = True
self.setDaemon(True) ;# this is "child" daemon thread
self.msgr = parent
def run(self):
@ -47,15 +47,11 @@ class OutputThread(Thread):
msgHeader = bytearray(MSG_HDR_SIZE)
msgHeader[0] = (msgLen >> 8) & 0x00ff
msgHeader[1] = msgLen & 0x00ff
try:
sys.stdout.buffer.write(msgHeader)
sys.stdout.buffer.write(msg)
sys.stdout.flush()
except:
sys.stderr.write("normMsgr: output thread exiting ...\n")
return
sys.stdout.write(msgHeader)
sys.stdout.write(msg)
del msg
class NormMsgr:
"""This class keeps state for NORM tx/rx operations"""
@ -82,12 +78,10 @@ class NormMsgr:
# Create a NormSession and set some default parameters
self.normSession = self.normInstance.createSession(addr, port, nodeId)
self.normSession.setRxCacheLimit(2*self.norm_tx_queue_max) ;# we let the receiver track some extra objects
self.normSession.setDefaultSyncPolicy(pynorm.SyncPolicy.ALL);
self.normSession.setDefaultSyncPolicy(pynorm.NORM_SYNC_ALL);
self.normSession.setDefaultUnicastNack(True);
self.normSession.setTxCacheBounds(10*1024*1024, self.norm_tx_queue_max, self.norm_tx_queue_max);
self.normSession.setCongestionControl(True, True);
self.normSession.setRxPortReuse(True)
self.normSession.setMulticastLoopback(True)
return self.normSession
def addAckingNode(self, nodeId):
@ -209,7 +203,7 @@ class NormMsgr:
def onNormRxObjectCompleted(self, obj):
with self.normRxLock:
if pynorm.ObjectType.DATA == obj.getType():
if pynorm.NORM_OBJECT_DATA == obj.getType():
if 0 != len(self.output_msg_queue):
wasEmpty = False
else:
@ -239,8 +233,7 @@ class NormEventHandler(Thread):
def __init__(self, parentMsgr, *args, **kwargs):
super(NormEventHandler, self).__init__(*args, **kwargs)
#self.setDaemon(True) ;# this is "child" daemon thread (setDaemon is deprecated)
self.daemon = True
self.setDaemon(True) ;# this is "child" daemon thread
self.lock = Lock()
self.msgr = parentMsgr
@ -255,12 +248,12 @@ class NormEventHandler(Thread):
return
if event is None:
break
if pynorm.EventType.EVENT_INVALID == event.type:
if pynorm.NORM_EVENT_INVALID == event.type:
continue
elif pynorm.EventType.TX_QUEUE_EMPTY == event.type or pynorm.EventType.TX_QUEUE_VACANCY == event.type:
elif pynorm.NORM_TX_QUEUE_EMPTY == event.type or pynorm.NORM_TX_QUEUE_VACANCY == event.type:
msgr.onNormTxQueueVacancy()
elif pynorm.EventType.TX_WATERMARK_COMPLETED == event.type:
if pynorm.EventType.ACK_SUCCESS == event.session.getAckingStatus():
elif pynorm.NORM_TX_WATERMARK_COMPLETED == event.type:
if pynorm.NORM_ACK_SUCCESS == event.session.getAckingStatus():
# All receivers acknowledged
msgr.onNormTxWatermarkCompleted()
else:
@ -268,12 +261,12 @@ class NormEventHandler(Thread):
# from our acking list. For now, we are infinitely
# persistent by resetting watermark ack request
event.session.resetWatermark()
elif pynorm.EventType.TX_OBJECT_PURGED == event.type:
elif pynorm.NORM_TX_OBJECT_PURGED == event.type:
msgr.onNormTxObjectPurged(event.object)
elif pynorm.EventType.RX_OBJECT_COMPLETED == event.type:
elif pynorm.NORM_RX_OBJECT_COMPLETED == event.type:
msgr.onNormRxObjectCompleted(event.object)
#else:
#sys.stderr.write("normMsgr: NormEventHandler warning: unhandled event: %s\n" % pynorm.EventType(event.type))
# sys.stderr.write("normMsgr: NormEventHandler warning: unhandled event: %s\n" % str(event))
sys.stderr.write("normMsgr: NormEventHandler thread exiting ...\n");
self.lock.release()
@ -400,9 +393,4 @@ except KeyboardInterrupt:
#sys.stderr.write("exception while waiting on input thread ..\n");
pass
# TBD - shut the NormEventHandler thread down in a graceful way
if send:
inputThread.join()
if recv:
outputThread.join()
sys.stderr.write("normMsgr: Done.\n")

0
examples/win32InputHandler.cpp Executable file → Normal file
View File

4
examples/wintest.cpp Executable file → Normal file
View File

@ -39,7 +39,7 @@ int main(int argc, char** argv)
Win32InputHandler inputHandler;
inputHandler.Open();
inputHandler.Start();
while (true)
{
@ -51,7 +51,7 @@ int main(int argc, char** argv)
DWORD dwWritten;
BOOL fSuccess = WriteFile(hStdout, buffer, numBytes, &dwWritten, NULL);
}
inputHandler.Close();
inputHandler.Stop();
return 0;
} // end main()

0
include/galois.h Executable file → Normal file
View File

363
include/normApi.h Executable file → Normal file
View File

@ -52,10 +52,10 @@ typedef uint32_t UINT32;
// is removed, the API shouldn't be considered final.
#ifndef __cplusplus
#include <stdbool.h>
#define DEFAULT(arg)
# include <stdbool.h>
# define DEFAULT(arg)
#else
#define DEFAULT(arg) = arg
# define DEFAULT(arg) = arg
#endif
#ifdef __cplusplus
@ -64,7 +64,7 @@ extern "C" {
#define NORM_VERSION_MAJOR 1
#define NORM_VERSION_MINOR 5
#define NORM_VERSION_PATCH 10
#define NORM_VERSION_PATCH 7
/** NORM API Types */
typedef const void* NormInstanceHandle;
@ -77,7 +77,7 @@ const NormSessionHandle NORM_SESSION_INVALID;
typedef UINT16 NormSessionId;
typedef const void* NormNodeHandle;
extern NORM_API_LINKAGE
extern NORM_API_LINKAGE
const NormNodeHandle NORM_NODE_INVALID;
typedef UINT32 NormNodeId;
extern NORM_API_LINKAGE
@ -96,65 +96,74 @@ typedef __int64 NormSize;
typedef off_t NormSize;
#endif // WIN32
NORM_API_LINKAGE
typedef enum NormObjectType
{
NORM_OBJECT_NONE,
NORM_OBJECT_DATA,
NORM_OBJECT_FILE,
NORM_OBJECT_STREAM
} NORM_API_LINKAGE NormObjectType;
NORM_OBJECT_STREAM
} NormObjectType;
NORM_API_LINKAGE
typedef enum NormFlushMode
{
NORM_FLUSH_NONE,
NORM_FLUSH_PASSIVE,
NORM_FLUSH_ACTIVE
} NORM_API_LINKAGE NormFlushMode;
NORM_FLUSH_ACTIVE
} NormFlushMode;
NORM_API_LINKAGE
typedef enum NormNackingMode
{
NORM_NACK_NONE,
NORM_NACK_INFO_ONLY,
NORM_NACK_NORMAL
} NORM_API_LINKAGE NormNackingMode;
NORM_NACK_NORMAL
} NormNackingMode;
NORM_API_LINKAGE
typedef enum NormAckingStatus
{
NORM_ACK_INVALID,
NORM_ACK_FAILURE,
NORM_ACK_PENDING,
NORM_ACK_SUCCESS
} NORM_API_LINKAGE NormAckingStatus;
NORM_ACK_SUCCESS
} NormAckingStatus;
NORM_API_LINKAGE
typedef enum NormTrackingStatus
{
NORM_TRACK_NONE,
NORM_TRACK_RECEIVERS,
NORM_TRACK_SENDERS,
NORM_TRACK_ALL
} NORM_API_LINKAGE NormTrackingStatus;
NORM_TRACK_ALL
} NormTrackingStatus;
NORM_API_LINKAGE
typedef enum NormProbingMode
{
NORM_PROBE_NONE,
NORM_PROBE_PASSIVE,
NORM_PROBE_ACTIVE
} NORM_API_LINKAGE NormProbingMode;
NORM_PROBE_ACTIVE
} NormProbingMode;
NORM_API_LINKAGE
typedef enum NormSyncPolicy
{
NORM_SYNC_CURRENT, // attempt to receiver current/new objects only, join mid-stream
NORM_SYNC_STREAM, // sync to current stream, but to beginning of stream
NORM_SYNC_ALL // attempt to receive old and new objects
} NORM_API_LINKAGE NormSyncPolicy;
} NormSyncPolicy;
NORM_API_LINKAGE
typedef enum NormRepairBoundary
{
NORM_BOUNDARY_BLOCK,
NORM_BOUNDARY_OBJECT
} NORM_API_LINKAGE NormRepairBoundary;
} NormRepairBoundary;
NORM_API_LINKAGE
typedef enum NormEventType
{
NORM_EVENT_INVALID = 0,
@ -179,14 +188,13 @@ typedef enum NormEventType
NORM_RX_OBJECT_UPDATED,
NORM_RX_OBJECT_COMPLETED,
NORM_RX_OBJECT_ABORTED,
NORM_RX_ACK_REQUEST, // upon receipt of app-extended watermark ack request
NORM_GRTT_UPDATED,
NORM_CC_ACTIVE,
NORM_CC_INACTIVE,
NORM_ACKING_NODE_NEW, // whe NormSetAutoAcking
NORM_ACKING_NODE_NEW, // whe NormSetAutoAcking
NORM_SEND_ERROR, // ICMP error (e.g. destination unreachable)
NORM_USER_TIMEOUT // issues when timeout set by NormSetUserTimer() expires
} NORM_API_LINKAGE NormEventType;
} NormEventType;
typedef struct
{
@ -195,47 +203,51 @@ typedef struct
NormNodeHandle sender;
NormObjectHandle object;
} NormEvent;
// For setting custom NORM_OBJECT_DATA alloc/free functions
typedef char* (*NormAllocFunctionHandle)(size_t);
typedef void (*NormFreeFunctionHandle)(char*);
/** NORM API General Initialization and Operation Functions */
NORM_API_LINKAGE
int NormGetVersion(int* major DEFAULT((int*)0),
int* minor DEFAULT((int*)0),
NORM_API_LINKAGE
int NormGetVersion(int* major DEFAULT((int*)0),
int* minor DEFAULT((int*)0),
int* patch DEFAULT((int*)0));
NORM_API_LINKAGE
NORM_API_LINKAGE
NormInstanceHandle NormCreateInstance(bool priorityBoost DEFAULT(false));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormDestroyInstance(NormInstanceHandle instanceHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStopInstance(NormInstanceHandle instanceHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormRestartInstance(NormInstanceHandle instanceHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSuspendInstance(NormInstanceHandle instanceHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormResumeInstance(NormInstanceHandle instanceHandle);
// This MUST be set to enable NORM_OBJECT_FILE reception!
// (otherwise received files are ignored)
NORM_API_LINKAGE
bool NormSetCacheDirectory(NormInstanceHandle instanceHandle,
bool NormSetCacheDirectory(NormInstanceHandle instanceHandle,
const char* cachePath);
// This call blocks until the next NormEvent is ready unless
// "waitForEvent" is set to "false"
NORM_API_LINKAGE
// This call blocks until the next NormEvent is ready unless asynchronous
// notification is used (see below)
NORM_API_LINKAGE
bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent, bool waitForEvent DEFAULT(true));
// The "NormGetDescriptor()" function returns a HANDLE (WIN32) or
@ -253,56 +265,56 @@ typedef int NormDescriptor;
#endif // if/else WIN32/UNIX
extern NORM_API_LINKAGE
const NormDescriptor NORM_DESCRIPTOR_INVALID;
NORM_API_LINKAGE
NORM_API_LINKAGE
NormDescriptor NormGetDescriptor(NormInstanceHandle instanceHandle);
NORM_API_LINKAGE
void NormSetAllocationFunctions(NormInstanceHandle instance,
NormAllocFunctionHandle allocFunc,
NORM_API_LINKAGE
void NormSetAllocationFunctions(NormInstanceHandle instance,
NormAllocFunctionHandle allocFunc,
NormFreeFunctionHandle freeFunc);
// NORM Session Creation and Control Functions
/** NORM Session Creation and Control Functions */
NORM_API_LINKAGE
NORM_API_LINKAGE
NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
const char* sessionAddress,
UINT16 sessionPort,
NormNodeId localNodeId);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormDestroySession(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormInstanceHandle NormGetInstance(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
bool NormIsUnicastAddress(const char* address);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetUserData(NormSessionHandle sessionHandle, const void* userData);
NORM_API_LINKAGE
NORM_API_LINKAGE
const void* NormGetUserData(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetUserTimer(NormSessionHandle sessionHandle, double seconds);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormCancelUserTimer(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
bool NormGetAddress(NormSessionHandle sessionHandle,
char* addrBuffer,
char* addrBuffer,
unsigned int* bufferLen,
UINT16* port DEFAULT((UINT16*)0));
NORM_API_LINKAGE
UINT16 NormGetRxPort(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetTxPort(NormSessionHandle sessionHandle,
UINT16 txPortNumber,
bool enableReuse DEFAULT(false),
@ -316,16 +328,6 @@ void NormSetTxOnly(NormSessionHandle sessionHandle,
bool txOnly,
bool connectToSessionAddress DEFAULT(false));
NORM_API_LINKAGE
void NormLimitObjectInfo(NormSessionHandle sessionHandle, bool state); // if true, FEC OTI in NORM_INFO only
NORM_API_LINKAGE
bool NormPresetObjectInfo(NormSessionHandle sessionHandle, // FEC OTI is preset and not sent
unsigned long objectSize, // (most useful for NORM_OBJECT_STREAM)
UINT16 segmentSize,
UINT16 numData,
UINT16 numParity);
NORM_API_LINKAGE
void NormSetId(NormSessionHandle sessionHandle, NormNodeId normId);
@ -344,7 +346,7 @@ NORM_API_LINKAGE
bool NormTransferSender(NormSessionHandle sessionHandle, NormNodeHandle sender);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetRxPortReuse(NormSessionHandle sessionHandle,
bool enableReuse,
const char* rxBindAddress DEFAULT((const char*)0), // if non-NULL, bind() to <rxBindAddress>/<sessionPort>
@ -354,9 +356,6 @@ void NormSetRxPortReuse(NormSessionHandle sessionHandle,
NORM_API_LINKAGE
UINT16 NormGetRxPort(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
bool NormGetRxBindAddress(NormSessionHandle sessionHandle, char* addr, unsigned int& addrLen, UINT16& port);
// TBD - We should probably have a "NormSetCCMode(NormCCMode ccMode)" function for users
NORM_API_LINKAGE
void NormSetEcnSupport(NormSessionHandle sessionHandle,
@ -364,27 +363,27 @@ void NormSetEcnSupport(NormSessionHandle sessionHandle,
bool ignoreLoss DEFAULT(false), // With "ecnEnable", use ECN-only, ignoring packet loss
bool tolerateLoss DEFAULT(false)); // loss-tolerant congestion control, ecnEnable or not, ignoreLoss = false
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
const char* interfaceName);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetSSM(NormSessionHandle sessionHandle,
const char* sourceAddress);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetTTL(NormSessionHandle sessionHandle,
unsigned char ttl);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetTOS(NormSessionHandle sessionHandle,
unsigned char tos);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetLoopback(NormSessionHandle sessionHandle,
bool loopback);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetMulticastLoopback(NormSessionHandle sessionHandle,
bool loopback);
@ -394,13 +393,13 @@ bool NormSetFragmentation(NormSessionHandle sessionHandle,
bool fragmentation);
// Special functions for debug support
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetMessageTrace(NormSessionHandle sessionHandle, bool state);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetTxLoss(NormSessionHandle sessionHandle, double percent);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetRxLoss(NormSessionHandle sessionHandle, double percent);
NORM_API_LINKAGE
@ -436,7 +435,7 @@ NormSessionId NormGetRandomSessionId();
// This function has been updated so that 16-bit Reed-Solomon
// codecs can be accessed. This may cause an issue for linking
// to older versions of the NORM library
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormStartSender(NormSessionHandle sessionHandle,
NormSessionId instanceId,
UINT32 bufferSpace,
@ -445,165 +444,149 @@ bool NormStartSender(NormSessionHandle sessionHandle,
UINT16 numParity,
UINT8 fecId DEFAULT(0));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStopSender(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetTxRate(NormSessionHandle sessionHandle,
double bitsPerSecond);
NORM_API_LINKAGE
NORM_API_LINKAGE
double NormGetTxRate(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetTxSocketBuffer(NormSessionHandle sessionHandle,
unsigned int bufferSize);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetFlowControl(NormSessionHandle sessionHandle,
double flowControlFactor);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetCongestionControl(NormSessionHandle sessionHandle,
bool enable,
bool adjustRate DEFAULT(true));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetTxRateBounds(NormSessionHandle sessionHandle,
double rateMin,
double rateMax);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetTxCacheBounds(NormSessionHandle sessionHandle,
NormSize sizeMax,
UINT32 countMin,
UINT32 countMax);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetAutoParity(NormSessionHandle sessionHandle,
unsigned char autoParity);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetGrttEstimate(NormSessionHandle sessionHandle,
double grttEstimate);
NORM_API_LINKAGE
double NormGetGrttEstimate(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetGrttMax(NormSessionHandle sessionHandle,
double grttMax);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetGrttProbingMode(NormSessionHandle sessionHandle,
NormProbingMode probingMode);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
double intervalMin,
double intervalMax);
NORM_API_LINKAGE
void NormSetGrttProbingTOS(NormSessionHandle sessionHandle,
UINT8 probeTOS);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetBackoffFactor(NormSessionHandle sessionHandle,
double backoffFactor);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetGroupSize(NormSessionHandle sessionHandle,
unsigned int groupSize);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetTxRobustFactor(NormSessionHandle sessionHandle,
int robustFactor);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
const char* fileName,
const char* infoPtr DEFAULT((const char*)0),
unsigned int infoLen DEFAULT(0));
NORM_API_LINKAGE
NORM_API_LINKAGE
NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
const char* dataPtr,
UINT32 dataLen,
const char* infoPtr DEFAULT((const char*)0),
unsigned int infoLen DEFAULT(0));
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormRequeueObject(NormSessionHandle sessionHandle, NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
UINT32 bufferSize,
const char* infoPtr DEFAULT((const char*)0),
unsigned int infoLen DEFAULT(0));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormObjectSetUserData(NormObjectHandle objectHandle, const void* userData);
NORM_API_LINKAGE
NORM_API_LINKAGE
const void* NormObjectGetUserData(NormObjectHandle objectHandle);
// TBD - we should add a "bool watermark" option to "graceful" stream closure???
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStreamClose(NormObjectHandle streamHandle, bool graceful DEFAULT(false));
NORM_API_LINKAGE
unsigned int NormGetStreamBufferSegmentCount(unsigned int bufferBytes, UINT16 segmentSize, UINT16 blockSize);
NORM_API_LINKAGE
NORM_API_LINKAGE
unsigned int NormStreamWrite(NormObjectHandle streamHandle,
const char* buffer,
unsigned int numBytes);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStreamFlush(NormObjectHandle streamHandle,
bool eom DEFAULT(false),
NormFlushMode flushMode DEFAULT(NORM_FLUSH_PASSIVE));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStreamSetAutoFlush(NormObjectHandle streamHandle,
NormFlushMode flushMode);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStreamSetPushEnable(NormObjectHandle streamHandle,
bool pushEnable);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormStreamHasVacancy(NormObjectHandle streamHandle);
NORM_API_LINKAGE
unsigned int NormStreamGetVacancy(NormObjectHandle streamHandle, unsigned int bytesWanted = 0);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStreamMarkEom(NormObjectHandle streamHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetWatermark(NormSessionHandle sessionHandle,
NormObjectHandle objectHandle,
bool overrideFlush DEFAULT(false));
NORM_API_LINKAGE
bool NormSetWatermarkEx(NormSessionHandle sessionHandle,
NormObjectHandle objectHandle,
const char* buffer,
unsigned int numBytes,
bool overrideFlush DEFAULT(false));
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormResetWatermark(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormCancelWatermark(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormAddAckingNode(NormSessionHandle sessionHandle,
NormNodeId nodeId);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
NormNodeId nodeId);
@ -615,92 +598,86 @@ NORM_API_LINKAGE
void NormSetAutoAckingNodes(NormSessionHandle sessionHandle,
NormTrackingStatus trackingStatus);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
NormNodeId nodeId DEFAULT(NORM_NODE_ANY));
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormGetNextAckingNode(NormSessionHandle sessionHandle,
NormNodeId* nodeId,
NormAckingStatus* ackingStatus DEFAULT(0));
NORM_API_LINKAGE
bool NormGetAckEx(NormSessionHandle sessionHandle,
NormNodeId nodeId,
char* buffer,
unsigned int* buflen);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSendCommand(NormSessionHandle sessionHandle,
const char* cmdBuffer,
unsigned int cmdLength,
bool robust DEFAULT(false));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormCancelCommand(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetSynStatus(NormSessionHandle sessionHandle, bool state);
/* NORM Receiver Functions */
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormStartReceiver(NormSessionHandle sessionHandle,
UINT32 bufferSpace);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormStopReceiver(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetRxCacheLimit(NormSessionHandle sessionHandle,
unsigned short countMax);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormSetRxSocketBuffer(NormSessionHandle sessionHandle,
unsigned int bufferSize);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetSilentReceiver(NormSessionHandle sessionHandle,
bool silent,
int maxDelay DEFAULT(-1));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle,
bool unicastNacks);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormNodeSetUnicastNack(NormNodeHandle remoteSender,
bool unicastNacks);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetDefaultSyncPolicy(NormSessionHandle sessionHandle,
NormSyncPolicy syncPolicy);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetDefaultNackingMode(NormSessionHandle sessionHandle,
NormNackingMode nackingMode);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormNodeSetNackingMode(NormNodeHandle remoteSender,
NormNackingMode nackingMode);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormObjectSetNackingMode(NormObjectHandle objectHandle,
NormNackingMode nackingMode);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle,
NormRepairBoundary repairBoundary);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormNodeSetRepairBoundary(NormNodeHandle remoteSender,
NormRepairBoundary repairBoundary);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormSetDefaultRxRobustFactor(NormSessionHandle sessionHandle,
int robustFactor);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormNodeSetRxRobustFactor(NormNodeHandle remoteSender,
int robustFactor);
@ -712,90 +689,90 @@ bool NormPreallocateRemoteSender(NormSessionHandle sessionHandle,
UINT16 numParity,
unsigned int streamBufferSize DEFAULT(0));
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormStreamRead(NormObjectHandle streamHandle,
char* buffer,
unsigned int* numBytes);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormStreamSeekMsgStart(NormObjectHandle streamHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
UINT32 NormStreamGetReadOffset(NormObjectHandle streamHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
UINT32 NormStreamGetBufferUsage(NormObjectHandle streamHandle);
/** NORM Object Functions */
NORM_API_LINKAGE
NORM_API_LINKAGE
NormObjectType NormObjectGetType(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormObjectHasInfo(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
UINT16 NormObjectGetInfoLength(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
UINT16 NormObjectGetInfo(NormObjectHandle objectHandle,
char* buffer,
UINT16 bufferLen);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormSize NormObjectGetSize(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormObjectCancel(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormObjectRetain(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormObjectRelease(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormFileGetName(NormObjectHandle fileHandle,
char* nameBuffer,
unsigned int bufferLen);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormFileRename(NormObjectHandle fileHandle,
const char* fileName);
NORM_API_LINKAGE
NORM_API_LINKAGE
const char* NormDataAccessData(NormObjectHandle objectHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
char* NormDataDetachData(NormObjectHandle objectHandle);
NORM_API_LINKAGE
char* NormAlloc(size_t numBytes);
NORM_API_LINKAGE
char* NormAlloc(size_t numBytes);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormFree(char* dataPtr);
NORM_API_LINKAGE
NORM_API_LINKAGE
NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle);
/** NORM Node Functions */
NORM_API_LINKAGE
NORM_API_LINKAGE
NormNodeId NormNodeGetId(NormNodeHandle nodeHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
bool NormNodeGetAddress(NormNodeHandle nodeHandle,
char* addrBuffer,
char* addrBuffer,
unsigned int* bufferLen,
UINT16* port DEFAULT((UINT16*)0));
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormNodeSetUserData(NormNodeHandle nodeHandle, const void* userData);
NORM_API_LINKAGE
NORM_API_LINKAGE
const void* NormNodeGetUserData(NormNodeHandle nodeHandle);
NORM_API_LINKAGE
@ -807,26 +784,16 @@ bool NormNodeGetCommand(NormNodeHandle remoteSender,
char* buffer,
unsigned int* buflen);
NORM_API_LINKAGE
bool NormNodeSendAckEx(NormNodeHandle remoteSender,
const char* buffer,
unsigned int numBytes);
NORM_API_LINKAGE
bool NormNodeGetWatermarkEx(NormNodeHandle remoteSender,
char* buffer,
unsigned int* buflen);
NORM_API_LINKAGE
void NormNodeFreeBuffers(NormNodeHandle remoteSender);
NORM_API_LINKAGE
void NormNodeDelete(NormNodeHandle remoteSender);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormNodeRetain(NormNodeHandle nodeHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
void NormNodeRelease(NormNodeHandle nodeHandle);
/** Some experimental functions */
@ -834,7 +801,7 @@ void NormNodeRelease(NormNodeHandle nodeHandle);
NORM_API_LINKAGE
void NormReleasePreviousEvent(NormInstanceHandle instanceHandle);
NORM_API_LINKAGE
NORM_API_LINKAGE
UINT32 NormCountCompletedObjects(NormSessionHandle sessionHandle);
@ -848,7 +815,7 @@ NORM_API_LINKAGE
bool NormNodeAllowSender(NormNodeId senderId);
NORM_API_LINKAGE
bool NormNodeDenySender(NormNodeId senderId);
bool NormNodeDenySender(NormNodeId senderId);
#ifdef __cplusplus
} // end extern "C"

0
include/normEncoder.h Executable file → Normal file
View File

0
include/normEncoderMDP.h Executable file → Normal file
View File

0
include/normEncoderRS16.h Executable file → Normal file
View File

0
include/normEncoderRS8.h Executable file → Normal file
View File

0
include/normFile.h Executable file → Normal file
View File

149
include/normMessage.h Executable file → Normal file
View File

@ -69,12 +69,12 @@ inline UINT16 NormQuantizeLoss(double lossFraction)
lossFraction = MIN(lossFraction, 65535.0);
return (UINT16)lossFraction;
} // end NormQuantizeLossFraction()
inline double NormUnquantizeLoss(UINT16 lossQuantized)
{
return (((double)lossQuantized) / 65535.0);
} // end NormUnquantizeLossFraction()
// Extended precision Norm loss quantize/unquantize with
// 32-bit precision (needed for low BER, high bandwidth*delay)
inline UINT32 NormQuantizeLoss32(double lossFraction)
@ -183,7 +183,7 @@ const NormNodeId NORM_NODE_ANY = 0xffffffff;
class NormObjectId
{
public:
NormObjectId() : value(0) {};
NormObjectId() {};
NormObjectId(UINT16 id) {value = id;}
NormObjectId(const NormObjectId& id) {value = id.value;}
operator UINT16() const {return value;}
@ -195,11 +195,13 @@ class NormObjectId
UINT16 diff = value - id.value;
return ((diff > 0x8000) || ((0x8000 == diff) && (value > id.value)));
}
bool operator>(const NormObjectId& id) const
{
UINT16 diff = id.value - value;
return ((diff > 0x8000) || ((0x8000 == diff) && (id.value > value)));
}
bool operator<=(const NormObjectId& id) const
{return ((value == id.value) || (*this < id));}
bool operator>=(const NormObjectId& id) const
@ -329,16 +331,14 @@ class NormHeaderExtension
INVALID = 0,
FTI = 64, // FEC Object Transmission Information (FTI) extension
CC_FEEDBACK = 3, // NORM-CC Feedback extension
CC_RATE = 128, // NORM-CC Rate extension
APP_ACK = 65 // app-defined ACK extension (see NormSetWatermarkEx())
CC_RATE = 128 // NORM-CC Rate extension
};
NormHeaderExtension();
virtual ~NormHeaderExtension() {}
virtual void Init(UINT32* theBuffer, UINT16 numBytes)
virtual void Init(UINT32* theBuffer)
{
// TBD - should we confirm that 'numBytes' is sufficient
AttachBuffer(theBuffer, numBytes);
buffer = theBuffer;
SetType(INVALID);
SetWords(0);
}
@ -347,17 +347,13 @@ class NormHeaderExtension
void SetWords(UINT8 words)
{((UINT8*)buffer)[LENGTH_OFFSET] = words;}
void AttachBuffer(const UINT32* theBuffer, UINT16 bufferLength)
{
buffer = (UINT32*)theBuffer;
buffer_length = bufferLength;
}
const UINT32* GetBuffer()
{return buffer;}
void AttachBuffer(const UINT32* theBuffer) {buffer = (UINT32*)theBuffer;}
const UINT32* GetBuffer() {return buffer;}
Type GetType() const
{return buffer ? (Type)(((UINT8*)buffer)[TYPE_OFFSET]) : INVALID;}
{
return buffer ? (Type)(((UINT8*)buffer)[TYPE_OFFSET]) : INVALID;
}
UINT16 GetLength() const
{
return (buffer ?
@ -365,27 +361,14 @@ class NormHeaderExtension
((((UINT8*)buffer)[LENGTH_OFFSET]) << 2) : 4) :
0);
}
// These currently only used for APP_ACK extension
const char* GetContent()
{return (((const char*)buffer) + CONTENT_OFFSET);}
UINT16 GetContentLength() const
{
UINT16 totalLen = GetLength();
return ((totalLen > CONTENT_OFFSET) ? (totalLen - CONTENT_OFFSET) : 0);
}
static UINT16 GetContentOffset()
{return (UINT16)CONTENT_OFFSET;}
protected:
enum
{
TYPE_OFFSET = 0, // UINT8 offset
LENGTH_OFFSET = TYPE_OFFSET + 1, // UINT8 offset
CONTENT_OFFSET = LENGTH_OFFSET + 1 // UINT8 offset
TYPE_OFFSET = 0, // UINT8 offset
LENGTH_OFFSET = TYPE_OFFSET + 1 // UINT8 offset
};
UINT32* buffer;
UINT16 buffer_length;
}; // end class NormHeaderExtension
@ -611,15 +594,9 @@ class NormMsg
void AttachExtension(NormHeaderExtension& extension)
{
extension.Init(buffer+(header_length/4), MAX_SIZE - header_length);
extension.Init(buffer+(header_length/4));
ExtendHeaderLength(extension.GetLength());
}
// Only use this for extensions that have content appended after attachment
// (Fixed-length extensions should set their length upon Init())
void PackExtension(NormHeaderExtension& extension)
{
ExtendHeaderLength(2 + extension.GetContentLength());
}
// Message processing routines
bool InitFromBuffer(UINT16 msgLength);
@ -633,7 +610,7 @@ class NormMsg
{return (((UINT8*)buffer)[VERSION_OFFSET] >> 4);}
NormMsg::Type GetType() const
{return (Type)(((UINT8*)buffer)[TYPE_OFFSET] & 0x0f);}
UINT16 GetHeaderLength() const
UINT16 GetHeaderLength()
{return ((UINT8*)buffer)[HDR_LEN_OFFSET] << 2;}
UINT16 GetBaseHeaderLength()
{return header_length_base;}
@ -654,24 +631,14 @@ class NormMsg
// To retrieve any attached header extensions
bool HasExtensions() const {return (header_length > header_length_base);}
bool HasExtension(NormHeaderExtension::Type extType);
bool GetNextExtension(NormHeaderExtension& ext) const
{
const UINT32* currentBuffer = ext.GetBuffer();
// 'nextOffset' here is a UINT32 offset
const UINT32* currentBuffer = ext.GetBuffer();
UINT16 nextOffset =
(UINT16)(currentBuffer ? (currentBuffer - buffer + (ext.GetLength()/4)) :
(header_length_base/4));
(header_length_base/4));
bool result = HasExtensions() ? (nextOffset < (header_length/4)) : false;
if (result)
{
UINT16 nextLength = ((UINT8*)(buffer + nextOffset))[1] << 2;
ext.AttachBuffer(buffer+nextOffset, nextLength);
}
else
{
ext.AttachBuffer((UINT32*)NULL, 0);
}
ext.AttachBuffer(result ? (buffer+nextOffset) : (UINT32*)NULL);
return result;
}
@ -786,9 +753,9 @@ class NormFtiExtension2 : public NormHeaderExtension
{
public:
// To build the FTI Header Extension
virtual void Init(UINT32* theBuffer, UINT16 numBytes)
virtual void Init(UINT32* theBuffer)
{
AttachBuffer(theBuffer, numBytes);
AttachBuffer(theBuffer);
SetType(FTI); // HET = 64
SetWords(4);
}
@ -847,16 +814,6 @@ class NormFtiData
num_data(0), num_parity(0), fec_m(0), instance_id(0) {}
~NormFtiData() {}
bool IsValid() const
{return (0 != segment_size);}
void Invalidate()
{
object_size = 0;
segment_size = num_data = num_parity = instance_id = 0;
fec_m = 0;
}
void SetObjectSize(const NormObjectSize& objectSize)
{object_size = objectSize;}
void SetSegmentSize(UINT16 segmentSize)
@ -893,15 +850,16 @@ class NormFtiData
}; // end class NormFtiData
// This FEC Object Transmission Information assumes "fec_id" == 5 (RFC 5510)
// (this is the fully-defined 8-bit Reed-Solomon codec)
class NormFtiExtension5 : public NormHeaderExtension
{
public:
// To build the fec_id=5 FTI Header Extension
virtual void Init(UINT32* theBuffer, UINT16 numBytes)
virtual void Init(UINT32* theBuffer)
{
AttachBuffer(theBuffer, numBytes);
AttachBuffer(theBuffer);
SetType(FTI); // HET = 64
SetWords(3);
}
@ -933,45 +891,14 @@ class NormFtiExtension5 : public NormHeaderExtension
private:
enum
{
OBJ_SIZE_MSB_OFFSET = (CONTENT_OFFSET)/2, // UINT16 offset
OBJ_SIZE_LSB_OFFSET = ((OBJ_SIZE_MSB_OFFSET*2)+2)/4,// UINT32 offset
SEG_SIZE_OFFSET = ((OBJ_SIZE_LSB_OFFSET*4)+4)/2, // UINT16 offset
FEC_NDATA_OFFSET = ((SEG_SIZE_OFFSET+1)*2), // UINT8 offset
FEC_NPARITY_OFFSET = (FEC_NDATA_OFFSET+1) // UINT8 offset
OBJ_SIZE_MSB_OFFSET = (LENGTH_OFFSET + 1)/2,
OBJ_SIZE_LSB_OFFSET = ((OBJ_SIZE_MSB_OFFSET*2)+2)/4,
SEG_SIZE_OFFSET = ((OBJ_SIZE_LSB_OFFSET*4)+4)/2,
FEC_NDATA_OFFSET = ((SEG_SIZE_OFFSET+1)*2),
FEC_NPARITY_OFFSET = (FEC_NDATA_OFFSET+1)
};
}; // end class NormFtiExtension5
class NormAppAckExtension : public NormHeaderExtension
{
public:
virtual void Init(UINT32* theBuffer, UINT16 numBytes)
{
AttachBuffer(theBuffer, numBytes);
SetType(APP_ACK);
SetWords(0);
}
bool SetContent(const char* data, UINT16 dataLen)
{
if (dataLen > (buffer_length - CONTENT_OFFSET)) return false;
memcpy(((char*)buffer) + CONTENT_OFFSET, data, dataLen);
if (dataLen > 2)
{
// Pad out to get 32-bit alignment of extension
dataLen += CONTENT_OFFSET;
UINT16 padLen = dataLen % 4;
if (padLen)
padLen = 4 - padLen;
dataLen += padLen;
SetWords(dataLen/4);
}
else
{
SetWords(1);
}
return true;
}
}; // end class NormAppAckExtension
// This FEC Object Transmission Information assumes "fec_id" == 129
class NormFtiExtension129 : public NormHeaderExtension
@ -979,9 +906,9 @@ class NormFtiExtension129 : public NormHeaderExtension
public:
// To build the FTI Header Extension
// (TBD) allow for different "fec_id" types in the future
virtual void Init(UINT32* theBuffer, UINT16 numBytes)
virtual void Init(UINT32* theBuffer)
{
AttachBuffer(theBuffer, numBytes);
AttachBuffer(theBuffer);
SetType(FTI);
SetWords(4);
}
@ -1277,7 +1204,7 @@ class NormCmdFlushMsg : public NormCmdMsg
{length = header_length;}
bool AppendAckingNode(NormNodeId nodeId, UINT16 segmentSize)
{
if ((length-header_length + 4) > segmentSize) return false;
if ((length-header_length+ 4) > segmentSize) return false;
buffer[length/4] = htonl((UINT32)nodeId);
length += 4;
return true;
@ -1521,9 +1448,9 @@ class NormCCRateExtension : public NormHeaderExtension
{
public:
virtual void Init(UINT32* theBuffer, UINT16 numBytes)
virtual void Init(UINT32* theBuffer)
{
AttachBuffer(theBuffer, numBytes);
AttachBuffer(theBuffer);
SetType(CC_RATE);
((UINT8*)buffer)[RESERVED_OFFSET] = 0;
}
@ -1741,9 +1668,9 @@ class NormCmdRepairAdvMsg : public NormCmdMsg
class NormCCFeedbackExtension : public NormHeaderExtension
{
public:
virtual void Init(UINT32* theBuffer, UINT16 numBytes)
virtual void Init(UINT32* theBuffer)
{
AttachBuffer(theBuffer, numBytes);
AttachBuffer(theBuffer);
SetType(CC_FEEDBACK);
SetWords(3);
((UINT8*)buffer)[CC_FLAGS_OFFSET] = 0;
@ -1801,7 +1728,7 @@ class NormCCFeedbackExtension : public NormHeaderExtension
CC_LOSS_OFFSET = (CC_RTT_OFFSET + 1)/2,
CC_RATE_OFFSET = ((CC_LOSS_OFFSET*2)+2)/2,
//CC_RESERVED_OFFSET = ((CC_RATE_OFFSET*2)+2)/2
CC_LOSS_EX_OFFSET = ((CC_RATE_OFFSET*2)+2)/2 // extended precision loss estimate (non-RFC5740 compliant, but compatible)
CC_LOSS_EX_OFFSET = ((CC_RATE_OFFSET*2)+2)/2 // extended precision loss estimate (non-RFC5940 compliant, but compatible)
};
}; // end class NormCCFeedbackExtension
@ -1988,7 +1915,7 @@ class NormNackMsg : public NormMsg
};
}; // end class NormNackMsg
class NormAckMsg : public NormAck, public NormMsg
class NormAckMsg : public NormMsg
{
public:

77
include/normNode.h Executable file → Normal file
View File

@ -134,7 +134,7 @@ class NormLossEstimator2
history[1] = (unsigned int)((1.0 / lossFraction) + 0.5);
}
unsigned long CurrentLossInterval() {return history[0];}
unsigned long LastLossInterval() {return history[1];}
unsigned int LastLossInterval() {return history[1];}
void SetIgnoreLoss(bool state)
{ignore_loss = state;}
@ -188,28 +188,6 @@ class NormLossEstimator2
}; // end class NormLossEstimator2
class NormCongestionDetector
{
// This class implements a delay-based congestion indicator
// based on feedback from NORM receivers. Similar to loss-based
// congestion detection, this detector monitors the history of
// RTT measurement
// NOTES:
// 1) One challenge to consider is reverse path contribution
// to RTT may create "false positives" on RTT change detection.
// A technique to mitigate is to use reference timing that the
// receiver can establish on expected sender packet arrivals
// given rate information to helps separate sender->receiver
// contribution to RTT versus the reverse path receiver->sender
// aspect. E.g., the receiver could compare the stats of arriving
// sender packets in reference to advertised rate to have an indication
// of increasing (or decreasing) sender->receiver latency.
//
// 2)
//
}; // end class NormCongestionDetector
class NormAckingNode : public NormNode
{
public:
@ -228,21 +206,10 @@ class NormAckingNode : public NormNode
unsigned int GetReqCount() const {return req_count;}
bool AckReceived() const {return ack_received;}
void MarkAckReceived() {ack_received = true;}
bool SetAckEx(const char* buffer, UINT16 numBytes);
bool GetAckEx(char* buffer, unsigned int* buflen);
/*
const char* GetAppAckContent() const
{return (const char*)ack_ex_buffer;}
unsigned int GetAppAckLength() const
{return ack_ex_length;} */
private:
bool ack_received; // was ack received?
unsigned int req_count; // remaining request attempts
char* ack_ex_buffer;
unsigned int ack_ex_length;
}; // end NormAckingNode
@ -330,7 +297,7 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
UINT16 segmentSize ,
UINT16 numData,
UINT16 numParity);
bool GetFtiData(const NormObjectMsg& msg, NormFtiData& ftiData);
bool GetFtiData(const NormObjectMsg& msg, NormFtiData& ftiData);
// Parameters
NormObject::NackingMode GetDefaultNackingMode() const
@ -392,7 +359,7 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
UINT16 segmentSize,
UINT16 numData,
UINT16 numParity);
bool BuffersAllocated() {return (NULL != retrieval_pool);}
bool BuffersAllocated() {return (0 != segment_size);}
void FreeBuffers();
void Activate(bool isObjectMsg);
@ -403,7 +370,7 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
UINT8 GetFecFieldSize() const
{return fti_data.GetFecFieldSize();}
{return fec_m;}
bool GetFirstPending(NormObjectId& objectId) const
{
@ -441,9 +408,9 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
return NULL;
}
UINT16 SegmentSize() const {return fti_data.GetSegmentSize();}
UINT16 BlockSize() const {return fti_data.GetFecMaxBlockLen();}
UINT16 NumParity() const {return fti_data.GetFecNumParity();}
UINT16 SegmentSize() {return segment_size;}
UINT16 BlockSize() {return ndata;}
UINT16 NumParity() {return nparity;}
NormBlock* GetFreeBlock(NormObjectId objectId, NormBlockId blockId);
void PutFreeBlock(NormBlock* block)
@ -458,7 +425,7 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
void SetErasureLoc(UINT16 index, UINT16 value)
{
ASSERT(index < NumParity());
ASSERT(index < nparity);
erasure_loc[index] = value;
}
UINT16 GetErasureLoc(UINT16 index)
@ -467,7 +434,7 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
}
void SetRetrievalLoc(UINT16 index, UINT16 value)
{
ASSERT(index < BlockSize());
ASSERT(index < ndata);
retrieval_loc[index] = value;
}
UINT16 GetRetrievalLoc(UINT16 index)
@ -477,7 +444,7 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
char* GetRetrievalSegment()
{
char* s = retrieval_pool[retrieval_index++];
retrieval_index = (retrieval_index >= BlockSize()) ? 0 : retrieval_index;
retrieval_index = (retrieval_index >= ndata) ? 0 : retrieval_index;
return s;
}
@ -491,9 +458,9 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
// Statistics kept on sender
unsigned long CurrentBufferUsage() const
{return (SegmentSize() * segment_pool.CurrentUsage());}
{return (segment_size * segment_pool.CurrentUsage());}
unsigned long PeakBufferUsage() const
{return (SegmentSize() * segment_pool.PeakUsage());}
{return (segment_size * segment_pool.PeakUsage());}
unsigned long BufferOverunCount() const
{return segment_pool.OverunCount() + block_pool.OverrunCount();}
@ -563,9 +530,6 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
bool ReadNextCmd(char* buffer, unsigned int* buflen);
bool SendAckEx(const char* data, unsigned int numBytes);
bool GetWatermarkEx(char* buffer, unsigned int* buflen);
void SetAddress(const ProtoAddress& address)
{
unsigned int len = address.GetLength();
@ -578,7 +542,7 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
UINT8 GetGrttQuantized() const
{return grtt_quantized;}
double GetBackoffFactor() const
UINT8 GetBackoffFactor() const
{return backoff_factor;}
UINT8 GetGroupSizeQuantized() const
{return gsize_quantized;}
@ -627,15 +591,11 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
UINT16 max_pending_range; // max range of pending objs allowed
bool is_open;
// TBD - embed the FTI parameters into a NormFtiData object
UINT16 segment_size;
UINT8 fec_id;
NormFtiData fti_data;
bool preset_fti;
//UINT16 segment_size;
//UINT8 fec_id;
//UINT8 fec_m;
//unsigned int ndata;
//unsigned int nparity;
UINT8 fec_m;
unsigned int ndata;
unsigned int nparity;
NormStreamObject* preset_stream;
NormObjectTable rx_table;
@ -662,9 +622,6 @@ class NormSenderNode : public NormNode, public ProtoTree::Item
NormObjectId watermark_object_id;
NormBlockId watermark_block_id;
NormSegmentId watermark_segment_id;
bool ack_ex_pending;
char* ack_ex_buffer;
unsigned int ack_ex_length;
// Remote sender grtt measurement state
double grtt_estimate;

15
include/normObject.h Executable file → Normal file
View File

@ -30,7 +30,6 @@ class NormObject
enum CheckLevel
{
BLIND_CHECK,
TO_OBJECT,
THRU_INFO,
TO_BLOCK,
@ -90,14 +89,7 @@ class NormObject
info_len = 0;
pending_info = false;
}
// This is used to bootstrap reception sender
// is using FTI_INFO FtiMode
void SetPendingInfo(bool state, UINT8 fecId)
{
pending_info = true;
fec_id = fecId;
}
const char* GetInfo() const {return info_ptr;}
UINT16 GetInfoLength() const {return info_len;}
bool IsStream() const {return (STREAM == type);}
@ -361,7 +353,6 @@ class NormFileObject : public NormObject
const char* infoPtr = NULL,
UINT16 infoLen = 0);
bool Accept(const char* thePath);
void CloseFile();
void Close();
const char* GetPath() {return path;}
@ -486,10 +477,6 @@ class NormStreamObject : public NormObject
bool HasVacancy()
{return (stream_closing ? false : write_vacancy);}
// Returns how many bytes can be written to stream without blocking
// (up to 'wanted' for non-zero 'wanted', otherwise max vacancy available)
unsigned int GetVacancy(unsigned int wanted = 0);
NormBlock* StreamBlockLo()
{return stream_buffer.Find(stream_buffer.RangeLo());}
void SetLastNackTime(NormBlockId blockId, const ProtoTime& theTime)

0
include/normPostProcess.h Executable file → Normal file
View File

0
include/normSegment.h Executable file → Normal file
View File

80
include/normSession.h Executable file → Normal file
View File

@ -51,15 +51,12 @@ class NormController
RX_OBJECT_UPDATED,
RX_OBJECT_COMPLETED,
RX_OBJECT_ABORTED,
RX_ACK_REQUEST, // upon receipt of app-extended watermark ack request
GRTT_UPDATED,
CC_ACTIVE, // posted when cc feedback is detected
CC_INACTIVE, // posted when no cc feedback and min rate reached
ACKING_NODE_NEW,
SEND_ERROR,
USER_TIMEOUT,
// The ones below here are not exposed via the NORM API
SEND_OK
USER_TIMEOUT
};
virtual void Notify(NormController::Event event,
@ -169,14 +166,6 @@ class NormSession
TRACK_SENDERS = 0x02,
TRACK_ALL = 0x03
};
// Object FEC Transport Information (FTI) mode
enum FtiMode
{
FTI_PRESET = 0, // Receivers have preset FTI, don't send
FTI_INFO = 1, // Send FTI in NORM_INFO messages only
FTI_ALWAYS = 2 // Send FTI in NORM_DATA and NORM_INFO messages
};
// General methods
void SetNodeId(NormNodeId nodeId)
@ -236,9 +225,6 @@ class NormSession
UINT16 GetRxPort() const;
const ProtoAddress& GetRxBindAddr() const
{return rx_bind_addr;}
// "SetEcnSupport(true)" sets up raw packet capture (pcap) so that incoming packet
// ECN status may be checked
// NOTE: only effective _before_ sndr/rcvr startup!
@ -272,9 +258,6 @@ class NormSession
}
void SetTxRateBounds(double rateMin, double rateMax);
void ClearSendError()
{posted_send_error = false;}
double BackoffFactor()
{return backoff_factor;}
void SetBackoffFactor(double value)
@ -289,12 +272,6 @@ class NormSession
if (state) probe_proactive = true;
}
// This MUST be called before
void SetProbeTOS(UINT8 probeTOS)
{probe_tos = probeTOS;}
UINT8 GetProbeTOS() const
{return probe_tos;}
// This method enables/disables flow control operation.
void SetFlowControl(double flowControlFactor)
{flow_control_factor = flowControlFactor;}
@ -407,14 +384,11 @@ class NormSession
NormObject* SenderFindTxObject(NormObjectId objectId)
{return tx_table.Find(objectId);}
// postive ack mgmnt (can only fail when 'appAckReq' is set)
bool SenderSetWatermark(NormObjectId objectId,
// postive ack mgmnt
void SenderSetWatermark(NormObjectId objectId,
NormBlockId blockId,
NormSegmentId segmentId,
bool overrideFlush = false,
const char* appAckReq = NULL,
unsigned int appAckReqLen = 0);
bool overrideFlush = false);
void SenderResetWatermark();
void SenderCancelWatermark();
@ -426,7 +400,6 @@ class NormSession
AckingStatus SenderGetAckingStatus(NormNodeId nodeId);
// Set "prevNodeId = NORM_NODE_NONE" to init this iteration (returns "false" when done)
bool SenderGetNextAckingNode(NormNodeId& prevNodeId, AckingStatus* ackingStatus = NULL);
bool SenderGetAckEx(NormNodeId nodeId, char* buffer, unsigned int* buflen);
NormAckingNode* SenderFindAckingNode(NormNodeId nodeId) const
{
@ -437,9 +410,6 @@ class NormSession
bool SenderSendCmd(const char* cmdBuffer, unsigned int cmdLength, bool robust);
void SenderCancelCmd();
// The following method is currently only used for NormSocket purposes
bool SenderSendAppCmd(const char* buffer, unsigned int length, const ProtoAddress& dst);
void SenderSetSynStatus(bool state)
{syn_status = state;}
@ -516,11 +486,6 @@ class NormSession
gsize_advertised = NormUnquantizeGroupSize(gsize_quantized);
}
FtiMode SenderFtiMode() const
{return fti_mode;}
void SenderSetFtiMode(FtiMode ftiMode)
{fti_mode = ftiMode;}
void SenderEncode(unsigned int segmentId, const char* segment, char** parityVectorList)
{encoder->Encode(segmentId, segment, parityVectorList);}
@ -565,21 +530,6 @@ class NormSession
UINT16 numParity,
unsigned int streamBufferSize = 0);
bool SetPresetFtiData(unsigned int objectSize,
UINT16 segmentSize,
UINT16 numData,
UINT16 numParity);
bool GetPresetFtiData(NormFtiData& ftiData)
{
if (preset_fti.IsValid())
{
ftiData = preset_fti;
return true;
}
return false;
}
void ReceiverSetUnicastNacks(bool state)
{unicast_nacks = state;}
bool ReceiverGetUnicastNacks() const
@ -680,15 +630,10 @@ class NormSession
void TxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
void RxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
void HandleReceiveMessage(NormMsg& msg, bool wasUnicast, bool ecn = false);
#ifdef ECN_SUPPORT
// This is used when raw packet capture is enabled
bool OpenProtoCap();
void CloseProtoCap();
bool RawSendTo(const char* buffer, unsigned int& numBytes, const ProtoAddress& dstAddr, UINT8 trafficClass);
void OnPktCapture(ProtoChannel& theChannel,
ProtoChannel::Notification notifyType);
#endif // ECN_SUPPORT
// Sender message handling routines
void SenderHandleNackMessage(const struct timeval& currentTime,
@ -714,6 +659,8 @@ class NormSession
bool SenderBuildRepairAdv(NormCmdRepairAdvMsg& cmd);
void SenderUpdateGroupSize();
bool SenderQueueAppCmd();
// The following method is only used for NormSocket purposes
bool SenderSendAppCmd(const char* buffer, unsigned int length, const ProtoAddress& dst);
// Receiver message handling routines
void ReceiverHandleObjectMessage(const struct timeval& currentTime,
@ -734,10 +681,7 @@ class NormSession
ProtoSocket tx_socket_actual;
ProtoSocket* tx_socket;
ProtoSocket rx_socket;
#ifdef ECN_SUPPORT
ProtoCap* proto_cap; // raw packet capture alternative to "rx_socket"
ProtoAddress src_addr; // used for raw packet sendto()
#endif // ECN_SUPPORT
ProtoCap* rx_cap; // raw packet capture alternative to "rx_socket"
bool rx_port_reuse; // enable rx_socket port (sessionPort) reuse when true
ProtoAddress rx_bind_addr;
ProtoAddress rx_connect_addr;
@ -780,7 +724,6 @@ class NormSession
bool sndr_emcon;
bool tx_only;
bool tx_connect;
FtiMode fti_mode;
NormObjectTable tx_table;
ProtoSlidingMask tx_pending_mask;
@ -801,7 +744,6 @@ class NormSession
int flush_count;
bool posted_tx_queue_empty;
bool posted_tx_rate_changed;
bool posted_send_error;
// For postive acknowledgement collection
NormNodeTree acking_node_tree;
@ -831,7 +773,6 @@ class NormSession
bool probe_reset;
bool probe_data_check; // refrain cc probe until data is send
struct timeval probe_time_last;
UINT8 probe_tos; // optionally use different IP TOS for GRTT probe/response
double grtt_interval; // current GRTT update interval
double grtt_interval_min; // minimum GRTT update interval
@ -872,10 +813,6 @@ class NormSession
ProtoTimer cmd_timer;
bool syn_status;
// Sender "app-defined" ACK_REQUEST state (for NormSetWatermarkEx())
char* ack_ex_buffer;
unsigned int ack_ex_length;
// Receiver parameters
bool is_receiver;
int rx_robust_factor;
@ -891,7 +828,6 @@ class NormSession
NormObject::NackingMode default_nacking_mode;
NormSenderNode::SyncPolicy default_sync_policy;
UINT16 rx_cache_count_max;
NormFtiData preset_fti;
// For NormSocket server-listener support
bool is_server_listener;

0
include/normSimAgent.h Executable file → Normal file
View File

2
include/normVersion.h Executable file → Normal file
View File

@ -36,6 +36,6 @@
#ifndef _NORM_VERSION
#define _NORM_VERSION
#define VERSION "1.5.10"
#define VERSION "1.5.8"
#endif // _NORM_VERSION

0
makefiles/Makefile.arm-linux Executable file → Normal file
View File

59
makefiles/Makefile.common Executable file → Normal file
View File

@ -14,13 +14,13 @@ NS = ../src/sim/ns
INCLUDES = $(SYSTEM_INCLUDES) -I$(UNIX) -I../include -I$(PROTOLIB)/include
CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 -O $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES) -Wno-attributes
CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 -O $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES)
#CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES)
LDFLAGS = $(SYSTEM_LDFLAGS)
# Note: Even command line app needs X11 for Netscape post-processing
LIBS = $(SYSTEM_LIBS) -lm
LIBS = $(SYSTEM_LIBS) -lm -lpthread
XLIBS = -lXmu -lXt -lX11
@ -178,7 +178,7 @@ normMsgr: $(MSGR_OBJ) libnorm.a $(LIBPROTO)
mkdir -p ../bin
cp $@ ../bin/$@
# (normStreamer) stream sender/receiver
# (normStreamer) message sender/receiver
STREAMER_SRC = $(EXAMPLE)/normStreamer.cpp
STREAMER_OBJ = $(STREAMER_SRC:.cpp=.o)
@ -186,64 +186,13 @@ normStreamer: $(STREAMER_OBJ) libnorm.a $(LIBPROTO)
$(CC) $(CFLAGS) -o $@ $(STREAMER_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
mkdir -p ../bin
cp $@ ../bin/$@
# (normCast) file sender/receiver
CAST_SRC = $(EXAMPLE)/normCast.cpp $(COMMON)/normPostProcess.cpp \
$(UNIX)/unixPostProcess.cpp
CAST_OBJ = $(CAST_SRC:.cpp=.o)
normCast: $(CAST_OBJ) libnorm.a $(LIBPROTO)
$(CC) $(CFLAGS) -o $@ $(CAST_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
mkdir -p ../bin
cp $@ ../bin/$@
# (normCastApp) file sender/receiver
CASTAPP_SRC = $(EXAMPLE)/normCastApp.cpp $(COMMON)/normPostProcess.cpp \
$(UNIX)/unixPostProcess.cpp
CASTAPP_OBJ = $(CASTAPP_SRC:.cpp=.o)
normCastApp: $(CASTAPP_OBJ) libnorm.a $(LIBPROTO)
$(CC) $(CFLAGS) -o $@ $(CASTAPP_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
mkdir -p ../bin
cp $@ ../bin/$@
# (chant) NORM command-line chat sender/receiver
CHANT_SRC = $(EXAMPLE)/chant.cpp
CHANT_OBJ = $(CHANT_SRC:.cpp=.o)
chant: $(CHANT_OBJ) libnorm.a $(LIBPROTO)
$(CC) $(CFLAGS) -o $@ $(CHANT_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
mkdir -p ../bin
cp $@ ../bin/$@
# These are the new "NormSocket" API extension examples
SERVER_SRC = $(EXAMPLE)/normServer.cpp $(EXAMPLE)/normSocket.cpp
SERVER_OBJ = $(SERVER_SRC:.cpp=.o)
normServer: $(SERVER_OBJ) libnorm.a $(LIBPROTO)
$(CC) $(CFLAGS) -o $@ $(SERVER_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
mkdir -p ../bin
cp $@ ../bin/$@
CLIENT_SRC = $(EXAMPLE)/normClient.cpp $(EXAMPLE)/normSocket.cpp
CLIENT_OBJ = $(CLIENT_SRC:.cpp=.o)
normClient: $(CLIENT_OBJ) libnorm.a $(LIBPROTO)
$(CC) $(CFLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
mkdir -p ../bin
cp $@ ../bin/$@
# (pcap2norm) - parses pcap (e.g. tcpdump) file and prints NORM trace
PCAP_SRC = $(COMMON)/pcap2norm.cpp
PCAP_OBJ = $(PCAP_SRC:.cpp=.o)
pcap2norm: $(PCAP_OBJ) libnorm.a $(LIBPROTO)
$(CC) $(CFLAGS) -o $@ $(PCAP_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) -lpcap
$(CC) $(CFLAGS) -o $@ $(PCAP_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
mkdir -p ../bin
cp $@ ../bin/$@

0
makefiles/Makefile.freebsd Executable file → Normal file
View File

2
makefiles/Makefile.hpux Executable file → Normal file
View File

@ -8,7 +8,7 @@
#
SYSTEM_INCLUDES =
SYSTEM_LDFLAGS =
SYTSTEM_LIBS = -lpthread
SYTSTEM_LIBS =
# 6) System specific capabilities
# Must choose appropriate for the following:

2
makefiles/Makefile.iphone Executable file → Normal file
View File

@ -12,7 +12,7 @@ SYSROOT = $(SDK)/SDKs/iPhoneOS2.2.1.sdk
SYSTEM_INCLUDES =
SYSTEM_LDFLAGS = -L$(SYSROOT)/usr/lib
SYSTEM_LIBS = -lresolv -lpthread
SYSTEM_LIBS = -lresolv
# 2) System specific capabilities
# Must choose appropriate for the following:

2
makefiles/Makefile.linux Executable file → Normal file
View File

@ -7,7 +7,7 @@
#
SYSTEM_INCLUDES = -Wall -I/usr/X11R6/include
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
SYSTEM_LIBS = -ldl -lpthread
SYSTEM_LIBS = -ldl
# 6) System specific capabilities
# Must choose appropriate for the following:

6
makefiles/Makefile.macosx Executable file → Normal file
View File

@ -8,7 +8,7 @@
SYSTEM_INCLUDES =
SYSTEM_LDFLAGS =
SYSTEM_LIBS = -lresolv -lpcap -lpthread
SYSTEM_LIBS = -lresolv -lpcap
# 2) System specific capabilities
# Must choose appropriate for the following:
@ -44,10 +44,8 @@ SYSTEM_SRC = ../protolib/src/unix/bpfCap.cpp
# The "SYSTEM" keyword can be used for dependent makes
SYSTEM = macosx
# TBD - provide means to build universal Mac OSX library (x86/arm64)
CC = g++
SYSTEM_CFLAGS = -Wall -Wcast-align -fPIC
SYSTEM_CFLAGS = -Wall -Wcast-align -fPIC -arch x86_64 -arch i386
SYSTEM_SOFLAGS = -dynamiclib
SYSTEM_SOEXT = dylib
RANLIB = ranlib

2
makefiles/Makefile.mklinux Executable file → Normal file
View File

@ -9,7 +9,7 @@
SYSTEM_INCLUDES = -I/usr/X11R6/include
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
SYSTEM_LIBS = -ldl -lpthread
SYSTEM_LIBS = -ldl
# 6) System specific capabilities
# Must choose appropriate for the following:

2
makefiles/Makefile.netbsd Executable file → Normal file
View File

@ -7,7 +7,7 @@
#
SYSTEM_INCLUDES = -I/usr/X11R6/include
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
SYSTEM_LIBS = -lpthread
SYSTEM_LIBS =
# 6) System specific capabilities
# Must choose appropriate for the following:

2
makefiles/Makefile.sgi Executable file → Normal file
View File

@ -8,7 +8,7 @@
#
SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333
SYSTEM_LDFLAGS =
SYSTEM_LIBS = -lpthread
SYSTEM_LIBS =
# 6) System specific capabilities
# Must choose appropriate for the following:

2
makefiles/Makefile.solaris Executable file → Normal file
View File

@ -7,7 +7,7 @@
#
SYSTEM_INCLUDES =
SYSTEM_LDFLAGS =
SYSTEM_LIBS = -ldl -lnsl -lsocket -lresolv -lpthread
SYSTEM_LIBS = -ldl -lnsl -lsocket -lresolv
# 2) System specific capabilities
# Must choose appropriate for the following:

Some files were not shown because too many files have changed in this diff Show More