NormDataEnqueue Refactor (#34)

* Updated to use SafeBuffer

* Added ByteBuffer and DirectByteBuffer

* Added pointer overload to DataEnqueue

* Updated FileEnqueue() to use pointer arithmetic

* Updated NormStream to use pointer arithmetic

* Updated NormSendCommand to nint

* Updated NormNodeGetCommand to nint

* Updated NormNodeGetAddress to use nint for buffer

* Updated NormStreamRead to use nint for buffer

* Updated NormObjectGetInfo to use nint for buffer

* Updated NormFileGetName nameBuffer to nint
pull/85/head
mullerj 2024-07-29 08:58:08 -04:00 committed by GitHub
parent 0eb0b82fa0
commit d539a35a73
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 1217 additions and 445 deletions

View File

@ -0,0 +1,7 @@
@startuml
abstract class ByteBuffer {
# ByteBuffer()
+ {static} AllocateDirect(capacity:int) : ByteBuffer
}
SafeBuffer <|-- ByteBuffer
@enduml

View File

@ -0,0 +1,7 @@
@startuml
class DirectByteBuffer <<sealed>> {
<<internal>> DirectByteBuffer(capacity:int)
# <<override>> ReleaseHandle() : bool
}
ByteBuffer <|-- DirectByteBuffer
@enduml

View File

@ -1,8 +1,8 @@
@startuml
enum NormAckingStatus {
NORM_ACK_INVALID
NORM_ACK_FAILURE
NORM_ACK_PENDING
NORM_ACK_SUCCESS
NORM_ACK_INVALID,
NORM_ACK_FAILURE,
NORM_ACK_PENDING,
NORM_ACK_SUCCESS,
}
@enduml
@enduml

View File

@ -1,33 +1,33 @@
@startuml
enum NormEventType {
NORM_EVENT_INVALID
NORM_TX_QUEUE_VACANCY
NORM_TX_QUEUE_EMPTY
NORM_TX_FLUSH_COMPLETED
NORM_TX_WATERMARK_COMPLETED
NORM_TX_CMD_SENT
NORM_TX_OBJECT_SENT
NORM_TX_OBJECT_PURGED
NORM_TX_RATE_CHANGED
NORM_LOCAL_SENDER_CLOSED
NORM_REMOTE_SENDER_NEW
NORM_REMOTE_SENDER_RESET
NORM_REMOTE_SENDER_ADDRESS
NORM_REMOTE_SENDER_ACTIVE
NORM_REMOTE_SENDER_INACTIVE
NORM_REMOTE_SENDER_PURGED
NORM_RX_CMD_NEW
NORM_RX_OBJECT_NEW
NORM_RX_OBJECT_INFO
NORM_RX_OBJECT_UPDATED
NORM_RX_OBJECT_COMPLETED
NORM_RX_OBJECT_ABORTED
NORM_RX_ACK_REQUEST
NORM_GRTT_UPDATED
NORM_CC_ACTIVE
NORM_CC_INACTIVE
NORM_ACKING_NODE_NEW
NORM_SEND_ERROR
NORM_USER_TIMEOUT
NORM_EVENT_INVALID,
NORM_TX_QUEUE_VACANCY,
NORM_TX_QUEUE_EMPTY,
NORM_TX_FLUSH_COMPLETED,
NORM_TX_WATERMARK_COMPLETED,
NORM_TX_CMD_SENT,
NORM_TX_OBJECT_SENT,
NORM_TX_OBJECT_PURGED,
NORM_TX_RATE_CHANGED,
NORM_LOCAL_SENDER_CLOSED,
NORM_REMOTE_SENDER_NEW,
NORM_REMOTE_SENDER_RESET,
NORM_REMOTE_SENDER_ADDRESS,
NORM_REMOTE_SENDER_ACTIVE,
NORM_REMOTE_SENDER_INACTIVE,
NORM_REMOTE_SENDER_PURGED,
NORM_RX_CMD_NEW,
NORM_RX_OBJECT_NEW,
NORM_RX_OBJECT_INFO,
NORM_RX_OBJECT_UPDATED,
NORM_RX_OBJECT_COMPLETED,
NORM_RX_OBJECT_ABORTED,
NORM_RX_ACK_REQUEST,
NORM_GRTT_UPDATED,
NORM_CC_ACTIVE,
NORM_CC_INACTIVE,
NORM_ACKING_NODE_NEW,
NORM_SEND_ERROR,
NORM_USER_TIMEOUT,
}
@enduml
@enduml

View File

@ -1,7 +1,7 @@
@startuml
enum NormFecType {
RS
RS8
SB
RS,
RS8,
SB,
}
@enduml
@enduml

View File

@ -1,7 +1,7 @@
@startuml
enum NormFlushMode {
NORM_FLUSH_NONE
NORM_FLUSH_PASSIVE
NORM_FLUSH_ACTIVE
NORM_FLUSH_NONE,
NORM_FLUSH_PASSIVE,
NORM_FLUSH_ACTIVE,
}
@enduml
@enduml

View File

@ -1,7 +1,7 @@
@startuml
enum NormNackingMode {
NORM_NACK_NONE
NORM_NACK_INFO_ONLY
NORM_NACK_NORMAL
NORM_NACK_NONE,
NORM_NACK_INFO_ONLY,
NORM_NACK_NORMAL,
}
@enduml
@enduml

View File

@ -1,8 +1,8 @@
@startuml
enum NormObjectType {
NORM_OBJECT_NONE
NORM_OBJECT_DATA
NORM_OBJECT_FILE
NORM_OBJECT_STREAM
NORM_OBJECT_NONE,
NORM_OBJECT_DATA,
NORM_OBJECT_FILE,
NORM_OBJECT_STREAM,
}
@enduml
@enduml

View File

@ -1,7 +1,7 @@
@startuml
enum NormProbingMode {
NORM_PROBE_NONE
NORM_PROBE_PASSIVE
NORM_PROBE_ACTIVE
NORM_PROBE_NONE,
NORM_PROBE_PASSIVE,
NORM_PROBE_ACTIVE,
}
@enduml
@enduml

View File

@ -1,6 +1,6 @@
@startuml
enum NormRepairBoundary {
NORM_BOUNDARY_BLOCK
NORM_BOUNDARY_OBJECT
NORM_BOUNDARY_BLOCK,
NORM_BOUNDARY_OBJECT,
}
@enduml
@enduml

View File

@ -1,7 +1,7 @@
@startuml
enum NormSyncPolicy {
NORM_SYNC_CURRENT
NORM_SYNC_STREAM
NORM_SYNC_ALL
NORM_SYNC_CURRENT,
NORM_SYNC_STREAM,
NORM_SYNC_ALL,
}
@enduml
@enduml

View File

@ -2,4 +2,4 @@
interface INormEventListener {
NormEventOccurred(normEvent:NormEvent) : void
}
@enduml
@enduml

View File

@ -1,32 +1,30 @@
@startuml
class NormInputStream {
- _normInstance : NormInstance
- _normSession : NormSession
- _normStream : NormStream
- _normEventListeners : List<INormEventListener>
- _normStream : NormStream?
- _closed : bool
- _closeLock : object
- _bufferIsEmpty : bool
- _receivedEof : bool
+ NormInputStream(address:string, port:int)
+ OpenDebugLog(filename:string) : void
+ SetDebugLevel(level:int) : void
+ OpenDebugLog(fileName:string) : void
+ CloseDebugLog() : void
+ NormSetDebugLevel(level:int) : void
+ SetMessageTrace(messageTrace:bool) : void
+ SetMulticastInterface(multicastInterface: string) : void
+ SetEcnSupport(ecnEnable:bool, ignoreLoss:bool)
+ SetMulticastInterface(multicastInterface:string) : void
+ SetEcnSupport(ecnEnable:bool, ignoreLoss:bool) : void
+ SetTtl(ttl:byte) : void
+ SetTos(tos:byte) : void
+ SetSilentReceiver(silent:bool, maxDelay:int) : void
+ setSilentReceiver(silent:bool, maxDelay:int) : void
+ SetDefaultUnicastNack(defaultUnicastNack:bool) : void
+ SeekMsgStart() : void
+ AddNormEventListener(normEventListener:INormEventListener) : void
+ RemoveNormEventListener(normEventListener:INormEventListener) : void
- FireNormEventOccured(normEvent:NormEvent) : void
+ Open(bufferSpace:long) : void
+ <<override>> Dispose() : void
+ <<override>> Close() : void
+ IsClosed : bool <<get>>
+ Read() : int
+ <<override>> Read(buffer:byte[], offset:int, length:int) : int
+ <<override>> Read(buffer:byte[], offset:int, count:int) : int
- ProcessEvent() : void
+ <<override>> Flush() : void
+ <<override>> Write(buffer:byte[], offset:int, count:int) : void
@ -38,5 +36,10 @@ class NormInputStream {
+ <<override>> Length : long <<get>>
+ <<override>> Position : long <<get>> <<set>>
}
class "List`1"<T> {
}
Stream <|-- NormInputStream
NormInputStream --> "_normInstance" NormInstance
NormInputStream --> "_normSession" NormSession
NormInputStream --> "_normEventListeners<INormEventListener>" "List`1"
@enduml

View File

@ -1,9 +1,6 @@
@startuml
class NormOutputStream {
- _normInstance : NormInstance
- _normSession : NormSession
- _normStream : NormStream
- _normEventListeners : List<INormEventListener>
- _normStream : NormStream?
- _closed : bool
- _closeLock : object
- _bufferIsFull : bool
@ -13,13 +10,13 @@ class NormOutputStream {
+ SetDebugLevel(level:int) : void
+ SetMessageTrace(messageTrace:bool) : void
+ SetMulticastInterface(multicastInterface:string) : void
+ SetEcnSupport(ecnEnable:bool, ignoreLoss:bool): void
+ SetEcnSupport(ecnEnable:bool, ignoreLoss:bool) : void
+ SetTtl(ttl:byte) : void
+ SetTos(tos:byte) : void
+ SetCongestionControl(ccEnabled:bool, ccAdjustRate: bool) : void
+ SetCongestionControl(ccEnabled:bool, ccAdjustRate:bool) : void
+ SetTxRateBounds(minTxRate:double, maxTxRate:double) : void
+ TxRate:double <<get>> <<set>>
+ GrttEstimate:double <<get>> <<set>>
+ TxRate : double <<get>> <<set>>
+ GrttEstimate : double <<get>> <<set>>
+ SetGroupSize(groupSize:long) : void
+ SetAutoParity(autoParity:short) : void
+ SetBackoffFactor(backoffFactor:double) : void
@ -27,16 +24,16 @@ class NormOutputStream {
+ SetPushEnable(pushEnable:bool) : void
+ MarkEom() : void
+ AddNormEventListener(normEventListener:INormEventListener) : void
+ RemoveNormEventListener(normEventListener:INormEventListener): void
+ RemoveNormEventListener(normEventListener:INormEventListener) : void
- FireNormEventOccured(normEvent:NormEvent) : void
+ Open(sessionId:int, bufferSpace:long, segmentSize:int, blockSize:short, numParity:short, repairWindow:long) : void
+ <<override>> Close() : void
+ IsClosed : bool <<get>>
+ Write(b:int) : void
+ <<override>> Write(buffer:byte[], offset:int, count:int)
+ <<override>> Write(buffer:byte[], offset:int, count:int) : void
- ProcessEvent() : void
+ <<override>> Flush() : void
+ <<override>> Read(buffer:byte[], offset:int, length:int) : int
+ <<override>> Read(buffer:byte[], offset:int, count:int) : int
+ <<override>> Seek(offset:long, origin:SeekOrigin) : long
+ <<override>> SetLength(value:long) : void
+ <<override>> CanRead : bool <<get>>
@ -45,5 +42,10 @@ class NormOutputStream {
+ <<override>> Length : long <<get>>
+ <<override>> Position : long <<get>> <<set>>
}
class "List`1"<T> {
}
Stream <|-- NormOutputStream
@enduml
NormOutputStream --> "_normInstance" NormInstance
NormOutputStream --> "_normSession" NormSession
NormOutputStream --> "_normEventListeners<INormEventListener>" "List`1"
@enduml

View File

@ -1,6 +1,6 @@
@startuml
class StreamBreakException {
+ StreamBreakException(message:string)
+ StreamBreakException(message:string?)
}
IOException <|-- StreamBreakException
@enduml
@enduml

View File

@ -1,119 +1,119 @@
@startuml
struct NormEvent
{
+ Type : NormEventType
@startuml
class NormApi <<static>> {
+ <<const>> NORM_LIBRARY : string = "norm"
+ {static} <<extern>> NormCreateInstance(priorityBoost:bool) : long
+ {static} <<extern>> NormDestroyInstance(instanceHandle:long) : void
+ {static} <<extern>> NormStopInstance(instanceHandle:long) : void
+ {static} <<extern>> NormRestartInstance(instanceHandle:long) : bool
+ {static} <<extern>> NormSuspendInstance(instanceHandle:long) : bool
+ {static} <<extern>> NormResumeInstance(instanceHandle:long) : bool
+ {static} <<extern>> NormSetCacheDirectory(instanceHandle:long, cachePath:string) : bool
+ {static} <<extern>> NormGetNextEvent(instanceHandle:long, theEvent:NormEvent, waitForEvent:bool) : bool
+ {static} <<extern>> NormGetDescriptor(instanceHandle:long) : int
+ {static} <<extern>> NormCreateSession(instanceHandle:long, sessionAddress:string, sessionPort:int, localNodeId:long) : long
+ {static} <<extern>> NormDestroySession(sessionHandle:long) : void
+ {static} <<extern>> NormGetLocalNodeId(sessionHandle:long) : long
+ {static} <<extern>> NormSetTxPort(sessionHandle:long, txPortNumber:int, enableReuse:bool, txBindAddress:string?) : bool
+ {static} <<extern>> NormSetTxOnly(sessionHandle:long, txOnly:bool, connectToSessionAddress:bool) : void
+ {static} <<extern>> NormSetRxPortReuse(sessionHandle:long, enableReuse:bool, rxBindAddress:string?, senderAddress:string?, senderPort:int) : void
+ {static} <<extern>> NormSetEcnSupport(sessionHandle:long, ecnEnable:bool, ignoreLoss:bool, tolerateLoss:bool) : void
+ {static} <<extern>> NormSetMulticastInterface(sessionHandle:long, interfaceName:string) : bool
+ {static} <<extern>> NormSetSSM(sessionHandle:long, sourceAddress:string) : bool
+ {static} <<extern>> NormSetTTL(sessionHandle:long, ttl:byte) : bool
+ {static} <<extern>> NormSetTOS(sessionHandle:long, tos:byte) : bool
+ {static} <<extern>> NormSetLoopback(sessionHandle:long, loopback:bool) : bool
+ {static} <<extern>> NormSetMessageTrace(sessionHandle:long, flag:bool) : void
+ {static} <<extern>> NormSetTxLoss(sessionHandle:long, precent:double) : void
+ {static} <<extern>> NormSetRxLoss(sessionHandle:long, precent:double) : void
+ {static} <<extern>> NormOpenDebugLog(instanceHandle:long, path:string) : bool
+ {static} <<extern>> NormCloseDebugLog(instanceHandle:long) : bool
+ {static} <<extern>> NormOpenDebugPipe(instanceHandle:long, pipeName:string) : bool
+ {static} <<extern>> NormSetDebugLevel(level:int) : void
+ {static} <<extern>> NormGetDebugLevel() : int
+ {static} <<extern>> NormSetReportInterval(sessionHandle:long, interval:double) : void
+ {static} <<extern>> NormGetReportInterval(sessionHandle:long) : double
+ {static} <<extern>> NormGetRandomSessionId() : int
+ {static} <<extern>> NormStartSender(instanceHandle:long, instanceId:int, bufferSpace:long, segmentSize:int, numData:short, numParity:short, fecId:NormFecType) : bool
+ {static} <<extern>> NormStopSender(sessionHandle:long) : void
+ {static} <<extern>> NormSetTxRate(sessionHandle:long, rate:double) : void
+ {static} <<extern>> NormGetTxRate(sessionHandle:long) : double
+ {static} <<extern>> NormSetTxSocketBuffer(sessionHandle:long, bufferSize:long) : bool
+ {static} <<extern>> NormSetFlowControl(sessionHandle:long, flowControlFactor:double) : void
+ {static} <<extern>> NormSetCongestionControl(sessionHandle:long, enable:bool, adjustRate:bool) : void
+ {static} <<extern>> NormSetTxRateBounds(sessionHandle:long, rateMin:double, rateMax:double) : void
+ {static} <<extern>> NormSetTxCacheBounds(sessionHandle:long, sizeMax:long, countMin:long, countMax:long) : void
+ {static} <<extern>> NormSetAutoParity(sesssionHandle:long, autoParity:short) : void
+ {static} <<extern>> NormSetGrttEstimate(sessionHandle:long, grtt:double) : void
+ {static} <<extern>> NormGetGrttEstimate(sessionHandle:long) : double
+ {static} <<extern>> NormSetGrttMax(sessionHandle:long, grttMax:double) : void
+ {static} <<extern>> NormSetGrttProbingMode(sesssionHandle:long, probingMode:NormProbingMode) : void
+ {static} <<extern>> NormSetGrttProbingInterval(sessionHandle:long, intervalMin:double, intervalMax:double) : void
+ {static} <<extern>> NormSetBackoffFactor(sessionHandle:long, backoffFactor:double) : void
+ {static} <<extern>> NormSetGroupSize(sessionHandle:long, groupSize:long) : void
+ {static} <<extern>> NormSetTxRobustFactor(sessionHandle:long, txRobustFactor:int) : void
+ {static} <<extern>> NormFileEnqueue(sessionHandle:long, fileName:string, infoPtr:nint, infoLen:int) : long
+ {static} <<extern>> NormDataEnqueue(sessionHandle:long, dataPtr:nint, dataLen:int, infoPtr:nint, infoLen:int) : long
+ {static} <<extern>> NormRequeueObject(sessionHandle:long, objectHandle:long) : bool
+ {static} <<extern>> NormStreamOpen(sessionHandle:long, bufferSize:long, infoPtr:nint, infoLen:int) : long
+ {static} <<extern>> NormStreamClose(streamHandle:long, graceful:bool) : void
<<internal>> {static} <<extern>> NormStreamWrite(streamHandle:long, buffer:nint, numBytes:int) : int
+ {static} <<extern>> NormStreamFlush(streamHandle:long, eom:bool, flushMode:NormFlushMode) : void
+ {static} <<extern>> NormStreamSetAutoFlush(streamHandle:long, flushMode:NormFlushMode) : void
+ {static} <<extern>> NormStreamSetPushEnable(streamHandle:long, pushEnable:bool) : void
+ {static} <<extern>> NormStreamHasVacancy(streamHandle:long) : bool
+ {static} <<extern>> NormStreamMarkEom(streamHandle:long) : void
+ {static} <<extern>> NormSetWatermark(sessionHandle:long, objectHandle:long, overrideFlush:bool) : bool
+ {static} <<extern>> NormResetWatermark(sessionHandle:long) : bool
+ {static} <<extern>> NormCancelWatermark(sessionHandle:long) : void
+ {static} <<extern>> NormAddAckingNode(sessionHandle:long, nodeId:long) : bool
+ {static} <<extern>> NormRemoveAckingNode(sessionHandle:long, nodeId:long) : void
+ {static} <<extern>> NormGetAckingStatus(sessionHandle:long, nodeId:long) : NormAckingStatus
+ {static} <<extern>> NormSendCommand(sessionHandle:long, cmdBuffer:nint, cmdLength:int, robust:bool) : bool
+ {static} <<extern>> NormCancelCommand(sessionHandle:long) : void
+ {static} <<extern>> NormStartReceiver(sessionHandle:long, bufferSpace:long) : bool
+ {static} <<extern>> NormStopReceiver(sessionHandle:long) : void
+ {static} <<extern>> NormSetRxCacheLimit(sessionHandle:long, countMax:int) : void
+ {static} <<extern>> NormSetRxSocketBuffer(sessionHandle:long, bufferSize:long) : bool
+ {static} <<extern>> NormSetSilentReceiver(sessionHandle:long, silent:bool, maxDelay:int) : void
+ {static} <<extern>> NormSetDefaultUnicastNack(sessionHandle:long, unicastNacks:bool) : void
+ {static} <<extern>> NormNodeSetUnicastNack(remoteSender:long, unicastNacks:bool) : void
+ {static} <<extern>> NormSetDefaultSyncPolicy(sessionHandle:long, syncPolicy:NormSyncPolicy) : void
+ {static} <<extern>> NormSetDefaultNackingMode(sessionHandle:long, nackingMode:NormNackingMode) : void
+ {static} <<extern>> NormNodeSetNackingMode(remoteSender:long, nackingMode:NormNackingMode) : void
+ {static} <<extern>> NormObjectSetNackingMode(objectHandle:long, nackingMode:NormNackingMode) : void
+ {static} <<extern>> NormSetDefaultRepairBoundary(sessionHandle:long, repairBoundary:NormRepairBoundary) : void
+ {static} <<extern>> NormNodeSetRepairBoundary(remoteSender:long, repairBoundary:NormRepairBoundary) : void
+ {static} <<extern>> NormSetDefaultRxRobustFactor(sessionHandle:long, robustFactor:int) : void
+ {static} <<extern>> NormNodeSetRxRobustFactor(remoteSender:long, robustFactor:int) : void
+ {static} <<extern>> NormStreamRead(streamHandle:long, buffer:nint, numBytes:int) : bool
+ {static} <<extern>> NormStreamSeekMsgStart(streamHandle:long) : bool
+ {static} <<extern>> NormStreamGetReadOffset(streamHandle:long) : long
+ {static} <<extern>> NormObjectGetType(objectHandle:long) : NormObjectType
+ {static} <<extern>> NormObjectHasInfo(objectHandle:long) : bool
+ {static} <<extern>> NormObjectGetInfoLength(objectHandle:long) : int
+ {static} <<extern>> NormObjectGetInfo(objectHandle:long, buffer:nint, bufferLen:int) : int
+ {static} <<extern>> NormObjectGetSize(objectHandle:long) : int
+ {static} <<extern>> NormObjectGetBytesPending(objectHandle:long) : long
+ {static} <<extern>> NormObjectCancel(objectHandle:long) : void
+ {static} <<extern>> NormObjectRetain(objectHandle:long) : void
+ {static} <<extern>> NormObjectRelease(objectHandle:long) : void
+ {static} <<extern>> NormFileGetName(fileHandle:long, nameBuffer:nint, bufferLen:int) : bool
+ {static} <<extern>> NormFileRename(fileHandle:long, fileName:string) : bool
+ {static} <<extern>> NormDataAccessData(objectHandle:long) : nint
+ {static} <<extern>> NormObjectGetSender(objectHandle:long) : long
+ {static} <<extern>> NormNodeGetId(nodeHandle:long) : long
+ {static} <<extern>> NormNodeGetAddress(nodeHandle:long, addrBuffer:nint, bufferLen:int, port:int) : bool
+ {static} <<extern>> NormNodeGetGrtt(nodeHandle:long) : double
+ {static} <<extern>> NormNodeGetCommand(remoteSender:long, cmdBuffer:nint, buflen:int) : bool
+ {static} <<extern>> NormNodeFreeBuffers(remoteSender:long) : void
+ {static} <<extern>> NormNodeRetain(nodeHandle:long) : void
+ {static} <<extern>> NormNodeRelease(nodeHandle:long) : void
}
struct NormEvent {
+ Session : long
+ Sender : long
+ Object : long
}
class NormApi
{
+ <<const>> NORM_LIBRARY : string = "norm"
+ {static} NormCreateInstance(priorityBoost:bool) : long
+ {static} NormDestroyInstance(instanceHandle:long) : void
+ {static} NormStopInstance(instanceHandle:long) : void
+ {static} NormRestartInstance(instanceHandle:long) : bool
+ {static} NormSuspendInstance(instanceHandle:long) : bool
+ {static} NormResumeInstance(instanceHandle:long) : void
+ {static} NormSetCacheDirectory(instanceHandle:long, cachePath:string) : bool
+ {static} NormGetNextEvent(instanceHandle:long, theEvent:NormEvent, waitForEvent:bool) : bool
+ {static} NormGetDescriptor(instanceHandle:long) : int
+ {static} NormCreateSession(instanceHandle:long, sessionAddress:string, sessionPort:int, localNodeId:long) : long
+ {static} NormDestroySession(sessionHandle:long) : void
+ {static} NormGetLocalNodeId(sessionHandle:long) : long
+ {static} NormSetTxPort(sessionHandle:long, txPortNumber:int, enableReuse:bool, txBindAddress:string) : bool
+ {static} NormSetTxOnly(sessionHandle:long, txOnly:bool, connectToSessionAddress: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} 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} NormSetDebugLevel(level:int) : void
+ {static} NormGetDebugLevel() : int
+ {static} NormSetReportInterval(sessionHandle:long, interval:double) : void
+ {static} NormGetRandomSessionId() : int
+ {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:long) : bool
+ {static} NormSetFlowControl(sessionHandle:long, flowControlFactor:double) : 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
+ {static} NormSetAutoParity(sessionHandle:long, autoParity:byte) : void
+ {static} NormSetGrttEstimate(sessionHandle:long, grttEstimate:double) : void
+ {static} NormGetGrttEstimate(sessionHandle:long) : double
+ {static} NormSetGrttMax(sessionHandle:long, grttMax:double) : void
+ {static} NormSetGrttProbingMode(sessionHandle:long, probingMode:NormProbingMode) : void
+ {static} NormSetGrttProbingInterval(sessionHandle:long, intervalMin:double, intervalMax:double) : void
+ {static} NormSetBackoffFactor(sessionHandle:long, backoffFactor:double) : void
+ {static} NormSetGroupSize(sessionHandle:long, groupSize:long) : void
+ {static} NormSetTxRobustFactor(sessionHandle:long, robustFactor:int) : void
+ {static} NormFileEnqueue(sessionHandle:long, fileName:string, infoPtr:string, infoLen:int): long
+ {static} NormDataEnqueue(sessionHandle:long, dataPtr:nint, dataLen:int, infoPtr:nint, infoLen:int) : long
+ {static} NormRequeueObject(sessionHandle:long, objectHandle:long) : bool
+ {static} NormStreamOpen(sessionHandle:long, bufferSize:long, infoPtr:string, infoLen:int) : long
+ {static} NormStreamClose(streamHandle:long, graceful:bool) : 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} NormStreamMarkEom(streamHandle:long) : void
+ {static} NormSetWatermark(sessionHandle:long, objectHandle:long, 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} NormGetAckingStatus(sessionHandle:long, nodeId:long) : NormAckingStatus
+ {static} NormSendCommand(sessionHandle:long, cmdBuffer:byte[], cmdLength:int, robust:bool) : bool
+ {static} NormCancelCommand(sessionHandle:long) : void
+ {static} NormStartReceiver(sessionHandle:long, bufferSpace:long) : bool
+ {static} NormStopReceiver(sessionHandle:long) : 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
+ {static} NormSetDefaultSyncPolicy(sessionHandle:long, syncPolicy:NormSyncPolicy) : void
+ {static} NormSetDefaultNackingMode(sessionHandle:long, nackingMode:NormNackingMode) : void
+ {static} NormNodeSetNackingMode(remoteSender:long, nackingMode:NormNackingMode) : void
+ {static} NormObjectSetNackingMode(objectHandle:long, nackingMode:NormNackingMode) : void
+ {static} NormSetDefaultRepairBoundary(sessionHandle:long, repairBoundary:NormRepairBoundary) : void
+ {static} NormNodeSetRepairBoundary(remoteSender:long, repairBoundary:NormRepairBoundary) : void
+ {static} NormSetDefaultRxRobustFactor(sessionHandle:long, robustFactor:int) : void
+ {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) : long
+ {static} NormObjectGetType(objectHandle:long) : NormObjectType
+ {static} NormObjectHasInfo(objectHandle:long) : bool
+ {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
+ {static} NormObjectRetain(objectHandle:long) : void
+ {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) : nint
+ {static} NormObjectGetSender(objectHandle:long) : long
+ {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, buffer:byte[], buflen:int) : bool
+ {static} NormNodeFreeBuffers(remoteSender:long) : void
+ {static} NormNodeRetain(nodeHandle:long) : void
+ {static} NormNodeRelease(nodeHandle:long) : void
}
@enduml
NormApi +-- NormEvent
NormEvent --> "Type" NormEventType
@enduml

View File

@ -1,7 +1,7 @@
@startuml
class NormData {
~ NormData(handle:long)
+ byte[] GetData()
+ GetData() : byte[]
<<internal>> NormData(handle:long)
}
NormObject <|-- NormData
@enduml
@enduml

View File

@ -1,14 +1,14 @@
@startuml
class NormEvent {
- _type: NormEventType
- _sessionHandle: long
- _nodeHandle: long
- _objectHandle: long
- _sessionHandle : long <<get>>
- _nodeHandle : long <<get>>
- _objectHandle : long <<get>>
+ NormEvent(type:NormEventType, sessionHandle:long, nodeHandle:long, objectHandle:long)
+ Type : NormEventType <<get>>
+ Session : NormSession <<get>>
+ Node : NormNode <<get>>
+ Object : NormObject <<get>>
+ <<override>> ToString() : string
}
@enduml
NormEvent --> "_type" NormEventType
NormEvent --> "Type" NormEventType
NormEvent --> "Session" NormSession
NormEvent --> "Node" NormNode
NormEvent --> "Object" NormObject
@enduml

View File

@ -1,9 +1,9 @@
@startuml
class NormFile {
+ <<const>> FILENAME_MAX : int = 260
~ NormFile(handle:long)
<<internal>> NormFile(handle:long)
+ Name : string <<get>>
+ Rename(filename:string) : void
+ Rename(filePath:string) : void
}
NormObject <|-- NormFile
@enduml
@enduml

View File

@ -1,24 +1,24 @@
@startuml
class NormInstance {
+ <<const>> NORM_DESCRIPTOR_INVALID : int = 0
- _handle: long
+ NormInstance()
- _handle : long
+ NormInstance(priorityBoost:bool)
+ NormInstance()
- CreateInstance(priorityBoost:bool) : void
+ DestroyInstance() : void
+ CreateSession(address:string, port:int, localNodeId:long) : NormSession
+ HasNextEvent(sec:int, usec:int) : bool
+ HasNextEvent(waitTime:TimeSpan) : bool
+ GetNextEvent(waitForEvent:bool) : NormEvent?
+ GetNextEvent() : NormEvent?
+ SetCacheDirectory(cachePath:string) : void
+ StopInstance() : void
+ RestartInstance() : bool
+ SuspendInstance() : bool
+ ResumeInstance() : void
+ SetCacheDirectory(cachePath:string) : void
+ OpenDebugLog(filename:string) : void
+ OpenDebugLog(fileName:string) : void
+ CloseDebugLog() : void
+ OpenDebugPipe(pipename:string) : void
+ DebugLevel: int <<get>> <<set>>
+ HasNextEvent(sec:int, usec:int) : bool
+ HasNextEvent(waitTime:TimeSpan) : bool
+ GetNextEvent(waitForEvent:bool) : NormEvent
+ GetNextEvent() : NormEvent
+ CreateSession(address:string, port:int, localNodeId:long) : NormSession
+ DebugLevel : int <<get>> <<set>>
}
@enduml
@enduml

View File

@ -4,17 +4,17 @@ class NormNode {
+ <<const>> NORM_NODE_NONE : int = 0
+ <<const>> NORM_NODE_INVALID : int = 0
- _handle : long
~ NormNode(handle:long)
<<internal>> NormNode(handle:long)
+ Id : long <<get>>
+ Grtt : double <<get>>
+ GetCommand(buffer:byte[], offset:int, length:int) : int
+ SetUnicastNack(state:bool) : void
+ SetNackingMode(nackingMode:NormNackingMode) : void
+ SetRepairBoundary(repairBoundary:NormRepairBoundary) : void
+ SetRxRobustFactor(robustFactor:int) : void
+ Id : long <<get>>
+ Address : IPEndPoint <<get>>
+ Grtt : double <<get>>
+ Command : byte[] <<get>>
+ FreeBuffers() : void
+ Retain() : void
+ Release(): void
+ Release() : void
}
@enduml
NormNode --> "Address" IPEndPoint
@enduml

View File

@ -1,18 +1,19 @@
@startuml
class NormObject {
+ <<const>> NORM_OBJECT_INVALID : int = 0
# _handle:long
~ NormObject(handle:long)
+ SetNackingMode(nackingMode:NormNackingMode) : void
+ Type : NormObjectType <<get>>
# _handle : long
<<internal>> NormObject(handle:long)
+ Handle : long <<get>>
+ Info : byte[] <<get>>
+ Size : long <<get>>
+ Sender : long <<get>>
+ SetNackingMode(nackingMode:NormNackingMode) : void
+ GetBytesPending() : long
+ Cancel() : void
+ Retain() : void
+ Release() : void
+ Sender : NormNode <<get>>
+ <<override>> GetHashCode() : int
+ <<override>> Equals(obj:object) : bool
+ <<override>> Equals(obj:object?) : bool
}
@enduml
NormObject --> "Type" NormObjectType
@enduml

View File

@ -1,74 +1,79 @@
@startuml
class NormSession {
+ <<const>> NORM_SESSION_INVALID : int = 0
{static} -_normSessions : Dictionary<long, NormSession>
- _handle : long
~ NormSession(handle:long)
{static} ~ NormSession GetSession(handle:long)
+ LocalNodeId : long <<get>>
+ ReportInterval : double <<get>> <<set>>
+ TxRate : double <<get>> <<set>>
+ GrttEstimate : double <<get>> <<set>>
<<internal>> NormSession(handle:long)
<<internal>> {static} GetSession(handle:long) : NormSession?
+ DestroySession() : void
- DestroySessionNative() : void
+ LocalNodeId: long <<get>>
+ SetTxPort(port:int) : void
+ SetTxPort(port:int, enableReuse:bool, txAddress:string) : void
+ SetTxPort(port:int, enableReuse:bool, txBindAddress:string?) : void
+ SetTxOnly(txOnly:bool) : void
+ SetTxOnly(txOnly:bool, connectToSessionAddress:bool) : void
+ SetRxPortReuse(enable:bool) : void
+ SetRxPortReuse(enable:bool, rxBindAddress:string, senderAddress:string, senderPort:int) : void
+ SetRxPortReuse(enable:bool, rxBindAddress:string?, senderAddress:string?, senderPort:int) : void
+ SetEcnSupport(ecnEnable:bool, ignoreLoss:bool) : void
+ SetEcnSupport(ecnEnable:bool, ignoreLoss:bool, tolerateLoss:bool) : void
+ SetMulticastInterface(interfaceName:string) : void
+ SetSSM(sourceAddr:string) : void
+ SetSSM(sourceAddress:string) : void
+ SetTTL(ttl:byte) : void
+ SetTOS(tos:byte) : void
+ SetLoopback(loopbackEnable:bool) : void
+ SetMessageTrace(flag:bool) : void
+ SetTxLoss(precent:double) : void
+ SetRxLoss(precent:double) : void
+ ReportInterval: double <<get>> <<set>>
+ 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>>
+ SetFlowControl(flowControlFactor:double) : void
+ SetFlowControl(precent:double) : void
+ SetTxSocketBuffer(bufferSize:long) : void
+ SetCongestionControl(enable:bool) : void
+ SetCongestionControl(enable:bool, adjustRate:bool) : void
+ SetTxRateBounds(rateMin:double, rateMax:double) : void
+ SetTxCacheBounds(sizeMax:long, countMin:long, countMax:long) : 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
+ FileEnqueue(filename:string) : NormFile
+ FileEnqueue(filename:string, info:byte[]?, infoOffset:int, infoLength:int) : NormFile
+ DataEnqueue(dataBuffer:SafeBuffer, dataOffset:int, dataLength:int) : NormData
+ DataEnqueue(dataBuffer:SafeBuffer, dataOffset:int, dataLength:int, info:byte[]?, infoOffset:int, infoLength:int) : NormData
+ DataEnqueue(dataPtr:nint, dataOffset:int, dataLength:int) : NormData
+ DataEnqueue(dataPtr:nint, dataOffset:int, dataLength:int, info:byte[]?, infoOffset:int, infoLength:int) : NormData
+ StreamOpen(bufferSize:long) : NormStream
+ StreamOpen(bufferSize:long, info:byte[]?, infoOffset:int, infoLength:int) : NormStream
+ StartReceiver(bufferSpace:long) : void
+ StopReceiver() : void
+ SetAutoParity(autoParity:short) : void
+ GrttEstimate:double <<get>> <<set>>
+ SetGrttMax(grttMax:double) : void
+ SetGrttProbingMode(probingMode:NormProbingMode) : void
+ SetGrttProbingInterval(intervalMin:double, intervalMax:double) : void
+ SetBackoffFactor(backoffFactor:double) : void
+ SetGroupSize(groupSize:long) : void
+ SetTxRobustFactor(robustFactor:int) : void
+ FileEnqueue(filename:string) : NormFile
+ FileEnqueue(filename:string, info:byte[], infoOffset:int, infoLength:int) : NormFile
+ 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
+ SetTxRobustFactor(txRobustFactor:int) : void
+ RequeueObject(normObject:NormObject) : void
+ SetWatermark(normObject:NormObject) : void
+ SetWatermark(normObject:NormObject, overrideFlush:bool) : void
+ CancelWatermark() : void
+ ResetWatermark() : void
+ AddAckingNode(nodeId:long) : void
+ RemoveAckingNode(nodeId:long) : void
+ GetAckingStatus(nodeId:long): NormAckingStatus
+ GetAckingStatus(nodeId:long) : NormAckingStatus
+ SendCommand(cmdBuffer:byte[], cmdOffset:int, cmdLength:int, robust:bool) : void
+ CancelCommand() : void
+ StartReceiver(bufferSpace:long) : void
+ StopReceiver() : void
+ SetRxCacheLimit(countMax:int) : void
+ SetRxSocketBuffer(bufferSize:long) : void
+ SetSilentReceiver(silent:bool, maxDelay:int) : void
+ SetDefaultUnicastNack(enabled:bool) : void
+ SetDefaultUnicastNack(enable:bool) : void
+ SetDefaultSyncPolicy(syncPolicy:NormSyncPolicy) : void
+ SetDefaultNackingMode(nackingMode: NormNackingMode) : void
+ SetDefaultRepairBoundary(repairBoundary: NormRepairBoundry) : void
+ SetDefaultRxRobustFactor(robustFactor: int): void
+ SetDefaultNackingMode(nackingMode:NormNackingMode) : void
+ SetDefaultRepairBoundary(repairBoundary:NormRepairBoundary) : void
+ SetDefaultRxRobustFactor(rxRobustFactor:int) : void
}
@enduml
class "Dictionary`2"<T1,T2> {
}
NormSession o-> "_normSessions<long,NormSession>" "Dictionary`2"
@enduml

View File

@ -1,18 +1,18 @@
@startuml
class NormStream {
~ NormStream(handle:long)
+ Close() : void
+ Close(boolean graceful) : void
+ Write(buffer:byte[], offset:int, length:int) : int
+ Flush() : void
+ Flush(eom:bool, flushMode:NormFlushMode) : void
+ SetAutoFlush(flushMode:NormFlushMode) : void
+ SetPushEnable(pushEnable:bool) : void
+ HasVacancy : bool <<get>>
+ ReadOffset : long <<get>>
<<internal>> NormStream(handle:long)
+ Write(buffer:byte[], offset:int, length:int) : int
+ MarkEom() : void
+ Flush(eom:bool, flushMode:NormFlushMode) : void
+ Flush() : void
+ Close(graceful:bool) : void
+ Close() : void
+ Read(buffer:byte[], offset:int, length:int) : int
+ SeekMsgStart() : bool
+ ReadOffset : long <<get>>
+ SetPushEnable(pushEnable:bool) : void
+ SetAutoFlush(flushMode:NormFlushMode) : void
}
NormObject <|-- NormStream
@enduml
@enduml

View File

@ -0,0 +1,26 @@
using System.Runtime.InteropServices;
namespace Mil.Navy.Nrl.Norm.Buffers
{
/// <summary>
/// A byte buffer
/// </summary>
public abstract class ByteBuffer : SafeBuffer
{
/// <summary>
/// Creates a new buffer
/// </summary>
protected ByteBuffer() : base(true)
{
}
/// <summary>
/// Allocates a new direct byte buffer
/// </summary>
/// <param name="capacity">The new buffer's capacity, in bytes</param>
/// <returns>The new byte buffer</returns>
public static ByteBuffer AllocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
}
}

View File

@ -0,0 +1,30 @@
using System.Runtime.InteropServices;
namespace Mil.Navy.Nrl.Norm.Buffers
{
/// <summary>
/// A direct byte buffer
/// </summary>
internal sealed class DirectByteBuffer : ByteBuffer
{
/// <summary>
/// Creates a new direct byte buffer with given capacity
/// </summary>
/// <param name="capacity">The new buffer's capacity, in bytes</param>
internal DirectByteBuffer(int capacity)
{
SetHandle(Marshal.AllocHGlobal(capacity));
Initialize(Convert.ToUInt64(capacity));
}
/// <summary>
/// Executes the code required to free the handle
/// </summary>
/// <returns>true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false</returns>
protected override bool ReleaseHandle()
{
Marshal.FreeHGlobal(handle);
return true;
}
}
}

View File

@ -4,6 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>1.0.0</Version>
</PropertyGroup>

View File

@ -524,7 +524,7 @@ namespace Mil.Navy.Nrl.Norm
/// NORM_INFO content is left to the application's discretion</param>
/// <returns>A NormObjectHandle is returned which the application may use in other NORM API calls as needed.</returns>
[DllImport(NORM_LIBRARY)]
public static extern long NormFileEnqueue(long sessionHandle, string fileName, byte[]? infoPtr, int infoLen);
public static extern long NormFileEnqueue(long sessionHandle, string fileName, nint infoPtr, int infoLen);
/// <summary>
/// This function enqueues a segment of application memory space for transmission within the specified NORM sessionHandle.
@ -571,7 +571,7 @@ namespace Mil.Navy.Nrl.Norm
/// which will enable NORM receiver applications to properly interpret the received stream as it is being received.</param>
/// <returns>A NormObjectHandle is returned which the application may use in other NORM API calls as needed.</returns>
[DllImport(NORM_LIBRARY)]
public static extern long NormStreamOpen(long sessionHandle, long bufferSize, byte[]? infoPtr, int infoLen);
public static extern long NormStreamOpen(long sessionHandle, long bufferSize, nint infoPtr, int infoLen);
/// <summary>
/// This function halts transfer of the stream specified by the streamHandle parameter and releases any resources
@ -591,7 +591,7 @@ namespace Mil.Navy.Nrl.Norm
/// <param name="numBytes">The numBytes 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>
[DllImport(NORM_LIBRARY)]
internal static extern int NormStreamWrite(long streamHandle, byte[] buffer, int numBytes);
internal static extern int NormStreamWrite(long streamHandle, nint buffer, int numBytes);
/// <summary>
/// This function causes an immediate "flush" of the transmit stream specified by the streamHandle parameter.
@ -725,7 +725,7 @@ namespace Mil.Navy.Nrl.Norm
/// operation (see NormStartSender()), the cmdLength exceeds the configured session segmentLength, or a previously-
/// enqueued command has not yet been sent.</returns>
[DllImport(NORM_LIBRARY)]
public static extern bool NormSendCommand(long sessionHandle, byte[] cmdBuffer, int cmdLength, bool robust);
public static extern bool NormSendCommand(long sessionHandle, nint cmdBuffer, int cmdLength, bool robust);
/// <summary>
/// This function terminates any pending NORM_CMD(APPLICATION) transmission that was previously initiated with the NormSendCommand() call.
@ -892,9 +892,10 @@ namespace Mil.Navy.Nrl.Norm
/// <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 numBytes pointer</param>
/// <param name="numBytes">Specifies the length of data.</param>
/// <returns></returns>
/// <returns>This function normally returns a value of true. However, if a break in the integrity of the reliable received stream
/// occurs(or the stream has been ended by the sender), a value of false is returned to indicate the break. </returns>
[DllImport(NORM_LIBRARY)]
public static extern bool NormStreamRead(long streamHandle, byte[] buffer, ref int numBytes);
public static extern bool NormStreamRead(long streamHandle, nint buffer, ref int numBytes);
/// <summary>
/// This function advances the read offset of the receive stream referenced by the streamHandle parameter to align
@ -960,7 +961,7 @@ namespace Mil.Navy.Nrl.Norm
/// function can be used to determine the length of NORM_INFO content for the object even if a NULL buffer value and
/// zero bufferLen is provided. A zero value is returned if NORM_INFO content has not yet been received (or is nonexistent) for the specified object.</returns>
[DllImport(NORM_LIBRARY)]
public static extern int NormObjectGetInfo(long objectHandle, [Out] byte[] buffer, int bufferLen);
public static extern int NormObjectGetInfo(long objectHandle, nint buffer, int bufferLen);
/// <summary>
/// This function can be used to determine the size (in bytes) of the transport object specified by the objectHandle parameter.
@ -1019,7 +1020,7 @@ namespace Mil.Navy.Nrl.Norm
/// does not refer to an object of type NORM_OBJECT_FILE.
/// </returns>
[DllImport(NORM_LIBRARY)]
public static extern bool NormFileGetName(long fileHandle, [Out] char[] nameBuffer, int bufferLen);
public static extern bool NormFileGetName(long fileHandle, nint nameBuffer, int bufferLen);
/// <summary>
/// This function renames the file used to store content for the NORM_OBJECT_FILE transport object specified by
@ -1080,7 +1081,7 @@ namespace Mil.Navy.Nrl.Norm
/// <param name="port">port number and/or specify a specific source address binding that is used for packet transmission.</param>
/// <returns>A value of true is returned upon success and false upon failure. An invalid nodeHandle parameter value would lead to such failure.</returns>
[DllImport(NORM_LIBRARY)]
public static extern bool NormNodeGetAddress(long nodeHandle, [Out] byte[] addrBuffer, ref int bufferLen, out int port);
public static extern bool NormNodeGetAddress(long nodeHandle, nint addrBuffer, ref int bufferLen, out int port);
/// <summary>
/// This function retrieves the advertised estimate of group round-trip timing (GRTT) for the remote sender referenced by the given nodeHandle value.
@ -1097,13 +1098,13 @@ namespace Mil.Navy.Nrl.Norm
/// This function retrieves the content of an application-defined command that was received from a remote sender associated with the given nodeHandle.
/// </summary>
/// <param name="remoteSender"> notification for a given remote sender when multiple senders may be providing content</param>
/// <param name="buffer">Allocated system resources for each active sender</param>
/// <param name="cmdBuffer">Allocated system resources for each active sender</param>
/// <param name="buflen">A return value of false indicates that either no command was available or the provided buffer size</param>
/// <returns>This function returns true upon successful retrieval of command content. A return value of false indicates that
/// either no command was available or the provided buffer size (buflen parameter) was inadequate.
/// The value referenced by the buflen parameter is adjusted to indicate the actual command length (in bytes) upon return.</returns>
[DllImport(NORM_LIBRARY)]
public static extern bool NormNodeGetCommand(long remoteSender, [Out] byte[] buffer, ref int buflen);
public static extern bool NormNodeGetCommand(long remoteSender, nint cmdBuffer, ref int buflen);
/// <summary>
/// This function releases memory resources that were allocated for a remote sender.

View File

@ -1,4 +1,7 @@
namespace Mil.Navy.Nrl.Norm
using System.Runtime.InteropServices;
using System.Text;
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// A transport object of type NORM_OBJECT_FILE.
@ -26,13 +29,24 @@
{
get
{
var buffer = new char[FILENAME_MAX];
if (!NormFileGetName(_handle, buffer, FILENAME_MAX))
var buffer = new byte[FILENAME_MAX];
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
throw new IOException("Failed to get file name");
var bufferPtr = bufferHandle.AddrOfPinnedObject();
if (!NormFileGetName(_handle, bufferPtr, FILENAME_MAX))
{
throw new IOException("Failed to get file name");
}
}
finally
{
bufferHandle.Free();
}
buffer = buffer.Where(c => c != 0).ToArray();
return new string(buffer);
return new string(buffer.Select(Convert.ToChar).ToArray());
}
}

View File

@ -1,4 +1,6 @@
using System.Net;
using Mil.Navy.Nrl.Norm.Buffers;
using System.Net;
using System.Runtime.InteropServices;
namespace Mil.Navy.Nrl.Norm
{
@ -45,14 +47,23 @@ namespace Mil.Navy.Nrl.Norm
{
get
{
var buffer = new byte[256];
var bufferLength = buffer.Length;
if (!NormNodeGetAddress(_handle, buffer, ref bufferLength, out var port))
var bufferLength = 256;
using var buffer = ByteBuffer.AllocateDirect(bufferLength);
int port;
unsafe
{
throw new IOException("Failed to get node address");
byte* addrBuffer = null;
buffer.AcquirePointer(ref addrBuffer);
if (!NormNodeGetAddress(_handle, (nint)addrBuffer, ref bufferLength, out port))
{
throw new IOException("Failed to get node address");
}
}
buffer = buffer.Take(bufferLength).ToArray();
var ipAddressText = string.Join('.', buffer);
var addressBytes = new byte[bufferLength];
buffer.ReadArray(0, addressBytes, 0, bufferLength);
var ipAddressText = string.Join('.', addressBytes);
var ipAddress = IPAddress.Parse(ipAddressText);
return new IPEndPoint(ipAddress, port);
@ -65,20 +76,35 @@ namespace Mil.Navy.Nrl.Norm
public double Grtt => NormNodeGetGrtt(_handle);
/// <summary>
/// NORM application-defined command for transmission.
/// This function retrieves the content of an application-defined command that was received from a remote sender.
/// </summary>
public byte[] Command
/// <exception cref="ArgumentOutOfRangeException">Thrown when the offset or length are outside of the buffer.</exception>
public int GetCommand(byte[] buffer, int offset, int length)
{
get
if (offset < 0 || offset >= buffer.Length)
{
var buffer = new byte[256];
var bufferLength = buffer.Length;
if (!NormNodeGetCommand(_handle, buffer, ref bufferLength))
throw new ArgumentOutOfRangeException(nameof(offset), "The offset is out of range");
}
if (length < 1 || offset + length > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(length), "The length is out of range");
}
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
var bufferPtr = bufferHandle.AddrOfPinnedObject() + offset;
if (!NormNodeGetCommand(_handle, bufferPtr, ref length))
{
throw new IOException("Failed to get command");
}
return buffer.Take(bufferLength).ToArray();
}
finally
{
bufferHandle.Free();
}
return length;
}
/// <summary>

View File

@ -1,4 +1,6 @@
namespace Mil.Navy.Nrl.Norm
using System.Runtime.InteropServices;
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// The base transport object.
@ -39,9 +41,21 @@
{
return null;
}
var length = NormObjectGetInfoLength(_handle);
var buffer = new byte[length];
NormObjectGetInfo(_handle, buffer, length);
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
var bufferPtr = bufferHandle.AddrOfPinnedObject();
NormObjectGetInfo(_handle, bufferPtr, length);
}
finally
{
bufferHandle.Free();
}
return buffer;
}
}

View File

@ -466,23 +466,35 @@ namespace Mil.Navy.Nrl.Norm
/// <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)
/// <exception cref="ArgumentOutOfRangeException">Thrown when the info offset or info length are outside of the info buffer.</exception>
public NormFile FileEnqueue(string filename, byte[]? info, int infoOffset, int infoLength)
{
byte[]? infoBytes;
if (info != null)
if (infoOffset < 0 || infoOffset >= info?.Length)
{
infoBytes = info.Skip(infoOffset).Take(infoLength).ToArray();
throw new ArgumentOutOfRangeException(nameof(infoOffset), "The info offset is out of range");
}
else
if (info != null && infoLength < 1 || infoOffset + infoLength > info?.Length)
{
infoBytes = null;
infoLength = 0;
throw new ArgumentOutOfRangeException(nameof(infoLength), "The info length is out of range");
}
var objectHandle = NormFileEnqueue(_handle, filename, infoBytes, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
long objectHandle;
var infoHandle = GCHandle.Alloc(info, GCHandleType.Pinned);
try
{
throw new IOException("Failed to enqueue file");
var infoPtr = infoHandle.AddrOfPinnedObject() + infoOffset;
objectHandle = NormFileEnqueue(_handle, filename, infoPtr, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
{
throw new IOException("Failed to enqueue file");
}
}
finally
{
infoHandle.Free();
}
return new NormFile(objectHandle);
}
@ -499,7 +511,7 @@ namespace Mil.Navy.Nrl.Norm
/// <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>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the data offset or data length are outside of the data buffer.</exception>
public NormData DataEnqueue(byte[] dataBuffer, int dataOffset, int dataLength)
public NormData DataEnqueue(SafeBuffer dataBuffer, int dataOffset, int dataLength)
{
return DataEnqueue(dataBuffer, dataOffset, dataLength, null, 0, 0);
}
@ -517,32 +529,73 @@ namespace Mil.Navy.Nrl.Norm
/// <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>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the data offset, data length, info offset or info length are outside of the associated buffer.</exception>
public NormData DataEnqueue(byte[] dataBuffer, int dataOffset, int dataLength, byte[]? info, int infoOffset, int infoLength)
public NormData DataEnqueue(SafeBuffer dataBuffer, int dataOffset, int dataLength, byte[]? info, int infoOffset, int infoLength)
{
if (dataOffset < 0 || dataOffset >= dataBuffer.Length)
if (dataOffset < 0 || Convert.ToUInt64(dataOffset) >= dataBuffer.ByteLength)
{
throw new ArgumentOutOfRangeException(nameof(dataOffset), "The data offset is out of range");
}
if (dataOffset + dataLength > dataBuffer.Length)
if (dataLength < 1 || Convert.ToUInt64(dataOffset + dataLength) > dataBuffer.ByteLength)
{
throw new ArgumentOutOfRangeException(nameof(dataLength), "The data length is out of range");
}
unsafe
{
byte* dataPtr = null;
dataBuffer.AcquirePointer(ref dataPtr);
return DataEnqueue((nint)dataPtr, dataOffset, dataLength, info, infoOffset, infoLength);
}
}
/// <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="dataPtr">The dataPtr is a pointer to the message to be transmitted.</param>
/// <param name="dataOffset">Indicates the start 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>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the data offset or data length are outside of the data buffer.</exception>
public NormData DataEnqueue(nint dataPtr, int dataOffset, int dataLength)
{
return DataEnqueue(dataPtr, dataOffset, dataLength, null, 0, 0);
}
/// <summary>
/// This function enqueues a segment of application memory space for transmission.
/// </summary>
/// <param name="dataPtr">The dataPtr is a pointer to the message to be transmitted.</param>
/// <param name="dataOffset">Indicates the start 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 start 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>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the data offset, data length, info offset or info length are outside of the associated buffer.</exception>
public NormData DataEnqueue(nint dataPtr, int dataOffset, int dataLength, byte[]? info, int infoOffset, int infoLength)
{
if (infoOffset < 0 || infoOffset >= info?.Length)
{
throw new ArgumentOutOfRangeException(nameof(infoOffset), "The info offset is out of range");
}
if (infoOffset + infoLength > info?.Length)
if (info != null && infoLength < 1 || infoOffset + infoLength > info?.Length)
{
throw new ArgumentOutOfRangeException(nameof(infoLength), "The info length is out of range");
}
long objectHandle;
var dataHandle = GCHandle.Alloc(dataBuffer, GCHandleType.Pinned);
var infoHandle = GCHandle.Alloc(info, GCHandleType.Pinned);
try
{
var dataPtr = dataHandle.AddrOfPinnedObject() + dataOffset;
dataPtr += dataOffset;
var infoPtr = infoHandle.AddrOfPinnedObject() + infoOffset;
objectHandle = NormDataEnqueue(_handle, dataPtr, dataLength, infoPtr, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
@ -552,7 +605,6 @@ namespace Mil.Navy.Nrl.Norm
}
finally
{
dataHandle.Free();
infoHandle.Free();
}
@ -597,23 +649,35 @@ namespace Mil.Navy.Nrl.Norm
/// <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>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the info offset or info length are outside of the info buffer.</exception>
public NormStream StreamOpen(long bufferSize, byte[]? info, int infoOffset, int infoLength)
{
byte[]? infoBytes;
if (info != null)
if (infoOffset < 0 || infoOffset >= info?.Length)
{
infoBytes = info.Skip(infoOffset).Take(infoLength).ToArray();
throw new ArgumentOutOfRangeException(nameof(infoOffset), "The info offset is out of range");
}
else
if (info != null && infoLength < 1 || infoOffset + infoLength > info?.Length)
{
infoBytes = null;
infoLength = 0;
throw new ArgumentOutOfRangeException(nameof(infoLength), "The info length is out of range");
}
var objectHandle = NormStreamOpen(_handle, bufferSize, infoBytes, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
long objectHandle;
var infoHandle = GCHandle.Alloc(info, GCHandleType.Pinned);
try
{
throw new IOException("Failed to open stream");
var infoPtr = infoHandle.AddrOfPinnedObject() + infoOffset;
objectHandle = NormStreamOpen(_handle, bufferSize, infoPtr, infoLength);
if (objectHandle == NormObject.NORM_OBJECT_INVALID)
{
throw new IOException("Failed to open stream");
}
}
finally
{
infoHandle.Free();
}
return new NormStream(objectHandle);
}
@ -825,16 +889,37 @@ namespace Mil.Navy.Nrl.Norm
/// 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="cmdOffset"></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)
/// <exception cref="ArgumentOutOfRangeException">Thrown when the offset or length are outside of the buffer.</exception>
public void SendCommand(byte[] cmdBuffer, int cmdOffset, int cmdLength, bool robust)
{
if(!NormSendCommand(_handle, cmdBuffer, cmdLength, robust))
if (cmdOffset < 0 || cmdOffset >= cmdBuffer.Length)
{
throw new IOException("Failed to send command");
throw new ArgumentOutOfRangeException(nameof(cmdOffset), "The offset is out of range");
}
if (cmdLength < 1 || cmdOffset + cmdLength > cmdBuffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(cmdLength), "The command length is out of range");
}
var commandHandle = GCHandle.Alloc(cmdBuffer, GCHandleType.Pinned);
try
{
var cmdPtr = commandHandle.AddrOfPinnedObject() + cmdOffset;
if (!NormSendCommand(_handle, cmdPtr, cmdLength, robust))
{
throw new IOException("Failed to send command");
}
}
finally
{
commandHandle.Free();
}
}

View File

@ -1,4 +1,6 @@
namespace Mil.Navy.Nrl.Norm
using System.Runtime.InteropServices;
namespace Mil.Navy.Nrl.Norm
{
/// <summary>
/// A transport object of type NORM_OBJECT_STREAM.
@ -44,10 +46,32 @@
/// 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>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the offset or length are outside of the buffer.</exception>
public int Write(byte[] buffer, int offset, int length)
{
var bytes = buffer.Skip(offset).Take(length).ToArray();
return NormStreamWrite(_handle, bytes, length);
if (offset < 0 || offset >= buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset), "The offset is out of range");
}
if (length < 1 || offset + length > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(length), "The length is out of range");
}
int numBytes;
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
var bufferPtr = bufferHandle.AddrOfPinnedObject() + offset;
numBytes = NormStreamWrite(_handle, bufferPtr, length);
}
finally
{
bufferHandle.Free();
}
return numBytes;
}
/// <summary>
@ -122,22 +146,31 @@
/// 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>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the offset or length are outside of the buffer.</exception>
public int Read(byte[] buffer, int offset, int length)
{
var bytes = new byte[length];
if (!NormStreamRead(_handle, bytes, ref length))
if (offset < 0 || offset >= buffer.Length)
{
return -1;
throw new ArgumentOutOfRangeException(nameof(offset), "The offset is out of range");
}
if (length < 1 || offset + length > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(length), "The length is out of range");
}
for (var i = 0; i < length; i++)
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
var bufferPosition = offset + i;
if (bufferPosition < buffer.Length)
var bufferPtr = bufferHandle.AddrOfPinnedObject() + offset;
if (!NormStreamRead(_handle, bufferPtr, ref length))
{
buffer[bufferPosition] = bytes[i];
}
length = -1;
}
}
finally
{
bufferHandle.Free();
}
return length;

View File

@ -1,4 +1,5 @@
using Bogus;
using Mil.Navy.Nrl.Norm.Buffers;
using System.Text;
namespace Mil.Navy.Nrl.Norm.IntegrationTests
@ -216,7 +217,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests
Assert.Equal(expectedDebugLevel, actualDebugLevel);
}
[Fact]
[SkippableFact(typeof(IOException))]
public void HasEventsFromTimeSpan()
{
var faker = new Faker();
@ -230,14 +231,16 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests
var dataContent = faker.Lorem.Paragraph();
var data = Encoding.ASCII.GetBytes(dataContent);
_normSession.DataEnqueue(data, 0, data.Length);
using var dataBuffer = ByteBuffer.AllocateDirect(data.Length);
dataBuffer.WriteArray(0, data, 0, data.Length);
_normSession.DataEnqueue(dataBuffer, 0, data.Length);
Assert.True(_normInstance.HasNextEvent(TimeSpan.FromSeconds(1.5)));
_normSession.StopSender();
}
[Fact]
[SkippableFact(typeof(IOException))]
public void HasEventsFromSecondsAndMicroseconds()
{
var faker = new Faker();
@ -251,7 +254,9 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests
var dataContent = faker.Lorem.Paragraph();
var data = Encoding.ASCII.GetBytes(dataContent);
_normSession.DataEnqueue(data, 0, data.Length);
using var dataBuffer = ByteBuffer.AllocateDirect(data.Length);
dataBuffer.WriteArray(0, data, 0, data.Length);
_normSession.DataEnqueue(dataBuffer, 0, data.Length);
Assert.True(_normInstance.HasNextEvent(1, 500000));