v1.3b7
parent
602326e415
commit
3dd25deec9
|
|
@ -6,7 +6,7 @@
|
|||
<META NAME="GENERATOR" CONTENT="NeoOffice/J 1.1 (Unix)">
|
||||
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
||||
<META NAME="CREATED" CONTENT="20040824;14180000">
|
||||
<META NAME="CHANGED" CONTENT="20050919;14362900">
|
||||
<META NAME="CHANGED" CONTENT="20051028;14285700">
|
||||
<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 ">
|
||||
<STYLE>
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
<TD WIDTH=371>
|
||||
<P ALIGN=LEFT STYLE="margin-left: 0.86in; margin-top: 0.17in; font-style: normal">
|
||||
<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<BR></FONT><FONT SIZE=4>(version 1.3b6)</FONT></B></FONT></FONT></P>
|
||||
<BR>Guide<BR></FONT><FONT SIZE=4>(version 1.3b7)</FONT></B></FONT></FONT></P>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
|
@ -60,7 +60,9 @@
|
|||
<P CLASS="western" STYLE="font-style: normal">This document describes
|
||||
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)</A></U></FONT> protocol implementation
|
||||
developed by the United States <FONT COLOR="#0000ff"><U><A HREF="http://www.nrl.navy.mil/">Naval
|
||||
developed by the Protocol Engineering and Advance Networking
|
||||
(<FONT COLOR="#0000ff"><U><A HREF="http://cs.itd.nrl.navy.mil/">PROTEAN</A></U></FONT>)
|
||||
Research Group of the United States <FONT COLOR="#0000ff"><U><A HREF="http://www.nrl.navy.mil/">Naval
|
||||
Research Laboratory</A></U></FONT> (NRL). The NORM protocol provides
|
||||
general purpose reliable data transport for applications wishing to
|
||||
use Internet Protocol (IP) Multicast services for group data
|
||||
|
|
@ -102,8 +104,6 @@ communication needs.</P>
|
|||
of Contents">Table
|
||||
of Contents</A></H1>
|
||||
<DIV ID="Table of Contents1" DIR="LTR">
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><BR>
|
||||
</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><A HREF="#API Initialization">API Initialization</A></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>
|
||||
|
|
@ -136,6 +136,8 @@ of Contents</A></H1>
|
|||
<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="#NormDestroyInstance()">NormDestroyInstance()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopInstance()">NormStopInstance()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRestartInstance()">NormRestartInstance()</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="#NormGetDescriptor()">NormGetDescriptor()</A></FONT></P>
|
||||
|
|
@ -151,7 +153,8 @@ of Contents</A></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="#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-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Sender Functions">NORM Sender Functions</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||
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="#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>
|
||||
|
|
@ -164,6 +167,8 @@ of Contents</A></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="#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="#NormSetBackoffFactor()">NormSetBackoffFactor()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGroupSize()">NormSetGroupSize()</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="#NormStreamOpen()">NormStreamOpen()</A></FONT></P>
|
||||
|
|
@ -234,7 +239,8 @@ protocol thread notifies the application of various protocol events
|
|||
through a thread-safe event dispatching mechanism and API calls are
|
||||
provided to allow the application to control NORM operation. (<I>Note:
|
||||
API mechanisms for lower-level, non-threaded control and execution
|
||||
of the NORM protocol engine may also be provided in the future</I>.)</P>
|
||||
of the NORM protocol engine code <U>may</U> also be provided in the
|
||||
future</I>.)</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM API operation
|
||||
can be roughly summarized with the following categories of functions:</P>
|
||||
<OL>
|
||||
|
|
@ -248,16 +254,16 @@ categories roughly reflects the order of function calls required to
|
|||
use NORM in an application. The first step is to create and
|
||||
initialize, as needed, at least one instance of the NORM API. Then
|
||||
one or more NORM transport sessions (where a “session”
|
||||
corresponds to data exchanges on a given multicast group and host
|
||||
port number) may be created and controlled. Applications may
|
||||
participate as senders and/or receivers within a NORM session. NORM
|
||||
senders transmit data to the session destination address (usually an
|
||||
IP multicast group) while receivers are notified of incoming data.
|
||||
The NORM API provides and event notification scheme to notify the
|
||||
application of significant sender and receiver events. There are
|
||||
also a number support functions provided for the application to
|
||||
control and monitor its participation within a NORM transport
|
||||
session.</P>
|
||||
corresponds to data exchanges on a given multicast group (or unicast
|
||||
address) and host port number) may be created and controlled.
|
||||
Applications may participate as senders and/or receivers within a
|
||||
NORM session. NORM senders transmit data to the session destination
|
||||
address (usually an IP multicast group) while receivers are notified
|
||||
of incoming data. The NORM API provides and event notification
|
||||
scheme to notify the application of significant sender and receiver
|
||||
events. There are also a number support functions provided for the
|
||||
application to control and monitor its participation within a NORM
|
||||
transport session.</P>
|
||||
<H2 CLASS="western"><A NAME="API Initialization">API Initialization</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM API requires
|
||||
that an application explicitly create at least one instance of the
|
||||
|
|
@ -271,9 +277,9 @@ mechanism.
|
|||
single thread should access the <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>
|
||||
API call for a given <FONT FACE="Courier">NormInstance</FONT>. This
|
||||
function serves as the conduit for delivering NORM protocol engine
|
||||
events to the application. While a NORM application can be designed
|
||||
to be single-threaded, even with multiple active <I>NormSessions</I>,
|
||||
multiple API instances can be created (see <FONT FACE="Courier"><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT>)
|
||||
events to the application. A NORM application can be designed to be
|
||||
single-threaded, even with multiple active <I>NormSessions</I>, but
|
||||
also multiple API instances can be created (see <FONT FACE="Courier"><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT>)
|
||||
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
|
||||
|
|
@ -295,7 +301,7 @@ transport session instances as needed. The application can
|
|||
participate in each session as a sender and/or receiver of data. If
|
||||
an application is participating as a sender, it may enqueue data
|
||||
transport objects for transmission. The control of transmission is
|
||||
largely left to the sender and API calls are provided to control
|
||||
largely left to the senders and API calls are provided to control
|
||||
transmission rate, FEC parameters, etc. Applications participating
|
||||
as receivers will be notified via the NORM API's event dispatching
|
||||
mechanism of pending and completed reliable reception of data along
|
||||
|
|
@ -531,12 +537,12 @@ build tools.</P>
|
|||
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
|
||||
(<I>iphlpapi.lib</I>) used by <I>Protolib</I> (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>
|
||||
possible that the <I>Protolib</I> 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
|
||||
reference to the NORM API variable types, constants and functions.</P>
|
||||
|
|
@ -702,7 +708,7 @@ description).
|
|||
</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormFlushMode">NormFlushMode</A></H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormFlushMode">NormFlushMode</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
|
||||
<A HREF="#NormFlushMode">NormFlushMode</A><BR>{<BR> NORM_FLUSH_NONE,<BR> NORM_FLUSH_PASSIVE,<BR> NORM_FLUSH_ACTIVE<BR>};</FONT></FONT></P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||
|
|
@ -710,7 +716,7 @@ these values is given in the descriptions of <FONT FACE="Courier"><A HREF="#Nor
|
|||
and <FONT FACE="Courier"><A HREF="#NormStreamSetAutoFlush()">NormStreamSetAutoFlush()</A></FONT> functions.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormProbingMode">NormProbingMode</A></H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormProbingMode">NormProbingMode</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
|
||||
<A HREF="#NormProbingMode">NormProbingMode</A><BR>{<BR> NORM_PROBE_NONE,<BR> NORM_PROBE_PASSIVE,<BR> NORM_PROBE_ACTIVE<BR>};</FONT></FONT></P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||
|
|
@ -802,6 +808,57 @@ has retained (see <FONT FACE="Courier"><A HREF="#NormObjectRetain()">NormObjectR
|
|||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function has no
|
||||
return value.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormStopInstance()">NormStopInstance()</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
|
||||
NormStopInstance(<A HREF="#NormInstanceHandle">NormInstanceHandle</A> instance);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function
|
||||
immediately stops the NORM protocol engine thread corresponding to
|
||||
the given <FONT FACE="Courier"><U>instance</U></FONT> parameter. It
|
||||
also posts a "dummy" notification event so that if another
|
||||
thread is blocked on a call to <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>,
|
||||
that thread will be released. Hence, for some multithreaded uses of
|
||||
the NORM API, this function may be useful as a preliminary step to
|
||||
safely coordinate thread shutdown before a call is made to
|
||||
<FONT FACE="Courier"><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT>. After
|
||||
<FONT FACE="Courier"><A HREF="#NormStopInstance()">NormStopInstance()</A></FONT> is called and any
|
||||
pending events posted prior to its call have been retrieved,
|
||||
<FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT> will return a value of
|
||||
<FONT FACE="Courier"><I>false</I></FONT>.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">When this function is
|
||||
invoked, state for any <I>NormSessions</I> associated with the given
|
||||
<FONT FACE="Courier"><U>instance</U></FONT> is "frozen".
|
||||
The complementary function, <FONT FACE="Courier"><A HREF="#NormRestartInstance()">NormRestartInstance()</A></FONT>
|
||||
can be subsequently used to "unfreeze" and resume NORM
|
||||
protocol operation (a new thread is created and started).</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function has no
|
||||
return value.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormRestartInstance()">NormRestartInstance()</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
|
||||
NormRestartInstance(<A HREF="#NormInstanceHandle">NormInstanceHandle</A> instance);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function creates
|
||||
and starts an operating system thread to resume NORM protocol engine
|
||||
operation for the given <FONT FACE="Courier"><U>instance</U></FONT>
|
||||
that was previously stopped by a call to <FONT FACE="Courier"><A HREF="#NormStopInstance()">NormStopInstance()</A></FONT>.
|
||||
It is not expected that this function will be used often, but there
|
||||
may be special application cases where "freezing" and later
|
||||
resuming NORM protocol operation may be useful.
|
||||
</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function returns
|
||||
<FONT FACE="Courier"><I>true</I></FONT> when the NORM protocol engine
|
||||
thread is successfully restarted, and <FONT FACE="Courier"><I>false</I></FONT>
|
||||
otherwise.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal"><BR>
|
||||
</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormSetCacheDirectory()">NormSetCacheDirectory()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -1142,7 +1199,7 @@ even when no event is pending. In these cases, the return value is
|
|||
provide an option to have a user-defined Window message posted when a
|
||||
NORM API event is pending. (Also some event filtering calls may be
|
||||
provided (e.g. avoid the potentially numerous <FONT FACE="Courier"><I>NORM_RX_OBJECT_UPDATED</I></FONT>
|
||||
events if undesired)).</P>
|
||||
events if not needed by the application)).</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormGetDescriptor()">NormGetDescriptor()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -1172,6 +1229,14 @@ returned which is valid until a call to <FONT FACE="Courier"><A HREF="#NormDestr
|
|||
is made. Upon error, a value of <I><FONT FACE="Courier">NORM_DESCRIPTOR_INVALID</FONT></I>
|
||||
is returned.</P>
|
||||
<H2 CLASS="western"><A NAME="Session Creation and Control Functions">Session Creation and Control Functions</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">Whether participating
|
||||
in a NORM protocol session as a sender, receiver, or both, there are
|
||||
some common API calls used to instantiate a <I>NormSession</I> and
|
||||
set some common session parameters. Functions are provided to
|
||||
control network socket and multicast parameters. Additionally, a
|
||||
"user data" value may be associated with a
|
||||
<FONT FACE="Courier"><A HREF="#NormSessionHandle">NormSessionHandle</A></FONT> for programming
|
||||
convenience when dealing with multiple sessions.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormCreateSession()">NormCreateSession()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -1182,20 +1247,21 @@ char* address,<BR> &nb
|
|||
short port,<BR> <A HREF="#NormNodeId">NormNodeId</A> localId);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function creates a
|
||||
NORM reliable multicast session (<I>NormSession</I>) using the
|
||||
address parameters provided. While session state is allocated and
|
||||
initialized, active session participation does not begin until a call
|
||||
is made to <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT> and/or
|
||||
<FONT FACE="Courier"><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT> to join the specified
|
||||
multicast group (if applicable) and start protocol operation. The
|
||||
following parameters are required in this function call:</P>
|
||||
NORM protocol session (<I>NormSession</I>) using the address
|
||||
(multicast or unicast) parameters provided. While session state is
|
||||
allocated and initialized, active session participation does not
|
||||
begin until a call is made to <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT>
|
||||
and/or <FONT FACE="Courier"><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT> to join the
|
||||
specified multicast group (if applicable) and start protocol
|
||||
operation. The following parameters are required in this function
|
||||
call:</P>
|
||||
<TABLE WIDTH=590 BORDER=0 CELLPADDING=7 CELLSPACING=0>
|
||||
<COL WIDTH=101>
|
||||
<COL WIDTH=461>
|
||||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=101>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
<FONT FACE="Courier">instance</FONT></P>
|
||||
<FONT FACE="Courier"><U>instance</U></FONT></P>
|
||||
</TD>
|
||||
<TD WIDTH=461>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
|
|
@ -1206,7 +1272,7 @@ following parameters are required in this function call:</P>
|
|||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=101>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
<FONT FACE="Courier">address</FONT></P>
|
||||
<FONT FACE="Courier"><U>address</U></FONT></P>
|
||||
</TD>
|
||||
<TD WIDTH=461>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
|
|
@ -1228,7 +1294,7 @@ following parameters are required in this function call:</P>
|
|||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=101>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
<FONT FACE="Courier">port</FONT></P>
|
||||
<FONT FACE="Courier"><U>port</U></FONT></P>
|
||||
</TD>
|
||||
<TD WIDTH=461>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
|
|
@ -1240,7 +1306,7 @@ following parameters are required in this function call:</P>
|
|||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=101>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
<FONT FACE="Courier">localId</FONT></P>
|
||||
<FONT FACE="Courier"><U>localId</U></FONT></P>
|
||||
</TD>
|
||||
<TD WIDTH=461>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
|
|
@ -1378,27 +1444,27 @@ return values.</P>
|
|||
<normApi.h></FONT></FONT></P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||
NormSetRxPortReuse(<A HREF="#NormSessionHandle">NormSessionHandle</A>
|
||||
session,<BR> bool
|
||||
state);</FONT></FONT></P>
|
||||
session,<BR> bool enable,<BR> bool bindToSessionAddr
|
||||
= true);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function allows
|
||||
the user to control the port reuse and binding behavior for the
|
||||
receive socket used for the given NORM <FONT FACE="Courier"><U>session</U></FONT>.
|
||||
When the <FONT FACE="Courier"><U>state</U></FONT> parameter is set
|
||||
to <FONT FACE="Courier"><I>true</I></FONT>:</P>
|
||||
<OL>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal">Reuse of the
|
||||
<I>NormSession</I> port number is enabled, and</P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal">the underlying
|
||||
socket is also bound (see the <FONT FACE="Courier">bind()</FONT>
|
||||
system call) to the <I>NormSession</I> destination address instead
|
||||
of the default behavior of binding to INADDR_ANY.
|
||||
</P>
|
||||
</OL>
|
||||
<P CLASS="western" STYLE="font-style: normal">The default binding to
|
||||
INADDR_ANY (<FONT FACE="Courier"><U>state</U></FONT> equals <FONT FACE="Courier"><I>false</I></FONT>)
|
||||
allows the <I>NormSession</I> receive socket to receive any multicast
|
||||
or unicast transmissions to the given port number. This allows a
|
||||
When the <FONT FACE="Courier"><U>enable</U></FONT> parameter is set
|
||||
to <FONT FACE="Courier"><I>true</I></FONT>, reuse of the <I>NormSession</I>
|
||||
port number is enabled, and, if the <FONT FACE="Courier"><U>bindToSessionAddr</U></FONT>
|
||||
is also set to <FONT FACE="Courier"><I>true</I></FONT> (default), the
|
||||
underlying socket is also bound (see the <FONT FACE="Courier">bind()</FONT>
|
||||
system call) to the <I>NormSession</I> destination address instead of
|
||||
the default behavior of binding to INADDR_ANY.
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">When this call is not
|
||||
made, the default binding to IP address INADDR_ANY (equivalent to
|
||||
when this call is made and <FONT FACE="Courier"><U>bindToSessionAddr</U></FONT>
|
||||
is set to <FONT FACE="Courier"><I>false</I></FONT>) allows the
|
||||
<I>NormSession</I> receive socket to receive <I>any</I> multicast or
|
||||
unicast transmissions to the session port number provided in the call
|
||||
to <FONT FACE="Courier"><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT>. This allows a
|
||||
NORM receiver to receive from senders sending to a multicast session
|
||||
address or the receiver's unicast address. Enabling port reuse and
|
||||
binding the session destination address allows multiple NORM sessions
|
||||
|
|
@ -1531,7 +1597,16 @@ created.</P>
|
|||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||
return values.</P>
|
||||
<H2 CLASS="western"><A NAME="NORM Sender Functions">NORM Sender Functions</A></H2>
|
||||
<H2 CLASS="western"><A NAME="NORM<SPAN STYLE="font-style: normal"> </SPAN>Sender
|
||||
Functions">NORM<SPAN STYLE="font-style: normal"> </SPAN>Sender
|
||||
Functions</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The functions described
|
||||
in this section apply only to NORM sender operation. Applications
|
||||
may participate strictly as senders or as receivers, or may act as
|
||||
both in the context of a NORM protocol session. The NORM sender is
|
||||
responsible for most parameters pertaining to its transmission of
|
||||
data. This includes transmission rate, data segmentation sizes, FEC
|
||||
coding parameters, stream buffer sizes, etc.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormStartSender()">NormStartSender()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -2112,6 +2187,75 @@ values are 1.0 second and 30.0 seconds, respectively.</P>
|
|||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||
return values.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormSetBackoffFactor()">NormSetBackoffFactor()</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
|
||||
NormSetBackoffFactor(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||
<BR> double backoffFactor);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal"><A NAME="OLE_LINK3"></A><A NAME="OLE_LINK2"></A>
|
||||
This function sets the sender's "backoff factor" for the
|
||||
given <FONT FACE="Courier"><U>session</U></FONT>.. The backoff
|
||||
factor is used to scale various timeouts related to the NACK repair
|
||||
process. The sender advertises its backoff factor setting to the
|
||||
receiver group in NORM protocol message headers. The default backoff
|
||||
factor for NORM sessions is <FONT FACE="Courier"><I>4.0</I></FONT>.
|
||||
The backoff factor is used to determine the maximum time that
|
||||
receivers may delay NACK transmissions (and other feedback messages)
|
||||
as part of NORM's probabilistic feedback suppression technique. For
|
||||
example, the maximum NACK delay time is <FONT FACE="Courier"><U>backoffFactor</U></FONT><FONT FACE="Courier">*GRTT</FONT>.
|
||||
Thus a large <FONT FACE="Courier"><U>backoffFactor</U></FONT> value
|
||||
introduces latency into the NORM repair process. However, a small
|
||||
<FONT FACE="Courier"><U>backoffFactor</U></FONT> value causes
|
||||
feedback suppression to be less effective and increases the risk of
|
||||
feedback implosion for large receiver group sizes. The default
|
||||
setting of <FONT FACE="Courier"><I>4.0</I></FONT> provides reasonable
|
||||
feedback suppression for moderate to large group sizes when multicast
|
||||
feedback is possible. The NORM specification recommends a backoff
|
||||
factor value of <FONT FACE="Courier"><I>6.0</I></FONT> when unicast
|
||||
feedback is used. However, for demanding applications (with respect
|
||||
to repair latency) when group sizes are modest, a small (even <FONT FACE="Courier"><I>0.0</I></FONT>)
|
||||
<FONT FACE="Courier"><U>backoffFactor</U></FONT> value can be
|
||||
specified to reduce the latency of reliable data delivery.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||
return values.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormSetGroupSize()">NormSetGroupSize()</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
|
||||
NormSetGroupSize(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||
<BR> unsigned
|
||||
int groupSize);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||
sender's estimate of receiver group size for the given session. The
|
||||
sender advertises its group size setting to the receiver group in
|
||||
NORM protocol message headers that, in turn, use this information to
|
||||
shape the distribution curve of their random timeouts for the
|
||||
timer-based, probabilistic feedback suppression technique used in the
|
||||
NORM protocol. Note that the <FONT FACE="Courier"><U>groupSize</U></FONT>
|
||||
estimate does not have to be very accurate and values within an order
|
||||
of magnitude of the actual group size tend to produce acceptable
|
||||
performance. The default group size setting in NORM is <FONT FACE="Courier"><I>1,000</I></FONT>
|
||||
and thus can work well for a wide range of actual receiver group
|
||||
sizes. The penalty of an overly large estimate is statistically a
|
||||
little more latency in reliable data delivery with respect to the
|
||||
round trip time and some potential for excess feedback. A
|
||||
substantial underestimation of group size increases the risk of
|
||||
feedback implosion. Currently, the NORM implementation does not
|
||||
attempt to automatically measure group size from receiver feedback.
|
||||
Applications could add their own mechanism for this (perhaps keeping
|
||||
explicit track of group membership), or it is possible that future
|
||||
versions of the NRL NORM implementation may have some provision for
|
||||
automatic group size estimation by the sender based on receiver
|
||||
feedback messages.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||
return values.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormFileEnqueue()">NormFileEnqueue()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -2392,22 +2536,36 @@ previously enqueued data pending transmission (original or repair)
|
|||
being dropped by the NORM protocol engine. While NORM NACK-based
|
||||
reliability does not provide explicit flow control, there is some
|
||||
degree of implicit flow control in limiting writing new data to the
|
||||
stream against pending repairs.
|
||||
</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>
|
||||
stream against pending repairs. Other flow control strategies are
|
||||
possible using the <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT>
|
||||
function.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier">NormEvents
|
||||
</FONT><FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT> and
|
||||
<FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT> are posted
|
||||
with the <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 the
|
||||
<FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY </I></FONT>event type
|
||||
is posted <I>only after</I> the stream's transmit buffer has been
|
||||
completely filled. Thus, the application <I>must</I> make a call to
|
||||
<FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT> that copies less than
|
||||
the requested <FONT FACE="Courier"><U>numBytes</U></FONT> value
|
||||
(return value less than <FONT FACE="Courier"><U>numBytes</U></FONT>)
|
||||
before additional <FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT>
|
||||
events are posted for the given <FONT FACE="Courier"><U>streamHandle</U></FONT>
|
||||
(i.e., the event type is not re-posted until the application has
|
||||
again filled the available stream transmit buffer space). By cueing
|
||||
off of <FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT>, the
|
||||
application can write its "freshest" available data to the
|
||||
stream, but by cueing off of <FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT>,
|
||||
an application can keep the NORM protocol engine busiest, to achieve
|
||||
the maximum possible throughput at high data rates.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function returns
|
||||
the number of bytes of data successfully enqueued for NORM stream
|
||||
transmission. If the underlying send stream buffer is full, this
|
||||
function may return zero.
|
||||
function may return zero or a value less than the requested <FONT FACE="Courier"><U>numBytes</U></FONT>.
|
||||
|
||||
</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormStreamFlush()">NormStreamFlush()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,42 @@
|
|||
0) Fix implementation of NORM_DATA_FLAG_REPAIR.
|
||||
|
||||
1) Implement unicast feedback of NACK messages and server
|
||||
re-advertisement for suppressing the unicast feedback.
|
||||
(COMPLETED)
|
||||
|
||||
2) Add mechanism to allow window-based control of NORM server
|
||||
transmission rate.
|
||||
|
||||
3) Implement TFMCC and/or PGM-CC congestion control mechanisms
|
||||
within NORM. (TFMCC COMPLETED)
|
||||
|
||||
4) A single squelch message should be sent per repair cycle?
|
||||
The squelch works to "synchronize" clients to the server
|
||||
repair window. As the code is currently implemented, the
|
||||
server might generate a squelch per NACK. This might be OK
|
||||
since the occurrence of squelch _should_ be rare. The
|
||||
debug statistics should keep a count of squelch events.
|
||||
(COMPLETED)
|
||||
|
||||
5) Implement positive acknowledgement mechanism per the NORM spec.
|
||||
(COMPLETED - needs more testing)
|
||||
|
||||
6) Implement and document simple API to control and access NORM
|
||||
features. (COMPLETED and enhancement in progress)
|
||||
|
||||
7) Build "norm daemon" using API.
|
||||
|
||||
8) JAVA API for NRL NORM Protocol library
|
||||
|
||||
9) Correct/complete user guide for "norm" demo app
|
||||
|
||||
10) Release wxNormChat project
|
||||
|
||||
11) Test, release "naft" (updated "raft") for reliable streaming.
|
||||
|
||||
12) Can we eliminate rapid clr norm-cc probing when data is
|
||||
not being actively sent? (COMPLETED)
|
||||
|
||||
|
||||
|
||||
|
||||
33
VERSION.TXT
33
VERSION.TXT
|
|
@ -1,5 +1,38 @@
|
|||
NORM Version History
|
||||
|
||||
Version 1.3b7
|
||||
=============
|
||||
- Deprecated NORM stream payload flags in favor of "payload_msg_start"
|
||||
field per revised NORM specification (draft-ietf-rmt-pi-nom-revised-00)
|
||||
This included interpreting NORM_DATA (source segment) messages for
|
||||
NORM_OBJECT_STREAM with "payload_len" field value of ZERO as
|
||||
"stream control" messages where the "payload_msg_start" field serves
|
||||
as the stream control message type indications. The "End-of-Stream"
|
||||
control message consists of "payload_msg_start" = 0
|
||||
when "payload_len" = 0. No other stream control messages are yet
|
||||
defined. The next revision of the NORM spec will describe this.
|
||||
(Thus for NORM stream purposes, this NORM version is _not_ interoperable
|
||||
with previous versions)
|
||||
- Fixed problem where NormServerNode "retrieval_pool" had allocated
|
||||
segments one byte too small (although this is OBE with the above
|
||||
deprecation of stream flags which is what the byte was used for)
|
||||
- Fixed bug where sender objects were not properly "closed" when the
|
||||
object table was cleaned upon NormStopSender()
|
||||
- Added support to VC++ .Net workspace for building "Norm.dll"
|
||||
(NORM as a dynamic linked library) and similarly added option
|
||||
to build "libnorm.dylib" for MacOS. ("libnorm.so" for other
|
||||
Unix platforms should already work).
|
||||
- Fixed NormSetTOS() call.
|
||||
- Added option to NormSetPortReuse() to maintain INADDR_ANY binding
|
||||
if desired.
|
||||
- Refined management of NORM sender stream buffer so sender wouldn't
|
||||
prematurely discard buffer stream blocks when alot of small
|
||||
segments (smaller than segment_size) were buffered.
|
||||
- Added NormStopInstance() call to provide means for multi-threaded
|
||||
NORM apps to stop the NORM protocol engine and awake any other thread
|
||||
blocked on NormGetNextEvent() to signal shutdown of NormInstance.
|
||||
- Also updated code so ns-2 build works and tested w/ ns-2.29
|
||||
|
||||
Version 1.3b6
|
||||
=============
|
||||
- Fixed some oversite bugs that crept in with changes in 1.3b5
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#define _NORM_API_BUILD // force 'dllexport' in "normApi.h"
|
||||
#include "normApi.h"
|
||||
#include "normSession.h"
|
||||
|
||||
|
|
@ -8,15 +9,23 @@
|
|||
#endif // WIN32
|
||||
|
||||
// const defs
|
||||
extern NORM_API_LINKAGE
|
||||
const NormInstanceHandle NORM_INSTANCE_INVALID = ((NormInstanceHandle)0);
|
||||
extern NORM_API_LINKAGE
|
||||
const NormSessionHandle NORM_SESSION_INVALID = ((NormSessionHandle)0);
|
||||
extern NORM_API_LINKAGE
|
||||
const NormNodeHandle NORM_NODE_INVALID = ((NormNodeHandle)0);
|
||||
extern NORM_API_LINKAGE
|
||||
const NormNodeId NORM_NODE_NONE = ((NormNodeId)0x00000000);
|
||||
extern NORM_API_LINKAGE
|
||||
const NormNodeId NORM_NODE_ANY = ((NormNodeId)0xffffffff);
|
||||
extern NORM_API_LINKAGE
|
||||
const NormObjectHandle NORM_OBJECT_INVALID = ((NormObjectHandle)0);
|
||||
|
||||
extern NORM_API_LINKAGE
|
||||
const NormDescriptor NORM_DESCRIPTOR_INVALID = ProtoDispatcher::INVALID_DESCRIPTOR;
|
||||
|
||||
|
||||
/** The "NormInstance" class is a C++ helper class that keeps
|
||||
* state for an instance of the NORM API. It acts as a
|
||||
* "go between" the API's procedural function calls and
|
||||
|
|
@ -37,6 +46,24 @@ class NormInstance : public NormController
|
|||
bool Startup(bool priorityBoost = false);
|
||||
void Shutdown();
|
||||
|
||||
void Pause() // pause NORM protocol engine
|
||||
{
|
||||
dispatcher.Stop();
|
||||
Notify(NormController::EVENT_INVALID, &session_mgr, NULL, NULL, NULL);
|
||||
}
|
||||
bool Resume()
|
||||
{
|
||||
if (dispatcher.StartThread(priority_boost))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "NormInstance::Resume() error restarting NORM thread\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WaitForEvent();
|
||||
bool GetNextEvent(NormEvent* theEvent);
|
||||
bool SetCacheDirectory(const char* cachePath);
|
||||
|
|
@ -63,7 +90,6 @@ class NormInstance : public NormController
|
|||
NormSession* session = (NormSession*)sessionHandle;
|
||||
NormInstance* theInstance = static_cast<NormInstance*>(session->GetSessionMgr().GetController());
|
||||
return theInstance;
|
||||
//return static_cast<NormInstance*>(session->GetSessionMgr().GetController());
|
||||
}
|
||||
static NormInstance* GetInstanceFromNode(NormNodeHandle nodeHandle)
|
||||
{
|
||||
|
|
@ -126,6 +152,7 @@ class NormInstance : public NormController
|
|||
}; // end class NormInstance::Notification
|
||||
|
||||
ProtoDispatcher dispatcher;
|
||||
bool priority_boost;
|
||||
NormSessionMgr session_mgr;
|
||||
|
||||
private:
|
||||
|
|
@ -165,7 +192,8 @@ void NormInstance::Notification::Queue::Destroy()
|
|||
////////////////////////////////////////////////////
|
||||
// NormInstance implementation
|
||||
NormInstance::NormInstance()
|
||||
: session_mgr(static_cast<ProtoTimerMgr&>(dispatcher),
|
||||
: priority_boost(false),
|
||||
session_mgr(static_cast<ProtoTimerMgr&>(dispatcher),
|
||||
static_cast<ProtoSocket::Notifier&>(dispatcher)),
|
||||
previous_notification(NULL), rx_cache_path(NULL)
|
||||
{
|
||||
|
|
@ -188,7 +216,7 @@ bool NormInstance::SetCacheDirectory(const char* cachePath)
|
|||
bool result = false;
|
||||
if (dispatcher.SuspendThread())
|
||||
{
|
||||
int length = strlen(cachePath);
|
||||
size_t length = strlen(cachePath);
|
||||
if (PROTO_PATH_DELIMITER != cachePath[length-1])
|
||||
length += 2;
|
||||
else
|
||||
|
|
@ -481,6 +509,11 @@ bool NormInstance::GetNextEvent(NormEvent* theEvent)
|
|||
|
||||
bool NormInstance::WaitForEvent()
|
||||
{
|
||||
if (!dispatcher.IsThreaded())
|
||||
{
|
||||
DMSG(0, "NormInstance::WaitForEvent() warning: NORM thread not running!\n");
|
||||
return false;
|
||||
}
|
||||
#ifdef WIN32
|
||||
WaitForSingleObject(notify_event, INFINITE);
|
||||
#else
|
||||
|
|
@ -537,6 +570,7 @@ bool NormInstance::Startup(bool priorityBoost)
|
|||
}
|
||||
#endif // if/else WIN32/UNIX
|
||||
// 2) Start thread
|
||||
priority_boost = priorityBoost;
|
||||
return dispatcher.StartThread(priorityBoost);
|
||||
} // end NormInstance::Startup()
|
||||
|
||||
|
|
@ -637,6 +671,7 @@ unsigned long NormInstance::CountCompletedObjects(NormSession* session)
|
|||
|
||||
/** NORM API Initialization */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormInstanceHandle NormCreateInstance(bool priorityBoost)
|
||||
{
|
||||
NormInstance* normInstance = new NormInstance;
|
||||
|
|
@ -650,11 +685,35 @@ NormInstanceHandle NormCreateInstance(bool priorityBoost)
|
|||
return NORM_INSTANCE_INVALID;
|
||||
} // end NormCreateInstance()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormDestroyInstance(NormInstanceHandle instanceHandle)
|
||||
{
|
||||
delete ((NormInstance*)instanceHandle);
|
||||
} // end NormDestroyInstance()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormRestartInstance(NormInstanceHandle instanceHandle)
|
||||
{
|
||||
NormInstance* instance = (NormInstance*)instanceHandle;
|
||||
if (instance)
|
||||
{
|
||||
if (instance->dispatcher.IsThreaded())
|
||||
instance->Pause();
|
||||
return instance->Resume();
|
||||
}
|
||||
return false; // invalid instanceHandle
|
||||
} // end NormStartInstance()
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStopInstance(NormInstanceHandle instanceHandle)
|
||||
{
|
||||
NormInstance* instance = (NormInstance*)instanceHandle;
|
||||
if (instance) instance->Pause(); // stops NORM protocol thread
|
||||
} // end NormStopInstance()
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetCacheDirectory(NormInstanceHandle instanceHandle,
|
||||
const char* cachePath)
|
||||
{
|
||||
|
|
@ -665,6 +724,7 @@ bool NormSetCacheDirectory(NormInstanceHandle instanceHandle,
|
|||
return false;
|
||||
} // end NormSetCacheDirectory()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormDescriptor NormGetDescriptor(NormInstanceHandle instanceHandle)
|
||||
{
|
||||
NormInstance* instance = (NormInstance*)instanceHandle;
|
||||
|
|
@ -675,6 +735,7 @@ NormDescriptor NormGetDescriptor(NormInstanceHandle instanceHandle)
|
|||
} // end NormGetDescriptor()
|
||||
|
||||
// (TBD) add a timeout option to this?
|
||||
NORM_API_LINKAGE
|
||||
bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -682,7 +743,12 @@ bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent)
|
|||
if (instance)
|
||||
{
|
||||
if (instance->NotifyQueueIsEmpty()) //(TBD) perform this check???
|
||||
instance->WaitForEvent();
|
||||
{
|
||||
if (!instance->WaitForEvent())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (instance->dispatcher.SuspendThread())
|
||||
{
|
||||
result = instance->GetNextEvent(theEvent);
|
||||
|
|
@ -695,6 +761,7 @@ bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent)
|
|||
|
||||
/** NORM Session Creation and Control Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
|
||||
const char* sessionAddr,
|
||||
unsigned short sessionPort,
|
||||
|
|
@ -711,6 +778,7 @@ NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
|
|||
return NORM_SESSION_INVALID;
|
||||
} // end NormCreateSession()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormDestroySession(NormSessionHandle sessionHandle)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
|
|
@ -729,6 +797,7 @@ void NormDestroySession(NormSessionHandle sessionHandle)
|
|||
}
|
||||
} // end NormDestroySession()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetUserData(NormSessionHandle sessionHandle, const void* userData)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
|
|
@ -743,6 +812,7 @@ void NormSetUserData(NormSessionHandle sessionHandle, const void* userData)
|
|||
}
|
||||
} // end NormSetUserData()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
const void* NormGetUserData(NormSessionHandle sessionHandle)
|
||||
{
|
||||
const void* userData = NULL;
|
||||
|
|
@ -760,6 +830,7 @@ const void* NormGetUserData(NormSessionHandle sessionHandle)
|
|||
return userData;
|
||||
} // end NormGetUserData()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle)
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
|
|
@ -769,6 +840,7 @@ NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle)
|
|||
return NORM_NODE_NONE;
|
||||
} // end NormGetLocalNodeId()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTxPort(NormSessionHandle sessionHandle,
|
||||
unsigned short txPort)
|
||||
{
|
||||
|
|
@ -784,8 +856,10 @@ void NormSetTxPort(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetTxPort()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetRxPortReuse(NormSessionHandle sessionHandle,
|
||||
bool state)
|
||||
bool enable,
|
||||
bool bindToSessionAddress)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (NULL != instance)
|
||||
|
|
@ -793,12 +867,13 @@ void NormSetRxPortReuse(NormSessionHandle sessionHandle,
|
|||
if (instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session) session->SetRxPortReuse(state);
|
||||
if (session) session->SetRxPortReuse(enable, bindToSessionAddress);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
}
|
||||
} // end NormSetTxPort()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
|
||||
const char* interfaceName)
|
||||
{
|
||||
|
|
@ -817,6 +892,7 @@ bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormSetMulticastInterface()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetTTL(NormSessionHandle sessionHandle,
|
||||
unsigned char ttl)
|
||||
{
|
||||
|
|
@ -835,6 +911,7 @@ bool NormSetTTL(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormSetTTL()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetTOS(NormSessionHandle sessionHandle,
|
||||
unsigned char tos)
|
||||
{
|
||||
|
|
@ -846,7 +923,7 @@ bool NormSetTOS(NormSessionHandle sessionHandle,
|
|||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session)
|
||||
result = session->SetTTL(tos);
|
||||
result = session->SetTOS(tos);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
}
|
||||
|
|
@ -855,6 +932,7 @@ bool NormSetTOS(NormSessionHandle sessionHandle,
|
|||
|
||||
/** Special test/debug support functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetLoopback(NormSessionHandle sessionHandle, bool state)
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
|
|
@ -864,18 +942,21 @@ bool NormSetLoopback(NormSessionHandle sessionHandle, bool state)
|
|||
return false;
|
||||
} // end NormSetLoopback()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetMessageTrace(NormSessionHandle sessionHandle, bool state)
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session) session->SetTrace(state);
|
||||
} // end NormSetMessageTrace()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTxLoss(NormSessionHandle sessionHandle, double percent)
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session) session->SetTxLoss(percent);
|
||||
} // end NormSetTxLoss()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetRxLoss(NormSessionHandle sessionHandle, double percent)
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
|
|
@ -885,6 +966,7 @@ void NormSetRxLoss(NormSessionHandle sessionHandle, double percent)
|
|||
|
||||
/** NORM Sender Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStartSender(NormSessionHandle sessionHandle,
|
||||
NormSessionId sessionId,
|
||||
unsigned long bufferSpace,
|
||||
|
|
@ -906,6 +988,7 @@ bool NormStartSender(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormStartSender()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStopSender(NormSessionHandle sessionHandle)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
|
|
@ -917,6 +1000,17 @@ void NormStopSender(NormSessionHandle sessionHandle)
|
|||
}
|
||||
} // end NormStopSender()
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
double NormGetTransmitRate(NormSessionHandle sessionHandle)
|
||||
{
|
||||
if (NORM_SESSION_INVALID != sessionHandle)
|
||||
return (((NormSession*)sessionHandle)->GetTxRate());
|
||||
else
|
||||
return -1.0;
|
||||
} // end NormGetTransmitRate()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTransmitRate(NormSessionHandle sessionHandle,
|
||||
double bitsPerSecond)
|
||||
{
|
||||
|
|
@ -929,6 +1023,7 @@ void NormSetTransmitRate(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetTransmitRate()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetTxSocketBuffer(NormSessionHandle sessionHandle,
|
||||
unsigned int bufferSize)
|
||||
{
|
||||
|
|
@ -944,6 +1039,7 @@ bool NormSetTxSocketBuffer(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormSetTxSocketBuffer()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetCongestionControl(NormSessionHandle sessionHandle, bool enable)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
|
|
@ -955,6 +1051,7 @@ void NormSetCongestionControl(NormSessionHandle sessionHandle, bool enable)
|
|||
}
|
||||
} // end NormSetCongestionControl()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTransmitRateBounds(NormSessionHandle sessionHandle,
|
||||
double rateMin,
|
||||
double rateMax)
|
||||
|
|
@ -968,6 +1065,7 @@ void NormSetTransmitRateBounds(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetTransmitRateBounds()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTransmitCacheBounds(NormSessionHandle sessionHandle,
|
||||
NormSize sizeMax,
|
||||
unsigned long countMin,
|
||||
|
|
@ -983,6 +1081,7 @@ void NormSetTransmitCacheBounds(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetTransmitCacheBounds()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetAutoParity(NormSessionHandle sessionHandle, unsigned char autoParity)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
|
|
@ -994,6 +1093,7 @@ void NormSetAutoParity(NormSessionHandle sessionHandle, unsigned char autoParity
|
|||
}
|
||||
} // end NormSetAutoParity()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttEstimate(NormSessionHandle sessionHandle,
|
||||
double grttEstimate)
|
||||
{
|
||||
|
|
@ -1006,6 +1106,7 @@ void NormSetGrttEstimate(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetGrttEstimate()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttMax(NormSessionHandle sessionHandle,
|
||||
double grttMax)
|
||||
{
|
||||
|
|
@ -1018,6 +1119,7 @@ void NormSetGrttMax(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetGrttMax()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttProbingMode(NormSessionHandle sessionHandle,
|
||||
NormProbingMode probingMode)
|
||||
{
|
||||
|
|
@ -1025,12 +1127,12 @@ void NormSetGrttProbingMode(NormSessionHandle sessionHandle,
|
|||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session)
|
||||
session->SetGrttProbingMode((NormSession::ProbingMode)probingMode);
|
||||
session->SetGrttProbingMode((NormSession::ProbingMode)probingMode);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
} // end NormSetGrttProbingMode()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
||||
double intervalMin,
|
||||
double intervalMax)
|
||||
|
|
@ -1044,6 +1146,34 @@ void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetGrttProbingInterval()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetBackoffFactor(NormSessionHandle sessionHandle,
|
||||
double backoffFactor)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (backoffFactor >= 0.0)
|
||||
session->SetBackoffFactor(backoffFactor);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
} // end NormSetBackoffFactor()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGroupSize(NormSessionHandle sessionHandle,
|
||||
unsigned int groupSize)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
session->ServerSetGroupSize((double)groupSize);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
} // end NormSetGroupSize()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||
const char* fileName,
|
||||
const char* infoPtr,
|
||||
|
|
@ -1064,6 +1194,7 @@ NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
|||
return objectHandle;
|
||||
} // end NormFileEnqueue()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
|
||||
const char* dataPtr,
|
||||
unsigned long dataLen,
|
||||
|
|
@ -1085,6 +1216,7 @@ NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
|
|||
return objectHandle;
|
||||
} // end NormDataEnqueue()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
|
||||
unsigned long bufferSize)
|
||||
{
|
||||
|
|
@ -1104,6 +1236,7 @@ NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
|
|||
return objectHandle;
|
||||
} // end NormStreamOpen()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamClose(NormObjectHandle streamHandle, bool graceful)
|
||||
{
|
||||
NormStreamObject* stream =
|
||||
|
|
@ -1126,6 +1259,7 @@ void NormStreamClose(NormObjectHandle streamHandle, bool graceful)
|
|||
}
|
||||
} // end NormStreamClose()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned int NormStreamWrite(NormObjectHandle streamHandle,
|
||||
const char* buffer,
|
||||
unsigned int numBytes)
|
||||
|
|
@ -1143,6 +1277,7 @@ unsigned int NormStreamWrite(NormObjectHandle streamHandle,
|
|||
return result;
|
||||
} // end NormStreamWrite()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamFlush(NormObjectHandle streamHandle,
|
||||
bool eom,
|
||||
NormFlushMode flushMode)
|
||||
|
|
@ -1163,6 +1298,7 @@ void NormStreamFlush(NormObjectHandle streamHandle,
|
|||
}
|
||||
} // end NormStreamFlush()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamSetAutoFlush(NormObjectHandle streamHandle,
|
||||
NormFlushMode flushMode)
|
||||
{
|
||||
|
|
@ -1172,6 +1308,7 @@ void NormStreamSetAutoFlush(NormObjectHandle streamHandle,
|
|||
stream->SetFlushMode((NormStreamObject::FlushMode)flushMode);
|
||||
} // end NormStreamSetAutoFlush()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamSetPushEnable(NormObjectHandle streamHandle, bool state)
|
||||
{
|
||||
NormStreamObject* stream =
|
||||
|
|
@ -1179,6 +1316,7 @@ void NormStreamSetPushEnable(NormObjectHandle streamHandle, bool state)
|
|||
if (stream) stream->SetPushMode(state);
|
||||
} // end NormStreamSetPushEnable()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStreamHasVacancy(NormObjectHandle streamHandle)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -1194,6 +1332,7 @@ bool NormStreamHasVacancy(NormObjectHandle streamHandle)
|
|||
return result;
|
||||
} // end NormStreamHasVacancy()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamMarkEom(NormObjectHandle streamHandle)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromObject(streamHandle);
|
||||
|
|
@ -1206,6 +1345,7 @@ void NormStreamMarkEom(NormObjectHandle streamHandle)
|
|||
}
|
||||
} // end NormStreamMarkEom()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetWatermark(NormSessionHandle sessionHandle,
|
||||
NormObjectHandle objectHandle)
|
||||
{
|
||||
|
|
@ -1240,6 +1380,7 @@ bool NormSetWatermark(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormSetWatermark()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
|
|
@ -1255,6 +1396,7 @@ bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormAddAckingNode()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
|
|
@ -1267,6 +1409,7 @@ void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormRemoveAckingNode()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
|
|
@ -1287,6 +1430,7 @@ NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
|
|||
|
||||
/** NORM Receiver Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStartReceiver(NormSessionHandle sessionHandle,
|
||||
unsigned long bufferSpace)
|
||||
{
|
||||
|
|
@ -1301,6 +1445,7 @@ bool NormStartReceiver(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormStartReceiver()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStopReceiver(NormSessionHandle sessionHandle)
|
||||
{
|
||||
|
||||
|
|
@ -1313,6 +1458,7 @@ void NormStopReceiver(NormSessionHandle sessionHandle)
|
|||
}
|
||||
} // end NormStopReceiver()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetRxSocketBuffer(NormSessionHandle sessionHandle,
|
||||
unsigned int bufferSize)
|
||||
{
|
||||
|
|
@ -1328,6 +1474,7 @@ bool NormSetRxSocketBuffer(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormSetRxSocketBuffer()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetSilentReceiver(NormSessionHandle sessionHandle,
|
||||
bool silent)
|
||||
{
|
||||
|
|
@ -1335,6 +1482,7 @@ void NormSetSilentReceiver(NormSessionHandle sessionHandle,
|
|||
if (session) session->ClientSetSilent(silent);
|
||||
} // end NormSetSilentReceiver()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle,
|
||||
bool unicastNacks)
|
||||
{
|
||||
|
|
@ -1342,6 +1490,7 @@ void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle,
|
|||
if (session) session->ClientSetUnicastNacks(unicastNacks);
|
||||
} // end NormSetDefaultUnicastNack()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeSetUnicastNack(NormNodeHandle nodeHandle,
|
||||
bool unicastNacks)
|
||||
{
|
||||
|
|
@ -1349,6 +1498,7 @@ void NormNodeSetUnicastNack(NormNodeHandle nodeHandle,
|
|||
if (node) node->SetUnicastNacks(unicastNacks);
|
||||
} // end NormNodeSetUnicastNack()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetDefaultNackingMode(NormSessionHandle sessionHandle,
|
||||
NormNackingMode nackingMode)
|
||||
{
|
||||
|
|
@ -1356,6 +1506,7 @@ void NormSetDefaultNackingMode(NormSessionHandle sessionHandle,
|
|||
if (session) session->ClientSetDefaultNackingMode((NormObject::NackingMode)nackingMode);
|
||||
} // end NormSetDefaultNackingMode()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeSetNackingMode(NormNodeHandle nodeHandle,
|
||||
NormNackingMode nackingMode)
|
||||
{
|
||||
|
|
@ -1363,6 +1514,7 @@ void NormNodeSetNackingMode(NormNodeHandle nodeHandle,
|
|||
if (node) node->SetDefaultNackingMode((NormObject::NackingMode)nackingMode);
|
||||
} // end NormNodeSetNackingMode()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectSetNackingMode(NormObjectHandle objectHandle,
|
||||
NormNackingMode nackingMode)
|
||||
{
|
||||
|
|
@ -1370,6 +1522,7 @@ void NormObjectSetNackingMode(NormObjectHandle objectHandle,
|
|||
if (object) object->SetNackingMode((NormObject::NackingMode)nackingMode);
|
||||
} // end NormObjectSetNackingMode()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle,
|
||||
NormRepairBoundary repairBoundary)
|
||||
{
|
||||
|
|
@ -1378,6 +1531,7 @@ void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle,
|
|||
session->ClientSetDefaultRepairBoundary((NormServerNode::RepairBoundary)repairBoundary);
|
||||
} // end NormSetDefaultRepairBoundary()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle,
|
||||
NormRepairBoundary repairBoundary)
|
||||
{
|
||||
|
|
@ -1386,6 +1540,7 @@ void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle,
|
|||
node->SetRepairBoundary((NormServerNode::RepairBoundary)repairBoundary);
|
||||
} // end NormNodeSetRepairBoundary()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStreamRead(NormObjectHandle streamHandle,
|
||||
char* buffer,
|
||||
unsigned int* numBytes)
|
||||
|
|
@ -1402,6 +1557,7 @@ bool NormStreamRead(NormObjectHandle streamHandle,
|
|||
return result;
|
||||
} // end NormStreamRead()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStreamSeekMsgStart(NormObjectHandle streamHandle)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -1418,6 +1574,7 @@ bool NormStreamSeekMsgStart(NormObjectHandle streamHandle)
|
|||
} // end NormStreamSeekMsgStart()
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle)
|
||||
{
|
||||
NormStreamObject* stream = static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
||||
|
|
@ -1430,6 +1587,7 @@ unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle)
|
|||
|
||||
/** NORM Object Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectType NormObjectGetType(NormObjectHandle objectHandle)
|
||||
{
|
||||
if (NORM_OBJECT_INVALID != objectHandle)
|
||||
|
|
@ -1438,16 +1596,19 @@ NormObjectType NormObjectGetType(NormObjectHandle objectHandle)
|
|||
return NORM_OBJECT_NONE;
|
||||
} // end NormObjectGetType()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormObjectHasInfo(NormObjectHandle objectHandle)
|
||||
{
|
||||
return ((NormObject*)objectHandle)->HasInfo();
|
||||
} // end NormObjectHasInfo()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned short NormObjectGetInfoLength(NormObjectHandle objectHandle)
|
||||
{
|
||||
return ((NormObject*)objectHandle)->GetInfoLength();
|
||||
} // end NormObjectGetInfoLength()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned short NormObjectGetInfo(NormObjectHandle objectHandle,
|
||||
char* buffer,
|
||||
unsigned short bufferLen)
|
||||
|
|
@ -1468,11 +1629,13 @@ unsigned short NormObjectGetInfo(NormObjectHandle objectHandle,
|
|||
return result;
|
||||
} // end NormObjectGetInfo()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormSize NormObjectGetSize(NormObjectHandle objectHandle)
|
||||
{
|
||||
return ((NormSize)((NormObject*)objectHandle)->GetSize().GetOffset());
|
||||
} // end NormObjectGetSize()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle)
|
||||
{
|
||||
NormSize bytesPending = 0;
|
||||
|
|
@ -1488,6 +1651,7 @@ NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle)
|
|||
return bytesPending;
|
||||
} // end NormObjectGetBytesPending()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectCancel(NormObjectHandle objectHandle)
|
||||
{
|
||||
if (NORM_OBJECT_INVALID != objectHandle)
|
||||
|
|
@ -1507,6 +1671,7 @@ void NormObjectCancel(NormObjectHandle objectHandle)
|
|||
}
|
||||
} // end NormObjectCancel()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectRetain(NormObjectHandle objectHandle)
|
||||
{
|
||||
if (NORM_OBJECT_INVALID != objectHandle)
|
||||
|
|
@ -1521,6 +1686,7 @@ void NormObjectRetain(NormObjectHandle objectHandle)
|
|||
}
|
||||
} // end NormRetainObject()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectRelease(NormObjectHandle objectHandle)
|
||||
{
|
||||
if (NORM_OBJECT_INVALID != objectHandle)
|
||||
|
|
@ -1536,6 +1702,7 @@ void NormObjectRelease(NormObjectHandle objectHandle)
|
|||
}
|
||||
} // end NormObjectRelease()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormFileGetName(NormObjectHandle fileHandle,
|
||||
char* nameBuffer,
|
||||
unsigned int bufferLen)
|
||||
|
|
@ -1554,6 +1721,7 @@ bool NormFileGetName(NormObjectHandle fileHandle,
|
|||
return result;
|
||||
} // end NormFileGetName()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormFileRename(NormObjectHandle fileHandle,
|
||||
const char* fileName)
|
||||
{
|
||||
|
|
@ -1570,6 +1738,7 @@ bool NormFileRename(NormObjectHandle fileHandle,
|
|||
return result;
|
||||
} // end NormFileRename()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
const char*volatile NormDataAccessData(NormObjectHandle dataHandle)
|
||||
{
|
||||
NormDataObject* dataObj =
|
||||
|
|
@ -1577,6 +1746,7 @@ const char*volatile NormDataAccessData(NormObjectHandle dataHandle)
|
|||
return dataObj->GetData();
|
||||
} // end NormDataAccessData()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
char* NormDataDetachData(NormObjectHandle dataHandle)
|
||||
{
|
||||
NormDataObject* dataObj =
|
||||
|
|
@ -1584,6 +1754,7 @@ char* NormDataDetachData(NormObjectHandle dataHandle)
|
|||
return dataObj->DetachData();
|
||||
} // end NormDataDetachData()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle)
|
||||
{
|
||||
return (NormNodeHandle)(((NormObject*)objectHandle)->GetServer());
|
||||
|
|
@ -1592,6 +1763,7 @@ NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle)
|
|||
|
||||
/** NORM Node Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormNodeId NormNodeGetId(NormNodeHandle nodeHandle)
|
||||
{
|
||||
NormNode* node = (NormNode*)nodeHandle;
|
||||
|
|
@ -1601,6 +1773,7 @@ NormNodeId NormNodeGetId(NormNodeHandle nodeHandle)
|
|||
return NORM_NODE_NONE;
|
||||
} // end NormNodeGetId()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormNodeGetAddress(NormNodeHandle nodeHandle,
|
||||
char* addrBuffer,
|
||||
unsigned int* bufferLen,
|
||||
|
|
@ -1632,6 +1805,7 @@ bool NormNodeGetAddress(NormNodeHandle nodeHandle,
|
|||
return result;
|
||||
} // end NormNodeGetId()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeRetain(NormNodeHandle nodeHandle)
|
||||
{
|
||||
if (NORM_NODE_INVALID != nodeHandle)
|
||||
|
|
@ -1646,6 +1820,7 @@ void NormNodeRetain(NormNodeHandle nodeHandle)
|
|||
}
|
||||
} // end NormNodeRetain()
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeRelease(NormNodeHandle nodeHandle)
|
||||
{
|
||||
if (NORM_NODE_INVALID != nodeHandle)
|
||||
|
|
@ -1675,6 +1850,7 @@ void NormNodeRelease(NormNodeHandle nodeHandle)
|
|||
// events with a "NormDispatchEvents()" call ...
|
||||
//
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned long NormCountCompletedObjects(NormSessionHandle sessionHandle)
|
||||
{
|
||||
unsigned long result = 0;
|
||||
|
|
|
|||
155
common/normApi.h
155
common/normApi.h
|
|
@ -1,12 +1,28 @@
|
|||
#ifndef _NORM_API
|
||||
#define _NORM_API
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTE: To use NORM as a DLL on Win32 platforms, the macro "NORM_USE_DLL" must be
|
||||
* defined. Otherwise, the static library "NormLib.lib" is built and should
|
||||
* be used for your code compilation and linking.
|
||||
********************************************************************************/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#ifdef NORM_USE_DLL
|
||||
#ifdef _NORM_API_BUILD
|
||||
#define NORM_API_LINKAGE __declspec(dllexport) // to support building of "Norm.dll"
|
||||
#else
|
||||
#define NORM_API_LINKAGE __declspec(dllimport) // to let apps use "Norm.dll" functions
|
||||
#endif // if/else _NORM_API_BUILD
|
||||
#else
|
||||
#define NORM_API_LINKAGE
|
||||
#endif // if/else NORM_USE_DLL
|
||||
#else
|
||||
#include <sys/types.h> // for "off_t"
|
||||
#endif // WIN32
|
||||
#define NORM_API_LINKAGE
|
||||
#endif // if/else WIN32/UNIX
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// IMPORTANT NOTICE
|
||||
|
|
@ -21,20 +37,26 @@
|
|||
|
||||
/** NORM API Types */
|
||||
typedef const void* NormInstanceHandle;
|
||||
extern const NormInstanceHandle NORM_INSTANCE_INVALID;
|
||||
extern NORM_API_LINKAGE
|
||||
const NormInstanceHandle NORM_INSTANCE_INVALID;
|
||||
|
||||
typedef const void* NormSessionHandle;
|
||||
extern const NormSessionHandle NORM_SESSION_INVALID;
|
||||
extern NORM_API_LINKAGE
|
||||
const NormSessionHandle NORM_SESSION_INVALID;
|
||||
typedef unsigned short NormSessionId;
|
||||
|
||||
typedef const void* NormNodeHandle;
|
||||
extern const NormNodeHandle NORM_NODE_INVALID;
|
||||
extern NORM_API_LINKAGE
|
||||
const NormNodeHandle NORM_NODE_INVALID;
|
||||
typedef unsigned long NormNodeId;
|
||||
extern const NormNodeId NORM_NODE_NONE;
|
||||
extern const NormNodeId NORM_NODE_ANY;
|
||||
extern NORM_API_LINKAGE
|
||||
const NormNodeId NORM_NODE_NONE;
|
||||
extern NORM_API_LINKAGE
|
||||
const NormNodeId NORM_NODE_ANY;
|
||||
|
||||
typedef const void* NormObjectHandle;
|
||||
extern const NormObjectHandle NORM_OBJECT_INVALID;
|
||||
extern NORM_API_LINKAGE
|
||||
const NormObjectHandle NORM_OBJECT_INVALID;
|
||||
typedef unsigned short NormObjectTransportId;
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
@ -43,6 +65,7 @@ typedef __int64 NormSize;
|
|||
typedef off_t NormSize;
|
||||
#endif // WIN32
|
||||
|
||||
NORM_API_LINKAGE
|
||||
enum NormObjectType
|
||||
{
|
||||
NORM_OBJECT_NONE,
|
||||
|
|
@ -50,7 +73,8 @@ enum NormObjectType
|
|||
NORM_OBJECT_FILE,
|
||||
NORM_OBJECT_STREAM
|
||||
};
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
enum NormFlushMode
|
||||
{
|
||||
NORM_FLUSH_NONE,
|
||||
|
|
@ -58,14 +82,15 @@ enum NormFlushMode
|
|||
NORM_FLUSH_ACTIVE
|
||||
};
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
enum NormNackingMode
|
||||
{
|
||||
NORM_NACK_NONE,
|
||||
NORM_NACK_INFO_ONLY,
|
||||
NORM_NACK_NORMAL
|
||||
};
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
enum NormAckingStatus
|
||||
{
|
||||
NORM_ACK_INVALID,
|
||||
|
|
@ -73,7 +98,8 @@ enum NormAckingStatus
|
|||
NORM_ACK_PENDING,
|
||||
NORM_ACK_SUCCESS
|
||||
};
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
enum NormProbingMode
|
||||
{
|
||||
NORM_PROBE_NONE,
|
||||
|
|
@ -81,12 +107,14 @@ enum NormProbingMode
|
|||
NORM_PROBE_ACTIVE
|
||||
};
|
||||
|
||||
NORM_API_LINKAGE
|
||||
enum NormRepairBoundary
|
||||
{
|
||||
NORM_BOUNDARY_BLOCK,
|
||||
NORM_BOUNDARY_OBJECT
|
||||
};
|
||||
|
||||
NORM_API_LINKAGE
|
||||
enum NormEventType
|
||||
{
|
||||
NORM_EVENT_INVALID = 0,
|
||||
|
|
@ -118,17 +146,26 @@ typedef struct
|
|||
|
||||
|
||||
/** NORM API General Initialization and Operation Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormInstanceHandle NormCreateInstance(bool priorityBoost = false);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormDestroyInstance(NormInstanceHandle instanceHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStopInstance(NormInstanceHandle instanceHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormRestartInstance(NormInstanceHandle instanceHandle);
|
||||
|
||||
// This MUST be set to enable NORM_OBJECT_FILE reception!
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetCacheDirectory(NormInstanceHandle instanceHandle,
|
||||
const char* cachePath);
|
||||
|
||||
// This call blocks until the next NormEvent is ready unless asynchronous
|
||||
// notification is used (see below)
|
||||
NORM_API_LINKAGE
|
||||
bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent);
|
||||
|
||||
// The "NormGetDescriptor()" function returns a HANDLE (WIN32) or
|
||||
|
|
@ -144,49 +181,67 @@ typedef HANDLE NormDescriptor;
|
|||
#else
|
||||
typedef int NormDescriptor;
|
||||
#endif // if/else WIN32/UNIX
|
||||
extern const NormDescriptor NORM_DESCRIPTOR_INVALID;
|
||||
extern NORM_API_LINKAGE
|
||||
const NormDescriptor NORM_DESCRIPTOR_INVALID;
|
||||
NORM_API_LINKAGE
|
||||
NormDescriptor NormGetDescriptor(NormInstanceHandle instanceHandle);
|
||||
|
||||
/** NORM Session Creation and Control Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
|
||||
const char* sessionAddress,
|
||||
unsigned short sessionPort,
|
||||
NormNodeId localNodeId);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormDestroySession(NormSessionHandle sessionHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetUserData(NormSessionHandle sessionHandle, const void* userData);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
const void* NormGetUserData(NormSessionHandle sessionHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTxPort(NormSessionHandle sessionHandle,
|
||||
unsigned short txPortNumber);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetRxPortReuse(NormSessionHandle sessionHandle,
|
||||
bool state);
|
||||
bool enable,
|
||||
bool bindToSessionAddress = true);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
|
||||
const char* interfaceName);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetTTL(NormSessionHandle sessionHandle,
|
||||
unsigned char ttl);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetTOS(NormSessionHandle sessionHandle,
|
||||
unsigned char tos);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetLoopback(NormSessionHandle sessionHandle,
|
||||
bool loopback);
|
||||
|
||||
// Special functions for debug support
|
||||
NORM_API_LINKAGE
|
||||
void NormSetMessageTrace(NormSessionHandle sessionHandle, bool state);
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTxLoss(NormSessionHandle sessionHandle, double percent);
|
||||
NORM_API_LINKAGE
|
||||
void NormSetRxLoss(NormSessionHandle sessionHandle, double percent);
|
||||
|
||||
/** NORM Sender Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStartSender(NormSessionHandle sessionHandle,
|
||||
NormSessionId sessionId,
|
||||
unsigned long bufferSpace,
|
||||
|
|
@ -194,47 +249,71 @@ bool NormStartSender(NormSessionHandle sessionHandle,
|
|||
unsigned char numData,
|
||||
unsigned char numParity);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStopSender(NormSessionHandle sessionHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
double NormGetTransmitRate(NormSessionHandle sessionHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTransmitRate(NormSessionHandle sessionHandle,
|
||||
double bitsPerSecond);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetTxSocketBuffer(NormSessionHandle sessionHandle,
|
||||
unsigned int bufferSize);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetCongestionControl(NormSessionHandle sessionHandle,
|
||||
bool state);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTransmitRateBounds(NormSessionHandle sessionHandle,
|
||||
double rateMin,
|
||||
double rateMax);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetTransmitCacheBounds(NormSessionHandle sessionHandle,
|
||||
NormSize sizeMax,
|
||||
unsigned long countMin,
|
||||
unsigned long countMax);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetAutoParity(NormSessionHandle sessionHandle,
|
||||
unsigned char autoParity);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttEstimate(NormSessionHandle sessionHandle,
|
||||
double grttEstimate);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttMax(NormSessionHandle sessionHandle,
|
||||
double grttMax);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttProbingMode(NormSessionHandle sessionHandle,
|
||||
NormProbingMode probingMode);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
||||
double intervalMin,
|
||||
double intervalMax);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetBackoffFactor(NormSessionHandle sessionHandle,
|
||||
double backoffFactor);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetGroupSize(NormSessionHandle sessionHandle,
|
||||
unsigned int groupSize);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||
const char* fileName,
|
||||
const char* infoPtr = (const char*)0,
|
||||
unsigned int infoLen = 0);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
|
||||
const char* dataPtr,
|
||||
unsigned long dataLen,
|
||||
|
|
@ -242,138 +321,182 @@ NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
|
|||
unsigned int infoLen = 0);
|
||||
|
||||
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
|
||||
unsigned long bufferSize);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamClose(NormObjectHandle streamHandle, bool graceful = false);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned int NormStreamWrite(NormObjectHandle streamHandle,
|
||||
const char* buffer,
|
||||
unsigned int numBytes);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamFlush(NormObjectHandle streamHandle,
|
||||
bool eom = false,
|
||||
NormFlushMode flushMode = NORM_FLUSH_PASSIVE);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamSetAutoFlush(NormObjectHandle streamHandle,
|
||||
NormFlushMode flushMode);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamSetPushEnable(NormObjectHandle streamHandle,
|
||||
bool pushEnable);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStreamHasVacancy(NormObjectHandle streamHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStreamMarkEom(NormObjectHandle streamHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetWatermark(NormSessionHandle sessionHandle,
|
||||
NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId = NORM_NODE_ANY);
|
||||
|
||||
/* NORM Receiver Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStartReceiver(NormSessionHandle sessionHandle,
|
||||
unsigned long bufferSpace);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormStopReceiver(NormSessionHandle sessionHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormSetRxSocketBuffer(NormSessionHandle sessionHandle,
|
||||
unsigned int bufferSize);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetSilentReceiver(NormSessionHandle sessionHandle,
|
||||
bool silent);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle,
|
||||
bool unicastNacks);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeSetUnicastNack(NormNodeHandle remoteSender,
|
||||
bool unicastNacks);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetDefaultNackingMode(NormSessionHandle sessionHandle,
|
||||
NormNackingMode nackingMode);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeSetNackingMode(NormNodeHandle nodeHandle,
|
||||
NormNackingMode nackingMode);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectSetNackingMode(NormObjectHandle objectHandle,
|
||||
NormNackingMode nackingMode);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle,
|
||||
NormRepairBoundary repairBoundary);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle,
|
||||
NormRepairBoundary repairBoundary);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStreamRead(NormObjectHandle streamHandle,
|
||||
char* buffer,
|
||||
unsigned int* numBytes);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormStreamSeekMsgStart(NormObjectHandle streamHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle);
|
||||
|
||||
|
||||
/** NORM Object Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormObjectType NormObjectGetType(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormObjectHasInfo(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned short NormObjectGetInfoLength(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned short NormObjectGetInfo(NormObjectHandle objectHandle,
|
||||
char* buffer,
|
||||
unsigned short bufferLen);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormSize NormObjectGetSize(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectCancel(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectRetain(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormObjectRelease(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormFileGetName(NormObjectHandle fileHandle,
|
||||
char* nameBuffer,
|
||||
unsigned int bufferLen);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormFileRename(NormObjectHandle fileHandle,
|
||||
const char* fileName);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
const char*volatile NormDataAccessData(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
char* NormDataDetachData(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
char* NormGetData(NormObjectHandle dataHandle);
|
||||
|
||||
/** NORM Node Functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
NormNodeId NormNodeGetId(NormNodeHandle nodeHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
bool NormNodeGetAddress(NormNodeHandle nodeHandle,
|
||||
char* addrBuffer,
|
||||
unsigned int* bufferLen,
|
||||
unsigned short* port = (unsigned short*)0);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeRetain(NormNodeHandle nodeHandle);
|
||||
|
||||
NORM_API_LINKAGE
|
||||
void NormNodeRelease(NormNodeHandle nodeHandle);
|
||||
|
||||
/** Some experimental functions */
|
||||
|
||||
NORM_API_LINKAGE
|
||||
unsigned long NormCountCompletedObjects(NormSessionHandle sessionHandle);
|
||||
|
||||
|
||||
#endif // _NORM_API
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class NormApp : public NormController, public ProtoApp
|
|||
// application parameters
|
||||
FILE* input; // input stream
|
||||
FILE* output; // output stream
|
||||
char input_buffer[1250];
|
||||
char input_buffer[65535];
|
||||
unsigned int input_index;
|
||||
unsigned int input_length;
|
||||
bool input_active;
|
||||
|
|
@ -78,7 +78,7 @@ class NormApp : public NormController, public ProtoApp
|
|||
bool input_messaging; // stream input mode
|
||||
UINT16 input_msg_length;
|
||||
UINT16 input_msg_index;
|
||||
char output_buffer[65536];
|
||||
char output_buffer[65535];
|
||||
UINT16 output_index;
|
||||
bool output_messaging;
|
||||
UINT16 output_msg_length;
|
||||
|
|
@ -104,6 +104,7 @@ class NormApp : public NormController, public ProtoApp
|
|||
double group_size;
|
||||
unsigned long tx_buffer_size; // bytes
|
||||
NormFileList tx_file_list;
|
||||
bool tx_one_shot;
|
||||
double tx_object_interval;
|
||||
int tx_repeat_count;
|
||||
double tx_repeat_interval;
|
||||
|
|
@ -140,7 +141,7 @@ NormApp::NormApp()
|
|||
backoff_factor(NormSession::DEFAULT_BACKOFF_FACTOR),
|
||||
grtt_estimate(NormSession::DEFAULT_GRTT_ESTIMATE),
|
||||
group_size(NormSession::DEFAULT_GSIZE_ESTIMATE),
|
||||
tx_buffer_size(1024*1024),
|
||||
tx_buffer_size(1024*1024), tx_one_shot(false),
|
||||
tx_object_interval(0.0), tx_repeat_count(0), tx_repeat_interval(2.0), tx_repeat_clear(true),
|
||||
rx_buffer_size(1024*1024), rx_sock_buffer_size(0),
|
||||
rx_cache_path(NULL), post_processor(NULL), unicast_nacks(false), silent_client(false),
|
||||
|
|
@ -211,6 +212,7 @@ const char* const NormApp::cmd_list[] =
|
|||
"+interval", // delay time (sec) between files (0.0 sec default)
|
||||
"+repeatcount", // How many times to repeat the file/directory list tx
|
||||
"+rinterval", // Interval (sec) between file/directory list repeats
|
||||
"-oneshot", // Transmit file(s), exiting upon TX_FLUSH_COMPLETED
|
||||
"-updatesOnly", // only send updated files on repeat transmission
|
||||
"+rxcachedir", // recv file cache directory
|
||||
"+segment", // payload segment size (bytes)
|
||||
|
|
@ -260,6 +262,7 @@ void NormApp::ShowHelp()
|
|||
" +interval, // delay time (sec) between files (0.0 sec default)\n"
|
||||
" +repeatcount, // How many times to repeat the file/directory list tx\n"
|
||||
" +rinterval, // Interval (sec) between file/directory list repeats\n"
|
||||
" -oneshot, // Exit upon sender TX_FLUSH_COMPLETED event (sender exits after transmission)\n"
|
||||
" -updatesOnly, // only send updated files on repeat transmission\n"
|
||||
" +rxcachedir, // recv file cache directory\n"
|
||||
" +segment, // payload segment size (bytes)\n"
|
||||
|
|
@ -628,6 +631,10 @@ bool NormApp::OnCommand(const char* cmd, const char* val)
|
|||
tx_repeat_interval = 0.0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!strncmp("oneshot", cmd, len))
|
||||
{
|
||||
tx_one_shot = true;
|
||||
}
|
||||
else if (!strncmp("updatesOnly", cmd, len))
|
||||
{
|
||||
|
|
@ -915,7 +922,7 @@ void NormApp::OnInputReady()
|
|||
{
|
||||
if (input_msg_length)
|
||||
{
|
||||
UINT16 bufferSpace = 1024 - input_index;
|
||||
UINT16 bufferSpace = 65535 - input_index;
|
||||
UINT16 msgRemainder = input_msg_length - input_msg_index;
|
||||
readLength = MIN(bufferSpace, msgRemainder);
|
||||
}
|
||||
|
|
@ -928,14 +935,14 @@ void NormApp::OnInputReady()
|
|||
memcpy(&input_msg_length, input_buffer, 2);
|
||||
input_msg_length = ntohs(input_msg_length);
|
||||
ASSERT(input_msg_length >= 2);
|
||||
UINT16 bufferSpace = 1024 - input_index;
|
||||
UINT16 bufferSpace = 65535 - input_index;
|
||||
UINT16 msgRemainder = input_msg_length - 2;
|
||||
readLength = MIN(bufferSpace, msgRemainder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
readLength = 1024;
|
||||
readLength = segment_size;
|
||||
}
|
||||
|
||||
// Read from "input" into our "input_buffer"
|
||||
|
|
@ -1005,21 +1012,21 @@ void NormApp::OnInputReady()
|
|||
|
||||
if (writeLength || endOfStream)
|
||||
{
|
||||
unsigned int wroteLength = tx_stream->Write(input_buffer+input_index,
|
||||
unsigned int wroteLength = tx_stream->Write(input_buffer+input_index,
|
||||
writeLength, false);
|
||||
input_length -= wroteLength;
|
||||
if (0 == input_length)
|
||||
input_index = 0;
|
||||
else
|
||||
input_index += wroteLength;
|
||||
if (input_messaging)
|
||||
if (input_messaging && (0 != wroteLength))
|
||||
{
|
||||
input_msg_index += wroteLength;
|
||||
if (input_msg_index == input_msg_length)
|
||||
{
|
||||
input_msg_index = 0;
|
||||
input_msg_length = 0;
|
||||
// Mark EOM _and_ flush
|
||||
// Mark EOM
|
||||
tx_stream->Write(NULL, 0, true);
|
||||
// No need to explicitly flush with "flush mode" set.
|
||||
//tx_stream->Flush();
|
||||
|
|
@ -1071,12 +1078,20 @@ void NormApp::Notify(NormController::Event event,
|
|||
{
|
||||
switch (event)
|
||||
{
|
||||
case TX_QUEUE_VACANCY:
|
||||
if (NULL != object)
|
||||
{
|
||||
if (input && (object == tx_stream))
|
||||
OnInputReady();
|
||||
}
|
||||
break;
|
||||
case TX_QUEUE_EMPTY:
|
||||
// Write to stream as needed
|
||||
//DMSG(0, "NormApp::Notify(TX_QUEUE_EMPTY) ...\n");
|
||||
if (object && (object == tx_stream))
|
||||
if (NULL != object)
|
||||
{
|
||||
if (input) OnInputReady();
|
||||
if (input && (object == tx_stream))
|
||||
OnInputReady();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1088,6 +1103,14 @@ void NormApp::Notify(NormController::Event event,
|
|||
OnIntervalTimeout(interval_timer);
|
||||
}
|
||||
break;
|
||||
|
||||
case TX_FLUSH_COMPLETED:
|
||||
if (tx_one_shot)
|
||||
{
|
||||
DMSG(0, "norm: transmit flushing completed, exiting.\n");
|
||||
Stop();
|
||||
}
|
||||
break;
|
||||
|
||||
case RX_OBJECT_NEW:
|
||||
{
|
||||
|
|
@ -1296,15 +1319,15 @@ void NormApp::Notify(NormController::Event event,
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (readLength > 0)
|
||||
{
|
||||
output_msg_sync = true;
|
||||
output_index += readLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readLength > 0) output_msg_sync = true;
|
||||
}
|
||||
|
||||
if (readLength)
|
||||
output_index += readLength;
|
||||
else
|
||||
reading = false;
|
||||
}
|
||||
|
||||
unsigned int writeLength;
|
||||
if (output_messaging)
|
||||
|
|
@ -1354,9 +1377,13 @@ void NormApp::Notify(NormController::Event event,
|
|||
}
|
||||
}
|
||||
} // end while(put < nBytes)
|
||||
if (writeLength) memset(output_buffer, 0, writeLength);
|
||||
if (writeLength > 0)
|
||||
{
|
||||
memset(output_buffer, 0, writeLength); // why did do this?
|
||||
fflush(output);
|
||||
}
|
||||
} // end while (reading)
|
||||
fflush(output);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include "normEncoder.h"
|
||||
#include "galois.h" // for Galois math routines
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef SIMULATE
|
||||
#include "normMessage.h"
|
||||
|
|
@ -44,14 +43,14 @@
|
|||
|
||||
NormEncoder::NormEncoder()
|
||||
: npar(0), vector_size(0),
|
||||
genPoly(NULL), scratch(NULL)
|
||||
gen_poly(NULL), scratch(NULL)
|
||||
{
|
||||
|
||||
} // end NormEncoder::NormEncoder()
|
||||
|
||||
NormEncoder::~NormEncoder()
|
||||
{
|
||||
if (genPoly) Destroy();
|
||||
if (gen_poly) Destroy();
|
||||
}
|
||||
|
||||
bool NormEncoder::Init(int numParity, int vecSizeMax)
|
||||
|
|
@ -59,7 +58,7 @@ bool NormEncoder::Init(int numParity, int vecSizeMax)
|
|||
// Debugging assertions
|
||||
ASSERT((numParity>=0)&&(numParity<129));
|
||||
ASSERT(vecSizeMax >= 0);
|
||||
if (genPoly) Destroy();
|
||||
if (gen_poly) Destroy();
|
||||
npar = numParity;
|
||||
|
||||
#ifdef SIMULATE
|
||||
|
|
@ -67,10 +66,10 @@ bool NormEncoder::Init(int numParity, int vecSizeMax)
|
|||
#endif // SIMUATE
|
||||
|
||||
vector_size = vecSizeMax;
|
||||
// Create generator polynomial
|
||||
// Create gen_poly polynomial
|
||||
if(!CreateGeneratorPolynomial())
|
||||
{
|
||||
DMSG(0, "NormEncoder: Error creating generator polynomial!\n");
|
||||
DMSG(0, "NormEncoder: Error creating gen_poly polynomial!\n");
|
||||
return false;
|
||||
}
|
||||
// Allocate scratch space for encoding
|
||||
|
|
@ -92,10 +91,10 @@ void NormEncoder::Destroy()
|
|||
delete[] scratch;
|
||||
scratch = NULL;
|
||||
}
|
||||
if (NULL != genPoly)
|
||||
if (NULL != gen_poly)
|
||||
{
|
||||
delete[] genPoly;
|
||||
genPoly = NULL;
|
||||
delete[] gen_poly;
|
||||
gen_poly = NULL;
|
||||
}
|
||||
} // end NormEncoder::Destroy()
|
||||
|
||||
|
|
@ -104,27 +103,27 @@ bool NormEncoder::CreateGeneratorPolynomial()
|
|||
{
|
||||
unsigned char *tp, *tp1, *tp2;
|
||||
int degree = 2*npar;
|
||||
if(genPoly) delete genPoly;
|
||||
if(gen_poly) delete gen_poly;
|
||||
|
||||
if(!(genPoly = new unsigned char[npar+1]))
|
||||
if(!(gen_poly = new unsigned char[npar+1]))
|
||||
{
|
||||
DMSG(0, "NormEncoder: Error allocating memory for generator polynomial: %s\n",
|
||||
DMSG(0, "NormEncoder: Error allocating memory for gen_poly polynomial: %s\n",
|
||||
GetErrorString());
|
||||
return false;
|
||||
}
|
||||
/* Allocate memory for temporary polynomial arrays */
|
||||
if(!(tp = new unsigned char[2*degree]))
|
||||
{
|
||||
DMSG(0, "NormEncoder: Error allocating memory while computing genpoly: %s\n",
|
||||
DMSG(0, "NormEncoder: Error allocating memory while computing gen_poly: %s\n",
|
||||
GetErrorString());
|
||||
delete genPoly;
|
||||
delete gen_poly;
|
||||
return false;
|
||||
}
|
||||
if(!(tp1 = new unsigned char[2*degree]))
|
||||
{
|
||||
delete tp;
|
||||
delete genPoly;
|
||||
DMSG(0, "NormEncoder: Error allocating memory while computing genpoly: %s\n",
|
||||
delete gen_poly;
|
||||
DMSG(0, "NormEncoder: Error allocating memory while computing gen_poly: %s\n",
|
||||
GetErrorString());
|
||||
return false;
|
||||
}
|
||||
|
|
@ -132,8 +131,8 @@ bool NormEncoder::CreateGeneratorPolynomial()
|
|||
{
|
||||
delete tp1;
|
||||
delete tp;
|
||||
delete genPoly;
|
||||
DMSG(0, "NormEncoder: Error allocating memory while computing genpoly: %s\n",
|
||||
delete gen_poly;
|
||||
DMSG(0, "NormEncoder: Error allocating memory while computing gen_poly: %s\n",
|
||||
GetErrorString());
|
||||
return false;
|
||||
}
|
||||
|
|
@ -146,7 +145,7 @@ bool NormEncoder::CreateGeneratorPolynomial()
|
|||
tp[0] = gexp(n); // set up x+a^n
|
||||
tp[1] = 1;
|
||||
// Polynomial multiplication
|
||||
memset(genPoly, 0, (npar+1)*sizeof(unsigned char));
|
||||
memset(gen_poly, 0, (npar+1)*sizeof(unsigned char));
|
||||
for (int i = 0; i < degree; i++)
|
||||
{
|
||||
memset(&tp2[degree], 0, degree*sizeof(unsigned char));
|
||||
|
|
@ -157,9 +156,9 @@ bool NormEncoder::CreateGeneratorPolynomial()
|
|||
for (j = (degree*2)-1; j >= i; j--) tp2[j] = tp2[j-i];
|
||||
memset(tp2, 0, i*sizeof(unsigned char));
|
||||
// Add into partial product
|
||||
for(j=0; j < (npar+1); j++) genPoly[j] ^= tp2[j];
|
||||
for(j=0; j < (npar+1); j++) gen_poly[j] ^= tp2[j];
|
||||
}
|
||||
memcpy(tp1, genPoly, (npar+1)*sizeof(unsigned char));
|
||||
memcpy(tp1, gen_poly, (npar+1)*sizeof(unsigned char));
|
||||
memset(&tp1[npar+1], 0, (2*degree)-(npar+1));
|
||||
}
|
||||
delete tp2;
|
||||
|
|
@ -178,7 +177,7 @@ void NormEncoder::Encode(const char *data, char **pVec)
|
|||
int i, j;
|
||||
unsigned char *userData, *LSFR1, *LSFR2, *pVec0;
|
||||
int npar_minus_one = npar - 1;
|
||||
unsigned char *gen_poly = &genPoly[npar_minus_one];
|
||||
unsigned char* genPoly = &gen_poly[npar_minus_one];
|
||||
ASSERT(scratch); // Make sure it's been init'd first
|
||||
// Assumes parity vectors are zero-filled at block start !!!
|
||||
// Copy pVec[0] for use in calculations
|
||||
|
|
@ -200,15 +199,15 @@ void NormEncoder::Encode(const char *data, char **pVec)
|
|||
LSFR2 = (unsigned char *) pVec[i+1];
|
||||
for(j = 0; j < vecSize; j++)
|
||||
*LSFR1++ = *LSFR2++ ^
|
||||
gmult(*gen_poly, (*userData++ ^ *pVec0++));
|
||||
gen_poly--;
|
||||
gmult(*genPoly, (*userData++ ^ *pVec0++));
|
||||
genPoly--;
|
||||
}
|
||||
}
|
||||
pVec0 = scratch;
|
||||
userData = (unsigned char *) data;
|
||||
LSFR1 = (unsigned char *) pVec[npar_minus_one];
|
||||
for(j = 0; j < vecSize; j++)
|
||||
*LSFR1++ = gmult(*gen_poly, (*userData++ ^ *pVec0++));
|
||||
*LSFR1++ = gmult(*genPoly, (*userData++ ^ *pVec0++));
|
||||
} // end NormEncoder::Encode()
|
||||
|
||||
|
||||
|
|
@ -217,15 +216,15 @@ void NormEncoder::Encode(const char *data, char **pVec)
|
|||
*/
|
||||
|
||||
NormDecoder::NormDecoder()
|
||||
: npar(0), vector_size(0), Lambda(NULL),
|
||||
sVec(NULL), oVec(NULL), scratch(NULL)
|
||||
: npar(0), vector_size(0), lambda(NULL),
|
||||
s_vec(NULL), o_vec(NULL), scratch(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NormDecoder::~NormDecoder()
|
||||
{
|
||||
if (Lambda) Destroy();
|
||||
if (lambda) Destroy();
|
||||
}
|
||||
|
||||
bool NormDecoder::Init(int numParity, int vecSizeMax)
|
||||
|
|
@ -238,22 +237,22 @@ bool NormDecoder::Init(int numParity, int vecSizeMax)
|
|||
vecSizeMax = MIN(SIM_PAYLOAD_MAX+1, vecSizeMax);
|
||||
#endif // SIMUATE
|
||||
|
||||
if (Lambda) Destroy(); // Check if already inited ...
|
||||
if (lambda) Destroy(); // Check if already inited ...
|
||||
|
||||
npar = numParity;
|
||||
vector_size = vecSizeMax;
|
||||
|
||||
if(!(Lambda = new unsigned char[2*npar]))
|
||||
if(!(lambda = new unsigned char[2*npar]))
|
||||
{
|
||||
DMSG(0, "NormDecoder: Error allocating memory for Lambda: %s\n",
|
||||
DMSG(0, "NormDecoder: Error allocating memory for lambda: %s\n",
|
||||
GetErrorString());
|
||||
return(false);
|
||||
}
|
||||
|
||||
/* Allocate memory for sVec ptr and the syndrome vectors */
|
||||
if(!(sVec = new unsigned char*[npar]))
|
||||
/* Allocate memory for s_vec ptr and the syndrome vectors */
|
||||
if(!(s_vec = new unsigned char*[npar]))
|
||||
{
|
||||
DMSG(0, "NormDecoder: Error allocating memory for sVec ptr: %s\n",
|
||||
DMSG(0, "NormDecoder: Error allocating memory for s_vec ptr: %s\n",
|
||||
GetErrorString());
|
||||
Destroy();
|
||||
return(false);
|
||||
|
|
@ -261,19 +260,19 @@ bool NormDecoder::Init(int numParity, int vecSizeMax)
|
|||
int i;
|
||||
for(i=0; i < npar; i++)
|
||||
{
|
||||
if(!(sVec[i] = new unsigned char[vecSizeMax]))
|
||||
if(!(s_vec[i] = new unsigned char[vecSizeMax]))
|
||||
{
|
||||
DMSG(0, "NormDecoder: Error allocating memory for new sVec: %s\n",
|
||||
DMSG(0, "NormDecoder: Error allocating memory for new s_vec: %s\n",
|
||||
GetErrorString());
|
||||
Destroy();
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory for the oVec ptr and the Omega vectors */
|
||||
if(!(oVec = new unsigned char*[npar]))
|
||||
/* Allocate memory for the o_vec ptr and the Omega vectors */
|
||||
if(!(o_vec = new unsigned char*[npar]))
|
||||
{
|
||||
DMSG(0, "NormDecoder: Error allocating memory for new oVec ptr: %s\n",
|
||||
DMSG(0, "NormDecoder: Error allocating memory for new o_vec ptr: %s\n",
|
||||
GetErrorString());
|
||||
Destroy();
|
||||
return(false);
|
||||
|
|
@ -281,9 +280,9 @@ bool NormDecoder::Init(int numParity, int vecSizeMax)
|
|||
|
||||
for(i=0; i < npar; i++)
|
||||
{
|
||||
if(!(oVec[i] = new unsigned char[vecSizeMax]))
|
||||
if(!(o_vec[i] = new unsigned char[vecSizeMax]))
|
||||
{
|
||||
DMSG(0, "NormDecoder: Error allocating memory for new oVec: %s",
|
||||
DMSG(0, "NormDecoder: Error allocating memory for new o_vec: %s",
|
||||
GetErrorString());
|
||||
Destroy();
|
||||
return(false);
|
||||
|
|
@ -307,25 +306,25 @@ void NormDecoder::Destroy()
|
|||
delete scratch;
|
||||
scratch = NULL;
|
||||
}
|
||||
if(oVec)
|
||||
if(o_vec)
|
||||
{
|
||||
for(int i=0; i<npar; i++)
|
||||
if (oVec[i]) delete oVec[i];
|
||||
delete oVec;
|
||||
oVec = NULL;
|
||||
if (o_vec[i]) delete o_vec[i];
|
||||
delete o_vec;
|
||||
o_vec = NULL;
|
||||
}
|
||||
if(sVec)
|
||||
if(s_vec)
|
||||
{
|
||||
for(int i = 0; i < npar; i++)
|
||||
if (sVec[i]) delete sVec[i];
|
||||
delete sVec;
|
||||
sVec = NULL;
|
||||
if (s_vec[i]) delete s_vec[i];
|
||||
delete s_vec;
|
||||
s_vec = NULL;
|
||||
}
|
||||
if (Lambda)
|
||||
if (lambda)
|
||||
{
|
||||
|
||||
delete Lambda;
|
||||
Lambda = NULL;
|
||||
delete lambda;
|
||||
lambda = NULL;
|
||||
}
|
||||
} // end NormDecoder::Destroy()
|
||||
|
||||
|
|
@ -334,7 +333,7 @@ void NormDecoder::Destroy()
|
|||
int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* erasureLocs)
|
||||
{
|
||||
// Debugging assertions
|
||||
ASSERT(Lambda);
|
||||
ASSERT(lambda);
|
||||
ASSERT(erasureCount && (erasureCount<=npar));
|
||||
|
||||
// (A) Compute syndrome vectors
|
||||
|
|
@ -353,7 +352,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
|||
for (i = 0; i < npar; i++)
|
||||
{
|
||||
int X = gexp(i+1);
|
||||
unsigned char* synVec = sVec[i];
|
||||
unsigned char* synVec = s_vec[i];
|
||||
memset(synVec, 0, vecSize*sizeof(char));
|
||||
for(int j = 0; j < nvecs; j++)
|
||||
{
|
||||
|
|
@ -367,29 +366,29 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
|||
}
|
||||
}
|
||||
|
||||
// (B) Init Lambda (the erasure locator polynomial)
|
||||
// (B) Init lambda (the erasure locator polynomial)
|
||||
int degree = 2*npar;
|
||||
int nvecsMinusOne = nvecs - 1;
|
||||
memset(Lambda, 0, degree*sizeof(char));
|
||||
Lambda[0] = 1;
|
||||
memset(lambda, 0, degree*sizeof(char));
|
||||
lambda[0] = 1;
|
||||
for (i = 0; i < erasureCount; i++)
|
||||
{
|
||||
int X = gexp(nvecsMinusOne - erasureLocs[i]);
|
||||
for(int j = (degree-1); j > 0; j--)
|
||||
Lambda[j] = Lambda[j] ^ gmult(X, Lambda[j-1]);
|
||||
lambda[j] = lambda[j] ^ gmult(X, lambda[j-1]);
|
||||
}
|
||||
|
||||
// (C) Compute modified Omega using Lambda
|
||||
// (C) Compute modified Omega using lambda
|
||||
for(i = 0; i < npar; i++)
|
||||
{
|
||||
int k = i;
|
||||
memset(oVec[i], 0, vecSize*sizeof(char));
|
||||
memset(o_vec[i], 0, vecSize*sizeof(char));
|
||||
int m = i + 1;
|
||||
for(int j = 0; j < m; j++)
|
||||
{
|
||||
unsigned char* Omega = oVec[i];
|
||||
unsigned char* S = sVec[j];
|
||||
int Lk = Lambda[k--];
|
||||
unsigned char* Omega = o_vec[i];
|
||||
unsigned char* S = s_vec[j];
|
||||
int Lk = lambda[k--];
|
||||
for(int n = 0; n < vecSize; n++)
|
||||
*Omega++ ^= gmult(*S++, Lk);
|
||||
}
|
||||
|
|
@ -401,13 +400,13 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
|||
// Only fill _data_ erasures
|
||||
if (erasureLocs[i] >= ndata) break;//return erasureCount;
|
||||
|
||||
// evaluate Lambda' (derivative) at alpha^(-i)
|
||||
// evaluate lambda' (derivative) at alpha^(-i)
|
||||
// ( all odd powers disappear)
|
||||
int k = nvecsMinusOne - erasureLocs[i];
|
||||
int denom = 0;
|
||||
int j;
|
||||
for (j = 1; j < degree; j += 2)
|
||||
denom ^= gmult(Lambda[j], gexp(((255-k)*(j-1)) % 255));
|
||||
denom ^= gmult(lambda[j], gexp(((255-k)*(j-1)) % 255));
|
||||
// Invert for use computing error value below
|
||||
denom = ginv(denom);
|
||||
|
||||
|
|
@ -416,7 +415,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
|||
for (j = 0; j < npar; j++)
|
||||
{
|
||||
unsigned char* data = eVec;
|
||||
unsigned char* Omega = oVec[j];
|
||||
unsigned char* Omega = o_vec[j];
|
||||
int X = gexp(((255-k)*j) % 255);
|
||||
for(int n = 0; n < vecSize; n++)
|
||||
*data++ ^= gmult(*Omega++, X);
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ class NormEncoder
|
|||
{
|
||||
// Members
|
||||
private:
|
||||
int npar; // No. of parity packets (N-k)
|
||||
int npar; // No. of parity packets (n-k)
|
||||
int vector_size; // Size of biggest vector to encode
|
||||
unsigned char* genPoly; // Ptr to generator polynomial
|
||||
unsigned char* gen_poly; // Ptr to generator polynomial
|
||||
unsigned char* scratch; // scratch space for encoding
|
||||
|
||||
// Methods
|
||||
|
|
@ -50,7 +50,8 @@ class NormEncoder
|
|||
~NormEncoder();
|
||||
bool Init(int numParity, int vectorSize);
|
||||
void Destroy();
|
||||
bool IsReady(){return (bool)(genPoly != NULL);}
|
||||
bool IsReady(){return (bool)(gen_poly != NULL);}
|
||||
// "Encode" must be called in order of source vector0, vector1, vector2, etc
|
||||
void Encode(const char *dataVector, char **parityVectorList);
|
||||
int NumParity() {return npar;}
|
||||
int VectorSize() {return vector_size;}
|
||||
|
|
@ -64,18 +65,18 @@ class NormDecoder
|
|||
{
|
||||
// Members
|
||||
private:
|
||||
int npar; // No. of parity packets (n-K)
|
||||
int npar; // No. of parity packets (n-k)
|
||||
int vector_size; // Size of biggest vector to encode
|
||||
unsigned char* Lambda; // Erasure location polynomial ("2*npar" ints)
|
||||
unsigned char** sVec; // Syndrome vectors (pointers to "npar" vectors)
|
||||
unsigned char** oVec; // Omega vectors (pointers to "npar" vectors)
|
||||
unsigned char* lambda; // Erasure location polynomial ("2*npar" ints)
|
||||
unsigned char** s_vec; // Syndrome vectors (pointers to "npar" vectors)
|
||||
unsigned char** o_vec; // Omega vectors (pointers to "npar" vectors)
|
||||
unsigned char* scratch;
|
||||
// Methods
|
||||
public:
|
||||
NormDecoder();
|
||||
~NormDecoder();
|
||||
bool Init(int numParity, int vectorSize);
|
||||
int Decode(char **vectorList, int ndata, UINT16 erasureCount, UINT16* erasureLocs);
|
||||
int Decode(char** vectorList, int ndata, UINT16 erasureCount, UINT16* erasureLocs);
|
||||
int NumParity() {return npar;}
|
||||
int VectorSize() {return vector_size;}
|
||||
void Destroy();
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ void NormFile::Close()
|
|||
close(fd);
|
||||
fd = -1;
|
||||
#endif // if/else WIN32
|
||||
|
||||
}
|
||||
} // end NormFile::Close()
|
||||
|
||||
|
|
@ -332,35 +331,52 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
|||
}
|
||||
} // end NormFile::Rename()
|
||||
|
||||
int NormFile::Read(char* buffer, int len)
|
||||
size_t NormFile::Read(char* buffer, size_t len)
|
||||
{
|
||||
ASSERT(IsOpen());
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32_WCE
|
||||
size_t result = fread(buffer, 1, len, file_ptr);
|
||||
#else
|
||||
int result = _read(fd, buffer, len);
|
||||
size_t result = _read(fd, buffer, (unsigned int)len);
|
||||
#endif // if/else _WIN32_WCE
|
||||
#else
|
||||
int result = read(fd, buffer, len);
|
||||
ssize_t result = read(fd, buffer, len);
|
||||
#endif // if/else WIN32
|
||||
if (result > 0) offset += (Offset)result;
|
||||
return result;
|
||||
if (result < 0)
|
||||
{
|
||||
DMSG(0, "NormFile::Read() read(%d) error: %s (fd = %d, offset:%d)\n", len, GetErrorString(), fd, offset);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset += (Offset)result;
|
||||
return result;
|
||||
}
|
||||
} // end NormFile::Read()
|
||||
|
||||
int NormFile::Write(const char* buffer, int len)
|
||||
size_t NormFile::Write(const char* buffer, size_t len)
|
||||
{
|
||||
ASSERT(IsOpen());
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32_WCE
|
||||
size_t result = fwrite(buffer, 1, len, file_ptr);
|
||||
#else
|
||||
int result = _write(fd, buffer, len);
|
||||
size_t result = _write(fd, buffer, (unsigned int)len);
|
||||
#endif // if/else _WIN32_WCE
|
||||
#else
|
||||
int result = write(fd, buffer, len);
|
||||
size_t result = write(fd, buffer, len);
|
||||
#endif // if/else WIN32
|
||||
if (result > 0) offset += (Offset)result;
|
||||
if (result < 0)
|
||||
{
|
||||
DMSG(0, "NormFile::Write() write() error: %s\n", GetErrorString());
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset += (Offset)result;
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
} // end NormFile::Write()
|
||||
|
||||
|
|
@ -451,7 +467,7 @@ bool NormDirectoryIterator::Open(const char *thePath)
|
|||
current = new NormDirectory(thePath);
|
||||
if (current && current->Open())
|
||||
{
|
||||
path_len = strlen(current->Path());
|
||||
path_len = (int)strlen(current->Path());
|
||||
path_len = MIN(PATH_MAX, path_len);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -555,7 +571,7 @@ bool NormDirectoryIterator::GetNextFile(char* fileName)
|
|||
NormFile::Type type = NormFile::GetType(fileName);
|
||||
if (NormFile::NORMAL == type)
|
||||
{
|
||||
int nameLen = strlen(fileName);
|
||||
size_t nameLen = strlen(fileName);
|
||||
nameLen = MIN(PATH_MAX, nameLen);
|
||||
nameLen -= path_len;
|
||||
memmove(fileName, fileName+path_len, nameLen);
|
||||
|
|
@ -682,7 +698,7 @@ NormDirectoryIterator::NormDirectory::NormDirectory(const char* thePath,
|
|||
#endif // if/else WIN32
|
||||
{
|
||||
strncpy(path, thePath, PATH_MAX);
|
||||
int len = MIN(PATH_MAX, strlen(path));
|
||||
size_t len = MIN(PATH_MAX, strlen(path));
|
||||
if ((len < PATH_MAX) && (PROTO_PATH_DELIMITER != path[len-1]))
|
||||
{
|
||||
path[len++] = PROTO_PATH_DELIMITER;
|
||||
|
|
@ -701,7 +717,7 @@ bool NormDirectoryIterator::NormDirectory::Open()
|
|||
char fullName[PATH_MAX];
|
||||
GetFullName(fullName);
|
||||
// Get rid of trailing PROTO_PATH_DELIMITER
|
||||
int len = MIN(PATH_MAX, strlen(fullName));
|
||||
size_t len = MIN(PATH_MAX, strlen(fullName));
|
||||
if (PROTO_PATH_DELIMITER == fullName[len-1]) fullName[len-1] = '\0';
|
||||
#ifdef WIN32
|
||||
#ifdef _UNICODE
|
||||
|
|
@ -753,7 +769,7 @@ void NormDirectoryIterator::NormDirectory::GetFullName(char* ptr)
|
|||
void NormDirectoryIterator::NormDirectory::RecursiveCatName(char* ptr)
|
||||
{
|
||||
if (parent) parent->RecursiveCatName(ptr);
|
||||
int len = MIN(PATH_MAX, strlen(ptr));
|
||||
size_t len = MIN(PATH_MAX, strlen(ptr));
|
||||
strncat(ptr, path, PATH_MAX-len);
|
||||
} // end NormDirectoryIterator::NormDirectory::RecursiveCatName()
|
||||
|
||||
|
|
@ -1020,11 +1036,11 @@ bool NormFileList::Append(const char* path)
|
|||
bool NormFileList::Remove(const char* path)
|
||||
{
|
||||
FileItem* nextItem = head;
|
||||
unsigned int pathLen = strlen(path);
|
||||
size_t pathLen = strlen(path);
|
||||
pathLen = MIN(pathLen, PATH_MAX);
|
||||
while (nextItem)
|
||||
{
|
||||
unsigned nameLen = strlen(nextItem->Path());
|
||||
size_t nameLen = strlen(nextItem->Path());
|
||||
nameLen = MIN(nameLen, PATH_MAX);
|
||||
nameLen = MAX(nameLen, pathLen);
|
||||
if (!strncmp(path, nextItem->Path(), nameLen))
|
||||
|
|
@ -1087,7 +1103,7 @@ void NormFileList::GetCurrentBasePath(char* pathBuffer)
|
|||
if (NormFile::DIRECTORY == next->GetType())
|
||||
{
|
||||
strncpy(pathBuffer, next->Path(), PATH_MAX);
|
||||
unsigned int len = strlen(pathBuffer);
|
||||
size_t len = strlen(pathBuffer);
|
||||
len = MIN(len, PATH_MAX);
|
||||
if (PROTO_PATH_DELIMITER != pathBuffer[len-1])
|
||||
{
|
||||
|
|
@ -1100,7 +1116,7 @@ void NormFileList::GetCurrentBasePath(char* pathBuffer)
|
|||
const char* ptr = strrchr(next->Path(), PROTO_PATH_DELIMITER);
|
||||
if (ptr++)
|
||||
{
|
||||
unsigned int len = ptr - next->Path();
|
||||
size_t len = ptr - next->Path();
|
||||
strncpy(pathBuffer, next->Path(), len);
|
||||
pathBuffer[len] = '\0';
|
||||
}
|
||||
|
|
@ -1120,7 +1136,7 @@ void NormFileList::GetCurrentBasePath(char* pathBuffer)
|
|||
NormFileList::FileItem::FileItem(const char* thePath)
|
||||
: prev(NULL), next(NULL)
|
||||
{
|
||||
unsigned int len = strlen(thePath);
|
||||
size_t len = strlen(thePath);
|
||||
len = MIN(len, PATH_MAX);
|
||||
strncpy(path, thePath, PATH_MAX);
|
||||
size = NormFile::GetSize(thePath);
|
||||
|
|
@ -1195,7 +1211,7 @@ bool NormFileList::DirectoryItem::GetNextFile(char* thePath,
|
|||
}
|
||||
}
|
||||
strncpy(thePath, path, PATH_MAX);
|
||||
unsigned int len = strlen(thePath);
|
||||
size_t len = strlen(thePath);
|
||||
len = MIN(len, PATH_MAX);
|
||||
if ((PROTO_PATH_DELIMITER != thePath[len-1]) && (len < PATH_MAX))
|
||||
{
|
||||
|
|
@ -1205,7 +1221,7 @@ bool NormFileList::DirectoryItem::GetNextFile(char* thePath,
|
|||
char tempPath[PATH_MAX];
|
||||
while (diterator.GetNextFile(tempPath))
|
||||
{
|
||||
unsigned int maxLen = PATH_MAX - len;
|
||||
size_t maxLen = PATH_MAX - len;
|
||||
strncat(thePath, tempPath, maxLen);
|
||||
if (updatesOnly)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ class NormFile
|
|||
return (fd >= 0);
|
||||
#endif // _WIN32_WCE
|
||||
}
|
||||
int Read(char* buffer, int len);
|
||||
int Write(const char* buffer, int len);
|
||||
size_t Read(char* buffer, size_t len);
|
||||
size_t Write(const char* buffer, size_t len);
|
||||
bool Seek(Offset theOffset);
|
||||
NormFile::Offset GetOffset() const {return (offset);}
|
||||
NormFile::Offset GetSize() const;
|
||||
|
|
@ -112,7 +112,7 @@ class NormFile
|
|||
|
||||
|
||||
// Members
|
||||
private:
|
||||
//private:
|
||||
#ifdef _WIN32_WCE
|
||||
FILE* file_ptr;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ const UINT8 NORM_PROTOCOL_VERSION = 1;
|
|||
|
||||
const int NORM_ROBUST_FACTOR = 20; // default robust factor
|
||||
|
||||
// This value is used in a couple places in the code as
|
||||
// a safety check where some critical timeouts may be
|
||||
// less than expected operating system clock resolution
|
||||
const double NORM_TICK_MIN = 0.100; // in seconds
|
||||
|
||||
// Pick a random number from 0..max
|
||||
inline double UniformRand(double max)
|
||||
{
|
||||
|
|
@ -41,6 +46,7 @@ inline double ExponentialRand(double max, double groupSize)
|
|||
// These are the GRTT estimation bounds set for the current
|
||||
// NORM protocol. (Note that our Grtt quantization routines
|
||||
// are good for the range of 1.0e-06 <= 1000.0)
|
||||
|
||||
const double NORM_GRTT_MIN = 0.001; // 1 msec
|
||||
const double NORM_GRTT_MAX = 15.0; // 15 sec
|
||||
const double NORM_RTT_MIN = 1.0e-06;
|
||||
|
|
@ -225,8 +231,8 @@ class NormHeaderExtension
|
|||
enum Type
|
||||
{
|
||||
INVALID = 0,
|
||||
FTI = 1, // FEC Object Transmission Information (FTI) extension
|
||||
CC_FEEDBACK = 2, // NORM-CC Feedback extension
|
||||
FTI = 64, // FEC Object Transmission Information (FTI) extension
|
||||
CC_FEEDBACK = 3, // NORM-CC Feedback extension
|
||||
CC_RATE = 128 // NORM-CC Rate extension
|
||||
};
|
||||
|
||||
|
|
@ -350,6 +356,8 @@ class NormMsg
|
|||
char* AccessBuffer() {return ((char*)buffer);}
|
||||
ProtoAddress& AccessAddress() {return addr;}
|
||||
|
||||
NormMsg* GetNext() {return next;}
|
||||
|
||||
protected:
|
||||
// Common message header offsets
|
||||
// All of our offsets reflect their offset based on the field size!
|
||||
|
|
@ -400,8 +408,8 @@ class NormObjectMsg : public NormMsg
|
|||
FLAG_INFO = 0x04,
|
||||
FLAG_UNRELIABLE = 0x08,
|
||||
FLAG_FILE = 0x10,
|
||||
FLAG_STREAM = 0x20,
|
||||
FLAG_MSG_START = 0x40
|
||||
FLAG_STREAM = 0x20
|
||||
//FLAG_MSG_START = 0x40 deprecated
|
||||
};
|
||||
UINT16 GetInstanceId() const
|
||||
{
|
||||
|
|
@ -632,6 +640,7 @@ class NormDataMsg : public NormObjectMsg
|
|||
// Some static helper routines for reading/writing embedded payload length/offsets
|
||||
static UINT16 GetStreamPayloadHeaderLength() {return (PAYLOAD_DATA_OFFSET);}
|
||||
|
||||
/* Payload flags have deprecated in the revised NORM spec
|
||||
enum PayloadFlag
|
||||
{
|
||||
FLAG_STREAM_END = 0x01,
|
||||
|
|
@ -649,6 +658,11 @@ class NormDataMsg : public NormObjectMsg
|
|||
static void SetStreamPayloadFlag(char* payload, PayloadFlag flag)
|
||||
{
|
||||
((UINT8*)payload)[PAYLOAD_FLAGS_OFFSET] |= flag;
|
||||
}*/
|
||||
static void WriteStreamPayloadMsgStart(char* payload, UINT16 msgStartOffset)
|
||||
{
|
||||
UINT16 temp16 = htons(msgStartOffset);
|
||||
memcpy(payload+PAYLOAD_MSG_START_OFFSET, &temp16, 2);
|
||||
}
|
||||
static void WriteStreamPayloadLength(char* payload, UINT16 len)
|
||||
{
|
||||
|
|
@ -660,6 +674,12 @@ class NormDataMsg : public NormObjectMsg
|
|||
UINT32 temp32 = htonl(offset);
|
||||
memcpy(payload+PAYLOAD_OFFSET_OFFSET, &temp32, 4);
|
||||
}
|
||||
static UINT16 ReadStreamPayloadMsgStart(const char* payload)
|
||||
{
|
||||
UINT16 temp16;
|
||||
memcpy(&temp16, payload+PAYLOAD_MSG_START_OFFSET, 2);
|
||||
return (ntohs(temp16));
|
||||
}
|
||||
static UINT16 ReadStreamPayloadLength(const char* payload)
|
||||
{
|
||||
UINT16 temp16;
|
||||
|
|
@ -685,11 +705,11 @@ class NormDataMsg : public NormObjectMsg
|
|||
};
|
||||
enum
|
||||
{
|
||||
PAYLOAD_FLAGS_OFFSET = 0,
|
||||
PAYLOAD_RESERVED_OFFSET = PAYLOAD_FLAGS_OFFSET+1, // this is not in the NORM spec!
|
||||
PAYLOAD_LENGTH_OFFSET = PAYLOAD_RESERVED_OFFSET+1,
|
||||
PAYLOAD_OFFSET_OFFSET = PAYLOAD_LENGTH_OFFSET+2,
|
||||
PAYLOAD_DATA_OFFSET = PAYLOAD_OFFSET_OFFSET+4
|
||||
//PAYLOAD_FLAGS_OFFSET = 0, // deprecated
|
||||
PAYLOAD_MSG_START_OFFSET = 0,
|
||||
PAYLOAD_LENGTH_OFFSET = PAYLOAD_MSG_START_OFFSET+2,
|
||||
PAYLOAD_OFFSET_OFFSET = PAYLOAD_LENGTH_OFFSET+2,
|
||||
PAYLOAD_DATA_OFFSET = PAYLOAD_OFFSET_OFFSET+4
|
||||
};
|
||||
}; // end class NormDataMsg
|
||||
|
||||
|
|
@ -1589,6 +1609,7 @@ class NormMessageQueue
|
|||
void Remove(NormMsg* msg);
|
||||
NormMsg* RemoveHead();
|
||||
NormMsg* RemoveTail();
|
||||
NormMsg* GetHead() {return head;}
|
||||
bool IsEmpty() {return ((NormMsg*)NULL == head);}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -160,9 +160,10 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
|||
// enforced. Note that "bufferFactor" values > 0.0 help reduce "seeking" for decoding,
|
||||
// but reduce the number of blocks for which NORM can keep state. Note this only comes
|
||||
// into play when NORM would be "buffer constrained"
|
||||
// (TBD) perhaps we should keep more "block state" than we can even buffer parity for ???
|
||||
// (this would reduce requests for full block retransmissions when resource contrained)
|
||||
double bufferFactor = 0.0;
|
||||
// (TBD) perhaps we should keep state for more blocks than we can even buffer parity for ???
|
||||
// (this would reduce requests for full block retransmissions when resource constrained)
|
||||
// (this would correspond to "bufferFactor < 0.0"
|
||||
double bufferFactor = 0.0; // (TBD) let app control "bufferFactor"???
|
||||
unsigned long segPerBlock =
|
||||
(unsigned long) ((bufferFactor * (double)numData) +
|
||||
((1.0 - bufferFactor) * (double)numParity) + 0.5);
|
||||
|
|
@ -206,7 +207,8 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
|||
memset(retrieval_pool, 0, numData*sizeof(char*));
|
||||
for (UINT16 i = 0; i < numData; i++)
|
||||
{
|
||||
char* s = new char[segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()];
|
||||
// allocate segment with extra byte for stream flags ...
|
||||
char* s = new char[segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()+1];
|
||||
if (NULL == s)
|
||||
{
|
||||
DMSG(0, "NormServerNode::AllocateBuffers() new retrieval segment error: %s\n", GetErrorString());
|
||||
|
|
@ -240,6 +242,7 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
|||
nominal_packet_size = (double)segmentSize;
|
||||
ndata = numData;
|
||||
nparity = numParity;
|
||||
IncrementResyncCount();
|
||||
return true;
|
||||
} // end NormServerNode::AllocateBuffers()
|
||||
|
||||
|
|
@ -326,6 +329,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
static_cast<NormStreamObject*>(obj)->Prune(blockId, true);
|
||||
}
|
||||
// 3) (TBD) Go ahead and discard any invalidated objects
|
||||
// (those listed with id's > objectId)
|
||||
// (although they will eventually get discarded anyway)
|
||||
break;
|
||||
}
|
||||
|
|
@ -391,7 +395,6 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
double backoffFactor = backoff_factor;
|
||||
backoffFactor = MAX(backoffFactor, 4.0);
|
||||
maxBackoff = grtt_estimate*backoffFactor;
|
||||
|
||||
}
|
||||
double backoffTime = (maxBackoff > 0.0) ?
|
||||
ExponentialRand(maxBackoff, gsize_estimate) :
|
||||
|
|
@ -415,7 +418,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
}
|
||||
//DMSG(0, "NormServerNode::HandleCommand(CC) node>%lu bias:%lf recv_rate:%lf send_rate:%lf "
|
||||
// "grtt:%lf gsize:%lf\n",
|
||||
// LocalNodeId(), r, recv_rate*(8.0/1000.0), send_rate*(8.0/1000.0),
|
||||
// LocalNodeId(), r, 8.0e-03*recv_rate, 8.0e-03*send_rate,
|
||||
//
|
||||
|
||||
backoffTime = 0.25 * r * maxBackoff + 0.75 * backoffTime;
|
||||
|
|
@ -491,7 +494,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
case NormCmdMsg::REPAIR_ADV:
|
||||
{
|
||||
const NormCmdRepairAdvMsg& repairAdv = (const NormCmdRepairAdvMsg&)cmd;
|
||||
// Does the CC feedback of this ACK suppress our CC feedback
|
||||
// Does the CC feedback of this ACK suppress our CC feedback?
|
||||
if (!is_clr && !is_plr && cc_timer.IsActive() &&
|
||||
cc_timer.GetRepeatCount())
|
||||
{
|
||||
|
|
@ -507,6 +510,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
}
|
||||
if (repair_timer.IsActive() && repair_timer.GetRepeatCount())
|
||||
{
|
||||
// (TBD) pay attention to the NORM_REPAIR_ADV_LIMIT flag
|
||||
HandleRepairContent(repairAdv.GetRepairContent(),
|
||||
repairAdv.GetRepairContentLength());
|
||||
}
|
||||
|
|
@ -522,7 +526,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
|
||||
void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
||||
{
|
||||
ASSERT(cc_timer.IsActive() && cc_timer.GetRepeatCount());
|
||||
//ASSERT(cc_timer.IsActive() && cc_timer.GetRepeatCount());
|
||||
if (0 == (ccFlags & NormCC::CLR))
|
||||
{
|
||||
// We're suppressed by non-CLR receivers with no RTT confirmed
|
||||
|
|
@ -532,6 +536,8 @@ void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
|||
NormSession::CalculateRate(nominal_packet_size,
|
||||
rtt_estimate,
|
||||
LossEstimate());
|
||||
// This increases our chance of being suppressed
|
||||
// (but is it a good idea?)
|
||||
localRate = MAX(localRate, cc_rate);
|
||||
|
||||
bool hasRtt = (0 != (ccFlags & NormCC::RTT));
|
||||
|
|
@ -562,7 +568,9 @@ void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
|||
if (suppressed)
|
||||
{
|
||||
if (cc_timer.IsActive()) cc_timer.Deactivate();
|
||||
cc_timer.SetInterval(grtt_estimate*backoff_factor); // (TBD) ???
|
||||
double backoffFactor = backoff_factor;
|
||||
backoffFactor = MAX(backoffFactor, 4.0); // always use at least 4 for cc purposes
|
||||
cc_timer.SetInterval(grtt_estimate*backoffFactor); // (TBD) ??? xxx
|
||||
session.ActivateTimer(cc_timer);
|
||||
cc_timer.DecrementRepeatCount();
|
||||
}
|
||||
|
|
@ -609,6 +617,7 @@ void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
|
|||
// Clients use this method to process NACK content overheard from other
|
||||
// clients or via NORM_CMD(REPAIR_ADV) messages received from the server.
|
||||
// Such content can "suppress" pending NACKs
|
||||
// (TBD) add provision to handle case when NORM_REPAIR_ADV_FLAG_LIMIT was set
|
||||
void NormServerNode::HandleRepairContent(const UINT32* buffer, UINT16 bufferLen)
|
||||
{
|
||||
// Parse NACK and incorporate into repair state masks
|
||||
|
|
@ -851,7 +860,8 @@ char* NormServerNode::GetFreeSegment(NormObjectId objectId, NormBlockId blockId)
|
|||
break;
|
||||
}
|
||||
}
|
||||
return segment_pool.Get();
|
||||
char* result = segment_pool.Get();
|
||||
return result;
|
||||
} // end NormServerNode::GetFreeSegment()
|
||||
|
||||
void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||
|
|
@ -1478,7 +1488,7 @@ bool NormServerNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
|
|||
ext.SetCCRate(NormQuantizeRate(ccRate));
|
||||
}
|
||||
DMSG(6, "NormServerNode::OnRepairTimeout() node>%lu sending NACK rate:%lf kbps (rtt:%lf loss:%lf s:%hu) slow_start:%d\n",
|
||||
LocalNodeId(), NormUnquantizeRate(ext.GetCCRate()) * (8.0/1000.0),
|
||||
LocalNodeId(), 8.0e-03*NormUnquantizeRate(ext.GetCCRate()),
|
||||
rtt_estimate, ccLoss, nominal_packet_size, slow_start);
|
||||
ext.SetCCSequence(cc_sequence);
|
||||
// Cancel potential pending NORM_ACK(RTT)
|
||||
|
|
@ -1675,25 +1685,23 @@ void NormServerNode::UpdateRecvRate(const struct timeval& currentTime, unsigned
|
|||
{
|
||||
if (prev_update_time.tv_sec || prev_update_time.tv_usec)
|
||||
{
|
||||
recv_accumulator += msgSize;
|
||||
|
||||
double interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
|
||||
if (currentTime.tv_usec > prev_update_time.tv_sec)
|
||||
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
|
||||
else
|
||||
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
|
||||
double measurementInterval = rtt_confirmed ? rtt_estimate : grtt_estimate;
|
||||
// Here, we put a 0.100 sec lower bound on our measurementInterval for the
|
||||
// Here, we put a NORM_TICK_MIN sec lower bound on our measurementInterval for the
|
||||
// recv_rate because of the typical limited granularity of our system clock
|
||||
// (Note this does limit our ramp up of data rate during slow start)
|
||||
if (measurementInterval < 0.100) measurementInterval = 0.100;
|
||||
if (measurementInterval < NORM_TICK_MIN) measurementInterval = NORM_TICK_MIN;
|
||||
if (interval > 0.0)
|
||||
{
|
||||
double currentRecvRate = ((double)(recv_accumulator)) / interval;
|
||||
if (currentRecvRate < recv_rate)
|
||||
if ((interval >= measurementInterval) && (currentRecvRate < recv_rate))
|
||||
{
|
||||
// Make sure we've allowed sufficient time for a measurement
|
||||
double minInterval = 4.0 * ((double)nominal_packet_size) / recv_rate;
|
||||
// Make sure we've allowed sufficient time for a measurement at low rates
|
||||
double minInterval = 4.0 * ((double)(MAX(nominal_packet_size, segment_size)))/ recv_rate;
|
||||
if (measurementInterval < minInterval)
|
||||
measurementInterval = minInterval;
|
||||
}
|
||||
|
|
@ -1701,46 +1709,28 @@ void NormServerNode::UpdateRecvRate(const struct timeval& currentTime, unsigned
|
|||
{
|
||||
recv_rate = currentRecvRate; //((double)(recv_accumulator)) / interval;
|
||||
prev_update_time = currentTime;
|
||||
recv_accumulator = 0;
|
||||
recv_accumulator = msgSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
recv_accumulator += msgSize;
|
||||
}
|
||||
}
|
||||
/*
|
||||
// We put a 0.100 sec lower bound on our rttEstimate for the recv_rate measurement
|
||||
// interval because of the typical limited granularity of our system clock
|
||||
// (Note this does limit our ramp up of data rate during slow start)
|
||||
if (rttEstimate < 0.1) rttEstimate = 0.1;
|
||||
rttEstimate = rttEstimate < 0.1 ? 0.1 : rttEstimate;
|
||||
|
||||
// Also, don't update more than nominal_packet_size / recv_rate
|
||||
// or our measurement is subject to quantization error
|
||||
|
||||
double minterval = recv_rate > 0.0 ? 2.0 * ((double)nominal_packet_size) / recv_rate : rttEstimate;
|
||||
|
||||
rttEstimate = rttEstimate < minterval ? minterval : rttEstimate;
|
||||
|
||||
|
||||
if (interval >= rttEstimate)
|
||||
{
|
||||
recv_rate = ((double)(recv_accumulator)) / interval;
|
||||
prev_update_time = currentTime;
|
||||
recv_accumulator = 0;
|
||||
}*/
|
||||
//TRACE("updated recv rate to %lf (accum:%lu) (cc_rate:%lf)\n", recv_rate,
|
||||
// recv_accumulator, cc_rate);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (send_rate > 0.0)
|
||||
/*if (send_rate > 0.0)
|
||||
recv_rate = send_rate;
|
||||
else
|
||||
recv_rate = ((double)msgSize) / grtt_estimate;
|
||||
recv_rate = ((double)msgSize) / grtt_estimate;*/
|
||||
recv_rate = 0.0;
|
||||
prev_update_time = currentTime;
|
||||
recv_accumulator = 0;
|
||||
recv_accumulator = msgSize;
|
||||
}
|
||||
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
|
||||
} // end NormServerNode::UpdateRecvRate()
|
||||
|
||||
void NormServerNode::Activate()
|
||||
void NormServerNode::Activate(bool isObjectMsg)
|
||||
{
|
||||
if (!activity_timer.IsActive())
|
||||
{
|
||||
|
|
@ -1749,7 +1739,7 @@ void NormServerNode::Activate()
|
|||
server_active = false;
|
||||
session.Notify(NormController::REMOTE_SERVER_ACTIVE, this, NULL);
|
||||
}
|
||||
else
|
||||
else if (isObjectMsg)
|
||||
{
|
||||
server_active = true;
|
||||
}
|
||||
|
|
@ -1797,9 +1787,19 @@ bool NormServerNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
|
|||
max_pending_object, 0, 0);
|
||||
}
|
||||
else
|
||||
RepairCheck(NormObject::TO_BLOCK, // (TBD) thru object???
|
||||
{
|
||||
RepairCheck(NormObject::THRU_OBJECT, // (TBD) thru object???
|
||||
max_pending_object, 0, 0);
|
||||
//RepairCheck(NormObject::TO_BLOCK, // (TBD) thru object???
|
||||
// max_pending_object, 0, 0);
|
||||
}
|
||||
}
|
||||
// At low recv data rates, we adjust the activity timeout a little.
|
||||
// to _help_ prevent premature timeout
|
||||
double nominalInterval = nominal_packet_size / recv_rate;
|
||||
if (grtt_estimate < nominalInterval)
|
||||
activity_timer.SetInterval(NORM_ROBUST_FACTOR * nominalInterval);
|
||||
|
||||
}
|
||||
server_active = false;
|
||||
return true;
|
||||
|
|
@ -1851,11 +1851,11 @@ void NormServerNode::AttachCCFeedback(NormAckMsg& ack)
|
|||
rtt_estimate, ccLoss);
|
||||
ext.SetCCRate(NormQuantizeRate(ccRate));
|
||||
}
|
||||
//DMSG(0, "NormServerNode::OnCCTimeout() node>%lu sending ACK rate:%lf kbps (rtt:%lf loss:%lf s:%lf recvRate:%lf) slow_start:%d\n",
|
||||
// LocalNodeId(), NormUnquantizeRate(ext.GetCCRate()) * (8.0/1000.0),
|
||||
// rtt_estimate, ccLoss, nominal_packet_size, recv_rate*(8.0/1000.), slow_start);
|
||||
//DMSG(0, "NormServerNode::AttachCCFeedback() node>%lu sending ACK rate:%lf kbps (rtt:%lf loss:%lf s:%lf recvRate:%lf) slow_start:%d\n",
|
||||
// LocalNodeId(), 8.0e-03*NormUnquantizeRate(ext.GetCCRate()) ,
|
||||
// rtt_estimate, ccLoss, nominal_packet_size, 8.0e-03*recv_rate, slow_start);
|
||||
ext.SetCCSequence(cc_sequence);
|
||||
} // end
|
||||
} // end ormServerNode::AttachCCFeedback()
|
||||
|
||||
bool NormServerNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
|
|
@ -1901,8 +1901,16 @@ bool NormServerNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
|
|||
//}
|
||||
|
||||
// Begin cc_timer "holdoff" phase
|
||||
cc_timer.SetInterval(grtt_estimate*backoff_factor);
|
||||
return true;
|
||||
if (session.Address().IsMulticast())
|
||||
{
|
||||
cc_timer.SetInterval(grtt_estimate*backoff_factor);
|
||||
return true;
|
||||
}
|
||||
else if (cc_timer.IsActive())
|
||||
{
|
||||
cc_timer.Deactivate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
@ -1935,7 +1943,7 @@ bool NormServerNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
|
|||
// Don't rate limit feedback messages
|
||||
session.SendMessage(*ack);
|
||||
session.ReturnMessageToPool(ack);
|
||||
if (!is_clr && !is_plr)
|
||||
if (!is_clr && !is_plr && session.Address().IsMulticast())
|
||||
{
|
||||
// Install cc feedback holdoff
|
||||
if (cc_timer.IsActive()) cc_timer.Deactivate();
|
||||
|
|
@ -1943,6 +1951,11 @@ bool NormServerNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
|
|||
session.ActivateTimer(cc_timer);
|
||||
cc_timer.DecrementRepeatCount();
|
||||
}
|
||||
else if (cc_timer.IsActive())
|
||||
{
|
||||
cc_timer.Deactivate();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ class NormServerNode : public NormNode
|
|||
bool AllocateBuffers(UINT16 segmentSize, UINT16 numData, UINT16 numParity);
|
||||
bool BuffersAllocated() {return (0 != segment_size);}
|
||||
void FreeBuffers();
|
||||
void Activate();
|
||||
void Activate(bool isObjectMsg);
|
||||
|
||||
|
||||
bool SyncTest(const NormObjectMsg& msg) const;
|
||||
|
|
|
|||
|
|
@ -1208,6 +1208,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
if (isSourceSymbol)
|
||||
{
|
||||
block->DecrementErasureCount();
|
||||
/* STREAM payload flags have been deprecated in favor of "payload_msg_start"
|
||||
// This bit of code makes sure that NORM Protocol Version 1
|
||||
// use of FLAG_MSG_START is observed even when the equivalent (and better!)
|
||||
// stream payload flag is not used.
|
||||
|
|
@ -1221,6 +1222,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
NormDataMsg::SetStreamPayloadFlag((char*)data.GetPayload(), NormDataMsg::FLAG_MSG_START);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (WriteSegment(blockId, segmentId, data.GetPayload()))
|
||||
{
|
||||
|
|
@ -1585,13 +1587,14 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
|
|||
}
|
||||
data->SetPayloadLength(payloadLength);
|
||||
|
||||
/* stream payload flags have been deprecated in favor of "payload_msg_start" field
|
||||
// Set FLAG_MSG_START as appropriated for NORM Protocol Version 1 compatibility
|
||||
if (IsStream())
|
||||
{
|
||||
if (NormDataMsg::StreamPayloadFlagIsSet(buffer, NormDataMsg::FLAG_MSG_START))
|
||||
data->SetFlag(NormObjectMsg::FLAG_MSG_START);
|
||||
}
|
||||
|
||||
*/
|
||||
// Perform incremental FEC encoding as needed
|
||||
if ((block->ParityReadiness() == segmentId) && nparity)
|
||||
// (TBD) && incrementalParity == true
|
||||
|
|
@ -1794,7 +1797,7 @@ bool NormFileObject::Open(const char* thePath,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (file.Open(thePath, O_WRONLY | O_CREAT | O_TRUNC))
|
||||
if (file.Open(thePath, O_RDWR | O_CREAT | O_TRUNC))
|
||||
{
|
||||
file.Lock();
|
||||
}
|
||||
|
|
@ -1849,7 +1852,7 @@ bool NormFileObject::Open(const char* thePath,
|
|||
large_block_length = NormObjectSize(large_block_size) * segment_size;
|
||||
small_block_length = NormObjectSize(small_block_size) * segment_size;
|
||||
strncpy(path, thePath, PATH_MAX);
|
||||
unsigned int len = strlen(thePath);
|
||||
size_t len = strlen(thePath);
|
||||
len = MIN(len, PATH_MAX);
|
||||
if (len < PATH_MAX) path[len] = '\0';
|
||||
return true;
|
||||
|
|
@ -1878,7 +1881,7 @@ bool NormFileObject::WriteSegment(NormBlockId blockId,
|
|||
NormSegmentId segmentId,
|
||||
const char* buffer)
|
||||
{
|
||||
UINT16 len;
|
||||
size_t len;
|
||||
if (blockId == final_block_id)
|
||||
{
|
||||
if (segmentId == (GetBlockSize(blockId)-1))
|
||||
|
|
@ -1909,7 +1912,7 @@ bool NormFileObject::WriteSegment(NormBlockId blockId,
|
|||
{
|
||||
if (!file.Seek(offset)) return false;
|
||||
}
|
||||
UINT16 nbytes = file.Write(buffer, len);
|
||||
size_t nbytes = file.Write(buffer, len);
|
||||
return (nbytes == len);
|
||||
} // end NormFileObject::WriteSegment()
|
||||
|
||||
|
|
@ -1919,7 +1922,7 @@ UINT16 NormFileObject::ReadSegment(NormBlockId blockId,
|
|||
char* buffer)
|
||||
{
|
||||
// Determine segment length from blockId::segmentId
|
||||
UINT16 len;
|
||||
size_t len;
|
||||
if (blockId == final_block_id)
|
||||
{
|
||||
if (segmentId == (GetBlockSize(blockId)-1))
|
||||
|
|
@ -1949,11 +1952,17 @@ UINT16 NormFileObject::ReadSegment(NormBlockId blockId,
|
|||
NormFile::Offset offset = segmentOffset.GetOffset();
|
||||
if (offset != file.GetOffset())
|
||||
{
|
||||
if (!file.Seek(offset))
|
||||
return false;
|
||||
if (!file.Seek(offset))
|
||||
{
|
||||
DMSG(0, "NormFileObject::ReadSegment() error seeking to file offset\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
UINT16 nbytes = file.Read(buffer, len);
|
||||
return (len == nbytes) ? len : 0;
|
||||
size_t nbytes = file.Read(buffer, len);
|
||||
if (len == nbytes)
|
||||
return (UINT16)len;
|
||||
else
|
||||
return 0;
|
||||
} // end NormFileObject::ReadSegment()
|
||||
|
||||
char* NormFileObject::RetrieveSegment(NormBlockId blockId,
|
||||
|
|
@ -2284,7 +2293,7 @@ bool NormStreamObject::Open(UINT32 bufferSize,
|
|||
numBlocks = MAX(2, numBlocks);
|
||||
if (doubleBuffer) numBlocks *= 2;
|
||||
UINT32 numSegments = numBlocks * numData;
|
||||
|
||||
|
||||
if (!block_pool.Init(numBlocks, numData))
|
||||
{
|
||||
DMSG(0, "NormStreamObject::Open() block_pool init error\n");
|
||||
|
|
@ -2310,6 +2319,7 @@ bool NormStreamObject::Open(UINT32 bufferSize,
|
|||
read_init = true;
|
||||
read_index.block = read_index.segment = 0;
|
||||
write_index.block = write_index.segment = 0;
|
||||
tx_index.block = tx_index.segment = 0;
|
||||
tx_offset = write_offset = read_offset = 0;
|
||||
write_vacancy = true;
|
||||
posted_tx_queue_vacancy = false;
|
||||
|
|
@ -2539,18 +2549,31 @@ UINT16 NormStreamObject::ReadSegment(NormBlockId blockId,
|
|||
char* segment = block->GetSegment(segmentId);
|
||||
ASSERT(segment != NULL);
|
||||
|
||||
// Update tx_offset if ((segmentOffset - tx_offset) > 0)
|
||||
UINT32 segmentOffset = NormDataMsg::ReadStreamPayloadOffset(segment);
|
||||
INT32 offsetDelta = segmentOffset - tx_offset;
|
||||
if (offsetDelta > 0) tx_offset = segmentOffset;
|
||||
// Update tx_offset if ((segmentOffset - tx_offset) > 0) (TBD) deprecate "tx_offset"
|
||||
//UINT32 segmentOffset = NormDataMsg::ReadStreamPayloadOffset(segment);
|
||||
//INT32 offsetDelta = segmentOffset - tx_offset;
|
||||
//if (offsetDelta > 0) tx_offset = segmentOffset;
|
||||
// Update tx_index if (blockId::segmentId > tx_index)
|
||||
if (blockId > tx_index.block)
|
||||
{
|
||||
tx_index.block = blockId;
|
||||
tx_index.segment = segmentId;
|
||||
}
|
||||
else if ((blockId == tx_index.block) && (segmentId > tx_index.segment))
|
||||
{
|
||||
tx_index.segment = segmentId;
|
||||
}
|
||||
|
||||
// Only advertise vacancy if stream_buffer.RangeLo() is non-pending _and_
|
||||
// (write_offset - tx_offset) < streamBufferSize
|
||||
// (write_index.block - tx_index.block) < block_pool.GetTotal() / 2
|
||||
if (!write_vacancy)
|
||||
{
|
||||
offsetDelta = write_offset - tx_offset;
|
||||
ASSERT(offsetDelta >= 0);
|
||||
if ((UINT32)offsetDelta < object_size.LSB())
|
||||
//offsetDelta = write_offset - tx_offset;
|
||||
//ASSERT(offsetDelta >= 0);
|
||||
//if ((UINT32)offsetDelta < object_size.LSB())
|
||||
ASSERT(tx_index.block <= write_index.block);
|
||||
UINT32 blockDelta = write_index.block - tx_index.block;
|
||||
if (blockDelta < (block_pool.GetTotal() >> 1))
|
||||
{
|
||||
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
||||
if (b && !b->IsPending())
|
||||
|
|
@ -2863,7 +2886,31 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
|||
} // end if (!segment)
|
||||
|
||||
UINT16 length = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||
if (length > segment_size)
|
||||
if (0 == length)
|
||||
{
|
||||
// It's a "stream control" message, so interpret "payload_msg_start" as control code
|
||||
switch (NormDataMsg::ReadStreamPayloadMsgStart(segment))
|
||||
{
|
||||
case 0:
|
||||
// This is the "stream end" control code
|
||||
break;
|
||||
default:
|
||||
// Invalid stream control code, skip this invalid segment
|
||||
DMSG(0, "NormStreamObject::Read() invalid stream control message\n");
|
||||
if (++read_index.segment >= ndata)
|
||||
{
|
||||
stream_buffer.Remove(block);
|
||||
block->EmptyToPool(segment_pool);
|
||||
block_pool.Put(block);
|
||||
read_index.block++;
|
||||
read_index.segment = 0;
|
||||
//Prune(read_index.block, false);
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
} // end switch(NormDataMsg::ReadStreamPayloadMsgStart(segment))
|
||||
}
|
||||
else if (length > segment_size)
|
||||
{
|
||||
Release();
|
||||
if (bytesRead > 0)
|
||||
|
|
@ -2935,18 +2982,19 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UINT16 count = length - index;
|
||||
count = MIN(count, bytesToRead);
|
||||
|
||||
if (seekMsgStart)
|
||||
{
|
||||
/* stream payload flags have in deprecated in favor of "payload_msg_start"
|
||||
if ((0 != index) ||
|
||||
!NormDataMsg::StreamPayloadFlagIsSet(segment, NormDataMsg::FLAG_MSG_START))
|
||||
*/
|
||||
UINT16 msgStart = NormDataMsg::ReadStreamPayloadMsgStart(segment);
|
||||
if (0 == msgStart)
|
||||
{
|
||||
// make sure msg start searches don't miss stream end ...
|
||||
if (NormDataMsg::StreamPayloadFlagIsSet(segment, NormDataMsg::FLAG_STREAM_END))
|
||||
//if (NormDataMsg::StreamPayloadFlagIsSet(segment, NormDataMsg::FLAG_STREAM_END))
|
||||
if (0 == NormDataMsg::ReadStreamPayloadLength(segment))
|
||||
{
|
||||
DMSG(4, "NormStreamObject::Read() stream ended by sender 1\n");
|
||||
session.Notify(NormController::RX_OBJECT_COMPLETED, server, this);
|
||||
|
|
@ -2971,10 +3019,13 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
|||
}
|
||||
else
|
||||
{
|
||||
seekMsgStart = false;
|
||||
read_offset += (msgStart - 1);
|
||||
index += (msgStart - 1);
|
||||
seekMsgStart = false;
|
||||
}
|
||||
}
|
||||
|
||||
UINT16 count = length - index;
|
||||
count = MIN(count, bytesToRead);
|
||||
#ifdef SIMULATE
|
||||
UINT16 simCount = index + count + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||
simCount = (simCount < SIM_PAYLOAD_MAX) ? (SIM_PAYLOAD_MAX - simCount) : 0;
|
||||
|
|
@ -2989,8 +3040,8 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
|||
bytesToRead -= count;
|
||||
if (index >= length)
|
||||
{
|
||||
bool streamEnded =
|
||||
NormDataMsg::StreamPayloadFlagIsSet(segment, NormDataMsg::FLAG_STREAM_END);
|
||||
bool streamEnded = (0 == NormDataMsg::ReadStreamPayloadLength(segment));
|
||||
// NormDataMsg::StreamPayloadFlagIsSet(segment, NormDataMsg::FLAG_STREAM_END);
|
||||
// Don't bother managing individual segments since
|
||||
// stream buffers are multiples of block size!
|
||||
// block->DetachSegment(read_index.segment);
|
||||
|
|
@ -3022,8 +3073,8 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
|||
|
||||
void NormStreamObject::Terminate()
|
||||
{
|
||||
// If there's a pending buffer at our "write_index", mark it
|
||||
// otherwise create a ZERO length segment to send
|
||||
// Flush stream and create a ZERO length segment to send
|
||||
Flush(); // should eom be set for this call?
|
||||
NormBlock* block = stream_buffer.Find(write_index.block);
|
||||
if (!block)
|
||||
{
|
||||
|
|
@ -3057,9 +3108,9 @@ void NormStreamObject::Terminate()
|
|||
ASSERT(success);
|
||||
} // end if (!block)
|
||||
char* segment = block->GetSegment(write_index.segment);
|
||||
if (!segment)
|
||||
if (NULL == segment)
|
||||
{
|
||||
if (!(segment = segment_pool.Get()))
|
||||
if (NULL == (segment = segment_pool.Get()))
|
||||
{
|
||||
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
||||
ASSERT(b != block);
|
||||
|
|
@ -3086,13 +3137,19 @@ void NormStreamObject::Terminate()
|
|||
segment = segment_pool.Get();
|
||||
ASSERT(segment);
|
||||
}
|
||||
NormDataMsg::WriteStreamPayloadOffset(segment, write_offset);
|
||||
NormDataMsg::WriteStreamPayloadLength(segment, 0);
|
||||
block->AttachSegment(write_index.segment, segment);
|
||||
} // end if (!segment)
|
||||
UINT16 index = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||
if (0 == index) NormDataMsg::ResetStreamPayloadFlags(segment);
|
||||
NormDataMsg::SetStreamPayloadFlag(segment, NormDataMsg::FLAG_STREAM_END);
|
||||
NormDataMsg::WriteStreamPayloadMsgStart(segment, 0);
|
||||
NormDataMsg::WriteStreamPayloadLength(segment, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0 == NormDataMsg::ReadStreamPayloadMsgStart(segment));
|
||||
ASSERT(0 == NormDataMsg::ReadStreamPayloadLength(segment));
|
||||
}
|
||||
NormDataMsg::WriteStreamPayloadOffset(segment, write_offset);
|
||||
|
||||
//NormDataMsg::ResetStreamPayloadFlags(segment); // flags are deprecated!
|
||||
//NormDataMsg::SetStreamPayloadFlag(segment, NormDataMsg::FLAG_STREAM_END);
|
||||
block->SetPending(write_index.segment);
|
||||
if (++write_index.segment >= ndata)
|
||||
{
|
||||
|
|
@ -3117,12 +3174,15 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
|||
}
|
||||
break;
|
||||
}
|
||||
INT32 deltaOffset = write_offset - tx_offset;
|
||||
ASSERT(deltaOffset >= 0);
|
||||
if (deltaOffset >= (INT32)object_size.LSB())
|
||||
//INT32 deltaOffset = write_offset - tx_offset; // (TBD) deprecate tx_offset
|
||||
//ASSERT(deltaOffset >= 0);
|
||||
//if (deltaOffset >= (INT32)object_size.LSB())
|
||||
ASSERT(write_index.block >= tx_index.block);
|
||||
UINT32 deltaBlock = write_index.block - tx_index.block;
|
||||
if (deltaBlock >= (block_pool.GetTotal() >> 1))
|
||||
{
|
||||
write_vacancy = false;
|
||||
DMSG(4, "NormStreamObject::Write() stream buffer full (1)\n", len, eom);
|
||||
DMSG(8, "NormStreamObject::Write() stream buffer full (1)\n", len, eom);
|
||||
if (!push_mode) break;
|
||||
}
|
||||
NormBlock* block = stream_buffer.Find(write_index.block);
|
||||
|
|
@ -3154,7 +3214,7 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
|||
}
|
||||
else
|
||||
{
|
||||
DMSG(4, "NormStreamObject::Write() stream buffer full (2) len:%d eom:%d\n", len, eom);
|
||||
DMSG(8, "NormStreamObject::Write() stream buffer full (2) len:%d eom:%d\n", len, eom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -3165,7 +3225,6 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
|||
block->ClearPending();
|
||||
bool success = stream_buffer.Insert(block);
|
||||
ASSERT(success);
|
||||
|
||||
} // end if (!block)
|
||||
char* segment = block->GetSegment(write_index.segment);
|
||||
if (!segment)
|
||||
|
|
@ -3196,7 +3255,7 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
|||
}
|
||||
else
|
||||
{
|
||||
DMSG(4, "NormStreamObject::Write() stream buffer full (3)\n");
|
||||
DMSG(8, "NormStreamObject::Write() stream buffer full (3)\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -3206,27 +3265,21 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
|||
segment = segment_pool.Get();
|
||||
ASSERT(segment);
|
||||
}
|
||||
NormDataMsg::WriteStreamPayloadOffset(segment, write_offset);
|
||||
NormDataMsg::WriteStreamPayloadMsgStart(segment, 0);
|
||||
NormDataMsg::WriteStreamPayloadLength(segment, 0);
|
||||
NormDataMsg::WriteStreamPayloadOffset(segment, write_offset);
|
||||
block->AttachSegment(write_index.segment, segment);
|
||||
} // end if (!segment)
|
||||
|
||||
UINT16 index = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||
|
||||
if (0 == index)
|
||||
// If it is an application start-of-message, mark the stream header accordingly
|
||||
// (but only if it is the _first_ message start for this segment!)
|
||||
if (msg_start && (0 != len))
|
||||
{
|
||||
NormDataMsg::ResetStreamPayloadFlags(segment);
|
||||
if (msg_start && len)
|
||||
{
|
||||
ASSERT(0 == index);
|
||||
NormDataMsg::SetStreamPayloadFlag(segment, NormDataMsg::FLAG_MSG_START);
|
||||
msg_start = false;
|
||||
}
|
||||
if (0 == NormDataMsg::ReadStreamPayloadMsgStart(segment))
|
||||
NormDataMsg::WriteStreamPayloadMsgStart(segment, index+1);
|
||||
msg_start = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_start = false;
|
||||
}
|
||||
|
||||
UINT16 count = (UINT16)(len - nBytes);
|
||||
UINT16 space = segment_size - index;
|
||||
|
|
|
|||
|
|
@ -305,8 +305,8 @@ class NormFileObject : public NormObject
|
|||
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||
NormSegmentId segmentId);
|
||||
|
||||
private:
|
||||
char path[PATH_MAX];
|
||||
//private:
|
||||
char path[PATH_MAX+10];
|
||||
NormFile file;
|
||||
NormObjectSize large_block_length;
|
||||
NormObjectSize small_block_length;
|
||||
|
|
@ -474,6 +474,7 @@ class NormStreamObject : public NormObject
|
|||
NormBlockBuffer stream_buffer;
|
||||
Index write_index;
|
||||
UINT32 write_offset;
|
||||
Index tx_index;
|
||||
UINT32 tx_offset;
|
||||
bool write_vacancy;
|
||||
bool posted_tx_queue_vacancy;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ char* NormSegmentPool::Get()
|
|||
char* ptr = seg_list;
|
||||
if (ptr)
|
||||
{
|
||||
memcpy(&seg_list, ptr, sizeof(char*));
|
||||
//memcpy(&seg_list, ptr, sizeof(char*));
|
||||
seg_list = *((char**)ptr);
|
||||
seg_count--;
|
||||
//#ifdef NORM_DEBUG
|
||||
overrun_flag = false;
|
||||
|
|
@ -601,7 +602,7 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
|
|||
} // end NormBlock::AppendRepairRequest()
|
||||
|
||||
NormBlockPool::NormBlockPool()
|
||||
: head((NormBlock*)NULL), count(0), overruns(0), overrun_flag(false)
|
||||
: head((NormBlock*)NULL), blk_total(0), blk_count(0), overruns(0), overrun_flag(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -627,6 +628,8 @@ bool NormBlockPool::Init(UINT32 numBlocks, UINT16 segsPerBlock)
|
|||
}
|
||||
b->next = head;
|
||||
head = b;
|
||||
blk_count++;
|
||||
blk_total++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -635,19 +638,19 @@ bool NormBlockPool::Init(UINT32 numBlocks, UINT16 segsPerBlock)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
count = numBlocks;
|
||||
return true;
|
||||
} // end NormBlockPool::Init()
|
||||
|
||||
void NormBlockPool::Destroy()
|
||||
{
|
||||
ASSERT(blk_total == blk_count);
|
||||
NormBlock* next;
|
||||
while ((next = head))
|
||||
{
|
||||
head = next->next;
|
||||
delete next;
|
||||
}
|
||||
count = 0;
|
||||
blk_count = blk_total = 0;
|
||||
} // end NormBlockPool::Destroy()
|
||||
|
||||
NormBlockBuffer::NormBlockBuffer()
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ class NormBlockPool
|
|||
head = b ? b->next : NULL;
|
||||
if (b)
|
||||
{
|
||||
count--;
|
||||
blk_count--;
|
||||
overrun_flag = false;
|
||||
}
|
||||
else if (!overrun_flag)
|
||||
|
|
@ -282,14 +282,16 @@ class NormBlockPool
|
|||
{
|
||||
b->next = head;
|
||||
head = b;
|
||||
count++;
|
||||
blk_count++;
|
||||
}
|
||||
unsigned long OverrunCount() const {return overruns;}
|
||||
UINT32 GetCount() {return count;}
|
||||
UINT32 GetCount() {return blk_count;}
|
||||
UINT32 GetTotal() {return blk_total;}
|
||||
|
||||
private:
|
||||
NormBlock* head;
|
||||
UINT32 count;
|
||||
UINT32 blk_total;
|
||||
UINT32 blk_count;
|
||||
unsigned long overruns;
|
||||
bool overrun_flag;
|
||||
}; // end class NormBlockPool
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
|||
: session_mgr(sessionMgr), notify_pending(false), tx_port(0),
|
||||
tx_socket(&tx_socket_actual), tx_socket_actual(ProtoSocket::UDP),
|
||||
rx_socket(ProtoSocket::UDP), local_node_id(localNodeId),
|
||||
ttl(DEFAULT_TTL), loopback(false), rx_port_reuse(false),
|
||||
ttl(DEFAULT_TTL), tos(0), loopback(false), rx_port_reuse(false), rx_addr_bind(false),
|
||||
tx_rate(DEFAULT_TRANSMIT_RATE/8.0), tx_rate_min(-1.0), tx_rate_max(-1.0),
|
||||
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), instance_id(0),
|
||||
ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0),
|
||||
|
|
@ -28,7 +28,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
|||
posted_tx_queue_empty(false),
|
||||
acking_node_count(0), watermark_pending(false), advertise_repairs(false),
|
||||
suppress_nonconfirmed(false), suppress_rate(-1.0), suppress_rtt(-1.0),
|
||||
probe_proactive(true), probe_pending(false), probe_reset(true),
|
||||
probe_proactive(true), probe_pending(false), probe_reset(true), probe_data_check(false),
|
||||
grtt_interval(0.5),
|
||||
grtt_interval_min(DEFAULT_GRTT_INTERVAL_MIN),
|
||||
grtt_interval_max(DEFAULT_GRTT_INTERVAL_MAX),
|
||||
|
|
@ -68,7 +68,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
|||
|
||||
grtt_quantized = NormQuantizeRtt(DEFAULT_GRTT_ESTIMATE);
|
||||
grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
|
||||
|
||||
gsize_measured = DEFAULT_GSIZE_ESTIMATE;
|
||||
gsize_quantized = NormQuantizeGroupSize(DEFAULT_GSIZE_ESTIMATE);
|
||||
gsize_advertised = NormUnquantizeGroupSize(gsize_quantized);
|
||||
|
|
@ -114,7 +114,7 @@ bool NormSession::Open(const char* interfaceName)
|
|||
Close();
|
||||
return false;
|
||||
}
|
||||
const ProtoAddress* bindAddr = NULL;
|
||||
|
||||
if (rx_port_reuse)
|
||||
{
|
||||
// Enable port/addr reuse and bind socket to destination address
|
||||
|
|
@ -124,6 +124,10 @@ bool NormSession::Open(const char* interfaceName)
|
|||
Close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const ProtoAddress* bindAddr = NULL;
|
||||
if (rx_addr_bind)
|
||||
{
|
||||
#ifndef WIN32
|
||||
if (address.IsMulticast()) // Win32 doesn't like to bind to multicast addr ???
|
||||
bindAddr = &address;
|
||||
|
|
@ -136,6 +140,13 @@ bool NormSession::Open(const char* interfaceName)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (0 != tos)
|
||||
{
|
||||
if (!tx_socket->SetTOS(tos))
|
||||
{
|
||||
DMSG(0, "NormSession::Open() warning: tx_socket set tos error\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (address.IsMulticast())
|
||||
{
|
||||
|
|
@ -238,12 +249,17 @@ bool NormSession::SetMulticastInterface(const char* interfaceName)
|
|||
|
||||
void NormSession::SetTxRateInternal(double txRate)
|
||||
{
|
||||
if (txRate < 0.0)
|
||||
{
|
||||
DMSG(0, "NormSession::SetTxRateInternal() invalid transmit rate!\n");
|
||||
return;
|
||||
}
|
||||
if (tx_timer.IsActive())
|
||||
{
|
||||
if (txRate > 0.0)
|
||||
{
|
||||
double adjustInterval = (tx_rate/txRate) * tx_timer.GetTimeRemaining();
|
||||
if (adjustInterval > 0.100)
|
||||
if (adjustInterval > NORM_TICK_MIN)
|
||||
{
|
||||
tx_timer.SetInterval(adjustInterval);
|
||||
tx_timer.Reschedule();
|
||||
|
|
@ -254,30 +270,38 @@ void NormSession::SetTxRateInternal(double txRate)
|
|||
tx_timer.Deactivate();
|
||||
|
||||
}
|
||||
tx_rate = txRate;
|
||||
}
|
||||
else if ((0.0 == tx_rate) && IsOpen())
|
||||
{
|
||||
tx_rate = txRate;
|
||||
tx_timer.SetInterval(0.0);
|
||||
ActivateTimer(tx_timer);
|
||||
if (txRate > 0.0) ActivateTimer(tx_timer);
|
||||
}
|
||||
else
|
||||
tx_rate = txRate;
|
||||
if (tx_rate > 0.0)
|
||||
{
|
||||
tx_rate = txRate;
|
||||
unsigned char grttQuantizedOld = grtt_quantized;
|
||||
double pktInterval = (double)(44+segment_size)/txRate;
|
||||
if (grtt_measured < pktInterval)
|
||||
grtt_quantized = NormQuantizeRtt(pktInterval);
|
||||
else
|
||||
grtt_quantized = NormQuantizeRtt(grtt_measured);
|
||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
|
||||
// What do we do when "pktInterval" > "grtt_max"?
|
||||
// We will take our lumps with some extra activity timeout NACKs when they happen?
|
||||
if (grtt_advertised > grtt_max)
|
||||
{
|
||||
grtt_quantized = NormQuantizeRtt(grtt_max);
|
||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
}
|
||||
|
||||
|
||||
if (grttQuantizedOld != grtt_quantized)
|
||||
DMSG(4, "NormSession::SetTxRateInternal() node>%lu %s to new grtt to: %lf sec\n",
|
||||
LocalNodeId(),
|
||||
(grttQuantizedOld < grtt_quantized) ? "increased" : "decreased",
|
||||
grtt_advertised);
|
||||
}
|
||||
unsigned char grttQuantizedOld = grtt_quantized;
|
||||
double pktInterval = (double)(44+segment_size)/tx_rate;
|
||||
if (grtt_measured < pktInterval)
|
||||
grtt_quantized = NormQuantizeRtt(pktInterval);
|
||||
else
|
||||
grtt_quantized = NormQuantizeRtt(grtt_measured);
|
||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
if (grttQuantizedOld != grtt_quantized)
|
||||
DMSG(4, "NormSession::SetTxRateInternal() node>%lu %s to new grtt to: %lf sec\n",
|
||||
LocalNodeId(),
|
||||
(grttQuantizedOld < grtt_quantized) ? "increased" : "decreased",
|
||||
grtt_advertised);
|
||||
} // end NormSession::SetTxRateInternal()
|
||||
|
||||
void NormSession::SetTxRateBounds(double rateMin, double rateMax)
|
||||
|
|
@ -292,8 +316,11 @@ void NormSession::SetTxRateBounds(double rateMin, double rateMax)
|
|||
rateMax = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (rateMin < 0.0)
|
||||
tx_rate_min = -1.0;
|
||||
else if (rateMin < 8.0)
|
||||
tx_rate_min = 1.0; // one byte/second absolute minimum
|
||||
else
|
||||
tx_rate_min = rateMin/8.0; // convert to bytes/second
|
||||
if (rateMax < 0.0)
|
||||
|
|
@ -302,11 +329,12 @@ void NormSession::SetTxRateBounds(double rateMin, double rateMax)
|
|||
tx_rate_max = rateMax/8.0; // convert to bytes/second
|
||||
if (cc_enable)
|
||||
{
|
||||
if ((tx_rate_min >= 0.0) && (tx_rate < tx_rate_min))
|
||||
tx_rate = tx_rate_min;
|
||||
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
|
||||
tx_rate = tx_rate_max;
|
||||
SetTxRateInternal(tx_rate);
|
||||
double txRate = tx_rate;
|
||||
if ((tx_rate_min > 0.0) && (txRate < tx_rate_min))
|
||||
txRate = tx_rate_min;
|
||||
if ((tx_rate_max >= 0.0) && (txRate > tx_rate_max))
|
||||
txRate = tx_rate_max;
|
||||
if (txRate != tx_rate) SetTxRateInternal(txRate);
|
||||
}
|
||||
} // end NormSession::SetTxRateBounds()
|
||||
|
||||
|
|
@ -382,8 +410,6 @@ bool NormSession::StartServer(UINT16 instanceId,
|
|||
|
||||
instance_id = instanceId;
|
||||
segment_size = segmentSize;
|
||||
sent_rate = 0.0;
|
||||
prev_update_time.tv_sec = prev_update_time.tv_usec = 0;
|
||||
sent_accumulator = 0;
|
||||
nominal_packet_size = (double)segmentSize;
|
||||
data_active = false;
|
||||
|
|
@ -394,14 +420,26 @@ bool NormSession::StartServer(UINT16 instanceId,
|
|||
|
||||
if (cc_enable)
|
||||
{
|
||||
tx_rate = segmentSize;
|
||||
if ((tx_rate_min >= 0.0) && (tx_rate < tx_rate_min))
|
||||
tx_rate = tx_rate_min;
|
||||
double txRate;
|
||||
if(tx_rate_min > 0.0)
|
||||
{
|
||||
txRate = tx_rate_min;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't let txRate below MIN(one segment per grtt, one segment per seconds)
|
||||
txRate = ((double)segment_size) / grtt_measured;
|
||||
if (txRate > ((double)(segment_size)))
|
||||
txRate = (double)(segment_size);
|
||||
}
|
||||
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
|
||||
tx_rate = tx_rate_max;
|
||||
txRate = tx_rate_max;
|
||||
tx_rate = txRate; // keep grtt at initial
|
||||
//SetTxRateInternal(txRate); // adjusts grtt_advertised as needed
|
||||
}
|
||||
grtt_age = 0.0;
|
||||
probe_pending = false;
|
||||
probe_data_check = false;
|
||||
if (probe_reset)
|
||||
{
|
||||
probe_reset = false;
|
||||
|
|
@ -428,6 +466,7 @@ void NormSession::StopServer()
|
|||
NormObject* obj = tx_table.Find(tx_table.RangeLo());
|
||||
ASSERT(obj);
|
||||
tx_table.Remove(obj);
|
||||
obj->Close();
|
||||
obj->Release();
|
||||
}
|
||||
// Then destroy table
|
||||
|
|
@ -680,7 +719,6 @@ void NormSession::Serve()
|
|||
posted_tx_queue_empty = true;
|
||||
Notify(NormController::TX_QUEUE_EMPTY, (NormServerNode*)NULL, obj);
|
||||
// (TBD) Was session deleted?
|
||||
//Serve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -702,13 +740,12 @@ void NormSession::Serve()
|
|||
// No pending objects or positive acknowledgement request
|
||||
if (!posted_tx_queue_empty)
|
||||
{
|
||||
data_active = false;
|
||||
data_active = false; // (TBD) should we wait until the flush process completes before setting false???
|
||||
posted_tx_queue_empty = true;
|
||||
Notify(NormController::TX_QUEUE_EMPTY,
|
||||
(NormServerNode*)NULL,
|
||||
(NormObject*)NULL);
|
||||
// (TBD) Was session deleted?
|
||||
//Serve();
|
||||
return;
|
||||
}
|
||||
if (flush_count < NORM_ROBUST_FACTOR)
|
||||
|
|
@ -732,8 +769,6 @@ void NormSession::ServerSetWatermark(NormObjectId objectId,
|
|||
NormBlockId blockId,
|
||||
NormSegmentId segmentId)
|
||||
{
|
||||
TRACE("NormSession::ServerSetWatermark(%hu:%lu:%hu) ...\n",
|
||||
(UINT16)objectId, (UINT32)blockId, (UINT16)segmentId);
|
||||
watermark_pending = true;
|
||||
watermark_active = false;
|
||||
watermark_object_id = objectId;
|
||||
|
|
@ -894,12 +929,14 @@ bool NormSession::ServerQueueWatermarkFlush()
|
|||
}
|
||||
else if (NULL != acking_node_tree.GetRoot())
|
||||
{
|
||||
ReturnMessageToPool(flush);
|
||||
DMSG(4, "NormSession::ServeQueueWatermarkFlush() node>%lu watermark ack finished.\n");
|
||||
Notify(NormController::TX_WATERMARK_COMPLETED, (NormServerNode*)NULL, (NormObject*)NULL);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnMessageToPool(flush);
|
||||
DMSG(2, "NormSession::ServeQueueWatermarkFlush() node>%lu no acking nodes specified?!\n");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -940,16 +977,21 @@ void NormSession::ServerQueueFlush()
|
|||
}
|
||||
else
|
||||
{
|
||||
// Why did I do this? - Brian
|
||||
// Why did I do this? - Brian // Because a squelch keeps the receivers from NACKing in futility
|
||||
// (TBD) send NORM_CMD(EOT) instead? - no
|
||||
if (ServerQueueSquelch(next_tx_object_id))
|
||||
{
|
||||
if (flush_count < NORM_ROBUST_FACTOR) flush_count++;
|
||||
flush_timer.SetInterval(2*grtt_advertised);
|
||||
flush_timer.SetInterval(4*grtt_advertised);
|
||||
ActivateTimer(flush_timer);
|
||||
DMSG(8, "NormSession::ServerQueueFlush() node>%lu squelch queued (flush_count:%u)...\n",
|
||||
LocalNodeId(), flush_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "NormSession::ServerQueueFlush() warning: node>%lu unable to queue squelch\n",
|
||||
LocalNodeId());
|
||||
}
|
||||
DMSG(8, "NormSession::ServerQueueFlush() node>%lu squelch queued (flush_count:%u)...\n",
|
||||
LocalNodeId(), flush_count);
|
||||
return;
|
||||
}
|
||||
NormCmdFlushMsg* flush = (NormCmdFlushMsg*)GetMessageFromPool();
|
||||
|
|
@ -973,14 +1015,14 @@ void NormSession::ServerQueueFlush()
|
|||
DMSG(0, "NormSession::ServerQueueFlush() node>%lu message_pool exhausted! (couldn't flush)\n",
|
||||
LocalNodeId());
|
||||
}
|
||||
flush_timer.SetInterval(2*grtt_advertised);
|
||||
flush_timer.SetInterval(4*grtt_advertised);
|
||||
ActivateTimer(flush_timer);
|
||||
} // end NormSession::ServerQueueFlush()
|
||||
|
||||
bool NormSession::OnFlushTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
flush_timer.Deactivate();
|
||||
PromptServer();//Serve(); // (TBD) Change this to PromptServer() ??
|
||||
PromptServer();
|
||||
return false;
|
||||
} // NormSession::OnFlushTimeout()
|
||||
|
||||
|
|
@ -1000,6 +1042,8 @@ void NormSession::QueueMessage(NormMsg* msg)
|
|||
}
|
||||
lastTime = currentTime;
|
||||
*/
|
||||
// (TBD) if (0.0 == tx_rate), should we just dump the
|
||||
// message rather than queueing it?
|
||||
if (!tx_timer.IsActive() && (tx_rate > 0.0))
|
||||
{
|
||||
tx_timer.SetInterval(0.0);
|
||||
|
|
@ -1348,7 +1392,6 @@ void NormTrace(const struct timeval& currentTime,
|
|||
const NormMsg& msg,
|
||||
bool sent)
|
||||
{
|
||||
//if (DebugLevel() < 8) return; // (TBD) provide per-session trace on/off switch
|
||||
static const char* MSG_NAME[] =
|
||||
{
|
||||
"INVALID",
|
||||
|
|
@ -1421,15 +1464,18 @@ void NormTrace(const struct timeval& currentTime,
|
|||
(UINT16)data.GetFecSymbolId());
|
||||
if (data.IsData() && data.IsStream())
|
||||
{
|
||||
if (NormDataMsg::StreamPayloadFlagIsSet(data.GetPayload(), NormDataMsg::FLAG_MSG_START))
|
||||
//if (NormDataMsg::StreamPayloadFlagIsSet(data.GetPayload(), NormDataMsg::FLAG_MSG_START))
|
||||
if (0 != NormDataMsg::ReadStreamPayloadMsgStart(data.GetPayload()))
|
||||
{
|
||||
// (TBD) use "payload_msg_start" value for this ...
|
||||
// We usually use the first two bytes of "messages"
|
||||
// as a "message length" header
|
||||
UINT16 x;
|
||||
memcpy(&x, data.GetPayloadData(), 2);
|
||||
DMSG(0, "start word>%hu ", ntohs(x));
|
||||
}
|
||||
if (NormDataMsg::StreamPayloadFlagIsSet(data.GetPayload(), NormDataMsg::FLAG_STREAM_END))
|
||||
//if (NormDataMsg::StreamPayloadFlagIsSet(data.GetPayload(), NormDataMsg::FLAG_STREAM_END))
|
||||
if (0 == NormDataMsg::ReadStreamPayloadLength(data.GetPayload()))
|
||||
DMSG(0, "(stream end) ");
|
||||
}
|
||||
break;
|
||||
|
|
@ -1479,7 +1525,7 @@ void NormTrace(const struct timeval& currentTime,
|
|||
if (NormHeaderExtension::CC_RATE == ext.GetType())
|
||||
{
|
||||
UINT16 sendRate = ((NormCCRateExtension&)ext).GetSendRate();
|
||||
DMSG(0, " rate>%f ", (8.0/1000.0) * NormUnquantizeRate(sendRate));
|
||||
DMSG(0, " rate>%f ", 8.0e-03 * NormUnquantizeRate(sendRate));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1620,7 +1666,7 @@ void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
|
|||
return;
|
||||
}
|
||||
}
|
||||
theServer->Activate();
|
||||
theServer->Activate(true);
|
||||
theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
|
||||
theServer->SetAddress(msg.GetSource());
|
||||
theServer->IncrementRecvTotal(msg.GetLength()); // for statistics only (TBD) #ifdef NORM_DEBUG
|
||||
|
|
@ -1677,7 +1723,7 @@ void NormSession::ClientHandleCommand(const struct timeval& currentTime,
|
|||
return;
|
||||
}
|
||||
}
|
||||
theServer->Activate();
|
||||
theServer->Activate(false);
|
||||
theServer->UpdateLossEstimate(currentTime, cmd.GetSequence());
|
||||
theServer->SetAddress(cmd.GetSource());
|
||||
theServer->IncrementRecvTotal(cmd.GetLength()); // for statistics only (TBD) #ifdef NORM_DEBUG
|
||||
|
|
@ -1721,14 +1767,12 @@ double NormSession::CalculateRtt(const struct timeval& currentTime,
|
|||
void NormSession::ServerUpdateGrttEstimate(double clientRtt)
|
||||
{
|
||||
grtt_response = true;
|
||||
|
||||
|
||||
if ((clientRtt > grtt_measured) || !address.IsMulticast())
|
||||
{
|
||||
// Immediately incorporate bigger RTT's
|
||||
grtt_decrease_delay_count = DEFAULT_GRTT_DECREASE_DELAY;
|
||||
//grtt_measured = 0.25 * grtt_measured + 0.75 * clientRtt;
|
||||
grtt_measured = 0.9 * grtt_measured + 0.1 * clientRtt;
|
||||
grtt_measured = 0.25 * grtt_measured + 0.75 * clientRtt;
|
||||
//grtt_measured = 0.9 * grtt_measured + 0.1 * clientRtt;
|
||||
if (grtt_measured > grtt_max) grtt_measured = grtt_max;
|
||||
UINT8 grttQuantizedOld = grtt_quantized;
|
||||
double pktInterval = ((double)(44+segment_size))/tx_rate;
|
||||
|
|
@ -1738,6 +1782,11 @@ void NormSession::ServerUpdateGrttEstimate(double clientRtt)
|
|||
grtt_quantized = NormQuantizeRtt(grtt_measured);
|
||||
// Calculate grtt_advertised since quantization rounds upward
|
||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
if (grtt_advertised > grtt_max)
|
||||
{
|
||||
grtt_quantized = NormQuantizeRtt(grtt_max);
|
||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
}
|
||||
grtt_current_peak = grtt_measured;
|
||||
if (grttQuantizedOld != grtt_quantized)
|
||||
DMSG(4, "NormSession::ServerUpdateGrttEstimate() node>%lu increased to new grtt>%lf sec\n",
|
||||
|
|
@ -1804,7 +1853,9 @@ void NormSession::ServerHandleCCFeedback(struct timeval currentTime,
|
|||
// 1) Does this response replace the active CLR?
|
||||
if (next && next->IsActive())
|
||||
{
|
||||
if (ccRate < next->GetRate() || (nodeId == next->GetId()))
|
||||
if ((nodeId == next->GetId()) ||
|
||||
(ccRate < next->GetRate()) ||
|
||||
((ccRate < (next->GetRate() * 1.1)) && (ccRtt > next->GetRtt()))) // use Rtt as tie-breaker if close
|
||||
{
|
||||
NormNodeId savedId = next->GetId();
|
||||
bool savedRttStatus = next->HasRtt();
|
||||
|
|
@ -2519,8 +2570,32 @@ void NormSession::ClientHandleNackMessage(const NormNackMsg& nack)
|
|||
|
||||
bool NormSession::ServerQueueSquelch(NormObjectId objectId)
|
||||
{
|
||||
// (TBD) if a squelch is already queued, update it if (objectId < squelch->objectId)
|
||||
NormCmdSquelchMsg* squelch = (NormCmdSquelchMsg*)GetMessageFromPool();
|
||||
// If a squelch is already queued, update it if (objectId < squelch->objectId)
|
||||
bool doEnqueue = true;
|
||||
NormCmdSquelchMsg* squelch = NULL;
|
||||
NormMsg* msg = message_pool.GetHead();
|
||||
while (NULL != msg)
|
||||
{
|
||||
if (NormMsg::CMD == msg->GetType())
|
||||
{
|
||||
if (NormCmdMsg::SQUELCH == static_cast<NormCmdMsg*>(msg)->GetFlavor())
|
||||
{
|
||||
squelch = static_cast<NormCmdSquelchMsg*>(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg = msg->GetNext();
|
||||
}
|
||||
if (NULL != squelch)
|
||||
{
|
||||
if (objectId >= squelch->GetObjectId())
|
||||
return false; // no need to update squelch
|
||||
doEnqueue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
squelch = (NormCmdSquelchMsg*)GetMessageFromPool();
|
||||
}
|
||||
if (squelch)
|
||||
{
|
||||
squelch->Init();
|
||||
|
|
@ -2577,9 +2652,17 @@ bool NormSession::ServerQueueSquelch(NormObjectId objectId)
|
|||
nextId++;
|
||||
}
|
||||
}
|
||||
QueueMessage(squelch);
|
||||
DMSG(4, "NormSession::ServerQueueSquelch() node>%lu server queued squelch ...\n",
|
||||
LocalNodeId());
|
||||
if (doEnqueue)
|
||||
{
|
||||
QueueMessage(squelch);
|
||||
DMSG(4, "NormSession::ServerQueueSquelch() node>%lu server queued squelch ...\n",
|
||||
LocalNodeId());
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(4, "NormSession::ServerQueueSquelch() node>%lu server updated squelch ...\n",
|
||||
LocalNodeId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
@ -2637,6 +2720,8 @@ bool NormSession::ServerBuildRepairAdv(NormCmdRepairAdvMsg& cmd)
|
|||
if (0 == cmd.PackRepairRequest(req))
|
||||
{
|
||||
DMSG(0, "NormSession::ServerBuildRepairAdv() warning: full msg\n");
|
||||
// (TBD) set NORM_REPAIR_ADV_LIMIT flag in this case
|
||||
prevForm = NormRepairRequest::INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2669,7 +2754,13 @@ bool NormSession::ServerBuildRepairAdv(NormCmdRepairAdvMsg& cmd)
|
|||
{
|
||||
if ((NormRepairRequest::INVALID != prevForm) && currentObject->IsRepairPending())
|
||||
{
|
||||
cmd.PackRepairRequest(req); // (TBD) error check;
|
||||
if (0 == cmd.PackRepairRequest(req))
|
||||
{
|
||||
DMSG(0, "NormSession::ServerBuildRepairAdv() warning: full msg\n");
|
||||
// (TBD) set NORM_REPAIR_ADV_LIMIT flag in this case
|
||||
prevForm = NormRepairRequest::INVALID;
|
||||
break;
|
||||
}
|
||||
prevForm = NormRepairRequest::INVALID;
|
||||
currentObject->AppendRepairAdv(cmd);
|
||||
}
|
||||
|
|
@ -2684,6 +2775,7 @@ bool NormSession::ServerBuildRepairAdv(NormCmdRepairAdvMsg& cmd)
|
|||
{
|
||||
if (0 == cmd.PackRepairRequest(req))
|
||||
DMSG(0, "NormSession::ServerBuildRepairAdv() warning: full msg\n");
|
||||
// (TBD) set NORM_REPAIR_ADV_LIMIT flag in this case
|
||||
}
|
||||
return true;
|
||||
} // end NormSession::ServerBuildRepairAdv()
|
||||
|
|
@ -2716,18 +2808,20 @@ bool NormSession::OnRepairTimeout(ProtoTimer& /*theTimer*/)
|
|||
}
|
||||
else
|
||||
{
|
||||
//DMSG(6, "NormSession::OnRepairTimeout() node>%lu activating obj>%hu repairs ...\n",
|
||||
// LocalNodeId(), (UINT16)objectId);
|
||||
DMSG(6, "NormSession::OnRepairTimeout() node>%lu activating obj>%hu repairs ...\n",
|
||||
LocalNodeId(), (UINT16)objectId);
|
||||
if (obj->ActivateRepairs())
|
||||
{
|
||||
DMSG(6, "NormSession::OnRepairTimeout() node>%lu activated obj>%hu repairs ...\n",
|
||||
LocalNodeId(), (UINT16)objectId);
|
||||
DMSG(6, "NormSession::OnRepairTimeout() node>%lu activated obj>%hu repairs fd=%d...\n",
|
||||
LocalNodeId(), (UINT16)objectId, static_cast<NormFileObject*>(obj)->file.fd);
|
||||
if (!tx_pending_mask.Set(objectId))
|
||||
DMSG(0, "NormSession::OnRepairTimeout() rx_pending_mask.Set(%hu) error (2)\n",
|
||||
(UINT16)objectId);
|
||||
}
|
||||
}
|
||||
} // end while (iterator.GetNextObject())
|
||||
} // end while (iterator.GetNextObject())
|
||||
// (TBD) should this be just PromptServer() instead???
|
||||
// (note we do set posted_tx_queue_empty when repair state blocks stream progress)
|
||||
TouchServer();
|
||||
// BACKOFF related code
|
||||
// Holdoff initiation of new repair cycle for one GRTT
|
||||
|
|
@ -2800,6 +2894,8 @@ bool NormSession::OnTxTimeout(ProtoTimer& /*theTimer*/)
|
|||
{
|
||||
if (SendMessage(*msg))
|
||||
{
|
||||
if (tx_rate > 0.0)
|
||||
tx_timer.SetInterval(msg->GetLength() / tx_rate);
|
||||
if (advertise_repairs)
|
||||
advertise_repairs = false;
|
||||
else
|
||||
|
|
@ -2840,10 +2936,7 @@ bool NormSession::OnTxTimeout(ProtoTimer& /*theTimer*/)
|
|||
|
||||
bool NormSession::SendMessage(NormMsg& msg)
|
||||
{
|
||||
struct timeval currentTime;
|
||||
ProtoSystemTime(currentTime);
|
||||
|
||||
bool clientMsg = false;
|
||||
bool isClientMsg = false;
|
||||
bool isProbe = false;
|
||||
|
||||
// Fill in any last minute timestamps
|
||||
|
|
@ -2860,9 +2953,15 @@ bool NormSession::SendMessage(NormMsg& msg)
|
|||
switch (((NormCmdMsg&)msg).GetFlavor())
|
||||
{
|
||||
case NormCmdMsg::CC:
|
||||
{
|
||||
struct timeval currentTime;
|
||||
ProtoSystemTime(currentTime);
|
||||
((NormCmdCCMsg&)msg).SetSendTime(currentTime);
|
||||
isProbe = true;
|
||||
break;
|
||||
}
|
||||
case NormCmdMsg::SQUELCH:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -2871,11 +2970,13 @@ bool NormSession::SendMessage(NormMsg& msg)
|
|||
|
||||
case NormMsg::NACK:
|
||||
{
|
||||
clientMsg = true;
|
||||
isClientMsg = true;
|
||||
NormNackMsg& nack = (NormNackMsg&)msg;
|
||||
NormServerNode* theServer =
|
||||
(NormServerNode*)server_tree.FindNodeById(nack.GetServerId());
|
||||
ASSERT(theServer);
|
||||
struct timeval currentTime;
|
||||
ProtoSystemTime(currentTime);
|
||||
struct timeval grttResponse;
|
||||
theServer->CalculateGrttResponse(currentTime, grttResponse);
|
||||
nack.SetGrttResponse(grttResponse);
|
||||
|
|
@ -2884,12 +2985,14 @@ bool NormSession::SendMessage(NormMsg& msg)
|
|||
|
||||
case NormMsg::ACK:
|
||||
{
|
||||
clientMsg = true;
|
||||
isClientMsg = true;
|
||||
NormAckMsg& ack = (NormAckMsg&)msg;
|
||||
NormServerNode* theServer =
|
||||
(NormServerNode*)server_tree.FindNodeById(ack.GetServerId());
|
||||
ASSERT(theServer);
|
||||
struct timeval grttResponse;
|
||||
struct timeval currentTime;
|
||||
ProtoSystemTime(currentTime);
|
||||
theServer->CalculateGrttResponse(currentTime, grttResponse);
|
||||
ack.SetGrttResponse(grttResponse);
|
||||
break;
|
||||
|
|
@ -2905,7 +3008,7 @@ bool NormSession::SendMessage(NormMsg& msg)
|
|||
bool result = true;
|
||||
// Possibly drop some tx messages for testing purposes
|
||||
bool drop = (UniformRand(100.0) < tx_loss_rate);
|
||||
if (drop || (clientMsg && client_silent))
|
||||
if (drop || (isClientMsg && client_silent))
|
||||
{
|
||||
//DMSG(0, "TX MESSAGE DROPPED! (tx_loss_rate:%lf\n", tx_loss_rate);
|
||||
}
|
||||
|
|
@ -2915,36 +3018,14 @@ bool NormSession::SendMessage(NormMsg& msg)
|
|||
msg.GetDestination()))
|
||||
{
|
||||
// Separate send/recv tracing
|
||||
if (trace) NormTrace(currentTime, LocalNodeId(), msg, true);
|
||||
|
||||
// Keep track of _actual_ sent rate
|
||||
// (TBD) move "sent_rate" tracking to ""OnReportTimeout()
|
||||
// since it is no longer critical to protocol operation
|
||||
// but just kept for information purposes ...
|
||||
if (prev_update_time.tv_sec || prev_update_time.tv_usec)
|
||||
if (trace)
|
||||
{
|
||||
double interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
|
||||
if (currentTime.tv_usec > prev_update_time.tv_sec)
|
||||
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
|
||||
else
|
||||
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
|
||||
if (interval < 1.0) //grtt_advertised)
|
||||
{
|
||||
sent_accumulator += msgSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
sent_rate = ((double)(sent_accumulator)) / interval;
|
||||
prev_update_time = currentTime;
|
||||
sent_accumulator = msgSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sent_rate = ((double)msgSize) / grtt_advertised;
|
||||
prev_update_time = currentTime;
|
||||
sent_accumulator = msgSize;
|
||||
struct timeval currentTime;
|
||||
ProtoSystemTime(currentTime);
|
||||
NormTrace(currentTime, LocalNodeId(), msg, true);
|
||||
}
|
||||
// To keep track of _actual_ sent rate
|
||||
sent_accumulator += msgSize;
|
||||
// Update nominal packet size
|
||||
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
|
||||
}
|
||||
|
|
@ -2954,19 +3035,36 @@ bool NormSession::SendMessage(NormMsg& msg)
|
|||
result = false;
|
||||
}
|
||||
}
|
||||
if (result && isProbe)
|
||||
if (result)
|
||||
{
|
||||
probe_pending = false;
|
||||
if (probe_reset)
|
||||
if (isProbe)
|
||||
{
|
||||
probe_reset = false;
|
||||
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);
|
||||
probe_pending = false;
|
||||
probe_data_check = true;
|
||||
if (probe_reset)
|
||||
{
|
||||
probe_reset = false;
|
||||
if (!probe_timer.IsActive())
|
||||
ActivateTimer(probe_timer);
|
||||
}
|
||||
}
|
||||
else if (!isClientMsg)
|
||||
{
|
||||
probe_data_check = false;
|
||||
if (!probe_pending && probe_reset)
|
||||
{
|
||||
probe_reset = false;
|
||||
OnProbeTimeout(probe_timer);
|
||||
if (!probe_timer.IsActive())
|
||||
ActivateTimer(probe_timer);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tx_timer.SetInterval(((double)msgSize) / tx_rate);
|
||||
return result;
|
||||
} // end NormSession::SendMessage()
|
||||
|
||||
void NormSession::SetGrttProbingInterval(double intervalMin, double intervalMax)
|
||||
|
|
@ -2978,8 +3076,8 @@ void NormSession::SetGrttProbingInterval(double intervalMin, double intervalMax)
|
|||
intervalMin = intervalMax;
|
||||
intervalMax = temp;
|
||||
}
|
||||
if (intervalMin < 0.100) intervalMin = 0.100;
|
||||
if (intervalMax < 0.100) intervalMax = 0.100;
|
||||
if (intervalMin < NORM_TICK_MIN) intervalMin = NORM_TICK_MIN;
|
||||
if (intervalMax < NORM_TICK_MIN) intervalMax = NORM_TICK_MIN;
|
||||
grtt_interval_min = intervalMin;
|
||||
grtt_interval_max = intervalMax;
|
||||
if (grtt_interval < grtt_interval_min)
|
||||
|
|
@ -3047,10 +3145,12 @@ void NormSession::SetGrttProbingMode(ProbingMode probingMode)
|
|||
bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
// 1) Temporarily kill probe_timer if CMD(CC) not yet tx'd
|
||||
if (probe_pending)
|
||||
// (or if data has not been sent since last probe)
|
||||
if (probe_pending || (data_active && probe_data_check))
|
||||
{
|
||||
probe_reset = true;
|
||||
probe_timer.Deactivate();
|
||||
if (probe_timer.IsActive())
|
||||
probe_timer.Deactivate();
|
||||
return false;
|
||||
}
|
||||
else if (0.0 == tx_rate)
|
||||
|
|
@ -3100,13 +3200,17 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
|||
// Update grtt estimate
|
||||
if (grtt_current_peak < grtt_measured)
|
||||
{
|
||||
if (grtt_decrease_delay_count-- == 0)
|
||||
grtt_measured *= 0.9;
|
||||
if (grtt_current_peak > grtt_measured)
|
||||
grtt_measured = grtt_current_peak;
|
||||
// (TBD) "grtt_decrease_delay_count" isn't needed any more ...
|
||||
/*if (grtt_decrease_delay_count-- == 0)
|
||||
{
|
||||
grtt_measured = 0.5 * grtt_measured +
|
||||
0.5 * grtt_current_peak;
|
||||
grtt_current_peak = 0.0;
|
||||
grtt_decrease_delay_count = DEFAULT_GRTT_DECREASE_DELAY;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3126,6 +3230,11 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
|||
grtt_quantized = NormQuantizeRtt(grtt_measured);
|
||||
// Recalculate grtt_advertise since quantization rounds upward
|
||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
if (grtt_advertised > grtt_max)
|
||||
{
|
||||
grtt_quantized = NormQuantizeRtt(grtt_max);
|
||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||
}
|
||||
if (grttQuantizedOld != grtt_quantized)
|
||||
DMSG(4, "NormSession::OnProbeTimeout() node>%lu decreased to new grtt to: %lf sec\n",
|
||||
LocalNodeId(), grtt_advertised);
|
||||
|
|
@ -3198,8 +3307,12 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
|||
else
|
||||
feedbackAge -= 1.0e-06*((double)(feedbackTime.tv_usec - currentTime.tv_usec));
|
||||
double maxFeedbackAge = 5 * grtt_advertised;
|
||||
if (maxFeedbackAge < 0.100)
|
||||
maxFeedbackAge = 0.100; // due computer clock coarseness
|
||||
// Safety bound to compensate for computer clock coarseness
|
||||
// and possible sluggish feedback from slower machines
|
||||
// at higher norm data rates (keeps rate from being
|
||||
// prematurely reduced)
|
||||
if (maxFeedbackAge <(10*NORM_TICK_MIN))
|
||||
maxFeedbackAge = (10*NORM_TICK_MIN);
|
||||
if (feedbackAge > maxFeedbackAge)
|
||||
next->SetActive(false);
|
||||
}
|
||||
|
|
@ -3223,9 +3336,10 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
|||
// Determine next probe_interval
|
||||
probeInterval = grtt_interval;
|
||||
}
|
||||
// perhaps this instead of the commented out probe_reset case???
|
||||
/*// perhaps this instead of the commented out probe_reset case???
|
||||
double nominalInterval = ((double)segment_size)/((double)tx_rate);
|
||||
if (nominalInterval > probeInterval) probeInterval = nominalInterval;
|
||||
if (nominalInterval > grtt_max) nominalInterval = grtt_max;
|
||||
if (nominalInterval > probeInterval) probeInterval = nominalInterval; */
|
||||
|
||||
// Set probe_timer interval for next probe
|
||||
probe_timer.SetInterval(probeInterval);
|
||||
|
|
@ -3254,9 +3368,12 @@ void NormSession::AdjustRate(bool onResponse)
|
|||
if (cc_slow_start)
|
||||
{
|
||||
txRate = clr->GetRate();
|
||||
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);
|
||||
if (GetDebugLevel() >= 6)
|
||||
{
|
||||
double sentRate = 8.0e-03*((double)sent_accumulator) / (report_timer.GetInterval() - report_timer.GetTimeRemaining());
|
||||
DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
|
||||
clr->GetId(), 8.0e-03*txRate, 8.0e-03*tx_rate, sentRate, 8.0e-03*clr->GetRate());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3271,8 +3388,17 @@ void NormSession::AdjustRate(bool onResponse)
|
|||
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());
|
||||
clr->GetId(), 8.0e-03*txRate, clr->GetRtt(), clr->GetLoss());
|
||||
}
|
||||
// Adjust the probe timeout right away
|
||||
/* double probeInterval = probe_timer.GetInterval();
|
||||
if (probeInterval > ccRtt)
|
||||
{
|
||||
double elapsed = probeInterval - probe_timer.GetTimeRemaining();
|
||||
probeInterval = (ccRtt > elapsed) ? (ccRtt - elapsed) : 0.0;
|
||||
probe_timer.SetInterval(probeInterval);
|
||||
if (probe_timer.IsActive()) probe_timer.Reschedule();
|
||||
} */
|
||||
}
|
||||
}
|
||||
else if (!data_active)
|
||||
|
|
@ -3305,38 +3431,30 @@ void NormSession::AdjustRate(bool onResponse)
|
|||
// reduce rate if no active clr
|
||||
txRate *= 0.5;
|
||||
}
|
||||
|
||||
|
||||
// Don't let txRate below MIN(one segment per grtt, one segment per 4 seconds)
|
||||
double minRate = ((double)segment_size) / grtt_measured;
|
||||
if (minRate > ((double)(segment_size >> 2)))
|
||||
minRate = (double)(segment_size >> 2);
|
||||
if (txRate < minRate)
|
||||
txRate = minRate;
|
||||
|
||||
// Keep "tx_rate" within user set rate bounds (if any)
|
||||
if ((tx_rate_min >= 0.0) && (txRate < tx_rate_min))
|
||||
txRate = tx_rate_min;
|
||||
// Keep "tx_rate" within default or user set rate bounds (if any)
|
||||
double minRate;
|
||||
if(tx_rate_min > 0.0)
|
||||
{
|
||||
minRate = tx_rate_min;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't let txRate below MIN(one segment per grtt, one segment per second)
|
||||
minRate = ((double)segment_size) / grtt_measured;
|
||||
if (minRate > ((double)(segment_size)))
|
||||
minRate = (double)(segment_size);
|
||||
}
|
||||
if (txRate < minRate) txRate = minRate;
|
||||
if ((tx_rate_max >= 0.0) && (txRate > tx_rate_max))
|
||||
txRate = tx_rate_max;
|
||||
|
||||
if (txRate != tx_rate) SetTxRateInternal(txRate);
|
||||
|
||||
/*if (txRate != oldRate)
|
||||
{
|
||||
if (tx_timer.IsActive())
|
||||
{
|
||||
//double ratio = tx_rate / oldRate;
|
||||
double txInterval = tx_timer.GetInterval() * oldRate / tx_rate;
|
||||
double timeElapsed = tx_timer.GetInterval() - tx_timer.GetTimeRemaining();
|
||||
txInterval = timeElapsed < txInterval ? (txInterval - timeElapsed) : 0.0;
|
||||
tx_timer.SetInterval(txInterval);
|
||||
tx_timer.Reschedule();
|
||||
}
|
||||
}*/
|
||||
|
||||
struct timeval currentTime;
|
||||
::ProtoSystemTime(currentTime);
|
||||
double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec);
|
||||
DMSG(8, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n\n", theTime, tx_rate*(8.0/1000.0), ccRtt, ccLoss);
|
||||
DMSG(8, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n\n", theTime, 8.0e-03*tx_rate, ccRtt, ccLoss);
|
||||
} // end NormSession::AdjustRate()
|
||||
|
||||
bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
|
||||
|
|
@ -3360,16 +3478,17 @@ bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
|
|||
if (IsServer())
|
||||
{
|
||||
DMSG(2, "Local status:\n");
|
||||
double sentRate = 8.0e-03*((double)sent_accumulator) / report_timer.GetInterval(); // kbps
|
||||
sent_accumulator = 0;
|
||||
DMSG(2, " txRate>%9.3lf kbps sentRate>%9.3lf grtt>%lf\n",
|
||||
((double)tx_rate)*8.0/1000.0, sent_rate*8.0/1000.0, grtt_advertised);
|
||||
8.0e-03*tx_rate, sentRate, grtt_advertised);
|
||||
if (cc_enable)
|
||||
{
|
||||
const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head();
|
||||
if (clr)
|
||||
DMSG(2, " clr>%lu rate>%9.3lf rtt>%lf loss>%lf\n", clr->GetId(),
|
||||
clr->GetRate()*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
|
||||
}
|
||||
|
||||
DMSG(2, " clr>%lu rate>%9.3lf rtt>%lf loss>%lf %s\n", clr->GetId(),
|
||||
8.0e-03*clr->GetRate(), clr->GetRtt(), clr->GetLoss(), cc_slow_start ? "(slow_start)" : "");
|
||||
}
|
||||
}
|
||||
if (IsClient())
|
||||
{
|
||||
|
|
@ -3384,12 +3503,13 @@ bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
|
|||
DMSG(2, " rxRate>%9.3lf kbps rx_goodput>%9.3lf kbps\n", rxRate, rxGoodput);
|
||||
DMSG(2, " rxObjects> completed>%lu pending>%lu failed:%lu\n",
|
||||
next->CompletionCount(), next->PendingCount(), next->FailureCount());
|
||||
DMSG(2, " bufferUsage> current>%lu peak>%lu (overuns>%lu)\n", next->CurrentBufferUsage(),
|
||||
DMSG(2, " fecBufferUsage> current>%lu peak>%lu (overuns>%lu)\n", next->CurrentBufferUsage(),
|
||||
next->PeakBufferUsage(),
|
||||
next->BufferOverunCount());
|
||||
DMSG(2, " resyncs>%lu nacks>%lu suppressed>%lu\n", next->ResyncCount(),
|
||||
next->NackCount(),
|
||||
next->SuppressCount());
|
||||
DMSG(2, " resyncs>%lu nacks>%lu suppressed>%lu\n",
|
||||
next->ResyncCount() ? next->ResyncCount() - 1 : 0, // "ResyncCount()" is reall "SyncCount()"
|
||||
next->NackCount(),
|
||||
next->SuppressCount());
|
||||
|
||||
}
|
||||
} // end if (IsClient())
|
||||
|
|
|
|||
|
|
@ -121,6 +121,14 @@ class NormSession
|
|||
ttl = result ? theTTL : ttl;
|
||||
return result;
|
||||
}
|
||||
bool SetTOS(UINT8 theTOS)
|
||||
{
|
||||
// (TBD) call tx_socket->SetFlowLabel() to set traffic class for IPv6 sockets
|
||||
// (or should we have ProtoSocket::SetTOS() do this for us?)
|
||||
bool result = tx_socket->IsOpen() ? tx_socket->SetTOS(theTOS) : true;
|
||||
tos = result ? theTOS : ttl;
|
||||
return result;
|
||||
}
|
||||
bool SetLoopback(bool state)
|
||||
{
|
||||
bool result = tx_socket->IsOpen() ? tx_socket->SetLoopback(state) : true;
|
||||
|
|
@ -128,7 +136,11 @@ class NormSession
|
|||
return result;
|
||||
}
|
||||
void SetTxPort(UINT16 txPort) {tx_port = txPort;}
|
||||
void SetRxPortReuse(bool state) {rx_port_reuse = state;}
|
||||
void SetRxPortReuse(bool enable, bool bindToSessionAddress = true)
|
||||
{
|
||||
rx_port_reuse = enable; // allow sessionPort reuse when true
|
||||
rx_addr_bind = bindToSessionAddress; // bind rx_socket to sessionAddr when true
|
||||
}
|
||||
static double CalculateRate(double size, double rtt, double loss);
|
||||
|
||||
NormSessionMgr& GetSessionMgr() {return session_mgr;}
|
||||
|
|
@ -139,7 +151,10 @@ class NormSession
|
|||
{return rx_socket.SetRxBufferSize(bufferSize);}
|
||||
|
||||
// Session parameters
|
||||
double TxRate() {return (tx_rate * 8.0);}
|
||||
double GetTxRate()
|
||||
{
|
||||
return (tx_rate * 8.0); // convert to bits/second
|
||||
}
|
||||
// (TBD) watch timer scheduling and min/max bounds
|
||||
void SetTxRate(double txRate)
|
||||
{
|
||||
|
|
@ -384,8 +399,10 @@ class NormSession
|
|||
NormNodeId local_node_id;
|
||||
ProtoAddress address; // session destination address & port
|
||||
UINT8 ttl; // session multicast ttl
|
||||
UINT8 tos; // session IPv4 TOS (or IPv6 traffic class - TBD)
|
||||
bool loopback; // to receive own traffic
|
||||
bool rx_port_reuse; // enable port reuse
|
||||
bool rx_port_reuse; // enable rx_socket port (sessionPort) reuse when true
|
||||
bool rx_addr_bind; // bind rx_socket to sessionAddr when true
|
||||
char interface_name[32];
|
||||
double tx_rate; // bytes per second
|
||||
double tx_rate_min;
|
||||
|
|
@ -437,6 +454,7 @@ class NormSession
|
|||
bool probe_proactive;
|
||||
bool probe_pending; // true while CMD(CC) enqueued
|
||||
bool probe_reset;
|
||||
bool probe_data_check; // refrain cc probe until data is send
|
||||
struct timeval probe_time_last;
|
||||
|
||||
double grtt_interval; // current GRTT update interval
|
||||
|
|
@ -460,9 +478,7 @@ class NormSession
|
|||
UINT8 cc_sequence;
|
||||
NormNodeList cc_node_list;
|
||||
bool cc_slow_start;
|
||||
double sent_rate; // measured sent rate
|
||||
struct timeval prev_update_time; // for sent_rate measurement
|
||||
unsigned long sent_accumulator; // for sent_rate measurement
|
||||
unsigned long sent_accumulator; // for sentRate measurement
|
||||
double nominal_packet_size;
|
||||
bool data_active; // true when actively sending data
|
||||
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
|
|||
tx_object_size += tx_object_size_min;
|
||||
if (session)
|
||||
{
|
||||
TRACE("Queued file size: %lu bytes\n", tx_object_size);
|
||||
DMSG(2, "NormSimAgent::ProcessCommand(sendRandomFile) Queued file size: %lu bytes\n", tx_object_size);
|
||||
return (NULL != session->QueueTxSim(tx_object_size));
|
||||
}
|
||||
else
|
||||
|
|
@ -494,7 +494,7 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
|
|||
DMSG(0, "NormSimAgent::ProcessCommand(unicastNacks) invalid argument!\n");
|
||||
return false;
|
||||
}
|
||||
if (session) session->SetUnicastNacks(unicast_nacks);
|
||||
if (session) session->ClientSetUnicastNacks(unicast_nacks);
|
||||
return true;
|
||||
}
|
||||
else if (!strncmp("silentClient", cmd, len))
|
||||
|
|
@ -590,8 +590,6 @@ bool NormSimAgent::SendMessage(unsigned int len, const char* txBuffer)
|
|||
|
||||
void NormSimAgent::OnInputReady()
|
||||
{
|
||||
//TRACE("NormSimAgent::OnInputReady() index:%lu len:%lu\n",
|
||||
// tx_msg_index, tx_msg_len);
|
||||
if (tx_msg_index < tx_msg_len)
|
||||
{
|
||||
unsigned int bytesWrote = stream->Write(tx_msg_buffer+tx_msg_index,
|
||||
|
|
@ -618,6 +616,7 @@ bool NormSimAgent::FlushStream()
|
|||
else
|
||||
{
|
||||
DMSG(0, "NormSimAgent::FlushStream() no output stream to flush\n");
|
||||
return false;
|
||||
}
|
||||
} // end NormSimAgent::FlushStream()
|
||||
|
||||
|
|
@ -630,6 +629,7 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
{
|
||||
switch (event)
|
||||
{
|
||||
//case TX_QUEUE_VACANCY:
|
||||
case TX_QUEUE_EMPTY:
|
||||
// Can queue a new object or write to stream for transmission
|
||||
if (object && (object == stream))
|
||||
|
|
@ -638,8 +638,7 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
{
|
||||
// sending a dummy byte stream
|
||||
char buffer[NormMsg::MAX_SIZE];
|
||||
unsigned int count =
|
||||
stream->Write(buffer, segment_size, false);
|
||||
stream->Write(buffer, segment_size, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -663,7 +662,6 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
|
||||
case RX_OBJECT_NEW:
|
||||
{
|
||||
//TRACE("NormSimAgent::Notify(RX_OBJECT_NEW) ...\n");
|
||||
// It's up to the app to "accept" the object
|
||||
switch (object->GetType())
|
||||
{
|
||||
|
|
@ -695,23 +693,26 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
case NormObject::DATA:
|
||||
DMSG(0, "NormSimAgent::Notify() FILE/DATA objects not _yet_ supported...\n");
|
||||
break;
|
||||
default:
|
||||
DMSG(0, "NormSimAgent::Notify() INVALID object type!\n");
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RX_OBJECT_INFO:
|
||||
//TRACE("NormSimAgent::Notify(RX_OBJECT_INFO) ...\n");
|
||||
switch(object->GetType())
|
||||
{
|
||||
case NormObject::FILE:
|
||||
case NormObject::DATA:
|
||||
case NormObject::STREAM:
|
||||
default:
|
||||
break;
|
||||
} // end switch(object->GetType())
|
||||
break;
|
||||
|
||||
case RX_OBJECT_UPDATE:
|
||||
//TRACE("NormSimAgent::Notify(RX_OBJECT_UPDATE) ...\n");
|
||||
case RX_OBJECT_UPDATED:
|
||||
switch (object->GetType())
|
||||
{
|
||||
case NormObject::FILE:
|
||||
|
|
@ -830,6 +831,10 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
case NormObject::DATA:
|
||||
DMSG(0, "NormSimAgent::Notify() FILE/DATA objects not _yet_ supported...\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
// should never occur
|
||||
break;
|
||||
} // end switch (object->GetType())
|
||||
break;
|
||||
case RX_OBJECT_COMPLETED:
|
||||
|
|
@ -839,16 +844,19 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
case NormObject::FILE:
|
||||
//DMSG(0, "norm: Completed rx file: %s\n", ((NormFileObject*)object)->Path());
|
||||
break;
|
||||
|
||||
case NormObject::STREAM:
|
||||
ASSERT(0);
|
||||
//DMSG(0, "norm: Completed rx stream ...\n");
|
||||
break;
|
||||
case NormObject::DATA:
|
||||
ASSERT(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DMSG(0, "NormSimAgent::Notify() unhandled NormEvent type\n");
|
||||
} // end switch(event)
|
||||
} // end NormSimAgent::Notify()
|
||||
|
||||
|
|
@ -875,7 +883,7 @@ bool NormSimAgent::OnIntervalTimeout(ProtoTimer& theTimer)
|
|||
{
|
||||
DMSG(0, "NormSimAgent::OnIntervalTimeout() Error queueing tx object.\n");
|
||||
}
|
||||
TRACE("Queued file size: %lu bytes\n", tx_object_size);
|
||||
DMSG(2, "NormSimAgent::OnIntervalTimeout(() Queued file size: %lu bytes\n", tx_object_size);
|
||||
}
|
||||
interval_timer.SetInterval(tx_object_interval);
|
||||
return true;
|
||||
|
|
@ -917,7 +925,8 @@ bool NormSimAgent::StartServer()
|
|||
session->ServerSetGroupSize(group_size);
|
||||
session->ServerSetGrtt(grtt_estimate);
|
||||
// StartServer(bufferMax, segmentSize, fec_ndata, fec_nparity)
|
||||
if (!session->StartServer(tx_buffer_size, segment_size, ndata, nparity))
|
||||
UINT16 instanceId = (rand() * 65535) / RAND_MAX;
|
||||
if (!session->StartServer(instanceId, tx_buffer_size, segment_size, ndata, nparity, NULL))
|
||||
{
|
||||
DMSG(0, "NormSimAgent::OnStartup() start server error!\n");
|
||||
session_mgr.Destroy();
|
||||
|
|
@ -961,7 +970,7 @@ bool NormSimAgent::StartClient()
|
|||
session->SetTxLoss(tx_loss);
|
||||
session->SetRxLoss(rx_loss);
|
||||
|
||||
session->SetUnicastNacks(unicast_nacks);
|
||||
session->ClientSetUnicastNacks(unicast_nacks);
|
||||
session->ClientSetSilent(silent_client);
|
||||
|
||||
// StartClient(bufferSize)
|
||||
|
|
|
|||
|
|
@ -65,12 +65,14 @@ int main(int argc, char* argv[])
|
|||
6003,
|
||||
localId);
|
||||
|
||||
//NormSetTOS(session, 0x20);
|
||||
|
||||
// NOTE: These are debugging routines available (not for normal app use)
|
||||
SetDebugLevel(2);
|
||||
// Uncomment to turn on debug NORM message tracing
|
||||
//NormSetMessageTrace(session, true);
|
||||
// Uncomment to turn on some random packet loss
|
||||
//NormSetTxLoss(session, 10.0); // 10% packet loss
|
||||
NormSetTxLoss(session, 25.0); // 10% packet loss
|
||||
//NormSetRxLoss(session, 20.0);
|
||||
struct timeval currentTime;
|
||||
ProtoSystemTime(currentTime);
|
||||
|
|
@ -78,19 +80,21 @@ int main(int argc, char* argv[])
|
|||
// (and a different sender sessionId)
|
||||
srand(currentTime.tv_sec); // seed random number generator
|
||||
|
||||
//NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
||||
NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
||||
|
||||
NormSetTransmitRate(session, 256.0e+03); // in bits/second
|
||||
NormSetTransmitRate(session, 256.0e+04); // in bits/second
|
||||
|
||||
// Uncomment to enable TCP-friendly congestion control (overrides NormSetTransmitRate())
|
||||
NormSetCongestionControl(session, true);
|
||||
//NormSetCongestionControl(session, true);
|
||||
|
||||
NormSetTransmitRateBounds(session, 1000.0, -1.0);
|
||||
|
||||
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
||||
|
||||
// Uncomment to use a _specific_ transmit port number
|
||||
// (Can be the same as session port (rx port), but this
|
||||
// is _not_ recommended when unicast feedback may be
|
||||
// possible!
|
||||
// is _not_ recommended when unicast feedback may be
|
||||
// possible!)
|
||||
//NormSetTxPort(session, 6001);
|
||||
|
||||
|
||||
|
|
@ -101,10 +105,12 @@ int main(int argc, char* argv[])
|
|||
NormSetRxPortReuse(session, true);
|
||||
|
||||
// Uncomment to receive your own traffic
|
||||
//NormSetLoopback(session, true);
|
||||
NormSetLoopback(session, true);
|
||||
|
||||
//NormSetSilentReceiver(session, true);
|
||||
|
||||
// Uncomment this line to participate as a receiver
|
||||
//NormStartReceiver(session, 1024*1024);
|
||||
NormStartReceiver(session, 1024*1024);
|
||||
|
||||
// Uncomment to set large rx socket buffer size
|
||||
// (might be needed for high rate sessions)
|
||||
|
|
@ -114,7 +120,9 @@ int main(int argc, char* argv[])
|
|||
NormSessionId sessionId = (NormSessionId)rand();
|
||||
|
||||
// Uncomment the following line to start sender
|
||||
NormStartSender(session, sessionId, 1024*1024, 1420, 64, 0);
|
||||
NormStartSender(session, sessionId, 1024*1024, 1400, 64, 8);
|
||||
|
||||
//NormSetAutoParity(session, 6);
|
||||
|
||||
// Uncomment to set large tx socket buffer size
|
||||
// (might be needed for high rate sessions)
|
||||
|
|
@ -128,7 +136,7 @@ int main(int argc, char* argv[])
|
|||
const char* fileName = "file1.jpg";
|
||||
const char* fileName2 = "file2.jpg";
|
||||
// Uncomment this line to send a stream instead of the file
|
||||
stream = NormStreamOpen(session, 10*1024*1024);
|
||||
stream = NormStreamOpen(session, 2*1024*1024);
|
||||
|
||||
// NORM_FLUSH_PASSIVE automatically flushes full writes to
|
||||
// the stream.
|
||||
|
|
@ -139,21 +147,26 @@ int main(int argc, char* argv[])
|
|||
int txIndex = 0;
|
||||
int txLen = 0;
|
||||
int rxIndex = 0;
|
||||
char refBuffer[1037];
|
||||
memset(refBuffer, 'a', 1037);
|
||||
|
||||
#define STREAM_MSG_PREFIX_SIZE 1024 // we pad with 'a' character value (the msgPrefix is a prefix)
|
||||
char msgPrefix[STREAM_MSG_PREFIX_SIZE];
|
||||
memset(msgPrefix, 'a', STREAM_MSG_PREFIX_SIZE);
|
||||
bool msgSync = false;
|
||||
|
||||
int msgCount = 0;
|
||||
int recvCount = -1; // used to monitor reliable stream reception
|
||||
int sendCount = 0;
|
||||
int sendMax = -1; // -1 means unlimited
|
||||
int sendMax = 300;//-1; // -1 means unlimited
|
||||
NormEvent theEvent;
|
||||
|
||||
while (NormGetNextEvent(instance, &theEvent))
|
||||
{
|
||||
switch (theEvent.type)
|
||||
{
|
||||
case NORM_TX_QUEUE_VACANCY:
|
||||
case NORM_TX_QUEUE_EMPTY:
|
||||
fprintf(stderr, "stopping ....\n");
|
||||
NormStopInstance(instance);
|
||||
/*if (NORM_TX_QUEUE_VACANCY == theEvent.type)
|
||||
TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
||||
else
|
||||
|
|
@ -167,9 +180,9 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
if (0 == txLen)
|
||||
{
|
||||
// Write a message to the "txBuffer"
|
||||
memset(txBuffer, 'a', 1037);
|
||||
sprintf(txBuffer+1037, "normTest says hello %d ...\n", sendCount);
|
||||
memset(txBuffer, 'a', STREAM_MSG_PREFIX_SIZE);
|
||||
// Write a message into the "txBuffer" for transmission
|
||||
sprintf(txBuffer+STREAM_MSG_PREFIX_SIZE, " normTest says hello %d ...\n", sendCount);
|
||||
txLen = strlen(txBuffer);
|
||||
}
|
||||
unsigned int want = txLen - txIndex;
|
||||
|
|
@ -178,18 +191,18 @@ int main(int argc, char* argv[])
|
|||
txIndex += put;
|
||||
if (txIndex == txLen)
|
||||
{
|
||||
// Instead of "NormStreamSetFlushMode(stream, NORM_FLUSH_PASSIVE)" above
|
||||
// and "NormStreamMarkEom()" here, I could have used
|
||||
// _Instead_ of "NormStreamSetAutoFlush(stream, NORM_FLUSH_PASSIVE)" above
|
||||
// _and_ "NormStreamMarkEom()" here, I could have used
|
||||
// "NormStreamFlush(stream, true)" here to perform explicit flushing
|
||||
// and EOM marking in one fell swoop. That would be a simpler approach
|
||||
// for apps where big stream messages need to be written with
|
||||
// for apps where very big stream messages might need to be written with
|
||||
// multiple calls to "NormStreamWrite()"
|
||||
NormStreamMarkEom(stream);
|
||||
txLen = txIndex = 0;
|
||||
sendCount++;
|
||||
if (sendCount == 15)
|
||||
{
|
||||
NormSetWatermark(session, stream);
|
||||
//NormSetWatermark(session, stream);
|
||||
}
|
||||
if ((sendMax > 0) && (sendCount >= sendMax))
|
||||
{
|
||||
|
|
@ -280,57 +293,82 @@ int main(int argc, char* argv[])
|
|||
rxBuffer[rxIndex] = '\0';
|
||||
if (rxIndex > 0)
|
||||
{
|
||||
char* ptr = strchr(rxBuffer, '\n');
|
||||
if (ptr)
|
||||
// The '\n' indicates we have received an entire message
|
||||
int parsedLen = 0;
|
||||
bool searching = true;
|
||||
char* startPtr = rxBuffer;
|
||||
while (searching)
|
||||
{
|
||||
// Save sub-string length
|
||||
len = ptr - rxBuffer + 1;
|
||||
|
||||
// Validate string
|
||||
if (memcmp(rxBuffer, refBuffer, 1037))
|
||||
ptr = (char*)NULL;
|
||||
else
|
||||
ptr = strstr(rxBuffer, "hello");
|
||||
if (NULL != ptr)
|
||||
char* endPtr = strchr(startPtr, '\n');
|
||||
if (endPtr)
|
||||
{
|
||||
int value;
|
||||
if (1 == sscanf(ptr, "hello %d", &value))
|
||||
// Save sub-string message length
|
||||
parsedLen += (endPtr - startPtr + 1);
|
||||
// Validate received message string
|
||||
if (0 == memcmp(rxBuffer, msgPrefix, STREAM_MSG_PREFIX_SIZE))
|
||||
{
|
||||
if (recvCount >= 0)
|
||||
char* ptr = strstr(startPtr, "hello");
|
||||
if (ptr)
|
||||
{
|
||||
if (1 != (value - recvCount))
|
||||
TRACE("WARNING! possible break? value:%d recvCount:%d\n",
|
||||
value, recvCount);
|
||||
else
|
||||
int value;
|
||||
if (1 == sscanf(ptr, "hello %d", &value))
|
||||
{
|
||||
msgCount++; // successful recv
|
||||
//else
|
||||
// TRACE("validated recv msg len:%d\n", len);
|
||||
if (recvCount >= 0)
|
||||
{
|
||||
if (0 != (value - recvCount))
|
||||
TRACE("WARNING! possible break? value:%d recvCount:%d\n",
|
||||
value, recvCount);
|
||||
}
|
||||
//else
|
||||
// TRACE("validated recv msg len:%d\n", len);
|
||||
recvCount = value+1;
|
||||
if (0 == msgCount % 100)
|
||||
{
|
||||
TRACE("normTest: status> msgCount:%d of total:%d (%lf)\n",
|
||||
msgCount, recvCount, 100.0*((double)msgCount)/((double)recvCount));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("couldn't find index!? len:%d in %s\n", len, ptr);
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
recvCount = value;
|
||||
//if (0 == msgCount % 100)
|
||||
// TRACE("recv stream msg count: %d\n", msgCount);
|
||||
else
|
||||
{
|
||||
TRACE("couldn't find \"hello\"!? len:%d in %s\n", len, rxBuffer);
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("couldn't find index!?\n");
|
||||
TRACE("invalid received message!?\n");
|
||||
ASSERT(0);
|
||||
}
|
||||
if ((unsigned int)rxIndex > len)
|
||||
if (parsedLen >= rxIndex)
|
||||
{
|
||||
memmove(rxBuffer, rxBuffer+len, rxIndex - len);
|
||||
rxIndex -= len;
|
||||
rxIndex = 0;
|
||||
searching = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rxIndex = 0;
|
||||
startPtr = rxBuffer + parsedLen;
|
||||
}
|
||||
} // end if (endPtr)
|
||||
else if (parsedLen > 0)
|
||||
{
|
||||
memmove(rxBuffer, rxBuffer+parsedLen, rxIndex - parsedLen);
|
||||
rxIndex -= parsedLen;
|
||||
searching = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("invalid string!?\n");
|
||||
ASSERT(0);
|
||||
searching = false;
|
||||
}
|
||||
}
|
||||
} // end while(searching)
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -32,6 +32,6 @@
|
|||
|
||||
#ifndef _NORM_VERSION
|
||||
#define _NORM_VERSION
|
||||
#define VERSION "1.3b6"
|
||||
#define VERSION "1.3b7"
|
||||
#endif // _NORM_VERSION
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
This directory contains files for incorporating the NORM protocol
|
||||
into the ns-2 network simulation tool.
|
||||
|
||||
(The NORM ns-2 support may need a little tweaking to work)
|
||||
|
||||
FILES:
|
||||
|
||||
nsNormAgent.h
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ $ns_ multicast
|
|||
|
||||
# 2) Trace files are opened and ns and nam
|
||||
# tracing is enabled:
|
||||
set f [open norm.tr w]
|
||||
#$ns_ trace-all $f
|
||||
set nf [open norm.nam w]
|
||||
#$ns_ namtrace-all $nf
|
||||
set f [open example.tr w]
|
||||
$ns_ trace-all $f
|
||||
set nf [open example.nam w]
|
||||
$ns_ namtrace-all $nf
|
||||
|
||||
set numNodes 10
|
||||
|
||||
|
|
@ -53,11 +53,11 @@ puts "Configuring NORM agents ..."
|
|||
|
||||
# 5) Configure global NORM agent parameters (debugging/logging is global)
|
||||
# (Uncomment the "log" command to direct NORM debug output to a file)
|
||||
$norm(1) debug 1
|
||||
#$norm(1) log normLog.txt
|
||||
$norm(1) debug 2
|
||||
$norm(1) log normLog.txt
|
||||
|
||||
# 6) Configure NORM server agent at node 1
|
||||
$norm(1) address $group/5000
|
||||
$norm(1) address $group/1
|
||||
$norm(1) rate 32000
|
||||
$norm(1) block 1
|
||||
$norm(1) parity 0
|
||||
|
|
@ -69,7 +69,7 @@ $norm(1) txloss 0.0
|
|||
|
||||
# 7) Configure NORM client agents at other nodes
|
||||
for {set i 2} {$i <= $numNodes} {incr i} {
|
||||
$norm($i) address $group/5000
|
||||
$norm($i) address $group/1
|
||||
$norm($i) rxbuffer 100000
|
||||
$norm($i) rxloss 0.0
|
||||
#$norm($i) trace
|
||||
|
|
|
|||
|
|
@ -107,9 +107,10 @@ bool NsNormAgent::ProcessCommands(int argc, const char*const* argv)
|
|||
// query agent's current state of activity
|
||||
Tcl& tcl = Tcl::instance();
|
||||
if (IsActive())
|
||||
sprintf(tcl.result(), "on");
|
||||
Tcl_SetResult(tcl.interp(), "on", TCL_STATIC);
|
||||
//sprintf(tcl.result(), "on");
|
||||
else
|
||||
sprintf(tcl.result(), "off");
|
||||
Tcl_SetResult(tcl.interp(), "off", TCL_STATIC);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,11 @@ libnorm.a: $(LIB_OBJ)
|
|||
libnorm.so: $(LIB_OBJ)
|
||||
$(CC) $(SYSTEM_SOFLAGS) $(LIB_OBJ) $(LIBS) -o $@
|
||||
|
||||
# NORM as a dynamic library for MacOS
|
||||
libnorm.dylib: $(LIB_OBJ) $(LIBPROTO)
|
||||
$(CC) $(SYSTEM_SOFLAGS) $(LIB_OBJ) $(LIBPROTO) $(LIBS) -o $@
|
||||
|
||||
|
||||
SIM_SRC = $(NORM_SRC) $(COMMON)/normSimAgent.cpp
|
||||
SIM_OBJ = $(SIM_SRC:.cpp=-sim.o)
|
||||
|
||||
|
|
@ -74,7 +79,7 @@ TEST_SRC = $(COMMON)/normTest.cpp
|
|||
TEST_OBJ = $(TEST_SRC:.cpp=.o)
|
||||
|
||||
normTest: $(TEST_OBJ) libnorm.a $(LIBPROTO)
|
||||
$(CC) $(CFLAGS) -o $@ $(TEST_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ $(TEST_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
|
||||
|
||||
# (raft) command-line reliable tunnel helper
|
||||
RAFT_SRC = $(COMMON)/raft.cpp
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ SYSTEM = macosx
|
|||
|
||||
CC = g++
|
||||
SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
|
||||
SYSTEM_SOFLAGS = -shared
|
||||
SYSTEM_SOFLAGS = -dynamiclib
|
||||
RANLIB = ranlib
|
||||
AR = ar
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,12 @@ EndProject
|
|||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "normTest", "normTest.vcproj", "{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{50D1D52B-702A-49FE-B490-9104FC72598D} = {50D1D52B-702A-49FE-B490-9104FC72598D}
|
||||
{D7B0023C-8798-4918-8DA0-05C9054D70B9} = {D7B0023C-8798-4918-8DA0-05C9054D70B9}
|
||||
{182006F3-188F-466E-89FE-8421C0478691} = {182006F3-188F-466E-89FE-8421C0478691}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormDll", "NormDll.vcproj", "{182006F3-188F-466E-89FE-8421C0478691}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{50D1D52B-702A-49FE-B490-9104FC72598D} = {50D1D52B-702A-49FE-B490-9104FC72598D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
|
|
@ -41,6 +46,10 @@ Global
|
|||
{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug.Build.0 = Debug|Win32
|
||||
{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release.ActiveCfg = Release|Win32
|
||||
{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release.Build.0 = Release|Win32
|
||||
{182006F3-188F-466E-89FE-8421C0478691}.Debug.ActiveCfg = Debug|Win32
|
||||
{182006F3-188F-466E-89FE-8421C0478691}.Debug.Build.0 = Debug|Win32
|
||||
{182006F3-188F-466E-89FE-8421C0478691}.Release.ActiveCfg = Release|Win32
|
||||
{182006F3-188F-466E-89FE-8421C0478691}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
|
|
|
|||
BIN
win32/Norm.suo
BIN
win32/Norm.suo
Binary file not shown.
|
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="NormDll"
|
||||
ProjectGUID="{182006F3-188F-466E-89FE-8421C0478691}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\common,..\protolib\common,..\protolib\win32"
|
||||
PreprocessorDefinitions="NORM_USE_DLL;NORM_API_BUILD;_DEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/Norm.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/NormDll.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/Norm.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\common,..\protolib\common,..\protolib\win32"
|
||||
PreprocessorDefinitions="NORM_USE_DLL;NORM_API_BUILD;NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="ws2_32.lib iphlpapi.lib"
|
||||
OutputFile="$(OutDir)/Norm.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/Norm.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath="..\common\galois.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normApi.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normEncoder.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normFile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normMessage.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normNode.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normObject.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normSegment.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\normSession.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\NormDll3.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Debug/NormLib.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ObjectFile="Norm.lib"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile=".\Debug\NormLib.lib"
|
||||
OutputFile="$(OutDir)/NormLib.lib"
|
||||
SuppressStartupBanner="TRUE"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
|
|
@ -81,7 +81,6 @@
|
|||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Release/NormLib.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
|
|
@ -90,7 +89,7 @@
|
|||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile=".\Release\NormLib.lib"
|
||||
OutputFile="$(OutDir)/NormLib.lib"
|
||||
SuppressStartupBanner="TRUE"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
Version="7.10"
|
||||
Name="normTest"
|
||||
ProjectGUID="{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}"
|
||||
RootNamespace="normTest"
|
||||
SccProjectName=""
|
||||
SccLocalPath="">
|
||||
<Platforms>
|
||||
|
|
@ -23,7 +24,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\common,..\protolib\common,..\protolib\win32"
|
||||
PreprocessorDefinitions="_DEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CONSOLE"
|
||||
PreprocessorDefinitions="NORM_USE_DLL, PROTO_DEBUG, WIN32"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="TRUE"
|
||||
|
|
@ -40,10 +41,11 @@
|
|||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="iphlpapi.lib ws2_32.lib odbc32.lib odbccp32.lib"
|
||||
AdditionalDependencies="iphlpapi.lib ws2_32.lib odbc32.lib odbccp32.lib Norm.dll"
|
||||
OutputFile=".\Debug/normTest.exe"
|
||||
LinkIncremental="0"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="./"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Debug/normTest.pdb"
|
||||
SubSystem="1"
|
||||
|
|
@ -85,8 +87,8 @@
|
|||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\common,..\protolib\common,..\protolib\win32"
|
||||
PreprocessorDefinitions="NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CONSOLE"
|
||||
AdditionalIncludeDirectories="..\common;..\protolib\common;..\protolib\win32;NormDll3"
|
||||
PreprocessorDefinitions="NORM_USE_DLL, PROTO_DEBUG, WIN32, HAVE_ASSERT"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
|
|
@ -103,10 +105,12 @@
|
|||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
IgnoreImportLibrary="FALSE"
|
||||
AdditionalDependencies="iphlpapi.lib ws2_32.lib odbc32.lib odbccp32.lib"
|
||||
OutputFile=".\Release/normTest.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories=""
|
||||
ProgramDatabaseFile=".\Release/normTest.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
|
|
@ -144,23 +148,6 @@
|
|||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath="..\common\normTest.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
|
|
|||
Loading…
Reference in New Issue