.NET Extension Design Implementation (#10)

* changes

* Removed GetsNextEvent test

* Implemented GetNextEvent

* Fixed NormStream design

* Fixed HasNextEvent design

* Added NormGetNextEvent overload

* Implemented HasNextEvent

* Updated design

* Added Kernel32 to design

* Modified to use .NET EventWaitHandle instead of kernel32 P/Invoke

* Modified to only copy norm.dll on Windows

* Added copy for non Windows

* add start and stop receiver

* add receiver

* Modified non-Windows to use Socket for HasNextEvent

* Deleted NormFileTests since they break the other tests

* Fixed ReceiverReceives test

* Updated ReceiverReceives test name

* Modified ReceivesFile to get all events instead of adding to array

* Cleaned up NormInstance formatting

* Refactored tests

* Updated NormFile

* Implemented send stream

* Implemented receive stream

* Implemented NormFile Name

* Updated ReceivesFile to use events

* data enqueue

* Fixed merge

* Fixed ReceivesData test

* Modified data test to compare collections without order

* stop instance working

* enqueues data

* Reverted upgrade to .NET 7

* Restartinstance is working

* Modified NormData to read bytes instead of as string

* Removed using statements in NormData

* Updated design

* Updated design

* Switched to nint

* Switched design to nint

* unfinished test for suspendinstance

* working suspend instance

* added resume function to instance

* Updated session send and receive data tests

* Removed launch settings

* session configuration functions

* Modified to use random port due to intermittent failed tests due to session conflict

* Modified to randomize text content

* Implemented NormNode Address

* Updated design for NormNode

* Implemented NormNode Grtt

* Implemented NormNode Id

* implement session configuration functions

* instance

* missing return types

* add missing handle param

* normNode

* Implemented RequeueObject

* Implemented SetWatermark and AckingNode

* Implemented CancelWatermark

* Implemented ResetWatermark

* Implemented SendCommand

* Implemented CancelCommand

* Implemented DebugLevel. Removed DebugPipe

* Updated SetTxPort

* Updated SetRxPortReuse

* Implemented SetEcnSupport

* Added test for RxLoss

* Implemented ReportInterval

* Refactored session calculated properties

* Updated enqueue methods

* Updated StreamOpen design

* Fixed SetWatermark overload

* Implemented GetAckingStatus

* Removed SendCommand overload

* Removed SetSilentReceiver overload

* Implemented NormEvent ToString

* Implemented NormFile Rename

* Implemented SetUnicastNack

* Added ReceivesCommand test

* Implemented SetNackingMode

* Implemented SetRepairBoundary

* Added Fact to SetsRepairBoundary test

* Implemented SetRxRobustFactor

* Implemented NormNode Command

* Implemented FreeBuffers

* Implemented Retain and Release

* Fix using namespaces

* test get object type

* NormObject get size

* NormObject setNackingMode

* NormObject get bytes pending

* NormObjet cancel

* NormObject retain

* NormObject release

* NormObject get sender

* NormObject get hashcode

* normObject equals

* Implemented NormObject Equals

* Removed redundant cast

* Removed unused using directive

* Removed static using

* Added NormApi to global Usings

* Added Enums to global usings

* Cleaned up NormObject Equals

* Cleaned up NormObject GetHashCode() test

* Cleaned up warning

* normStream has vacancy

* normStream read offset

* normStream seek msg start

* NormEventListener interface

* normStream set push enable

* normStream set auto flush

* Simplified NormApi usage

* Updated design of NormStream

* public interface

* Fixed INormEventListener

* fixing name space

* commit initializing  inputstream

* Added StreamBreakException

* Fixed formatting

* Fixed formatting

* Fixed formatting

* Initial implementation of NormOutputStream

* Cleaned up NormObject Equals

* NormInputStream class

Co-authored-by: mullerj <mullerj@users.noreply.github.com>

* normStream data offset

* move offset length arithmetic into write method

* building normInputstream

* all method implemented

Co-authored-by: mullerj <mullerj@users.noreply.github.com>

* NormStreamRead

* Fixed build error

* Completed ReceivesStreamWithOffset test

* Added retries to GetsCommand test

* Updated type for NormStreamRead

* Simplified NormStream Read

* Simplified NormStream Write

* Added dataOffset to DataEnqueue

* Fixed DataEnqueue overload

* Added infoOffset to FileEnqueue

* Added infoOffset to StreamOpen

* Updated design

* Removed extra overload of FileEnqueue

* Removed DataEnqueue overloads

* Removed extra overload from StreamOpen

* Added HasNextEvent overload

* Implemented OpenDebugPipe

* add thread locking

* locking for properties

* Not supported exceptions

* Implementing sychronize

* fixing inputstream

* adding sychronize message

* Reorganized NormApi and updated design

* Modified to skip GetsCommand test on IO exception

* WIP: 537b706 adding sychronize message

* adding message to expections

* Fixed test file cleanup

* Added locking to NormSession methods that use static field

* Changed StartsSender to skippablefact

* Changed to SetsNackingMode to skippable fact

* Converted tests to skippable

* Converted more tests to skippable

* Converted all tests that start sender to skippable

* Updated README about skipped tests

* documentation

* 2 doc

* Cleaned up input and output stream classes

* Cleaned up NormApi

* Updated NormOutputStream Write

* Added document comments to NormApi

* Added comments to NormApi

* Removed unnecessary usings

* Added comments to NormApi

* set up the rest of doc

* api documentation

* fix typo

* fix spacing

* Doc for instance need clean up

* clean up

* document norm session

* NormStream documentation

* commit for node

* NormObject docs

* Updated NormApi comments

* Cleaned up NormInstance comments

* Cleaned up NormNode comments

* Cleaned up NormObject comments

* Cleaned up NormSession comments

* Cleaned up NormStream comments

* Cleaned up NormObject comments

* Adding commits

* Update get commit

* clean up on data and event

* Norm Data change

* clean up normfile docs

* clean up normstream

* clean up api docs

* Fixed data

* space approved

* Cleaned up NormData comment

* documentation clean up

* Update the ReadMe

* Cleaned up comments

* Added comments to NormAckingStatus

* Added comments to NormEventType

* Added comments to NormFecType

* Added comments to NormNackingMode

* Added comments to NormObjectType

* Added comments to NormProbingMode

* Added comments to NormRepairBoundary

* Added comments to NormFlushMode

* Added comments to NormSyncPolicy

* Cleaned up comments.  Fixed default for StartSender

* Added comments to constants

* Moved constants to relevant classes

* Updated design

* Removed NormDataDetachData since it is not referenced

* Updated design

* Updated input and output stream design

* Updated packaging README

* Removed language version since redundant

* Cleaned up project file

* Updated to package from the dotnet directory (test project is set to not pack)

* Added version to project

---------

Co-authored-by: syermak <syerm001@odu.edu>
Co-authored-by: Sylvester Freeman III <Slyfreeman3@gmail.com>
Co-authored-by: Sergiy <47069243+SergiyYermak@users.noreply.github.com>
Co-authored-by: mullerj <mullerj@users.noreply.github.com>
pull/85/head
mullerj 2023-03-01 17:05:29 -05:00 committed by GitHub
parent 3a20a8bcb2
commit 26944463e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 6996 additions and 96 deletions

276
.gitignore vendored
View File

@ -18,9 +18,16 @@ norp/makefiles/norp
*.o
*.a
# build java files
*.class
#build android files
android/.gradle
# waf cruft
.waf*
.lock-waf*
waf*/*
# OS generated files #
.DS_Store
@ -30,3 +37,272 @@ norp/makefiles/norp
.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

54
README-DotNet.md Normal file
View File

@ -0,0 +1,54 @@
.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
```

View File

@ -0,0 +1,39 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mil.Navy.Nrl.Norm", "src\Mil.Navy.Nrl.Norm\Mil.Navy.Nrl.Norm.csproj", "{0B38FE25-685E-4ADC-B63D-CA43EC023E1F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A6F15F54-6953-49E7-9394-8F6BF6EF64D0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mil.Navy.Nrl.Norm.IntegrationTests", "tests\Mil.Navy.Nrl.Norm.IntegrationTests\Mil.Navy.Nrl.Norm.IntegrationTests.csproj", "{E5CDA4C5-C1A1-4AD7-B10D-80B8A995FC49}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{8B6C912C-2A15-41F3-B3A4-E9C01E6672DE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0B38FE25-685E-4ADC-B63D-CA43EC023E1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B38FE25-685E-4ADC-B63D-CA43EC023E1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B38FE25-685E-4ADC-B63D-CA43EC023E1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B38FE25-685E-4ADC-B63D-CA43EC023E1F}.Release|Any CPU.Build.0 = Release|Any CPU
{E5CDA4C5-C1A1-4AD7-B10D-80B8A995FC49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5CDA4C5-C1A1-4AD7-B10D-80B8A995FC49}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5CDA4C5-C1A1-4AD7-B10D-80B8A995FC49}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5CDA4C5-C1A1-4AD7-B10D-80B8A995FC49}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0B38FE25-685E-4ADC-B63D-CA43EC023E1F} = {A6F15F54-6953-49E7-9394-8F6BF6EF64D0}
{E5CDA4C5-C1A1-4AD7-B10D-80B8A995FC49} = {8B6C912C-2A15-41F3-B3A4-E9C01E6672DE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8BC1F27F-D633-4B45-A16D-D112CB08840E}
EndGlobalSection
EndGlobal

View File

@ -1,6 +1,6 @@
@startuml
enum NormNackingMode {
ORM_NACK_NONE
NORM_NACK_NONE
NORM_NACK_INFO_ONLY
NORM_NACK_NORMAL
}

View File

@ -28,6 +28,15 @@ class NormInputStream {
+ Read() : int
+ <<override>> Read(buffer:byte[], offset:int, length:int) : int
- ProcessEvent() : void
+ <<override>> Flush() : void
+ <<override>> Write(buffer:byte[], offset:int, count:int) : void
+ <<override>> Seek(offset:long, origin:SeekOrigin) : long
+ <<override>> SetLength(value:long) : void
+ <<override>> CanRead : bool <<get>>
+ <<override>> CanSeek : bool <<get>>
+ <<override>> CanWrite : bool <<get>>
+ <<override>> Length : long <<get>>
+ <<override>> Position : long <<get>> <<set>>
}
Stream <|-- NormInputStream
@enduml

View File

@ -17,7 +17,7 @@ class NormOutputStream {
+ SetTtl(ttl:byte) : void
+ SetTos(tos:byte) : void
+ SetCongestionControl(ccEnabled:bool, ccAdjustRate: bool) : void
+ SetTxRateBounds(rateMin:double, rateMax:double) : void
+ SetTxRateBounds(minTxRate:double, maxTxRate:double) : void
+ TxRate:double <<get>> <<set>>
+ GrttEstimate:double <<get>> <<set>>
+ SetGroupSize(groupSize:long) : void
@ -30,11 +30,20 @@ class NormOutputStream {
+ RemoveNormEventListener(normEventListener:INormEventListener): void
- FireNormEventOccured(normEvent:NormEvent) : void
+ Open(sessionId:int, bufferSpace:long, segmentSize:int, blockSize:short, numParity:short, repairWindow:long) : void
+ <<override>> Dispose() : void
+ <<override>> Close() : void
+ IsClosed : bool <<get>>
+ Write(b:int) : void
+ <<override>> Write(buffer:byte[], offset:int, count:int)
- ProcessEvent() : void
+ <<override>> Flush() : void
+ <<override>> Read(buffer:byte[], offset:int, length:int) : int
+ <<override>> Seek(offset:long, origin:SeekOrigin) : long
+ <<override>> SetLength(value:long) : void
+ <<override>> CanRead : bool <<get>>
+ <<override>> CanSeek : bool <<get>>
+ <<override>> CanWrite : bool <<get>>
+ <<override>> Length : long <<get>>
+ <<override>> Position : long <<get>> <<set>>
}
Stream <|-- NormOutputStream
@enduml

View File

@ -1,11 +1,14 @@
@startuml
struct NormEvent
{
+ Type : NormEventType
+ Session : long
+ Sender : long
+ Object : long
}
class NormApi
{
+ <<const>> NORM_OBJECT_INVALID : int = 0
+ <<const>> FILENAME_MAX : int = 260
+ <<const>> NORM_LIBRARY : string = "norm"
+ {static} NormGetVersion(major:int, minor:int, patch:int) : int
+ {static} NormCreateInstance() : long
+ {static} NormCreateInstance(priorityBoost:bool) : long
+ {static} NormDestroyInstance(instanceHandle:long) : void
+ {static} NormStopInstance(instanceHandle:long) : void
@ -13,63 +16,36 @@ class NormApi
+ {static} NormSuspendInstance(instanceHandle:long) : bool
+ {static} NormResumeInstance(instanceHandle:long) : void
+ {static} NormSetCacheDirectory(instanceHandle:long, cachePath:string) : bool
+ {static} NormGetNextEvent(instanceHandle:long, theEvent:NormEvent) : bool
+ {static} NormGetNextEvent(instanceHandle:long, theEvent:NormEvent, waitForEvent:bool) : bool
+ {static} NormGetDescriptor(instanceHandle:long) : NormDescriptor
+ {static} NormGetDescriptor(instanceHandle:long) : int
+ {static} NormCreateSession(instanceHandle:long, sessionAddress:string, sessionPort:int, localNodeId:long) : long
+ {static} NormDestroySession(sessionHandle:long) : void
+ {static} NormGetInstance(sessionHandle:long) : long
+ {static} NormIsUnicastAddress(address:string) : bool
+ {static} NormSetUserTimer(sessionHandle:long, seconds:double) : void
+ {static} NormCancelUserTimer(sessionHandle:long) : void
+ {static} NormGetLocalNodeId(sessionHandle:long) : long
+ {static} NormGetAddress(sessionHandle:long, addrBuffer:string, bufferLen:uint) : bool
+ {static} NormGetAddress(sessionHandle:long, addrBuffer:string, bufferLen:uint, port:ushort) : bool
+ {static} NormGetRxPort(sessionHandle:long) : ushort
+ {static} NormSetTxPort(sessionHandle:long, txPortNumber:ushort) : bool
+ {static} NormSetTxPort(sessionHandle:long, txPortNumber:ushort, enableReuse:bool, txBindAddress:string) : bool
+ {static} NormGetTxPort(sessionHandle:long) : ushort
+ {static} NormSetTxOnly(sessionHandle:long, txOnly:bool) : void
+ {static} NormSetTxPort(sessionHandle:long, txPortNumber:int, enableReuse:bool, txBindAddress:string) : bool
+ {static} NormSetTxOnly(sessionHandle:long, txOnly:bool, connectToSessionAddress:bool) : void
+ {static} NormLimitObjectInfo(sessionHandle:long, state:bool) : void
+ {static} NormPresetObjectInfo(sessionHandle:long, objectSize:ulong, segmentSize:ushort, numData:ushort, numParity:ushort) : bool
+ {static} NormSetId(sessionHandle:long, normId:long) : void
+ {static} NormChangeDestination(sessionHandle:long, sessionAddress:string, sessionPort:ushort) : bool
+ {static} NormChangeDestination(sessionHandle:long, sessionAddress:string, sessionPort:ushort, connectToSessionAddress:bool) : bool
+ {static} NormSetServerListner(sessionHandle:long, state:bool) : void
+ {static} NormTransferSender(sessionHandle:long, sender:long) : bool
+ {static} NormSetRxPortReuse(sessionHandle:long, enableReuse:bool) : void
+ {static} NormSetRxPortReuse(sessionHandle:long, enableReuse:bool, rxBindAddress:string, senderAddress:string, senderPort:ushort) : void
+ {static} NormGetRxBindAddress(sessionHandle:long, addr:string, addrLen:uint, port:ushort) : bool
+ {static} NormSetEcnSupport(sessionHandle:long, ecnEnable:bool) : void
+ {static} NormSetRxPortReuse(sessionHandle:long, enableReuse:bool, rxBindAddress:string, senderAddress:string, senderPort:int) : void
+ {static} NormSetEcnSupport(sessionHandle:long, ecnEnable:bool, ignoreLoss:bool, tolerateLoss:bool) : void
+ {static} NormSetMulticastInterface(sessionHandle:long, interfaceName:string) : bool
+ {static} NormSetSSM(sessionHandle:long, sourceAddress:string) : bool
+ {static} NormSetTTL(sessionHandle:long, ttl:byte) : bool
+ {static} NormSetTOS(sessionHandle:long, tos:byte) : bool
+ {static} NormSetLoopback(sessionHandle:long, loopback:bool) : bool
+ {static} NormSetMulticastLoopback(sessionHandle:long, loopback:bool) : bool
+ {static} NormSetFragmentation(sessionHandle:long, fragmentation:bool) : bool
+ {static} NormSetMessageTrace(sessionHandle:long, state:bool) : void
+ {static} NormSetTxLoss(sessionHandle:long, precent:double) : void
+ {static} NormSetRxLoss(sessionHandle:long, precent:double) : void
+ {static} NormOpenDebugLog(instanceHandle:long, path:string) : bool
+ {static} NormCloseDebugLog(instanceHandle:long) : void
+ {static} NormOpenDebugPipe(instanceHandle:long, pipeName:string) : bool
+ {static} NormCloseDebugPipe(instanceHandle:long) : void
+ {static} NormSetDebugLevel(level:int) : void
+ {static} NormGetDebugLevel() : int
+ {static} NormSetReportInterval(sessionHandle:long, interval:double) : void
+ {static} NormGetReportInterval(sessionHandle:long) : double
+ {static} NormGetRandomSessionId() : int
+ {static} NormStartSender(sessionHandle:long, instanceId:int, bufferSpace:long, segmentSize:int, numData:short, numParity:short) : bool
+ {static} NormStartSender(sessionHandle:long, instanceId:int, bufferSpace:long, segmentSize:int, numData:short, numParity:short, fecId:NormFecType) : bool
+ {static} NormStopSender(sessionHandle:long) : void
+ {static} NormSetTxRate(sessionHandle:long, bitsPerSecond:double) : void
+ {static} NormGetTxRate(sessionHandle:long) : double
+ {static} NormSetTxSocketBuffer(sessionHandle:long, bufferSize:uint) : bool
+ {static} NormSetTxSocketBuffer(sessionHandle:long, bufferSize:long) : bool
+ {static} NormSetFlowControl(sessionHandle:long, flowControlFactor:double) : void
+ {static} NormSetCongestionControl(sessionHandle:long, enable:bool) : void
+ {static} NormSetCongestionControl(sessionHandle:long, enable:bool, adjustRate:bool) : void
+ {static} NormSetTxRateBounds(sessionHandle:long, rateMin:double, rateMax:double) : void
+ {static} NormSetTxCacheBounds(sessionHandle:long, sizeMax:long, countMin:long, countMax:long) : void
@ -79,52 +55,32 @@ class NormApi
+ {static} NormSetGrttMax(sessionHandle:long, grttMax:double) : void
+ {static} NormSetGrttProbingMode(sessionHandle:long, probingMode:NormProbingMode) : void
+ {static} NormSetGrttProbingInterval(sessionHandle:long, intervalMin:double, intervalMax:double) : void
+ {static} NormSetGrttProbingTOS(sessionHandle:long, probeTOS:byte) : void
+ {static} NormSetBackoffFactor(sessionHandle:long, backoffFactor:double) : void
+ {static} NormSetGroupSize(sessionHandle:long, groupSize:uint) : void
+ {static} NormSetGroupSize(sessionHandle:long, groupSize:long) : void
+ {static} NormSetTxRobustFactor(sessionHandle:long, robustFactor:int) : void
+ {static} NormFileEnqueue(sessionHandle:long, fileName:string): long
+ {static} NormFileEnqueue(sessionHandle:long, fileName:string, infoPtr:string, infoLen:int): long
+ {static} NormDataEnqueue(sessionHandle:long, dataPtr:string, dataLen:int) : long
+ {static} NormDataEnqueue(sessionHandle:long, dataPtr:string, dataLen:int, infoPtr:string, infoLen:int) : long
+ {static} NormDataEnqueue(sessionHandle:long, dataPtr:byte[], dataLen:int, infoPtr:byte[], infoLen:int) : long
+ {static} NormRequeueObject(sessionHandle:long, objectHandle:long) : bool
+ {static} NormStreamOpen(sessionHandle:long, bufferSize:long) : long
+ {static} NormStreamOpen(sessionHandle:long, bufferSize:long, infoPtr:string, infoLen:int) : long
+ {static} NormStreamClose(streamHandle:long) : void
+ {static} NormStreamClose(streamHandle:long, graceful:bool) : void
+ {static} NormGetStreamBufferSegmentCount(bufferBytes:uint, segmentSize:ushort, blockSize:ushort) : uint
+ {static} NormStreamWrite(streamHandle:long, buffer:string, numBytes:uint) : uint
+ {static} NormStreamFlush(streamHandle:long) : void
+ {static} NormStreamWrite(streamHandle:long, buffer:byte[], numBytes:int) : int
+ {static} NormStreamFlush(streamHandle:long, eom:bool, flushMode:NormFlushMode) : void
+ {static} NormStreamSetAutoFlush(streamHandle:long, flushMode: NormFlushMode) : void
+ {static} NormStreamSetPushEnable(streamHandle:long, pushEnable:bool) : void
+ {static} NormStreamHasVacancy(streamHandle:long) : bool
+ {static} NormStreamGetVacancy(streamHandle:long, bytesWanted:uint) : uint
+ {static} NormStreamMarkEom(streamHandle:long) : void
+ {static} NormSetWatermark(sessionHandle:long, objectHandle:long) : bool
+ {static} NormSetWatermark(sessionHandle:long, objectHandle:long, overrideFlush:bool) : bool
+ {static} NormSetWatermarkEx(sessionHandle:long, objectHandle:long, buffer:string, numBytes:uint) : bool
+ {static} NormSetWatermarkEx(sessionHandle:long, objectHandle:long, buffer:string, numBytes:uint, overrideFlush:bool) : bool
+ {static} NormResetWatermark(sessionHandle:long) : bool
+ {static} NormCancelWatermark(sessionHandle:long) : void
+ {static} NormAddAckingNode(sessionHandle:long, nodeId:long) : bool
+ {static} NormRemoveAckingNode(sessionHandle:long, nodeId:long) : void
+ {static} NormGetAckingNodeHandle(sessionHandle:long, nodeId:long) : long
+ {static} NormSetAutoAckingNodes(sessionHandle:long, trackingStatus:NormTrackingStatus) : void
+ {static} NormGetAckingStatus(sessionHandle:long) : NormAckingStatus
+ {static} NormGetAckingStatus(sessionHandle:long, nodeId:long) : NormAckingStatus
+ {static} NormGetNextAckingNode(sessionHandle:long, nodeId:long) : bool
+ {static} NormGetNextAckingNode(sessionHandle:long, nodeId:long, ackingStatus:NormAckingStatus) : bool
+ {static} NormGetAckEx(sessionHandle:long, nodeId:long, buffer:string, buflen:uint) : bool
+ {static} NormSendCommand(sessionHandle:long, cmdBuffer:string, cmdLength:uint) : bool
+ {static} NormSendCommand(sessionHandle:long, cmdBuffer:string, cmdLength:uint, robust:bool) : bool
+ {static} NormSendCommand(sessionHandle:long, cmdBuffer:byte[], cmdLength:int, robust:bool) : bool
+ {static} NormCancelCommand(sessionHandle:long) : void
+ {static} NormSetSynStatus(sessionHandle:long, state:bool) : void
+ {static} NormStartReceiver(sessionHandle:long, bufferSpace:long) : bool
+ {static} NormStopReceiver(sessionHandle:long) : void
+ {static} NormSetRxCacheLimit(sessionHandle:long, countMax:ushort) : void
+ {static} NormSetRxSocketBuffer(sessionHandle:long, bufferSize:uint) : bool
+ {static} NormSetSilentReceiver(sessionHandle:long, silent:bool) : void
+ {static} NormSetRxCacheLimit(sessionHandle:long, countMax:int) : void
+ {static} NormSetRxSocketBuffer(sessionHandle:long, bufferSize:long) : bool
+ {static} NormSetSilentReceiver(sessionHandle:long, silent:bool, maxDelay:int) : void
+ {static} NormSetDefaultUnicastNack(sessionHandle:long, unicastNacks:bool) : void
+ {static} NormNodeSetUnicastNack(remoteSender:long, unicastNacks:bool) : void
@ -135,17 +91,14 @@ class NormApi
+ {static} NormSetDefaultRepairBoundary(sessionHandle:long, repairBoundary:NormRepairBoundary) : void
+ {static} NormNodeSetRepairBoundary(remoteSender:long, repairBoundary:NormRepairBoundary) : void
+ {static} NormSetDefaultRxRobustFactor(sessionHandle:long, robustFactor:int) : void
+ {static} NormNodeSetRxRobustFactor(remoteSenderremoteSender, robustFactor:int) : void
+ {static} NormPreallocateRemoteSender(sessionHandle:long, bufferSize:ulong, segmentSize:ushort, numData:ushort, numParity:ushort) : bool
+ {static} NormPreallocateRemoteSender(sessionHandle:long, bufferSize:ulong, segmentSize:ushort, numData:ushort, numParity:ushort, streamBufferSize:uint) : bool
+ {static} NormStreamRead(streamHandle:long, buffer:string, numBytes:uint) : bool
+ {static} NormNodeSetRxRobustFactor(remoteSender:long, robustFactor:int) : void
+ {static} NormStreamRead(streamHandle:long, buffer:byte[], numBytes:int) : bool
+ {static} NormStreamSeekMsgStart(streamHandle:long) : bool
+ {static} NormStreamGetReadOffset(streamHandle:long) : uint
+ {static} NormStreamGetBufferUsage(streamHandle:long) : uint
+ {static} NormStreamGetReadOffset(streamHandle:long) : long
+ {static} NormObjectGetType(objectHandle:long) : NormObjectType
+ {static} NormObjectHasInfo(objectHandle:long) : bool
+ {static} NormObjectGetInfoLength(objectHandle:long) : ushort
+ {static} NormObjectGetInfo(objectHandle:long, buffer:char, bufferLen:ushort) : ushort
+ {static} NormObjectGetInfoLength(objectHandle:long) : int
+ {static} NormObjectGetInfo(objectHandle:long, buffer:byte[], bufferLen:int) : int
+ {static} NormObjectGetSize(objectHandle:long) : int
+ {static} NormObjectGetBytesPending(objectHandle:long) : int
+ {static} NormObjectCancel(objectHandle:long) : void
@ -153,24 +106,14 @@ class NormApi
+ {static} NormObjectRelease(objectHandle:long) : void
+ {static} NormFileGetName(fileHandle:long, nameBuffer:string, bufferLen:int) : bool
+ {static} NormFileRename(fileHandle:long, fileName:string) : bool
+ {static} NormDataAccessData(objectHandle:long) : string
+ {static} NormDataDetachData(objectHandle:long) : string
+ {static} NormDataAccessData(objectHandle:long) : nint
+ {static} NormObjectGetSender(objectHandle:long) : long
+ {static} NormNodeGetId(nodeHandle:long) : uint
+ {static} NormNodeGetAddress(nodeHandle:long, addrBuffer:string, bufferLen: uint) : bool
+ {static} NormNodeGetAddress(nodeHandle:long, addrBuffer:string, bufferLen: uint, port:ushort) : bool
+ {static} NormNodeGetId(nodeHandle:long) : long
+ {static} NormNodeGetAddress(nodeHandle:long, addrBuffer:byte[], bufferLen: int, port:int) : bool
+ {static} NormNodeGetGrtt(remoteSender:long) : double
+ {static} NormNodeGetCommand(remoteSender:long, :string, buflen:uint) : bool
+ {static} NormNodeSendAckEx(remoteSender:long, buffer:string, numBytes:uint) : bool
+ {static} NormNodeGetWatermarkEx(remoteSender:long, buffer:string, buflen:uint) : bool
+ {static} NormNodeGetCommand(remoteSender:long, buffer:byte[], buflen:int) : bool
+ {static} NormNodeFreeBuffers(remoteSender:long) : void
+ {static} NormNodeDelete(remoteSender:long) : void
+ {static} NormNodeRetain(nodeHandle:long) : void
+ {static} NormNodeRelease(nodeHandle:long) : void
+ {static} NormReleasePreviousEvent(instanceHandle:long) : void
+ {static} NormCountCompletedObjects(sessionHandle:long) : uint
+ {static} NormNodeSetAutoDelete(remoteSender:long, autoDelete:bool) : void
+ {static} NormNodeAllowSender(senderId:long) : bool
+ {static} NormNodeDenySender(senderId:long) : bool
}
@enduml

View File

@ -1,5 +1,6 @@
@startuml
class NormFile {
+ <<const>> FILENAME_MAX : int = 260
~ NormFile(handle:long)
+ Name : string <<get>>
+ Rename(filename:string) : void

View File

@ -1,5 +1,6 @@
@startuml
class NormInstance {
+ <<const>> NORM_DESCRIPTOR_INVALID : int = 0
- _handle: long
+ NormInstance()
+ NormInstance(priorityBoost:bool)
@ -14,7 +15,9 @@ class NormInstance {
+ CloseDebugLog() : void
+ OpenDebugPipe(pipename:string) : void
+ DebugLevel: int <<get>> <<set>>
+ HasNextEvent(sec:int, usec:int) : boolean
+ HasNextEvent(sec:int, usec:int) : bool
+ HasNextEvent(waitTime:TimeSpan) : bool
+ GetNextEvent(waitForEvent:bool) : NormEvent
+ GetNextEvent() : NormEvent
+ CreateSession(address:string, port:int, localNodeId:long) : NormSession
}

View File

@ -1,6 +1,8 @@
@startuml
class NormNode {
+ <<const>> NORM_NODE_ANY : long = 0xffffffff
+ <<const>> NORM_NODE_NONE : int = 0
+ <<const>> NORM_NODE_INVALID : int = 0
- _handle : long
~ NormNode(handle:long)
+ SetUnicastNack(state:bool) : void
@ -8,9 +10,9 @@ class NormNode {
+ SetRepairBoundary(repairBoundary:NormRepairBoundary) : void
+ SetRxRobustFactor(robustFactor:int) : void
+ Id : long <<get>>
+ Address : SocketAddress <<get>>
+ Address : IPEndPoint <<get>>
+ Grtt : double <<get>>
+ GetCommand(buffer:byte[], offset:int, length:int) : int
+ Command : byte[] <<get>>
+ FreeBuffers() : void
+ Retain() : void
+ Release(): void

View File

@ -1,5 +1,6 @@
@startuml
class NormObject {
+ <<const>> NORM_OBJECT_INVALID : int = 0
# _handle:long
~ NormObject(handle:long)
+ SetNackingMode(nackingMode:NormNackingMode) : void

View File

@ -1,5 +1,6 @@
@startuml
class NormSession {
+ <<const>> NORM_SESSION_INVALID : int = 0
{static} -_normSessions : Dictionary<long, NormSession>
- _handle : long
~ NormSession(handle:long)
@ -22,8 +23,10 @@ class NormSession {
+ SetTxLoss(precent:double) : void
+ SetRxLoss(precent:double) : void
+ ReportInterval: double <<get>> <<set>>
+ StartSender(sessionId:int, bufferSpace:long, segmentSize:int, blockSize:short, numParity:short) : void
+ StartSender(sessionId:int, bufferSpace:long, segmentSize:int, blockSize:short, numParity:short, fecId:NormFecType) : void
+ StartSender(sessionId:int, bufferSpace:long, segmentSize:int, blockSize:short, numParity:short) : void
+ StartSender(bufferSpace:long, segmentSize:int, blockSize:short, numParity:short, fecId:NormFecType) : void
+ StartSender(bufferSpace:long, segmentSize:int, blockSize:short, numParity:short) : void
+ StopSender() : void
+ SetTxOnly(txOnly:bool) : void
+ TxRate:double <<get>> <<set>>
@ -43,11 +46,12 @@ class NormSession {
+ SetTxRobustFactor(robustFactor:int) : void
+ FileEnqueue(filename:string) : NormFile
+ FileEnqueue(filename:string, info:byte[], infoOffset:int, infoLength:int) : NormFile
+ DataEnqueue(dataBuffer:MemoryStream, dataOffset:int, dataLength:int) : NormData
+ DataEnqueue(dataBuffer:MemoryStream, dataOffset:int, dataLength:int, info:byte[], infoOffset:int, infoLength:int) : NormData
+ DataEnqueue(dataBuffer:byte[], dataLength:int) : NormData
+ DataEnqueue(dataBuffer:byte[], dataOffset:int, dataLength:int, info:byte[], infoOffset:int, infoLength:int) : NormData
+ RequeueObject(object:NormObject) : void
+ StreamOpen(bufferSize:long) : NormStream
+ StreamOpen(bufferSize:long, info:byte[], infoOffset:int, infoLength:int) : NormStream
+ SetWatermark(object:NormObject) : void
+ SetWatermark(object:NormObject, overrideFlush:bool) : void
+ CancelWatermark() : void
+ ResetWatermark() : void

View File

@ -14,4 +14,5 @@ class NormStream {
+ SeekMsgStart() : bool
+ ReadOffset : long <<get>>
}
NormObject <|-- NormStream
@enduml

View File

@ -7,7 +7,7 @@ Client <- NormInstance : NormInstance
Client -> NormInstance : CreateSession(address, port, localNodeId)
NormInstance -> NormApi : NormCreateSession(instanceHandle, address, port, localNodeId)
NormInstance <- NormApi : sessionHandle
alt sessionHandle == NORM_SESSION_INVALID
alt sessionHandle == NormApi.NORM_SESSION_INVALID
NormInstance -> IOException : throw new("Failed to create session")
end
NormInstance -> NormSession : new(sessionHandle)
@ -30,9 +30,9 @@ end
NormSession -> NormFile: new(objectHandle)
NormSession <- NormFile : NormFile
Client <- NormSession : NormFile
loop NormEvent != null
Client -> NormInstance : GetNextEvent()
NormInstance -> NormApi : NormGetNextEvent(instanceHandle, NormEvent)
loop NormInstance.HasNextEvent(waitTime)
Client -> NormInstance : GetNextEvent(false)
NormInstance -> NormApi : NormGetNextEvent(instanceHandle, NormEvent, false)
NormInstance <- NormApi : success
alt success == false
Client <- NormInstance : null

View File

@ -0,0 +1,28 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The status of the watermark flushing process and/or positive acknowledgment collection.
/// </summary>
public enum NormAckingStatus
{
/// <summary>
/// The given sessionHandle is invalid or the given nodeId is not in the sender's acking list.
/// </summary>
NORM_ACK_INVALID,
/// <summary>
/// The positive acknowledgement collection process did not receive acknowledgment from every
/// listed receiver (nodeId = NORM_NODE_ANY) or the identified nodeId did not respond.
/// </summary>
NORM_ACK_FAILURE,
/// <summary>
/// The flushing process at large has not yet completed (nodeId = NORM_NODE_ANY) or the given
/// individual nodeId is still being queried for response.
/// </summary>
NORM_ACK_PENDING,
/// <summary>
/// All receivers (nodeId = NORM_NODE_ANY) responded with positive acknowledgement or the given
/// specific nodeId did acknowledge.
/// </summary>
NORM_ACK_SUCCESS
}
}

View File

@ -0,0 +1,194 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The type identifies the event with one of NORM protocol events.
/// </summary>
public enum NormEventType
{
/// <summary>
/// This NormEventType indicates an invalid or "null" notification which should be ignored.
/// </summary>
NORM_EVENT_INVALID,
/// <summary>
/// This event indicates that there is room for additional transmit objects to be enqueued, or,
/// if the handle of NORM_OBJECT_STREAM is given in the corresponding
/// event "object" field, the application may successfully write to the indicated stream
/// object. Note this event is not dispatched until a call to NormFileEnqueue(),
/// NormDataEnqueue(), or NormStreamWrite() fails because of a filled transmit
/// cache or stream buffer.
/// </summary>
NORM_TX_QUEUE_VACANCY,
/// <summary>
/// This event indicates the NORM protocol engine has no new data pending transmission
/// and the application may enqueue additional objects for transmission.
/// If the handle of a sender NORM_OBJECT_STREAM is given in the corresponding event
/// "object" field, this indicates the stream transmit buffer has been emptied and the
/// sender application may write to the stream (Use of NORM_TX_QUEUE_VACANCY may
/// be preferred for this purpose since it allows the application to keep the NORM
/// protocol engine busier sending data, resulting in higher throughput when attempting
/// very high transfer rates).
/// </summary>
NORM_TX_QUEUE_EMPTY,
/// <summary>
/// This event indicates that the flushing process the NORM sender observes when
/// it no longer has data ready for transmission has completed. The completion of the
/// flushing process is a reasonable indicator (with a sufficient NORM "robust factor"
/// value) that the receiver set no longer has any pending repair requests. Note the
/// use of NORM's optional positive acknowledgement feature is more deterministic
/// in this regards, but this notification is useful when there are non-acking (NACK-only)
/// receivers. The default NORM robust factor of 20 (20 flush messages are
/// sent at end-of-transmission) provides a high assurance of reliable transmission,
/// even with packet loss rates of 50%.
/// </summary>
NORM_TX_FLUSH_COMPLETED,
/// <summary>
/// This event indicates that the flushing process initiated by a prior application call
/// to NormSetWatermark() has completed. The posting of this event indicates the
/// appropriate time for the application to make a call NormGetAckingStatus() to
/// determine the results of the watermark flushing process.
/// </summary>
NORM_TX_WATERMARK_COMPLETED,
/// <summary>
/// This event indicates that an application-defined command previously enqueued
/// with a call to NormSendCommand() has been transmitted, including any repetition.
/// </summary>
NORM_TX_CMD_SENT,
/// <summary>
/// This event indicates that the transport object referenced by the event's "object"
/// field has completed at least one pass of total transmission. Note that this does not
/// guarantee that reliable transmission has yet completed; only that the entire object
/// content has been transmitted. Depending upon network behavior, several rounds
/// of NACKing and repair transmissions may be required to complete reliable transfer.
/// </summary>
NORM_TX_OBJECT_SENT,
/// <summary>
/// This event indicates that the NORM protocol engine will no longer refer to the
/// transport object identified by the event's "object" field. Typically, this will occur
/// when the application has enqueued more objects than space available within the
/// set sender transmit cache bounds. Posting of this notification means the application is
/// free to free any resources (memory, files, etc) associated with the indicated "object".
/// After this event, the given "object" handle (NormObjectHandle) is no longer valid unless
/// it is specifically retained by the application.
/// </summary>
NORM_TX_OBJECT_PURGED,
/// <summary>
/// This event indicates that NORM Congestion Control operation has adjusted the
/// transmission rate. The NormGetTxRate() call may be used to retrieve the new
/// corresponding transmission rate. Note that if NormSetCongestionControl() was
/// called with its adjustRate parameter set to false, then no actual rate change has
/// occurred and the rate value returned by NormGetTxRate() reflects a "suggested"
/// rate and not the actual transmission rate.
/// </summary>
NORM_TX_RATE_CHANGED,
/// <summary>
/// This event is posted when the NORM protocol engine completes the "graceful
/// shutdown" of its participation as a sender in the indicated "session".
/// </summary>
NORM_LOCAL_SENDER_CLOSED,
/// <summary>
/// This event is posted when a receiver first receives messages from a specific remote
/// NORM sender. This marks the beginning of the interval during which the application
/// may reference the provided "node" handle (NormNodeHandle).
/// </summary>
NORM_REMOTE_SENDER_NEW,
/// <summary>
/// Remote sender instanceId or FEC params changed.
/// </summary>
NORM_REMOTE_SENDER_RESET,
/// <summary>
/// Remote sender src addr and/or port changed.
/// </summary>
NORM_REMOTE_SENDER_ADDRESS,
/// <summary>
/// This event is posted when a previously inactive (or new) remote sender is detected
/// operating as an active sender within the session.
/// </summary>
NORM_REMOTE_SENDER_ACTIVE,
/// <summary>
/// This event is posted after a significant period of inactivity (no sender messages
/// received) of a specific NORM sender within the session. The NORM protocol
/// engine frees buffering resources allocated for this sender when it becomes inactive.
/// </summary>
NORM_REMOTE_SENDER_INACTIVE,
/// <summary>
/// This event is posted when the NORM protocol engine frees resources for, and
/// thus invalidates the indicated "node" handle.
/// </summary>
NORM_REMOTE_SENDER_PURGED,
/// <summary>
/// This event indicates that an application-defined command has been received from
/// a remote sender. The NormEvent node element indicates the NormNodeHandle
/// value associated with the given sender. The NormNodeGetCommand() call can be
/// used to retrieve the received command content.
/// </summary>
NORM_RX_CMD_NEW,
/// <summary>
/// This event is posted when reception of a new transport object begins and marks
/// the beginning of the interval during which the specified "object" (NormObjectHandle)
/// is valid.
/// </summary>
NORM_RX_OBJECT_NEW,
/// <summary>
/// This notification is posted when the NORM_INFO content for the indicated "object" is received.
/// </summary>
NORM_RX_OBJECT_INFO,
/// <summary>
/// This event indicates that the identified receive "object" has newly received data content.
/// </summary>
NORM_RX_OBJECT_UPDATED,
/// <summary>
/// This event is posted when a receive object is completely received, including
/// available NORM_INFO content. Unless the application specifically retains the "object"
/// handle, the indicated NormObjectHandle becomes invalid and must no longer be
/// referenced.
/// </summary>
NORM_RX_OBJECT_COMPLETED,
/// <summary>
/// This notification is posted when a pending receive object's transmission is aborted
/// by the remote sender. Unless the application specifically retains the "object"
/// handle, the indicated NormObjectHandle becomes invalid and must no longer be
/// referenced.
/// </summary>
NORM_RX_OBJECT_ABORTED,
/// <summary>
/// Upon receipt of app-extended watermark ack request.
/// </summary>
NORM_RX_ACK_REQUEST,
/// <summary>
/// This notification indicates that either the local sender estimate of GRTT has
/// changed, or that a remote sender's estimate of GRTT has changed. The "sender"
/// member of the NormEvent is set to NORM_NODE_INVALID if the local sender's
/// GRTT estimate has changed or to the NormNodeHandle of the remote sender that
/// has updated its estimate of GRTT
/// </summary>
NORM_GRTT_UPDATED,
/// <summary>
/// This event indicates that congestion control feedback from receivers has begun
/// to be received (This also implies that receivers in the group are actually present
/// and can be used as a cue to begin data transmission.). Note that congestion control
/// must be enabled for this event to be posted.
/// Congestion control feedback can be assumed to be received until a NORM_CC_INACTIVE event is posted.
/// </summary>
NORM_CC_ACTIVE,
/// <summary>
/// This event indicates there has been no recent congestion control feedback received
/// from the receiver set and that the local NORM sender has reached its minimum
/// transmit rate. Applications may wish to refrain from new data transmission until
/// a NORM_CC_ACTIVE event is posted. This notification is only posted when congestion
/// control operation is enabled and a previous NORM_CC_ACTIVE event has occurred.
/// </summary>
NORM_CC_INACTIVE,
/// <summary>
/// When NormSetAutoAcking.
/// </summary>
NORM_ACKING_NODE_NEW,
/// <summary>
/// ICMP error (e.g. destination unreachable).
/// </summary>
NORM_SEND_ERROR,
/// <summary>
/// Issues when timeout set by NormSetUserTimer() expires.
/// </summary>
NORM_USER_TIMEOUT
}
}

View File

@ -0,0 +1,21 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The valid FEC Types.
/// </summary>
public enum NormFecType
{
/// <summary>
/// Fully-specified, general purpose Reed-Solomon.
/// </summary>
RS,
/// <summary>
/// Fully-specified 8-bit Reed-Solmon per RFC 5510.
/// </summary>
RS8,
/// <summary>
/// Partially-specified "small block" codes.
/// </summary>
SB
}
}

View File

@ -0,0 +1,22 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The possible flush modes.
/// </summary>
public enum NormFlushMode
{
/// <summary>
/// No flushing occurs unless explicitly requested via NormStreamFlush().
/// </summary>
NORM_FLUSH_NONE,
/// <summary>
/// Causes NORM to immediately transmit all enqueued data for the stream (subject to session transmit rate limits),
/// even if this results in NORM_DATA messages with "small" payloads.
/// </summary>
NORM_FLUSH_PASSIVE,
/// <summary>
/// The sender actively transmits NORM_CMD(FLUSH) messages after any enqueued stream content has been sent.
/// </summary>
NORM_FLUSH_ACTIVE
}
}

View File

@ -0,0 +1,21 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The available nacking modes.
/// </summary>
public enum NormNackingMode
{
/// <summary>
/// Do not transmit any repair requests for the newly received object.
/// </summary>
NORM_NACK_NONE,
/// <summary>
/// Transmit repair requests for NORM_INFO content only as needed.
/// </summary>
NORM_NACK_INFO_ONLY,
/// <summary>
/// Transmit repair requests for entire object as needed.
/// </summary>
NORM_NACK_NORMAL
}
}

View File

@ -0,0 +1,25 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The possible NORM data transport object types.
/// </summary>
public enum NormObjectType
{
/// <summary>
/// A special NormObjectType value, NORM_OBJECT_NONE, indicates an invalid object type.
/// </summary>
NORM_OBJECT_NONE,
/// <summary>
/// A transport object of type NORM_OBJECT_DATA.
/// </summary>
NORM_OBJECT_DATA,
/// <summary>
/// A transport object of type NORM_OBJECT_FILE.
/// </summary>
NORM_OBJECT_FILE,
/// <summary>
/// A transport object of type NORM_OBJECT_STREAM.
/// </summary>
NORM_OBJECT_STREAM
}
}

View File

@ -0,0 +1,24 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The possible probing modes.
/// </summary>
public enum NormProbingMode
{
/// <summary>
/// The sender application must explicitly set its estimate of GRTT using the NormSetGrttEstimate() function.
/// </summary>
NORM_PROBE_NONE,
/// <summary>
/// The NORM sender still transmits NORM_CMD(CC) probe messages multiplexed with its data transmission,
/// but the receiver set does not explicitly acknowledge these probes. Instead the receiver set is limited
/// to opportunistically piggy-backing responses when NORM_NACK messages are generated.
/// </summary>
NORM_PROBE_PASSIVE,
/// <summary>
/// In this mode, the receiver set explicitly acknowledges NORM sender GRTT probes ((NORM_CMD(CC) messages)
/// with NORM_ACK responses that are group-wise suppressed.
/// </summary>
NORM_PROBE_ACTIVE
}
}

View File

@ -0,0 +1,22 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The possible for values for NORM repair boundary.
/// </summary>
/// <remarks>
/// Customizes at what points the receiver initiates the NORM NACK repair process during protocol operation.
/// </remarks>
public enum NormRepairBoundary
{
/// <summary>
/// For smaller block sizes, the NACK repair process is often/quickly initiated and the
/// repair of an object will occur, as needed, during the transmission of the object.
/// </summary>
NORM_BOUNDARY_BLOCK,
/// <summary>
/// Causes the protocol to defer NACK process initiation until the current transport object
/// has been completely transmitted.
/// </summary>
NORM_BOUNDARY_OBJECT
}
}

View File

@ -0,0 +1,22 @@
namespace Mil.Navy.Nrl.Norm.Enums
{
/// <summary>
/// The possible synchronization policies.
/// </summary>
public enum NormSyncPolicy
{
/// <summary>
/// Attempt reception of "current" and new objects only (default).
/// </summary>
NORM_SYNC_CURRENT,
/// <summary>
/// Sync to current stream, but to beginning of stream.
/// </summary>
NORM_SYNC_STREAM,
/// <summary>
/// Attempt recovery and reliable reception of all objects
/// held in sender transmit object cache and newer objects.
/// </summary>
NORM_SYNC_ALL
}
}

View File

@ -0,0 +1,7 @@
namespace Mil.Navy.Nrl.Norm.IO
{
public interface INormEventListener
{
void NormEventOccurred(NormEvent normEvent);
}
}

View File

@ -0,0 +1,332 @@
using System.Runtime.CompilerServices;
namespace Mil.Navy.Nrl.Norm.IO
{
public class NormInputStream : Stream
{
private NormInstance _normInstance;
private NormSession _normSession;
private NormStream? _normStream;
private List<INormEventListener> _normEventListeners;
private bool _closed;
private object _closeLock;
private bool _bufferIsEmpty;
private bool _receivedEof;
/// <exception cref="IOException"></exception>
public NormInputStream(string address, int port)
{
// Create the NORM instance
_normInstance = new NormInstance();
// Create the NORM session
_normSession = _normInstance.CreateSession(address, port, NormNode.NORM_NODE_ANY);
_normStream = null;
_normEventListeners = new List<INormEventListener>();
_closed = true;
_closeLock = new object();
_bufferIsEmpty = true;
_receivedEof = false;
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void OpenDebugLog(string fileName)
{
if (fileName == null)
{
throw new IOException("File was name was not found.");
}
_normInstance.OpenDebugLog(fileName);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void CloseDebugLog() => _normInstance.CloseDebugLog();
[MethodImpl(MethodImplOptions.Synchronized)]
public void NormSetDebugLevel(int level) { _normInstance.DebugLevel = level; }
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetMessageTrace(bool messageTrace) => _normSession.SetMessageTrace(messageTrace);
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetMulticastInterface(string multicastInterface)
{
_normSession.SetMulticastInterface(multicastInterface);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetEcnSupport(bool ecnEnable, bool ignoreLoss)
{
_normSession.SetEcnSupport(ecnEnable, ignoreLoss);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetTtl(byte ttl)
{
_normSession.SetTTL(ttl);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetTos(byte tos)
{
_normSession.SetTOS(tos);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void setSilentReceiver(bool silent, int maxDelay)
{
_normSession.SetSilentReceiver(silent, maxDelay);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetDefaultUnicastNack(bool defaultUnicastNack)
{
_normSession.SetDefaultUnicastNack(defaultUnicastNack);
}
/// <exception cref="InvalidOperationException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SeekMsgStart()
{
if (_normStream == null)
{
throw new InvalidOperationException("Can only seek msg start after the stream is connected");
}
_normStream.SeekMsgStart();
}
/// <param name="normEventListener">The INormEventListener to add.</param>
[MethodImpl(MethodImplOptions.Synchronized)]
public void AddNormEventListener(INormEventListener normEventListener)
{
lock (_normEventListeners)
{
_normEventListeners.Add(normEventListener);
}
}
/// <param name="normEventListener">The INormEventListener to remove.</param>
[MethodImpl(MethodImplOptions.Synchronized)]
public void RemoveNormEventListener(INormEventListener normEventListener)
{
lock (_normEventListeners)
{
_normEventListeners.Remove(normEventListener);
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
private void FireNormEventOccured(NormEvent normEvent)
{
lock (_normEventListeners)
{
foreach (var normEventListener in _normEventListeners)
{
normEventListener.NormEventOccurred(normEvent);
}
}
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void Open(long bufferSpace)
{
lock (_closeLock)
{
if (!IsClosed)
{
throw new IOException("Stream is already open");
}
_normSession.StartReceiver(bufferSpace);
_closed = false;
}
}
/// <exception cref="IOException"></exception>
public override void Close()
{
lock (_closeLock)
{
if (IsClosed)
{
return;
}
_normStream?.Close(false);
_normSession.StopSender();
_normInstance.StopInstance();
_closed = true;
}
}
public bool IsClosed
{
get
{
lock (_closeLock)
{
return _closed;
}
}
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public int Read()
{
var buffer = new byte[1];
if (IsClosed)
{
throw new IOException("Stream is closed");
}
if (Read(buffer) < 0)
{
return -1;
}
return buffer[0];
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public override int Read(byte[] buffer, int offset, int count)
{
int n;
if (IsClosed)
{
throw new IOException("Stream is closed");
}
do
{
while (_bufferIsEmpty || _normInstance.HasNextEvent(0, 0))
{
ProcessEvent();
if (_receivedEof)
{
return -1;
}
}
if (_normStream == null)
{
return -1;
}
// Read from the stream
if ((n = _normStream.Read(buffer, offset, count)) < 0)
{
throw new IOException("Break in stream integrity");
}
_bufferIsEmpty = n == 0;
}
while (_bufferIsEmpty);
return n;
}
private void ProcessEvent()
{
// Retrieve the next event
var normEvent = _normInstance.GetNextEvent();
// Check if the stream was closed
if (IsClosed)
{
throw new IOException("Stream closed");
}
if (normEvent != null)
{
// Process the event
var eventType = normEvent.Type;
switch (eventType)
{
case NormEventType.NORM_RX_OBJECT_NEW:
var normObject = normEvent.Object;
if (normObject != null && normObject.Type == NormObjectType.NORM_OBJECT_STREAM)
{
_normStream = (NormStream)normObject;
}
break;
case NormEventType.NORM_RX_OBJECT_UPDATED:
var theNormObject = normEvent.Object;
if (theNormObject == null || !theNormObject.Equals(_normStream))
{
break;
}
// Signal that the buffer is not empty
_bufferIsEmpty = false;
break;
case NormEventType.NORM_RX_OBJECT_ABORTED:
case NormEventType.NORM_RX_OBJECT_COMPLETED:
_normStream = null;
// Signal that the stream has ended
_receivedEof = true;
break;
default:
break;
}
// Notify listeners of the norm event
FireNormEventOccured(normEvent);
}
}
public override void Flush()
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => throw new NotSupportedException();
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
}
}

View File

@ -0,0 +1,392 @@
using System.Runtime.CompilerServices;
namespace Mil.Navy.Nrl.Norm.IO
{
public class NormOutputStream : Stream
{
private NormInstance _normInstance;
private NormSession _normSession;
private NormStream? _normStream;
private List<INormEventListener> _normEventListeners;
private bool _closed;
private object _closeLock;
private bool _bufferIsFull;
/// <exception cref="IOException"></exception>
public NormOutputStream(string address, int port)
{
// Create the NORM instance
_normInstance = new NormInstance();
// Create the NORM session
_normSession = _normInstance.CreateSession(address, port, NormNode.NORM_NODE_ANY);
_normStream = null;
_normEventListeners = new List<INormEventListener>();
_closed = true;
_closeLock = new object();
_bufferIsFull = false;
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void OpenDebugLog(string filename)
{
_normInstance.OpenDebugLog(filename);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void CloseDebugLog()
{
_normInstance.CloseDebugLog();
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetDebugLevel(int level)
{
_normInstance.DebugLevel = level;
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetMessageTrace(bool messageTrace)
{
_normSession.SetMessageTrace(messageTrace);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetMulticastInterface(string multicastInterface)
{
_normSession.SetMulticastInterface(multicastInterface);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetEcnSupport(bool ecnEnable, bool ignoreLoss)
{
_normSession.SetEcnSupport(ecnEnable, ignoreLoss);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetTtl(byte ttl)
{
_normSession.SetTTL(ttl);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetTos(byte tos)
{
_normSession.SetTOS(tos);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetCongestionControl(bool ccEnabled, bool ccAdjustRate)
{
_normSession.SetCongestionControl(ccEnabled, ccAdjustRate);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetTxRateBounds(double minTxRate, double maxTxRate)
{
_normSession.SetTxRateBounds(maxTxRate, minTxRate);
}
public double TxRate
{
get
{
lock (this)
{
return _normSession.TxRate;
}
}
set
{
lock (this)
{
_normSession.TxRate = value;
}
}
}
public double GrttEstimate
{
get
{
lock (this)
{
return _normSession.GrttEstimate;
}
}
set
{
lock (this)
{
_normSession.GrttEstimate = value;
}
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetGroupSize(long groupSize)
{
_normSession.SetGroupSize(groupSize);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetAutoParity(short autoParity)
{
_normSession.SetAutoParity(autoParity);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetBackoffFactor(double backoffFactor)
{
_normSession.SetBackoffFactor(backoffFactor);
}
/// <exception cref="InvalidOperationException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetAutoFlush(NormFlushMode flushMode)
{
if (_normStream == null)
{
throw new InvalidOperationException("Can only set auto flush after the stream is open");
}
_normStream.SetAutoFlush(flushMode);
}
/// <exception cref="InvalidOperationException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetPushEnable(bool pushEnable)
{
if (_normStream == null)
{
throw new InvalidOperationException("Can only set push enabled after the stream is open");
}
_normStream.SetPushEnable(pushEnable);
}
/// <exception cref="InvalidOperationException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void MarkEom()
{
if (_normStream == null)
{
throw new InvalidOperationException("Can only mark EOM after the stream is open");
}
_normStream.MarkEom();
}
/// <param name="normEventListener">The INormEventListener to add.</param>
public void AddNormEventListener(INormEventListener normEventListener)
{
lock (_normEventListeners)
{
_normEventListeners.Add(normEventListener);
}
}
/// <param name="normEventListener">The INormEventListener to remove.</param>
public void RemoveNormEventListener(INormEventListener normEventListener)
{
lock (_normEventListeners)
{
_normEventListeners.Remove(normEventListener);
}
}
private void FireNormEventOccured(NormEvent normEvent)
{
lock (_normEventListeners)
{
foreach (var normEventListener in _normEventListeners)
{
normEventListener.NormEventOccurred(normEvent);
}
}
}
/// <exception cref="IOException"></exception>
public void Open(int sessionId, long bufferSpace, int segmentSize, short blockSize, short numParity, long repairWindow)
{
lock (_closeLock)
{
if (IsClosed)
{
throw new IOException("Stream is already open");
}
_normSession.StartSender(sessionId, bufferSpace, segmentSize, blockSize, numParity);
// Open the stream
_normStream = _normSession.StreamOpen(repairWindow);
_closed = false;
}
}
/// <exception cref="IOException"></exception>
public override void Close()
{
lock (_closeLock)
{
if (IsClosed)
{
return;
}
_normStream?.Close(false);
_normSession.StopSender();
_normInstance.StopInstance();
_closed = true;
}
}
public bool IsClosed
{
get
{
lock (_closeLock)
{
return _closed;
}
}
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public void Write(int b)
{
if (IsClosed)
{
throw new IOException("Stream is closed");
}
var buffer = new byte[1];
buffer[0] = (byte)b;
Write(buffer);
}
/// <exception cref="IOException"></exception>
[MethodImpl(MethodImplOptions.Synchronized)]
public override void Write(byte[] buffer, int offset, int count)
{
int n;
if (IsClosed)
{
throw new IOException("Stream is closed");
}
while (count > 0)
{
while (_normInstance.HasNextEvent(0, 0))
{
ProcessEvent();
}
// Wait while the buffer is full
while (_bufferIsFull)
{
ProcessEvent();
}
// Write some data
if (_normStream == null || (n = _normStream.Write(buffer, offset, count)) < 0)
{
throw new IOException("Failed to write to stream");
}
_bufferIsFull = n == 0;
count -= n;
offset += n;
}
}
/// <exception cref="IOException"></exception>
private void ProcessEvent()
{
// Retrieve the next event
var normEvent = _normInstance.GetNextEvent();
// Check if the stream was closed
if (IsClosed)
{
throw new IOException("Stream closed");
}
if (normEvent != null)
{
// Process the event
var eventType = normEvent.Type;
switch (eventType)
{
case NormEventType.NORM_TX_QUEUE_VACANCY:
case NormEventType.NORM_TX_QUEUE_EMPTY:
var normObject = normEvent.Object;
if (normObject == null || !normObject.Equals(_normStream))
{
break;
}
// Signal that the buffer is not full
_bufferIsFull = false;
break;
case NormEventType.NORM_TX_OBJECT_SENT:
case NormEventType.NORM_TX_OBJECT_PURGED:
_normStream = null;
break;
default:
break;
}
// Notify listeners of the norm event
FireNormEventOccured(normEvent);
}
}
public override void Flush()
{
throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override bool CanRead => false;
public override bool CanSeek => false;
public override bool CanWrite => IsClosed;
public override long Length => throw new NotSupportedException();
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
}
}

View File

@ -0,0 +1,9 @@
namespace Mil.Navy.Nrl.Norm.IO
{
public class StreamBreakException : IOException
{
public StreamBreakException(string? message) : base(message)
{
}
}
}

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>1.0.0</Version>
</PropertyGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
using System.Runtime.InteropServices;
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// A transport object of type NORM_OBJECT_FILE.
/// </summary>
/// <remarks>
/// The data storage area for the specified transport object.
/// </remarks>
public class NormData : NormObject
{
/// <summary>
/// The data storage area associated with a transport object of type NORM_OBJECT_DATA.
/// </summary>
public byte[] Data
{
get
{
var dataPointer = NormDataAccessData(_handle);
var length = NormObjectGetSize(_handle);
var data = new byte[length];
for (var i = 0; i < length; i++)
{
data[i] = Marshal.ReadByte(dataPointer, i);
}
return data;
}
}
/// <summary>
/// Constructor of NormData
/// </summary>
/// <param name="handle">Type is used to reference state kept for data transport objects being actively transmitted or received.</param>
internal NormData(long handle) : base(handle)
{
}
}
}

View File

@ -0,0 +1,112 @@
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// The NormEvent type is used to describe significant NORM protocol events.
/// </summary>
public class NormEvent
{
/// <summary>
/// The type identifies the event with one of NORM protocol events.
/// </summary>
private NormEventType _type { get; }
/// <summary>
/// Used to identify application in the NormSession.
/// </summary>
private long _sessionHandle { get; }
/// <summary>
/// This type is used to reference state kept by the NORM implementation with respect to other participants within a NormSession.
/// </summary>
private long _nodeHandle { get; }
/// <summary>
/// This type is used to reference state kept for data transport objects being actively transmitted or received.
/// </summary>
private long _objectHandle { get; }
/// <summary>
/// The Parameterized constructor of NormEvent
/// </summary>
/// <param name="type">indicates the NormEventType and determines how the other fields should be interpreted.</param>
/// <param name="sessionHandle">indicates the applicable NormSessionHandle to which the event applies.</param>
/// <param name="nodeHandle">indicates the applicable NormNodeHandle to which the event applies</param>
/// <param name="objectHandle">indicates the applicable NormObjectHandle to which the event applies.</param>
public NormEvent(NormEventType type, long sessionHandle, long nodeHandle, long objectHandle)
{
_type = type;
_sessionHandle = sessionHandle;
_nodeHandle = nodeHandle;
_objectHandle = objectHandle;
}
/// <summary>
/// The type identifies the event with one of NORM protocol events.
/// </summary>
public NormEventType Type => _type;
/// <summary>
/// The NormSession associated with the event.
/// </summary>
public NormSession? Session
{
get
{
if (_sessionHandle == NormSession.NORM_SESSION_INVALID)
{
return null;
}
return NormSession.GetSession(_sessionHandle);
}
}
/// <summary>
/// A remote participant associated with the event.
/// </summary>
public NormNode? Node
{
get
{
if (_nodeHandle == 0)
{
return null;
}
return new NormNode(_nodeHandle);
}
}
/// <summary>
/// NORM transport object.
/// </summary>
public NormObject? Object
{
get
{
NormObject? normObject = null;
var normObjectType = NormObjectGetType(_objectHandle);
switch (normObjectType)
{
case NormObjectType.NORM_OBJECT_DATA:
normObject = new NormData(_objectHandle);
break;
case NormObjectType.NORM_OBJECT_FILE:
normObject = new NormFile(_objectHandle);
break;
case NormObjectType.NORM_OBJECT_STREAM:
normObject= new NormStream(_objectHandle);
break;
case NormObjectType.NORM_OBJECT_NONE:
default:
break;
}
return normObject;
}
}
/// <summary>
/// This function returns a description of the NORM protocol event
/// </summary>
/// <returns>A string that includes the event type.</returns>
public override string ToString()
{
return $"NormEvent [type={_type}]";
}
}
}

View File

@ -0,0 +1,54 @@
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// A transport object of type NORM_OBJECT_FILE.
/// </summary>
public class NormFile : NormObject
{
/// <summary>
/// Maximum length of file names.
/// </summary>
public const int FILENAME_MAX = 260;
/// <summary>
/// Constructor of NormFile
/// </summary>
/// <param name="handle">This type is used to reference state kept for data transport objects being actively transmitted or received.</param>
internal NormFile(long handle) : base(handle)
{
}
/// <summary>
/// The name of the file.
/// </summary>
/// <exception cref="IOException">Thrown when failed to get file name.</exception>
public string Name
{
get
{
var buffer = new char[FILENAME_MAX];
if (!NormFileGetName(_handle, buffer, FILENAME_MAX))
{
throw new IOException("Failed to get file name");
}
buffer = buffer.Where(c => c != 0).ToArray();
return new string(buffer);
}
}
/// <summary>
/// This function renames the file used to store content for the NORM_OBJECT_FILE transport object.
/// This allows receiver applications to rename (or move) received files as needed.
/// NORM uses temporary file names for received files until the application explicitly renames the file.
/// </summary>
/// <param name="filePath">The full path of received file.</param>
/// <exception cref="IOException">Thrown when failed to rename file.</exception>
public void Rename(string filePath)
{
if(!NormFileRename(_handle, filePath))
{
throw new IOException("Failed to rename file");
}
}
}
}

View File

@ -0,0 +1,236 @@
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Net.Sockets;
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// An instance of a NORM protocol engine
/// </summary>
public class NormInstance
{
/// <summary>
/// Returned on error when getting the file descriptor for a NormInstance.
/// </summary>
public const int NORM_DESCRIPTOR_INVALID = 0;
/// <summary>
/// The _handle refers to the NORM protocol engine instance
/// </summary>
private long _handle;
/// <summary>
/// Constructor for NormInstance with priority boost
/// </summary>
/// <param name="priorityBoost">The priorityBoost parameter, when set to a value of true, specifies that the NORM protocol engine thread be run with higher priority scheduling.</param>
public NormInstance(bool priorityBoost)
{
CreateInstance(priorityBoost);
}
/// <summary>
/// Default constructor for NormInstance
/// </summary>
public NormInstance() : this(false)
{
}
/// <summary>
/// This function creates an instance of a NORM protocol engine and is the necessary first step before any other API functions may be used.
/// </summary>
/// <param name="priorityBoost">The priorityBoost parameter, when set to a value of true, specifies that the NORM protocol engine thread be run with higher priority scheduling.</param>
private void CreateInstance(bool priorityBoost)
{
var handle = NormCreateInstance(priorityBoost);
_handle = handle;
}
/// <summary>
/// The function immediately shuts down and destroys the NORM protocol engine instance referred to by the instanceHandle parameter.
/// </summary>
public void DestroyInstance()
{
NormDestroyInstance(_handle);
}
/// <summary>
/// This function creates a NORM protocol session (NormSession) using the address (multicast or unicast) and port
/// parameters provided. While session state is allocated and initialized, active session participation does not begin
/// until the session starts the sender and/or receiver to join the specified multicast group
/// (if applicable) and start protocol operation.
/// </summary>
/// <param name="address">Specified address determines the destination of NORM messages sent </param>
/// <param name="port">Valid, unused port number corresponding to the desired NORM session address. </param>
/// <param name="localNodeId">Identifies the application's presence in the NormSession </param>
/// <returns>The NormSession that was created</return
/// <exception cref="IOException">Throws when fails to create session</exception>
public NormSession CreateSession(string address, int port, long localNodeId)
{
var session = NormCreateSession(_handle, address, port, localNodeId);
if (session == NormSession.NORM_SESSION_INVALID)
{
throw new IOException("Failed to create session");
}
return new NormSession(session);
}
/// <summary>
/// Determines if the NORM protocol engine instance has a next event
/// </summary>
/// <param name="sec">The seconds to wait</param>
/// <param name="usec">The microseconds to wait</param>
/// <returns>True if the NORM protocol engine instance has a next event</returns>
public bool HasNextEvent(int sec, int usec)
{
var totalMilliseconds = sec * 1000 + usec / 1000;
var waitTime = TimeSpan.FromMilliseconds(totalMilliseconds);
return HasNextEvent(waitTime);
}
/// <summary>
/// Determines if the NORM protocol engine instance has a next event
/// </summary>
/// <param name="waitTime">The time to wait</param>
/// <returns>True if the NORM protocol engine instance has a next event</returns>
public bool HasNextEvent(TimeSpan waitTime)
{
var normDescriptor = NormGetDescriptor(_handle);
if (normDescriptor == NORM_DESCRIPTOR_INVALID)
{
return false;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
using var eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
eventWaitHandle.SafeWaitHandle = new SafeWaitHandle(new IntPtr(normDescriptor), false);
return eventWaitHandle.WaitOne(waitTime);
}
var hasNextEvent = false;
var timeout = DateTime.Now.Add(waitTime);
while (!hasNextEvent && DateTime.Now <= timeout)
{
using var socketHandle = new SafeSocketHandle(new IntPtr(normDescriptor), false);
using var socket = new Socket(socketHandle);
hasNextEvent = socket.Available > 0;
}
return hasNextEvent;
}
/// <summary>
/// This function retrieves the next available NORM protocol event from the protocol engine.
/// </summary>
/// <param name="waitForEvent">waitForEvent specifies whether the call to this function is blocking or not, if "waitForEvent" is false, this is a non-blocking call. </param>
/// <returns>Returns an instance of NormEvent if NormGetNextEvent() returns true, returns null otherwise. </returns>
public NormEvent? GetNextEvent(bool waitForEvent)
{
bool success = NormGetNextEvent(_handle, out NormApi.NormEvent normEvent, waitForEvent);
if (!success)
{
return null;
}
return new NormEvent(normEvent.Type, normEvent.Session, normEvent.Sender, normEvent.Object);
}
/// <summary>
/// This function retrieves the next available NORM protocol event from the protocol engine.
/// </summary>
/// <remarks>
/// This is a default function which calls GetNextEvent(bool waitForEvent) override
/// with waitForEvent set as true.
/// </remarks>
/// <returns>Returns an instance of NormEvent if NormGetNextEvent() returns true, returns null otherwise.</returns>
public NormEvent? GetNextEvent()
{
return GetNextEvent(true);
}
/// <summary>
/// This function sets the directory path used by receivers to cache newly-received NORM_OBJECT_FILE content.
/// </summary>
/// <param name="cachePath">the cachePath is a string specifying a valid (and writable) directory path.</param>
/// <exception cref="IOException">Throws when fails to set the cache directory</exception>
public void SetCacheDirectory(string cachePath)
{
if(!NormSetCacheDirectory(_handle, cachePath))
{
throw new IOException("Failed to set the cache directory");
}
}
/// <summary>
/// This function immediately stops the NORM protocol engine thread.
/// </summary>
public void StopInstance()
{
NormStopInstance(_handle);
}
/// <summary>
/// This function creates and starts an operating system thread to resume NORM protocol engine operation that was previously stopped by a call to StopInstance().
/// </summary>
/// <returns>Boolean as to the success of the instance restart. </return>
public bool RestartInstance()
{
return NormRestartInstance(_handle);
}
/// <summary>
/// Immediately suspends the NORM protocol engine thread.
/// </summary>
/// <returns>Boolean as to the success of the instance suspension. </returns>
public bool SuspendInstance()
{
return NormSuspendInstance(_handle);
}
/// <summary>
/// This function allows NORM debug output to be directed to a file instead of the default STDERR.
/// </summary>
public void ResumeInstance()
{
NormResumeInstance(_handle);
}
/// <summary>
/// This function allows NORM debug output to be directed to a file instead of the default STDERR.
/// </summary>
/// <param name="fileName">Full path and name of the debug log.</param>
/// <exception cref="IOException">Throws when fails to open debug log"</exception>
public void OpenDebugLog(string fileName)
{
if (!NormOpenDebugLog(_handle, fileName))
{
throw new IOException("Failed to open debug log");
}
}
/// <summary>
/// This function disables NORM debug output to be directed to a file instead of the default STDERR.
/// </summary>
public void CloseDebugLog()
{
NormCloseDebugLog(_handle);
}
/// <summary>
/// This function allows NORM debug output to be directed to a named pipe.
/// </summary>
/// <param name="pipename">The debug pipe name.</param>
/// <exception cref="IOException">Throws when fails to open debug pipe.</exception>
public void OpenDebugPipe(string pipename)
{
if (!NormOpenDebugPipe(_handle, pipename))
{
throw new IOException("Failed to open debug pipe");
}
}
/// <summary>
/// The currently set debug level.
/// </summary>
public int DebugLevel
{
get => NormGetDebugLevel();
set => NormSetDebugLevel(value);
}
}
}

View File

@ -0,0 +1,147 @@
using System.Net;
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// A participant in a NORM protocol session
/// </summary>
public class NormNode
{
/// <summary>
/// When creating a session, allows the NORM implementation to attempt to pick an identifier based on the host computer's "default" IP address.
/// </summary>
public const long NORM_NODE_ANY = 0xffffffff;
/// <summary>
/// The special value NORM_NODE_NONE corresponds to an invalid (or null) node.
/// </summary>
public const int NORM_NODE_NONE = 0;
/// <summary>
/// The special value NORM_NODE_INVALID corresponds to an invalid reference.
/// </summary>
public const int NORM_NODE_INVALID = 0;
/// <summary>
/// The handle is associated to the NORM protocol engine instance.
/// </summary>
private long _handle;
/// <summary>
/// Parameterized contructor.
/// </summary>
/// <param name="handle">The handle is associated to the NORM protocol engine instance.</param>
internal NormNode(long handle)
{
_handle = handle;
}
/// <summary>
/// The NormNodeId identifier for the remote participant.
/// </summary>
public long Id => NormNodeGetId(_handle);
/// <summary>
/// The current network source address detected for packets received from remote NORM sender.
/// </summary>
public IPEndPoint Address
{
get
{
var buffer = new byte[256];
var bufferLength = buffer.Length;
if (!NormNodeGetAddress(_handle, buffer, ref bufferLength, out var port))
{
throw new IOException("Failed to get node address");
}
buffer = buffer.Take(bufferLength).ToArray();
var ipAddressText = string.Join('.', buffer);
var ipAddress = IPAddress.Parse(ipAddressText);
return new IPEndPoint(ipAddress, port);
}
}
/// <summary>
/// The advertised estimate of group round-trip timing (GRTT) for the remote sender.
/// </summary>
public double Grtt => NormNodeGetGrtt(_handle);
/// <summary>
/// NORM application-defined command for transmission.
/// </summary>
public byte[] Command
{
get
{
var buffer = new byte[256];
var bufferLength = buffer.Length;
if (!NormNodeGetCommand(_handle, buffer, ref bufferLength))
{
throw new IOException("Failed to get command");
}
return buffer.Take(bufferLength).ToArray();
}
}
/// <summary>
/// This function controls the destination address of receiver feedback messages generated in response to a specific remote NORM sender.
/// </summary>
/// <param name="state">If state is true, "unicast NACKing" is enabled.</param>
public void SetUnicastNack(bool state)
{
NormNodeSetUnicastNack(_handle, state);
}
/// <summary>
/// This function sets the default "nacking mode" used for receiving new objects from a specific sender.
/// </summary>
/// <param name="nackingMode">Specifies the nacking mode.</param>
public void SetNackingMode(NormNackingMode nackingMode)
{
NormNodeSetNackingMode(_handle, nackingMode);
}
/// <summary>
/// This function allows the receiver application to customize at what points the receiver initiates the NORM NACK repair process during protocol operation.
/// </summary>
/// <param name="repairBoundary">Specifies the repair boundary.</param>
public void SetRepairBoundary(NormRepairBoundary repairBoundary)
{
NormNodeSetRepairBoundary(_handle, repairBoundary);
}
/// <summary>
/// This routine sets the robustFactor as described in NormSetDefaultRxRobustFactor() for an individual remote sender.
/// </summary>
/// <param name="robustFactor">The robustFactor value determines how
/// many times a NORM receiver will self-initiate NACKing (repair requests) upon cessation of packet reception from
/// a sender. The default value is 20. Setting rxRobustFactor to -1 will make the NORM receiver infinitely persistent
/// (i.e., it will continue to NACK indefinitely as long as it is missing data content).</param>
public void SetRxRobustFactor(int robustFactor)
{
NormNodeSetRxRobustFactor(_handle, robustFactor);
}
/// <summary>
/// This function releases memory resources that were allocated for a remote sender.
/// </summary>
public void FreeBuffers()
{
NormNodeFreeBuffers(_handle);
}
/// <summary>
/// This function allows the application to retain state associated even when the underlying NORM protocol engine might normally free the associated state.
/// </summary>
public void Retain()
{
NormNodeRetain(_handle);
}
/// <summary>
/// This function releases the Node so that the NORM protocol engine may free associated resources as needed.
/// </summary>
public void Release()
{
NormNodeRelease(_handle);
}
}
}

View File

@ -0,0 +1,163 @@
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// The base transport object.
/// </summary>
public class NormObject
{
/// <summary>
/// The special value NORM_OBJECT_INVALID corresponds to an invalid reference.
/// </summary>
public const int NORM_OBJECT_INVALID = 0;
/// <summary>
/// Used to reference state kept for data transport objects being actively transmitted or received.
/// </summary>
protected long _handle;
/// <summary>
/// Internal constructor for NormObject
/// </summary>
/// <param name="handle">Identifies an instance of NormObject</param>
internal NormObject(long handle)
{
_handle = handle;
}
/// <summary>
/// Used to reference state kept for data transport objects being actively transmitted or received.
/// </summary>
public long Handle => _handle;
/// <summary>
/// Data associated with NormObject.
/// </summary>
public byte[]? Info
{
get
{
if (!NormObjectHasInfo(_handle))
{
return null;
}
var length = NormObjectGetInfoLength(_handle);
var buffer = new byte[length];
NormObjectGetInfo(_handle, buffer, length);
return buffer;
}
}
/// <summary>
/// The type of Norm object.
/// Valid types include:
/// NORM_OBJECT_FILE
/// NORM_OBJECT_DATA
/// NORM_OBJECT_STREAM
/// </summary>
public NormObjectType Type
{
get
{
return NormObjectGetType(_handle);
}
}
/// <summary>
/// The size (in bytes) of the transport object.
/// </summary>
public long Size
{
get
{
return NormObjectGetSize(_handle);
}
}
/// <summary>
/// The NormNodeHandle corresponding to the remote sender of the transport object.
/// </summary>
/// <exception cref="IOException">Thrown when NormObjectGetSender() returns NORM_NODE_INVALID, indicating locally originated sender object.</exception>
public long Sender
{
get
{
var sender = NormObjectGetSender(_handle);
if(sender == NormNode.NORM_NODE_INVALID)
{
throw new IOException("Locally originated sender object");
}
return sender;
}
}
/// <summary>
/// This function sets the "nacking mode" used for receiving a specific transport object.
/// </summary>
/// <param name="nackingMode">Specifies the nacking mode.</param>
public void SetNackingMode(NormNackingMode nackingMode)
{
NormObjectSetNackingMode(_handle, nackingMode);
}
/// <summary>
/// This function can be used to determine the progress of reception of the NORM transport object
/// </summary>
/// <returns>A number of object source data bytes pending reception (or transmission) is returned.</returns>
public long GetBytesPending()
{
return NormObjectGetBytesPending(_handle);
}
/// <summary>
/// This function immediately cancels the transmission of a local sender transport object or the reception of a specified
/// object from a remote sender.
/// </summary>
public void Cancel()
{
NormObjectCancel(_handle);
}
/// <summary>
/// This function "retains" the objectHandle and any state associated with it for further use by the application even
/// when the NORM protocol engine may no longer require access to the associated transport object.
/// </summary>
public void Retain()
{
NormObjectRetain(_handle);
}
/// <summary>
/// This function complements the Retain() call by immediately freeing any resources associated with
/// the given objectHandle, assuming the underlying NORM protocol engine no longer requires access to the corresponding
/// transport object. Note the NORM protocol engine retains/releases state for associated objects for its own
/// needs and thus it is very unsafe for an application to call Release() for an objectHandle for which
/// it has not previously explicitly retained via Retain().
/// </summary>
public void Release()
{
NormObjectRelease(_handle);
}
/// <summary>
/// Gets the hash code of the object.
/// </summary>
/// <returns>Returns the handle of the object.</returns>
public override int GetHashCode()
{
return (int)_handle;
}
/// <summary>
/// Decides wether specified object is equal another.
/// </summary>
/// <param name="obj">NormObject to compare to.</param>
/// <returns>Returns true if two objects equal, false otherwise.</returns>
public override bool Equals(object? obj)
{
if(obj is NormObject)
{
return _handle == ((NormObject)obj).Handle;
}
return false;
}
}
}

View File

@ -0,0 +1,923 @@
using System.Runtime.CompilerServices;
using System.Text;
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// NORM transport session
/// </summary>
public class NormSession
{
/// <summary>
/// The special value NORM_SESSION_INVALID is used to refer to invalid session references.
/// </summary>
public const int NORM_SESSION_INVALID = 0;
/// <summary>
/// A dictionary of NORM sessions with their respective handles.
/// </summary>
private static Dictionary<long, NormSession> _normSessions = new Dictionary<long, NormSession>();
/// <summary>
/// The NormSessionHandle type is used to reference the NORM transport session.
/// </summary>
private long _handle;
/// <summary>
/// Used for the application's participation in the NormSession.
/// </summary>
public long LocalNodeId
{
get => NormGetLocalNodeId(_handle);
}
/// <summary>
/// The report interval.
/// </summary>
public double ReportInterval
{
get => NormGetReportInterval(_handle);
set => NormSetReportInterval(_handle, value);
}
/// <summary>
/// Transmission rate (in bits per second (bps)) limit used for NormSender transmissions.
/// </summary>
public double TxRate
{
get => NormGetTxRate(_handle);
set => NormSetTxRate(_handle, value);
}
/// <summary>
/// Group round-trip timing.
/// </summary>
public double GrttEstimate
{
get => NormGetGrttEstimate(_handle);
set => NormSetGrttEstimate(_handle, value);
}
/// <summary>
/// Internal constructor of NormSession.
/// </summary>
/// <param name="handle">Used to identify application in the NormSession.</param>
/// <remarks>The handle and NormSession are added to the dictionary of NORM sessions.</remarks>
internal NormSession(long handle)
{
_handle = handle;
lock (_normSessions)
{
_normSessions.Add(handle, this);
}
}
/// <summary>
/// Get a specified NormSession from the dictionary of NORM sessions.
/// </summary>
/// <param name="handle">Specifies the session to return.</param>
/// <returns>Returns a NormSession.</returns>
[MethodImpl(MethodImplOptions.Synchronized)]
internal static NormSession GetSession(long handle)
{
return _normSessions[handle];
}
/// <summary>
/// This function immediately terminates the application's participation in the NormSession and frees any resources used by that session.
/// </summary>
public void DestroySession()
{
lock (_normSessions)
{
_normSessions.Remove(_handle);
}
DestroySessionNative();
}
/// <summary>
/// This function immediately terminates the application's participation in the NormSession and frees any resources used by that session.
/// </summary>
private void DestroySessionNative()
{
NormDestroySession(_handle);
}
/// <summary>
/// This function is used to force NORM to use a specific port number for UDP packets sent.
/// </summary>
/// <remarks>
/// This is a default function which calls SetTxPort(int port, bool enableReuse, string? txBindAddress) override
/// with enableReuse set as false and txBindAddress set to null.
/// </remarks>
/// <param name="port">The port parameter, specifies which port number to use.</param>
/// <exception cref="IOException">Thrown when NormSetTxPort() returns false, indicating the failure to set tx port.</exception>
public void SetTxPort(int port)
{
SetTxPort(port, false, null);
}
/// <summary>
/// This function is used to force NORM to use a specific port number for UDP packets sent.
/// </summary>
/// <param name="port">The port parameter, specifies which port number to use.</param>
/// <param name="enableReuse">When set to true, allows that the specified port may be reused for multiple sessions.</param>
/// <param name="txBindAddress">The txBindAddress parameter allows specification of a specific source address binding for packet transmission.</param>
/// <exception cref="IOException">Thrown when NormSetTxPort() returns false, indicating the failure to set tx port.</exception>
public void SetTxPort(int port, bool enableReuse, string? txBindAddress)
{
if (!NormSetTxPort(_handle, port, enableReuse, txBindAddress))
{
throw new IOException("Failed to set Tx Port");
}
}
/// <summary>
/// This function limits the NormSession to perform NORM sender functions only.
/// </summary>
/// <remarks>
/// This is a default function which calls etTxOnly(bool txOnly, bool connectToSessionAddress) override
/// with connectToSessionAddress set as false.
/// </remarks>
/// <param name="txOnly">Boolean specifing whether to turn on or off the txOnly operation.</param>
public void SetTxOnly(bool txOnly)
{
SetTxOnly(txOnly, false);
}
/// <summary>
/// This function limits the NormSession to perform NORM sender functions only.
/// </summary>
/// <param name="txOnly">Boolean specifing whether to turn on or off the txOnly operation.</param>
/// <param name="connectToSessionAddress">The optional connectToSessionAddress parameter, when set to true, causes the underlying NORM code to
/// "connect()" the UDP socket to the session (remote receiver) address and port number.</param>
public void SetTxOnly(bool txOnly, bool connectToSessionAddress)
{
NormSetTxOnly(_handle, txOnly, connectToSessionAddress);
}
/// <summary>
/// This function allows the user to control the port reuse and binding behavior for the receive socket.
/// </summary>
/// <remarks>
/// This is a default function which calls SetRxPortReuse(bool enable, string? rxBindAddress, string? senderAddress, int senderPort)
/// with rxBindAddress set to null, senderAddress set to null, and senderPort set to 0.
/// </remarks>
/// <param name="enable">When the enable parameter is set to true, reuse of the NormSession port number by multiple NORM instances or sessions is enabled.</param>
public void SetRxPortReuse(bool enable)
{
SetRxPortReuse(enable, null, null, 0);
}
/// <summary>
/// This function allows the user to control the port reuse and binding behavior for the receive socket.
/// </summary>
/// <param name="enable">When the enable parameter is set to true, reuse of the NormSession port number by multiple NORM instances or sessions is enabled.</param>
/// <param name="rxBindAddress">If the optional rxBindAddress is supplied (an IP address or host name in string form),
/// the socket will bind() to the given address when it is opened in a call to StartReceiver() or StartSender().</param>
/// <param name="senderAddress">The optional senderAddress parameter can be used to connect() the underlying NORM receive socket to specific address.</param>
/// <param name="senderPort">The optional senderPort parameter can be used to connect() the underlying NORM receive socket to specific port.</param>
public void SetRxPortReuse(bool enable, string? rxBindAddress, string? senderAddress, int senderPort)
{
NormSetRxPortReuse(_handle, enable, rxBindAddress, senderAddress, senderPort);
}
/// <remarks>
/// This is a default function which calls SetEcnSupport(bool ecnEnable, bool ignoreLoss, bool tolerateLoss) override
/// with tolerateLoss set as false.
/// </remarks>
/// <param name="ecnEnable">Enables NORM ECN (congestion control) support.</param>
/// <param name="ignoreLoss">With "ecnEnable", use ECN-only, ignoring packet loss.</param>
public void SetEcnSupport(bool ecnEnable, bool ignoreLoss)
{
SetEcnSupport(ecnEnable, ignoreLoss, false);
}
/// <param name="ecnEnable">Enables NORM ECN (congestion control) support.</param>
/// <param name="ignoreLoss">With "ecnEnable", use ECN-only, ignoring packet loss.</param>
/// <param name="tolerateLoss">Loss-tolerant congestion control, ecnEnable or not.</param>
public void SetEcnSupport(bool ecnEnable, bool ignoreLoss, bool tolerateLoss)
{
NormSetEcnSupport(_handle, ecnEnable, ignoreLoss, tolerateLoss);
}
/// <summary>
/// This function specifies which host network interface is used for IP Multicast transmissions and group membership.
/// This should be called before any call to StartSender() or StartReceiver() is made so that the IP multicast
/// group is joined on the proper host interface.
/// </summary>
/// <param name="interfaceName">Name of the interface</param>
/// <exception cref="IOException">Thrown when NormSetMulticastInterface() returns false, indicating the failure to set multicast interface.</exception>
public void SetMulticastInterface(string interfaceName)
{
if(!NormSetMulticastInterface(_handle, interfaceName))
{
throw new IOException("Failed to set multicast interface");
}
}
/// <summary>
/// This function sets the source address for Source-Specific Multicast (SSM) operation.
/// </summary>
/// <param name="sourceAddress">Address to be set as source for source-specific multicast operation. </param>
/// <exception cref="IOException">Thrown when NormSetSSM() returns false, indicating the failure to set ssm.</exception>
public void SetSSM(string sourceAddress)
{
if(!NormSetSSM(_handle, sourceAddress))
{
throw new IOException("Failed to set SSM");
}
}
/// <summary>
/// This function specifies the time-to-live (ttl) for IP Multicast datagrams generated by NORM for the specified
/// sessionHandle. The IP TTL field limits the number of router "hops" that a generated multicast packet may traverse
/// before being dropped.
/// </summary>
/// <param name="ttl">If TTL is equal to one, the transmissions will be limited to the local area network
/// (LAN) of the host computers network interface. Larger TTL values should be specified to span large networks.</param>
/// <exception cref="IOException">Thrown when NormSetTTL() returns false, indicating the failure to set ttl.</exception>
public void SetTTL(byte ttl)
{
if (!NormSetTTL(_handle, ttl))
{
throw new IOException("Failed to set TTL");
}
}
/// <summary>
/// This function specifies the type-of-service (tos) field value used in IP Multicast datagrams generated by NORM.
/// </summary>
/// <param name="tos">The IP TOS field value can be used as an indicator that a "flow" of packets may merit special Quality-of-Service (QoS) treatment by network devices.
/// Users should refer to applicable QoS information for their network to determine the expected interpretation and treatment (if any) of packets with explicit TOS marking.</param>
/// <exception cref="IOException">Thrown when NormSetTOS() returns false, indicating the failure to set TOS.</exception>
public void SetTOS(byte tos)
{
if(!NormSetTOS(_handle, tos))
{
throw new IOException("Failed to set TOS");
}
}
/// <summary>
/// This function enables or disables loopback operation.
/// </summary>
/// <param name="loopbackEnable">If loopbackEnable is set to true, loopback operation is enabled which allows the application to receive its own message traffic.
/// Thus, an application which is both actively receiving and sending may receive its own transmissions.</param>
/// <exception cref="IOException">Thrown when NormSetLoopback() returns false, indicating the failure to set loopback.</exception>
public void SetLoopback(bool loopbackEnable)
{
if (!NormSetLoopback(_handle, loopbackEnable))
{
throw new IOException("Failed to set loopback");
}
}
public void SetMessageTrace(bool flag)
{
NormSetMessageTrace(_handle, flag);
}
public void SetTxLoss(double precent)
{
NormSetTxLoss(_handle, precent);
}
public void SetRxLoss(double precent)
{
NormSetRxLoss(_handle, precent);
}
/// <summary>
/// This function controls a scaling factor that is used for sender timer-based flow control.
/// Timer-based flow control works by preventing the NORM sender application from enqueueing
/// new transmit objects or stream data that would purge "old" objects or stream data when there has been recent
/// NACK activity for those old objects or data.
/// </summary>
/// <param name="precent">The precent is used to compute a delay time for when a sender buffered object (or block of stream
/// data) may be released (i.e. purged) after transmission or applicable NACKs reception. </param>
public void SetFlowControl(double precent)
{
NormSetFlowControl(_handle, precent);
}
/// <summary>
/// This function can be used to set a non-default socket buffer size for the UDP socket used for data transmission.
/// </summary>
/// <param name="bufferSize">The bufferSize parameter specifies the desired socket buffer size in bytes.</param>
/// <exception cref="IOException">Thrown when NormSetTxSocketBuffer() returns false, indicating the failure to set tx socket buffer.
/// Possible failure modes include an invalid sessionHandle parameter, a call to StartReceiver() or StartSender() has not yet been made for the
/// session, or an invalid bufferSize was given.
/// Note some operating systems may require additional system configuration to use non-standard socket buffer sizes.</exception>
public void SetTxSocketBuffer(long bufferSize)
{
if(!NormSetTxSocketBuffer(_handle, bufferSize))
{
throw new IOException("Failed to set tx socket buffer");
}
}
/// <summary>
/// This function enables (or disables) the NORM sender congestion control operation.
/// For best operation, this function should be called before the call to StartSender() is made,
/// but congestion control operation can be dynamically enabled/disabled during the course of sender operation.
/// </summary>
/// <remarks>
/// This is the default function which calls SetCongestionControl(bool enable, bool adjustRate) override
/// with adjustRate set to true.
/// </remarks>
/// <param name="enable">Specifies whether to enable or disable the NORM sender congestion control operation.</param>
public void SetCongestionControl(bool enable)
{
SetCongestionControl(enable, true);
}
/// <summary>
/// This function enables (or disables) the NORM sender congestion control operation.
/// For best operation, this function should be called before the call to StartSender() is made,
/// but congestion control operation can be dynamically enabled/disabled during the course of sender operation.
/// </summary>
/// <param name="enable">Specifies whether to enable or disable the NORM sender congestion control operation.</param>
/// <param name="adjustRate">The rate set by SetTxRate() has no effect when congestion control operation is enabled, unless the adjustRate
/// parameter here is set to false. When the adjustRate parameter is set to false, the NORM Congestion Control
/// operates as usual, with feedback collected from the receiver set and the "current limiting receiver" identified, except
/// that no actual adjustment is made to the sender's transmission rate.</param>
public void SetCongestionControl(bool enable, bool adjustRate)
{
NormSetCongestionControl(_handle, enable, adjustRate);
}
/// <summary>
/// This function sets the range of sender transmission rates within which the NORM congestion control algorithm is allowed to operate.
/// </summary>
/// <param name="rateMin">rateMin corresponds to the minimum transmission rate (bps).</param>
/// <param name="rateMax">rateMax corresponds to the maximum transmission rate (bps).</param>
public void SetTxRateBounds(double rateMin, double rateMax)
{
NormSetTxRateBounds(_handle, rateMin, rateMax);
}
/// <summary>
/// This function sets limits that define the number and total size of pending transmit objects a NORM sender will allow to be enqueued by the application.
/// </summary>
/// <param name="sizeMax">The sizeMax parameter sets the maximum total size, in bytes, of enqueued objects allowed.</param>
/// <param name="countMin">The countMin parameter sets the minimum number of objects the application may enqueue, regardless of the objects' sizes and the sizeMax value.</param>
/// <param name="countMax">The countMax parameter sets a ceiling on how many objects may be enqueued, regardless of their total sizes with respect to the sizeMax setting.</param>
public void SetTxCacheBounds(long sizeMax, long countMin, long countMax)
{
NormSetTxCacheBounds(_handle,sizeMax, countMin, countMax);
}
/// <summary>
/// The application's participation as a sender begins when this function is called.
/// </summary>
/// <param name="sessionId">Application-defined value used as the instance_id field of NORM sender messages for the application's participation within a session.</param>
/// <param name="bufferSpace">This specifies the maximum memory space (in bytes) the NORM protocol engine is allowed to use to buffer any sender calculated FEC segments and repair state for the session.</param>
/// <param name="segmentSize">This parameter sets the maximum payload size (in bytes) of NORM sender messages (not including any NORM message header fields).</param>
/// <param name="blockSize">This parameter sets the number of source symbol segments (packets) per coding block, for the systematic Reed-Solomon FEC code used in the current NORM implementation.</param>
/// <param name="numParity">This parameter sets the maximum number of parity symbol segments (packets) the sender is willing to calculate per FEC coding block.</param>
/// <param name="fecId">Sets the NormFecType.</param>
/// <exception cref="IOException">Thrown when NormStartSender() returns false, indicating the failure to start sender.</exception>
public void StartSender(int sessionId, long bufferSpace, int segmentSize, short blockSize, short numParity, NormFecType fecId)
{
if (!NormStartSender(_handle, sessionId, bufferSpace, segmentSize, blockSize, numParity, fecId))
{
throw new IOException("Failed to start sender");
}
}
/// <summary>
/// The application's participation as a sender begins when this function is called.
/// </summary>
/// <param name="sessionId">Application-defined value used as the instance_id field of NORM sender messages for the application's participation within a session.</param>
/// <param name="bufferSpace">This specifies the maximum memory space (in bytes) the NORM protocol engine is allowed to use to buffer any sender calculated FEC segments and repair state for the session.</param>
/// <param name="segmentSize">This parameter sets the maximum payload size (in bytes) of NORM sender messages (not including any NORM message header fields).</param>
/// <param name="blockSize">This parameter sets the number of source symbol segments (packets) per coding block, for the systematic Reed-Solomon FEC code used in the current NORM implementation.</param>
/// <param name="numParity">This parameter sets the maximum number of parity symbol segments (packets) the sender is willing to calculate per FEC coding block.</param>
/// <remarks>Uses NormFecType.RS for fecId.</remarks>
/// <exception cref="IOException">Thrown when NormStartSender() returns false, indicating the failure to start sender.</exception>
public void StartSender(int sessionId, long bufferSpace, int segmentSize, short blockSize, short numParity)
{
StartSender(sessionId, bufferSpace, segmentSize, blockSize, numParity, NormFecType.RS);
}
/// <summary>
/// The application's participation as a sender begins when this function is called.
/// </summary>
/// <param name="bufferSpace">This specifies the maximum memory space (in bytes) the NORM protocol engine is allowed to use to buffer any sender calculated FEC segments and repair state for the session.</param>
/// <param name="segmentSize">This parameter sets the maximum payload size (in bytes) of NORM sender messages (not including any NORM message header fields).</param>
/// <param name="blockSize">This parameter sets the number of source symbol segments (packets) per coding block, for the systematic Reed-Solomon FEC code used in the current NORM implementation.</param>
/// <param name="numParity">This parameter sets the maximum number of parity symbol segments (packets) the sender is willing to calculate per FEC coding block.</param>
/// <param name="fecId">Sets the NormFecType.</param>
/// <remarks>Generates a random sessionId.</remarks>
/// <exception cref="IOException">Thrown when NormStartSender() returns false, indicating the failure to start sender.</exception>
public void StartSender(long bufferSpace, int segmentSize, short blockSize, short numParity, NormFecType fecId)
{
var sessionId = NormGetRandomSessionId();
StartSender(sessionId, bufferSpace, segmentSize, blockSize, numParity, fecId);
}
/// <summary>
/// The application's participation as a sender begins when this function is called.
/// </summary>
/// <param name="bufferSpace">This specifies the maximum memory space (in bytes) the NORM protocol engine is allowed to use to buffer any sender calculated FEC segments and repair state for the session.</param>
/// <param name="segmentSize">This parameter sets the maximum payload size (in bytes) of NORM sender messages (not including any NORM message header fields).</param>
/// <param name="blockSize">This parameter sets the number of source symbol segments (packets) per coding block, for the systematic Reed-Solomon FEC code used in the current NORM implementation.</param>
/// <param name="numParity">This parameter sets the maximum number of parity symbol segments (packets) the sender is willing to calculate per FEC coding block.</param>
/// <remarks>Generates a random sessionId and uses NormFecType.RS for fecId.</remarks>
/// <exception cref="IOException">Thrown when NormStartSender() returns false, indicating the failure to start sender.</exception>
public void StartSender(long bufferSpace, int segmentSize, short blockSize, short numParity)
{
StartSender(bufferSpace, segmentSize, blockSize, numParity, NormFecType.RS);
}
/// <summary>
/// This function terminates the application's participation in a NormSession as a sender. By default, the sender will
/// immediately exit the session without notifying the receiver set of its intention.
/// </summary>
public void StopSender()
{
NormStopSender(_handle);
}
/// <summary>
/// This function enqueues a file for transmission.
/// </summary>
/// <remarks>
/// This is an overload which will call FileEnqueue() with info set to encoding of the filename, infoOffset set to 0, and infoLength set to info.Length.
/// </reamarks>
/// <param name="filename">The fileName parameter specifies the path to the file to be transmitted. The NORM protocol engine
/// read and writes directly from/to file system storage for file transport, potentially providing for a very large virtual
/// "repair window" as needed for some applications. While relative paths with respect to the "current working directory"
/// may be used, it is recommended that full paths be used when possible.</param>
/// <returns>A NormFile is returned which the application may use in other NORM API calls as needed.</returns>
/// <exception cref="IOException">Thrown when NormFileEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue file.</exception>
public NormFile FileEnqueue(string filename)
{
var info = Encoding.ASCII.GetBytes(filename);
return FileEnqueue(filename, info, 0, info.Length);
}
/// <summary>
/// This function enqueues a file for transmission.
/// </summary>
/// <param name="filename">The fileName parameter specifies the path to the file to be transmitted. The NORM protocol engine
/// read and writes directly from/to file system storage for file transport, potentially providing for a very large virtual
/// "repair window" as needed for some applications. While relative paths with respect to the "current working directory"
/// may be used, it is recommended that full paths be used when possible.</param>
/// <param name="info">The optional info and infoLength parameters are used to associate NORM_INFO content with the sent transport object.</param>
/// <param name="infoOffset">Indicates the strart of the message. Anything before it will not be sent.
/// Note: to send full message infoOffset should be set to 0.</param>
/// <param name="infoLength">The optional info and infoLength parameters are used to associate NORM_INFO content with the sent transport object.</param>
/// <returns>A NormFile is returned which the application may use in other NORM API calls as needed.</returns>
/// <exception cref="IOException">Thrown when NormFileEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue file.</exception>
public NormFile FileEnqueue(string filename, byte[] info, int infoOffset, int infoLength)
{
byte[]? infoBytes;
if (info != null)
{
infoBytes = info.Skip(infoOffset).Take(infoLength).ToArray();
}
else
{
infoBytes = null;
infoLength = 0;
}
var objectHandle = NormFileEnqueue(_handle, filename, infoBytes, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
{
throw new IOException("Failed to enqueue file");
}
return new NormFile(objectHandle);
}
/// <summary>
/// This function enqueues a segment of application memory space for transmission.
/// </summary>
/// <remarks>
/// This is an overload which will call DataEnqueue() with info set to null, infoOffset set to 0, and infoLength set to 0.
/// </remarks>
/// <param name="dataBuffer">The dataBuffer is a byte array containing the message to be transmitted.</param>
/// <param name="dataOffset">Indicates the strart of the message. Anything before it will not be sent.
/// Note: to send full message dataOffset should be set to 0.</param>
/// <param name="dataLength">Size of the message.</param>
/// <returns>A NormData is returned which the application may use in other NORM API calls as needed.</returns>
/// <exception cref="IOException">Thrown when NormDataEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue data.</exception>
public NormData DataEnqueue(byte[] dataBuffer, int dataOffset, int dataLength)
{
return DataEnqueue(dataBuffer, dataOffset, dataLength, null, 0, 0);
}
/// <summary>
/// This function enqueues a segment of application memory space for transmission.
/// </summary>
/// <param name="dataBuffer">The dataBuffer is a byte array containing the message to be transmitted.</param>
/// <param name="dataOffset">Indicates the strart of the message. Anything before it will not be sent.
/// Note: to send full message dataOffset should be set to 0.</param>
/// <param name="dataLength">Size of the message.</param>
/// <param name="info">The optional info and infoLength parameters are used to associate NORM_INFO content with the sent transport object.</param>
/// <param name="infoOffset">Indicates the strart of the message.</param>
/// <param name="infoLength">The optional info and infoLength parameters are used to associate NORM_INFO content with the sent transport object.</param>
/// <returns>A NormData is returned which the application may use in other NORM API calls as needed.</returns>
/// <exception cref="IOException">Thrown when NormDataEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue data.</exception>
public NormData DataEnqueue(byte[] dataBuffer, int dataOffset, int dataLength, byte[]? info, int infoOffset, int infoLength)
{
var dataBytes = dataBuffer.Skip(dataOffset).Take(dataLength).ToArray();
byte[]? infoBytes;
if (info != null)
{
infoBytes = info.Skip(infoOffset).Take(infoLength).ToArray();
}
else
{
infoBytes = null;
infoLength = 0;
}
var objectHandle = NormDataEnqueue(_handle, dataBytes, dataLength, infoBytes, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
{
throw new IOException("Failed to enqueue data");
}
return new NormData(objectHandle);
}
/// <summary>
/// This function opens a NORM_OBJECT_STREAM sender object and enqueues it for transmission.
/// </summary>
/// <remarks>
/// No data is sent until subsequent calls to StreamWrite() are made unless
/// NORM_INFO content is specified for the stream with the info and infoLength parameters. Example usage of
/// NORM_INFO content for NORM_OBJECT_STREAM might include application-defined data typing or other information
/// which will enable NORM receiver applications to properly interpret the received stream as it is being received.
/// This is an overload which will call StreamOpen() with info set to null, infoOffset set to 0, and infoLength set to 0.
/// </remarks>
/// <param name="bufferSize">
/// The bufferSize parameter controls the size of the stream's "repair window"
/// which limits how far back the sender will "rewind" to satisfy receiver repair requests.
/// </param>
/// <returns> A NormStream is returned which the application may use in other NORM API calls as needed.</returns>
/// <exception cref="IOException">Thrown when NormStreamOpen() returns NORM_OBJECT_INVALID, indicating the failure to open stream.</exception>
public NormStream StreamOpen(long bufferSize)
{
return StreamOpen(bufferSize, null, 0, 0);
}
/// <summary>
/// This function opens a NORM_OBJECT_STREAM sender object and enqueues it for transmission.
/// </summary>
/// <remarks>
/// No data is sent until subsequent calls to NormStreamWrite() are made unless
/// NORM_INFO content is specified for the stream with the info and infoLength parameters. Example usage of
/// NORM_INFO content for NORM_OBJECT_STREAM might include application-defined data typing or other information
/// which will enable NORM receiver applications to properly interpret the received stream as it is being received.
/// </remarks>
/// <param name="bufferSize"> The bufferSize parameter controls the size of the stream's "repair window"
/// which limits how far back the sender will "rewind" to satisfy receiver repair requests.</param>
/// <param name="info">Alloted memory space for transmitted information.</param>
/// <param name="infoOffset">Indicates the strart of the message. Anything before it will not be sent.
/// Note: to send full message infoOffset should be set to 0.</param>
/// <param name="infoLength">Size of the message.</param>
/// <returns>A NormStream is returned which the application may use in other NORM API calls as needed.</returns>
/// <exception cref="IOException">Thrown when NormStreamOpen() returns NORM_OBJECT_INVALID, indicating the failure to open stream.</exception>
public NormStream StreamOpen(long bufferSize, byte[]? info, int infoOffset, int infoLength)
{
byte[]? infoBytes;
if (info != null)
{
infoBytes = info.Skip(infoOffset).Take(infoLength).ToArray();
}
else
{
infoBytes = null;
infoLength = 0;
}
var objectHandle = NormStreamOpen(_handle, bufferSize, infoBytes, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
{
throw new IOException("Failed to open stream");
}
return new NormStream(objectHandle);
}
/// <summary>
/// This function initiates the application's participation as a receiver within the NormSession.
/// </summary>
/// <param name="bufferSpace">The bufferSpace parameter is used to set a limit on the amount of bufferSpace allocated
/// by the receiver per active NormSender within the session.</param>
/// <exception cref="IOException">Thrown when NormStartReceiver() returns false, indicating the failure to start receiver.</exception>
public void StartReceiver(long bufferSpace)
{
if(!NormStartReceiver(_handle, bufferSpace))
{
throw new IOException("Failed to start receiver");
}
}
/// <summary>
/// This function ends the application's participation as a receiver in the NormSession.
/// </summary>
public void StopReceiver()
{
NormStopReceiver(_handle);
}
/// <summary>
/// This function sets the quantity of proactive "auto parity" NORM_DATA messages sent at the end of each FEC coding
/// block. By default (i.e., autoParity = 0), FEC content is sent only in response to repair requests (NACKs) from receivers.
/// </summary>
/// <param name="autoParity">Setting a non-zero value for autoParity, the sender can automatically accompany each coding
/// block of transport object source data segments ((NORM_DATA messages) with the set number of FEC segments.</param>
public void SetAutoParity(short autoParity)
{
NormSetAutoParity(_handle, autoParity);
}
/// <summary>
/// This function sets the sender's maximum advertised GRTT value.
/// </summary>
/// <param name="grttMax">The grttMax parameter, in units of seconds, limits the GRTT used by the group for scaling protocol timers, regardless
/// of larger measured round trip times. The default maximum for the NRL NORM library is 10 seconds.</param>
public void SetGrttMax(double grttMax)
{
NormSetGrttMax(_handle, grttMax);
}
/// <summary>
/// This function sets the sender's mode of probing for round trip timing measurement responses from the receiver.
/// </summary>
/// <param name="probingMode">Possible values for the probingMode parameter include NORM_PROBE_NONE, NORM_PROBE_PASSIVE, and NORM_PROBE_ACTIVE.</param>
public void SetGrttProbingMode(NormProbingMode probingMode)
{
NormSetGrttProbingMode(_handle, probingMode);
}
/// <summary>
/// This function controls the sender GRTT measurement and estimation process.
/// The NORM sender multiplexes periodic transmission of NORM_CMD(CC) messages with its ongoing data transmission
/// or when data transmission is idle.When NORM congestion control operation is enabled, these probes are sent
/// once per RTT of the current limiting receiver(with respect to congestion control rate). In this case the intervalMin
/// and intervalMax parameters (in units of seconds) control the rate at which the sender's estimate of GRTT is updated.
/// </summary>
/// <param name="intervalMin">At session start, the estimate is updated at intervalMin and the update interval time is doubled until intervalMax is reached.</param>
/// <param name="intervalMax">At session start, the estimate is updated at intervalMin and the update interval time is doubled until intervalMax is reached.</param>
public void SetGrttProbingInterval(double intervalMin, double intervalMax)
{
NormSetGrttProbingInterval(_handle, intervalMin, intervalMax);
}
/// <summary>
/// This function sets the sender's "backoff factor".
/// </summary>
/// <param name="backoffFactor">The backoffFactor (in units of seconds) is used to scale various timeouts related to the NACK repair process.</param>
public void SetBackoffFactor(double backoffFactor)
{
NormSetBackoffFactor(_handle, backoffFactor);
}
/// <summary>
/// This function sets the sender's estimate of receiver group size.
/// </summary>
/// <param name="groupSize">The sender advertises its groupSize setting to the receiver group in NORM protocol message
/// headers that, in turn, use this information to shape the distribution curve of their random timeouts for the timer-based,
/// probabilistic feedback suppression technique used in the NORM protocol.</param>
public void SetGroupSize(long groupSize)
{
NormSetGroupSize(_handle, groupSize);
}
/// <summary>
/// This routine sets the "robustness factor" used for various NORM sender functions. These functions include the
/// number of repetitions of "robustly-transmitted" NORM sender commands such as NORM_CMD(FLUSH) or similar
/// application-defined commands, and the number of attempts that are made to collect positive acknowledgement
/// from receivers.These commands are distinct from the NORM reliable data transmission process, but play a role
/// in overall NORM protocol operation.
/// </summary>
/// <param name="txRobustFactor">The default txRobustFactor value is 20. This relatively large value makes
/// the NORM sender end-of-transmission flushing and positive acknowledgement collection functions somewhat immune from packet loss.
/// Setting txRobustFactor to a value of -1 makes the redundant transmission of these commands continue indefinitely until completion.</param>
public void SetTxRobustFactor(int txRobustFactor)
{
NormSetTxRobustFactor(_handle, txRobustFactor);
}
/// <summary>
/// This function allows the application to resend (or reset transmission of) a NORM_OBJECT_FILE or NORM_OBJECT_DATA
/// transmit object that was previously enqueued for the session.
/// </summary>
/// <param name="normObject">The normObject parameter must be a valid transmit NormObject that has not yet been "purged" from the sender's transmit queue.</param>
/// <exception cref="IOException">Thrown when NormRequeueObject() returns false, indicating the failure to requeue object.</exception>
public void RequeueObject(NormObject normObject)
{
if(!NormRequeueObject(_handle, normObject.Handle))
{
throw new IOException("Failed to requeue object");
}
}
/// <summary>
/// This function specifies a "watermark" transmission point at which NORM sender protocol operation should perform
/// a flushing process and/or positive acknowledgment collection for a given sessionHandle.
/// </summary>
/// <remarks>This is an overload which will call the SetWatermark() override with overrideFlush set as false.</remarks>
/// <param name="normObject">The normObject parameter must be a valid transmit NormObject that has not yet been "purged" from the sender's transmit queue.</param>
/// <exception cref="IOException">Thrown when NormSetWatermark() returns false, indicating the failure to set watermark.</exception>
public void SetWatermark(NormObject normObject)
{
SetWatermark(normObject, false);
}
/// <summary>
/// This function specifies a "watermark" transmission point at which NORM sender protocol operation should perform
/// a flushing process and/or positive acknowledgment collection for a given sessionHandle.
/// </summary>
/// <param name="normObject">The normObject parameter must be a valid transmit NormObject that has not yet been "purged" from the sender's transmit queue.</param>
/// <param name="overrideFlush">The optional overrideFlush parameter, when set to true, causes the watermark acknowledgment process that is
/// established with this function call to potentially fully supersede the usual NORM end-of-transmission flushing
/// process that occurs. If overrideFlush is set and the "watermark" transmission point corresponds to the last
/// transmission that will result from data enqueued by the sending application, then the watermark flush completion
/// will terminate the usual flushing process</param>
/// <exception cref="IOException">Thrown when NormSetWatermark() returns false, indicating the failure to set watermark.</exception>
public void SetWatermark(NormObject normObject, bool overrideFlush)
{
if(!NormSetWatermark(_handle, normObject.Handle, overrideFlush))
{
throw new IOException("Failed to set watermark");
}
}
/// <summary>
/// This function cancels any "watermark" acknowledgement request that was previously set via the SetWatermark() function.
/// </summary>
public void CancelWatermark()
{
NormCancelWatermark(_handle);
}
/// <exception cref="IOException">Thrown when NormResetWatermark() returns false, indicating the failure to reset watermark.</exception>
public void ResetWatermark()
{
if(!NormResetWatermark(_handle))
{
throw new IOException("Failed to reset watermark");
}
}
/// <summary>
/// When this function is called, the specified nodeId is added to the list of NormNodeId values (i.e., the "acking node"
/// list) used when NORM sender operation performs positive acknowledgement (ACK) collection.
/// </summary>
/// <param name="nodeId">Identifies the application's presence in the NormSession.</param>
/// <exception cref="IOException">Thrown when NormAddAckingNode() returns false, indicating the failure to add acking node.</exception>
public void AddAckingNode(long nodeId)
{
if(!NormAddAckingNode(_handle, nodeId))
{
throw new IOException("Failed to add acking node");
}
}
/// <summary>
/// This function deletes the specified nodeId from the list of NormNodeId values used when NORM sender operation
/// performs positive acknowledgement (ACK) collection.
/// </summary>
/// <param name="nodeId">Identifies the application's presence in the NormSession.</param>
public void RemoveAckingNode(long nodeId)
{
NormRemoveAckingNode(_handle, nodeId);
}
/// <summary>
/// This function queries the status of the watermark flushing process and/or positive acknowledgment collection
/// initiated by a prior call to SetWatermark().
/// </summary>
/// <param name="nodeId">Identifies the application's presence in the NormSession.</param>
/// <returns>
/// Possible return values include:
/// NORM_ACK_INVALID - The given sessionHandle is invalid or the given nodeId is not in the sender's acking list.
/// NORM_ACK_FAILURE - The positive acknowledgement collection process did not receive acknowledgment from every listed receiver (nodeId = NORM_NODE_ANY) or the identified nodeId did not respond.
/// NORM_ACK_PENDING - The flushing process at large has not yet completed (nodeId = NORM_NODE_ANY) or the given individual nodeId is still being queried for response.
/// NORM_ACK_SUCCESS - All receivers (nodeId = NORM_NODE_ANY) responded with positive acknowledgement or the given specific nodeId did acknowledge.
/// </returns>
public NormAckingStatus GetAckingStatus(long nodeId)
{
return NormGetAckingStatus(_handle, nodeId);
}
/// <summary>
/// This function enqueues a NORM application-defined command for transmission.
/// </summary>
/// <param name="cmdBuffer">The cmdBuffer parameter points to a buffer containing the application-defined command content that will be contained in the NORM_CMD(APPLICA-TION) message payload.</param>
/// <param name="cmdLength">The cmdLength indicates the length of this content (in bytes) and MUST be less than or equal to the segmentLength value for the given session.</param>
/// <param name="robust">The command is NOT delivered reliably,
/// but can be optionally transmitted with repetition (once per GRTT) according to the NORM transmit robust factor
/// value for the given session if the robust parameter is set to true.</param>
/// <exception cref="IOException">Thrown when NormSendCommand() returns false, indicating the failure to send command.</exception>
public void SendCommand(byte[] cmdBuffer, int cmdLength, bool robust)
{
if(!NormSendCommand(_handle, cmdBuffer, cmdLength, robust))
{
throw new IOException("Failed to send command");
}
}
/// <summary>
/// This function terminates any pending NORM_CMD(APPLICATION) transmission that was previously initiated with the SendCommand() call.
/// </summary>
public void CancelCommand()
{
NormCancelCommand(_handle);
}
/// <summary>
/// This function sets a limit on the number of outstanding (pending) NormObjects for which a receiver will keep state on a per-sender basis.
/// </summary>
/// <param name="countMax">The value countMax sets a limit on the maximum consecutive range of objects that can be pending.</param>
public void SetRxCacheLimit(int countMax)
{
NormSetRxCacheLimit(_handle, countMax);
}
/// <summary>
/// This function allows the application to set an alternative, non-default buffer size for the UDP socket for packet reception.
/// </summary>
/// <param name="bufferSize">The bufferSize parameter specifies the socket buffer size in bytes.</param>
/// <exception cref="IOException">Thrown when NormSetRxSocketBuffer() returns false, indicating the failure to set rx socket buffer.</exception>
public void SetRxSocketBuffer(long bufferSize)
{
if(!NormSetRxSocketBuffer(_handle, bufferSize))
{
throw new IOException("Failed to set rx socket buffer");
}
}
/// <summary>
/// This function provides the option to configure a NORM receiver application as a "silent receiver". This mode of
/// receiver operation dictates that the host does not generate any protocol messages while operating as a receiver.
/// </summary>
/// <param name="silent">Setting the silent parameter to true enables silent receiver operation while
/// setting it to false results in normal protocol operation where feedback is provided as needed for reliability and
/// protocol operation.</param>
/// <param name="maxDelay">When the maxDelay parameter is set to a non-negative value, the value determines the maximum number
/// of FEC coding blocks (according to a NORM sender's current transmit position) the receiver will cache an incompletely-received
/// FEC block before giving the application the (incomplete) set of received source segments.</param>
public void SetSilentReceiver(bool silent, int maxDelay)
{
NormSetSilentReceiver(_handle, silent, maxDelay);
}
/// <summary>
/// This function controls the default behavior determining the destination of receiver feedback messages generated
/// while participating in the session.
/// </summary>
/// <param name="enable">If the enable parameter is true, "unicast NACKing" is enabled for new remote
/// senders while it is disabled for state equal to false.</param>
public void SetDefaultUnicastNack(bool enable)
{
NormSetDefaultUnicastNack(_handle, enable);
}
/// <summary>
/// This function sets the default "synchronization policy" used when beginning (or restarting) reception of objects
/// from a remote sender (i.e., "syncing" to the sender).
/// </summary>
/// <param name="syncPolicy">The "synchronization policy" is the behavior observed by the receiver with regards to what objects it attempts to reliably receive
/// (via transmissions of Negative Acknowledgements to the sender(s) or group as needed).</param>
public void SetDefaultSyncPolicy(NormSyncPolicy syncPolicy)
{
NormSetDefaultSyncPolicy(_handle, syncPolicy);
}
/// <summary>
/// This function sets the default "nacking mode" used when receiving objects.
/// This allows the receiver application some control of its degree of participation in the repair process. By limiting receivers
/// to only request repair of objects in which they are really interested in receiving, some overall savings in unnecessary
/// network loading might be realized for some applications and users.
/// </summary>
/// <param name="nackingMode">Specifies the nacking mode.</param>
public void SetDefaultNackingMode(NormNackingMode nackingMode)
{
NormSetDefaultNackingMode(_handle, nackingMode);
}
/// <summary>
/// This function allows the receiver application to customize at what points the receiver
/// initiates the NORM NACK repair process during protocol operation.
/// </summary>
/// <param name="repairBoundary">Specifies the repair boundary.</param>
public void SetDefaultRepairBoundary(NormRepairBoundary repairBoundary)
{
NormSetDefaultRepairBoundary(_handle, repairBoundary);
}
/// <summary>
/// This routine controls how persistently NORM receivers will maintain state for sender(s) and continue to request
/// repairs from the sender(s) even when packet reception has ceased.
/// </summary>
/// <param name="rxRobustFactor">The rxRobustFactor value determines how
/// many times a NORM receiver will self-initiate NACKing (repair requests) upon cessation of packet reception from
/// a sender. The default value is 20. Setting rxRobustFactor to -1 will make the NORM receiver infinitely persistent
/// (i.e., it will continue to NACK indefinitely as long as it is missing data content).</param>
public void SetDefaultRxRobustFactor(int rxRobustFactor)
{
NormSetDefaultRxRobustFactor(_handle, rxRobustFactor);
}
}
}

View File

@ -0,0 +1,184 @@
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// A transport object of type NORM_OBJECT_STREAM.
/// </summary>
public class NormStream : NormObject
{
/// <summary>
/// This boolean tells whether the transmit stream, specified by the streamHandle parameter,
/// has buffer space available so that the application may successfully make a call to NormStreamWrite().
/// </summary>
public bool HasVacancy
{
get
{
return NormStreamHasVacancy(_handle);
}
}
/// <summary>
/// The current read offset value for the receive stream.
/// </summary>
public long ReadOffset
{
get
{
return NormStreamGetReadOffset(_handle);
}
}
/// <summary>
/// Internal constructor for NormStream
/// </summary>
/// <param name="handle">The handle is associated to the NORM protocol engine instance</param>
internal NormStream(long handle) : base(handle)
{
}
/// <summary>
/// This function enqueues data for transmission within the NORM stream.
/// </summary>
/// <param name="buffer">The buffer parameter must be a pointer to the data to be enqueued.</param>
/// <param name="offset">The offset indicated where in the buffer to start writing the data.
/// Note: If the data is written in its entirety, offset should be set to 0.</param>
/// <param name="length">The length parameter indicates the length of the data content.</param>
/// <returns>This function returns the number of bytes of data successfully enqueued for NORM stream transmission.</returns>
public int Write(byte[] buffer, int offset, int length)
{
var bytes = buffer.Skip(offset).Take(length).ToArray();
return NormStreamWrite(_handle, bytes, length);
}
/// <summary>
/// This function allows the application to indicate to the NORM protocol engine that the last data successfully written
/// to the stream indicated by streamHandle corresponded to the end of an application-defined message boundary.
/// </summary>
public void MarkEom()
{
NormStreamMarkEom(_handle);
}
/// <summary>
/// This function causes an immediate "flush" of the transmit stream.
/// </summary>
/// <param name="eom">The optional eom parameter, when set to true, allows the sender application to mark an end-of-message indication
/// (see NormStreamMarkEom()) for the stream and initiate flushing in a single function call.</param>
/// <param name="flushMode">The default stream "flush" operation invoked via
/// NormStreamFlush() for flushMode equal to NORM_FLUSH_PASSIVE causes NORM to immediately transmit all
/// enqueued data for the stream(subject to session transmit rate limits), even if this results in NORM_DATA messages
/// with "small" payloads.If the optional flushMode parameter is set to NORM_FLUSH_ACTIVE, the application can
/// achieve reliable delivery of stream content up to the current write position in an even more proactive fashion.In
/// this case, the sender additionally, actively transmits NORM_CMD(FLUSH) messages after any enqueued stream
/// content has been sent. This immediately prompt receivers for repair requests which reduces latency of reliable
/// delivery, but at a cost of some additional messaging. Note any such "active" flush activity will be terminated upon
/// the next subsequent write to the stream.If flushMode is set to NORM_FLUSH_NONE, this call has no effect other than
/// the optional end-of-message marking described here. </param>
public void Flush(bool eom, NormFlushMode flushMode)
{
NormStreamFlush(_handle, eom, flushMode);
}
/// <summary>
/// This function causes an immediate "flush" of the transmit stream.
/// </summary>
/// <remarks>
/// This is a default function which calls Flush(bool eom, NormFlushMode flushMode) override
/// with eom set as false and flushMode set to NORM_FLUSH_PASSIVE
/// </remarks>
public void Flush()
{
Flush(false, NormFlushMode.NORM_FLUSH_PASSIVE);
}
/// <summary>
/// This function halts transfer of the stream and releases any resources used unless the associated object
/// has been explicitly retained by a call to NormObjectRetain().
/// </summary>
/// <param name="graceful">The optional graceful parameter, when
/// set to a value of true, may be used by NORM senders to initiate "graceful" shutdown of a transmit stream.</param>
public void Close(bool graceful)
{
NormStreamClose(_handle, graceful);
}
/// <summary>
/// This function halts transfer of the stream and releases any resources used unless the associated object
/// has been explicitly retained by a call to NormObjectRetain().
/// </summary>
/// <remarks>
/// This is a default function which calls Close(bool graceful) override
/// with graceful set as false.
/// </remarks>
public void Close()
{
Close(false);
}
/// <summary>
/// This function can be used by the receiver application to read any available data from an incoming NORM stream.
/// </summary>
/// <param name="buffer">The buffer parameter must be a pointer to an array where the received
/// data can be stored of a length as referenced by the length parameter. </param>
/// <param name="offset">Indicates where in the buffer to start reading the data.
/// Note: To read the data in its entirety, begin at offset 0.</param>
/// <param name="length">Expected length of data received</param>
/// <returns>The length of data received</returns>
public int Read(byte[] buffer, int offset, int length)
{
var bytes = new byte[length];
if (!NormStreamRead(_handle, bytes, ref length))
{
return -1;
}
for (var i = 0; i < length; i++)
{
var bufferPosition = offset + i;
if (bufferPosition < buffer.Length)
{
buffer[bufferPosition] = bytes[i];
}
}
return length;
}
/// <summary>
/// This function advances the read offset of the receive stream referenced by the streamHandle parameter to align
/// with the next available message boundary
/// </summary>
/// <returns>
/// This function returns a value of true when start-of-message is found. The next call to NormStreamRead() will
/// retrieve data aligned with the message start. If no new message boundary is found in the buffered receive data for
/// the stream, the function returns a value of false. In this case, the application should defer repeating a call to this
/// function until a subsequent NORM_RX_OBJECT_UPDATE notification is posted.</returns>
public bool SeekMsgStart()
{
return NormStreamSeekMsgStart(_handle);
}
/// <summary>
/// This function controls how the NORM API behaves when the application attempts to enqueue new stream data for transmission
/// when the associated stream's transmit buffer is fully occupied with data pending original or repair transmission.
/// </summary>
/// <param name="pushEnable"> By default (pushEnable = false), a call to NormStreamWrite() will return a zero value under this
/// condition, indicating it was unable to enqueue the new data. However, if pushEnable is set to true for a given
/// streamHandle, the NORM protocol engine will discard the oldest buffered stream data(even if it is pending repair
/// transmission or has never been transmitted) as needed to enqueue the new data.</param>
public void SetPushEnable(bool pushEnable)
{
NormStreamSetPushEnable(_handle, pushEnable);
}
/// <summary>
/// This function sets "automated flushing" for the NORM transmit stream indicated by the streamHandle parameter.
/// </summary>
/// <param name="flushMode">Possible values for the flushMode parameter include NORM_FLUSH_NONE, NORM_FLUSH_PASSIVE, and NORM_FLUSH_ACTIVE.</param>
public void SetAutoFlush(NormFlushMode flushMode)
{
NormStreamSetAutoFlush(_handle, flushMode);
}
}
}

View File

@ -0,0 +1,3 @@
global using static Mil.Navy.Nrl.Norm.NormApi;
global using NormEvent = Mil.Navy.Nrl.Norm.NormEvent;
global using Mil.Navy.Nrl.Norm.Enums;

View File

@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bogus" Version="34.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Mil.Navy.Nrl.Norm\Mil.Navy.Nrl.Norm.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy ..\..\..\..\build\norm*.dll $(TargetDir)&#xD;&#xA;cd $(TargetDir)&#xD;&#xA;del /f norm.dll&#xD;&#xA;ren norm*.dll norm.dll" Condition="'$(OS)' == 'Windows_NT'" />
<Exec Command="cp -f ../../../../build/libnorm.so $(TargetDir)norm.so" Condition="'$(OS)' != 'Windows_NT'" />
</Target>
</Project>

View File

@ -0,0 +1,261 @@
using Bogus;
using System.Text;
namespace Mil.Navy.Nrl.Norm.IntegrationTests
{
/// <summary>
/// Tests for NORM instance
/// </summary>
public class NormInstanceTests : IDisposable
{
/// <summary>
/// The NORM instance
/// </summary>
private NormInstance _normInstance;
private NormSession? _normSession;
/// <summary>
/// Determines if the NORM instance has been destroyed
/// </summary>
private bool _isDestroyed;
private string _testPath;
private void CreateTestDirectory()
{
if (!Directory.Exists(_testPath))
{
Directory.CreateDirectory(_testPath);
}
}
private void DeleteTestDirectory()
{
if (Directory.Exists(_testPath))
{
Directory.Delete(_testPath, true);
}
}
/// <summary>
/// Default constructor for NORM instance tests
/// </summary>
/// <remarks>
/// Creates the NORM instance.
/// Initializes _isDestroyed to false.
/// </remarks>
public NormInstanceTests()
{
_normInstance = new NormInstance();
_isDestroyed = false;
var currentDirectory = Directory.GetCurrentDirectory();
_testPath = Path.Combine(currentDirectory, Guid.NewGuid().ToString());
CreateTestDirectory();
}
/// <summary>
/// Destroy the NORM instance
/// </summary>
private void DestroyInstance()
{
if (!_isDestroyed)
{
_normSession?.DestroySession();
_normInstance.CloseDebugLog();
_normInstance.DestroyInstance();
_isDestroyed = true;
}
}
/// <summary>
/// Dispose destroys the NORM instance
/// </summary>
public void Dispose()
{
DestroyInstance();
DeleteTestDirectory();
}
/// <summary>
/// Test for creating a NORM instance
/// </summary>
[Fact]
public void CreatesNormInstance()
{
Assert.NotNull(_normInstance);
}
/// <summary>
/// Test for creating a NORM instance
/// </summary>
[Fact]
public void CreatesNormInstanceWithPriorityBoost()
{
_normInstance.DestroyInstance();
_normInstance = new NormInstance(true);
Assert.NotNull(_normInstance);
}
/// <summary>
/// Test for destroying a NORM instance
/// </summary>
[Fact]
public void DestroysNormInstance()
{
DestroyInstance();
}
/// <summary>
/// Test for creating a NORM session
/// </summary>
[Fact]
public void CreatesSession()
{
var faker = new Faker();
var sessionAddress = "224.1.2.3";
var sessionPort = faker.Internet.Port();
var localNodeId = NormNode.NORM_NODE_ANY;
_normSession = _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId);
Assert.NotNull(_normSession);
}
/// <summary>
/// Test for throwing an exception when attempting to create a NORM session with an invalid session address
/// </summary>
[Fact]
public void CreateSessionThrowsExceptionForInvalidSessionAddress()
{
var sessionAddress = "999.999.999.999";
var sessionPort = 6003;
var localNodeId = NormNode.NORM_NODE_ANY;
Assert.Throws<IOException>(() => _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId));
}
[Fact]
public void StopInstance()
{
var sessionAddress = "224.1.2.3";
var sessionPort = 6003;
var localNodeId = NormNode.NORM_NODE_ANY;
_normSession = _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId);
_normInstance.StopInstance();
}
[Fact]
public void RestartInstance()
{
var sessionAddress = "224.1.2.3";
var sessionPort = 6003;
var localNodeId = NormNode.NORM_NODE_ANY;
var expected = true;
_normSession = _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId);
_normInstance.StopInstance();
var actual = _normInstance.RestartInstance();
Assert.Equal(expected,actual);
}
[Fact]
public void SuspendInstance()
{
var sessionAddress = "224.1.2.3";
var sessionPort = 6003;
var localNodeId = NormNode.NORM_NODE_ANY;
var expected = true;
_normSession = _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId);
_normInstance.StopInstance();
var actual = _normInstance.SuspendInstance();
Assert.Equal(expected,actual);
}
[Fact]
public void ResumeInstance()
{
var sessionAddress = "224.1.2.3";
var sessionPort = 6003;
var localNodeId = NormNode.NORM_NODE_ANY;
_normSession = _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId);
_normInstance.StopInstance();
_normInstance.ResumeInstance();
Assert.NotNull(_normInstance);
}
[Fact]
public void OpenDebugLog(){
var fileName = Guid.NewGuid().ToString();
var filePath = Path.Combine(_testPath, fileName);
_normInstance.OpenDebugLog(filePath);
}
[Fact]
public void CloseDebugLog()
{
_normInstance.CloseDebugLog();
}
[Fact]
public void OpensDebugPipe()
{
var pipename = "test.pipe";
Assert.Throws<IOException>(() => _normInstance.OpenDebugPipe(pipename));
}
[Fact]
public void SetsDebugLevel()
{
var expectedDebugLevel = 12;
_normInstance.DebugLevel = expectedDebugLevel;
var actualDebugLevel = _normInstance.DebugLevel;
Assert.Equal(expectedDebugLevel, actualDebugLevel);
}
[Fact]
public void HasEventsFromTimeSpan()
{
var faker = new Faker();
var sessionAddress = "224.1.2.3";
var sessionPort = faker.Internet.Port();
var localNodeId = NormNode.NORM_NODE_ANY;
_normSession = _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId);
_normSession.StartSender(1024 * 1024, 1400, 64, 16);
var dataContent = faker.Lorem.Paragraph();
var data = Encoding.ASCII.GetBytes(dataContent);
_normSession.DataEnqueue(data, 0, data.Length);
Assert.True(_normInstance.HasNextEvent(TimeSpan.FromSeconds(1.5)));
_normSession.StopSender();
}
[Fact]
public void HasEventsFromSecondsAndMicroseconds()
{
var faker = new Faker();
var sessionAddress = "224.1.2.3";
var sessionPort = faker.Internet.Port();
var localNodeId = NormNode.NORM_NODE_ANY;
_normSession = _normInstance.CreateSession(sessionAddress, sessionPort, localNodeId);
_normSession.StartSender(1024 * 1024, 1400, 64, 16);
var dataContent = faker.Lorem.Paragraph();
var data = Encoding.ASCII.GetBytes(dataContent);
_normSession.DataEnqueue(data, 0, data.Length);
Assert.True(_normInstance.HasNextEvent(1, 500000));
_normSession.StopSender();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
global using Xunit;