diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Buffers/ByteBuffer.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Buffers/ByteBuffer.puml new file mode 100644 index 0000000..22de7e7 --- /dev/null +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Buffers/ByteBuffer.puml @@ -0,0 +1,7 @@ +@startuml +abstract class ByteBuffer { + # ByteBuffer() + + {static} AllocateDirect(capacity:int) : ByteBuffer +} +SafeBuffer <|-- ByteBuffer +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Buffers/DirectByteBuffer.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Buffers/DirectByteBuffer.puml new file mode 100644 index 0000000..58106fc --- /dev/null +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Buffers/DirectByteBuffer.puml @@ -0,0 +1,7 @@ +@startuml +class DirectByteBuffer <> { + <> DirectByteBuffer(capacity:int) + # <> ReleaseHandle() : bool +} +ByteBuffer <|-- DirectByteBuffer +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormAckingStatus.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormAckingStatus.puml index f31c80e..aa34be5 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormAckingStatus.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormAckingStatus.puml @@ -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 \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormEventType.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormEventType.puml index 71dd8fb..bf72c92 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormEventType.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormEventType.puml @@ -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 \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFecType.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFecType.puml index 4b55669..c492e79 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFecType.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFecType.puml @@ -1,7 +1,7 @@ @startuml enum NormFecType { - RS - RS8 - SB + RS, + RS8, + SB, } -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFlushMode.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFlushMode.puml index 63f7b1a..1de4e63 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFlushMode.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormFlushMode.puml @@ -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 \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormNackingMode.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormNackingMode.puml index 357ea0b..8128596 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormNackingMode.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormNackingMode.puml @@ -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 \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormObjectType.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormObjectType.puml index 00e2dd8..4268986 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormObjectType.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormObjectType.puml @@ -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 \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormProbingMode.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormProbingMode.puml index 004ada7..93c95f0 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormProbingMode.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormProbingMode.puml @@ -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 \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormRepairBoundary.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormRepairBoundary.puml index b97df40..bba6130 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormRepairBoundary.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormRepairBoundary.puml @@ -1,6 +1,6 @@ @startuml enum NormRepairBoundary { - NORM_BOUNDARY_BLOCK - NORM_BOUNDARY_OBJECT + NORM_BOUNDARY_BLOCK, + NORM_BOUNDARY_OBJECT, } -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormSyncPolicy.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormSyncPolicy.puml index 3bb1cf5..870db56 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormSyncPolicy.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/Enums/NormSyncPolicy.puml @@ -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 \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/INormEventListener.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/INormEventListener.puml index ba923b3..0243b8e 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/INormEventListener.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/INormEventListener.puml @@ -2,4 +2,4 @@ interface INormEventListener { NormEventOccurred(normEvent:NormEvent) : void } -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormInputStream.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormInputStream.puml index c6cfef6..9136cba 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormInputStream.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormInputStream.puml @@ -1,32 +1,30 @@ @startuml class NormInputStream { - - _normInstance : NormInstance - - _normSession : NormSession - - _normStream : NormStream - - _normEventListeners : List + - _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 - + <> Dispose() : void + + <> Close() : void + IsClosed : bool <> + Read() : int - + <> Read(buffer:byte[], offset:int, length:int) : int + + <> Read(buffer:byte[], offset:int, count:int) : int - ProcessEvent() : void + <> Flush() : void + <> Write(buffer:byte[], offset:int, count:int) : void @@ -38,5 +36,10 @@ class NormInputStream { + <> Length : long <> + <> Position : long <> <> } +class "List`1" { +} Stream <|-- NormInputStream +NormInputStream --> "_normInstance" NormInstance +NormInputStream --> "_normSession" NormSession +NormInputStream --> "_normEventListeners" "List`1" @enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormOutputStream.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormOutputStream.puml index 72468b1..a15b0e6 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormOutputStream.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/NormOutputStream.puml @@ -1,9 +1,6 @@ @startuml class NormOutputStream { - - _normInstance : NormInstance - - _normSession : NormSession - - _normStream : NormStream - - _normEventListeners : List + - _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 <> <> - + GrttEstimate:double <> <> + + TxRate : double <> <> + + GrttEstimate : double <> <> + 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 + <> Close() : void + IsClosed : bool <> + Write(b:int) : void - + <> Write(buffer:byte[], offset:int, count:int) + + <> Write(buffer:byte[], offset:int, count:int) : void - ProcessEvent() : void + <> Flush() : void - + <> Read(buffer:byte[], offset:int, length:int) : int + + <> Read(buffer:byte[], offset:int, count:int) : int + <> Seek(offset:long, origin:SeekOrigin) : long + <> SetLength(value:long) : void + <> CanRead : bool <> @@ -45,5 +42,10 @@ class NormOutputStream { + <> Length : long <> + <> Position : long <> <> } +class "List`1" { +} Stream <|-- NormOutputStream -@enduml \ No newline at end of file +NormOutputStream --> "_normInstance" NormInstance +NormOutputStream --> "_normSession" NormSession +NormOutputStream --> "_normEventListeners" "List`1" +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/StreamBreakException.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/StreamBreakException.puml index 6ae4008..10cdc78 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/StreamBreakException.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/IO/StreamBreakException.puml @@ -1,6 +1,6 @@ @startuml class StreamBreakException { - + StreamBreakException(message:string) + + StreamBreakException(message:string?) } IOException <|-- StreamBreakException -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormApi.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormApi.puml index 027ac46..824d07a 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormApi.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormApi.puml @@ -1,119 +1,119 @@ -@startuml -struct NormEvent -{ - + Type : NormEventType +@startuml +class NormApi <> { + + <> 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) : bool + + {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, flag: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) : bool + + {static} <> NormOpenDebugPipe(instanceHandle:long, pipeName:string) : bool + + {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(instanceHandle:long, instanceId:int, bufferSpace:long, segmentSize:int, numData:short, numParity:short, fecId:NormFecType) : bool + + {static} <> NormStopSender(sessionHandle:long) : void + + {static} <> NormSetTxRate(sessionHandle:long, rate: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(sesssionHandle:long, autoParity:short) : void + + {static} <> NormSetGrttEstimate(sessionHandle:long, grtt:double) : void + + {static} <> NormGetGrttEstimate(sessionHandle:long) : double + + {static} <> NormSetGrttMax(sessionHandle:long, grttMax:double) : void + + {static} <> NormSetGrttProbingMode(sesssionHandle: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, txRobustFactor:int) : void + + {static} <> NormFileEnqueue(sessionHandle:long, fileName:string, infoPtr:nint, 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:nint, infoLen:int) : long + + {static} <> NormStreamClose(streamHandle:long, graceful:bool) : void + <> {static} <> NormStreamWrite(streamHandle:long, buffer:nint, 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:nint, 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:nint, 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:nint, bufferLen:int) : int + + {static} <> NormObjectGetSize(objectHandle:long) : int + + {static} <> NormObjectGetBytesPending(objectHandle:long) : long + + {static} <> NormObjectCancel(objectHandle:long) : void + + {static} <> NormObjectRetain(objectHandle:long) : void + + {static} <> NormObjectRelease(objectHandle:long) : void + + {static} <> NormFileGetName(fileHandle:long, nameBuffer:nint, 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:nint, bufferLen:int, port:int) : bool + + {static} <> NormNodeGetGrtt(nodeHandle:long) : double + + {static} <> NormNodeGetCommand(remoteSender:long, cmdBuffer:nint, buflen:int) : bool + + {static} <> NormNodeFreeBuffers(remoteSender:long) : void + + {static} <> NormNodeRetain(nodeHandle:long) : void + + {static} <> NormNodeRelease(nodeHandle:long) : void +} +struct NormEvent { + Session : long + Sender : long + Object : long } -class NormApi -{ - + <> 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 \ No newline at end of file +NormApi +-- NormEvent +NormEvent --> "Type" NormEventType +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormData.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormData.puml index e11e79e..2415206 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormData.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormData.puml @@ -1,7 +1,7 @@ @startuml class NormData { - ~ NormData(handle:long) - + byte[] GetData() + + GetData() : byte[] + <> NormData(handle:long) } NormObject <|-- NormData -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormEvent.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormEvent.puml index 3a1a991..6d94d58 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormEvent.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormEvent.puml @@ -1,14 +1,14 @@ @startuml class NormEvent { - - _type: NormEventType - - _sessionHandle: long - - _nodeHandle: long - - _objectHandle: long + - _sessionHandle : long <> + - _nodeHandle : long <> + - _objectHandle : long <> + NormEvent(type:NormEventType, sessionHandle:long, nodeHandle:long, objectHandle:long) - + Type : NormEventType <> - + Session : NormSession <> - + Node : NormNode <> - + Object : NormObject <> + <> ToString() : string } -@enduml \ No newline at end of file +NormEvent --> "_type" NormEventType +NormEvent --> "Type" NormEventType +NormEvent --> "Session" NormSession +NormEvent --> "Node" NormNode +NormEvent --> "Object" NormObject +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormFile.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormFile.puml index b7c7f98..f26b63a 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormFile.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormFile.puml @@ -1,9 +1,9 @@ @startuml class NormFile { + <> FILENAME_MAX : int = 260 - ~ NormFile(handle:long) + <> NormFile(handle:long) + Name : string <> - + Rename(filename:string) : void + + Rename(filePath:string) : void } NormObject <|-- NormFile -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormInstance.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormInstance.puml index 6207ae7..f9a66e7 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormInstance.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormInstance.puml @@ -1,24 +1,24 @@ @startuml class NormInstance { + <> 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 <> <> - + 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 <> <> } -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormNode.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormNode.puml index 34a87df..e583819 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormNode.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormNode.puml @@ -4,17 +4,17 @@ class NormNode { + <> NORM_NODE_NONE : int = 0 + <> NORM_NODE_INVALID : int = 0 - _handle : long - ~ NormNode(handle:long) + <> NormNode(handle:long) + + Id : long <> + + Grtt : double <> + + 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 <> - + Address : IPEndPoint <> - + Grtt : double <> - + Command : byte[] <> + FreeBuffers() : void + Retain() : void - + Release(): void + + Release() : void } -@enduml \ No newline at end of file +NormNode --> "Address" IPEndPoint +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormObject.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormObject.puml index 3c2e8c1..7696026 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormObject.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormObject.puml @@ -1,18 +1,19 @@ @startuml class NormObject { + <> NORM_OBJECT_INVALID : int = 0 - # _handle:long - ~ NormObject(handle:long) - + SetNackingMode(nackingMode:NormNackingMode) : void - + Type : NormObjectType <> + # _handle : long + <> NormObject(handle:long) + + Handle : long <> + Info : byte[] <> + Size : long <> + + Sender : long <> + + SetNackingMode(nackingMode:NormNackingMode) : void + GetBytesPending() : long + Cancel() : void + Retain() : void + Release() : void - + Sender : NormNode <> + <> GetHashCode() : int - + <> Equals(obj:object) : bool + + <> Equals(obj:object?) : bool } -@enduml \ No newline at end of file +NormObject --> "Type" NormObjectType +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormSession.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormSession.puml index 443590c..6a6c9ee 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormSession.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormSession.puml @@ -1,74 +1,79 @@ @startuml class NormSession { + <> NORM_SESSION_INVALID : int = 0 - {static} -_normSessions : Dictionary - _handle : long - ~ NormSession(handle:long) - {static} ~ NormSession GetSession(handle:long) + + LocalNodeId : long <> + + ReportInterval : double <> <> + + TxRate : double <> <> + + GrttEstimate : double <> <> + <> NormSession(handle:long) + <> {static} GetSession(handle:long) : NormSession? + DestroySession() : void - DestroySessionNative() : void - + LocalNodeId: long <> + 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 <> <> - + 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 <> <> - + 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 <> <> + 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 \ No newline at end of file +class "Dictionary`2" { +} +NormSession o-> "_normSessions" "Dictionary`2" +@enduml diff --git a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormStream.puml b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormStream.puml index bb06864..95b215d 100644 --- a/src/dotnet/design/Mil/Navy/Nrl/Norm/NormStream.puml +++ b/src/dotnet/design/Mil/Navy/Nrl/Norm/NormStream.puml @@ -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 <> + + ReadOffset : long <> + <> 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 <> + + SetPushEnable(pushEnable:bool) : void + + SetAutoFlush(flushMode:NormFlushMode) : void } NormObject <|-- NormStream -@enduml \ No newline at end of file +@enduml diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/Buffers/ByteBuffer.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/Buffers/ByteBuffer.cs new file mode 100644 index 0000000..d85303b --- /dev/null +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/Buffers/ByteBuffer.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; + +namespace Mil.Navy.Nrl.Norm.Buffers +{ + /// + /// A byte buffer + /// + public abstract class ByteBuffer : SafeBuffer + { + /// + /// Creates a new buffer + /// + protected ByteBuffer() : base(true) + { + } + + /// + /// Allocates a new direct byte buffer + /// + /// The new buffer's capacity, in bytes + /// The new byte buffer + public static ByteBuffer AllocateDirect(int capacity) { + return new DirectByteBuffer(capacity); + } + } +} \ No newline at end of file diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/Buffers/DirectByteBuffer.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/Buffers/DirectByteBuffer.cs new file mode 100644 index 0000000..077a9a0 --- /dev/null +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/Buffers/DirectByteBuffer.cs @@ -0,0 +1,30 @@ +using System.Runtime.InteropServices; + +namespace Mil.Navy.Nrl.Norm.Buffers +{ + /// + /// A direct byte buffer + /// + internal sealed class DirectByteBuffer : ByteBuffer + { + /// + /// Creates a new direct byte buffer with given capacity + /// + /// The new buffer's capacity, in bytes + internal DirectByteBuffer(int capacity) + { + SetHandle(Marshal.AllocHGlobal(capacity)); + Initialize(Convert.ToUInt64(capacity)); + } + + /// + /// Executes the code required to free the handle + /// + /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false + protected override bool ReleaseHandle() + { + Marshal.FreeHGlobal(handle); + return true; + } + } +} \ No newline at end of file diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/Mil.Navy.Nrl.Norm.csproj b/src/dotnet/src/Mil.Navy.Nrl.Norm/Mil.Navy.Nrl.Norm.csproj index efa1468..ef5a5fe 100644 --- a/src/dotnet/src/Mil.Navy.Nrl.Norm/Mil.Navy.Nrl.Norm.csproj +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/Mil.Navy.Nrl.Norm.csproj @@ -4,6 +4,7 @@ net6.0 enable enable + true 1.0.0 diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormApi.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormApi.cs index e5f56b8..d1085ef 100644 --- a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormApi.cs +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormApi.cs @@ -524,7 +524,7 @@ namespace Mil.Navy.Nrl.Norm /// NORM_INFO content is left to the application's discretion /// A NormObjectHandle is returned which the application may use in other NORM API calls as needed. [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); /// /// 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. /// A NormObjectHandle is returned which the application may use in other NORM API calls as needed. [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); /// /// 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 /// The numBytes parameter indicates the length of the data content. /// This function returns the number of bytes of data successfully enqueued for NORM stream transmission. [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); /// /// 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. [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); /// /// 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 /// 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 /// Specifies the length of data. - /// + /// 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. [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); /// /// 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. [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); /// /// 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. /// [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); /// /// 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 /// port number and/or specify a specific source address binding that is used for packet transmission. /// A value of true is returned upon success and false upon failure. An invalid nodeHandle parameter value would lead to such failure. [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); /// /// 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. /// /// notification for a given remote sender when multiple senders may be providing content - /// Allocated system resources for each active sender + /// Allocated system resources for each active sender /// A return value of false indicates that either no command was available or the provided buffer size /// 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. [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); /// /// This function releases memory resources that were allocated for a remote sender. diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormFile.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormFile.cs index a627a48..0146f67 100644 --- a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormFile.cs +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormFile.cs @@ -1,4 +1,7 @@ -namespace Mil.Navy.Nrl.Norm +using System.Runtime.InteropServices; +using System.Text; + +namespace Mil.Navy.Nrl.Norm { /// /// 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()); } } diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormNode.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormNode.cs index dbb9c7d..46dba7a 100644 --- a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormNode.cs +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormNode.cs @@ -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); /// - /// NORM application-defined command for transmission. + /// This function retrieves the content of an application-defined command that was received from a remote sender. /// - public byte[] Command + /// Thrown when the offset or length are outside of the buffer. + 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; } /// diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormObject.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormObject.cs index 4d7ffef..f3ded3a 100644 --- a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormObject.cs +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormObject.cs @@ -1,4 +1,6 @@ -namespace Mil.Navy.Nrl.Norm +using System.Runtime.InteropServices; + +namespace Mil.Navy.Nrl.Norm { /// /// 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; } } diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormSession.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormSession.cs index b7a318b..2aa968e 100644 --- a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormSession.cs +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormSession.cs @@ -466,23 +466,35 @@ namespace Mil.Navy.Nrl.Norm /// The optional info and infoLength parameters are used to associate NORM_INFO content with the sent transport object. /// A NormFile is returned which the application may use in other NORM API calls as needed. /// Thrown when NormFileEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue file. - public NormFile FileEnqueue(string filename, byte[] info, int infoOffset, int infoLength) + /// Thrown when the info offset or info length are outside of the info buffer. + 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 /// A NormData is returned which the application may use in other NORM API calls as needed. /// Thrown when NormDataEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue data. /// Thrown when the data offset or data length are outside of the data buffer. - 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 /// A NormData is returned which the application may use in other NORM API calls as needed. /// Thrown when NormDataEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue data. /// Thrown when the data offset, data length, info offset or info length are outside of the associated buffer. - 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); + } + } + + /// + /// This function enqueues a segment of application memory space for transmission. + /// + /// + /// This is an overload which will call DataEnqueue() with info set to null, infoOffset set to 0, and infoLength set to 0. + /// + /// The dataPtr is a pointer to the message to be transmitted. + /// Indicates the start of the message. Anything before it will not be sent. + /// Note: to send full message dataOffset should be set to 0. + /// Size of the message. + /// A NormData is returned which the application may use in other NORM API calls as needed. + /// Thrown when NormDataEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue data. + /// Thrown when the data offset or data length are outside of the data buffer. + public NormData DataEnqueue(nint dataPtr, int dataOffset, int dataLength) + { + return DataEnqueue(dataPtr, dataOffset, dataLength, null, 0, 0); + } + + /// + /// This function enqueues a segment of application memory space for transmission. + /// + /// The dataPtr is a pointer to the message to be transmitted. + /// Indicates the start of the message. Anything before it will not be sent. + /// Note: to send full message dataOffset should be set to 0. + /// Size of the message. + /// The optional info and infoLength parameters are used to associate NORM_INFO content with the sent transport object. + /// Indicates the start of the message. + /// The optional info and infoLength parameters are used to associate NORM_INFO content with the sent transport object. + /// A NormData is returned which the application may use in other NORM API calls as needed. + /// Thrown when NormDataEnqueue() returns NORM_OBJECT_INVALID, indicating the failure to enqueue data. + /// Thrown when the data offset, data length, info offset or info length are outside of the associated buffer. + 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 /// Size of the message. /// A NormStream is returned which the application may use in other NORM API calls as needed. /// Thrown when NormStreamOpen() returns NORM_OBJECT_INVALID, indicating the failure to open stream. + /// Thrown when the info offset or info length are outside of the info buffer. 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. /// /// 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. + /// /// 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. /// 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. /// Thrown when NormSendCommand() returns false, indicating the failure to send command. - public void SendCommand(byte[] cmdBuffer, int cmdLength, bool robust) + /// Thrown when the offset or length are outside of the buffer. + 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(); } } diff --git a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormStream.cs b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormStream.cs index 3732051..c6b39d1 100644 --- a/src/dotnet/src/Mil.Navy.Nrl.Norm/NormStream.cs +++ b/src/dotnet/src/Mil.Navy.Nrl.Norm/NormStream.cs @@ -1,4 +1,6 @@ -namespace Mil.Navy.Nrl.Norm +using System.Runtime.InteropServices; + +namespace Mil.Navy.Nrl.Norm { /// /// 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. /// The length parameter indicates the length of the data content. /// This function returns the number of bytes of data successfully enqueued for NORM stream transmission. + /// Thrown when the offset or length are outside of the buffer. 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; } /// @@ -122,22 +146,31 @@ /// Note: To read the data in its entirety, begin at offset 0. /// Expected length of data received /// The length of data received + /// Thrown when the offset or length are outside of the buffer. 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; diff --git a/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormInstanceTests.cs b/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormInstanceTests.cs index e811132..60bd071 100644 --- a/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormInstanceTests.cs +++ b/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormInstanceTests.cs @@ -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)); diff --git a/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormSessionTests.cs b/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormSessionTests.cs index a478299..39d24d5 100644 --- a/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormSessionTests.cs +++ b/src/dotnet/tests/Mil.Navy.Nrl.Norm.IntegrationTests/NormSessionTests.cs @@ -1,5 +1,7 @@ using Bogus; +using Mil.Navy.Nrl.Norm.Buffers; using Mil.Navy.Nrl.Norm.Enums; +using System.Net; using System.Text; namespace Mil.Navy.Nrl.Norm.IntegrationTests @@ -240,8 +242,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests { var actualId = normNode.Id; Assert.NotEqual(NormNode.NORM_NODE_NONE, actualId); + var expectedIpAddresses = Dns.GetHostAddresses(Dns.GetHostName()) + .Where(i => i.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !IPAddress.IsLoopback(i)); var actualAddress = normNode.Address; Assert.NotNull(actualAddress); + Assert.Contains(actualAddress.Address, expectedIpAddresses); + Assert.NotEqual(default, actualAddress.Port); var actualGrtt = normNode.Grtt; Assert.NotEqual(-1, actualGrtt); var expectedEventString = $"NormEvent [type={normEvent.Type}]"; @@ -251,8 +257,41 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests } } - [SkippableFact(typeof(IOException))] - public void EnqueuesFile() + public static IEnumerable GenerateInfo() + { + var info = new List(); + + var infoContent = GenerateInfoContent(); + var expectedInfoContent = infoContent; + var infoOffset = 0; + var infoLength = infoContent.Length; + info.Add(new object?[] { infoContent, expectedInfoContent, infoOffset, infoLength }); + + var faker = new Faker(); + infoLength = faker.Random.Int(infoContent.Length / 2, infoContent.Length - 1); + expectedInfoContent = infoContent.Substring(infoOffset, infoLength); + info.Add(new object?[] { infoContent, expectedInfoContent, infoOffset, infoLength }); + + infoOffset = faker.Random.Int(1, (infoContent.Length - 1) / 2); + infoLength = infoContent.Length - infoOffset; + expectedInfoContent = infoContent.Substring(infoOffset, infoLength); + info.Add(new object?[] { infoContent, expectedInfoContent, infoOffset, infoLength }); + + infoOffset = faker.Random.Int(1, (infoContent.Length - 1) / 2); + infoLength = faker.Random.Int(1, infoContent.Length - infoOffset); + expectedInfoContent = infoContent.Substring(infoOffset, infoLength); + info.Add(new object?[] { infoContent, expectedInfoContent, infoOffset, infoLength }); + + info.Add(new object?[] { null, null, null, null }); + + info.Add(new object?[] { null, "", 0, 0 }); + + return info; + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateInfo))] + public void EnqueuesFile(string? infoContent = null, string? expectedInfoContent = null, int? infoOffset = null, int? infoLength = null) { StartSender(); @@ -260,10 +299,27 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var fileName = Guid.NewGuid().ToString(); var filePath = Path.Combine(_testPath, fileName); File.WriteAllText(filePath, fileContent); + //Create info to enqueue + byte[]? info = null; + if (infoContent != null) { + info = Encoding.ASCII.GetBytes(infoContent); + } + else if (expectedInfoContent == null) + { + expectedInfoContent = filePath; + } + + var expectedInfo = Array.Empty(); + if (expectedInfoContent != null) + { + expectedInfo = Encoding.ASCII.GetBytes(expectedInfoContent); + } try { - var normFile = _normSession.FileEnqueue(filePath); + var normFile = infoOffset != null && infoLength != null ? + _normSession.FileEnqueue(filePath, info, infoOffset.Value, infoLength.Value) : + _normSession.FileEnqueue(filePath); Assert.NotNull(normFile); var expectedEventTypes = new List { NormEventType.NORM_TX_OBJECT_SENT, NormEventType.NORM_TX_QUEUE_EMPTY }; var actualEvents = GetEvents(); @@ -272,6 +328,13 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var expectedFileName = filePath; var actualFileName = normFile.Name; Assert.Equal(expectedFileName, actualFileName); + var actualInfo = normFile.Info; + Assert.Equal(expectedInfo, actualInfo); + if (actualInfo != null) + { + var actualInfoContent = Encoding.ASCII.GetString(actualInfo); + Assert.Equal(expectedInfoContent, actualInfoContent); + } } catch (Exception) { @@ -283,8 +346,70 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests } } - [SkippableFact(typeof(IOException))] - public void ReceivesFile() + public static IEnumerable GenerateOutOfRangeInfo() + { + var info = new List(); + var faker = new Faker(); + + var infoContent = GenerateInfoContent(); + var infoOffset = faker.Random.Int(-infoContent.Length, -1); + var infoLength = infoContent.Length; + info.Add(new object[] { infoContent, infoOffset, infoLength }); + + infoOffset = faker.Random.Int(infoContent.Length, infoContent.Length * 2); + infoLength = infoContent.Length; + info.Add(new object[] { infoContent, infoOffset, infoLength }); + + infoOffset = 0; + infoLength = faker.Random.Int(infoContent.Length + 1, infoContent.Length * 2); + info.Add(new object[] { infoContent, infoOffset, infoLength }); + + infoLength = -1; + info.Add(new object[] { infoContent, infoOffset, infoLength }); + + infoLength = 0; + info.Add(new object[] { infoContent, infoOffset, infoLength }); + + infoOffset = infoContent.Length - 1; + infoLength = infoContent.Length; + info.Add(new object[] { infoContent, infoOffset, infoLength }); + + return info; + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateOutOfRangeInfo))] + public void EnqueuesFileThrowsExceptionWhenOutOfRange(string? infoContent = null, int? infoOffset = null, int? infoLength = null) + { + StartSender(); + + var fileContent = GenerateTextContent(); + var fileName = Guid.NewGuid().ToString(); + var filePath = Path.Combine(_testPath, fileName); + File.WriteAllText(filePath, fileContent); + //Create info to enqueue + var info = infoContent != null ? Encoding.ASCII.GetBytes(infoContent) : null; + + try + { + Assert.Throws(() => + infoOffset != null && infoLength != null ? + _normSession.FileEnqueue(filePath, info, infoOffset.Value, infoLength.Value) : + _normSession.FileEnqueue(filePath)); + } + catch (Exception) + { + throw; + } + finally + { + StopSender(); + } + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateInfo))] + public void ReceivesFile(string? infoContent = null, string? expectedInfoContent = null, int? infoOffset = null, int? infoLength = null) { _normSession.SetLoopback(true); StartSender(); @@ -301,11 +426,27 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var fileContent = GenerateTextContent(); var filePath = Path.Combine(_testPath, fileName); File.WriteAllText(filePath, fileContent); + //Create info to enqueue + byte[]? info = null; + if (infoContent != null) { + info = Encoding.ASCII.GetBytes(infoContent); + } + else if (expectedInfoContent == null) + { + expectedInfoContent = filePath; + } + var expectedInfo = Array.Empty(); + if (expectedInfoContent != null) + { + expectedInfo = Encoding.ASCII.GetBytes(expectedInfoContent); + } try { //Enqueue file - var normFile = _normSession.FileEnqueue(filePath); + var normFile = infoOffset != null && infoLength != null ? + _normSession.FileEnqueue(filePath, info, infoOffset.Value, infoLength.Value) : + _normSession.FileEnqueue(filePath); //Wait for events var normEvents = GetEvents(); AssertNormEvents(normEvents); @@ -329,6 +470,13 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var actualContent = File.ReadAllText(actualFileName); Assert.Equal(fileContent, actualContent); + var actualInfo = receivedNormFile.Info; + Assert.Equal(expectedInfo, actualInfo); + if (actualInfo != null) + { + var actualInfoContent = Encoding.ASCII.GetString(actualInfo); + Assert.Equal(expectedInfoContent, actualInfoContent); + } } catch (Exception) { @@ -429,12 +577,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests expectedInfoContent = infoContent.Substring(infoOffset, infoLength); data.Add(new object[] { dataContent, expectedDataContent, dataOffset, dataLength, infoContent, expectedInfoContent, infoOffset, infoLength }); - infoOffset = faker.Random.Int(1, infoContent.Length - 1 / 2); + infoOffset = faker.Random.Int(1, (infoContent.Length - 1) / 2); infoLength = infoContent.Length - infoOffset; expectedInfoContent = infoContent.Substring(infoOffset, infoLength); data.Add(new object[] { dataContent, expectedDataContent, dataOffset, dataLength, infoContent, expectedInfoContent, infoOffset, infoLength }); - infoOffset = faker.Random.Int(1, infoContent.Length - 1 / 2); + infoOffset = faker.Random.Int(1, (infoContent.Length - 1) / 2); infoLength = faker.Random.Int(1, infoContent.Length - infoOffset); expectedInfoContent = infoContent.Substring(infoOffset, infoLength); data.Add(new object[] { dataContent, expectedDataContent, dataOffset, dataLength, infoContent, expectedInfoContent, infoOffset, infoLength }); @@ -443,12 +591,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests expectedDataContent = dataContent.Substring(dataOffset, dataLength); data.Add(new object[] { dataContent, expectedDataContent, dataOffset, dataLength }); - dataOffset = faker.Random.Int(1, dataContent.Length - 1 / 2); + dataOffset = faker.Random.Int(1, (dataContent.Length - 1) / 2); dataLength = dataContent.Length - dataOffset; expectedDataContent = dataContent.Substring(dataOffset, dataLength); data.Add(new object[] { dataContent, expectedDataContent, dataOffset, dataLength }); - dataOffset = faker.Random.Int(1, dataContent.Length - 1 / 2); + dataOffset = faker.Random.Int(1, (dataContent.Length - 1) / 2); dataLength = faker.Random.Int(1, dataContent.Length - dataOffset); expectedDataContent = dataContent.Substring(dataOffset, dataLength); data.Add(new object[] { dataContent, expectedDataContent, dataOffset, dataLength }); @@ -463,6 +611,8 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests StartSender(); //Create data to write to enqueue var data = Encoding.ASCII.GetBytes(dataContent); + using var dataBuffer = ByteBuffer.AllocateDirect(data.Length); + dataBuffer.WriteArray(0, data, 0, data.Length); var expectedData = Encoding.ASCII.GetBytes(expectedDataContent); //Create info to enqueue var info = infoContent != null ? Encoding.ASCII.GetBytes(infoContent) : null; @@ -471,8 +621,8 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { var normData = infoOffset != null && infoLength != null ? - _normSession.DataEnqueue(data, dataOffset, dataLength, info, infoOffset.Value, infoLength.Value) : - _normSession.DataEnqueue(data, dataOffset, dataLength); + _normSession.DataEnqueue(dataBuffer, dataOffset, dataLength, info, infoOffset.Value, infoLength.Value) : + _normSession.DataEnqueue(dataBuffer, dataOffset, dataLength); var expectedEventTypes = new List { NormEventType.NORM_TX_OBJECT_SENT, NormEventType.NORM_TX_QUEUE_EMPTY }; var actualEventTypes = GetEvents().Select(e => e.Type).ToList(); Assert.Equal(expectedEventTypes, actualEventTypes); @@ -516,6 +666,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests dataLength = faker.Random.Int(dataContent.Length + 1, dataContent.Length * 2); data.Add(new object[] { dataContent, dataOffset, dataLength }); + dataLength = -1; + data.Add(new object[] { dataContent, dataOffset, dataLength }); + + dataLength = 0; + data.Add(new object[] { dataContent, dataOffset, dataLength }); + dataOffset = dataContent.Length - 1; dataLength = dataContent.Length; data.Add(new object[] { dataContent, dataOffset, dataLength }); @@ -536,6 +692,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests infoLength = faker.Random.Int(infoContent.Length + 1, infoContent.Length * 2); data.Add(new object[] { dataContent, dataOffset, dataLength, infoContent, infoOffset, infoLength }); + infoLength = -1; + data.Add(new object[] { dataContent, dataOffset, dataLength, infoContent, infoOffset, infoLength }); + + infoLength = 0; + data.Add(new object[] { dataContent, dataOffset, dataLength, infoContent, infoOffset, infoLength }); + infoOffset = infoContent.Length - 1; infoLength = infoContent.Length; data.Add(new object[] { dataContent, dataOffset, dataLength, infoContent, infoOffset, infoLength }); @@ -550,6 +712,8 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests StartSender(); //Create data to enqueue var data = Encoding.ASCII.GetBytes(dataContent); + using var dataBuffer = ByteBuffer.AllocateDirect(data.Length); + dataBuffer.WriteArray(0, data, 0, data.Length); //Create info to enqueue var info = infoContent != null ? Encoding.ASCII.GetBytes(infoContent) : null; @@ -557,8 +721,8 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests { Assert.Throws(() => infoOffset != null && infoLength != null ? - _normSession.DataEnqueue(data, dataOffset, dataLength, info, infoOffset.Value, infoLength.Value) : - _normSession.DataEnqueue(data, dataOffset, dataLength)); + _normSession.DataEnqueue(dataBuffer, dataOffset, dataLength, info, infoOffset.Value, infoLength.Value) : + _normSession.DataEnqueue(dataBuffer, dataOffset, dataLength)); } catch (Exception) { @@ -586,6 +750,8 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var data = Encoding.ASCII.GetBytes(content); + using var dataBuffer = ByteBuffer.AllocateDirect(data.Length); + dataBuffer.WriteArray(0, data, 0, data.Length); var expectedData = Encoding.ASCII.GetBytes(expectedDataContent); //Create info to be sent var info = infoContent != null ? Encoding.ASCII.GetBytes(infoContent) : null; @@ -594,8 +760,8 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { var normData = infoOffset != null && infoLength != null ? - _normSession.DataEnqueue(data, dataOffset, dataLength, info, infoOffset.Value, infoLength.Value) : - _normSession.DataEnqueue(data, dataOffset, dataLength); + _normSession.DataEnqueue(dataBuffer, dataOffset, dataLength, info, infoOffset.Value, infoLength.Value) : + _normSession.DataEnqueue(dataBuffer, dataOffset, dataLength); var expectedEventTypes = new List { NormEventType.NORM_REMOTE_SENDER_NEW, @@ -619,7 +785,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests Assert.Equal(expectedData, actualData); var actualDataContent = Encoding.ASCII.GetString(actualData); Assert.Equal(expectedDataContent, actualDataContent); - var actualInfo = normData.Info; + var actualInfo = actualNormData.Info; Assert.Equal(expectedInfo, actualInfo); if (actualInfo != null) { @@ -638,29 +804,41 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests } } - [SkippableFact(typeof(IOException))] - public void SendsStream() + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateData))] + public void SendsStream(string content, string expectedContent, int offset, int length, string? infoContent = null, string expectedInfoContent = "", int? infoOffset = null, int? infoLength = null) { StartSender(); - var fileContent = GenerateTextContent(); - var data = Encoding.ASCII.GetBytes(fileContent); - var dataOffset = 0; + var buffer = Encoding.ASCII.GetBytes(content); + var expectedBuffer = Encoding.ASCII.GetBytes(expectedContent); + //Create info to enqueue + var info = infoContent != null ? Encoding.ASCII.GetBytes(infoContent) : null; + var expectedInfo = Encoding.ASCII.GetBytes(expectedInfoContent); NormStream? normStream = null; try { var repairWindowSize = 1024 * 1024; - normStream = _normSession.StreamOpen(repairWindowSize); + normStream = infoOffset != null && infoLength != null ? + _normSession.StreamOpen(repairWindowSize, info, infoOffset.Value, infoLength.Value) : + _normSession.StreamOpen(repairWindowSize); - var expectedBytesWritten = data.Length; - var actualBytesWritten = normStream.Write(data, dataOffset, data.Length); + var expectedBytesWritten = expectedBuffer.Length; + var actualBytesWritten = normStream.Write(buffer, offset, length); WaitForEvents(); normStream.MarkEom(); normStream.Flush(); Assert.Equal(expectedBytesWritten, actualBytesWritten); + var actualInfo = normStream.Info; + Assert.Equal(expectedInfo, actualInfo); + if (actualInfo != null) + { + var actualInfoContent = Encoding.ASCII.GetString(actualInfo); + Assert.Equal(expectedInfoContent, actualInfoContent); + } } catch (Exception) { @@ -673,31 +851,65 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests } } - [SkippableFact(typeof(IOException))] - public void ReceivesStream() + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateOutOfRangeData))] + public void SendsStreamThrowsExceptionWhenOutOfRange(string content, int offset, int length, string? infoContent = null, int? infoOffset = null, int? infoLength = null) { - _normSession.SetLoopback(true); StartSender(); - StartReceiver(); - - //Set up cache directory - var folderName = Guid.NewGuid().ToString(); - var cachePath = Path.Combine(_testPath, folderName); - Directory.CreateDirectory(cachePath); - _normInstance.SetCacheDirectory(cachePath); - - var fileContent = GenerateTextContent(); - var data = Encoding.ASCII.GetBytes(fileContent); - var dataOffset = 0; + var buffer = Encoding.ASCII.GetBytes(content); + //Create info to enqueue + var info = infoContent != null ? Encoding.ASCII.GetBytes(infoContent) : null; NormStream? normStream = null; try { var repairWindowSize = 1024 * 1024; - normStream = _normSession.StreamOpen(repairWindowSize); - var expectedBytesWritten = data.Length; - normStream.Write(data, dataOffset, data.Length-dataOffset); + if (infoOffset != null && infoLength != null) { + Assert.Throws(() => + _normSession.StreamOpen(repairWindowSize, info, infoOffset.Value, infoLength.Value)); + } + else + { + normStream = _normSession.StreamOpen(repairWindowSize); + Assert.Throws(() => + normStream.Write(buffer, offset, length)); + } + } + catch (Exception) + { + throw; + } + finally + { + StopSender(); + } + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateData))] + public void ReceivesStream(string content, string expectedContent, int offset, int length, string? infoContent = null, string expectedInfoContent = "", int? infoOffset = null, int? infoLength = null) + { + _normSession.SetLoopback(true); + StartSender(); + StartReceiver(); + + var buffer = Encoding.ASCII.GetBytes(content); + var expectedBuffer = Encoding.ASCII.GetBytes(expectedContent); + //Create info to enqueue + var info = infoContent != null ? Encoding.ASCII.GetBytes(infoContent) : null; + var expectedInfo = Encoding.ASCII.GetBytes(expectedInfoContent); + NormStream? normStream = null; + + try + { + var repairWindowSize = 1024 * 1024; + normStream = infoOffset != null && infoLength != null ? + _normSession.StreamOpen(repairWindowSize, info, infoOffset.Value, infoLength.Value) : + _normSession.StreamOpen(repairWindowSize); + + var expectedBytesWritten = expectedBuffer.Length; + normStream.Write(buffer, offset, length); normStream.MarkEom(); normStream.Flush(); @@ -711,15 +923,22 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var receivedNormStream = Assert.IsType(normObjectEvent.Object); var numRead = 0; var receiveBuffer = new byte[65536]; - while ((numRead = receivedNormStream.Read(receiveBuffer, dataOffset, receiveBuffer.Length-dataOffset)) > 0) + while ((numRead = receivedNormStream.Read(receiveBuffer, 0, length)) > 0) { if (numRead != -1) { var receivedData = receiveBuffer.Take(numRead).ToArray(); var receivedContent = Encoding.ASCII.GetString(receivedData); - Assert.Equal(fileContent, receivedContent); + Assert.Equal(expectedContent, receivedContent); } } + var actualInfo = receivedNormStream.Info; + Assert.Equal(expectedInfo, actualInfo); + if (actualInfo != null) + { + var actualInfoContent = Encoding.ASCII.GetString(actualInfo); + Assert.Equal(expectedInfoContent, actualInfoContent); + } } catch (Exception) { @@ -800,6 +1019,90 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests } } + public static IEnumerable GenerateOutOfRangeReceiveStream() + { + var data = new List(); + + var faker = new Faker(); + var initialLength = faker.Random.Int(256, 1024); + var dataOffset = faker.Random.Int(-initialLength, -1); + var dataLength = initialLength; + data.Add(new object[] { initialLength, dataOffset, dataLength }); + + dataOffset = faker.Random.Int(initialLength, initialLength * 2); + dataLength = initialLength; + data.Add(new object[] { initialLength, dataOffset, dataLength }); + + dataOffset = 0; + dataLength = faker.Random.Int(initialLength + 1, initialLength * 2); + data.Add(new object[] { initialLength, dataOffset, dataLength }); + + dataLength = -1; + data.Add(new object[] { initialLength, dataOffset, dataLength }); + + dataLength = 0; + data.Add(new object[] { initialLength, dataOffset, dataLength }); + + dataOffset = initialLength - 1; + dataLength = initialLength; + data.Add(new object[] { initialLength, dataOffset, dataLength }); + + return data; + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateOutOfRangeReceiveStream))] + public void ReceivesStreamThrowsExceptionWhenOutOfRange(int initialReceiveBufferLength, int receiveBufferOffset, int receiveBufferLength) + { + _normSession.SetLoopback(true); + StartSender(); + StartReceiver(); + + //Set up cache directory + var folderName = Guid.NewGuid().ToString(); + var cachePath = Path.Combine(_testPath, folderName); + Directory.CreateDirectory(cachePath); + _normInstance.SetCacheDirectory(cachePath); + + var fileContent = GenerateTextContent(); + var data = Encoding.ASCII.GetBytes(fileContent); + NormStream? normStream = null; + + try + { + var repairWindowSize = 1024 * 1024; + + normStream = _normSession.StreamOpen(repairWindowSize); + var offset = 0; + var length = data.Length; + normStream.Write(data, offset, length); + normStream.MarkEom(); + normStream.Flush(); + + var normEvents = GetEvents(); + AssertNormEvents(normEvents); + + var expectedNormEventType = NormEventType.NORM_RX_OBJECT_UPDATED; + var normObjectEvent = normEvents.First(e => e.Type == expectedNormEventType); + var receivedNormStream = Assert.IsType(normObjectEvent.Object); + + var receiveBuffer = new byte[initialReceiveBufferLength]; + + Assert.Throws(() => + receivedNormStream.Read(receiveBuffer, receiveBufferOffset, receiveBufferLength)); + } + catch (Exception) + { + throw; + } + finally + { + normStream?.Close(true); + StopSender(); + StopReceiver(); + } + } + [Fact] public void SetsTxPort() { @@ -1040,10 +1343,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); var expectedEventTypes = new List { NormEventType.NORM_TX_OBJECT_SENT, NormEventType.NORM_TX_QUEUE_EMPTY }; var actualEventTypes = GetEvents().Select(e => e.Type).ToList(); Assert.Equal(expectedEventTypes, actualEventTypes); @@ -1078,10 +1383,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var expectedContent = GenerateTextContent(); var expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); _normSession.SetWatermark(normData); var expectedEventTypes = new List { @@ -1126,10 +1433,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var expectedContent = GenerateTextContent(); var expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); _normSession.SetWatermark(normData); _normSession.CancelWatermark(); var expectedEventTypes = new List @@ -1173,10 +1482,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var expectedContent = GenerateTextContent(); var expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); _normSession.SetWatermark(normData); var expectedEventTypes = new List { @@ -1243,10 +1554,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var expectedContent = GenerateTextContent(); var expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); _normSession.SetWatermark(normData); WaitForEvents(TimeSpan.FromSeconds(1)); var expectedAckingStatus = NormAckingStatus.NORM_ACK_SUCCESS; @@ -1268,13 +1581,13 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests public void SendsCommand() { StartSender(); - //Create data to write to the stream + //Create command to send var expectedContent = GenerateTextContent(); byte[] expectedCommand = Encoding.ASCII.GetBytes(expectedContent); try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var expectedEventTypes = new List { NormEventType.NORM_TX_CMD_SENT }; var actualEventTypes = GetEvents().Select(e => e.Type).ToList(); Assert.Equal(expectedEventTypes, actualEventTypes); @@ -1289,19 +1602,77 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests } } + public static IEnumerable GenerateOutOfRangeCommand() + { + var command = new List(); + var faker = new Faker(); + + var content = GenerateInfoContent(); + var offset = faker.Random.Int(-content.Length, -1); + var length = content.Length; + command.Add(new object[] { content, offset, length }); + + offset = faker.Random.Int(content.Length, content.Length * 2); + length = content.Length; + command.Add(new object[] { content, offset, length }); + + offset = 0; + length = faker.Random.Int(content.Length + 1, content.Length * 2); + command.Add(new object[] { content, offset, length }); + + length = -1; + command.Add(new object[] { content, offset, length }); + + length = 0; + command.Add(new object[] { content, offset, length }); + + offset = content.Length - 1; + length = content.Length; + command.Add(new object[] { content, offset, length }); + + return command; + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateOutOfRangeCommand))] + public void SendsCommandThrowsExceptionWhenOutOfRange(string content, int offset, int length) + { + StartSender(); + //Create data to enqueue + var command = Encoding.ASCII.GetBytes(content); + + try + { + Assert.Throws(() => + _normSession.SendCommand(command, offset, length, false)); + } + catch (Exception) + { + throw; + } + finally + { + StopSender(); + } + } + [SkippableFact(typeof(IOException))] public void ReceivesCommand() { _normSession.SetLoopback(true); StartSender(); StartReceiver(); - //Create data to write to the stream - var expectedContent = GenerateTextContent(); - byte[] expectedCommand = Encoding.ASCII.GetBytes(expectedContent); + //Create command to send + var content = GenerateInfoContent(); + var expectedContent = content; + var offset = 0; + var length = content.Length; + var command = Encoding.ASCII.GetBytes(content); + var expectedCommand = Encoding.ASCII.GetBytes(expectedContent); try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(command, 0, command.Length, false); var expectedEventTypes = new List { NormEventType.NORM_TX_CMD_SENT, @@ -1309,8 +1680,17 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests NormEventType.NORM_REMOTE_SENDER_ACTIVE, NormEventType.NORM_RX_CMD_NEW }; - var actualEventTypes = GetEvents().Select(e => e.Type).ToList(); + var actualEvents = GetEvents(); + var actualEventTypes = actualEvents.Select(e => e.Type).ToList(); Assert.Equivalent(expectedEventTypes, actualEventTypes); + + var actualEvent = actualEvents.First(e => e.Type == NormEventType.NORM_RX_CMD_NEW); + var actualCommand = new byte[command.Length]; + var actualLength = actualEvent?.Node?.GetCommand(actualCommand, offset, length); + Assert.Equal(length, actualLength); + Assert.Equal(expectedCommand, actualCommand); + var actualContent = Encoding.ASCII.GetString(actualCommand); + Assert.Equal(expectedContent, actualContent); } catch (Exception) { @@ -1323,6 +1703,110 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests } } + private void ReceivesCommandThrowsException(string content, int offset, int length) where TExceptionType : Exception + { + _normSession.SetLoopback(true); + StartSender(); + StartReceiver(); + //Create command to send + var command = Encoding.ASCII.GetBytes(content); + + try + { + _normSession.SendCommand(command, 0, command.Length, false); + var expectedEventTypes = new List + { + NormEventType.NORM_TX_CMD_SENT, + NormEventType.NORM_REMOTE_SENDER_NEW, + NormEventType.NORM_REMOTE_SENDER_ACTIVE, + NormEventType.NORM_RX_CMD_NEW + }; + var actualEvents = GetEvents(); + var actualEventTypes = actualEvents.Select(e => e.Type).ToList(); + Assert.Equivalent(expectedEventTypes, actualEventTypes); + + var actualEvent = actualEvents.First(e => e.Type == NormEventType.NORM_RX_CMD_NEW); + var actualCommand = new byte[command.Length]; + Assert.Throws(() => + actualEvent?.Node?.GetCommand(actualCommand, offset, length)); + } + catch (Exception) + { + throw; + } + finally + { + StopSender(); + StopReceiver(); + } + } + + public static IEnumerable GenerateShortLengthCommand() + { + var command = new List(); + + var content = GenerateInfoContent(); + var faker = new Faker(); + var offset = 0; + var length = faker.Random.Int(content.Length / 2, content.Length - 1); + command.Add(new object[] { content, offset, length }); + + offset = faker.Random.Int(1, (content.Length - 1) / 2); + length = content.Length - offset; + command.Add(new object[] { content, offset, length }); + + offset = faker.Random.Int(1, (content.Length - 1) / 2); + length = faker.Random.Int(1, content.Length - offset); + command.Add(new object[] { content, offset, length }); + + return command; + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateShortLengthCommand))] + public void ReceivesCommandThrowsExceptionWhenLengthLessThanCommand(string content, int offset, int length) + { + ReceivesCommandThrowsException(content, offset, length); + } + + public static IEnumerable GenerateOutOfRangeReceiveCommand() + { + var command = new List(); + + var content = GenerateTextContent(); + var faker = new Faker(); + var offset = faker.Random.Int(-content.Length, -1); + var length = content.Length; + command.Add(new object[] { content, offset, length }); + + offset = faker.Random.Int(content.Length, content.Length * 2); + length = content.Length; + command.Add(new object[] { content, offset, length }); + + offset = 0; + length = faker.Random.Int(content.Length + 1, content.Length * 2); + command.Add(new object[] { content, offset, length }); + + length = -1; + command.Add(new object[] { content, offset, length }); + + length = 0; + command.Add(new object[] { content, offset, length }); + + offset = content.Length - 1; + length = content.Length; + command.Add(new object[] { content, offset, length }); + + return command; + } + + [SkippableTheory(typeof(IOException))] + [MemberData(nameof(GenerateOutOfRangeReceiveCommand))] + public void ReceivesCommandThrowsExceptionWhenOutOfRange(string content, int offset, int length) + { + ReceivesCommandThrowsException(content, offset, length); + } + [SkippableFact(typeof(IOException))] public void CancelsCommand() { @@ -1333,7 +1817,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); _normSession.CancelCommand(); var expectedEventTypes = new List(); var actualEventTypes = GetEvents().Select(e => e.Type).ToList(); @@ -1390,7 +1874,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var normEventType = NormEventType.NORM_RX_CMD_NEW; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -1464,7 +1948,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var normEventType = NormEventType.NORM_RX_CMD_NEW; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -1510,7 +1994,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var normEventType = NormEventType.NORM_RX_CMD_NEW; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -1549,7 +2033,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var normEventType = NormEventType.NORM_RX_CMD_NEW; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -1581,7 +2065,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var normEventType = NormEventType.NORM_RX_CMD_NEW; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -1589,7 +2073,9 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var actualNode = actualEvent.Node; Assert.NotNull(actualNode); - var actualCommand = actualNode.Command; + var actualCommand = new byte[expectedCommand.Length]; + var actualLength = actualEvent?.Node?.GetCommand(actualCommand, 0, expectedCommand.Length); + Assert.Equal(expectedCommand.Length, actualLength); Assert.Equal(expectedCommand, actualCommand); var actualContent = Encoding.ASCII.GetString(actualCommand); Assert.Equal(expectedContent, actualContent); @@ -1617,7 +2103,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var normEventType = NormEventType.NORM_RX_CMD_NEW; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -1649,7 +2135,7 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests try { - _normSession.SendCommand(expectedCommand, expectedCommand.Length, false); + _normSession.SendCommand(expectedCommand, 0, expectedCommand.Length, false); var normEventType = NormEventType.NORM_RX_CMD_NEW; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -1677,10 +2163,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); Assert.Equal(NormObjectType.NORM_OBJECT_DATA, normData.Type); } catch (Exception) @@ -1752,10 +2240,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); var expectedSize = Encoding.ASCII.GetByteCount(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); Assert.Equal(expectedSize, normData.Size); } catch (Exception) @@ -1775,10 +2265,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); normData.SetNackingMode(NormNackingMode.NORM_NACK_NONE); } catch (Exception) @@ -1798,10 +2290,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); normData.SetNackingMode(NormNackingMode.NORM_NACK_INFO_ONLY); } catch (Exception) @@ -1821,10 +2315,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); normData.SetNackingMode(NormNackingMode.NORM_NACK_NORMAL); } catch (Exception) @@ -1845,10 +2341,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); var expectedBytesPending = (long)0; + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); WaitForEvents(); Assert.Equal(expectedBytesPending, normData.GetBytesPending()); } @@ -1869,10 +2367,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); normData.Cancel(); } catch (Exception) @@ -1892,10 +2392,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); normData.Retain(); } catch (Exception) @@ -1915,10 +2417,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); normData.Retain(); normData.Release(); } @@ -1939,10 +2443,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to write to the stream var expectedContent = GenerateTextContent(); byte[] expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); Assert.Throws(() => normData.Sender); } catch (Exception) @@ -1971,10 +2477,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var expectedContent = GenerateTextContent(); var expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); var normEventType = NormEventType.NORM_RX_OBJECT_COMPLETED; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -2009,10 +2517,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var expectedContent = GenerateTextContent(); var expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - var normData = _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + var normData = _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); var normEventType = NormEventType.NORM_RX_OBJECT_COMPLETED; var actualEvents = GetEvents(); Assert.Contains(normEventType, actualEvents.Select(e => e.Type)); @@ -2049,10 +2559,12 @@ namespace Mil.Navy.Nrl.Norm.IntegrationTests //Create data to be sent var expectedContent = GenerateTextContent(); var expectedData = Encoding.ASCII.GetBytes(expectedContent); + using var dataBuffer = ByteBuffer.AllocateDirect(expectedData.Length); + dataBuffer.WriteArray(0, expectedData, 0, expectedData.Length); try { - _normSession.DataEnqueue(expectedData, 0, expectedData.Length); + _normSession.DataEnqueue(dataBuffer, 0, expectedData.Length); var actualEvents = GetEvents();