v1.3b6
parent
de8a3c799b
commit
602326e415
|
|
@ -6,7 +6,7 @@
|
||||||
<META NAME="GENERATOR" CONTENT="NeoOffice/J 1.1 (Unix)">
|
<META NAME="GENERATOR" CONTENT="NeoOffice/J 1.1 (Unix)">
|
||||||
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
||||||
<META NAME="CREATED" CONTENT="20040824;14180000">
|
<META NAME="CREATED" CONTENT="20040824;14180000">
|
||||||
<META NAME="CHANGED" CONTENT="20050907;17092400">
|
<META NAME="CHANGED" CONTENT="20050919;14362900">
|
||||||
<META NAME="DESCRIPTION" CONTENT="NORM Object Functions 42
NORM Object Functions
NORM_OBJECT_STREAM
NORM Sender Functions 19
NORM Sender Functions
">
|
<META NAME="DESCRIPTION" CONTENT="NORM Object Functions 42
NORM Object Functions
NORM_OBJECT_STREAM
NORM Sender Functions 19
NORM Sender Functions
">
|
||||||
<META NAME="KEYWORDS" CONTENT="norm object value application function ">
|
<META NAME="KEYWORDS" CONTENT="norm object value application function ">
|
||||||
<STYLE>
|
<STYLE>
|
||||||
|
|
@ -51,22 +51,24 @@
|
||||||
</TD>
|
</TD>
|
||||||
<TD WIDTH=371>
|
<TD WIDTH=371>
|
||||||
<P ALIGN=LEFT STYLE="margin-left: 0.86in; margin-top: 0.17in; font-style: normal">
|
<P ALIGN=LEFT STYLE="margin-left: 0.86in; margin-top: 0.17in; font-style: normal">
|
||||||
<FONT FACE="Helvetica, sans-serif"><FONT SIZE=6 STYLE="font-size: 28pt"><B>NORM<BR>Developer’s
|
<FONT FACE="Helvetica, sans-serif"><FONT SIZE=4 STYLE="font-size: 16pt"><B><FONT SIZE=6 STYLE="font-size: 28pt">NORM<BR>Developer’s
|
||||||
<BR>Guide</B></FONT></FONT></P>
|
<BR>Guide<BR></FONT><FONT SIZE=4>(version 1.3b6)</FONT></B></FONT></FONT></P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
</TABLE>
|
</TABLE>
|
||||||
<H1 CLASS="western">Background</H1>
|
<H1 CLASS="western"><A NAME="Background">Background</A></H1>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This document describes
|
<P CLASS="western" STYLE="font-style: normal">This document describes
|
||||||
an application programming interface (API) for the Nack-Oriented
|
an application programming interface (API) for the <FONT COLOR="#0000ff"><U><A HREF="http://norm.pf.itd.nrl.navy.mil/">Nack-Oriented
|
||||||
Reliable Multicast (NORM) protocol implementation developed by the
|
Reliable Multicast (NORM)</A></U></FONT> protocol implementation
|
||||||
United States Naval Research Laboratory (NRL). The NORM protocol
|
developed by the United States <FONT COLOR="#0000ff"><U><A HREF="http://www.nrl.navy.mil/">Naval
|
||||||
provides general purpose reliable data transport for applications
|
Research Laboratory</A></U></FONT> (NRL). The NORM protocol provides
|
||||||
wishing to use Internet Protocol (IP) Multicast services for group
|
general purpose reliable data transport for applications wishing to
|
||||||
data delivery. NORM can also support unicast (point-to-point) data
|
use Internet Protocol (IP) Multicast services for group data
|
||||||
|
delivery. NORM can also support unicast (point-to-point) data
|
||||||
communication and may be used for such when deemed appropriate. The
|
communication and may be used for such when deemed appropriate. The
|
||||||
current NORM protocol specification is given in the Internet
|
current NORM protocol specification is given in the <FONT COLOR="#0000ff"><U><A HREF="http://www.ietf.org/">Internet
|
||||||
Engineering Task Force RFC 3940.</P>
|
Engineering Task Force</A></U></FONT> (IETF) <FONT COLOR="#0000ff"><U><A HREF="http://norm.pf.itd.nrl.navy.mil/rfc3940.pdf">RFC
|
||||||
|
3940</A></U></FONT>.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM protocol is
|
<P CLASS="western" STYLE="font-style: normal">The NORM protocol is
|
||||||
designed to provide end-to-end reliable transport of bulk data
|
designed to provide end-to-end reliable transport of bulk data
|
||||||
objects or streams over generic IP multicast routing and forwarding
|
objects or streams over generic IP multicast routing and forwarding
|
||||||
|
|
@ -96,32 +98,24 @@ possible group communication paradigms dictate different needs for
|
||||||
different applications. Even with NORM, the developer should have a
|
different applications. Even with NORM, the developer should have a
|
||||||
thorough understanding of the specific application's group
|
thorough understanding of the specific application's group
|
||||||
communication needs.</P>
|
communication needs.</P>
|
||||||
<H1 CLASS="western" ALIGN=CENTER STYLE="page-break-before: always">Table
|
<H1 CLASS="western" ALIGN=CENTER STYLE="page-break-before: always"><A NAME="Table
|
||||||
of Contents</H1>
|
of Contents">Table
|
||||||
|
of Contents</A></H1>
|
||||||
<DIV ID="Table of Contents1" DIR="LTR">
|
<DIV ID="Table of Contents1" DIR="LTR">
|
||||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>Overview</B></FONT></P>
|
<P STYLE="margin-top: 0.25in; font-style: normal"><BR>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
</P>
|
||||||
Initialization</B></FONT></P>
|
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B><A HREF="#Overview">Overview</A></B></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Session
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Initialization">API Initialization</A></B></FONT></P>
|
||||||
Creation and Control</B></FONT></P>
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Session Creation and Control">Session Creation and Control</A></B></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Data Transport">Data Transport</A></B></FONT></P>
|
||||||
Data Transport</B></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#Data Transmission">Data Transmission</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#Data Reception">Data Reception</A></FONT></P>
|
||||||
Data Transmission</FONT></P>
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Event Notification">API Event Notification</A></B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B><A HREF="#Build Notes">Build Notes</A></B></FONT></P>
|
||||||
Data Reception</FONT></P>
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Unix Platforms">Unix Platforms</A></B></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Win32/WiNCE Platforms">Win32/WiNCE Platforms</A></B></FONT></P>
|
||||||
Event Notification</B></FONT></P>
|
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B><A HREF="#API Reference">API Reference</A></B></FONT></P>
|
||||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>Build
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Variable Types and Constants">API Variable Types and Constants</A></B></FONT></P>
|
||||||
Notes</B></FONT></P>
|
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Unix
|
|
||||||
Platforms</B></FONT></P>
|
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Win32/WiNCE
|
|
||||||
Platforms</B></FONT></P>
|
|
||||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>API
|
|
||||||
Reference</B></FONT></P>
|
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
|
||||||
Variable Types and Constants</B></FONT></P>
|
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormInstanceHandle">NormInstanceHandle</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormInstanceHandle">NormInstanceHandle</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionHandle">NormSessionHandle</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionHandle">NormSessionHandle</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionId">NormSessionId</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionId">NormSessionId</A></FONT></P>
|
||||||
|
|
@ -138,15 +132,14 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormProbingMode">NormProbingMode</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormProbingMode">NormProbingMode</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNackingMode">NormNackingMode</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNackingMode">NormNackingMode</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAckingStatus">NormAckingStatus</A></FONT></P>
|
||||||
Initialization and Operation</B></FONT></P>
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Initialization and Operation">API Initialization and Operation</A></B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetCacheDirectory()">NormSetCacheDirectory()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetCacheDirectory()">NormSetCacheDirectory()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetDescriptor()">NormGetDescriptor()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetDescriptor()">NormGetDescriptor()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Session
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Session Creation and Control Functions">Session Creation and Control Functions</A></B></FONT></P>
|
||||||
Creation and Control</B></FONT></P>
|
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroySession()">NormDestroySession()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroySession()">NormDestroySession()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetUserData()">NormSetUserData()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetUserData()">NormSetUserData()</A></FONT></P>
|
||||||
|
|
@ -158,8 +151,7 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTTL()">NormSetTTL()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTTL()">NormSetTTL()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTOS()">NormSetTOS()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTOS()">NormSetTOS()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetLoopback()">NormSetLoopback()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetLoopback()">NormSetLoopback()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Sender Functions">NORM Sender Functions</A></B></FONT></P>
|
||||||
Sender Functions</B></FONT></P>
|
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartSender()">NormStartSender()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartSender()">NormStartSender()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopSender()">NormStopSender()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopSender()">NormStopSender()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitRate()">NormSetTransmitRate()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitRate()">NormSetTransmitRate()</A></FONT></P>
|
||||||
|
|
@ -172,8 +164,6 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttMax()">NormSetGrttMax()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttMax()">NormSetGrttMax()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingMode()">NormSetGrttProbingMode()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingMode()">NormSetGrttProbingMode()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingInterval()">NormSetGrttProbingInterval()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingInterval()">NormSetGrttProbingInterval()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT></P>
|
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT></P>
|
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileEnqueue()">NormFileEnqueue()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileEnqueue()">NormFileEnqueue()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataEnqueue()">NormDataEnqueue()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataEnqueue()">NormDataEnqueue()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT></P>
|
||||||
|
|
@ -185,8 +175,10 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamHasVacancy()">NormStreamHasVacancy()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamHasVacancy()">NormStreamHasVacancy()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamMarkEom()">NormStreamMarkEom()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamMarkEom()">NormStreamMarkEom()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT></P>
|
||||||
Receiver Functions</B></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT></P>
|
||||||
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Receiver Functions">NORM Receiver Functions</A></B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopReceiver()">NormStopReceiver()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopReceiver()">NormStopReceiver()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetRxSocketBuffer()">NormSetRxSocketBuffer()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetRxSocketBuffer()">NormSetRxSocketBuffer()</A></FONT></P>
|
||||||
|
|
@ -201,8 +193,7 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamRead()">NormStreamRead()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamRead()">NormStreamRead()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSeekMsgStart()">NormStreamSeekMsgStart()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSeekMsgStart()">NormStreamSeekMsgStart()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamGetReadOffset()">NormStreamGetReadOffset()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamGetReadOffset()">NormStreamGetReadOffset()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Object Functions">NORM Object Functions</A></B></FONT></P>
|
||||||
Object Functions</B></FONT></P>
|
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetType()">NormObjectGetType()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetType()">NormObjectGetType()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectHasInfo()">NormObjectHasInfo()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectHasInfo()">NormObjectHasInfo()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetInfoLength()">NormObjectGetInfoLength()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetInfoLength()">NormObjectGetInfoLength()</A></FONT></P>
|
||||||
|
|
@ -217,14 +208,13 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataAccessData()">NormDataAccessData()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataAccessData()">NormDataAccessData()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataDetachData()">NormDataDetachData()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataDetachData()">NormDataDetachData()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetSender()">NormObjectGetSender()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetSender()">NormObjectGetSender()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Node Functions">NORM Node Functions</A></B></FONT></P>
|
||||||
Node Functions</B></FONT></P>
|
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetId()">NormNodeGetId()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetId()">NormNodeGetId()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetAddress()">NormNodeGetAddress()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetAddress()">NormNodeGetAddress()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRetain()">NormNodeRetain()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRetain()">NormNodeRetain()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRelease()">NormNodeRelease()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRelease()">NormNodeRelease()</A></FONT></P>
|
||||||
</DIV>
|
</DIV>
|
||||||
<H1 CLASS="western" STYLE="page-break-before: always">Overview</H1>
|
<H1 CLASS="western" STYLE="page-break-before: always"><A NAME="Overview">Overview</A></H1>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM API has been
|
<P CLASS="western" STYLE="font-style: normal">The NORM API has been
|
||||||
designed to provide simple, straightforward access to and control of
|
designed to provide simple, straightforward access to and control of
|
||||||
NORM protocol state and functions. Functions are provided to create
|
NORM protocol state and functions. Functions are provided to create
|
||||||
|
|
@ -244,15 +234,14 @@ protocol thread notifies the application of various protocol events
|
||||||
through a thread-safe event dispatching mechanism and API calls are
|
through a thread-safe event dispatching mechanism and API calls are
|
||||||
provided to allow the application to control NORM operation. (<I>Note:
|
provided to allow the application to control NORM operation. (<I>Note:
|
||||||
API mechanisms for lower-level, non-threaded control and execution
|
API mechanisms for lower-level, non-threaded control and execution
|
||||||
of the NORM protocol engine will also be provided in the future</I>.)</P>
|
of the NORM protocol engine may also be provided in the future</I>.)</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM API operation
|
<P CLASS="western" STYLE="font-style: normal">The NORM API operation
|
||||||
can be roughly summarized with the following categories of functions:</P>
|
can be roughly summarized with the following categories of functions:</P>
|
||||||
<OL>
|
<OL>
|
||||||
<LI><P CLASS="western" STYLE="font-style: normal">API Initialization</P>
|
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#API Initialization">API Initialization</A></P>
|
||||||
<LI><P CLASS="western" STYLE="font-style: normal">Session Creation
|
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#Session Creation and Control">Session Creation and Control</A></P>
|
||||||
and Control</P>
|
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#Data Transport">Data Transport</A></P>
|
||||||
<LI><P CLASS="western" STYLE="font-style: normal">Data Transport</P>
|
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#API Event Notification">API Event Notification</A></P>
|
||||||
<LI><P CLASS="western" STYLE="font-style: normal">Event Notification</P>
|
|
||||||
</OL>
|
</OL>
|
||||||
<P CLASS="western" STYLE="font-style: normal">Note the order of these
|
<P CLASS="western" STYLE="font-style: normal">Note the order of these
|
||||||
categories roughly reflects the order of function calls required to
|
categories roughly reflects the order of function calls required to
|
||||||
|
|
@ -269,23 +258,37 @@ application of significant sender and receiver events. There are
|
||||||
also a number support functions provided for the application to
|
also a number support functions provided for the application to
|
||||||
control and monitor its participation within a NORM transport
|
control and monitor its participation within a NORM transport
|
||||||
session.</P>
|
session.</P>
|
||||||
<H2 CLASS="western">API Initialization</H2>
|
<H2 CLASS="western"><A NAME="API Initialization">API Initialization</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM API requires
|
<P CLASS="western" STYLE="font-style: normal">The NORM API requires
|
||||||
that an application explicitly create at least one instance of the
|
that an application explicitly create at least one instance of the
|
||||||
NORM protocol engine which is subsequently used as a conduit for
|
NORM protocol engine which is subsequently used as a conduit for
|
||||||
further NORM API calls. By default, the NORM protocol engine runs in
|
further NORM API calls. By default, the NORM protocol engine runs in
|
||||||
its own operating system thread and interacts with the application in
|
its own operating system thread and interacts with the application in
|
||||||
a thread-safe manner through the API calls and event dispatching
|
a thread-safe manner through the API calls and event dispatching
|
||||||
mechanism. In general, only the thread creating the NORM API
|
mechanism.
|
||||||
instance should invoke API calls referencing that instance or any
|
</P>
|
||||||
sessions or state created within that instance (<I>NOTE: This
|
<P CLASS="western" STYLE="font-style: normal">In general, only a
|
||||||
limitation may change in the future. The current implementation is
|
single thread should access the <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>
|
||||||
theoretically safe for concurrent access, but this has not been fully
|
API call for a given <FONT FACE="Courier">NormInstance</FONT>. This
|
||||||
tested</I>). Multiple API instances may be created as needed for
|
function serves as the conduit for delivering NORM protocol engine
|
||||||
applications with specific requirements for accessing and controlling
|
events to the application. While a NORM application can be designed
|
||||||
participation in multiple NORM sessions from operating system
|
to be single-threaded, even with multiple active <I>NormSessions</I>,
|
||||||
multiple threads.</P>
|
multiple API instances can be created (see <FONT FACE="Courier"><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT>)
|
||||||
<H2 CLASS="western">Session Creation and Control</H2>
|
as needed for applications with specific requirements for accessing
|
||||||
|
and controlling participation in multiple <I>NormSessions</I> from
|
||||||
|
separate operating system multiple threads. Or, alternatively, a
|
||||||
|
single <FONT FACE="Courier">NormInstance</FONT> could be used, with a
|
||||||
|
"master thread" serving as an intermediary between the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT> function,
|
||||||
|
demultiiplexing and dispatching events as appropriate to other "child
|
||||||
|
threads" that are created to handle "per-<I>NormSession</I>"
|
||||||
|
input/output. The advantage of this alternative approach is that the
|
||||||
|
end result would be one NORM protocol engine thread plus one "master
|
||||||
|
thread" plus one "child thread" per <I>NormSession</I>
|
||||||
|
instead of two threads (protocol engine plus application thread) per
|
||||||
|
<I>NormSession</I> if such multi-threaded operation is needed by the
|
||||||
|
application.</P>
|
||||||
|
<H2 CLASS="western"><A NAME="Session Creation and Control">Session Creation and Control</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">Once an API instance
|
<P CLASS="western" STYLE="font-style: normal">Once an API instance
|
||||||
has been successfully created, the application may then create NORM
|
has been successfully created, the application may then create NORM
|
||||||
transport session instances as needed. The application can
|
transport session instances as needed. The application can
|
||||||
|
|
@ -310,7 +313,7 @@ limit the number of active senders monitored and/or provide the
|
||||||
application with finer control over receive buffer allocation,
|
application with finer control over receive buffer allocation,
|
||||||
perhaps on a per sender basis</I>).
|
perhaps on a per sender basis</I>).
|
||||||
</P>
|
</P>
|
||||||
<H2 CLASS="western">NORM Data Transport</H2>
|
<H2 CLASS="western"><A NAME="Data Transport">Data Transport</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM protocol
|
<P CLASS="western" STYLE="font-style: normal">The NORM protocol
|
||||||
supports transport of three basic types of data content. These
|
supports transport of three basic types of data content. These
|
||||||
include the types <FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT>
|
include the types <FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT>
|
||||||
|
|
@ -333,7 +336,7 @@ application-defined message-oriented transport where receivers can
|
||||||
recover message boundaries without any “handshake” with the
|
recover message boundaries without any “handshake” with the
|
||||||
sender. Stream content is buffered by the NORM implementation for
|
sender. Stream content is buffered by the NORM implementation for
|
||||||
transmission/retransmission and as it is received.</P>
|
transmission/retransmission and as it is received.</P>
|
||||||
<H3 CLASS="western">NORM Data Transmission</H3>
|
<H3 CLASS="western"><A NAME="Data Transmission">Data Transmission</A></H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The behavior of data
|
<P CLASS="western" STYLE="font-style: normal">The behavior of data
|
||||||
transport operation is largely placed in the control of the NORM
|
transport operation is largely placed in the control of the NORM
|
||||||
sender(s). NORM senders controls their data transmission rate,
|
sender(s). NORM senders controls their data transmission rate,
|
||||||
|
|
@ -375,7 +378,59 @@ node list") and set "watermark" points for which
|
||||||
positive acknowledgement is collected. This process can provide the
|
positive acknowledgement is collected. This process can provide the
|
||||||
application with explicit flow control for an application-determined
|
application with explicit flow control for an application-determined
|
||||||
critical set of receivers in the group.</P>
|
critical set of receivers in the group.</P>
|
||||||
<H3 CLASS="western">NORM Data Reception</H3>
|
<P CLASS="western" STYLE="font-style: normal">For a NORM application
|
||||||
|
to perform data transmission, it must first create a session using
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT> and make a call to
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT> before sending actual
|
||||||
|
user data. The functions <FONT FACE="Courier">NormEnqueueFile()</FONT>,
|
||||||
|
<FONT FACE="Courier">NormEnqueueData()</FONT>, and <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT>
|
||||||
|
are available for the application to pass data to the NORM protocol
|
||||||
|
engine for transmission. Note that to use <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT>,
|
||||||
|
a "sender stream" must first be created using
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT>.
|
||||||
|
</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The calls to enqueue
|
||||||
|
transport objects or write to a stream may be called at any time, but
|
||||||
|
the <FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT> and
|
||||||
|
<FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT> notification
|
||||||
|
events (see <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>) provide
|
||||||
|
useful cues for when these functions may be successfully called.
|
||||||
|
Typically, an application might catch both <FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT>
|
||||||
|
and <FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT> event
|
||||||
|
types as cues for enqueuing additional transport objects or writing
|
||||||
|
to a stream. However, an application may choose to cue off of
|
||||||
|
<FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT> only if it
|
||||||
|
wishes to provide the "freshest" data to NORM for
|
||||||
|
transmission. The advantage of additionally using
|
||||||
|
<FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT> is that if
|
||||||
|
the application uses this cue to fill up NORM transport object or
|
||||||
|
stream buffers, it can keep the NORM stream busy sending data and
|
||||||
|
realize the highest possible transmission rate when attempting very
|
||||||
|
high speed communication (Otherwise, the NORM protocol engine may
|
||||||
|
experience some "dead air time" waiting for the application
|
||||||
|
thread to respond to a <FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT>
|
||||||
|
event). Note the sender application can control buffer depths as
|
||||||
|
needed with the <A HREF="#NormSetTransmitCacheBounds()">NormSetTransmitCacheBounds()</A> and <A HREF="#NormStreamOpen()">NormStreamOpen()</A>
|
||||||
|
calls.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">Another cue that can be
|
||||||
|
leveraged by the sender application to determine when it is
|
||||||
|
appropriate to enqueue (or write) additional data for transmission is
|
||||||
|
the <FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT>
|
||||||
|
event. This event is posted when the flushing or explicit positive
|
||||||
|
acknowledgment collection process has completed for a "watermark"
|
||||||
|
point in transmission that was set by the sender (see
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> and
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT>). A list of
|
||||||
|
<FONT FACE="Courier">NormNodeIds</FONT> can be supplied from which
|
||||||
|
explicit acknowledgement is expected and/or the <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>
|
||||||
|
NORM_NODE_NONE can be set (using <FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT>)
|
||||||
|
for completion of a NACK-based version of the watermark flushing
|
||||||
|
procedure. This flushing process can be used as a flow control
|
||||||
|
mechanism for NORM applications. Note this is distinct from NORM's
|
||||||
|
congestion control mechanism that, while it provides network-friendly
|
||||||
|
transmission rate control, does guarantee flow control to receiving
|
||||||
|
nodes.</P>
|
||||||
|
<H3 CLASS="western"><A NAME="Data Reception">Data Reception</A></H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">NORM receiver
|
<P CLASS="western" STYLE="font-style: normal">NORM receiver
|
||||||
applications learn of active senders and their corresponding pending
|
applications learn of active senders and their corresponding pending
|
||||||
and completed data transfers, etc via the API event dispatching
|
and completed data transfers, etc via the API event dispatching
|
||||||
|
|
@ -384,8 +439,12 @@ repair of transmitted content from the originating sender as needed
|
||||||
to achieve reliable transfer. Some API functions are available to
|
to achieve reliable transfer. Some API functions are available to
|
||||||
provide some additional control over the NACKing behavior, such as
|
provide some additional control over the NACKing behavior, such as
|
||||||
initially NACKing for NORM_INFO content only or even to the extent of
|
initially NACKing for NORM_INFO content only or even to the extent of
|
||||||
disabling receiver feedback (silent receiver operation) entirely.</P>
|
disabling receiver feedback (silent receiver or emission-controlled
|
||||||
<H2 CLASS="western">API Event Notification</H2>
|
(EMCON) operation) entirely. Otherwise, the parameters and operation
|
||||||
|
of reliable data transmission are left to sender applications and
|
||||||
|
receivers learn of sender parameters in NORM protocol message headers
|
||||||
|
and are instructed by NORM_CMD messages from the sender(s).</P>
|
||||||
|
<H2 CLASS="western"><A NAME="API Event Notification">API Event Notification</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">An asynchronous event
|
<P CLASS="western" STYLE="font-style: normal">An asynchronous event
|
||||||
dispatching mechanism is provided to notify the application of
|
dispatching mechanism is provided to notify the application of
|
||||||
significant NORM protocol events. The centerpiece of this is the
|
significant NORM protocol events. The centerpiece of this is the
|
||||||
|
|
@ -402,7 +461,7 @@ be signaled when a <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FON
|
||||||
available. For Win32 platforms, dispatching of a user-defined
|
available. For Win32 platforms, dispatching of a user-defined
|
||||||
Windows message for NORM event notification is also planned for a
|
Windows message for NORM event notification is also planned for a
|
||||||
future update to the API.</P>
|
future update to the API.</P>
|
||||||
<H1 CLASS="western">Build Notes</H1>
|
<H1 CLASS="western"><A NAME="Build Notes">Build Notes</A></H1>
|
||||||
<P CLASS="western" STYLE="font-style: normal">To build applications
|
<P CLASS="western" STYLE="font-style: normal">To build applications
|
||||||
that use the NORM library, a path to the "normApi.h" header
|
that use the NORM library, a path to the "normApi.h" header
|
||||||
file must be provided and the linker step needs to reference the NORM
|
file must be provided and the linker step needs to reference the NORM
|
||||||
|
|
@ -410,22 +469,23 @@ library file ("libnorm.a" for Unix platforms and "Norm.lib"
|
||||||
for Win32 platforms). NORM also depends upon the NRL Protean
|
for Win32 platforms). NORM also depends upon the NRL Protean
|
||||||
Protocol Prototyping toolkit "Protokit" library (a.k.a
|
Protocol Prototyping toolkit "Protokit" library (a.k.a
|
||||||
"Protolib") (static library files "libProtokit.a"
|
"Protolib") (static library files "libProtokit.a"
|
||||||
for Unix and "Protokit.lib" for Win32). Depending upon the
|
for Unix and "Protokit.lib" for Win32). Shared or
|
||||||
platform, some additional library dependencies may be required to
|
dynamically-linked versions of these libraries may also be built from
|
||||||
support the needs of NORM and/or Protokit. These are described
|
the NORM source code or provided. Depending upon the platform, some
|
||||||
below.</P>
|
additional library dependencies may be required to support the needs
|
||||||
<H2 CLASS="western">Unix Platforms</H2>
|
of NORM and/or Protokit. These are described below.</P>
|
||||||
|
<H2 CLASS="western"><A NAME="Unix Platforms">Unix Platforms</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">NORM has been built and
|
<P CLASS="western" STYLE="font-style: normal">NORM has been built and
|
||||||
tested on Linux (various architectures), MacOS (BSD), Solaris, and
|
tested on Linux (various architectures), MacOS (BSD), Solaris, and
|
||||||
IRIX (SGI) platforms. The code should be readily portable to other
|
IRIX (SGI) platforms. The code should be readily portable to other
|
||||||
Unix platforms.</P>
|
Unix platforms.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">To support IPv6
|
<P CLASS="western" STYLE="font-style: normal">To support IPv6
|
||||||
operation, the NORM and the Protokit library must be compiled with
|
operation, the NORM and the <I>Protokit</I> library must be compiled
|
||||||
the "HAVE_IPV6" macro defined. This is default in the NORM
|
with the "HAVE_IPV6" macro defined. This is default in the
|
||||||
and Protokit Makefiles for platforms that support IPv6. It is
|
NORM and <I>Protokit</I> Makefiles for platforms that support IPv6.
|
||||||
important that NORM and Protokit be built with this macro defined the
|
It is important that NORM and <I>Protokit</I> be built with this
|
||||||
same. With NORM, it is recommended that "large file support"
|
macro defined the same. With NORM, it is recommended that "large
|
||||||
options be enabled when possible.</P>
|
file support" options be enabled when possible.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM API uses
|
<P CLASS="western" STYLE="font-style: normal">The NORM API uses
|
||||||
threading so that the NORM protocol engine may run independent of the
|
threading so that the NORM protocol engine may run independent of the
|
||||||
application. Thus the "POSIX Threads" library must be
|
application. Thus the "POSIX Threads" library must be
|
||||||
|
|
@ -444,7 +504,7 @@ the compilation to enable "large file support".
|
||||||
Applications built using NORM should have the same compilation option
|
Applications built using NORM should have the same compilation option
|
||||||
set to operate correctly (The definition of the <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
set to operate correctly (The definition of the <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
||||||
type in "normApi.h" depends upon this compilation flag).</P>
|
type in "normApi.h" depends upon this compilation flag).</P>
|
||||||
<H2 CLASS="western">Win32/WiNCE Platforms</H2>
|
<H2 CLASS="western"><A NAME="Win32/WiNCE Platforms">Win32/WiNCE Platforms</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">NORM has been built
|
<P CLASS="western" STYLE="font-style: normal">NORM has been built
|
||||||
using Microsoft's Visual C++ (6.0 and .NET) and Embedded VC++ 4.2
|
using Microsoft's Visual C++ (6.0 and .NET) and Embedded VC++ 4.2
|
||||||
environments. In addition to proper macro definitions (e.g.,
|
environments. In addition to proper macro definitions (e.g.,
|
||||||
|
|
@ -463,14 +523,24 @@ and these must be included in the project "Link"
|
||||||
attributes.</P>
|
attributes.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">An additional note is
|
<P CLASS="western" STYLE="font-style: normal">An additional note is
|
||||||
that a bug in VC++ 6.0 and earlier compilers (includes embedded VC++
|
that a bug in VC++ 6.0 and earlier compilers (includes embedded VC++
|
||||||
4.x compilers) prevent compilation of Protokit-based code with
|
4.x compilers) prevent compilation of <I>Protokit</I>-based code with
|
||||||
debugging capabilities enabled. However, this has been resolved in
|
debugging capabilities enabled. However, this has been resolved in
|
||||||
VC++ .NET and is hoped to be resolved in the future for the WinCE
|
VC++ .NET and is hoped to be resolved in the future for the WinCE
|
||||||
build tools.</P>
|
build tools.</P>
|
||||||
<H1 CLASS="western">API Reference</H1>
|
<P CLASS="western" STYLE="font-style: normal">Operation on Windows
|
||||||
|
NT4 (and perhaps other older Windows operating systems) requires that
|
||||||
|
the compile time macro <FONT FACE="Courier"><I>WINVER=0x0400</I></FONT>
|
||||||
|
defined. This is because the version of the IP Helper API library
|
||||||
|
(<I>iphlpapi.lib</I>) used y Protolib (and hence NORM) for this
|
||||||
|
system doesn't support some of the functions defined for this
|
||||||
|
library. This may be related to IPv6 support issues so it may be
|
||||||
|
possible that the Protolib build could be tweaked to provide a single
|
||||||
|
binary executable suitable for IPv4 operation only across a large
|
||||||
|
range of Windows platforms.</P>
|
||||||
|
<H1 CLASS="western"><A NAME="API Reference">API Reference</A></H1>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This section provides a
|
<P CLASS="western" STYLE="font-style: normal">This section provides a
|
||||||
reference to the NORM API variable types, constants and functions.</P>
|
reference to the NORM API variable types, constants and functions.</P>
|
||||||
<H2 CLASS="western">API Variable Types and Constants</H2>
|
<H2 CLASS="western"><A NAME="API Variable Types and Constants">API Variable Types and Constants</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM API defines
|
<P CLASS="western" STYLE="font-style: normal">The NORM API defines
|
||||||
and enumerates a number of supporting variable types and values which
|
and enumerates a number of supporting variable types and values which
|
||||||
are used in different function calls. The variable types are
|
are used in different function calls. The variable types are
|
||||||
|
|
@ -648,7 +718,7 @@ these values is given in the description of <FONT FACE="Courier"><A HREF="#Norm
|
||||||
function.</P>
|
function.</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormNackingMode">NormNackingMode</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormNackingMode">NormNackingMode</A></H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormNackingMode">NormNackingMode</A></FONT>
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormNackingMode">NormNackingMode</A></FONT>
|
||||||
consist of the following enumeration:</P>
|
type consists of the following enumeration:</P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||||
<A HREF="#NormNackingMode">NormNackingMode</A><BR>{<BR> NORM_NACK_NONE,<BR> NORM_NACK_INFO_ONLY,<BR> NORM_NACK_NORMAL<BR>};</FONT></FONT></P>
|
<A HREF="#NormNackingMode">NormNackingMode</A><BR>{<BR> NORM_NACK_NONE,<BR> NORM_NACK_INFO_ONLY,<BR> NORM_NACK_NORMAL<BR>};</FONT></FONT></P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||||
|
|
@ -658,14 +728,22 @@ these values is given in the descriptions of the
|
||||||
<FONT FACE="Courier"><A HREF="#NormObjectSetNackingMode()">NormObjectSetNackingMode()</A></FONT> functions.</P>
|
<FONT FACE="Courier"><A HREF="#NormObjectSetNackingMode()">NormObjectSetNackingMode()</A></FONT> functions.</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormRepairBoundary">NormRepairBoundary</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormRepairBoundary">NormRepairBoundary</A></H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT>
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT>
|
||||||
consist of the following enumeration:</P>
|
types consists of the following enumeration:</P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||||
<A HREF="#NormRepairBoundary">NormRepairBoundary</A><BR>{<BR> NORM_BOUNDARY_BLOCK,<BR> NORM_BOUNDARY_OBJECT<BR>};</FONT></FONT></P>
|
<A HREF="#NormRepairBoundary">NormRepairBoundary</A><BR>{<BR> NORM_BOUNDARY_BLOCK,<BR> NORM_BOUNDARY_OBJECT<BR>};</FONT></FONT></P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||||
these values is given in the descriptions of the
|
these values is given in the descriptions of the
|
||||||
<FONT FACE="Courier"><A HREF="#NormSetDefaultRepairBoundary()">NormSetDefaultRepairBoundary()</A> </FONT>and
|
<FONT FACE="Courier"><A HREF="#NormSetDefaultRepairBoundary()">NormSetDefaultRepairBoundary()</A> </FONT>and
|
||||||
<FONT FACE="Courier"><A HREF="#NormNodeSetRepairBoundary()">NormNodeSetRepairBoundary()</A></FONT> functions.</P>
|
<FONT FACE="Courier"><A HREF="#NormNodeSetRepairBoundary()">NormNodeSetRepairBoundary()</A></FONT> functions.</P>
|
||||||
<H2 CLASS="western">API Initialization and Operation</H2>
|
<H3 CLASS="functionheading-western"><A NAME="NormAckingStatus">NormAckingStatus</A></H3>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormAckingStatus">NormAckingStatus</A></FONT>
|
||||||
|
consist of the following enumeration:</P>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||||
|
<A HREF="#NormAckingStatus">NormAckingStatus</A><BR>{<BR> NORM_ACK_INVALID,<BR> NORM_ACK_FAILURE,<BR> NORM_ACK_PENDING,<BR> NORM_ACK_SUCCESS<BR>};</FONT></FONT></P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||||
|
these values is given in the descriptions of the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT> function.</P>
|
||||||
|
<H2 CLASS="western"><A NAME="API Initialization and Operation">API Initialization and Operation</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The first step in using
|
<P CLASS="western" STYLE="font-style: normal">The first step in using
|
||||||
the NORM API is to create an "instance" of the NORM
|
the NORM API is to create an "instance" of the NORM
|
||||||
protocol engine. Note that multiple instances may be created by the
|
protocol engine. Note that multiple instances may be created by the
|
||||||
|
|
@ -804,8 +882,12 @@ function call.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
This event indicates that there is room for additional transmit
|
This event indicates that there is room for additional transmit
|
||||||
objects to be enqueued, or, if the handle of <FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>
|
objects to be enqueued, or, if the handle of <FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>
|
||||||
is given in the event "object" field, the application
|
is given in the corresponding event "object" field, the
|
||||||
may successfully write to the indicated stream object.</P>
|
application may successfully write to the indicated stream object.
|
||||||
|
Note this event is not dispatched until a call to
|
||||||
|
<FONT FACE="Courier">NormEnqueueFile()</FONT>, <FONT FACE="Courier">NormEnqueueData()</FONT>,
|
||||||
|
or <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT> fails because of
|
||||||
|
a filled transmit cache or stream buffer.</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
|
|
@ -817,7 +899,14 @@ function call.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
This event indicates the NORM protocol engine has no new data
|
This event indicates the NORM protocol engine has no new data
|
||||||
pending transmission and the application may enqueue additional
|
pending transmission and the application may enqueue additional
|
||||||
objects for transmission.</P>
|
objects for transmission. If the handle of a sender
|
||||||
|
<FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT> is given in
|
||||||
|
the corresponding event "object" field, this indicates
|
||||||
|
the stream transmit buffer has been emptied and the sender
|
||||||
|
application may write to the stream (Use of <FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT>
|
||||||
|
may be preferred for this purpose since it allows the application
|
||||||
|
to keep the NORM protocol engine busier sending data, resulting in
|
||||||
|
higher throughput when attempting very high transfer rates).</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
|
|
@ -840,6 +929,20 @@ function call.</P>
|
||||||
transmission, even with packet loss rates of 50%.</P>
|
transmission, even with packet loss rates of 50%.</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD WIDTH=269>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
<FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT></P>
|
||||||
|
</TD>
|
||||||
|
<TD WIDTH=293>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
This event indicates that the flushing process initiated by a
|
||||||
|
prior application call to <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT>
|
||||||
|
has completed The posting of this event indicates the appropriate
|
||||||
|
time for the application to make a call <FONT FACE="Courier"><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT>
|
||||||
|
to determine the results of the watermark flushing process.</P>
|
||||||
|
</TD>
|
||||||
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD WIDTH=269>
|
<TD WIDTH=269>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
|
@ -1068,7 +1171,7 @@ descriptor.</P>
|
||||||
returned which is valid until a call to <FONT FACE="Courier"><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT>
|
returned which is valid until a call to <FONT FACE="Courier"><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT>
|
||||||
is made. Upon error, a value of <I><FONT FACE="Courier">NORM_DESCRIPTOR_INVALID</FONT></I>
|
is made. Upon error, a value of <I><FONT FACE="Courier">NORM_DESCRIPTOR_INVALID</FONT></I>
|
||||||
is returned.</P>
|
is returned.</P>
|
||||||
<H2 CLASS="western">Session Creation and Control</H2>
|
<H2 CLASS="western"><A NAME="Session Creation and Control Functions">Session Creation and Control Functions</A></H2>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormCreateSession()">NormCreateSession()</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormCreateSession()">NormCreateSession()</A></H3>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
|
@ -1428,8 +1531,7 @@ created.</P>
|
||||||
<H4 CLASS="western">Return Values</H4>
|
<H4 CLASS="western">Return Values</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||||
return values.</P>
|
return values.</P>
|
||||||
<H2 CLASS="western">NORM<SPAN STYLE="font-style: normal"> </SPAN>Sender
|
<H2 CLASS="western"><A NAME="NORM Sender Functions">NORM Sender Functions</A></H2>
|
||||||
Functions</H2>
|
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormStartSender()">NormStartSender()</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormStartSender()">NormStartSender()</A></H3>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
|
@ -1925,7 +2027,7 @@ return values.</P>
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormSetGrttProbingMode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
NormSetGrttProbingMode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||||
<BR> NormProbingMode probingMode);</FONT></FONT></P>
|
<BR> <A HREF="#NormProbingMode">NormProbingMode</A> probingMode);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||||
sender's mode of probing for round trip timing measurement responses
|
sender's mode of probing for round trip timing measurement responses
|
||||||
|
|
@ -2010,44 +2112,6 @@ values are 1.0 second and 30.0 seconds, respectively.</P>
|
||||||
<H4 CLASS="western">Return Values</H4>
|
<H4 CLASS="western">Return Values</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||||
return values.</P>
|
return values.</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormAddAckingNode()">NormAddAckingNode()</A></H3>
|
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
|
||||||
<normApi.h></FONT></FONT></P>
|
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>bool
|
|
||||||
NormAddAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
|
||||||
<H4 CLASS="western">Description</H4>
|
|
||||||
<P CLASS="western" STYLE="font-style: normal">When this function is
|
|
||||||
called, the specified <FONT FACE="Courier"><U>nodeId</U></FONT> is
|
|
||||||
added to the list of <I>NormNodes</I> used when NORM sender operation
|
|
||||||
performs positive acknowledgement (ACK) collection for the specified
|
|
||||||
<FONT FACE="Courier"><U>session</U></FONT>. The optional NORM
|
|
||||||
positive acknowledgement collection occurs when a specified
|
|
||||||
transmission point (see <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A>)</FONT>
|
|
||||||
is reached or for specialized protocol actions such as
|
|
||||||
positively-acknowledged application-defined commands (<I>TBD</I>).</P>
|
|
||||||
<H4 CLASS="western">Return Values</H4>
|
|
||||||
<P CLASS="western" STYLE="font-style: normal">The function returns
|
|
||||||
<FONT FACE="Courier"><I>true</I></FONT> upon success and <FONT FACE="Courier"><I>false</I></FONT>
|
|
||||||
upon failure. The only failure condition is that insufficient memory
|
|
||||||
resources were available. If a specific <FONT FACE="Courier"><U>nodeId</U></FONT>
|
|
||||||
is added more than once, this has no effect.</P>
|
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormRemoveAckingNode()">NormRemoveAckingNode()</A></H3>
|
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
|
||||||
<normApi.h></FONT></FONT></P>
|
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
|
||||||
NormRemoveAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
|
||||||
<H4 CLASS="western">Description</H4>
|
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function deletes
|
|
||||||
the specified <FONT FACE="Courier"><U>nodeId</U></FONT> from the list
|
|
||||||
of <I>NormNodes</I> used when NORM sender operation performs positive
|
|
||||||
acknowledgement (ACK) collection for the specified <FONT FACE="Courier"><U>session</U></FONT>.
|
|
||||||
|
|
||||||
</P>
|
|
||||||
<H4 CLASS="western">Return Values</H4>
|
|
||||||
<P CLASS="western" STYLE="font-style: normal">The function has no
|
|
||||||
return values.</P>
|
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormFileEnqueue()">NormFileEnqueue()</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormFileEnqueue()">NormFileEnqueue()</A></H3>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
|
@ -2330,10 +2394,21 @@ reliability does not provide explicit flow control, there is some
|
||||||
degree of implicit flow control in limiting writing new data to the
|
degree of implicit flow control in limiting writing new data to the
|
||||||
stream against pending repairs.
|
stream against pending repairs.
|
||||||
</P>
|
</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT>
|
||||||
|
NORM_TX_QUEUE_VACANCY is posted with its <I><A HREF="#NormEvent">NormEvent</A>::object</I>
|
||||||
|
field set to a valid sender stream <FONT FACE="Courier"><A HREF="#NormObjectHandle">NormObjectHandle</A></FONT>
|
||||||
|
to indicate when the stream is ready for writing via this function.
|
||||||
|
Note that, after this event type is posted, the application <I>must</I>
|
||||||
|
make a call to <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT> with a
|
||||||
|
non-zero <FONT FACE="Courier"><U>numBytes</U></FONT> value before
|
||||||
|
addition NORM_TX_QUEUE_VACANCY events are posted for the given
|
||||||
|
<FONT FACE="Courier"><U>streamHandle</U></FONT>.</P>
|
||||||
<H4 CLASS="western">Return Values</H4>
|
<H4 CLASS="western">Return Values</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function returns
|
<P CLASS="western" STYLE="font-style: normal">This function returns
|
||||||
the number of bytes of data successfully enqueued for NORM stream
|
the number of bytes of data successfully enqueued for NORM stream
|
||||||
transmission.</P>
|
transmission. If the underlying send stream buffer is full, this
|
||||||
|
function may return zero.
|
||||||
|
</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormStreamFlush()">NormStreamFlush()</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormStreamFlush()">NormStreamFlush()</A></H3>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
|
@ -2548,53 +2623,218 @@ NormSetWatermark(<A HREF="#NormSessionHandle">NormSessionHandle</A> session
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function specifies
|
<P CLASS="western" STYLE="font-style: normal">This function specifies
|
||||||
a "watermark" transmission point at which NORM sender
|
a "watermark" transmission point at which NORM sender
|
||||||
protocol operation should perform positive acknowledgment collection
|
protocol operation should perform a flushing process and/or positive
|
||||||
for a given <FONT FACE="Courier"><U>session</U></FONT>. For
|
acknowledgment collection for a given <FONT FACE="Courier"><U>session</U></FONT>.
|
||||||
<FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT> and
|
For <FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT> and
|
||||||
<FONT FACE="Courier"><I>NORM_OBJECT_DATA</I></FONT> transmissions,
|
<FONT FACE="Courier"><I>NORM_OBJECT_DATA</I></FONT> transmissions,
|
||||||
the positive acknowledgement collection will begin when the specified
|
the positive acknowledgement collection will begin when the specified
|
||||||
<FONT FACE="Courier"><U>object</U></FONT> has been completely
|
<FONT FACE="Courier"><U>object</U></FONT> has been completely
|
||||||
transmitted. The object parameter must be a valid handle to a
|
transmitted. The object parameter must be a valid handle to a
|
||||||
previously-created sender object (see <FONT SIZE=2><FONT FACE="Courier">NormEnqueueFile(),</FONT></FONT>
|
previously-created sender object (see <FONT FACE="Courier">NormEnqueueFile()</FONT><FONT SIZE=2><FONT FACE="Courier">,</FONT></FONT>
|
||||||
<FONT SIZE=2><FONT FACE="Courier">NormEnqueueData()</FONT></FONT>, or
|
<FONT FACE="Courier">NormEnqueueData()</FONT>, or <FONT FACE="Courier"><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT>).
|
||||||
<FONT SIZE=2><FONT FACE="Courier"><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT></FONT>).
|
For <FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>
|
||||||
For <FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>
|
|
||||||
transmission, the positive acknowledgment collection begins
|
transmission, the positive acknowledgment collection begins
|
||||||
immediately, using the current position (last data written) of the
|
immediately, using the current position (offset of most recent data
|
||||||
sender stream as a reference.
|
written) of the sender stream as a reference.
|
||||||
</P>
|
</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">As the acknowledgment
|
<P CLASS="western" STYLE="font-style: normal">The functions
|
||||||
collection proceeds, <FONT FACE="Courier"><I>NORM_ACK_FAILED</I></FONT>
|
<FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT> and
|
||||||
events will be posted for individual receiver <I>NormNodes</I> which
|
<FONT FACE="Courier"><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT> are used to manage
|
||||||
fail to acknowledge the request. The <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A>::node</FONT>
|
the list of <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT> values
|
||||||
field contains a <FONT FACE="Courier"><A HREF="#NormNodeHandle">NormNodeHandle</A></FONT> for the
|
corresponding to NORM receivers that are expected to explicitly
|
||||||
failed node and <FONT FACE="Courier"><A HREF="#NormNodeGetId()">NormNodeGetId()</A></FONT> can be
|
acknowledge the watermark flushing messages transmitted by the
|
||||||
used to retrieve the failing node's <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>.
|
sender. Note that the <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>
|
||||||
When the sender acknowledgment collection process has completed, the
|
<FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> may be included in
|
||||||
<FONT FACE="Courier"><I>NORM_ACK_COMPLETE</I></FONT> event is posted
|
the list. Inclusion of <FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT>
|
||||||
and the application may assume that the remaining nodes (those for
|
forces the watermark flushing process to proceed through a full
|
||||||
which there was no <FONT FACE="Courier"><I>NORM_ACK_FAILED</I></FONT>
|
<FONT FACE="Courier"><I>NORM_ROBUST_FACTOR</I></FONT> number of
|
||||||
event) successfully acknowledged the request.</P>
|
rounds before completing, prompting any receivers that have not
|
||||||
<P CLASS="western" STYLE="font-style: normal">If a subsequent call is
|
completed reliable reception to the given watermark point to NACK for
|
||||||
made to <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> before the
|
any repair needs. If NACKs occur, the flushing process is reset and
|
||||||
prior acknowledgement request has completed, the pending
|
repeated until completing with no NACKs for data through the given
|
||||||
acknowledgment request is canceled and new one may begin.</P>
|
watermark transmission point are received. Thus, even without
|
||||||
<P CLASS="western" STYLE="font-style: normal">Note that the sender
|
explicit positive acknowledgment, the sender can use this process (by
|
||||||
may still enqueue <I>NormObjects</I> for transmission (or write to
|
adding <FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> to the
|
||||||
the existing stream) and the positive acknowledgement collection will
|
<FONT FACE="Courier"><U>session</U></FONT>'s list of acking nodes)
|
||||||
be multiplexed with the ongoing data transmission. However, the
|
for a high level of assurance that the receiver set is "happy"
|
||||||
sender application may wish to defer sending more data until a
|
(completed reliable data reception) through the given <FONT FACE="Courier"><U>object</U></FONT>
|
||||||
<FONT FACE="Courier"><I>NORM_ACK_COMPLETE</I></FONT> event is
|
(or stream transmission point).
|
||||||
received for the <FONT FACE="Courier"><U>session</U></FONT>. This
|
</P>
|
||||||
provides a form of explicit sender->receiver(s) flow control (with
|
<P CLASS="western" STYLE="font-style: normal">The event
|
||||||
respect to the current list of "acking" receivers) which
|
<FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT> is
|
||||||
does not exist in NORM's default NACK-only operation.</P>
|
posted for the given <FONT FACE="Courier"><U>session</U></FONT> when
|
||||||
|
the flushing process or positive acknowledgment collection has
|
||||||
|
completed. The process completes as soon as all listed receivers
|
||||||
|
have responded unless <FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT>
|
||||||
|
is included in the acking list. The sender application may use the
|
||||||
|
function <FONT FACE="Courier"><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT> to
|
||||||
|
determine the degree of success of the flushing process in general or
|
||||||
|
for individual <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT> values.
|
||||||
|
</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The flushing is
|
||||||
|
conducted concurrently with ongoing data transmission and does not
|
||||||
|
impede the progress of reliable data transfer. Thus the sender may
|
||||||
|
still enqueue <I>NormObjects</I> for transmission (or write to the
|
||||||
|
existing stream) and the positive acknowledgement collection and
|
||||||
|
flushing procedure will be multiplexed with the ongoing data
|
||||||
|
transmission. However, the sender application may wish to defer from
|
||||||
|
or limit itself in sending more data until a
|
||||||
|
<FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT> event
|
||||||
|
is received for the given <FONT FACE="Courier"><U>session</U></FONT>.
|
||||||
|
This provides a form of sender->receiver(s) flow control which
|
||||||
|
does not exist in NORM's default protocol operation. If a subsequent
|
||||||
|
call is made to <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> before
|
||||||
|
the current acknowledgement request has completed, the pending
|
||||||
|
acknowledgment request is canceled and the new one begins.</P>
|
||||||
<H4 CLASS="western">Return Values</H4>
|
<H4 CLASS="western">Return Values</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The function returns
|
<P CLASS="western" STYLE="font-style: normal">The function returns
|
||||||
<FONT FACE="Courier"><I>true</I></FONT> upon successful establishment
|
<FONT FACE="Courier"><I>true</I></FONT> upon successful establishment
|
||||||
of the watermark point. The function may return <FONT FACE="Courier"><I>false</I></FONT>
|
of the watermark point. The function may return <FONT FACE="Courier"><I>false</I></FONT>
|
||||||
upon failure (<I>why would it fail? – TBD</I>).</P>
|
upon failure (<I>why would it fail? – TBD</I>).</P>
|
||||||
<H2 CLASS="western">NORM Receiver Functions</H2>
|
<H3 CLASS="functionheading-western"><A NAME="NormAddAckingNode()">NormAddAckingNode()</A></H3>
|
||||||
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
<normApi.h></FONT></FONT></P>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>bool
|
||||||
|
NormAddAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
||||||
|
<H4 CLASS="western">Description</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">When this function is
|
||||||
|
called, the specified <FONT FACE="Courier"><U>nodeId</U></FONT> is
|
||||||
|
added to the list of <I>NormNodes</I> used when NORM sender operation
|
||||||
|
performs positive acknowledgement (ACK) collection for the specified
|
||||||
|
<FONT FACE="Courier"><U>session</U></FONT>. The optional NORM
|
||||||
|
positive acknowledgement collection occurs when a specified
|
||||||
|
transmission point (see <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A>)</FONT>
|
||||||
|
is reached or for specialized protocol actions such as
|
||||||
|
positively-acknowledged application-defined commands. Additionally a
|
||||||
|
value of <FONT FACE="Courier"><U>nodeId</U></FONT> equal to
|
||||||
|
<FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> may be set to force
|
||||||
|
the watermark flushing process through a full <FONT FACE="Courier"><I>NORM_ROBUST_FACTOR</I></FONT>
|
||||||
|
number of rounds regardless of actual acking nodes. Otherwise the
|
||||||
|
flushing process is terminated when all of the nodes in the acking
|
||||||
|
node list have responded.</P>
|
||||||
|
<H4 CLASS="western">Return Values</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The function returns
|
||||||
|
<FONT FACE="Courier"><I>true</I></FONT> upon success and <FONT FACE="Courier"><I>false</I></FONT>
|
||||||
|
upon failure. The only failure condition is that insufficient memory
|
||||||
|
resources were available. If a specific <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
is added more than once, this has no effect.</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormRemoveAckingNode()">NormRemoveAckingNode()</A></H3>
|
||||||
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
<normApi.h></FONT></FONT></P>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
|
NormRemoveAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
||||||
|
<H4 CLASS="western">Description</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">This function deletes
|
||||||
|
the specified <FONT FACE="Courier"><U>nodeId</U></FONT> from the list
|
||||||
|
of <I>NormNodes</I> used when NORM sender operation performs positive
|
||||||
|
acknowledgement (ACK) collection for the specified <FONT FACE="Courier"><U>session</U></FONT>.
|
||||||
|
Note that if the <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
<FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> has been added to
|
||||||
|
the list, it too must be removed to change the watermark flushing
|
||||||
|
behavior if desired.</P>
|
||||||
|
<H4 CLASS="western">Return Values</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The function has no
|
||||||
|
return values.</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormGetAckingStatus()">NormGetAckingStatus()</A></H3>
|
||||||
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
<normApi.h></FONT></FONT></P>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2><A HREF="#NormAckingStatus">NormAckingStatus</A>
|
||||||
|
NormGetAckingStatus(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId
|
||||||
|
=
|
||||||
|
NORM_NODE_ANY);</FONT></FONT></P>
|
||||||
|
<H4 CLASS="western">Description</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">This function queries
|
||||||
|
the status of the watermark flushing process and/or positive
|
||||||
|
acknowledgment collection initiated by a prior call to
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> for the given <FONT FACE="Courier"><U>session</U></FONT>.
|
||||||
|
In general, it is expected that applications will invoke this
|
||||||
|
function <I>after</I> the corresponding <FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT>
|
||||||
|
event has been posted. Setting the default parameter value <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
= <FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT> returns a "status"
|
||||||
|
indication for the overall process. Also, individual <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
values may be queried using the <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>
|
||||||
|
values of receivers that were included in previous calls to
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT> to populate the
|
||||||
|
sender <FONT FACE="Courier"><U>session</U></FONT>'s acking node list.
|
||||||
|
|
||||||
|
</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">If the
|
||||||
|
flushing/acknowledgment process is being used for application flow
|
||||||
|
control, the sender application may wish to reset the watermark and
|
||||||
|
flushing process (using <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT>)
|
||||||
|
if the response indicates that some nodes have failed to respond.
|
||||||
|
However, note that the flushing/acknowledgment process itself does
|
||||||
|
elicit NACKs from receivers as needed and is interrupted and reset by
|
||||||
|
any repair response that occurs. Thus, even by the time the flushing
|
||||||
|
process has completed (and <FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT>
|
||||||
|
is posted) once, this is an indication that the NORM protocol has
|
||||||
|
made a valiant attempt to deliver the content. Resetting the
|
||||||
|
watermark process <I>can</I> increase robustness, but it may be in
|
||||||
|
vain to repeat this process multiple times when likely network
|
||||||
|
connectivity has been lost or expected receivers have failed (dropped
|
||||||
|
out, shut down, etc).</P>
|
||||||
|
<H4 CLASS="western">Return Values</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-after: avoid">
|
||||||
|
Possible return values include:</P>
|
||||||
|
<TABLE WIDTH=592 BORDER=1 BORDERCOLOR="#000000" CELLPADDING=8 CELLSPACING=0>
|
||||||
|
<COL WIDTH=200>
|
||||||
|
<COL WIDTH=358>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD WIDTH=200>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||||
|
NORM_ACK_INVALID</P>
|
||||||
|
</TD>
|
||||||
|
<TD WIDTH=358>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||||
|
The given session is invalid or the given <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
is not in the session's acking list.</P>
|
||||||
|
</TD>
|
||||||
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD WIDTH=200>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||||
|
NORM_ACK_FAILURE</P>
|
||||||
|
</TD>
|
||||||
|
<TD WIDTH=358>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||||
|
The positive acknowledgement collection process did not receive
|
||||||
|
acknowledgment from every listed receiver (<FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
= <FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT>) or the
|
||||||
|
identified <FONT FACE="Courier"><U>nodeId</U></FONT> did not
|
||||||
|
respond.</P>
|
||||||
|
</TD>
|
||||||
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD WIDTH=200>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||||
|
NORM_ACK_PENDING</P>
|
||||||
|
</TD>
|
||||||
|
<TD WIDTH=358>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||||
|
The flushing process at large has not yet completed (<FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
= <FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT>) or the given
|
||||||
|
individual <FONT FACE="Courier"><U>nodeId</U></FONT> is still
|
||||||
|
being queried for response.</P>
|
||||||
|
</TD>
|
||||||
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD WIDTH=200>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
NORM_ACK_SUCCESS</P>
|
||||||
|
</TD>
|
||||||
|
<TD WIDTH=358>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
All receivers (<FONT FACE="Courier"><U>nodeId</U></FONT> =
|
||||||
|
<FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT>) responded with
|
||||||
|
positive acknowledgement or the given specific <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||||
|
did acknowledge.</P>
|
||||||
|
</TD>
|
||||||
|
</TR>
|
||||||
|
</TABLE>
|
||||||
|
<H2 CLASS="western"><A NAME="NORM Receiver Functions">NORM Receiver Functions</A></H2>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormStartReceiver()">NormStartReceiver()</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormStartReceiver()">NormStartReceiver()</A></H3>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
|
@ -3047,7 +3287,7 @@ associate some application context with stream position.</P>
|
||||||
the current read offset in bytes. The return value is undefined for
|
the current read offset in bytes. The return value is undefined for
|
||||||
sender streams. There is no error result.
|
sender streams. There is no error result.
|
||||||
</P>
|
</P>
|
||||||
<H2 CLASS="western">NORM Object Functions</H2>
|
<H2 CLASS="western"><A NAME="NORM Object Functions">NORM Object Functions</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The functions described
|
<P CLASS="western" STYLE="font-style: normal">The functions described
|
||||||
in this section may be used for sender or receiver purposes to manage
|
in this section may be used for sender or receiver purposes to manage
|
||||||
transmission and reception of NORM transport objects. In most cases,
|
transmission and reception of NORM transport objects. In most cases,
|
||||||
|
|
@ -3442,7 +3682,7 @@ valid for the same period that the <FONT FACE="Courier"><U>objectHandle</U></FON
|
||||||
is valid. The returned <FONT FACE="Courier"><A HREF="#NormNodeHandle">NormNodeHandle</A></FONT>
|
is valid. The returned <FONT FACE="Courier"><A HREF="#NormNodeHandle">NormNodeHandle</A></FONT>
|
||||||
may optionally be retained for further use by the application using
|
may optionally be retained for further use by the application using
|
||||||
the <FONT FACE="Courier"><A HREF="#NormNodeRetain()">NormNodeRetain()</A></FONT> function call. The
|
the <FONT FACE="Courier"><A HREF="#NormNodeRetain()">NormNodeRetain()</A></FONT> function call. The
|
||||||
returned value can be used in the NORM Node Functions described later
|
returned value can be used in the <A HREF="#NORM Node Functions">NORM Node Functions</A> described later
|
||||||
in this document.</P>
|
in this document.</P>
|
||||||
<H4 CLASS="western">Return Values</H4>
|
<H4 CLASS="western">Return Values</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function returns
|
<P CLASS="western" STYLE="font-style: normal">This function returns
|
||||||
|
|
@ -3451,7 +3691,7 @@ remote sender of the transport object associated with the given
|
||||||
<FONT FACE="Courier"><U>objectHandle</U></FONT> parameter. A value
|
<FONT FACE="Courier"><U>objectHandle</U></FONT> parameter. A value
|
||||||
of NORM_NODE_INVALID is returned if the specified <FONT FACE="Courier"><U>objectHandle</U></FONT>
|
of NORM_NODE_INVALID is returned if the specified <FONT FACE="Courier"><U>objectHandle</U></FONT>
|
||||||
references a locally originated, sender object.</P>
|
references a locally originated, sender object.</P>
|
||||||
<H2 CLASS="western">NORM Node Functions</H2>
|
<H2 CLASS="western"><A NAME="NORM Node Functions">NORM Node Functions</A></H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The functions described
|
<P CLASS="western" STYLE="font-style: normal">The functions described
|
||||||
in this section may be used for NORM sender or receiver (most
|
in this section may be used for NORM sender or receiver (most
|
||||||
typically receiver) purposes to retrieve additional information about
|
typically receiver) purposes to retrieve additional information about
|
||||||
|
|
|
||||||
Binary file not shown.
18
VERSION.TXT
18
VERSION.TXT
|
|
@ -1,5 +1,23 @@
|
||||||
NORM Version History
|
NORM Version History
|
||||||
|
|
||||||
|
Version 1.3b6
|
||||||
|
=============
|
||||||
|
- Fixed some oversite bugs that crept in with changes in 1.3b5
|
||||||
|
(Fixed code related to NormNode/NormObject retain and release)
|
||||||
|
- Changed NORM_TX_QUEUE_VACANCY posting behavior to be less chatty.
|
||||||
|
NORM_TX_QUEUE_VACANCY now posted _only_ after a call to
|
||||||
|
NormStreamWrite() fails to fulfill a full write request
|
||||||
|
(i.e. returns less than the "numBytes" requested to be written)
|
||||||
|
This helps prevent build up of these notifications in multi-
|
||||||
|
threaded applications that write to a stream in a different
|
||||||
|
thread than is fetching events via NormGetNextEvent().
|
||||||
|
- Added NORM_TX_WATERMARK_COMPLETED notification and NormGetAckingStatus()
|
||||||
|
function to provide API support for optional positive acknowledgment
|
||||||
|
(ACK) collection in NORM implementation. Note that use of
|
||||||
|
NormAddAckingNode(session, NORM_NODE_NONE) enables a NACK-based
|
||||||
|
watermark flushing concurrent with ongoing data transmission that
|
||||||
|
can be used as a scalable application-level flow control mechanism.
|
||||||
|
|
||||||
Version 1.3b5
|
Version 1.3b5
|
||||||
=============
|
=============
|
||||||
- Changed ProtoSocket::GetInterfaceAddress() and related methods on Win32
|
- Changed ProtoSocket::GetInterfaceAddress() and related methods on Win32
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ class NormInstance : public NormController
|
||||||
|
|
||||||
void PurgeObjectNotifications(NormObjectHandle objectHandle);
|
void PurgeObjectNotifications(NormObjectHandle objectHandle);
|
||||||
|
|
||||||
|
unsigned long CountCompletedObjects(NormSession* theSession);
|
||||||
|
|
||||||
ProtoDispatcher::Descriptor GetDescriptor() const
|
ProtoDispatcher::Descriptor GetDescriptor() const
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
@ -57,6 +59,7 @@ class NormInstance : public NormController
|
||||||
|
|
||||||
static NormInstance* GetInstanceFromSession(NormSessionHandle sessionHandle)
|
static NormInstance* GetInstanceFromSession(NormSessionHandle sessionHandle)
|
||||||
{
|
{
|
||||||
|
if (NORM_SESSION_INVALID == sessionHandle) return ((NormInstance*)NULL);
|
||||||
NormSession* session = (NormSession*)sessionHandle;
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
NormInstance* theInstance = static_cast<NormInstance*>(session->GetSessionMgr().GetController());
|
NormInstance* theInstance = static_cast<NormInstance*>(session->GetSessionMgr().GetController());
|
||||||
return theInstance;
|
return theInstance;
|
||||||
|
|
@ -64,11 +67,13 @@ class NormInstance : public NormController
|
||||||
}
|
}
|
||||||
static NormInstance* GetInstanceFromNode(NormNodeHandle nodeHandle)
|
static NormInstance* GetInstanceFromNode(NormNodeHandle nodeHandle)
|
||||||
{
|
{
|
||||||
|
if (NORM_NODE_INVALID == nodeHandle) return ((NormInstance*)NULL);
|
||||||
NormSession& session = ((NormNode*)nodeHandle)->GetSession();
|
NormSession& session = ((NormNode*)nodeHandle)->GetSession();
|
||||||
return static_cast<NormInstance*>(session.GetSessionMgr().GetController());
|
return static_cast<NormInstance*>(session.GetSessionMgr().GetController());
|
||||||
}
|
}
|
||||||
static NormInstance* GetInstanceFromObject(NormObjectHandle objectHandle)
|
static NormInstance* GetInstanceFromObject(NormObjectHandle objectHandle)
|
||||||
{
|
{
|
||||||
|
if (NORM_OBJECT_INVALID == objectHandle) return ((NormInstance*)NULL);
|
||||||
NormSession& session = ((NormObject*)objectHandle)->GetSession();;
|
NormSession& session = ((NormObject*)objectHandle)->GetSession();;
|
||||||
return static_cast<NormInstance*>(session.GetSessionMgr().GetController());
|
return static_cast<NormInstance*>(session.GetSessionMgr().GetController());
|
||||||
}
|
}
|
||||||
|
|
@ -610,6 +615,21 @@ void NormInstance::Shutdown()
|
||||||
notify_pool.Destroy();
|
notify_pool.Destroy();
|
||||||
} // end NormInstance::Shutdown()
|
} // end NormInstance::Shutdown()
|
||||||
|
|
||||||
|
unsigned long NormInstance::CountCompletedObjects(NormSession* session)
|
||||||
|
{
|
||||||
|
unsigned long result = 0UL;
|
||||||
|
Notification* n = notify_queue.GetHead();
|
||||||
|
while (NULL != n)
|
||||||
|
{
|
||||||
|
if ((session == n->event.session) &&
|
||||||
|
(NORM_RX_OBJECT_COMPLETED == n->event.type))
|
||||||
|
{
|
||||||
|
result ++;
|
||||||
|
}
|
||||||
|
n = n->GetNext();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} // end NormInstance::CountCompletedObjects()
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// NORM API FUNCTION IMPLEMENTATIONS
|
// NORM API FUNCTION IMPLEMENTATIONS
|
||||||
|
|
@ -1024,35 +1044,6 @@ void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
||||||
}
|
}
|
||||||
} // end NormSetGrttProbingInterval()
|
} // end NormSetGrttProbingInterval()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
|
||||||
NormNodeId nodeId)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
|
||||||
if (instance && instance->dispatcher.SuspendThread())
|
|
||||||
{
|
|
||||||
NormSession* session = (NormSession*)sessionHandle;
|
|
||||||
if (session)
|
|
||||||
result = session->ServerAddAckingNode(nodeId);
|
|
||||||
instance->dispatcher.ResumeThread();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} // end NormAddAckingNode()
|
|
||||||
|
|
||||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
|
||||||
NormNodeId nodeId)
|
|
||||||
{
|
|
||||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
|
||||||
if (instance && instance->dispatcher.SuspendThread())
|
|
||||||
{
|
|
||||||
NormSession* session = (NormSession*)sessionHandle;
|
|
||||||
if (session) session->ServerRemoveAckingNode(nodeId);
|
|
||||||
instance->dispatcher.ResumeThread();
|
|
||||||
}
|
|
||||||
} // end NormRemoveAckingNode()
|
|
||||||
|
|
||||||
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||||
const char* fileName,
|
const char* fileName,
|
||||||
const char* infoPtr,
|
const char* infoPtr,
|
||||||
|
|
@ -1249,6 +1240,50 @@ bool NormSetWatermark(NormSessionHandle sessionHandle,
|
||||||
return result;
|
return result;
|
||||||
} // end NormSetWatermark()
|
} // end NormSetWatermark()
|
||||||
|
|
||||||
|
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||||
|
NormNodeId nodeId)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
if (session)
|
||||||
|
result = session->ServerAddAckingNode(nodeId);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} // end NormAddAckingNode()
|
||||||
|
|
||||||
|
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||||
|
NormNodeId nodeId)
|
||||||
|
{
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
if (session) session->ServerRemoveAckingNode(nodeId);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
} // end NormRemoveAckingNode()
|
||||||
|
|
||||||
|
NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
|
||||||
|
NormNodeId nodeId)
|
||||||
|
{
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
NormAckingStatus status =
|
||||||
|
(NormAckingStatus)session->ServerGetAckingStatus(nodeId);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NORM_ACK_INVALID;
|
||||||
|
}
|
||||||
|
} // end NormGetAckingNodeStatus()
|
||||||
|
|
||||||
/** NORM Receiver Functions */
|
/** NORM Receiver Functions */
|
||||||
|
|
||||||
|
|
@ -1260,10 +1295,7 @@ bool NormStartReceiver(NormSessionHandle sessionHandle,
|
||||||
if (instance && instance->dispatcher.SuspendThread())
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
{
|
{
|
||||||
NormSession* session = (NormSession*)sessionHandle;
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
if (session)
|
result = session->StartClient(bufferSpace);
|
||||||
result = session->StartClient(bufferSpace);
|
|
||||||
else
|
|
||||||
result = false;
|
|
||||||
instance->dispatcher.ResumeThread();
|
instance->dispatcher.ResumeThread();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1276,7 +1308,7 @@ void NormStopReceiver(NormSessionHandle sessionHandle)
|
||||||
if (instance && instance->dispatcher.SuspendThread())
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
{
|
{
|
||||||
NormSession* session = (NormSession*)sessionHandle;
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
if (session) session->StopClient();
|
session->StopClient();
|
||||||
instance->dispatcher.ResumeThread();
|
instance->dispatcher.ResumeThread();
|
||||||
}
|
}
|
||||||
} // end NormStopReceiver()
|
} // end NormStopReceiver()
|
||||||
|
|
@ -1364,8 +1396,7 @@ bool NormStreamRead(NormObjectHandle streamHandle,
|
||||||
{
|
{
|
||||||
NormStreamObject* stream =
|
NormStreamObject* stream =
|
||||||
static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
||||||
if (stream)
|
result = stream->Read(buffer, numBytes);
|
||||||
result = stream->Read(buffer, numBytes);
|
|
||||||
instance->dispatcher.ResumeThread();
|
instance->dispatcher.ResumeThread();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1380,8 +1411,7 @@ bool NormStreamSeekMsgStart(NormObjectHandle streamHandle)
|
||||||
NormStreamObject* stream =
|
NormStreamObject* stream =
|
||||||
static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
||||||
unsigned int numBytes = 0;
|
unsigned int numBytes = 0;
|
||||||
if (stream)
|
result = stream->Read(NULL, &numBytes, true);
|
||||||
result = stream->Read(NULL, &numBytes, true);
|
|
||||||
instance->dispatcher.ResumeThread();
|
instance->dispatcher.ResumeThread();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1391,7 +1421,10 @@ bool NormStreamSeekMsgStart(NormObjectHandle streamHandle)
|
||||||
unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle)
|
unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle)
|
||||||
{
|
{
|
||||||
NormStreamObject* stream = static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
NormStreamObject* stream = static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
||||||
return stream->GetCurrentReadOffset();
|
if (stream)
|
||||||
|
return stream->GetCurrentReadOffset();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
} // end NormStreamGetReadOffset()
|
} // end NormStreamGetReadOffset()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1641,3 +1674,16 @@ void NormNodeRelease(NormNodeHandle nodeHandle)
|
||||||
// the app to install an event handler callback and dispatch
|
// the app to install an event handler callback and dispatch
|
||||||
// events with a "NormDispatchEvents()" call ...
|
// events with a "NormDispatchEvents()" call ...
|
||||||
//
|
//
|
||||||
|
|
||||||
|
unsigned long NormCountCompletedObjects(NormSessionHandle sessionHandle)
|
||||||
|
{
|
||||||
|
unsigned long result = 0;
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
result = instance->CountCompletedObjects(session);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} // end long NormCountCompletedObjects()
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// C++ code continues to evolve. But, until this notice
|
// C++ code continues to evolve. But, until this notice
|
||||||
// is removed, the API shouldn't be considered final.
|
// is removed, the API shouldn't be considered final.
|
||||||
|
|
||||||
// NORM API control
|
/** NORM API Types */
|
||||||
typedef const void* NormInstanceHandle;
|
typedef const void* NormInstanceHandle;
|
||||||
extern const NormInstanceHandle NORM_INSTANCE_INVALID;
|
extern const NormInstanceHandle NORM_INSTANCE_INVALID;
|
||||||
|
|
||||||
|
|
@ -66,6 +66,14 @@ enum NormNackingMode
|
||||||
NORM_NACK_NORMAL
|
NORM_NACK_NORMAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum NormAckingStatus
|
||||||
|
{
|
||||||
|
NORM_ACK_INVALID,
|
||||||
|
NORM_ACK_FAILURE,
|
||||||
|
NORM_ACK_PENDING,
|
||||||
|
NORM_ACK_SUCCESS
|
||||||
|
};
|
||||||
|
|
||||||
enum NormProbingMode
|
enum NormProbingMode
|
||||||
{
|
{
|
||||||
NORM_PROBE_NONE,
|
NORM_PROBE_NONE,
|
||||||
|
|
@ -85,6 +93,7 @@ enum NormEventType
|
||||||
NORM_TX_QUEUE_VACANCY,
|
NORM_TX_QUEUE_VACANCY,
|
||||||
NORM_TX_QUEUE_EMPTY,
|
NORM_TX_QUEUE_EMPTY,
|
||||||
NORM_TX_FLUSH_COMPLETED,
|
NORM_TX_FLUSH_COMPLETED,
|
||||||
|
NORM_TX_WATERMARK_COMPLETED,
|
||||||
NORM_TX_OBJECT_SENT,
|
NORM_TX_OBJECT_SENT,
|
||||||
NORM_TX_OBJECT_PURGED,
|
NORM_TX_OBJECT_PURGED,
|
||||||
NORM_LOCAL_SERVER_CLOSED,
|
NORM_LOCAL_SERVER_CLOSED,
|
||||||
|
|
@ -221,12 +230,6 @@ void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
||||||
double intervalMin,
|
double intervalMin,
|
||||||
double intervalMax);
|
double intervalMax);
|
||||||
|
|
||||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
|
||||||
NormNodeId nodeId);
|
|
||||||
|
|
||||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
|
||||||
NormNodeId nodeId);
|
|
||||||
|
|
||||||
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||||
const char* fileName,
|
const char* fileName,
|
||||||
const char* infoPtr = (const char*)0,
|
const char* infoPtr = (const char*)0,
|
||||||
|
|
@ -261,13 +264,22 @@ void NormStreamSetPushEnable(NormObjectHandle streamHandle,
|
||||||
|
|
||||||
bool NormStreamHasVacancy(NormObjectHandle streamHandle);
|
bool NormStreamHasVacancy(NormObjectHandle streamHandle);
|
||||||
|
|
||||||
NormSize NormGetObjectSize(NormObjectHandle objectHandle);
|
|
||||||
|
|
||||||
void NormStreamMarkEom(NormObjectHandle streamHandle);
|
void NormStreamMarkEom(NormObjectHandle streamHandle);
|
||||||
|
|
||||||
bool NormSetWatermark(NormSessionHandle sessionHandle,
|
bool NormSetWatermark(NormSessionHandle sessionHandle,
|
||||||
NormObjectHandle objectHandle);
|
NormObjectHandle objectHandle);
|
||||||
|
|
||||||
|
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||||
|
NormNodeId nodeId);
|
||||||
|
|
||||||
|
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||||
|
NormNodeId nodeId);
|
||||||
|
|
||||||
|
NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
|
||||||
|
NormNodeId nodeId = NORM_NODE_ANY);
|
||||||
|
|
||||||
|
/* NORM Receiver Functions */
|
||||||
|
|
||||||
bool NormStartReceiver(NormSessionHandle sessionHandle,
|
bool NormStartReceiver(NormSessionHandle sessionHandle,
|
||||||
unsigned long bufferSpace);
|
unsigned long bufferSpace);
|
||||||
|
|
||||||
|
|
@ -359,5 +371,9 @@ void NormNodeRetain(NormNodeHandle nodeHandle);
|
||||||
|
|
||||||
void NormNodeRelease(NormNodeHandle nodeHandle);
|
void NormNodeRelease(NormNodeHandle nodeHandle);
|
||||||
|
|
||||||
|
/** Some experimental functions */
|
||||||
|
|
||||||
|
unsigned long NormCountCompletedObjects(NormSessionHandle sessionHandle);
|
||||||
|
|
||||||
|
|
||||||
#endif // _NORM_API
|
#endif // _NORM_API
|
||||||
|
|
|
||||||
|
|
@ -437,6 +437,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
NormNodeId localId = LocalNodeId();
|
NormNodeId localId = LocalNodeId();
|
||||||
for (UINT16 i = 0; i < nodeCount; i++)
|
for (UINT16 i = 0; i < nodeCount; i++)
|
||||||
{
|
{
|
||||||
|
// (TBD) also ACK if NORM_NODE_ANY is listed???
|
||||||
if (flush.GetAckingNodeId(i) == localId)
|
if (flush.GetAckingNodeId(i) == localId)
|
||||||
{
|
{
|
||||||
doAck = true;
|
doAck = true;
|
||||||
|
|
@ -1084,7 +1085,6 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (repair_boundary)
|
switch (repair_boundary)
|
||||||
{
|
{
|
||||||
case BLOCK_BOUNDARY:
|
case BLOCK_BOUNDARY:
|
||||||
|
|
@ -1296,6 +1296,7 @@ bool NormServerNode::PassiveRepairCheck(NormObjectId objectId,
|
||||||
NormBlockId blockId,
|
NormBlockId blockId,
|
||||||
NormSegmentId segmentId)
|
NormSegmentId segmentId)
|
||||||
{
|
{
|
||||||
|
if (!synchronized) return true;
|
||||||
NormObjectId nextId;
|
NormObjectId nextId;
|
||||||
if (GetFirstPending(nextId))
|
if (GetFirstPending(nextId))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -148,13 +148,14 @@ class NormAckingNode : public NormNode
|
||||||
NormAckingNode(class NormSession& theSession, NormNodeId nodeId);
|
NormAckingNode(class NormSession& theSession, NormNodeId nodeId);
|
||||||
~NormAckingNode();
|
~NormAckingNode();
|
||||||
bool IsPending() const
|
bool IsPending() const
|
||||||
{return (!ack_received &&( req_count > 0));}
|
{return (!ack_received && ( req_count > 0));}
|
||||||
void Reset(unsigned int maxAttempts = NORM_ROBUST_FACTOR)
|
void Reset(unsigned int maxAttempts = NORM_ROBUST_FACTOR)
|
||||||
{
|
{
|
||||||
ack_received = false;
|
ack_received = false;
|
||||||
req_count = maxAttempts;
|
req_count = maxAttempts;
|
||||||
}
|
}
|
||||||
void DecrementReqCount() {if (req_count > 0) req_count--;}
|
void DecrementReqCount() {if (req_count > 0) req_count--;}
|
||||||
|
void ResetReqCount() {req_count = NORM_ROBUST_FACTOR;}
|
||||||
unsigned int GetReqCount() const {return req_count;}
|
unsigned int GetReqCount() const {return req_count;}
|
||||||
bool AckReceived() const {return ack_received;}
|
bool AckReceived() const {return ack_received;}
|
||||||
void MarkAckReceived() {ack_received = true;}
|
void MarkAckReceived() {ack_received = true;}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,14 @@ NormObject::NormObject(NormObject::Type theType,
|
||||||
info_ptr(NULL), info_len(0), accepted(false), notify_on_update(true)
|
info_ptr(NULL), info_len(0), accepted(false), notify_on_update(true)
|
||||||
{
|
{
|
||||||
if (theServer)
|
if (theServer)
|
||||||
|
{
|
||||||
nacking_mode = theServer->GetDefaultNackingMode();
|
nacking_mode = theServer->GetDefaultNackingMode();
|
||||||
else
|
theServer->Retain();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
nacking_mode = NACK_NORMAL; // it doesn't really matter if !theServer
|
nacking_mode = NACK_NORMAL; // it doesn't really matter if !theServer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NormObject::~NormObject()
|
NormObject::~NormObject()
|
||||||
|
|
@ -47,7 +52,6 @@ void NormObject::Release()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMSG(0, "NormObject::Release() releasing non-retained object?!\n");
|
DMSG(0, "NormObject::Release() releasing non-retained object?!\n");
|
||||||
ASSERT(0);
|
|
||||||
}
|
}
|
||||||
if (0 == reference_count) delete this;
|
if (0 == reference_count) delete this;
|
||||||
} // end NormObject::Release()
|
} // end NormObject::Release()
|
||||||
|
|
@ -1677,6 +1681,7 @@ void NormStreamObject::StreamAdvance()
|
||||||
|
|
||||||
bool NormObject::CalculateBlockParity(NormBlock* block)
|
bool NormObject::CalculateBlockParity(NormBlock* block)
|
||||||
{
|
{
|
||||||
|
if (0 == nparity) return true;
|
||||||
char buffer[NormMsg::MAX_SIZE];
|
char buffer[NormMsg::MAX_SIZE];
|
||||||
UINT16 numData = GetBlockSize(block->GetId());
|
UINT16 numData = GetBlockSize(block->GetId());
|
||||||
for (UINT16 i = 0; i < numData; i++)
|
for (UINT16 i = 0; i < numData; i++)
|
||||||
|
|
@ -2548,14 +2553,18 @@ UINT16 NormStreamObject::ReadSegment(NormBlockId blockId,
|
||||||
if ((UINT32)offsetDelta < object_size.LSB())
|
if ((UINT32)offsetDelta < object_size.LSB())
|
||||||
{
|
{
|
||||||
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
||||||
if (b && !b->IsPending()) write_vacancy = true;
|
if (b && !b->IsPending())
|
||||||
|
{
|
||||||
|
write_vacancy = true;
|
||||||
|
session.Notify(NormController::TX_QUEUE_VACANCY, NULL, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (write_vacancy && !posted_tx_queue_vacancy)
|
/*if (HasVacancy() && !posted_tx_queue_vacancy)
|
||||||
{
|
{
|
||||||
posted_tx_queue_vacancy = true;
|
posted_tx_queue_vacancy = true;
|
||||||
session.Notify(NormController::TX_QUEUE_VACANCY, NULL, this);
|
session.Notify(NormController::TX_QUEUE_VACANCY, NULL, this);
|
||||||
}
|
} */
|
||||||
|
|
||||||
UINT16 segmentLength = NormDataMsg::ReadStreamPayloadLength(segment);
|
UINT16 segmentLength = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||||
ASSERT(segmentLength <= segment_size);
|
ASSERT(segmentLength <= segment_size);
|
||||||
|
|
@ -3103,7 +3112,7 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
||||||
{
|
{
|
||||||
if (0 != len)
|
if (0 != len)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Write() error: stream is closing\n");
|
DMSG(0, "NormStreamObject::Write() error: stream is closing (len:%lu eom:%d)\n", len, eom);
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -3254,7 +3263,7 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
||||||
msg_start = true;
|
msg_start = true;
|
||||||
if (FLUSH_ACTIVE == flush_mode)
|
if (FLUSH_ACTIVE == flush_mode)
|
||||||
flush_pending = true;
|
flush_pending = true;
|
||||||
else
|
else if (!stream_closing)
|
||||||
flush_pending = false;
|
flush_pending = false;
|
||||||
if ((0 != nBytes) || (FLUSH_NONE != flush_mode))
|
if ((0 != nBytes) || (FLUSH_NONE != flush_mode))
|
||||||
session.TouchServer();
|
session.TouchServer();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "normSegment.h"
|
#include "normSegment.h"
|
||||||
|
|
||||||
NormSegmentPool::NormSegmentPool()
|
NormSegmentPool::NormSegmentPool()
|
||||||
: seg_size(0), seg_count(0), seg_total(0), seg_list(NULL),
|
: seg_size(0), seg_count(0), seg_total(0), seg_list(NULL), seg_pool(NULL),
|
||||||
peak_usage(0), overruns(0), overrun_flag(false)
|
peak_usage(0), overruns(0), overrun_flag(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ NormSegmentPool::~NormSegmentPool()
|
||||||
|
|
||||||
bool NormSegmentPool::Init(unsigned int count, unsigned int size)
|
bool NormSegmentPool::Init(unsigned int count, unsigned int size)
|
||||||
{
|
{
|
||||||
if (seg_list) Destroy();
|
if (seg_pool) Destroy();
|
||||||
peak_usage = 0;
|
peak_usage = 0;
|
||||||
overruns = 0;
|
overruns = 0;
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
|
|
@ -23,46 +23,41 @@ bool NormSegmentPool::Init(unsigned int count, unsigned int size)
|
||||||
size = MIN(size, (SIM_PAYLOAD_MAX+1));
|
size = MIN(size, (SIM_PAYLOAD_MAX+1));
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
// This makes sure we get appropriate alignment
|
// This makes sure we get appropriate alignment
|
||||||
unsigned int alloc_size = size / sizeof(char*);
|
unsigned int allocSize = size / sizeof(char*);
|
||||||
if ((alloc_size*sizeof(char*)) < size) alloc_size++;
|
if ((allocSize*sizeof(char*)) < size) allocSize++;
|
||||||
seg_size = alloc_size * sizeof(char*);
|
seg_size = allocSize * sizeof(char*);
|
||||||
for (unsigned int i = 0; i < count; i++)
|
seg_pool = new char*[allocSize * count];
|
||||||
{
|
if (seg_pool)
|
||||||
char** ptr = new char*[alloc_size];
|
{
|
||||||
if (ptr)
|
char **ptr = seg_pool;
|
||||||
{
|
for (unsigned int i = 0; i < count; i++)
|
||||||
*ptr = seg_list;
|
{
|
||||||
seg_list = (char*)ptr;
|
*ptr = seg_list;
|
||||||
seg_count++;
|
seg_list = (char*)ptr;
|
||||||
}
|
ptr += allocSize;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
DMSG(0, "NormSegmentPool::Init() memory allocation error: %s\n",
|
else
|
||||||
GetErrorString());
|
{
|
||||||
seg_total = seg_count;
|
DMSG(0, "NormSegmentPool::Init() memory allocation error: %s\n",
|
||||||
Destroy();
|
GetErrorString());
|
||||||
return false;
|
Destroy();
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
seg_total = seg_count;
|
|
||||||
return true;
|
seg_total = seg_count = count;
|
||||||
|
return true;
|
||||||
} // end NormSegmentPool::Init()
|
} // end NormSegmentPool::Init()
|
||||||
|
|
||||||
void NormSegmentPool::Destroy()
|
void NormSegmentPool::Destroy()
|
||||||
{
|
{
|
||||||
ASSERT(seg_count == seg_total);
|
ASSERT(seg_count == seg_total);
|
||||||
char* ptr = seg_list;
|
delete [] seg_pool;
|
||||||
while (ptr)
|
seg_pool = NULL;
|
||||||
{
|
seg_list = NULL;
|
||||||
char* next;
|
seg_count = 0;
|
||||||
memcpy(&next, ptr, sizeof(char*));
|
seg_total = 0;
|
||||||
delete[] ptr;
|
seg_size = 0;
|
||||||
ptr = next;
|
|
||||||
}
|
|
||||||
seg_list = NULL;
|
|
||||||
seg_count = 0;
|
|
||||||
seg_total = 0;
|
|
||||||
seg_size = 0;
|
|
||||||
} // end NormSegmentPool::Destroy()
|
} // end NormSegmentPool::Destroy()
|
||||||
|
|
||||||
char* NormSegmentPool::Get()
|
char* NormSegmentPool::Get()
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ class NormSegmentPool
|
||||||
//char** ptr = (char**)segment;
|
//char** ptr = (char**)segment;
|
||||||
//ptr = seg_list;
|
//ptr = seg_list;
|
||||||
// (TBD) avoid this system call
|
// (TBD) avoid this system call
|
||||||
memcpy(segment, &seg_list, sizeof(char*));
|
//memcpy(segment, &seg_list, sizeof(char*));
|
||||||
|
*((char**)segment) = seg_list; // this might make a warning on Solaris
|
||||||
seg_list = segment;
|
seg_list = segment;
|
||||||
seg_count++;
|
seg_count++;
|
||||||
}
|
}
|
||||||
|
|
@ -39,6 +40,7 @@ class NormSegmentPool
|
||||||
unsigned int seg_count;
|
unsigned int seg_count;
|
||||||
unsigned int seg_total;
|
unsigned int seg_total;
|
||||||
char* seg_list;
|
char* seg_list;
|
||||||
|
char** seg_pool;
|
||||||
|
|
||||||
unsigned long peak_usage;
|
unsigned long peak_usage;
|
||||||
unsigned long overruns;
|
unsigned long overruns;
|
||||||
|
|
|
||||||
|
|
@ -240,12 +240,19 @@ void NormSession::SetTxRateInternal(double txRate)
|
||||||
{
|
{
|
||||||
if (tx_timer.IsActive())
|
if (tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
tx_timer.Deactivate();
|
|
||||||
if (txRate > 0.0)
|
if (txRate > 0.0)
|
||||||
{
|
{
|
||||||
double adjustInterval = (tx_rate/txRate) * tx_timer.GetTimeRemaining();
|
double adjustInterval = (tx_rate/txRate) * tx_timer.GetTimeRemaining();
|
||||||
tx_timer.SetInterval(adjustInterval);
|
if (adjustInterval > 0.100)
|
||||||
ActivateTimer(tx_timer);
|
{
|
||||||
|
tx_timer.SetInterval(adjustInterval);
|
||||||
|
tx_timer.Reschedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tx_timer.Deactivate();
|
||||||
|
|
||||||
}
|
}
|
||||||
tx_rate = txRate;
|
tx_rate = txRate;
|
||||||
}
|
}
|
||||||
|
|
@ -379,6 +386,7 @@ bool NormSession::StartServer(UINT16 instanceId,
|
||||||
prev_update_time.tv_sec = prev_update_time.tv_usec = 0;
|
prev_update_time.tv_sec = prev_update_time.tv_usec = 0;
|
||||||
sent_accumulator = 0;
|
sent_accumulator = 0;
|
||||||
nominal_packet_size = (double)segmentSize;
|
nominal_packet_size = (double)segmentSize;
|
||||||
|
data_active = false;
|
||||||
ndata = numData;
|
ndata = numData;
|
||||||
nparity = numParity;
|
nparity = numParity;
|
||||||
is_server = true;
|
is_server = true;
|
||||||
|
|
@ -420,7 +428,7 @@ void NormSession::StopServer()
|
||||||
NormObject* obj = tx_table.Find(tx_table.RangeLo());
|
NormObject* obj = tx_table.Find(tx_table.RangeLo());
|
||||||
ASSERT(obj);
|
ASSERT(obj);
|
||||||
tx_table.Remove(obj);
|
tx_table.Remove(obj);
|
||||||
obj->Release();
|
obj->Release();
|
||||||
}
|
}
|
||||||
// Then destroy table
|
// Then destroy table
|
||||||
tx_table.Destroy();
|
tx_table.Destroy();
|
||||||
|
|
@ -478,7 +486,7 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
// Determine next message (objectId::blockId::segmentId) to be sent
|
// Determine next message (objectId::blockId::segmentId) to be sent
|
||||||
NormObject* nextObj;
|
NormObject* nextObj;
|
||||||
NormObjectId nextObjectId;
|
NormObjectId nextObjectId = next_tx_object_id;
|
||||||
NormBlockId nextBlockId = 0;
|
NormBlockId nextBlockId = 0;
|
||||||
NormSegmentId nextSegmentId = 0;
|
NormSegmentId nextSegmentId = 0;
|
||||||
if (obj)
|
if (obj)
|
||||||
|
|
@ -520,19 +528,33 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
// Nothing transmit pending, check for repair pending object
|
// Nothing transmit pending, check for repair pending object
|
||||||
NormObjectTable::Iterator iterator(tx_table);
|
NormObjectTable::Iterator iterator(tx_table);
|
||||||
while ((nextObj = iterator.GetNextObject()))
|
|
||||||
if (nextObj->IsRepairPending()) break;
|
|
||||||
if (ServerGetFirstRepairPending(nextObjectId))
|
if (ServerGetFirstRepairPending(nextObjectId))
|
||||||
{
|
{
|
||||||
if (nextObj && (nextObj->GetId() < nextObjectId))
|
while ((nextObj = iterator.GetNextObject()))
|
||||||
{
|
{
|
||||||
nextObjectId = nextObj->GetId();
|
if (nextObjectId < nextObj->GetId())
|
||||||
}
|
{
|
||||||
else
|
nextObj = tx_table.Find(nextObjectId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (nextObj->IsRepairPending())
|
||||||
|
{
|
||||||
|
nextObjectId = nextObj->GetId();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextObjectId = next_tx_object_id;
|
||||||
|
while ((nextObj = iterator.GetNextObject()))
|
||||||
{
|
{
|
||||||
nextObj = tx_table.Find(nextObjectId);
|
if (nextObj->IsRepairPending())
|
||||||
ASSERT(nextObj);
|
{
|
||||||
}
|
nextObjectId = nextObj->GetId();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nextObj)
|
if (nextObj)
|
||||||
{
|
{
|
||||||
|
|
@ -542,10 +564,6 @@ void NormSession::Serve()
|
||||||
nextObj->FindRepairIndex(nextBlockId, nextSegmentId);
|
nextObj->FindRepairIndex(nextBlockId, nextSegmentId);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
nextObjectId = next_tx_object_id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ((nextObjectId > watermark_object_id) ||
|
if ((nextObjectId > watermark_object_id) ||
|
||||||
((nextObjectId == watermark_object_id) &&
|
((nextObjectId == watermark_object_id) &&
|
||||||
|
|
@ -555,14 +573,31 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
if (ServerQueueWatermarkFlush())
|
if (ServerQueueWatermarkFlush())
|
||||||
{
|
{
|
||||||
|
watermark_active = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// (TBD) optionally return here to have ack collection temporarily suspend data transmission
|
// (TBD) optionally return here to have ack collection temporarily
|
||||||
return;
|
// suspend forward progress of data transmission
|
||||||
|
//return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reset non-acked acking nodes since server has rewound
|
||||||
|
if (watermark_active)
|
||||||
|
{
|
||||||
|
watermark_active = false;
|
||||||
|
NormNodeTreeIterator iterator(acking_node_tree);
|
||||||
|
NormAckingNode* next;
|
||||||
|
while ((next = static_cast<NormAckingNode*>(iterator.GetNextNode())))
|
||||||
|
{
|
||||||
|
//if (next->IsPending())
|
||||||
|
next->ResetReqCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} // end if (watermark_pending)
|
} // end if (watermark_pending)
|
||||||
|
|
||||||
if (obj)
|
if (obj)
|
||||||
|
|
@ -572,6 +607,23 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
if (obj->NextServerMsg(msg))
|
if (obj->NextServerMsg(msg))
|
||||||
{
|
{
|
||||||
|
if (cc_enable && !data_active)
|
||||||
|
{
|
||||||
|
data_active = true;
|
||||||
|
if (probe_timer.IsActive())
|
||||||
|
{
|
||||||
|
double elapsed = probe_timer.GetInterval() - probe_timer.GetTimeRemaining();
|
||||||
|
const NormCCNode* clr = static_cast<const NormCCNode*>(cc_node_list.Head());
|
||||||
|
double probeInterval = (clr && clr->IsActive()) ?
|
||||||
|
MIN(grtt_advertised, clr->GetRtt()) :
|
||||||
|
grtt_advertised;
|
||||||
|
if (elapsed > probeInterval)
|
||||||
|
probe_timer.SetInterval(0.0);
|
||||||
|
else
|
||||||
|
probe_timer.SetInterval(probeInterval - elapsed);
|
||||||
|
probe_timer.Reschedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
msg->SetDestination(address);
|
msg->SetDestination(address);
|
||||||
msg->SetGrtt(grtt_quantized);
|
msg->SetGrtt(grtt_quantized);
|
||||||
msg->SetBackoffFactor((unsigned char)backoff_factor);
|
msg->SetBackoffFactor((unsigned char)backoff_factor);
|
||||||
|
|
@ -602,28 +654,29 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
// Queue flush message
|
// Queue flush message
|
||||||
if (!flush_timer.IsActive())
|
if (!flush_timer.IsActive())
|
||||||
|
{
|
||||||
if (flush_count < NORM_ROBUST_FACTOR)
|
if (flush_count < NORM_ROBUST_FACTOR)
|
||||||
{
|
|
||||||
ServerQueueFlush();
|
|
||||||
}
|
|
||||||
else if (NORM_ROBUST_FACTOR == flush_count)
|
|
||||||
{
|
|
||||||
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
|
||||||
LocalNodeId());
|
|
||||||
flush_count++;
|
|
||||||
if (stream->IsClosing())
|
|
||||||
{
|
{
|
||||||
stream->Close();
|
ServerQueueFlush();
|
||||||
stream->Retain();
|
}
|
||||||
Notify(NormController::TX_OBJECT_PURGED, (NormServerNode*)NULL, stream);
|
else if (NORM_ROBUST_FACTOR == flush_count)
|
||||||
stream->Release();
|
{
|
||||||
DeleteTxObject(stream);
|
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
||||||
obj = NULL;
|
LocalNodeId());
|
||||||
|
flush_count++;
|
||||||
|
if (stream->IsClosing())
|
||||||
|
{
|
||||||
|
stream->Close();
|
||||||
|
Notify(NormController::TX_OBJECT_PURGED, (NormServerNode*)NULL, stream);
|
||||||
|
DeleteTxObject(stream);
|
||||||
|
obj = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!posted_tx_queue_empty)
|
if (!posted_tx_queue_empty && !stream->IsClosing())
|
||||||
{
|
{
|
||||||
|
//data_active = false;
|
||||||
posted_tx_queue_empty = true;
|
posted_tx_queue_empty = true;
|
||||||
Notify(NormController::TX_QUEUE_EMPTY, (NormServerNode*)NULL, obj);
|
Notify(NormController::TX_QUEUE_EMPTY, (NormServerNode*)NULL, obj);
|
||||||
// (TBD) Was session deleted?
|
// (TBD) Was session deleted?
|
||||||
|
|
@ -649,6 +702,7 @@ void NormSession::Serve()
|
||||||
// No pending objects or positive acknowledgement request
|
// No pending objects or positive acknowledgement request
|
||||||
if (!posted_tx_queue_empty)
|
if (!posted_tx_queue_empty)
|
||||||
{
|
{
|
||||||
|
data_active = false;
|
||||||
posted_tx_queue_empty = true;
|
posted_tx_queue_empty = true;
|
||||||
Notify(NormController::TX_QUEUE_EMPTY,
|
Notify(NormController::TX_QUEUE_EMPTY,
|
||||||
(NormServerNode*)NULL,
|
(NormServerNode*)NULL,
|
||||||
|
|
@ -666,7 +720,6 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
||||||
LocalNodeId());
|
LocalNodeId());
|
||||||
|
|
||||||
Notify(NormController::TX_FLUSH_COMPLETED,
|
Notify(NormController::TX_FLUSH_COMPLETED,
|
||||||
(NormServerNode*)NULL,
|
(NormServerNode*)NULL,
|
||||||
(NormObject*)NULL);
|
(NormObject*)NULL);
|
||||||
|
|
@ -682,10 +735,11 @@ void NormSession::ServerSetWatermark(NormObjectId objectId,
|
||||||
TRACE("NormSession::ServerSetWatermark(%hu:%lu:%hu) ...\n",
|
TRACE("NormSession::ServerSetWatermark(%hu:%lu:%hu) ...\n",
|
||||||
(UINT16)objectId, (UINT32)blockId, (UINT16)segmentId);
|
(UINT16)objectId, (UINT32)blockId, (UINT16)segmentId);
|
||||||
watermark_pending = true;
|
watermark_pending = true;
|
||||||
|
watermark_active = false;
|
||||||
watermark_object_id = objectId;
|
watermark_object_id = objectId;
|
||||||
watermark_block_id = blockId;
|
watermark_block_id = blockId;
|
||||||
watermark_segment_id = segmentId;
|
watermark_segment_id = segmentId;
|
||||||
acks_collected = 0;
|
acking_success_count = 0;
|
||||||
// Reset acking_node_list
|
// Reset acking_node_list
|
||||||
NormNodeTreeIterator iterator(acking_node_tree);
|
NormNodeTreeIterator iterator(acking_node_tree);
|
||||||
NormNode* next;
|
NormNode* next;
|
||||||
|
|
@ -721,16 +775,54 @@ bool NormSession::ServerAddAckingNode(NormNodeId nodeId)
|
||||||
|
|
||||||
void NormSession::ServerRemoveAckingNode(NormNodeId nodeId)
|
void NormSession::ServerRemoveAckingNode(NormNodeId nodeId)
|
||||||
{
|
{
|
||||||
NormAckingNode* theNode = static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
|
NormAckingNode* theNode =
|
||||||
|
static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
|
||||||
if (theNode)
|
if (theNode)
|
||||||
{
|
{
|
||||||
if (watermark_pending && theNode->AckReceived())
|
|
||||||
acks_collected--;
|
|
||||||
acking_node_tree.DetachNode(theNode);
|
acking_node_tree.DetachNode(theNode);
|
||||||
acking_node_count--;
|
acking_node_count--;
|
||||||
}
|
}
|
||||||
} // end NormSession::RemoveAckingNode()
|
} // end NormSession::RemoveAckingNode()
|
||||||
|
|
||||||
|
NormSession::AckingStatus NormSession::ServerGetAckingStatus(NormNodeId nodeId)
|
||||||
|
{
|
||||||
|
if (NORM_NODE_ANY == nodeId)
|
||||||
|
{
|
||||||
|
// Return result based on overall success of acking process
|
||||||
|
if (watermark_pending)
|
||||||
|
{
|
||||||
|
return ACK_PENDING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (acking_success_count < acking_node_count)
|
||||||
|
return ACK_FAILURE;
|
||||||
|
else
|
||||||
|
return ACK_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NormAckingNode* theNode =
|
||||||
|
static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
|
||||||
|
if (theNode)
|
||||||
|
{
|
||||||
|
if (theNode->IsPending())
|
||||||
|
return ACK_PENDING;
|
||||||
|
else if (NORM_NODE_NONE == theNode->GetId())
|
||||||
|
return ACK_SUCCESS;
|
||||||
|
else if (theNode->AckReceived())
|
||||||
|
return ACK_SUCCESS;
|
||||||
|
else
|
||||||
|
return ACK_FAILURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ACK_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end NormSession::ServerGetAckingStatus()
|
||||||
|
|
||||||
bool NormSession::ServerQueueWatermarkFlush()
|
bool NormSession::ServerQueueWatermarkFlush()
|
||||||
{
|
{
|
||||||
if (flush_timer.IsActive()) return false;
|
if (flush_timer.IsActive()) return false;
|
||||||
|
|
@ -748,9 +840,24 @@ bool NormSession::ServerQueueWatermarkFlush()
|
||||||
NormNodeTreeIterator iterator(acking_node_tree);
|
NormNodeTreeIterator iterator(acking_node_tree);
|
||||||
NormAckingNode* next;
|
NormAckingNode* next;
|
||||||
watermark_pending = false;
|
watermark_pending = false;
|
||||||
|
NormAckingNode* nodeNone = NULL;
|
||||||
|
acking_success_count = 0;
|
||||||
while ((next = static_cast<NormAckingNode*>(iterator.GetNextNode())))
|
while ((next = static_cast<NormAckingNode*>(iterator.GetNextNode())))
|
||||||
{
|
{
|
||||||
if (next->IsPending())
|
// Save NORM_NODE_NONE for last
|
||||||
|
if (NORM_NODE_NONE == next->GetId())
|
||||||
|
{
|
||||||
|
if (next->IsPending())
|
||||||
|
nodeNone = next;
|
||||||
|
else
|
||||||
|
acking_success_count++; // implicit success for NORM_NODE_NONE
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (next->AckReceived())
|
||||||
|
{
|
||||||
|
acking_success_count++; // ACK was received for this node
|
||||||
|
}
|
||||||
|
else if (next->IsPending())
|
||||||
{
|
{
|
||||||
// Add node to list
|
// Add node to list
|
||||||
if (flush->AppendAckingNode(next->GetId(), segment_size))
|
if (flush->AppendAckingNode(next->GetId(), segment_size))
|
||||||
|
|
@ -761,22 +868,40 @@ bool NormSession::ServerQueueWatermarkFlush()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMSG(8, "NormSession::ServeQueueWatermarkFlush() full cmd ...\n");
|
DMSG(8, "NormSession::ServeQueueWatermarkFlush() full cmd ...\n");
|
||||||
|
nodeNone = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (NULL != nodeNone)
|
||||||
|
{
|
||||||
|
if (flush->AppendAckingNode(NORM_NODE_NONE, segment_size))
|
||||||
|
{
|
||||||
|
nodeNone->DecrementReqCount();
|
||||||
|
watermark_pending = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(8, "NormSession::ServeQueueWatermarkFlush() full cmd ...\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (watermark_pending)
|
if (watermark_pending)
|
||||||
{
|
{
|
||||||
flush_count++;
|
if (flush_count < NORM_ROBUST_FACTOR) flush_count++;
|
||||||
QueueMessage(flush);
|
QueueMessage(flush);
|
||||||
DMSG(8, "NormSession::ServeQueueWatermarkFlush() node>%lu cmd queued ...\n",
|
DMSG(8, "NormSession::ServeQueueWatermarkFlush() node>%lu cmd queued ...\n",
|
||||||
LocalNodeId());
|
LocalNodeId());
|
||||||
}
|
}
|
||||||
|
else if (NULL != acking_node_tree.GetRoot())
|
||||||
|
{
|
||||||
|
DMSG(4, "NormSession::ServeQueueWatermarkFlush() node>%lu watermark ack finished.\n");
|
||||||
|
Notify(NormController::TX_WATERMARK_COMPLETED, (NormServerNode*)NULL, (NormObject*)NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMSG(4, "NormSession::ServeQueueWatermarkFlush() node>%lu watermark ack finished incomplete\n");
|
DMSG(2, "NormSession::ServeQueueWatermarkFlush() node>%lu no acking nodes specified?!\n");
|
||||||
// (TBD) notify app
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -819,7 +944,7 @@ void NormSession::ServerQueueFlush()
|
||||||
// (TBD) send NORM_CMD(EOT) instead? - no
|
// (TBD) send NORM_CMD(EOT) instead? - no
|
||||||
if (ServerQueueSquelch(next_tx_object_id))
|
if (ServerQueueSquelch(next_tx_object_id))
|
||||||
{
|
{
|
||||||
flush_count++;
|
if (flush_count < NORM_ROBUST_FACTOR) flush_count++;
|
||||||
flush_timer.SetInterval(2*grtt_advertised);
|
flush_timer.SetInterval(2*grtt_advertised);
|
||||||
ActivateTimer(flush_timer);
|
ActivateTimer(flush_timer);
|
||||||
}
|
}
|
||||||
|
|
@ -839,7 +964,7 @@ void NormSession::ServerQueueFlush()
|
||||||
flush->SetFecBlockId(blockId);
|
flush->SetFecBlockId(blockId);
|
||||||
flush->SetFecSymbolId(segmentId);
|
flush->SetFecSymbolId(segmentId);
|
||||||
QueueMessage(flush);
|
QueueMessage(flush);
|
||||||
flush_count++;
|
if (flush_count < NORM_ROBUST_FACTOR) flush_count++;
|
||||||
DMSG(4, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n",
|
DMSG(4, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n",
|
||||||
LocalNodeId(), flush_count);
|
LocalNodeId(), flush_count);
|
||||||
}
|
}
|
||||||
|
|
@ -1058,7 +1183,7 @@ bool NormSession::QueueTxObject(NormObject* obj)
|
||||||
count = tx_table.Count();
|
count = tx_table.Count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Attempt to queue the object
|
// Attempt to queue the object (note it gets "retained" by the tx_table)
|
||||||
if (!tx_table.Insert(obj))
|
if (!tx_table.Insert(obj))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::QueueTxObject() tx_table insert error\n");
|
DMSG(0, "NormSession::QueueTxObject() tx_table insert error\n");
|
||||||
|
|
@ -1074,6 +1199,7 @@ bool NormSession::QueueTxObject(NormObject* obj)
|
||||||
|
|
||||||
void NormSession::DeleteTxObject(NormObject* obj)
|
void NormSession::DeleteTxObject(NormObject* obj)
|
||||||
{
|
{
|
||||||
|
ASSERT(obj);
|
||||||
if (tx_table.Remove(obj))
|
if (tx_table.Remove(obj))
|
||||||
{
|
{
|
||||||
NormObjectId objectId = obj->GetId();
|
NormObjectId objectId = obj->GetId();
|
||||||
|
|
@ -1101,6 +1227,7 @@ void NormSession::SetTxCacheBounds(NormObjectSize sizeMax,
|
||||||
{
|
{
|
||||||
// Remove oldest non-pending
|
// Remove oldest non-pending
|
||||||
NormObject* oldest = tx_table.Find(tx_table.RangeLo());
|
NormObject* oldest = tx_table.Find(tx_table.RangeLo());
|
||||||
|
ASSERT(oldest);
|
||||||
Notify(NormController::TX_OBJECT_PURGED, (NormServerNode*)NULL, oldest);
|
Notify(NormController::TX_OBJECT_PURGED, (NormServerNode*)NULL, oldest);
|
||||||
DeleteTxObject(oldest);
|
DeleteTxObject(oldest);
|
||||||
count = tx_table.Count();
|
count = tx_table.Count();
|
||||||
|
|
@ -1878,13 +2005,6 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
|
||||||
(watermark_segment_id == flushAck.GetFecSymbolId()))
|
(watermark_segment_id == flushAck.GetFecSymbolId()))
|
||||||
{
|
{
|
||||||
acker->MarkAckReceived();
|
acker->MarkAckReceived();
|
||||||
acks_collected++;
|
|
||||||
if (acks_collected >= acking_node_count)
|
|
||||||
{
|
|
||||||
watermark_pending = false;
|
|
||||||
DMSG(4, "NormSession::ServerHandleAckMessage() watermark acknowledgement complete\n");
|
|
||||||
// (TBD) notify app
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2840,7 +2960,8 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
if (probe_reset)
|
if (probe_reset)
|
||||||
{
|
{
|
||||||
probe_reset = false;
|
probe_reset = false;
|
||||||
OnProbeTimeout(probe_timer);
|
OnProbeTimeout(probe_timer); //we commented this out to give data a chance at low rates
|
||||||
|
// we may want to re-visit this, it might compromis high rate performance a little
|
||||||
ActivateTimer(probe_timer);
|
ActivateTimer(probe_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2870,12 +2991,11 @@ void NormSession::SetGrttProbingInterval(double intervalMin, double intervalMax)
|
||||||
{
|
{
|
||||||
double elapsed = probe_timer.GetInterval() - probe_timer.GetTimeRemaining();
|
double elapsed = probe_timer.GetInterval() - probe_timer.GetTimeRemaining();
|
||||||
if (elapsed < 0.0) elapsed = 0.0;
|
if (elapsed < 0.0) elapsed = 0.0;
|
||||||
probe_timer.Deactivate();
|
|
||||||
if (elapsed > grtt_interval)
|
if (elapsed > grtt_interval)
|
||||||
probe_timer.SetInterval(0.0);
|
probe_timer.SetInterval(0.0);
|
||||||
else
|
else
|
||||||
probe_timer.SetInterval(grtt_interval - elapsed);
|
probe_timer.SetInterval(grtt_interval - elapsed);
|
||||||
ActivateTimer(probe_timer);
|
probe_timer.Reschedule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end NormSession::SetGrttProbingInterval()
|
} // end NormSession::SetGrttProbingInterval()
|
||||||
|
|
@ -3088,23 +3208,31 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
AdjustRate(false);
|
AdjustRate(false);
|
||||||
|
|
||||||
// Determine next probe_interval
|
// Determine next probe_interval
|
||||||
const NormCCNode* clr = static_cast<const NormCCNode*>(cc_node_list.Head());
|
if (data_active)
|
||||||
probeInterval = clr ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised;
|
{
|
||||||
//double nominalRate = ((double)segment_size)/((double)tx_rate);
|
const NormCCNode* clr = static_cast<const NormCCNode*>(cc_node_list.Head());
|
||||||
//probeInterval = MAX(probeInterval, nominalRate);
|
probeInterval = (clr && clr->IsActive()) ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
probeInterval = grtt_interval;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Determine next probe_interval
|
// Determine next probe_interval
|
||||||
probeInterval = grtt_interval;
|
probeInterval = grtt_interval;
|
||||||
}
|
}
|
||||||
|
// perhaps this instead of the commented out probe_reset case???
|
||||||
QueueMessage(cmd);
|
double nominalInterval = ((double)segment_size)/((double)tx_rate);
|
||||||
probe_pending = true;
|
if (nominalInterval > probeInterval) probeInterval = nominalInterval;
|
||||||
|
|
||||||
// 3) Set probe_timer interval
|
// Set probe_timer interval for next probe
|
||||||
probe_timer.SetInterval(probeInterval);
|
probe_timer.SetInterval(probeInterval);
|
||||||
|
|
||||||
|
QueueMessage(cmd);
|
||||||
|
probe_pending = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // end NormSession::OnProbeTimeout()
|
} // end NormSession::OnProbeTimeout()
|
||||||
|
|
||||||
|
|
@ -3117,33 +3245,42 @@ void NormSession::AdjustRate(bool onResponse)
|
||||||
double txRate = tx_rate;
|
double txRate = tx_rate;
|
||||||
if (onResponse)
|
if (onResponse)
|
||||||
{
|
{
|
||||||
// Adjust rate based on CLR feedback and
|
if (data_active) // adjust only if actively transmitting
|
||||||
// adjust probe schedule
|
|
||||||
ASSERT(clr);
|
|
||||||
// (TBD) check feedback age
|
|
||||||
if (cc_slow_start)
|
|
||||||
{
|
{
|
||||||
txRate = clr->GetRate();
|
// Adjust rate based on CLR feedback and
|
||||||
DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
|
// adjust probe schedule
|
||||||
clr->GetId(), txRate*8.0/1000.0, tx_rate*8.0/1000.0, sent_rate*8.0/1000.0,
|
ASSERT(clr);
|
||||||
clr->GetRate()*8.0/1000.0);
|
// (TBD) check feedback age
|
||||||
}
|
if (cc_slow_start)
|
||||||
else
|
|
||||||
{
|
|
||||||
double clrRate = clr->GetRate();
|
|
||||||
if (clrRate > txRate)
|
|
||||||
{
|
{
|
||||||
double linRate = txRate + segment_size;
|
txRate = clr->GetRate();
|
||||||
txRate = MIN(clrRate, linRate);
|
DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
|
||||||
|
clr->GetId(), txRate*8.0/1000.0, tx_rate*8.0/1000.0, sent_rate*8.0/1000.0,
|
||||||
|
clr->GetRate()*8.0/1000.0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
txRate = clrRate;
|
double clrRate = clr->GetRate();
|
||||||
}
|
if (clrRate > txRate)
|
||||||
DMSG(6, "NormSession::AdjustRate(stdy state) clr>%lu newRate>%lf (rtt>%lf loss>%lf)\n",
|
{
|
||||||
clr->GetId(), txRate*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
|
double linRate = txRate + segment_size;
|
||||||
|
txRate = MIN(clrRate, linRate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
txRate = clrRate;
|
||||||
|
}
|
||||||
|
DMSG(6, "NormSession::AdjustRate(stdy state) clr>%lu newRate>%lf (rtt>%lf loss>%lf)\n",
|
||||||
|
clr->GetId(), txRate*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!data_active)
|
||||||
|
{
|
||||||
|
// reduce rate if no active data transmission
|
||||||
|
// (TBD) Perhaps we want to be less aggressive here someday
|
||||||
|
txRate *= 0.5;
|
||||||
|
}
|
||||||
else if (clr && clr->IsActive())
|
else if (clr && clr->IsActive())
|
||||||
{
|
{
|
||||||
// (TBD) fix CC feedback aging ...
|
// (TBD) fix CC feedback aging ...
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class NormController
|
||||||
TX_QUEUE_VACANCY,
|
TX_QUEUE_VACANCY,
|
||||||
TX_QUEUE_EMPTY,
|
TX_QUEUE_EMPTY,
|
||||||
TX_FLUSH_COMPLETED,
|
TX_FLUSH_COMPLETED,
|
||||||
|
TX_WATERMARK_COMPLETED,
|
||||||
TX_OBJECT_SENT,
|
TX_OBJECT_SENT,
|
||||||
TX_OBJECT_PURGED,
|
TX_OBJECT_PURGED,
|
||||||
LOCAL_SERVER_CLOSED,
|
LOCAL_SERVER_CLOSED,
|
||||||
|
|
@ -98,6 +99,13 @@ class NormSession
|
||||||
static const UINT16 DEFAULT_NDATA;
|
static const UINT16 DEFAULT_NDATA;
|
||||||
static const UINT16 DEFAULT_NPARITY;
|
static const UINT16 DEFAULT_NPARITY;
|
||||||
enum ProbingMode {PROBE_NONE, PROBE_PASSIVE, PROBE_ACTIVE};
|
enum ProbingMode {PROBE_NONE, PROBE_PASSIVE, PROBE_ACTIVE};
|
||||||
|
enum AckingStatus
|
||||||
|
{
|
||||||
|
ACK_INVALID,
|
||||||
|
ACK_FAILURE,
|
||||||
|
ACK_PENDING,
|
||||||
|
ACK_SUCCESS
|
||||||
|
};
|
||||||
|
|
||||||
// General methods
|
// General methods
|
||||||
const NormNodeId& LocalNodeId() const {return local_node_id;}
|
const NormNodeId& LocalNodeId() const {return local_node_id;}
|
||||||
|
|
@ -205,6 +213,7 @@ class NormSession
|
||||||
NormSegmentId segmentId);
|
NormSegmentId segmentId);
|
||||||
bool ServerAddAckingNode(NormNodeId nodeId);
|
bool ServerAddAckingNode(NormNodeId nodeId);
|
||||||
void ServerRemoveAckingNode(NormNodeId nodeId);
|
void ServerRemoveAckingNode(NormNodeId nodeId);
|
||||||
|
AckingStatus ServerGetAckingStatus(NormNodeId nodeId);
|
||||||
|
|
||||||
|
|
||||||
UINT16 ServerSegmentSize() const {return segment_size;}
|
UINT16 ServerSegmentSize() const {return segment_size;}
|
||||||
|
|
@ -411,11 +420,12 @@ class NormSession
|
||||||
// For postive acknowledgement collection
|
// For postive acknowledgement collection
|
||||||
NormNodeTree acking_node_tree;
|
NormNodeTree acking_node_tree;
|
||||||
unsigned int acking_node_count;
|
unsigned int acking_node_count;
|
||||||
|
unsigned int acking_success_count;
|
||||||
bool watermark_pending;
|
bool watermark_pending;
|
||||||
|
bool watermark_active;
|
||||||
NormObjectId watermark_object_id;
|
NormObjectId watermark_object_id;
|
||||||
NormBlockId watermark_block_id;
|
NormBlockId watermark_block_id;
|
||||||
NormSegmentId watermark_segment_id;
|
NormSegmentId watermark_segment_id;
|
||||||
unsigned int acks_collected;
|
|
||||||
|
|
||||||
// for unicast nack/cc feedback suppression
|
// for unicast nack/cc feedback suppression
|
||||||
bool advertise_repairs;
|
bool advertise_repairs;
|
||||||
|
|
@ -454,6 +464,7 @@ class NormSession
|
||||||
struct timeval prev_update_time; // for sent_rate measurement
|
struct timeval prev_update_time; // for sent_rate measurement
|
||||||
unsigned long sent_accumulator; // for sent_rate measurement
|
unsigned long sent_accumulator; // for sent_rate measurement
|
||||||
double nominal_packet_size;
|
double nominal_packet_size;
|
||||||
|
bool data_active; // true when actively sending data
|
||||||
|
|
||||||
// Client parameters
|
// Client parameters
|
||||||
bool is_client;
|
bool is_client;
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,14 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
NormSetCacheDirectory(instance, cachePath);
|
NormSetCacheDirectory(instance, cachePath);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Here's a trick to generate a _hopefully_ unique NormNodeId
|
// Here's a trick to generate a _hopefully_ unique NormNodeId
|
||||||
// based on an XOR of the system's IP address and the process id.
|
// based on an XOR of the system's IP address and the process id.
|
||||||
// (We use ProtoAddress::GetEndIdentifier() to get the local
|
// (We use ProtoAddress::GetEndIdentifier() to get the local
|
||||||
// "default" IP address for the system)
|
// "default" IP address for the system)
|
||||||
// (Note that passing "NORM_NODE_ANY" to the last arg of
|
// (Note that passing "NORM_NODE_ANY" to the last arg of
|
||||||
// NormCreateSession() does a similar thing but without
|
// NormCreateSession() does a similar thing but without
|
||||||
// the process id ... perhaps we should add the process id
|
// the processId XOR ... perhaps we should add the processId
|
||||||
// hack to that default NormNodeId picker?
|
// hack to that default "NORM_NODE_ANY" local NormNodeId picker???
|
||||||
ProtoAddress localAddr;
|
ProtoAddress localAddr;
|
||||||
if (!localAddr.ResolveLocalAddress())
|
if (!localAddr.ResolveLocalAddress())
|
||||||
{
|
{
|
||||||
|
|
@ -59,10 +57,9 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
localId ^= (NormNodeId)rand();
|
localId ^= (NormNodeId)rand();
|
||||||
}
|
}
|
||||||
|
//localId = 15; // for testing purposes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Create a NORM session instance
|
||||||
NormSessionHandle session = NormCreateSession(instance,
|
NormSessionHandle session = NormCreateSession(instance,
|
||||||
"224.1.2.3",
|
"224.1.2.3",
|
||||||
6003,
|
6003,
|
||||||
|
|
@ -74,6 +71,7 @@ int main(int argc, char* argv[])
|
||||||
//NormSetMessageTrace(session, true);
|
//NormSetMessageTrace(session, true);
|
||||||
// Uncomment to turn on some random packet loss
|
// Uncomment to turn on some random packet loss
|
||||||
//NormSetTxLoss(session, 10.0); // 10% packet loss
|
//NormSetTxLoss(session, 10.0); // 10% packet loss
|
||||||
|
//NormSetRxLoss(session, 20.0);
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
ProtoSystemTime(currentTime);
|
ProtoSystemTime(currentTime);
|
||||||
// Uncomment to get different packet loss patterns from run to run
|
// Uncomment to get different packet loss patterns from run to run
|
||||||
|
|
@ -82,7 +80,10 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
//NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
//NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
||||||
|
|
||||||
NormSetTransmitRate(session, 6000.0e+03); // in bits/second
|
NormSetTransmitRate(session, 256.0e+03); // in bits/second
|
||||||
|
|
||||||
|
// Uncomment to enable TCP-friendly congestion control (overrides NormSetTransmitRate())
|
||||||
|
NormSetCongestionControl(session, true);
|
||||||
|
|
||||||
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
||||||
|
|
||||||
|
|
@ -100,7 +101,7 @@ int main(int argc, char* argv[])
|
||||||
NormSetRxPortReuse(session, true);
|
NormSetRxPortReuse(session, true);
|
||||||
|
|
||||||
// Uncomment to receive your own traffic
|
// Uncomment to receive your own traffic
|
||||||
NormSetLoopback(session, true);
|
//NormSetLoopback(session, true);
|
||||||
|
|
||||||
// Uncomment this line to participate as a receiver
|
// Uncomment this line to participate as a receiver
|
||||||
//NormStartReceiver(session, 1024*1024);
|
//NormStartReceiver(session, 1024*1024);
|
||||||
|
|
@ -109,13 +110,9 @@ int main(int argc, char* argv[])
|
||||||
// (might be needed for high rate sessions)
|
// (might be needed for high rate sessions)
|
||||||
NormSetRxSocketBuffer(session, 512000);
|
NormSetRxSocketBuffer(session, 512000);
|
||||||
|
|
||||||
// Uncomment to enable TCP-friendly congestion control
|
|
||||||
NormSetCongestionControl(session, true);
|
|
||||||
|
|
||||||
// We use a random "sessionId"
|
// We use a random "sessionId"
|
||||||
NormSessionId sessionId = (NormSessionId)rand();
|
NormSessionId sessionId = (NormSessionId)rand();
|
||||||
|
|
||||||
|
|
||||||
// Uncomment the following line to start sender
|
// Uncomment the following line to start sender
|
||||||
NormStartSender(session, sessionId, 1024*1024, 1420, 64, 0);
|
NormStartSender(session, sessionId, 1024*1024, 1420, 64, 0);
|
||||||
|
|
||||||
|
|
@ -123,12 +120,13 @@ int main(int argc, char* argv[])
|
||||||
// (might be needed for high rate sessions)
|
// (might be needed for high rate sessions)
|
||||||
NormSetTxSocketBuffer(session, 512000);
|
NormSetTxSocketBuffer(session, 512000);
|
||||||
|
|
||||||
NormAddAckingNode(session, NormGetLocalNodeId(session));
|
NormAddAckingNode(session, NORM_NODE_NONE); //15); //NormGetLocalNodeId(session));
|
||||||
|
|
||||||
NormObjectHandle stream = NORM_OBJECT_INVALID;
|
NormObjectHandle stream = NORM_OBJECT_INVALID;
|
||||||
const char* filePath = "/home/adamson/images/art/giger/giger205.jpg";
|
const char* filePath = "/home/adamson/images/art/giger/giger205.jpg";
|
||||||
const char* fileName = "ferrari.jpg";
|
//const char* filePath = "/home/adamson/pkgs/rh73.tgz";
|
||||||
|
const char* fileName = "file1.jpg";
|
||||||
|
const char* fileName2 = "file2.jpg";
|
||||||
// Uncomment this line to send a stream instead of the file
|
// Uncomment this line to send a stream instead of the file
|
||||||
stream = NormStreamOpen(session, 10*1024*1024);
|
stream = NormStreamOpen(session, 10*1024*1024);
|
||||||
|
|
||||||
|
|
@ -148,18 +146,20 @@ int main(int argc, char* argv[])
|
||||||
int msgCount = 0;
|
int msgCount = 0;
|
||||||
int recvCount = -1; // used to monitor reliable stream reception
|
int recvCount = -1; // used to monitor reliable stream reception
|
||||||
int sendCount = 0;
|
int sendCount = 0;
|
||||||
int sendMax = 20;
|
int sendMax = -1; // -1 means unlimited
|
||||||
NormEvent theEvent;
|
NormEvent theEvent;
|
||||||
while (NormGetNextEvent(instance, &theEvent))
|
while (NormGetNextEvent(instance, &theEvent))
|
||||||
{
|
{
|
||||||
switch (theEvent.type)
|
switch (theEvent.type)
|
||||||
{
|
{
|
||||||
case NORM_TX_QUEUE_VACANCY:
|
case NORM_TX_QUEUE_VACANCY:
|
||||||
// TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
|
||||||
case NORM_TX_QUEUE_EMPTY:
|
case NORM_TX_QUEUE_EMPTY:
|
||||||
//TRACE("NORM_TX_QUEUE_EMPTY ...\n");
|
/*if (NORM_TX_QUEUE_VACANCY == theEvent.type)
|
||||||
//if (sendCount >= sendMax) break;
|
TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
||||||
if (NORM_OBJECT_INVALID != stream)
|
else
|
||||||
|
TRACE("NORM_TX_QUEUE_EMPTY ...\n");*/
|
||||||
|
if ((sendMax > 0) && (sendCount >= sendMax)) break;
|
||||||
|
if (NORM_OBJECT_INVALID != theEvent.object)
|
||||||
{
|
{
|
||||||
// We loop here to keep stream buffer full ....
|
// We loop here to keep stream buffer full ....
|
||||||
bool keepWriting = true;
|
bool keepWriting = true;
|
||||||
|
|
@ -187,22 +187,27 @@ int main(int argc, char* argv[])
|
||||||
NormStreamMarkEom(stream);
|
NormStreamMarkEom(stream);
|
||||||
txLen = txIndex = 0;
|
txLen = txIndex = 0;
|
||||||
sendCount++;
|
sendCount++;
|
||||||
if (sendCount >= sendMax)
|
if (sendCount == 15)
|
||||||
|
{
|
||||||
|
NormSetWatermark(session, stream);
|
||||||
|
}
|
||||||
|
if ((sendMax > 0) && (sendCount >= sendMax))
|
||||||
{
|
{
|
||||||
// Uncomment to gracefully shut down the stream
|
// Uncomment to gracefully shut down the stream
|
||||||
// after "sendMax" messages
|
// after "sendMax" messages
|
||||||
//NormStreamClose(stream, true);
|
NormStreamClose(stream, true);
|
||||||
//keepWriting = false;
|
keepWriting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // end while(keepWriting)
|
||||||
}
|
}
|
||||||
else
|
else if (NORM_OBJECT_INVALID == stream) // we weren't sending a stream that finished
|
||||||
{
|
{
|
||||||
|
const char* namePtr = (0 == (sendCount & 0x01)) ? fileName : fileName2;
|
||||||
NormObjectHandle txFile =
|
NormObjectHandle txFile =
|
||||||
NormFileEnqueue(session,
|
NormFileEnqueue(session,
|
||||||
filePath,
|
filePath,
|
||||||
fileName,
|
namePtr,
|
||||||
strlen(fileName));
|
strlen(fileName));
|
||||||
// Repeatedly queue our file for sending
|
// Repeatedly queue our file for sending
|
||||||
if (NORM_OBJECT_INVALID == txFile)
|
if (NORM_OBJECT_INVALID == txFile)
|
||||||
|
|
@ -214,13 +219,21 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
TRACE("QUEUED FILE ...\n");
|
TRACE("QUEUED FILE ...\n");
|
||||||
sendCount++;
|
sendCount++;
|
||||||
NormSetWatermark(session, txFile);
|
if (sendCount < 2) NormSetWatermark(session, txFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NORM_TX_OBJECT_PURGED:
|
case NORM_TX_OBJECT_PURGED:
|
||||||
DMSG(2, "normTest: NORM_TX_OBJECT_PURGED event ...\n");
|
DMSG(2, "normTest: NORM_TX_OBJECT_PURGED event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_TX_FLUSH_COMPLETED:
|
||||||
|
DMSG(2, "normTest: NORM_TX_FLUSH_COMPLETED event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_TX_WATERMARK_COMPLETED:
|
||||||
|
DMSG(2, "normTest: NORM_TX_WATERMARK_COMPLETED event ...\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NORM_RX_OBJECT_NEW:
|
case NORM_RX_OBJECT_NEW:
|
||||||
|
|
@ -335,6 +348,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
case NORM_RX_OBJECT_COMPLETED:
|
case NORM_RX_OBJECT_COMPLETED:
|
||||||
TRACE("normTest: NORM_RX_OBJECT_COMPLETED event ...\n");
|
TRACE("normTest: NORM_RX_OBJECT_COMPLETED event ...\n");
|
||||||
|
//NormStopReceiver(session);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NORM_RX_OBJECT_ABORTED:
|
case NORM_RX_OBJECT_ABORTED:
|
||||||
|
|
@ -345,8 +359,8 @@ int main(int argc, char* argv[])
|
||||||
TRACE("Got event type: %d\n", theEvent.type);
|
TRACE("Got event type: %d\n", theEvent.type);
|
||||||
} // end switch(theEvent.type)
|
} // end switch(theEvent.type)
|
||||||
|
|
||||||
// Break after sending "sendMax" messages or files
|
// Uncomment to exit program after sending "sendMax" messages or files
|
||||||
//if (sendCount >= sendMax) break;
|
//if ((sendMax > 0) && (sendCount >= sendMax)) break;
|
||||||
|
|
||||||
} // end while (NormGetNextEvent())
|
} // end while (NormGetNextEvent())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,6 @@
|
||||||
|
|
||||||
#ifndef _NORM_VERSION
|
#ifndef _NORM_VERSION
|
||||||
#define _NORM_VERSION
|
#define _NORM_VERSION
|
||||||
#define VERSION "1.3b5"
|
#define VERSION "1.3b6"
|
||||||
#endif // _NORM_VERSION
|
#endif // _NORM_VERSION
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
BUILD (Unix):
|
BUILD (Unix):
|
||||||
|
|
||||||
g++ -o normFileSend normFileSend.cpp -D_FILE_OFFSET_BITS=64 -DPROTO_DEBUG \
|
g++ -o normFileRecv normFileRecv.cpp -D_FILE_OFFSET_BITS=64 -DPROTO_DEBUG \
|
||||||
-I../common/ -I../protolib/common ../unix/libnorm.a \
|
-I../common/ -I../protolib/common ../unix/libnorm.a \
|
||||||
../protolib/unix/libProtokit.a -lpthread
|
../protolib/unix/libProtokit.a -lpthread
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
This directory contains files for incorporating the NORM protocol
|
This directory contains files for incorporating the NORM protocol
|
||||||
into the ns-2 network simulation tool.
|
into the ns-2 network simulation tool.
|
||||||
|
|
||||||
|
(The NORM ns-2 support may need a little tweaking to work)
|
||||||
|
|
||||||
FILES:
|
FILES:
|
||||||
|
|
||||||
nsNormAgent.h
|
nsNormAgent.h
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue