v1.3b5
parent
32c42ee9c0
commit
de8a3c799b
|
|
@ -1,12 +1,12 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||||
<HTML>
|
<HTML>
|
||||||
<HEAD>
|
<HEAD>
|
||||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-15">
|
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
|
||||||
<TITLE>NORM Developer’s Guide</TITLE>
|
<TITLE>NORM Developer’s Guide</TITLE>
|
||||||
<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3 (Linux)">
|
<META NAME="GENERATOR" CONTENT="NeoOffice/J 1.1 (Unix)">
|
||||||
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
||||||
<META NAME="CREATED" CONTENT="20040824;15180000">
|
<META NAME="CREATED" CONTENT="20040824;14180000">
|
||||||
<META NAME="CHANGED" CONTENT="20050621;14191600">
|
<META NAME="CHANGED" CONTENT="20050907;17092400">
|
||||||
<META NAME="DESCRIPTION" CONTENT="NORM Object Functions 42
NORM Object Functions
NORM_OBJECT_STREAM
NORM Sender Functions 19
NORM Sender Functions
">
|
<META NAME="DESCRIPTION" CONTENT="NORM Object Functions 42
NORM Object Functions
NORM_OBJECT_STREAM
NORM Sender Functions 19
NORM Sender Functions
">
|
||||||
<META NAME="KEYWORDS" CONTENT="norm object value application function ">
|
<META NAME="KEYWORDS" CONTENT="norm object value application function ">
|
||||||
<STYLE>
|
<STYLE>
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
</TD>
|
</TD>
|
||||||
<TD WIDTH=371>
|
<TD WIDTH=371>
|
||||||
<P ALIGN=LEFT STYLE="margin-left: 0.86in; margin-top: 0.17in; font-style: normal">
|
<P ALIGN=LEFT STYLE="margin-left: 0.86in; margin-top: 0.17in; font-style: normal">
|
||||||
<FONT FACE="Helvetica, sans-serif"><FONT SIZE=6 STYLE="font-size: 28pt"><B>NORM<BR>Developer’s
|
<FONT FACE="Helvetica, sans-serif"><FONT SIZE=6 STYLE="font-size: 28pt"><B>NORM<BR>Developer’s
|
||||||
<BR>Guide</B></FONT></FONT></P>
|
<BR>Guide</B></FONT></FONT></P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
|
@ -99,8 +99,6 @@ communication needs.</P>
|
||||||
<H1 CLASS="western" ALIGN=CENTER STYLE="page-break-before: always">Table
|
<H1 CLASS="western" ALIGN=CENTER STYLE="page-break-before: always">Table
|
||||||
of Contents</H1>
|
of Contents</H1>
|
||||||
<DIV ID="Table of Contents1" DIR="LTR">
|
<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>Overview</B></FONT></P>
|
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>Overview</B></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
||||||
Initialization</B></FONT></P>
|
Initialization</B></FONT></P>
|
||||||
|
|
@ -136,6 +134,10 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormEventType">NormEventType</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormEventType">NormEventType</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormEvent">NormEvent</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormEvent">NormEvent</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDescriptor">NormDescriptor</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDescriptor">NormDescriptor</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFlushMode">NormFlushMode</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormProbingMode">NormProbingMode</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNackingMode">NormNackingMode</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
||||||
Initialization and Operation</B></FONT></P>
|
Initialization and Operation</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT></P>
|
||||||
|
|
@ -151,6 +153,7 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetUserData()">NormGetUserData()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetUserData()">NormGetUserData()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetLocalNodeId()">NormGetLocalNodeId()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetLocalNodeId()">NormGetLocalNodeId()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTxPort()">NormSetTxPort()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTxPort()">NormSetTxPort()</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetRxPortReuse()">NormSetRxPortReuse()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetMulticastInterface()">NormSetMulticastInterface()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetMulticastInterface()">NormSetMulticastInterface()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTTL()">NormSetTTL()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTTL()">NormSetTTL()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTOS()">NormSetTOS()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTOS()">NormSetTOS()</A></FONT></P>
|
||||||
|
|
@ -166,6 +169,9 @@ of Contents</H1>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitCacheBounds()">NormSetTransmitCacheBounds()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitCacheBounds()">NormSetTransmitCacheBounds()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetAutoParity()">NormSetAutoParity()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetAutoParity()">NormSetAutoParity()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttEstimate()">NormSetGrttEstimate()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttEstimate()">NormSetGrttEstimate()</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttMax()">NormSetGrttMax()</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingMode()">NormSetGrttProbingMode()</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingInterval()">NormSetGrttProbingInterval()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileEnqueue()">NormFileEnqueue()</A></FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileEnqueue()">NormFileEnqueue()</A></FONT></P>
|
||||||
|
|
@ -252,7 +258,7 @@ can be roughly summarized with the following categories of functions:</P>
|
||||||
categories roughly reflects the order of function calls required to
|
categories roughly reflects the order of function calls required to
|
||||||
use NORM in an application. The first step is to create and
|
use NORM in an application. The first step is to create and
|
||||||
initialize, as needed, at least one instance of the NORM API. Then
|
initialize, as needed, at least one instance of the NORM API. Then
|
||||||
one or more NORM transport sessions (where a “session”
|
one or more NORM transport sessions (where a “session”
|
||||||
corresponds to data exchanges on a given multicast group and host
|
corresponds to data exchanges on a given multicast group and host
|
||||||
port number) may be created and controlled. Applications may
|
port number) may be created and controlled. Applications may
|
||||||
participate as senders and/or receivers within a NORM session. NORM
|
participate as senders and/or receivers within a NORM session. NORM
|
||||||
|
|
@ -311,10 +317,10 @@ include the types <FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT>
|
||||||
and <FONT FACE="Courier"><I>NORM_OBJECT_DATA</I></FONT> which
|
and <FONT FACE="Courier"><I>NORM_OBJECT_DATA</I></FONT> which
|
||||||
represent predetermined, fixed-size application data content. The
|
represent predetermined, fixed-size application data content. The
|
||||||
only differentiation with respect to these two types is the implicit
|
only differentiation with respect to these two types is the implicit
|
||||||
“hint” to the receiver to use non-volatile (i.e. file
|
“hint” to the receiver to use non-volatile (i.e. file system)
|
||||||
system) storage or memory. This “hint” lets the receiver
|
storage or memory. This “hint” lets the receiver allocate
|
||||||
allocate appropriate storage space with no other information on the
|
appropriate storage space with no other information on the incoming
|
||||||
incoming data. The NORM implementation reads/writes data for the
|
data. The NORM implementation reads/writes data for the
|
||||||
<FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT> type directly
|
<FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT> type directly
|
||||||
from/to file storage, while application memory space is accessed for
|
from/to file storage, while application memory space is accessed for
|
||||||
the <FONT FACE="Courier"><I>NORM_OBJECT_DATA</I></FONT> type. The
|
the <FONT FACE="Courier"><I>NORM_OBJECT_DATA</I></FONT> type. The
|
||||||
|
|
@ -324,9 +330,9 @@ Using this transport paradigm, traditional, byte-oriented streaming
|
||||||
transport service (e.g. similar to that provided by a TCP socket) can
|
transport service (e.g. similar to that provided by a TCP socket) can
|
||||||
be provided. Additionally, NORM has provisions for
|
be provided. Additionally, NORM has provisions for
|
||||||
application-defined message-oriented transport where receivers can
|
application-defined message-oriented transport where receivers can
|
||||||
recover message boundaries without any “handshake” with
|
recover message boundaries without any “handshake” with the
|
||||||
the sender. Stream content is buffered by the NORM implementation
|
sender. Stream content is buffered by the NORM implementation for
|
||||||
for transmission/retransmission and as it is received.</P>
|
transmission/retransmission and as it is received.</P>
|
||||||
<H3 CLASS="western">NORM Data Transmission</H3>
|
<H3 CLASS="western">NORM Data Transmission</H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The behavior of data
|
<P CLASS="western" STYLE="font-style: normal">The behavior of data
|
||||||
transport operation is largely placed in the control of the NORM
|
transport operation is largely placed in the control of the NORM
|
||||||
|
|
@ -337,14 +343,13 @@ operate in a session, each with independent transmission parameters.
|
||||||
NORM receivers learn needed parameter values from fields in NORM
|
NORM receivers learn needed parameter values from fields in NORM
|
||||||
message headers.</P>
|
message headers.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">NORM transport
|
<P CLASS="western" STYLE="font-style: normal">NORM transport
|
||||||
“objects” (file, data, or stream) are queued for
|
“objects” (file, data, or stream) are queued for transmission by
|
||||||
transmission by NORM senders. NORM senders may also cancel
|
NORM senders. NORM senders may also cancel transmission of objects
|
||||||
transmission of objects at any time. The NORM sender controls the
|
at any time. The NORM sender controls the transmission rate either
|
||||||
transmission rate either manually (fixed transmission rate) or
|
manually (fixed transmission rate) or automatically when NORM
|
||||||
automatically when NORM congestion control operation is enabled. The
|
congestion control operation is enabled. The NORM congestion control
|
||||||
NORM congestion control mechanism is designed to be "friendly"
|
mechanism is designed to be "friendly" to other data flows
|
||||||
to other data flows on the network, fairly sharing available
|
on the network, fairly sharing available bandwidth.</P>
|
||||||
bandwidth.</P>
|
|
||||||
<P CLASS="western" STYLE="font-style: normal">By default, the NORM
|
<P CLASS="western" STYLE="font-style: normal">By default, the NORM
|
||||||
sender transmits application-enqueued data content, providing repair
|
sender transmits application-enqueued data content, providing repair
|
||||||
transmissions (usually in the form of FEC messages) only when
|
transmissions (usually in the form of FEC messages) only when
|
||||||
|
|
@ -427,15 +432,15 @@ application. Thus the "POSIX Threads" library must be
|
||||||
included ("-'pthread") in the linking step. MacOS/BSD also
|
included ("-'pthread") in the linking step. MacOS/BSD also
|
||||||
requires the addition of the "-lresolv" (resolver) library
|
requires the addition of the "-lresolv" (resolver) library
|
||||||
and Solaris requires the dynamic loader, network/socket, and resolver
|
and Solaris requires the dynamic loader, network/socket, and resolver
|
||||||
libraries ("–lnsl –lsocket –lresolv") to
|
libraries ("–lnsl –lsocket –lresolv") to achieve
|
||||||
achieve successful compilation. The Makefiles in the NORM source
|
successful compilation. The Makefiles in the NORM source code
|
||||||
code distribution are a reference for these requirements. Note that
|
distribution are a reference for these requirements. Note that MacOS
|
||||||
MacOS 9 and earlier are not supported.</P>
|
9 and earlier are not supported.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">Additionally, it is
|
<P CLASS="western" STYLE="font-style: normal">Additionally, it is
|
||||||
critical that the _FILE_OFFSET_BITS macro be consistently defined for
|
critical that the _FILE_OFFSET_BITS macro be consistently defined for
|
||||||
the NORM library build and the application build using the library.
|
the NORM library build and the application build using the library.
|
||||||
The distributed NORM Makefiles have –D_FILE_OFFSET_BITS=64 set
|
The distributed NORM Makefiles have –D_FILE_OFFSET_BITS=64 set in
|
||||||
in the compilation to enable "large file support".
|
the compilation to enable "large file support".
|
||||||
Applications built using NORM should have the same compilation option
|
Applications built using NORM should have the same compilation option
|
||||||
set to operate correctly (The definition of the <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
set to operate correctly (The definition of the <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
||||||
type in "normApi.h" depends upon this compilation flag).</P>
|
type in "normApi.h" depends upon this compilation flag).</P>
|
||||||
|
|
@ -583,10 +588,10 @@ session as part of protocol operation. Typically, the application
|
||||||
should not need access to these values, but an API call
|
should not need access to these values, but an API call
|
||||||
<FONT FACE="Courier">NormObjectGetTransportId() </FONT>is provided to
|
<FONT FACE="Courier">NormObjectGetTransportId() </FONT>is provided to
|
||||||
retrieve these values if needed. (<I>Note this type may be
|
retrieve these values if needed. (<I>Note this type may be
|
||||||
deprecated – it may not be needed at all if the
|
deprecated – it may not be needed at all if the NormObjectRequeue()
|
||||||
NormObjectRequeue() function (TBD) is implemented using handles only,
|
function (TBD) is implemented using handles only, but _some_
|
||||||
but _some_ applications requiring persistence even after a system
|
applications requiring persistence even after a system reboot may
|
||||||
reboot may need the ability to recall previous transport ids?</I>)</P>
|
need the ability to recall previous transport ids?</I>)</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormEventType">NormEventType</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormEventType">NormEventType</A></H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormEventType">NormEventType</A></FONT>
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormEventType">NormEventType</A></FONT>
|
||||||
is an enumeration of NORM API events. "Events" are used by
|
is an enumeration of NORM API events. "Events" are used by
|
||||||
|
|
@ -625,6 +630,41 @@ appropriate system calls (e.g. <I>select()</I> or
|
||||||
NORM protocol engine for notification events (see <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT>
|
NORM protocol engine for notification events (see <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT>
|
||||||
description).
|
description).
|
||||||
</P>
|
</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>
|
||||||
|
<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
|
||||||
|
these values is given in the descriptions of <FONT FACE="Courier"><A HREF="#NormStreamFlush()">NormStreamFlush()</A></FONT>
|
||||||
|
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>
|
||||||
|
<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
|
||||||
|
these values is given in the description of <FONT FACE="Courier"><A HREF="#NormSetGrttProbingMode()">NormSetGrttProbingMode()</A></FONT>
|
||||||
|
function.</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormNackingMode">NormNackingMode</A></H3>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormNackingMode">NormNackingMode</A></FONT>
|
||||||
|
consist of the following enumeration:</P>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||||
|
<A HREF="#NormNackingMode">NormNackingMode</A><BR>{<BR> NORM_NACK_NONE,<BR> NORM_NACK_INFO_ONLY,<BR> NORM_NACK_NORMAL<BR>};</FONT></FONT></P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||||
|
these values is given in the descriptions of the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormSetDefaultNackingMode()">NormSetDefaultNackingMode()</A></FONT>,
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormNodeSetNackingMode()">NormNodeSetNackingMode()</A></FONT> and
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormObjectSetNackingMode()">NormObjectSetNackingMode()</A></FONT> functions.</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormRepairBoundary">NormRepairBoundary</A></H3>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT>
|
||||||
|
consist of the following enumeration:</P>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||||
|
<A HREF="#NormRepairBoundary">NormRepairBoundary</A><BR>{<BR> NORM_BOUNDARY_BLOCK,<BR> NORM_BOUNDARY_OBJECT<BR>};</FONT></FONT></P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||||
|
these values is given in the descriptions of the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormSetDefaultRepairBoundary()">NormSetDefaultRepairBoundary()</A> </FONT>and
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormNodeSetRepairBoundary()">NormNodeSetRepairBoundary()</A></FONT> functions.</P>
|
||||||
<H2 CLASS="western">API Initialization and Operation</H2>
|
<H2 CLASS="western">API Initialization and Operation</H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The first step in using
|
<P CLASS="western" STYLE="font-style: normal">The first step in using
|
||||||
the NORM API is to create an "instance" of the NORM
|
the NORM API is to create an "instance" of the NORM
|
||||||
|
|
@ -1220,9 +1260,57 @@ reception. However, the use of separate transmit/receive ports
|
||||||
allows NORM to discriminate when unicast feedback is occurring and
|
allows NORM to discriminate when unicast feedback is occurring and
|
||||||
thus it is not generally recommended that the transmit port be set to
|
thus it is not generally recommended that the transmit port be set to
|
||||||
the same value as the <FONT FACE="Courier"><U>session</U></FONT>
|
the same value as the <FONT FACE="Courier"><U>session</U></FONT>
|
||||||
receive port. This call <I>must</I> be made <I>before</I> any calls
|
receive port.
|
||||||
to <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT> or
|
</P>
|
||||||
<FONT FACE="Courier"><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT> to succeed.</P>
|
<P CLASS="western" STYLE="font-style: normal">Note this call <I>must</I>
|
||||||
|
be made <I>before</I> any calls to <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT>
|
||||||
|
or <FONT FACE="Courier"><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT> for the given
|
||||||
|
<FONT FACE="Courier"><U>session</U></FONT> to succeed.</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="NormSetRxPortReuse()">NormSetRxPortReuse()</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
|
||||||
|
NormSetRxPortReuse(<A HREF="#NormSessionHandle">NormSessionHandle</A>
|
||||||
|
session,<BR> bool
|
||||||
|
state);</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
|
||||||
|
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
|
||||||
|
on the same port number, but participating in different multicast
|
||||||
|
groups.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">Note this call <I>must</I>
|
||||||
|
be made <I>before</I> any calls to <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT>
|
||||||
|
or <FONT FACE="Courier"><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT> for the given
|
||||||
|
<FONT FACE="Courier"><U>session</U></FONT> to succeed.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">This call could also be
|
||||||
|
used in conjunction with <FONT FACE="Courier"><A HREF="#NormSetMulticastInterface()">NormSetMulticastInterface()</A></FONT>
|
||||||
|
so that multiple <I>NormSessions</I>, using the same port and
|
||||||
|
multicast address, could separately cover multiple network interfaces
|
||||||
|
(and some sort of application-layer bridging of reliable multicast
|
||||||
|
could be realized if desired).</P>
|
||||||
<H4 CLASS="western">Return Values</H4>
|
<H4 CLASS="western">Return Values</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||||
return values.</P>
|
return values.</P>
|
||||||
|
|
@ -1462,7 +1550,7 @@ function call include:</P>
|
||||||
The maximum <FONT FACE="Courier"><U>blockSize</U></FONT> allowed
|
The maximum <FONT FACE="Courier"><U>blockSize</U></FONT> allowed
|
||||||
by the 8-bit Reed-Solomon codes in NORM is 255, with the further
|
by the 8-bit Reed-Solomon codes in NORM is 255, with the further
|
||||||
limitation that (<FONT FACE="Courier"><U>blockSize</U></FONT> +
|
limitation that (<FONT FACE="Courier"><U>blockSize</U></FONT> +
|
||||||
<FONT FACE="Courier"><U>numParity</U></FONT>) ≤ 255.</P>
|
<FONT FACE="Courier"><U>numParity</U></FONT>) ≤ 255.</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
|
|
@ -1483,15 +1571,14 @@ function call include:</P>
|
||||||
that one parity segment can fill any one erasure (missing segment
|
that one parity segment can fill any one erasure (missing segment
|
||||||
(packet)) for a coding block. For a given <FONT FACE="Courier"><U>blockSize</U></FONT>,
|
(packet)) for a coding block. For a given <FONT FACE="Courier"><U>blockSize</U></FONT>,
|
||||||
the maximum <FONT FACE="Courier"><U>numParity</U></FONT> value is
|
the maximum <FONT FACE="Courier"><U>numParity</U></FONT> value is
|
||||||
(255 – <FONT FACE="Courier"><U>blockSize</U></FONT>).
|
(255 – <FONT FACE="Courier"><U>blockSize</U></FONT>). However,
|
||||||
However, note that computational complexity increases
|
note that computational complexity increases significantly with
|
||||||
significantly with increasing <FONT FACE="Courier"><U>numParity</U></FONT>
|
increasing <FONT FACE="Courier"><U>numParity</U></FONT> values and
|
||||||
values and applications may wish to be conservative with respect
|
applications may wish to be conservative with respect to <FONT FACE="Courier"><U>numParity</U></FONT>
|
||||||
to <FONT FACE="Courier"><U>numParity</U></FONT> selection, given
|
selection, given anticipated network packet loss conditions and
|
||||||
anticipated network packet loss conditions and group size
|
group size scalability concerns. Additional FEC code options may
|
||||||
scalability concerns. Additional FEC code options may be provided
|
be provided for this NORM implementation in the future with
|
||||||
for this NORM implementation in the future with different
|
different parameters, capabilities, trade-offs, and computational
|
||||||
parameters, capabilities, trade-offs, and computational
|
|
||||||
requirements.</P>
|
requirements.</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
|
@ -1516,7 +1603,7 @@ implementation.</P>
|
||||||
is returned upon success and <FONT FACE="Courier"><I>false</I></FONT>
|
is returned upon success and <FONT FACE="Courier"><I>false</I></FONT>
|
||||||
upon failure. The reasons failure may occur include limited system
|
upon failure. The reasons failure may occur include limited system
|
||||||
resources or that the network sockets required for communication
|
resources or that the network sockets required for communication
|
||||||
failed to open or properly configure. <I>(TBD – Provide a
|
failed to open or properly configure. <I>(TBD – Provide a
|
||||||
<FONT FACE="Courier">NormGetError(<A HREF="#NormSessionHandle">NormSessionHandle</A> session)</FONT>
|
<FONT FACE="Courier">NormGetError(<A HREF="#NormSessionHandle">NormSessionHandle</A> session)</FONT>
|
||||||
function to retrieve a more specific error indication for this and
|
function to retrieve a more specific error indication for this and
|
||||||
other functions.)</I></P>
|
other functions.)</I></P>
|
||||||
|
|
@ -1777,8 +1864,9 @@ NormSetGrttEstimate(<A HREF="#NormSessionHandle">NormSessionHandle</A> sess
|
||||||
<BR> double grtt);</FONT></FONT></P>
|
<BR> double grtt);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||||
sender's estimate of group round-trip timing (GRTT). This function
|
sender's estimate of group round-trip timing (GRTT) for the given
|
||||||
is expected to most typically used to initialize the sender's GRTT
|
NORM <FONT FACE="Courier"><U>session</U></FONT>. This function is
|
||||||
|
expected to most typically used to initialize the sender's GRTT
|
||||||
estimate prior to the call to <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT>
|
estimate prior to the call to <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT>
|
||||||
when the application has <I>a priori</I> confidence that the default
|
when the application has <I>a priori</I> confidence that the default
|
||||||
initial GRTT value of 0.5 second is inappropriate. The sender GRTT
|
initial GRTT value of 0.5 second is inappropriate. The sender GRTT
|
||||||
|
|
@ -1788,7 +1876,7 @@ is active. For experimental purposes (or very special application
|
||||||
needs), this API provides a mechanism to control or disable the
|
needs), this API provides a mechanism to control or disable the
|
||||||
sender GRTT update process (see <FONT FACE="Courier">NormSetGrttProbing()</FONT>).
|
sender GRTT update process (see <FONT FACE="Courier">NormSetGrttProbing()</FONT>).
|
||||||
The <FONT FACE="Courier"><U>grtt</U></FONT> value will be limited to
|
The <FONT FACE="Courier"><U>grtt</U></FONT> value will be limited to
|
||||||
the maximum GRTT as set (see <FONT FACE="Courier">NormSetGrttMax())
|
the maximum GRTT as set (see <FONT FACE="Courier"><A HREF="#NormSetGrttMax()">NormSetGrttMax()</A>)
|
||||||
</FONT>or the default maximum of 10 seconds.
|
</FONT>or the default maximum of 10 seconds.
|
||||||
</P>
|
</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The sender GRTT is
|
<P CLASS="western" STYLE="font-style: normal">The sender GRTT is
|
||||||
|
|
@ -1800,7 +1888,125 @@ additional latency into the reliability process (resulting in a
|
||||||
larger virtual <I>delay*bandwidth</I> product for the protocol and
|
larger virtual <I>delay*bandwidth</I> product for the protocol and
|
||||||
potentially requiring more buffer space to maintain reliability). An
|
potentially requiring more buffer space to maintain reliability). An
|
||||||
overly-small GRTT estimate may introduce the potential for feedback
|
overly-small GRTT estimate may introduce the potential for feedback
|
||||||
implosion, limiting the scalability of group size.</P>
|
implosion, limiting the scalability of group size.
|
||||||
|
</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">Also note that the
|
||||||
|
advertised GRTT estimate can also be limited by transmission rate.
|
||||||
|
When the sender transmission rate is low, the GRTT is also governed
|
||||||
|
to a lower bound of the nominal packet transmission interval (i.e.,
|
||||||
|
<FONT FACE="Courier">1/txRate</FONT>). This maintains the “event
|
||||||
|
driven” nature of the NORM protocol with respect to receiver
|
||||||
|
reception of NORM sender data and commands.</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="NormSetGrttMax()">NormSetGrttMax()</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
|
||||||
|
NormSetGrttMax(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||||
|
<BR> double grttMax);</FONT></FONT></P>
|
||||||
|
<H4 CLASS="western">Description</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||||
|
sender's maximum advertised GRTT value for the given NORM <FONT FACE="Courier"><U>session</U></FONT>.
|
||||||
|
The <FONT FACE="Courier"><U>grttMax</U></FONT> parameter, in units
|
||||||
|
of <I>seconds</I>, limits the GRTT used by the group for scaling
|
||||||
|
protocol timers, regardless of larger measured round trip times.
|
||||||
|
The default maximum for the NRL NORM library is 10 seconds. See the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormSetGrttEstimate()">NormSetGrttEstimate()</A></FONT> function
|
||||||
|
description for the purpose of the NORM GRTT measurement process.</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="NormSetGrttProbingMode()">NormSetGrttProbingMode()</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
|
||||||
|
NormSetGrttProbingMode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||||
|
<BR> NormProbingMode probingMode);</FONT></FONT></P>
|
||||||
|
<H4 CLASS="western">Description</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||||
|
sender's mode of probing for round trip timing measurement responses
|
||||||
|
from the receiver set for the given NORM <FONT FACE="Courier"><U>session</U></FONT>.
|
||||||
|
Possible values for the <FONT FACE="Courier"><U>probingMode</U></FONT>
|
||||||
|
parameter include <FONT FACE="Courier"><I>NORM_PROBE_NONE</I></FONT>,
|
||||||
|
<FONT FACE="Courier"><I>NORM_PROBE_PASSIVE</I></FONT>, and
|
||||||
|
<FONT FACE="Courier"><I>NORM_PROBE_ACTIVE</I></FONT>. The default
|
||||||
|
probing mode is <FONT FACE="Courier"><I>NORM_PROBE_ACTIVE</I></FONT>.
|
||||||
|
In this mode, the receiver set explicitly acknowledges NORM sender
|
||||||
|
GRTT probes (NORM_CMD(CC) messages) with NORM_ACK responses that are
|
||||||
|
group-wise suppressed. Note that NORM receivers also will include
|
||||||
|
their response to GRTT probing piggy-backed on any NORM_NACK messages
|
||||||
|
sent in this mode as well to minimize feedback.
|
||||||
|
</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">Note that the
|
||||||
|
<FONT FACE="Courier"><I>NORM_PROBE_ACTIVE</I></FONT> probing mode is
|
||||||
|
<I>required</I> and automatically set when NORM congestion control
|
||||||
|
operation is enabled (see <FONT FACE="Courier"><A HREF="#NormSetCongestionControl()">NormSetCongestionControl()</A></FONT>).
|
||||||
|
Thus, when congestion control is enabled, the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormSetGrttProbingMode()">NormSetGrttProbingMode()</A></FONT> function has no
|
||||||
|
effect.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">If congestion control
|
||||||
|
operation is not enabled, the NORM applicaiton may elect to reduce
|
||||||
|
the volume of feedback traffic by setting the <FONT FACE="Courier"><U>probingMode</U></FONT>
|
||||||
|
to <FONT FACE="Courier"><I>NORM_PROBE_PASSIVE.</I></FONT> Here, the
|
||||||
|
NORM sender still transmits NORM_CMD(CC) probe messages multiplexed
|
||||||
|
with its data transmission, but the receiver set does not explicitly
|
||||||
|
acknowledge these probes. Instead the receiver set is limited to
|
||||||
|
piggy-backing responses when NORM_NACK messages are generated. Note
|
||||||
|
that this may, in some cases, introduce some opportunity for bursts
|
||||||
|
of large volume receiver feedback when the sender’s estimate of
|
||||||
|
GRTT is incorrect due to the reduced probing feedback. But, in some
|
||||||
|
controlled network environments, this option for passive probing may
|
||||||
|
provide some benefits in reducing protocol overhead.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">Finally, the
|
||||||
|
<FONT FACE="Courier"><U>probingMode</U></FONT> can be set to
|
||||||
|
<FONT FACE="Courier"><I>NORM_PROBE_NONE</I></FONT> to eliminate the
|
||||||
|
overhead (and benefits) of NORM GRTT measurement entirely. In this
|
||||||
|
case, the sender application must explicitly set its estimate of GRTT
|
||||||
|
using the <FONT FACE="Courier"><A HREF="#NormSetGrttEstimate()">NormSetGrttEstimate()</A></FONT> function.
|
||||||
|
See this function for a description of the purpose of the NORM GRTT
|
||||||
|
measurement.</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="NormSetGrttProbingInterval()">NormSetGrttProbingInterval()</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
|
||||||
|
NormSetGrttProbingInterval(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||||
|
<BR> double intervalMin,<BR> double intervalMax);</FONT></FONT></P>
|
||||||
|
<H4 CLASS="western">Description</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">This function controls
|
||||||
|
the sender GRTT measurement and estimation process for the given NORM
|
||||||
|
<FONT FACE="Courier"><U>session</U></FONT>. The NORM sender
|
||||||
|
multiplexes periodic transmission of NORM_CMD(CC) messages with its
|
||||||
|
ongoing data transmission or when data transmission is idle. When
|
||||||
|
NORM congestion control operation is enabled, these probes are sent
|
||||||
|
once per RTT of the current limiting receiver (with respect to
|
||||||
|
congestion control rate). In this case the <FONT FACE="Courier"><U>intervalMin</U></FONT>
|
||||||
|
and <FONT FACE="Courier"><U>intervalMax</U></FONT> parameters (in
|
||||||
|
units of <I>seconds</I>) control the rate at which the sender’s
|
||||||
|
estimate of GRTT is updated. At session start, the estimate is
|
||||||
|
updated at <FONT FACE="Courier"><U>intervalMin</U></FONT> and the
|
||||||
|
update interval time is doubled until <FONT FACE="Courier"><U>intervalMax</U></FONT>
|
||||||
|
is reached. This dynamic allows for a rapid initial estimation of
|
||||||
|
GRTT and a slower, steady-state update of GRTT. When congestion
|
||||||
|
control is disabled and NORM GRTT probing is enabled
|
||||||
|
(NORM_PROBE_ACTIVE or NORM_PROBE_PASSIVE) the <FONT FACE="Courier"><U>intervalMin</U></FONT>
|
||||||
|
and <FONT FACE="Courier"><U>intervalMax</U></FONT> values also
|
||||||
|
determine the rate at which NORM_CMD(CC) probes are transmitted by
|
||||||
|
the sender. Thus by setting larger values for <FONT FACE="Courier"><U>intervalMin</U></FONT>
|
||||||
|
and <FONT FACE="Courier"><U>intervalMax</U></FONT>, the NORM sender
|
||||||
|
application can reduce the overhead of the GRTT measurement process.
|
||||||
|
However, this also reduces the ability of NORM to adapt to changes in
|
||||||
|
GRTT.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The default NORM GRTT
|
||||||
|
<FONT FACE="Courier"><U>intervalMin</U></FONT> and <FONT FACE="Courier"><U>intervalMax</U></FONT>
|
||||||
|
values are 1.0 second and 30.0 seconds, respectively.</P>
|
||||||
<H4 CLASS="western">Return Values</H4>
|
<H4 CLASS="western">Return Values</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||||
return values.</P>
|
return values.</P>
|
||||||
|
|
@ -2057,7 +2263,7 @@ limit.</P>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>bool
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormStreamClose(<A HREF="#NormObjectHandle">NormObjectHandle</A>
|
NormStreamClose(<A HREF="#NormObjectHandle">NormObjectHandle</A>
|
||||||
streamHandle,<BR> bool graceful
|
streamHandle,<BR> bool graceful
|
||||||
= false);</FONT></FONT></P>
|
= false);</FONT></FONT></P>
|
||||||
|
|
@ -2135,7 +2341,7 @@ transmission.</P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormStreamFlush(<A HREF="#NormObjectHandle">NormObjectHandle</A>
|
NormStreamFlush(<A HREF="#NormObjectHandle">NormObjectHandle</A>
|
||||||
streamHandle,<BR> bool eom
|
streamHandle,<BR> bool eom
|
||||||
= false,<BR> NormFlushMode flushMode
|
= false,<BR> <A HREF="#NormFlushMode">NormFlushMode</A> flushMode
|
||||||
= NORM_FLUSH_PASSIVE);</FONT></FONT></P>
|
= NORM_FLUSH_PASSIVE);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function causes an
|
<P CLASS="western" STYLE="font-style: normal">This function causes an
|
||||||
|
|
@ -2157,7 +2363,7 @@ NORM to immediately transmit all enqueued data for the stream
|
||||||
(subject to session transmit rate limits), even if this results in
|
(subject to session transmit rate limits), even if this results in
|
||||||
NORM_DATA messages with "small" payloads. If the optional
|
NORM_DATA messages with "small" payloads. If the optional
|
||||||
<FONT FACE="Courier"><U>flushMode</U></FONT> parameter is set to
|
<FONT FACE="Courier"><U>flushMode</U></FONT> parameter is set to
|
||||||
<FONT FACE="Courier"><I>NORM_FLUSH_ACTIV</I></FONT>, the application
|
<FONT FACE="Courier"><I>NORM_FLUSH_ACTIVE</I></FONT>, the application
|
||||||
can achieve reliable delivery of stream content up to the current
|
can achieve reliable delivery of stream content up to the current
|
||||||
write position in an even more proactive fashion. In this case, the
|
write position in an even more proactive fashion. In this case, the
|
||||||
sender additionally, <I>actively</I> transmits NORM_CMD(FLUSH)
|
sender additionally, <I>actively</I> transmits NORM_CMD(FLUSH)
|
||||||
|
|
@ -2193,7 +2399,7 @@ return values.</P>
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormStreamSetAutoFlush(<A HREF="#NormObjectHandle">NormObjectHandle</A>
|
NormStreamSetAutoFlush(<A HREF="#NormObjectHandle">NormObjectHandle</A>
|
||||||
streamHandle<BR> NormFlushMode flushMode);</FONT></FONT></P>
|
streamHandle<BR> <A HREF="#NormFlushMode">NormFlushMode</A> flushMode);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function sets
|
<P CLASS="western" STYLE="font-style: normal">This function sets
|
||||||
"<I>automated</I> flushing" for the NORM transmit stream
|
"<I>automated</I> flushing" for the NORM transmit stream
|
||||||
|
|
@ -2387,7 +2593,7 @@ does not exist in NORM's default NACK-only operation.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The function returns
|
<P CLASS="western" STYLE="font-style: normal">The function returns
|
||||||
<FONT FACE="Courier"><I>true</I></FONT> upon successful establishment
|
<FONT FACE="Courier"><I>true</I></FONT> upon successful establishment
|
||||||
of the watermark point. The function may return <FONT FACE="Courier"><I>false</I></FONT>
|
of the watermark point. The function may return <FONT FACE="Courier"><I>false</I></FONT>
|
||||||
upon failure (<I>why would it fail? – TBD</I>).</P>
|
upon failure (<I>why would it fail? – TBD</I>).</P>
|
||||||
<H2 CLASS="western">NORM Receiver Functions</H2>
|
<H2 CLASS="western">NORM Receiver Functions</H2>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormStartReceiver()">NormStartReceiver()</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormStartReceiver()">NormStartReceiver()</A></H3>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
|
|
@ -2552,7 +2758,7 @@ NACK-messages as well as some ACK messages such as congestion control
|
||||||
feedback. Explicitly solicited ACK messages, such as those used to
|
feedback. Explicitly solicited ACK messages, such as those used to
|
||||||
satisfy sender watermark acknowledgement requests (see
|
satisfy sender watermark acknowledgement requests (see
|
||||||
<FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT>) are always unicast to
|
<FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT>) are always unicast to
|
||||||
the applicable sender. (TBD – provide API option so that <I>all</I>
|
the applicable sender. (TBD – provide API option so that <I>all</I>
|
||||||
messages are multicast.) The default session-wide behavior for
|
messages are multicast.) The default session-wide behavior for
|
||||||
unicast NACKing can be overridden via the <FONT FACE="Courier"><A HREF="#NormNodeSetUnicastNack()">NormNodeSetUnicastNack()</A></FONT>
|
unicast NACKing can be overridden via the <FONT FACE="Courier"><A HREF="#NormNodeSetUnicastNack()">NormNodeSetUnicastNack()</A></FONT>
|
||||||
function for individual remote senders.</P>
|
function for individual remote senders.</P>
|
||||||
|
|
@ -2583,7 +2789,7 @@ return values.</P>
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormSetDefaultNackingMode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
NormSetDefaultNackingMode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||||
<BR> NormNackingMode nackingMode);</FONT></FONT></P>
|
<BR> <A HREF="#NormNackingMode">NormNackingMode</A> nackingMode);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||||
default "nacking mode" used when receiving objects. This
|
default "nacking mode" used when receiving objects. This
|
||||||
|
|
@ -2650,7 +2856,7 @@ return values.</P>
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormNodeSetNackingMode(<A HREF="#NormNodeHandle">NormNodeHandle</A> nodeHandle,
|
NormNodeSetNackingMode(<A HREF="#NormNodeHandle">NormNodeHandle</A> nodeHandle,
|
||||||
<BR> NormNackingMode
|
<BR> <A HREF="#NormNackingMode">NormNackingMode</A>
|
||||||
nackingMode);</FONT></FONT></P>
|
nackingMode);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||||
|
|
@ -2670,7 +2876,7 @@ return values.</P>
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormObjectSetNackingMode(<A HREF="#NormObjectHandle">NormObjectHandle</A> objectHandle,
|
NormObjectSetNackingMode(<A HREF="#NormObjectHandle">NormObjectHandle</A> objectHandle,
|
||||||
<BR> NormNackingMode nackingMode);</FONT></FONT></P>
|
<BR> <A HREF="#NormNackingMode">NormNackingMode</A> nackingMode);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||||
"nacking mode" used for receiving a specific transport
|
"nacking mode" used for receiving a specific transport
|
||||||
|
|
@ -2689,7 +2895,7 @@ return values.</P>
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormSetDefaultRepairBoundary(<A HREF="#NormSessionHandle">NormSessionHandle</A> sessionHandle,
|
NormSetDefaultRepairBoundary(<A HREF="#NormSessionHandle">NormSessionHandle</A> sessionHandle,
|
||||||
<BR> NormRepairBoundary
|
<BR> <A HREF="#NormRepairBoundary">NormRepairBoundary</A>
|
||||||
repairBoundary);</FONT></FONT></P>
|
repairBoundary);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function allows
|
<P CLASS="western" STYLE="font-style: normal">This function allows
|
||||||
|
|
@ -2723,7 +2929,7 @@ return values.</P>
|
||||||
<normApi.h></FONT></FONT></P>
|
<normApi.h></FONT></FONT></P>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||||
NormNodeSetRepairBoundary(<A HREF="#NormNodeHandle">NormNodeHandle</A> nodeHandle,
|
NormNodeSetRepairBoundary(<A HREF="#NormNodeHandle">NormNodeHandle</A> nodeHandle,
|
||||||
<BR> NormRepairBoundary
|
<BR> <A HREF="#NormRepairBoundary">NormRepairBoundary</A>
|
||||||
repairBoundary);</FONT></FONT></P>
|
repairBoundary);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function allows
|
<P CLASS="western" STYLE="font-style: normal">This function allows
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
19
README.md
19
README.md
|
|
@ -63,7 +63,7 @@ The following items can be build from this source code release:
|
||||||
be provided as additional documentation in the future)
|
be provided as additional documentation in the future)
|
||||||
|
|
||||||
|
|
||||||
2) norm (or norm.exe (WIN32) - command-line "demo" application
|
3) norm (or norm.exe (WIN32) - command-line "demo" application
|
||||||
built from "common/normApp.cpp"
|
built from "common/normApp.cpp"
|
||||||
|
|
||||||
(The included "Norm User's Guide" provides a rough overview
|
(The included "Norm User's Guide" provides a rough overview
|
||||||
|
|
@ -71,7 +71,7 @@ The following items can be build from this source code release:
|
||||||
updating to be accurate and complete. This demo application
|
updating to be accurate and complete. This demo application
|
||||||
is useful for file transfers (and streaming on Unix))
|
is useful for file transfers (and streaming on Unix))
|
||||||
|
|
||||||
3) normTest (or normTest.exe (WIN32)) - very simple test application
|
4) normTest (or normTest.exe (WIN32)) - very simple test application
|
||||||
|
|
||||||
(The "normTest" application (see "common/normTest.cpp") is really
|
(The "normTest" application (see "common/normTest.cpp") is really
|
||||||
just a simple playground for preliminary testing of the NORM
|
just a simple playground for preliminary testing of the NORM
|
||||||
|
|
@ -80,6 +80,19 @@ The following items can be build from this source code release:
|
||||||
(and better-documented) examples of NORM API usage will be
|
(and better-documented) examples of NORM API usage will be
|
||||||
provided in the future.
|
provided in the future.
|
||||||
|
|
||||||
|
5) There is also an "examples" directory in the source code tree
|
||||||
|
that contains some simplified examples of NORM API usage. The
|
||||||
|
example set will be expanded as time progresses.
|
||||||
|
|
||||||
|
NRL also has started some apps built around NORM including:
|
||||||
|
|
||||||
|
A) A reliable multicast "chat" application (users can share files
|
||||||
|
and images, too) with a GUI. Like IRC with no server needed.
|
||||||
|
|
||||||
|
B) An application for reliably "tunneling" real-time UDP packet
|
||||||
|
streams (like RTP video or audio) using NORM's streaming
|
||||||
|
capability.
|
||||||
|
|
||||||
|
|
||||||
OTHER FILES:
|
OTHER FILES:
|
||||||
============
|
============
|
||||||
|
|
@ -92,6 +105,8 @@ NormDeveloperGuide.html - HTML version of NORM Developer's Guide
|
||||||
(nice for browsing)
|
(nice for browsing)
|
||||||
|
|
||||||
NormUserGuide.pdf - Guide to "norm" demo app usage
|
NormUserGuide.pdf - Guide to "norm" demo app usage
|
||||||
|
(this document needs corrections and
|
||||||
|
is currently incomplete)
|
||||||
|
|
||||||
VERSION.TXT - NORM version history notes
|
VERSION.TXT - NORM version history notes
|
||||||
|
|
||||||
|
|
|
||||||
50
VERSION.TXT
50
VERSION.TXT
|
|
@ -1,5 +1,51 @@
|
||||||
NORM Version History
|
NORM Version History
|
||||||
|
|
||||||
|
Version 1.3b5
|
||||||
|
=============
|
||||||
|
- Changed ProtoSocket::GetInterfaceAddress() and related methods on Win32
|
||||||
|
to use different system APIs depending on Windows version.
|
||||||
|
- Fixed some details related to compilation with g++ 4.x.
|
||||||
|
- Various issues fixed thanks to input from Timothy Chaplin.
|
||||||
|
- Fixed some issues where attempt to resync rx stream after long
|
||||||
|
outages (at high data rates) called assertion failures
|
||||||
|
(Thanks to Charlie Davis for finding this one)
|
||||||
|
- Fixed problem where, on Win32, the sender GRTT estimate was not
|
||||||
|
being updated (in the downward direction) properly.
|
||||||
|
- Changes to Protolib & Norm to support build of shared libraries
|
||||||
|
(Thanks to Dave Talmage & Timothy Mann)
|
||||||
|
- Added "NormSetRxPortReuse()" API and code support to allow
|
||||||
|
(with care) multiple NORM instances on the same host.
|
||||||
|
- Fixes to NORM congestion control including:
|
||||||
|
1) measurement of "recv_rate" at low transmission rates
|
||||||
|
fixed (made sure measurement was over sufficient
|
||||||
|
interval at low rates including cc startup)
|
||||||
|
2) Re-instated code to reduce rate when feedback stopped
|
||||||
|
being received.
|
||||||
|
3) Changed to time-based aging of feedback to "deactivate"
|
||||||
|
stale congestion control feedback representative state
|
||||||
|
kept by sender.
|
||||||
|
4) Fixed mis-set of PLR flag as CLR flag and fixed bug
|
||||||
|
in updating CC node list upon CC feedback reception.
|
||||||
|
(Thanks to Praveen Gopala for prompting all of this)
|
||||||
|
- Fixes for Win32 large file support "in normFile.cpp"
|
||||||
|
(Thanks to Titze Stefan for this fix).
|
||||||
|
- Added "NormSetGrttMax()", "NormSetGrttProbingMode()",
|
||||||
|
and "NormSetGrttProbingInterval()" APIs to control
|
||||||
|
NORM GRTT measurement/estimation process.
|
||||||
|
(Thanks to Dave Lucas for prompting me here)
|
||||||
|
- Changed posting of NORM_TX_QUEUE_VACANCY for streams such
|
||||||
|
that new postings of this event are made, _only_ after a
|
||||||
|
successful call to NormStreamWrite() ... This results in
|
||||||
|
reduced posting of unnecessary vacancy events, but now the
|
||||||
|
onus is on the app to pay attention to this event, since
|
||||||
|
another of it's type won't be posted until the app calls
|
||||||
|
NormStreamWrite() with non-zero content length.
|
||||||
|
(Thanks to Charlie Davis for bringing this to my attention)
|
||||||
|
- Made sure messages from self are ignored unless loopback
|
||||||
|
is explicitly enabled (see NormSetLoopback()) even for
|
||||||
|
operating systems whose ProtoSocket::SetLoopback() doesn't
|
||||||
|
work properly.
|
||||||
|
|
||||||
Version 1.3b4
|
Version 1.3b4
|
||||||
=============
|
=============
|
||||||
- Added NormSetTxCacheBounds(), see NormDevGuide for details
|
- Added NormSetTxCacheBounds(), see NormDevGuide for details
|
||||||
|
|
@ -118,3 +164,7 @@ Version 1.1b3
|
||||||
- Started keeping version history. This release includes
|
- Started keeping version history. This release includes
|
||||||
some bug fixes, smoother congestion control operation, etc
|
some bug fixes, smoother congestion control operation, etc
|
||||||
over some of the earlier releases.
|
over some of the earlier releases.
|
||||||
|
|
||||||
|
Please address bug reports, suggestions etc to the email list:
|
||||||
|
|
||||||
|
mailto:norm-dev@pf.itd.nrl.navy.mil
|
||||||
|
|
|
||||||
|
|
@ -460,8 +460,8 @@ bool NormInstance::GetNextEvent(NormEvent* theEvent)
|
||||||
((NormObject*)n->event.object)->SetNotifyOnUpdate(true);
|
((NormObject*)n->event.object)->SetNotifyOnUpdate(true);
|
||||||
break;
|
break;
|
||||||
case NORM_TX_QUEUE_VACANCY:
|
case NORM_TX_QUEUE_VACANCY:
|
||||||
if (NULL != n->event.object)
|
//if (NULL != n->event.object)
|
||||||
static_cast<NormStreamObject*>((NormObject*)n->event.object)->ResetPostedTxQueueVacancy();
|
// static_cast<NormStreamObject*>((NormObject*)n->event.object)->ResetPostedTxQueueVacancy();
|
||||||
// (TBD) support session-level queue vacancy notify
|
// (TBD) support session-level queue vacancy notify
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -764,6 +764,21 @@ void NormSetTxPort(NormSessionHandle sessionHandle,
|
||||||
}
|
}
|
||||||
} // end NormSetTxPort()
|
} // end NormSetTxPort()
|
||||||
|
|
||||||
|
void NormSetRxPortReuse(NormSessionHandle sessionHandle,
|
||||||
|
bool state)
|
||||||
|
{
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (NULL != instance)
|
||||||
|
{
|
||||||
|
if (instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
if (session) session->SetRxPortReuse(state);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end NormSetTxPort()
|
||||||
|
|
||||||
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
|
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
|
||||||
const char* interfaceName)
|
const char* interfaceName)
|
||||||
{
|
{
|
||||||
|
|
@ -971,6 +986,46 @@ void NormSetGrttEstimate(NormSessionHandle sessionHandle,
|
||||||
}
|
}
|
||||||
} // end NormSetGrttEstimate()
|
} // end NormSetGrttEstimate()
|
||||||
|
|
||||||
|
void NormSetGrttMax(NormSessionHandle sessionHandle,
|
||||||
|
double grttMax)
|
||||||
|
{
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
if (session) session->SetGrttMax(grttMax);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
} // end NormSetGrttMax()
|
||||||
|
|
||||||
|
void NormSetGrttProbingMode(NormSessionHandle sessionHandle,
|
||||||
|
NormProbingMode probingMode)
|
||||||
|
{
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
if (session)
|
||||||
|
session->SetGrttProbingMode((NormSession::ProbingMode)probingMode);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
} // end NormSetGrttProbingMode()
|
||||||
|
|
||||||
|
void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
||||||
|
double intervalMin,
|
||||||
|
double intervalMax)
|
||||||
|
{
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
|
if (session) session->SetGrttProbingInterval(intervalMin, intervalMax);
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
} // end NormSetGrttProbingInterval()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||||
NormNodeId nodeId)
|
NormNodeId nodeId)
|
||||||
{
|
{
|
||||||
|
|
@ -1021,8 +1076,8 @@ NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||||
NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
|
NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
|
||||||
const char* dataPtr,
|
const char* dataPtr,
|
||||||
unsigned long dataLen,
|
unsigned long dataLen,
|
||||||
const char* infoPtr = NULL,
|
const char* infoPtr,
|
||||||
unsigned int infoLen = 0)
|
unsigned int infoLen)
|
||||||
{
|
{
|
||||||
NormObjectHandle objectHandle = NORM_OBJECT_INVALID;
|
NormObjectHandle objectHandle = NORM_OBJECT_INVALID;
|
||||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||||
|
|
@ -1460,7 +1515,7 @@ bool NormFileGetName(NormObjectHandle fileHandle,
|
||||||
static_cast<NormFileObject*>((NormObject*)fileHandle);
|
static_cast<NormFileObject*>((NormObject*)fileHandle);
|
||||||
bufferLen = (bufferLen < PATH_MAX) ? bufferLen : PATH_MAX;
|
bufferLen = (bufferLen < PATH_MAX) ? bufferLen : PATH_MAX;
|
||||||
strncpy(nameBuffer, file->GetPath(), bufferLen);
|
strncpy(nameBuffer, file->GetPath(), bufferLen);
|
||||||
nameBuffer[bufferLen=1] = '\0';
|
nameBuffer[bufferLen] = '\0';
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,7 @@
|
||||||
// C++ code continues to evolve. But, until this notice
|
// C++ code continues to evolve. But, until this notice
|
||||||
// is removed, the API shouldn't be considered final.
|
// is removed, the API shouldn't be considered final.
|
||||||
|
|
||||||
|
// NORM API control
|
||||||
/** NORM API Data Types and Constants
|
|
||||||
* These are data types and constants defined
|
|
||||||
* for the NORM API
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef const void* NormInstanceHandle;
|
typedef const void* NormInstanceHandle;
|
||||||
extern const NormInstanceHandle NORM_INSTANCE_INVALID;
|
extern const NormInstanceHandle NORM_INSTANCE_INVALID;
|
||||||
|
|
||||||
|
|
@ -71,6 +66,13 @@ enum NormNackingMode
|
||||||
NORM_NACK_NORMAL
|
NORM_NACK_NORMAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum NormProbingMode
|
||||||
|
{
|
||||||
|
NORM_PROBE_NONE,
|
||||||
|
NORM_PROBE_PASSIVE,
|
||||||
|
NORM_PROBE_ACTIVE
|
||||||
|
};
|
||||||
|
|
||||||
enum NormRepairBoundary
|
enum NormRepairBoundary
|
||||||
{
|
{
|
||||||
NORM_BOUNDARY_BLOCK,
|
NORM_BOUNDARY_BLOCK,
|
||||||
|
|
@ -154,6 +156,9 @@ NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle);
|
||||||
void NormSetTxPort(NormSessionHandle sessionHandle,
|
void NormSetTxPort(NormSessionHandle sessionHandle,
|
||||||
unsigned short txPortNumber);
|
unsigned short txPortNumber);
|
||||||
|
|
||||||
|
void NormSetRxPortReuse(NormSessionHandle sessionHandle,
|
||||||
|
bool state);
|
||||||
|
|
||||||
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
|
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
|
||||||
const char* interfaceName);
|
const char* interfaceName);
|
||||||
|
|
||||||
|
|
@ -206,6 +211,16 @@ void NormSetAutoParity(NormSessionHandle sessionHandle,
|
||||||
void NormSetGrttEstimate(NormSessionHandle sessionHandle,
|
void NormSetGrttEstimate(NormSessionHandle sessionHandle,
|
||||||
double grttEstimate);
|
double grttEstimate);
|
||||||
|
|
||||||
|
void NormSetGrttMax(NormSessionHandle sessionHandle,
|
||||||
|
double grttMax);
|
||||||
|
|
||||||
|
void NormSetGrttProbingMode(NormSessionHandle sessionHandle,
|
||||||
|
NormProbingMode probingMode);
|
||||||
|
|
||||||
|
void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
||||||
|
double intervalMin,
|
||||||
|
double intervalMax);
|
||||||
|
|
||||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||||
NormNodeId nodeId);
|
NormNodeId nodeId);
|
||||||
|
|
||||||
|
|
@ -217,10 +232,11 @@ NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||||
const char* infoPtr = (const char*)0,
|
const char* infoPtr = (const char*)0,
|
||||||
unsigned int infoLen = 0);
|
unsigned int infoLen = 0);
|
||||||
|
|
||||||
bool NormDataEnqueue(const char* dataPtr,
|
NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle,
|
||||||
unsigned long dataLen,
|
const char* dataPtr,
|
||||||
const char* infoPtr = (const char*)0,
|
unsigned long dataLen,
|
||||||
unsigned int infoLen = 0);
|
const char* infoPtr = (const char*)0,
|
||||||
|
unsigned int infoLen = 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -243,16 +259,15 @@ void NormStreamSetAutoFlush(NormObjectHandle streamHandle,
|
||||||
void NormStreamSetPushEnable(NormObjectHandle streamHandle,
|
void NormStreamSetPushEnable(NormObjectHandle streamHandle,
|
||||||
bool pushEnable);
|
bool pushEnable);
|
||||||
|
|
||||||
|
|
||||||
bool NormStreamHasVacancy(NormObjectHandle streamHandle);
|
bool NormStreamHasVacancy(NormObjectHandle streamHandle);
|
||||||
|
|
||||||
|
NormSize NormGetObjectSize(NormObjectHandle objectHandle);
|
||||||
|
|
||||||
void NormStreamMarkEom(NormObjectHandle streamHandle);
|
void NormStreamMarkEom(NormObjectHandle streamHandle);
|
||||||
|
|
||||||
bool NormSetWatermark(NormSessionHandle sessionHandle,
|
bool NormSetWatermark(NormSessionHandle sessionHandle,
|
||||||
NormObjectHandle objectHandle);
|
NormObjectHandle objectHandle);
|
||||||
|
|
||||||
/** NORM Receiver Functions */
|
|
||||||
|
|
||||||
bool NormStartReceiver(NormSessionHandle sessionHandle,
|
bool NormStartReceiver(NormSessionHandle sessionHandle,
|
||||||
unsigned long bufferSpace);
|
unsigned long bufferSpace);
|
||||||
|
|
||||||
|
|
@ -329,6 +344,7 @@ char* NormDataDetachData(NormObjectHandle objectHandle);
|
||||||
|
|
||||||
NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle);
|
NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle);
|
||||||
|
|
||||||
|
char* NormGetData(NormObjectHandle dataHandle);
|
||||||
|
|
||||||
/** NORM Node Functions */
|
/** NORM Node Functions */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1624,7 +1624,7 @@ void NormApp::OnShutdown()
|
||||||
} // end NormApp::OnShutdown()
|
} // end NormApp::OnShutdown()
|
||||||
|
|
||||||
// Out application instance
|
// Out application instance
|
||||||
PROTO_INSTANTIATE_APP(NormApp);
|
PROTO_INSTANTIATE_APP(NormApp)
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
void NormApp::SignalHandler(int sigNum)
|
void NormApp::SignalHandler(int sigNum)
|
||||||
|
|
|
||||||
|
|
@ -397,8 +397,8 @@ NormFile::Offset NormFile::GetSize() const
|
||||||
return ((Offset)fileSize);
|
return ((Offset)fileSize);
|
||||||
#else
|
#else
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
struct _stat info;
|
struct __stat64 info; // instead of "struct _stat"
|
||||||
int result = _fstat(fd, &info);
|
int result = _fstat64(fd, &info); // instead of "_fstat()"
|
||||||
#else
|
#else
|
||||||
struct stat info;
|
struct stat info;
|
||||||
int result = fstat(fd, &info);
|
int result = fstat(fd, &info);
|
||||||
|
|
@ -811,8 +811,8 @@ NormFile::Offset NormFile::GetSize(const char* path)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
struct _stat info;
|
struct __stat64 info; // instead of "struct _stat"
|
||||||
int result = _stat(path, &info);
|
int result = _stat64(path, &info); // instead of "_stat()"
|
||||||
#else
|
#else
|
||||||
struct stat info;
|
struct stat info;
|
||||||
int result = stat(path, &info);
|
int result = stat(path, &info);
|
||||||
|
|
@ -863,8 +863,8 @@ time_t NormFile::GetUpdateTime(const char* path)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
struct _stat info;
|
struct __stat64 info; // instead of "struct _stat"
|
||||||
int result = _stat(path, &info);
|
int result = _stat64(path, &info); // instead of "_stat()"
|
||||||
#else
|
#else
|
||||||
struct stat info;
|
struct stat info;
|
||||||
int result = stat(path, &info);
|
int result = stat(path, &info);
|
||||||
|
|
@ -877,9 +877,9 @@ time_t NormFile::GetUpdateTime(const char* path)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// Hack because Win2K and Win98 seem to work differently
|
// Hack because Win2K and Win98 seem to work differently
|
||||||
time_t updateTime = MAX(info.st_ctime, info.st_atime);
|
__time64_t updateTime = MAX(info.st_ctime, info.st_atime);
|
||||||
updateTime = MAX(updateTime, info.st_mtime);
|
updateTime = MAX(updateTime, info.st_mtime);
|
||||||
return updateTime;
|
return ((time_t)updateTime);
|
||||||
#else
|
#else
|
||||||
return info.st_ctime;
|
return info.st_ctime;
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,7 @@ class NormHeaderExtension
|
||||||
};
|
};
|
||||||
|
|
||||||
NormHeaderExtension();
|
NormHeaderExtension();
|
||||||
|
virtual ~NormHeaderExtension() {}
|
||||||
virtual void Init(UINT32* theBuffer)
|
virtual void Init(UINT32* theBuffer)
|
||||||
{
|
{
|
||||||
buffer = theBuffer;
|
buffer = theBuffer;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include "normSession.h"
|
#include "normSession.h"
|
||||||
|
|
||||||
NormNode::NormNode(class NormSession& theSession, NormNodeId nodeId)
|
NormNode::NormNode(class NormSession& theSession, NormNodeId nodeId)
|
||||||
: session(theSession), id(nodeId), reference_count(0),
|
: session(theSession), id(nodeId), reference_count(1),
|
||||||
parent(NULL), right(NULL), left(NULL)
|
parent(NULL), right(NULL), left(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
if (obj && (NormObject::STREAM == obj->GetType()))
|
if (obj && (NormObject::STREAM == obj->GetType()))
|
||||||
{
|
{
|
||||||
NormBlockId blockId = squelch.GetFecBlockId();
|
NormBlockId blockId = squelch.GetFecBlockId();
|
||||||
static_cast<NormStreamObject*>(obj)->Prune(blockId);
|
static_cast<NormStreamObject*>(obj)->Prune(blockId, true);
|
||||||
}
|
}
|
||||||
// 3) (TBD) Go ahead and discard any invalidated objects
|
// 3) (TBD) Go ahead and discard any invalidated objects
|
||||||
// (although they will eventually get discarded anyway)
|
// (although they will eventually get discarded anyway)
|
||||||
|
|
@ -614,7 +614,7 @@ void NormServerNode::HandleRepairContent(const UINT32* buffer, UINT16 bufferLen)
|
||||||
NormRepairRequest req;
|
NormRepairRequest req;
|
||||||
UINT16 requestLength = 0;
|
UINT16 requestLength = 0;
|
||||||
bool freshObject = true;
|
bool freshObject = true;
|
||||||
NormObjectId prevObjectId;
|
NormObjectId prevObjectId(0);
|
||||||
NormObject* object = NULL;
|
NormObject* object = NULL;
|
||||||
bool freshBlock = true;
|
bool freshBlock = true;
|
||||||
NormBlockId prevBlockId = 0;
|
NormBlockId prevBlockId = 0;
|
||||||
|
|
@ -1005,10 +1005,9 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj)
|
if (NULL != obj)
|
||||||
{
|
{
|
||||||
rx_table.Insert(obj);
|
rx_table.Insert(obj);
|
||||||
obj->Retain();
|
|
||||||
NormFtiExtension fti;
|
NormFtiExtension fti;
|
||||||
while (msg.GetNextExtension(fti))
|
while (msg.GetNextExtension(fti))
|
||||||
{
|
{
|
||||||
|
|
@ -1458,7 +1457,7 @@ bool NormServerNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
|
||||||
if (is_clr)
|
if (is_clr)
|
||||||
ext.SetCCFlag(NormCC::CLR);
|
ext.SetCCFlag(NormCC::CLR);
|
||||||
else if (is_plr)
|
else if (is_plr)
|
||||||
ext.SetCCFlag(NormCC::CLR);
|
ext.SetCCFlag(NormCC::PLR);
|
||||||
if (rtt_confirmed)
|
if (rtt_confirmed)
|
||||||
ext.SetCCFlag(NormCC::RTT);
|
ext.SetCCFlag(NormCC::RTT);
|
||||||
ext.SetCCRtt(rtt_quantized);
|
ext.SetCCRtt(rtt_quantized);
|
||||||
|
|
@ -1675,22 +1674,58 @@ void NormServerNode::UpdateRecvRate(const struct timeval& currentTime, unsigned
|
||||||
{
|
{
|
||||||
if (prev_update_time.tv_sec || prev_update_time.tv_usec)
|
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);
|
double interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
|
||||||
if (currentTime.tv_usec > 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);
|
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
|
||||||
else
|
else
|
||||||
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
|
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
|
||||||
double rttEstimate = rtt_confirmed ? rtt_estimate : grtt_estimate;
|
double measurementInterval = rtt_confirmed ? rtt_estimate : grtt_estimate;
|
||||||
|
// Here, we put a 0.100 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 (interval > 0.0)
|
||||||
|
{
|
||||||
|
double currentRecvRate = ((double)(recv_accumulator)) / interval;
|
||||||
|
if (currentRecvRate < recv_rate)
|
||||||
|
{
|
||||||
|
// Make sure we've allowed sufficient time for a measurement
|
||||||
|
double minInterval = 4.0 * ((double)nominal_packet_size) / recv_rate;
|
||||||
|
if (measurementInterval < minInterval)
|
||||||
|
measurementInterval = minInterval;
|
||||||
|
}
|
||||||
|
if (interval >= measurementInterval)
|
||||||
|
{
|
||||||
|
recv_rate = currentRecvRate; //((double)(recv_accumulator)) / interval;
|
||||||
|
prev_update_time = currentTime;
|
||||||
|
recv_accumulator = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
// We put a 0.100 sec lower bound on our rttEstimate for the recv_rate measurement
|
// 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
|
// 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;
|
rttEstimate = rttEstimate < 0.1 ? 0.1 : rttEstimate;
|
||||||
recv_accumulator += msgSize;
|
|
||||||
|
// 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)
|
if (interval >= rttEstimate)
|
||||||
{
|
{
|
||||||
recv_rate = ((double)(recv_accumulator)) / interval;
|
recv_rate = ((double)(recv_accumulator)) / interval;
|
||||||
prev_update_time = currentTime;
|
prev_update_time = currentTime;
|
||||||
recv_accumulator = 0;
|
recv_accumulator = 0;
|
||||||
}
|
}*/
|
||||||
|
//TRACE("updated recv rate to %lf (accum:%lu) (cc_rate:%lf)\n", recv_rate,
|
||||||
|
// recv_accumulator, cc_rate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1956,6 +1991,7 @@ NormNode *NormNodeTree::FindNodeById(NormNodeId nodeId) const
|
||||||
void NormNodeTree::AttachNode(NormNode *node)
|
void NormNodeTree::AttachNode(NormNode *node)
|
||||||
{
|
{
|
||||||
ASSERT(node);
|
ASSERT(node);
|
||||||
|
node->Retain();
|
||||||
node->left = NULL;
|
node->left = NULL;
|
||||||
node->right = NULL;
|
node->right = NULL;
|
||||||
NormNode *x = root;
|
NormNode *x = root;
|
||||||
|
|
@ -1995,6 +2031,7 @@ void NormNodeTree::AttachNode(NormNode *node)
|
||||||
void NormNodeTree::DetachNode(NormNode* node)
|
void NormNodeTree::DetachNode(NormNode* node)
|
||||||
{
|
{
|
||||||
ASSERT(node);
|
ASSERT(node);
|
||||||
|
node->Release();
|
||||||
NormNode* x;
|
NormNode* x;
|
||||||
NormNode* y;
|
NormNode* y;
|
||||||
if (!node->left || !node->right)
|
if (!node->left || !node->right)
|
||||||
|
|
@ -2056,7 +2093,7 @@ void NormNodeTree::Destroy()
|
||||||
while ((n = root))
|
while ((n = root))
|
||||||
{
|
{
|
||||||
DetachNode(n);
|
DetachNode(n);
|
||||||
delete n;
|
n->Release();
|
||||||
}
|
}
|
||||||
} // end NormNodeTree::Destroy()
|
} // end NormNodeTree::Destroy()
|
||||||
|
|
||||||
|
|
@ -2141,6 +2178,7 @@ NormNode* NormNodeList::FindNodeById(NormNodeId nodeId) const
|
||||||
void NormNodeList::Append(NormNode *theNode)
|
void NormNodeList::Append(NormNode *theNode)
|
||||||
{
|
{
|
||||||
ASSERT(theNode);
|
ASSERT(theNode);
|
||||||
|
theNode->Retain();
|
||||||
theNode->left = tail;
|
theNode->left = tail;
|
||||||
if (tail)
|
if (tail)
|
||||||
tail->right = theNode;
|
tail->right = theNode;
|
||||||
|
|
@ -2154,6 +2192,7 @@ void NormNodeList::Append(NormNode *theNode)
|
||||||
void NormNodeList::Remove(NormNode *theNode)
|
void NormNodeList::Remove(NormNode *theNode)
|
||||||
{
|
{
|
||||||
ASSERT(theNode);
|
ASSERT(theNode);
|
||||||
|
theNode->Release();
|
||||||
if (theNode->right)
|
if (theNode->right)
|
||||||
theNode->right->left = theNode->left;
|
theNode->right->left = theNode->left;
|
||||||
else
|
else
|
||||||
|
|
@ -2171,7 +2210,7 @@ void NormNodeList::Destroy()
|
||||||
while ((n = head))
|
while ((n = head))
|
||||||
{
|
{
|
||||||
Remove(n);
|
Remove(n);
|
||||||
delete n;
|
n->Release();
|
||||||
}
|
}
|
||||||
} // end NormNodeList::Destroy()
|
} // end NormNodeList::Destroy()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,10 @@ class NormCCNode : public NormNode
|
||||||
NormCCNode(class NormSession& theSession, NormNodeId nodeId);
|
NormCCNode(class NormSession& theSession, NormNodeId nodeId);
|
||||||
~NormCCNode();
|
~NormCCNode();
|
||||||
|
|
||||||
|
enum {ACTIVE_MAX = 7};
|
||||||
|
|
||||||
bool IsClr() const {return is_clr;}
|
bool IsClr() const {return is_clr;}
|
||||||
|
bool IsPlr() const {return is_plr;}
|
||||||
bool IsActive() const {return is_active;}
|
bool IsActive() const {return is_active;}
|
||||||
bool HasRtt() const {return rtt_confirmed;}
|
bool HasRtt() const {return rtt_confirmed;}
|
||||||
|
|
||||||
|
|
@ -179,9 +182,13 @@ class NormCCNode : public NormNode
|
||||||
double GetLoss() const {return loss;}
|
double GetLoss() const {return loss;}
|
||||||
double GetRate() const {return rate;}
|
double GetRate() const {return rate;}
|
||||||
UINT16 GetCCSequence() const {return cc_sequence;}
|
UINT16 GetCCSequence() const {return cc_sequence;}
|
||||||
|
const struct timeval& GetFeedbackTime()
|
||||||
|
{return feedback_time;}
|
||||||
|
void SetFeedbackTime(struct timeval& theTime)
|
||||||
|
{feedback_time = theTime;}
|
||||||
void SetActive(bool state) {is_active = state;}
|
void SetActive(bool state) {is_active = state;}
|
||||||
void SetClrStatus(bool state) {is_clr = state;}
|
void SetClrStatus(bool state) {is_clr = state;}
|
||||||
|
void SetPlrStatus(bool state) {is_plr = state;}
|
||||||
void SetRttStatus(bool state) {rtt_confirmed = state;}
|
void SetRttStatus(bool state) {rtt_confirmed = state;}
|
||||||
void SetRtt(double value) {rtt = value;}
|
void SetRtt(double value) {rtt = value;}
|
||||||
double UpdateRtt(double value)
|
double UpdateRtt(double value)
|
||||||
|
|
@ -194,14 +201,15 @@ class NormCCNode : public NormNode
|
||||||
void SetCCSequence(UINT16 value) {cc_sequence = value;}
|
void SetCCSequence(UINT16 value) {cc_sequence = value;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_clr; // true if worst path representative
|
bool is_clr; // true if worst path representative
|
||||||
bool is_plr; // true if worst path candidate
|
bool is_plr; // true if worst path candidate
|
||||||
bool is_active;
|
bool rtt_confirmed;
|
||||||
bool rtt_confirmed;
|
bool is_active;
|
||||||
double rtt; // in seconds
|
struct timeval feedback_time; // time of last received feedback
|
||||||
double loss; // loss fraction
|
double rtt; // in seconds
|
||||||
double rate; // in bytes per second
|
double loss; // loss fraction
|
||||||
UINT16 cc_sequence;
|
double rate; // in bytes per second
|
||||||
|
UINT16 cc_sequence;
|
||||||
}; // end class NormCCNode
|
}; // end class NormCCNode
|
||||||
|
|
||||||
class NormServerNode : public NormNode
|
class NormServerNode : public NormNode
|
||||||
|
|
@ -496,7 +504,7 @@ class NormNodeList
|
||||||
{
|
{
|
||||||
ASSERT(theNode);
|
ASSERT(theNode);
|
||||||
Remove(theNode);
|
Remove(theNode);
|
||||||
delete theNode;
|
theNode->Release();
|
||||||
}
|
}
|
||||||
void Destroy(); // delete all nodes in list
|
void Destroy(); // delete all nodes in list
|
||||||
const NormNode* Head() {return head;}
|
const NormNode* Head() {return head;}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ NormObject::NormObject(NormObject::Type theType,
|
||||||
class NormSession& theSession,
|
class NormSession& theSession,
|
||||||
class NormServerNode* theServer,
|
class NormServerNode* theServer,
|
||||||
const NormObjectId& transportId)
|
const NormObjectId& transportId)
|
||||||
: type(theType), session(theSession), server(theServer), reference_count(0),
|
: type(theType), session(theSession), server(theServer), reference_count(1),
|
||||||
transport_id(transportId), segment_size(0), pending_info(false), repair_info(false),
|
transport_id(transportId), segment_size(0), pending_info(false), repair_info(false),
|
||||||
current_block_id(0), next_segment_id(0),
|
current_block_id(0), next_segment_id(0),
|
||||||
max_pending_block(0), max_pending_segment(0),
|
max_pending_block(0), max_pending_segment(0),
|
||||||
|
|
@ -132,8 +132,6 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pending_mask.Clear();
|
|
||||||
pending_mask.SetBits(0, numBlocks.LSB());
|
|
||||||
|
|
||||||
// Init repair_mask
|
// Init repair_mask
|
||||||
if (!repair_mask.Init(numBlocks.LSB(), 0xffffffff))
|
if (!repair_mask.Init(numBlocks.LSB(), 0xffffffff))
|
||||||
|
|
@ -151,10 +149,13 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
small_block_count = large_block_count = numBlocks.LSB();
|
small_block_count = large_block_count = numBlocks.LSB();
|
||||||
final_segment_size = segmentSize;
|
final_segment_size = segmentSize;
|
||||||
NormStreamObject* stream = static_cast<NormStreamObject*>(this);
|
NormStreamObject* stream = static_cast<NormStreamObject*>(this);
|
||||||
stream->StreamResync(numBlocks.LSB());
|
stream->StreamResync(NormBlockId(0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Set everything pending
|
||||||
|
pending_mask.Clear();
|
||||||
|
pending_mask.SetBits(0, numBlocks.LSB());
|
||||||
// Compute FEC block structure per NORM Protocol Spec Section 5.1.1
|
// Compute FEC block structure per NORM Protocol Spec Section 5.1.1
|
||||||
// (Note NormObjectSize divide operator always rounds _up_)
|
// (Note NormObjectSize divide operator always rounds _up_)
|
||||||
NormObjectSize largeBlockSize = numSegments / numBlocks;
|
NormObjectSize largeBlockSize = numSegments / numBlocks;
|
||||||
|
|
@ -1136,7 +1137,8 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream->StreamResync(blockId);// - NormBlockId(pending_mask.Size()));
|
stream->StreamResync(blockId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1268,25 +1270,18 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
}
|
}
|
||||||
else if (!block->GetSegment(nextSegment))
|
else if (!block->GetSegment(nextSegment))
|
||||||
{
|
{
|
||||||
// "tempRetrieval" is set to "true" if the retrieved segment
|
if (!(segment = RetrieveSegment(blockId, nextSegment)))
|
||||||
// comes from the "server" temp retrieval pool
|
|
||||||
bool tempRetrieval = false;
|
|
||||||
if (!(segment = RetrieveSegment(blockId, nextSegment, tempRetrieval)))
|
|
||||||
{
|
{
|
||||||
ASSERT(IsStream());
|
ASSERT(IsStream());
|
||||||
block->SetPending(nextSegment);
|
block->SetPending(nextSegment);
|
||||||
block->IncrementErasureCount();
|
block->IncrementErasureCount();
|
||||||
// Clear any erasure/retrieval segments
|
// Clear block of any retrieval (temp) segments
|
||||||
UINT16 i;
|
for (UINT16 i = 0; i < retrievalCount; i++)
|
||||||
for (i = 0; i < erasureCount; i++)
|
|
||||||
block->DetachSegment(server->GetErasureLoc(i));
|
|
||||||
for (i = 0; i < retrievalCount; i++)
|
|
||||||
block->DetachSegment(server->GetRetrievalLoc(i));
|
block->DetachSegment(server->GetRetrievalLoc(i));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tempRetrieval)
|
server->SetRetrievalLoc(retrievalCount++, nextSegment);
|
||||||
server->SetRetrievalLoc(retrievalCount++, nextSegment);
|
block->SetSegment(nextSegment, segment);
|
||||||
block->SetSegment(nextSegment, segment);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nextErasure = numData;
|
nextErasure = numData;
|
||||||
|
|
@ -1309,8 +1304,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
objectUpdated = true;
|
objectUpdated = true;
|
||||||
// For statistics only (TBD) #ifdef NORM_DEBUG
|
// For statistics only (TBD) #ifdef NORM_DEBUG
|
||||||
server->IncrementRecvGoodput(segmentLength);
|
server->IncrementRecvGoodput(segmentLength);
|
||||||
}
|
}
|
||||||
block->DetachSegment(sid);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1318,13 +1312,13 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clear any temporarily retrieved (non-cached) segments for the block
|
// Clear any temporarily retrieved segments for the block
|
||||||
for (UINT16 i = 0; i < retrievalCount; i++)
|
for (UINT16 i = 0; i < retrievalCount; i++)
|
||||||
block->DetachSegment(server->GetRetrievalLoc(i));
|
block->DetachSegment(server->GetRetrievalLoc(i));
|
||||||
// OK, we're done with this block
|
// OK, we're done with this block
|
||||||
pending_mask.Unset(blockId);
|
pending_mask.Unset(blockId);
|
||||||
block_buffer.Remove(block);
|
block_buffer.Remove(block);
|
||||||
server->PutFreeBlock(block);
|
server->PutFreeBlock(block);
|
||||||
}
|
}
|
||||||
// Notify application of new data available
|
// Notify application of new data available
|
||||||
// (TBD) this could be improved for stream objects
|
// (TBD) this could be improved for stream objects
|
||||||
|
|
@ -1958,8 +1952,7 @@ UINT16 NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
} // end NormFileObject::ReadSegment()
|
} // end NormFileObject::ReadSegment()
|
||||||
|
|
||||||
char* NormFileObject::RetrieveSegment(NormBlockId blockId,
|
char* NormFileObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId)
|
||||||
bool& tempRetrieval)
|
|
||||||
{
|
{
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
|
|
@ -1970,7 +1963,6 @@ char* NormFileObject::RetrieveSegment(NormBlockId blockId,
|
||||||
// zeroize remainder for proper decodes
|
// zeroize remainder for proper decodes
|
||||||
if (len < segment_size)
|
if (len < segment_size)
|
||||||
memset(segment+len, 0, segment_size-len);
|
memset(segment+len, 0, segment_size-len);
|
||||||
tempRetrieval = true;
|
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2057,7 +2049,6 @@ bool NormDataObject::Open(char* dataPtr,
|
||||||
|
|
||||||
bool NormDataObject::Accept(char* dataPtr, UINT32 dataMax, bool dataRelease)
|
bool NormDataObject::Accept(char* dataPtr, UINT32 dataMax, bool dataRelease)
|
||||||
{
|
{
|
||||||
ASSERT(NULL == server);
|
|
||||||
if (Open(dataPtr, dataMax, dataRelease))
|
if (Open(dataPtr, dataMax, dataRelease))
|
||||||
{
|
{
|
||||||
NormObject::Accept();
|
NormObject::Accept();
|
||||||
|
|
@ -2167,8 +2158,7 @@ UINT16 NormDataObject::ReadSegment(NormBlockId blockId,
|
||||||
} // end NormDataObject::ReadSegment()
|
} // end NormDataObject::ReadSegment()
|
||||||
|
|
||||||
char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId)
|
||||||
bool& tempRetrieval)
|
|
||||||
{
|
{
|
||||||
if (NULL == data_ptr)
|
if (NULL == data_ptr)
|
||||||
{
|
{
|
||||||
|
|
@ -2210,7 +2200,6 @@ char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
||||||
char* segment = server->GetRetrievalSegment();
|
char* segment = server->GetRetrievalSegment();
|
||||||
len = ReadSegment(blockId, segmentId, segment);
|
len = ReadSegment(blockId, segmentId, segment);
|
||||||
memset(segment+len, 0, segment_size-len);
|
memset(segment+len, 0, segment_size-len);
|
||||||
tempRetrieval = true;
|
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2221,7 +2210,6 @@ char* NormDataObject::RetrieveSegment(NormBlockId blockId,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tempRetrieval = false;
|
|
||||||
return (data_ptr + segmentOffset.LSB());
|
return (data_ptr + segmentOffset.LSB());
|
||||||
}
|
}
|
||||||
} // end NormDataObject::RetrieveSegment()
|
} // end NormDataObject::RetrieveSegment()
|
||||||
|
|
@ -2442,7 +2430,7 @@ bool NormStreamObject::StreamUpdateStatus(NormBlockId blockId)
|
||||||
{
|
{
|
||||||
pending_mask.SetBits(stream_next_id, blockId - stream_next_id + 1);
|
pending_mask.SetBits(stream_next_id, blockId - stream_next_id + 1);
|
||||||
stream_next_id = blockId + 1;
|
stream_next_id = blockId + 1;
|
||||||
// Handle potential sync block id wrap
|
// Handle potential stream_sync_id wrap
|
||||||
NormBlockId delta = stream_next_id - stream_sync_id;
|
NormBlockId delta = stream_next_id - stream_sync_id;
|
||||||
if (delta > NormBlockId(2*pending_mask.GetSize()))
|
if (delta > NormBlockId(2*pending_mask.GetSize()))
|
||||||
GetFirstPending(stream_sync_id);
|
GetFirstPending(stream_sync_id);
|
||||||
|
|
@ -2468,8 +2456,8 @@ bool NormStreamObject::StreamUpdateStatus(NormBlockId blockId)
|
||||||
{
|
{
|
||||||
pending_mask.SetBits(blockId, pending_mask.GetSize());
|
pending_mask.SetBits(blockId, pending_mask.GetSize());
|
||||||
stream_next_id = blockId + NormBlockId(pending_mask.GetSize());
|
stream_next_id = blockId + NormBlockId(pending_mask.GetSize());
|
||||||
// Handle potential sync block id wrap
|
// Handle potential stream_sync_id wrap
|
||||||
delta = stream_next_id - stream_sync_id;
|
NormBlockId delta = stream_next_id - stream_sync_id;
|
||||||
if (delta > NormBlockId(2*pending_mask.GetSize()))
|
if (delta > NormBlockId(2*pending_mask.GetSize()))
|
||||||
stream_sync_id = blockId;
|
stream_sync_id = blockId;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2481,20 +2469,35 @@ bool NormStreamObject::StreamUpdateStatus(NormBlockId blockId)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// For now, let stream begin anytime
|
// For now, let stream begin anytime
|
||||||
|
// First, clean out block_buffer
|
||||||
|
NormBlock* block;
|
||||||
|
while (NULL != (block = block_buffer.Find(block_buffer.RangeLo())))
|
||||||
|
{
|
||||||
|
block_buffer.Remove(block);
|
||||||
|
server->PutFreeBlock(block);
|
||||||
|
}
|
||||||
pending_mask.Clear();
|
pending_mask.Clear();
|
||||||
pending_mask.SetBits(blockId, pending_mask.GetSize());
|
pending_mask.SetBits(blockId, pending_mask.GetSize());
|
||||||
stream_sync = true;
|
stream_sync = true;
|
||||||
stream_sync_id = blockId;
|
stream_sync_id = blockId;
|
||||||
stream_next_id = blockId + pending_mask.GetSize();
|
stream_next_id = blockId + pending_mask.GetSize();
|
||||||
read_init = true;
|
// Since we're doing a resync including "read_init", dump any buffered data
|
||||||
|
// (TBD) this may not be necessary and is thus currently commented-out code
|
||||||
|
/*read_init = true;
|
||||||
|
NormBlock* block;
|
||||||
|
while (NULL != (block = stream_buffer.Find(stream_buffer.RangeLo())))
|
||||||
|
{
|
||||||
|
stream_buffer.Remove(block);
|
||||||
|
block->EmptyToPool(segment_pool);
|
||||||
|
block_pool.Put(block);
|
||||||
|
}*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} // end NormStreamObject::StreamUpdateStatus()
|
} // end NormStreamObject::StreamUpdateStatus()
|
||||||
|
|
||||||
|
|
||||||
char* NormStreamObject::RetrieveSegment(NormBlockId blockId,
|
char* NormStreamObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId)
|
||||||
bool& tempRetrieval)
|
|
||||||
{
|
{
|
||||||
NormBlock* block = stream_buffer.Find(blockId);
|
NormBlock* block = stream_buffer.Find(blockId);
|
||||||
if (!block)
|
if (!block)
|
||||||
|
|
@ -2505,7 +2508,6 @@ char* NormStreamObject::RetrieveSegment(NormBlockId blockId,
|
||||||
char* segment = block->GetSegment(segmentId);
|
char* segment = block->GetSegment(segmentId);
|
||||||
if (NULL == segment)
|
if (NULL == segment)
|
||||||
DMSG(0, "NormStreamObject::RetrieveSegment() segment unavailable\n");
|
DMSG(0, "NormStreamObject::RetrieveSegment() segment unavailable\n");
|
||||||
tempRetrieval = false;
|
|
||||||
return segment;
|
return segment;
|
||||||
} // end NormStreamObject::RetrieveSegment()
|
} // end NormStreamObject::RetrieveSegment()
|
||||||
|
|
||||||
|
|
@ -2581,8 +2583,6 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
read_index.block = blockId;
|
read_index.block = blockId;
|
||||||
read_index.segment = segmentId;
|
read_index.segment = segmentId;
|
||||||
read_offset = segmentOffset;
|
read_offset = segmentOffset;
|
||||||
TRACE("norm stream read init read_index.segment:%hu read_offset:%lu\n",
|
|
||||||
read_index.segment, read_offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((blockId < read_index.block) ||
|
if ((blockId < read_index.block) ||
|
||||||
|
|
@ -2649,7 +2649,7 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
block->EmptyToPool(segment_pool);
|
block->EmptyToPool(segment_pool);
|
||||||
block_pool.Put(block);
|
block_pool.Put(block);
|
||||||
block = NULL;
|
block = NULL;
|
||||||
Prune(read_index.block);
|
Prune(read_index.block, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2667,7 +2667,7 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
{
|
{
|
||||||
read_index.block++;
|
read_index.block++;
|
||||||
read_index.segment = 0;
|
read_index.segment = 0;
|
||||||
Prune(read_index.block);
|
Prune(read_index.block, false);
|
||||||
}
|
}
|
||||||
stream_buffer.Remove(block);
|
stream_buffer.Remove(block);
|
||||||
block->EmptyToPool(segment_pool);
|
block->EmptyToPool(segment_pool);
|
||||||
|
|
@ -2714,50 +2714,69 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
return true;
|
return true;
|
||||||
} // end NormStreamObject::WriteSegment()
|
} // end NormStreamObject::WriteSegment()
|
||||||
|
|
||||||
void NormStreamObject::Prune(NormBlockId blockId)
|
void NormStreamObject::Prune(NormBlockId blockId, bool updateStatus)
|
||||||
{
|
{
|
||||||
bool resync = false;
|
if (updateStatus || StreamUpdateStatus(blockId))
|
||||||
NormBlock* block;
|
|
||||||
while ((block = block_buffer.Find(block_buffer.RangeLo())))
|
|
||||||
{
|
{
|
||||||
if (block->GetId() < blockId)
|
bool resync = false;
|
||||||
|
NormBlock* block;
|
||||||
|
while ((block = block_buffer.Find(block_buffer.RangeLo())))
|
||||||
{
|
{
|
||||||
resync = true;
|
if (block->GetId() < blockId)
|
||||||
pending_mask.Unset(block->GetId());
|
{
|
||||||
block_buffer.Remove(block);
|
resync = true;
|
||||||
server->PutFreeBlock(block);
|
pending_mask.Unset(block->GetId());
|
||||||
}
|
block_buffer.Remove(block);
|
||||||
else
|
server->PutFreeBlock(block);
|
||||||
{
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
NormBlockId firstId;
|
||||||
NormBlockId firstId;
|
if (GetFirstPending(firstId))
|
||||||
if (GetFirstPending(firstId))
|
|
||||||
{
|
|
||||||
if (firstId < blockId)
|
|
||||||
{
|
{
|
||||||
resync = true;
|
if (firstId < blockId)
|
||||||
UINT32 count = blockId - firstId;
|
{
|
||||||
pending_mask.UnsetBits(firstId, count);
|
resync = true;
|
||||||
|
UINT32 count = blockId - firstId;
|
||||||
|
pending_mask.UnsetBits(firstId, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
while (!StreamUpdateStatus(blockId))
|
||||||
|
{
|
||||||
|
// Server is too far ahead of me ...
|
||||||
|
resync = true;
|
||||||
|
NormBlockId firstId;
|
||||||
|
if (GetFirstPending(firstId))
|
||||||
|
{
|
||||||
|
NormBlock* block = block_buffer.Find(firstId);
|
||||||
|
if (block)
|
||||||
|
{
|
||||||
|
block_buffer.Remove(block);
|
||||||
|
server->PutFreeBlock(block);
|
||||||
|
}
|
||||||
|
pending_mask.Unset(firstId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StreamResync(blockId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resync) server->IncrementResyncCount();
|
||||||
}
|
}
|
||||||
bool result = StreamUpdateStatus(blockId);
|
|
||||||
ASSERT(result);
|
|
||||||
if (resync) server->IncrementResyncCount();
|
|
||||||
result = GetFirstPending(firstId);
|
|
||||||
} // end NormStreamObject::Prune()
|
} // end NormStreamObject::Prune()
|
||||||
|
|
||||||
// Sequential (in order) read/write routines (TBD) Add a "Seek()" method
|
// Sequential (in order) read/write routines (TBD) Add a "Seek()" method
|
||||||
bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStart)
|
bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStart)
|
||||||
{
|
{
|
||||||
SetDebugLevel(4);
|
if (stream_closing || read_init)
|
||||||
TRACE("NormStreamObject::Read(seekMsgStart:%d) read_offset:%lu\n", seekMsgStart, read_offset);
|
|
||||||
if (stream_closing)
|
|
||||||
{
|
{
|
||||||
DMSG(4, "NormStreamObject::Read() attempted to read from closed stream\n");
|
if (stream_closing)
|
||||||
|
DMSG(4, "NormStreamObject::Read() attempted to read from closed stream\n");
|
||||||
*buflen = 0;
|
*buflen = 0;
|
||||||
TRACE("return 1\n");
|
|
||||||
return seekMsgStart ? false : true;
|
return seekMsgStart ? false : true;
|
||||||
}
|
}
|
||||||
Retain();
|
Retain();
|
||||||
|
|
@ -2766,16 +2785,14 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
unsigned int bytesToRead = *buflen;
|
unsigned int bytesToRead = *buflen;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
TRACE("do top ...\n");
|
|
||||||
NormBlock* block = stream_buffer.Find(read_index.block);
|
NormBlock* block = stream_buffer.Find(read_index.block);
|
||||||
if (!block)
|
if (!block)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Read() stream buffer empty (1) (sbEmpty:%d)\n", stream_buffer.IsEmpty());
|
//DMSG(0, "NormStreamObject::Read() stream buffer empty (1) (sbEmpty:%d)\n", stream_buffer.IsEmpty());
|
||||||
*buflen = bytesRead;
|
*buflen = bytesRead;
|
||||||
if (bytesRead > 0)
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
TRACE("return 2\n");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2787,14 +2804,13 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
{
|
{
|
||||||
read_index.block++;
|
read_index.block++;
|
||||||
read_index.segment = 0;
|
read_index.segment = 0;
|
||||||
Prune(read_index.block);
|
Prune(read_index.block, false);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
TRACE("return 3\n");
|
|
||||||
return seekMsgStart ? false : true;
|
return seekMsgStart ? false : true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2805,13 +2821,12 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
|
|
||||||
if (!segment)
|
if (!segment)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Read(%lu:%hu) stream buffer empty (2)\n",
|
//DMSG(0, "NormStreamObject::Read(%lu:%hu) stream buffer empty (2)\n",
|
||||||
(UINT32)read_index.block, read_index.segment);
|
// (UINT32)read_index.block, read_index.segment);
|
||||||
*buflen = bytesRead;
|
*buflen = bytesRead;
|
||||||
if (bytesRead > 0)
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
TRACE("return 4\n");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2826,17 +2841,45 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
block_pool.Put(block);
|
block_pool.Put(block);
|
||||||
read_index.block++;
|
read_index.block++;
|
||||||
read_index.segment = 0;
|
read_index.segment = 0;
|
||||||
Prune(read_index.block);
|
Prune(read_index.block, false); // prevents repair requests for data we
|
||||||
}
|
} // no longer care about
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
TRACE("return 5\n");
|
|
||||||
return seekMsgStart ? false : true;
|
return seekMsgStart ? false : true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // end if (!segment)
|
||||||
|
|
||||||
|
UINT16 length = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||||
|
if (length > segment_size)
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
if (bytesRead > 0)
|
||||||
|
{
|
||||||
|
// Go ahead and return data read thus so far
|
||||||
|
*buflen = bytesRead;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Skip this invalid segment
|
||||||
|
DMSG(0, "NormStreamObject::Read() node>%lu obj>%hu blk>%lu seg>%hu invalid stream segment! (read_offset>%lu length>%hu)\n",
|
||||||
|
LocalNodeId(), (UINT16)transport_id, (UINT32)read_index.block, read_index.segment, read_offset, length);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
*buflen = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 segmentOffset = NormDataMsg::ReadStreamPayloadOffset(segment);
|
UINT32 segmentOffset = NormDataMsg::ReadStreamPayloadOffset(segment);
|
||||||
|
|
@ -2844,26 +2887,44 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
UINT32 diff = read_offset - segmentOffset;
|
UINT32 diff = read_offset - segmentOffset;
|
||||||
if ((diff > 0x80000000) || ((0x80000000 == diff) && (read_offset > segmentOffset)))
|
if ((diff > 0x80000000) || ((0x80000000 == diff) && (read_offset > segmentOffset)))
|
||||||
{
|
{
|
||||||
DMSG(4, "NormStreamObject::Read() node>%lu obj>%hu blk>%lu seg>%hu broken stream! (read_offset>%lu segmentOffset>%lu)\n",
|
|
||||||
LocalNodeId(), (UINT16)transport_id, (UINT32)read_index.block, read_index.segment, read_offset, segmentOffset);
|
|
||||||
read_offset = segmentOffset;
|
|
||||||
*buflen = bytesRead;
|
|
||||||
Release();
|
Release();
|
||||||
return false;
|
if (bytesRead > 0)
|
||||||
|
{
|
||||||
|
// Go ahead and return data read thus so far
|
||||||
|
*buflen = bytesRead;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(4, "NormStreamObject::Read() node>%lu obj>%hu blk>%lu seg>%hu broken stream! (read_offset>%lu segmentOffset>%lu)\n",
|
||||||
|
LocalNodeId(), (UINT16)transport_id, (UINT32)read_index.block, read_index.segment, read_offset, segmentOffset);
|
||||||
|
read_offset = segmentOffset;
|
||||||
|
*buflen = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 index = read_offset - segmentOffset;
|
UINT32 index = read_offset - segmentOffset;
|
||||||
UINT16 length = NormDataMsg::ReadStreamPayloadLength(segment);
|
|
||||||
if ((length > 0) && (index >= length))
|
if ((length > 0) && (index >= length))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Read() node>%lu obj>%hu blk>%lu seg>%hu mangled stream! index:%hu length:%hu "
|
|
||||||
"read_offset:%lu segmentOffset:%lu\n",
|
|
||||||
LocalNodeId(), (UINT16)transport_id, (UINT32)read_index.block, read_index.segment, index, length, read_offset, segmentOffset);
|
|
||||||
read_offset = segmentOffset;
|
|
||||||
*buflen = bytesRead;
|
|
||||||
ASSERT(0);
|
|
||||||
Release();
|
Release();
|
||||||
return false;
|
if (bytesRead > 0)
|
||||||
|
{
|
||||||
|
// Go ahead and return data read thus so far
|
||||||
|
*buflen = bytesRead;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(0, "NormStreamObject::Read() node>%lu obj>%hu blk>%lu seg>%hu mangled stream! index:%hu length:%hu "
|
||||||
|
"read_offset:%lu segmentOffset:%lu\n",
|
||||||
|
LocalNodeId(), (UINT16)transport_id, (UINT32)read_index.block, read_index.segment, index, length, read_offset, segmentOffset);
|
||||||
|
// Reset our read_offset ...
|
||||||
|
read_offset = segmentOffset;
|
||||||
|
*buflen = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2895,9 +2956,8 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
block_pool.Put(block);
|
block_pool.Put(block);
|
||||||
read_index.block++;
|
read_index.block++;
|
||||||
read_index.segment = 0;
|
read_index.segment = 0;
|
||||||
Prune(read_index.block);
|
Prune(read_index.block, false);
|
||||||
}
|
}
|
||||||
TRACE("continue ...\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2934,7 +2994,7 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
block_pool.Put(block);
|
block_pool.Put(block);
|
||||||
read_index.block++;
|
read_index.block++;
|
||||||
read_index.segment = 0;
|
read_index.segment = 0;
|
||||||
Prune(read_index.block);
|
Prune(read_index.block, false);
|
||||||
}
|
}
|
||||||
if (streamEnded)
|
if (streamEnded)
|
||||||
{
|
{
|
||||||
|
|
@ -2947,7 +3007,6 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool seekMsgStar
|
||||||
} while ((bytesToRead > 0) || seekMsgStart); // end while (len > 0)
|
} while ((bytesToRead > 0) || seekMsgStart); // end while (len > 0)
|
||||||
*buflen = bytesRead;
|
*buflen = bytesRead;
|
||||||
Release();
|
Release();
|
||||||
TRACE("return 7\n");
|
|
||||||
return true;
|
return true;
|
||||||
} // end NormStreamObject::Read()
|
} // end NormStreamObject::Read()
|
||||||
|
|
||||||
|
|
@ -3205,8 +3264,8 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
||||||
if (0 != nBytes)
|
if (0 != nBytes)
|
||||||
session.TouchServer();
|
session.TouchServer();
|
||||||
}
|
}
|
||||||
//if ((0 != nBytes) && posted_tx_queue_vacancy)
|
if ((0 != nBytes) && posted_tx_queue_vacancy)
|
||||||
// posted_tx_queue_vacancy = false;
|
posted_tx_queue_vacancy = false;
|
||||||
return nBytes;
|
return nBytes;
|
||||||
} // end NormStreamObject::Write()
|
} // end NormStreamObject::Write()
|
||||||
|
|
||||||
|
|
@ -3262,10 +3321,8 @@ UINT16 NormSimObject::ReadSegment(NormBlockId blockId,
|
||||||
} // end NormSimObject::ReadSegment()
|
} // end NormSimObject::ReadSegment()
|
||||||
|
|
||||||
char* NormSimObject::RetrieveSegment(NormBlockId blockId,
|
char* NormSimObject::RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId)
|
||||||
bool& tempRetrieval)
|
|
||||||
{
|
{
|
||||||
tempRetrieval = true;
|
|
||||||
return server ? server->GetRetrievalSegment() : NULL;
|
return server ? server->GetRetrievalSegment() : NULL;
|
||||||
} // end NormSimObject::RetrieveSegment()
|
} // end NormSimObject::RetrieveSegment()
|
||||||
|
|
||||||
|
|
@ -3313,7 +3370,7 @@ void NormObjectTable::Destroy()
|
||||||
while((obj = Find(range_lo)))
|
while((obj = Find(range_lo)))
|
||||||
{
|
{
|
||||||
Remove(obj);
|
Remove(obj);
|
||||||
delete obj; // (TBD - make this obj->Release() ???
|
obj->Release();
|
||||||
}
|
}
|
||||||
delete []table;
|
delete []table;
|
||||||
table = (NormObject**)NULL;
|
table = (NormObject**)NULL;
|
||||||
|
|
@ -3405,10 +3462,11 @@ bool NormObjectTable::Insert(NormObject* theObject)
|
||||||
theObject->next = entry;
|
theObject->next = entry;
|
||||||
count++;
|
count++;
|
||||||
size = size + theObject->GetSize();
|
size = size + theObject->GetSize();
|
||||||
|
theObject->Retain();
|
||||||
return true;
|
return true;
|
||||||
} // end NormObjectTable::Insert()
|
} // end NormObjectTable::Insert()
|
||||||
|
|
||||||
bool NormObjectTable::Remove(const NormObject* theObject)
|
bool NormObjectTable::Remove(NormObject* theObject)
|
||||||
{
|
{
|
||||||
ASSERT(theObject);
|
ASSERT(theObject);
|
||||||
const NormObjectId& objectId = theObject->GetId();
|
const NormObjectId& objectId = theObject->GetId();
|
||||||
|
|
@ -3508,6 +3566,7 @@ bool NormObjectTable::Remove(const NormObject* theObject)
|
||||||
}
|
}
|
||||||
count--;
|
count--;
|
||||||
size = size - theObject->GetSize();
|
size = size - theObject->GetSize();
|
||||||
|
theObject->Release();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class NormObject
|
||||||
NACK_INFO_ONLY,
|
NACK_INFO_ONLY,
|
||||||
NACK_NORMAL
|
NACK_NORMAL
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~NormObject();
|
virtual ~NormObject();
|
||||||
void Retain();
|
void Retain();
|
||||||
void Release();
|
void Release();
|
||||||
|
|
@ -93,8 +93,7 @@ class NormObject
|
||||||
char* buffer) = 0;
|
char* buffer) = 0;
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId) = 0;
|
||||||
bool& tempRetrieval) = 0;
|
|
||||||
|
|
||||||
NackingMode GetNackingMode() const {return nacking_mode;}
|
NackingMode GetNackingMode() const {return nacking_mode;}
|
||||||
void SetNackingMode(NackingMode nackingMode)
|
void SetNackingMode(NackingMode nackingMode)
|
||||||
|
|
@ -304,8 +303,7 @@ class NormFileObject : public NormObject
|
||||||
char* buffer);
|
char* buffer);
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId);
|
||||||
bool& tempRetrieval);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
@ -348,8 +346,7 @@ class NormDataObject : public NormObject
|
||||||
char* buffer);
|
char* buffer);
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId);
|
||||||
bool& tempRetrieval);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NormObjectSize large_block_length;
|
NormObjectSize large_block_length;
|
||||||
|
|
@ -407,9 +404,12 @@ class NormStreamObject : public NormObject
|
||||||
UINT32 GetCurrentReadOffset() {return read_offset;}
|
UINT32 GetCurrentReadOffset() {return read_offset;}
|
||||||
|
|
||||||
bool StreamUpdateStatus(NormBlockId blockId);
|
bool StreamUpdateStatus(NormBlockId blockId);
|
||||||
void StreamResync(NormBlockId nextBlockId)
|
// Note that the "pending_mask" should be cleared and the
|
||||||
|
// "block_buffer" emptied before "StreamResync()" is invoked
|
||||||
|
void StreamResync(NormBlockId blockId)
|
||||||
{
|
{
|
||||||
stream_next_id = nextBlockId;
|
stream_sync = false;
|
||||||
|
StreamUpdateStatus(blockId);
|
||||||
}
|
}
|
||||||
void StreamAdvance();
|
void StreamAdvance();
|
||||||
|
|
||||||
|
|
@ -422,8 +422,7 @@ class NormStreamObject : public NormObject
|
||||||
char* buffer);
|
char* buffer);
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId);
|
||||||
bool& tempRetrieval);
|
|
||||||
|
|
||||||
|
|
||||||
// For receive stream, we can rewind to earliest buffered offset
|
// For receive stream, we can rewind to earliest buffered offset
|
||||||
|
|
@ -433,7 +432,7 @@ class NormStreamObject : public NormObject
|
||||||
bool LockSegments(NormBlockId blockId, NormSegmentId firstId,
|
bool LockSegments(NormBlockId blockId, NormSegmentId firstId,
|
||||||
NormSegmentId lastId);
|
NormSegmentId lastId);
|
||||||
NormBlockId StreamBufferLo() {return stream_buffer.RangeLo();}
|
NormBlockId StreamBufferLo() {return stream_buffer.RangeLo();}
|
||||||
void Prune(NormBlockId blockId);
|
void Prune(NormBlockId blockId, bool updateStatus);
|
||||||
|
|
||||||
bool IsFlushPending() {return flush_pending;}
|
bool IsFlushPending() {return flush_pending;}
|
||||||
NormBlockId FlushBlockId()
|
NormBlockId FlushBlockId()
|
||||||
|
|
@ -518,8 +517,7 @@ class NormSimObject : public NormObject
|
||||||
char* buffer);
|
char* buffer);
|
||||||
|
|
||||||
virtual char* RetrieveSegment(NormBlockId blockId,
|
virtual char* RetrieveSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId);
|
||||||
bool& tempRetrieval);
|
|
||||||
}; // end class NormSimObject
|
}; // end class NormSimObject
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
|
|
||||||
|
|
@ -537,7 +535,7 @@ class NormObjectTable
|
||||||
bool IsInited() const {return (NULL != table);}
|
bool IsInited() const {return (NULL != table);}
|
||||||
bool CanInsert(NormObjectId objectId) const;
|
bool CanInsert(NormObjectId objectId) const;
|
||||||
bool Insert(NormObject* theObject);
|
bool Insert(NormObject* theObject);
|
||||||
bool Remove(const NormObject* theObject);
|
bool Remove(NormObject* theObject);
|
||||||
NormObject* Find(const NormObjectId& objectId) const;
|
NormObject* Find(const NormObjectId& objectId) const;
|
||||||
|
|
||||||
NormObjectId RangeLo() const {return range_lo;}
|
NormObjectId RangeLo() const {return range_lo;}
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ void NormBlock::EmptyToPool(NormSegmentPool& segmentPool)
|
||||||
ASSERT(segment_table);
|
ASSERT(segment_table);
|
||||||
for (unsigned int i = 0; i < size; i++)
|
for (unsigned int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
if (segment_table[i])
|
if (NULL != segment_table[i])
|
||||||
{
|
{
|
||||||
segmentPool.Put(segment_table[i]);
|
segmentPool.Put(segment_table[i]);
|
||||||
segment_table[i] = (char*)NULL;
|
segment_table[i] = (char*)NULL;
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ class NormBlock
|
||||||
pending_mask.SetBits(0, ndata+nparity);
|
pending_mask.SetBits(0, ndata+nparity);
|
||||||
repair_mask.Clear();
|
repair_mask.Clear();
|
||||||
erasure_count = ndata;
|
erasure_count = ndata;
|
||||||
parity_count = 0;
|
parity_count = 0;
|
||||||
parity_offset = 0;
|
parity_offset = 0;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ const UINT8 NormSession::DEFAULT_TTL = 255; // bits/sec
|
||||||
const double NormSession::DEFAULT_TRANSMIT_RATE = 64000.0; // bits/sec
|
const double NormSession::DEFAULT_TRANSMIT_RATE = 64000.0; // bits/sec
|
||||||
const double NormSession::DEFAULT_GRTT_INTERVAL_MIN = 1.0; // sec
|
const double NormSession::DEFAULT_GRTT_INTERVAL_MIN = 1.0; // sec
|
||||||
const double NormSession::DEFAULT_GRTT_INTERVAL_MAX = 30.0; // sec
|
const double NormSession::DEFAULT_GRTT_INTERVAL_MAX = 30.0; // sec
|
||||||
const double NormSession::DEFAULT_GRTT_ESTIMATE = 0.5; // sec
|
const double NormSession::DEFAULT_GRTT_ESTIMATE = 0.25; // sec
|
||||||
const double NormSession::DEFAULT_GRTT_MAX = 10.0; // sec
|
const double NormSession::DEFAULT_GRTT_MAX = 10.0; // sec
|
||||||
const unsigned int NormSession::DEFAULT_GRTT_DECREASE_DELAY = 3;
|
const unsigned int NormSession::DEFAULT_GRTT_DECREASE_DELAY = 3;
|
||||||
const double NormSession::DEFAULT_BACKOFF_FACTOR = 4.0;
|
const double NormSession::DEFAULT_BACKOFF_FACTOR = 4.0;
|
||||||
|
|
@ -18,7 +18,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
: session_mgr(sessionMgr), notify_pending(false), tx_port(0),
|
: session_mgr(sessionMgr), notify_pending(false), tx_port(0),
|
||||||
tx_socket(&tx_socket_actual), tx_socket_actual(ProtoSocket::UDP),
|
tx_socket(&tx_socket_actual), tx_socket_actual(ProtoSocket::UDP),
|
||||||
rx_socket(ProtoSocket::UDP), local_node_id(localNodeId),
|
rx_socket(ProtoSocket::UDP), local_node_id(localNodeId),
|
||||||
ttl(DEFAULT_TTL), loopback(false),
|
ttl(DEFAULT_TTL), loopback(false), rx_port_reuse(false),
|
||||||
tx_rate(DEFAULT_TRANSMIT_RATE/8.0), tx_rate_min(-1.0), tx_rate_max(-1.0),
|
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),
|
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), instance_id(0),
|
||||||
ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(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),
|
posted_tx_queue_empty(false),
|
||||||
acking_node_count(0), watermark_pending(false), advertise_repairs(false),
|
acking_node_count(0), watermark_pending(false), advertise_repairs(false),
|
||||||
suppress_nonconfirmed(false), suppress_rate(-1.0), suppress_rtt(-1.0),
|
suppress_nonconfirmed(false), suppress_rate(-1.0), suppress_rtt(-1.0),
|
||||||
probe_proactive(true), probe_pending(false), probe_reset(false),
|
probe_proactive(true), probe_pending(false), probe_reset(true),
|
||||||
grtt_interval(0.5),
|
grtt_interval(0.5),
|
||||||
grtt_interval_min(DEFAULT_GRTT_INTERVAL_MIN),
|
grtt_interval_min(DEFAULT_GRTT_INTERVAL_MIN),
|
||||||
grtt_interval_max(DEFAULT_GRTT_INTERVAL_MAX),
|
grtt_interval_max(DEFAULT_GRTT_INTERVAL_MAX),
|
||||||
|
|
@ -64,6 +64,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
probe_timer.SetListener(this, &NormSession::OnProbeTimeout);
|
probe_timer.SetListener(this, &NormSession::OnProbeTimeout);
|
||||||
probe_timer.SetInterval(0.0);
|
probe_timer.SetInterval(0.0);
|
||||||
probe_timer.SetRepeat(-1);
|
probe_timer.SetRepeat(-1);
|
||||||
|
probe_time_last.tv_sec = probe_time_last.tv_usec = 0;
|
||||||
|
|
||||||
grtt_quantized = NormQuantizeRtt(DEFAULT_GRTT_ESTIMATE);
|
grtt_quantized = NormQuantizeRtt(DEFAULT_GRTT_ESTIMATE);
|
||||||
grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||||
|
|
@ -107,12 +108,33 @@ bool NormSession::Open(const char* interfaceName)
|
||||||
}
|
}
|
||||||
if (!rx_socket.IsOpen())
|
if (!rx_socket.IsOpen())
|
||||||
{
|
{
|
||||||
if (!rx_socket.Open(address.GetPort(), address.GetType()))
|
if (!rx_socket.Open(0, address.GetType(), false))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::Open() rx_socket open error\n");
|
DMSG(0, "NormSession::Open() rx_socket open error\n");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const ProtoAddress* bindAddr = NULL;
|
||||||
|
if (rx_port_reuse)
|
||||||
|
{
|
||||||
|
// Enable port/addr reuse and bind socket to destination address
|
||||||
|
if (!rx_socket.SetReuse(true))
|
||||||
|
{
|
||||||
|
DMSG(0, "NormSession::Open() rx_socket reuse error\n");
|
||||||
|
Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#ifndef WIN32
|
||||||
|
if (address.IsMulticast()) // Win32 doesn't like to bind to multicast addr ???
|
||||||
|
bindAddr = &address;
|
||||||
|
#endif // !WIN32
|
||||||
|
}
|
||||||
|
if(!rx_socket.Bind(address.GetPort(), bindAddr))
|
||||||
|
{
|
||||||
|
DMSG(0, "NormSession::Open() rx_socket bind error\n");
|
||||||
|
Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.IsMulticast())
|
if (address.IsMulticast())
|
||||||
|
|
@ -198,11 +220,13 @@ bool NormSession::SetMulticastInterface(const char* interfaceName)
|
||||||
{
|
{
|
||||||
if (interfaceName)
|
if (interfaceName)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
if (rx_socket.IsOpen())
|
if (rx_socket.IsOpen())
|
||||||
result &= rx_socket.SetMulticastInterface(interfaceName);
|
result &= rx_socket.SetMulticastInterface(interfaceName);
|
||||||
if (tx_socket->IsOpen())
|
if (tx_socket->IsOpen())
|
||||||
result &= tx_socket->SetMulticastInterface(interfaceName);
|
result &= tx_socket->SetMulticastInterface(interfaceName);
|
||||||
|
strncpy(interface_name, interfaceName, 32);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -212,9 +236,8 @@ bool NormSession::SetMulticastInterface(const char* interfaceName)
|
||||||
}
|
}
|
||||||
} // end NormSession::SetMulticastInterface()
|
} // end NormSession::SetMulticastInterface()
|
||||||
|
|
||||||
void NormSession::SetTxRate(double txRate)
|
void NormSession::SetTxRateInternal(double txRate)
|
||||||
{
|
{
|
||||||
txRate /= 8.0; // convert to bytes/sec
|
|
||||||
if (tx_timer.IsActive())
|
if (tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
tx_timer.Deactivate();
|
tx_timer.Deactivate();
|
||||||
|
|
@ -236,7 +259,19 @@ void NormSession::SetTxRate(double txRate)
|
||||||
{
|
{
|
||||||
tx_rate = txRate;
|
tx_rate = txRate;
|
||||||
}
|
}
|
||||||
} // end NormSession::SetTxRate()
|
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)
|
void NormSession::SetTxRateBounds(double rateMin, double rateMax)
|
||||||
{
|
{
|
||||||
|
|
@ -264,7 +299,7 @@ void NormSession::SetTxRateBounds(double rateMin, double rateMax)
|
||||||
tx_rate = tx_rate_min;
|
tx_rate = tx_rate_min;
|
||||||
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
|
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
|
||||||
tx_rate = tx_rate_max;
|
tx_rate = tx_rate_max;
|
||||||
SetTxRate(tx_rate*8.0);
|
SetTxRateInternal(tx_rate);
|
||||||
}
|
}
|
||||||
} // end NormSession::SetTxRateBounds()
|
} // end NormSession::SetTxRateBounds()
|
||||||
|
|
||||||
|
|
@ -348,8 +383,6 @@ bool NormSession::StartServer(UINT16 instanceId,
|
||||||
nparity = numParity;
|
nparity = numParity;
|
||||||
is_server = true;
|
is_server = true;
|
||||||
flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor
|
flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor
|
||||||
//probe_timer.SetInterval(0.0);
|
|
||||||
probe_pending = probe_reset = false;
|
|
||||||
|
|
||||||
if (cc_enable)
|
if (cc_enable)
|
||||||
{
|
{
|
||||||
|
|
@ -359,16 +392,25 @@ bool NormSession::StartServer(UINT16 instanceId,
|
||||||
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
|
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
|
||||||
tx_rate = tx_rate_max;
|
tx_rate = tx_rate_max;
|
||||||
}
|
}
|
||||||
|
grtt_age = 0.0;
|
||||||
OnProbeTimeout(probe_timer);
|
probe_pending = false;
|
||||||
ActivateTimer(probe_timer);
|
if (probe_reset)
|
||||||
|
{
|
||||||
|
probe_reset = false;
|
||||||
|
OnProbeTimeout(probe_timer);
|
||||||
|
ActivateTimer(probe_timer);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} // end NormSession::StartServer()
|
} // end NormSession::StartServer()
|
||||||
|
|
||||||
|
|
||||||
void NormSession::StopServer()
|
void NormSession::StopServer()
|
||||||
{
|
{
|
||||||
if (probe_timer.IsActive()) probe_timer.Deactivate();
|
if (probe_timer.IsActive())
|
||||||
|
{
|
||||||
|
probe_timer.Deactivate();
|
||||||
|
probe_reset = true;
|
||||||
|
}
|
||||||
encoder.Destroy();
|
encoder.Destroy();
|
||||||
acking_node_tree.Destroy();
|
acking_node_tree.Destroy();
|
||||||
cc_node_list.Destroy();
|
cc_node_list.Destroy();
|
||||||
|
|
@ -685,7 +727,6 @@ void NormSession::ServerRemoveAckingNode(NormNodeId nodeId)
|
||||||
if (watermark_pending && theNode->AckReceived())
|
if (watermark_pending && theNode->AckReceived())
|
||||||
acks_collected--;
|
acks_collected--;
|
||||||
acking_node_tree.DetachNode(theNode);
|
acking_node_tree.DetachNode(theNode);
|
||||||
delete theNode;
|
|
||||||
acking_node_count--;
|
acking_node_count--;
|
||||||
}
|
}
|
||||||
} // end NormSession::RemoveAckingNode()
|
} // end NormSession::RemoveAckingNode()
|
||||||
|
|
@ -863,7 +904,7 @@ NormFileObject* NormSession::QueueTxFile(const char* path,
|
||||||
if (!file->Open(path, infoPtr, infoLen))
|
if (!file->Open(path, infoPtr, infoLen))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::QueueTxFile() file open error\n");
|
DMSG(0, "NormSession::QueueTxFile() file open error\n");
|
||||||
delete file;
|
file->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (QueueTxObject(file))
|
if (QueueTxObject(file))
|
||||||
|
|
@ -873,7 +914,7 @@ NormFileObject* NormSession::QueueTxFile(const char* path,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
file->Close();
|
file->Close();
|
||||||
delete file;
|
file->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} // end NormSession::QueueTxFile()
|
} // end NormSession::QueueTxFile()
|
||||||
|
|
@ -898,7 +939,7 @@ NormDataObject* NormSession::QueueTxData(const char* dataPtr,
|
||||||
if (!obj->Open((char*)dataPtr, dataLen, false, infoPtr, infoLen))
|
if (!obj->Open((char*)dataPtr, dataLen, false, infoPtr, infoLen))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::QueueTxData() object open error\n");
|
DMSG(0, "NormSession::QueueTxData() object open error\n");
|
||||||
delete obj;
|
obj->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (QueueTxObject(obj))
|
if (QueueTxObject(obj))
|
||||||
|
|
@ -908,7 +949,7 @@ NormDataObject* NormSession::QueueTxData(const char* dataPtr,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
obj->Close();
|
obj->Close();
|
||||||
delete obj;
|
obj->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} // end NormSession::QueueTxData()
|
} // end NormSession::QueueTxData()
|
||||||
|
|
@ -934,7 +975,7 @@ NormStreamObject* NormSession::QueueTxStream(UINT32 bufferSize,
|
||||||
if (!stream->Open(bufferSize, doubleBuffer, infoPtr, infoLen))
|
if (!stream->Open(bufferSize, doubleBuffer, infoPtr, infoLen))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::QueueTxStream() stream open error\n");
|
DMSG(0, "NormSession::QueueTxStream() stream open error\n");
|
||||||
delete stream;
|
stream->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (QueueTxObject(stream))
|
if (QueueTxObject(stream))
|
||||||
|
|
@ -946,7 +987,7 @@ NormStreamObject* NormSession::QueueTxStream(UINT32 bufferSize,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream->Close();
|
stream->Close();
|
||||||
delete stream;
|
stream->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} // end NormSession::QueueTxStream()
|
} // end NormSession::QueueTxStream()
|
||||||
|
|
@ -970,7 +1011,7 @@ NormSimObject* NormSession::QueueTxSim(unsigned long objectSize)
|
||||||
if (!simObject->Open(objectSize))
|
if (!simObject->Open(objectSize))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::QueueTxSim() open error\n");
|
DMSG(0, "NormSession::QueueTxSim() open error\n");
|
||||||
delete simObject;
|
simObject->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (QueueTxObject(simObject))
|
if (QueueTxObject(simObject))
|
||||||
|
|
@ -979,7 +1020,7 @@ NormSimObject* NormSession::QueueTxSim(unsigned long objectSize)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete simObject;
|
simObject->Release();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} // end NormSession::QueueTxSim()
|
} // end NormSession::QueueTxSim()
|
||||||
|
|
@ -1024,7 +1065,6 @@ bool NormSession::QueueTxObject(NormObject* obj)
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
obj->Retain();
|
|
||||||
tx_pending_mask.Set(obj->GetId());
|
tx_pending_mask.Set(obj->GetId());
|
||||||
ASSERT(tx_pending_mask.Test(obj->GetId()));
|
ASSERT(tx_pending_mask.Test(obj->GetId()));
|
||||||
next_tx_object_id++;
|
next_tx_object_id++;
|
||||||
|
|
@ -1351,11 +1391,12 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
|
|
||||||
void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
||||||
{
|
{
|
||||||
|
// Ignore messages from ourself unless "loopback" is enabled
|
||||||
|
if ((msg.GetSourceId() == LocalNodeId()) && !loopback)
|
||||||
|
return;
|
||||||
// Drop some rx messages for testing
|
// Drop some rx messages for testing
|
||||||
if (UniformRand(100.0) < rx_loss_rate)
|
if (UniformRand(100.0) < rx_loss_rate)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
::ProtoSystemTime(currentTime);
|
::ProtoSystemTime(currentTime);
|
||||||
|
|
@ -1434,7 +1475,6 @@ void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
|
||||||
if (theServer->Open(msg.GetInstanceId()))
|
if (theServer->Open(msg.GetInstanceId()))
|
||||||
{
|
{
|
||||||
server_tree.AttachNode(theServer);
|
server_tree.AttachNode(theServer);
|
||||||
theServer->Retain();
|
|
||||||
DMSG(4, "NormSession::ClientHandleObjectMessage() node>%lu new remote server:%lu ...\n",
|
DMSG(4, "NormSession::ClientHandleObjectMessage() node>%lu new remote server:%lu ...\n",
|
||||||
LocalNodeId(), msg.GetSourceId());
|
LocalNodeId(), msg.GetSourceId());
|
||||||
}
|
}
|
||||||
|
|
@ -1492,7 +1532,6 @@ void NormSession::ClientHandleCommand(const struct timeval& currentTime,
|
||||||
if (theServer->Open(cmd.GetInstanceId()))
|
if (theServer->Open(cmd.GetInstanceId()))
|
||||||
{
|
{
|
||||||
server_tree.AttachNode(theServer);
|
server_tree.AttachNode(theServer);
|
||||||
theServer->Retain();
|
|
||||||
DMSG(4, "NormSession::ClientHandleCommand() node>%lu new remote server:%lu ...\n",
|
DMSG(4, "NormSession::ClientHandleCommand() node>%lu new remote server:%lu ...\n",
|
||||||
LocalNodeId(), cmd.GetSourceId());
|
LocalNodeId(), cmd.GetSourceId());
|
||||||
}
|
}
|
||||||
|
|
@ -1555,28 +1594,32 @@ double NormSession::CalculateRtt(const struct timeval& currentTime,
|
||||||
void NormSession::ServerUpdateGrttEstimate(double clientRtt)
|
void NormSession::ServerUpdateGrttEstimate(double clientRtt)
|
||||||
{
|
{
|
||||||
grtt_response = true;
|
grtt_response = true;
|
||||||
//if ((clientRtt > grtt_current_peak) || !address.IsMulticast())
|
|
||||||
|
|
||||||
if ((clientRtt > grtt_measured) || !address.IsMulticast())
|
if ((clientRtt > grtt_measured) || !address.IsMulticast())
|
||||||
{
|
{
|
||||||
// Immediately incorporate bigger RTT's
|
// Immediately incorporate bigger RTT's
|
||||||
grtt_current_peak = clientRtt;
|
grtt_decrease_delay_count = DEFAULT_GRTT_DECREASE_DELAY;
|
||||||
//if ((clientRtt > grtt_measured) || !address.IsMulticast())
|
//grtt_measured = 0.25 * grtt_measured + 0.75 * clientRtt;
|
||||||
{
|
grtt_measured = 0.9 * grtt_measured + 0.1 * clientRtt;
|
||||||
grtt_decrease_delay_count = DEFAULT_GRTT_DECREASE_DELAY;
|
if (grtt_measured > grtt_max) grtt_measured = grtt_max;
|
||||||
//grtt_measured = 0.25 * grtt_measured + 0.75 * clientRtt;
|
UINT8 grttQuantizedOld = grtt_quantized;
|
||||||
grtt_measured = 0.9 * grtt_measured + 0.1 * clientRtt;
|
double pktInterval = ((double)(44+segment_size))/tx_rate;
|
||||||
if (grtt_measured > grtt_max) grtt_measured = grtt_max;
|
if (grtt_measured < pktInterval)
|
||||||
double pktInterval = ((double)(44+segment_size))/tx_rate;
|
grtt_quantized = NormQuantizeRtt(pktInterval);
|
||||||
UINT8 grttQuantizedOld = grtt_quantized;
|
else
|
||||||
grtt_quantized = NormQuantizeRtt(MAX(pktInterval, grtt_measured));
|
grtt_quantized = NormQuantizeRtt(grtt_measured);
|
||||||
// Calculate grtt_advertised since quantization rounds upward
|
// Calculate grtt_advertised since quantization rounds upward
|
||||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||||
|
grtt_current_peak = grtt_measured;
|
||||||
if (grttQuantizedOld != grtt_quantized)
|
if (grttQuantizedOld != grtt_quantized)
|
||||||
DMSG(4, "NormSession::ServerUpdateGrttEstimate() node>%lu new grtt>%lf sec\n",
|
DMSG(4, "NormSession::ServerUpdateGrttEstimate() node>%lu increased to new grtt>%lf sec\n",
|
||||||
LocalNodeId(), grtt_advertised);
|
LocalNodeId(), grtt_advertised);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (clientRtt > grtt_current_peak)
|
||||||
|
{
|
||||||
|
grtt_current_peak = clientRtt;
|
||||||
|
}
|
||||||
} // end NormSession::ServerUpdateGrttEstimate()
|
} // end NormSession::ServerUpdateGrttEstimate()
|
||||||
|
|
||||||
double NormSession::CalculateRate(double size, double rtt, double loss)
|
double NormSession::CalculateRate(double size, double rtt, double loss)
|
||||||
|
|
@ -1587,12 +1630,13 @@ double NormSession::CalculateRate(double size, double rtt, double loss)
|
||||||
return (size / denom);
|
return (size / denom);
|
||||||
} // end NormSession::CalculateRate()
|
} // end NormSession::CalculateRate()
|
||||||
|
|
||||||
void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
void NormSession::ServerHandleCCFeedback(struct timeval currentTime,
|
||||||
UINT8 ccFlags,
|
NormNodeId nodeId,
|
||||||
double ccRtt,
|
UINT8 ccFlags,
|
||||||
double ccLoss,
|
double ccRtt,
|
||||||
double ccRate,
|
double ccLoss,
|
||||||
UINT16 ccSequence)
|
double ccRate,
|
||||||
|
UINT16 ccSequence)
|
||||||
{
|
{
|
||||||
// Keep track of current suppressing feedback
|
// Keep track of current suppressing feedback
|
||||||
// (non-CLR, lowest rate, unconfirmed RTT)
|
// (non-CLR, lowest rate, unconfirmed RTT)
|
||||||
|
|
@ -1641,6 +1685,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
double savedLoss = next->GetLoss();
|
double savedLoss = next->GetLoss();
|
||||||
double savedRate = next->GetRate();
|
double savedRate = next->GetRate();
|
||||||
UINT16 savedSequence = next->GetCCSequence();
|
UINT16 savedSequence = next->GetCCSequence();
|
||||||
|
struct timeval savedTime = next->GetFeedbackTime();
|
||||||
|
|
||||||
next->SetId(nodeId);
|
next->SetId(nodeId);
|
||||||
next->SetClrStatus(true);
|
next->SetClrStatus(true);
|
||||||
|
|
@ -1649,7 +1694,8 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
next->SetRate(ccRate);
|
next->SetRate(ccRate);
|
||||||
next->SetCCSequence(ccSequence);
|
next->SetCCSequence(ccSequence);
|
||||||
next->SetActive(true);
|
next->SetActive(true);
|
||||||
if (next->GetId() == nodeId)
|
next->SetFeedbackTime(currentTime);
|
||||||
|
if (savedId == nodeId)
|
||||||
{
|
{
|
||||||
// This was feedback from the current CLR
|
// This was feedback from the current CLR
|
||||||
AdjustRate(true);
|
AdjustRate(true);
|
||||||
|
|
@ -1668,6 +1714,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
ccLoss = savedLoss;
|
ccLoss = savedLoss;
|
||||||
ccRate = savedRate,
|
ccRate = savedRate,
|
||||||
ccSequence = savedSequence;
|
ccSequence = savedSequence;
|
||||||
|
currentTime = savedTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1688,12 +1735,14 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
}
|
}
|
||||||
next->SetId(nodeId);
|
next->SetId(nodeId);
|
||||||
next->SetClrStatus(true);
|
next->SetClrStatus(true);
|
||||||
|
//next->SetPlrStatus(false);
|
||||||
next->SetRttStatus(0 != (ccFlags & NormCC::RTT));
|
next->SetRttStatus(0 != (ccFlags & NormCC::RTT));
|
||||||
next->SetRtt(ccRtt);
|
next->SetRtt(ccRtt);
|
||||||
next->SetLoss(ccLoss);
|
next->SetLoss(ccLoss);
|
||||||
next->SetRate(ccRate);
|
next->SetRate(ccRate);
|
||||||
next->SetCCSequence(ccSequence);
|
next->SetCCSequence(ccSequence);
|
||||||
next->SetActive(true);
|
next->SetActive(true);
|
||||||
|
next->SetFeedbackTime(currentTime);
|
||||||
AdjustRate(true);
|
AdjustRate(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1764,6 +1813,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
{
|
{
|
||||||
candidate->SetId(nodeId);
|
candidate->SetId(nodeId);
|
||||||
candidate->SetClrStatus(false);
|
candidate->SetClrStatus(false);
|
||||||
|
//candidate->SetPlrStatus(true); // do this only
|
||||||
candidate->SetRttStatus(0 != (ccFlags & NormCC::RTT));
|
candidate->SetRttStatus(0 != (ccFlags & NormCC::RTT));
|
||||||
candidate->SetRtt(ccRtt);
|
candidate->SetRtt(ccRtt);
|
||||||
candidate->SetLoss(ccLoss);
|
candidate->SetLoss(ccLoss);
|
||||||
|
|
@ -1789,28 +1839,28 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
|
||||||
{
|
{
|
||||||
if (NormHeaderExtension::CC_FEEDBACK == ext.GetType())
|
if (NormHeaderExtension::CC_FEEDBACK == ext.GetType())
|
||||||
{
|
{
|
||||||
ServerHandleCCFeedback(ack.GetSourceId(),
|
ServerHandleCCFeedback(currentTime,
|
||||||
|
ack.GetSourceId(),
|
||||||
ext.GetCCFlags(),
|
ext.GetCCFlags(),
|
||||||
clientRtt >= 0.0 ?
|
clientRtt >= 0.0 ?
|
||||||
clientRtt : NormUnquantizeRtt(ext.GetCCRtt()),
|
clientRtt : NormUnquantizeRtt(ext.GetCCRtt()),
|
||||||
NormUnquantizeLoss(ext.GetCCLoss()),
|
NormUnquantizeLoss(ext.GetCCLoss()),
|
||||||
NormUnquantizeRate(ext.GetCCRate()),
|
NormUnquantizeRate(ext.GetCCRate()),
|
||||||
ext.GetCCSequence());
|
ext.GetCCSequence());
|
||||||
|
if (wasUnicast && probe_proactive && Address().IsMulticast())
|
||||||
|
{
|
||||||
|
// for suppression of unicast cc feedback
|
||||||
|
advertise_repairs = true;
|
||||||
|
QueueMessage(NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wasUnicast && probe_proactive && Address().IsMulticast())
|
|
||||||
{
|
|
||||||
// for suppression of unicast feedback
|
|
||||||
advertise_repairs = true;
|
|
||||||
QueueMessage(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ack.GetAckType())
|
switch (ack.GetAckType())
|
||||||
{
|
{
|
||||||
case NormAck::CC:
|
case NormAck::CC:
|
||||||
// Everything is in the ACK header for this one
|
// Everything is in the ACK header or extension for this one
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NormAck::FLUSH:
|
case NormAck::FLUSH:
|
||||||
|
|
@ -1880,7 +1930,8 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
||||||
{
|
{
|
||||||
if (NormHeaderExtension::CC_FEEDBACK == ext.GetType())
|
if (NormHeaderExtension::CC_FEEDBACK == ext.GetType())
|
||||||
{
|
{
|
||||||
ServerHandleCCFeedback(nack.GetSourceId(),
|
ServerHandleCCFeedback(currentTime,
|
||||||
|
nack.GetSourceId(),
|
||||||
ext.GetCCFlags(),
|
ext.GetCCFlags(),
|
||||||
clientRtt >= 0.0 ?
|
clientRtt >= 0.0 ?
|
||||||
clientRtt : NormUnquantizeRtt(ext.GetCCRtt()),
|
clientRtt : NormUnquantizeRtt(ext.GetCCRtt()),
|
||||||
|
|
@ -2583,9 +2634,8 @@ bool NormSession::OnTxTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
NormMsg* msg;
|
NormMsg* msg;
|
||||||
|
|
||||||
// (TBD) sometimes need RepairAdv even when cc_enable is false ...
|
// Note: sometimes need RepairAdv even when cc_enable is false ...
|
||||||
NormCmdRepairAdvMsg adv;
|
NormCmdRepairAdvMsg adv;
|
||||||
|
|
||||||
if (advertise_repairs && (probe_proactive || (repair_timer.IsActive() &&
|
if (advertise_repairs && (probe_proactive || (repair_timer.IsActive() &&
|
||||||
repair_timer.GetRepeatCount())))
|
repair_timer.GetRepeatCount())))
|
||||||
{
|
{
|
||||||
|
|
@ -2729,7 +2779,7 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Fill in common message fields
|
// Fill in common message fields
|
||||||
|
|
||||||
msg.SetSourceId(local_node_id);
|
msg.SetSourceId(local_node_id);
|
||||||
UINT16 msgSize = msg.GetLength();
|
UINT16 msgSize = msg.GetLength();
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
@ -2798,6 +2848,82 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
return result;
|
return result;
|
||||||
} // end NormSession::SendMessage()
|
} // end NormSession::SendMessage()
|
||||||
|
|
||||||
|
void NormSession::SetGrttProbingInterval(double intervalMin, double intervalMax)
|
||||||
|
{
|
||||||
|
if ((intervalMin < 0.0) || (intervalMax < 0.0)) return;
|
||||||
|
double temp = intervalMin;
|
||||||
|
if (temp > intervalMax)
|
||||||
|
{
|
||||||
|
intervalMin = intervalMax;
|
||||||
|
intervalMax = temp;
|
||||||
|
}
|
||||||
|
if (intervalMin < 0.100) intervalMin = 0.100;
|
||||||
|
if (intervalMax < 0.100) intervalMax = 0.100;
|
||||||
|
grtt_interval_min = intervalMin;
|
||||||
|
grtt_interval_max = intervalMax;
|
||||||
|
if (grtt_interval < grtt_interval_min)
|
||||||
|
grtt_interval = grtt_interval_min;
|
||||||
|
if (grtt_interval > grtt_interval_max)
|
||||||
|
{
|
||||||
|
grtt_interval = grtt_interval_max;
|
||||||
|
if (probe_timer.IsActive() && !cc_enable)
|
||||||
|
{
|
||||||
|
double elapsed = probe_timer.GetInterval() - probe_timer.GetTimeRemaining();
|
||||||
|
if (elapsed < 0.0) elapsed = 0.0;
|
||||||
|
probe_timer.Deactivate();
|
||||||
|
if (elapsed > grtt_interval)
|
||||||
|
probe_timer.SetInterval(0.0);
|
||||||
|
else
|
||||||
|
probe_timer.SetInterval(grtt_interval - elapsed);
|
||||||
|
ActivateTimer(probe_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end NormSession::SetGrttProbingInterval()
|
||||||
|
|
||||||
|
void NormSession::SetGrttProbingMode(ProbingMode probingMode)
|
||||||
|
{
|
||||||
|
if (cc_enable) return; // can't change probing mode when cc is enabled!
|
||||||
|
// (cc _requires_ probing mode == PROBE_ACTIVE)
|
||||||
|
switch (probingMode)
|
||||||
|
{
|
||||||
|
case PROBE_NONE:
|
||||||
|
probe_reset = false;
|
||||||
|
if (probe_timer.IsActive())
|
||||||
|
probe_timer.Deactivate();
|
||||||
|
break;
|
||||||
|
case PROBE_PASSIVE:
|
||||||
|
probe_proactive = false;
|
||||||
|
if (IsServer())
|
||||||
|
{
|
||||||
|
if (!probe_timer.IsActive())
|
||||||
|
{
|
||||||
|
probe_timer.SetInterval(0.0);
|
||||||
|
ActivateTimer(probe_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
probe_reset = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROBE_ACTIVE:
|
||||||
|
probe_proactive = true;
|
||||||
|
if (IsServer())
|
||||||
|
{
|
||||||
|
if (!probe_timer.IsActive())
|
||||||
|
{
|
||||||
|
probe_timer.SetInterval(0.0);
|
||||||
|
ActivateTimer(probe_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
probe_reset = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end NormSession::SetGrttProbingMode()
|
||||||
|
|
||||||
bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
// 1) Temporarily kill probe_timer if CMD(CC) not yet tx'd
|
// 1) Temporarily kill probe_timer if CMD(CC) not yet tx'd
|
||||||
|
|
@ -2809,17 +2935,45 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
}
|
}
|
||||||
else if (0.0 == tx_rate)
|
else if (0.0 == tx_rate)
|
||||||
{
|
{
|
||||||
// Sender paused, just idle probing until transmission is resumed
|
// Sender paused, so just skip probing until transmission is resumed
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Update grtt_estimate _if_ sufficient time elapsed.
|
// 2) Update grtt_estimate _if_ sufficient time elapsed.
|
||||||
// This new code allows more liberal downward adjustment of
|
// This new code allows more liberal downward adjustment of
|
||||||
// of grtt when congestion control is enabled.
|
// of grtt when congestion control is enabled.
|
||||||
grtt_age += probe_timer.GetInterval();
|
|
||||||
double ageMax = 3 * grtt_advertised;
|
// We have to keep track of the _actual_ deltaTime instead
|
||||||
ageMax = ageMax > grtt_interval_min ? ageMax : grtt_interval_min;
|
// of relying on the probe_timer interval because in real-
|
||||||
if (grtt_age >= ageMax)//grtt_interval)
|
// world operating systems, they're aren't the same and
|
||||||
|
// sometimes not even close.
|
||||||
|
struct timeval currentTime;
|
||||||
|
ProtoSystemTime(currentTime);
|
||||||
|
if ((0 == probe_time_last.tv_sec) && (0 == probe_time_last.tv_usec))
|
||||||
|
{
|
||||||
|
grtt_age += probe_timer.GetInterval();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double deltaTime = currentTime.tv_sec - probe_time_last.tv_sec;
|
||||||
|
if (currentTime.tv_usec > probe_time_last.tv_usec)
|
||||||
|
deltaTime += 1.0e-06*((double)(currentTime.tv_usec - probe_time_last.tv_usec));
|
||||||
|
else
|
||||||
|
deltaTime -= 1.0e-06*((double)(probe_time_last.tv_usec - currentTime.tv_usec));
|
||||||
|
grtt_age += deltaTime;
|
||||||
|
}
|
||||||
|
probe_time_last = currentTime;
|
||||||
|
|
||||||
|
// (TBD) We need to revisit the whole set of issues surrounding dynamic
|
||||||
|
// estimation of grtt, particularly when congestion control is involved.
|
||||||
|
// The main issue is when the rate increases rapidly with respect to
|
||||||
|
// how the grtt estimate is descreasing ... this is most notable at
|
||||||
|
// startup and thus the hack here to allow the grtt estimate to more
|
||||||
|
// rapidly decrease during "slow start"
|
||||||
|
double ageMax = grtt_advertised;
|
||||||
|
if (!cc_enable && !cc_slow_start)
|
||||||
|
ageMax = ageMax > grtt_interval_min ? ageMax : grtt_interval_min;
|
||||||
|
if (grtt_age >= ageMax)
|
||||||
{
|
{
|
||||||
if (grtt_response)
|
if (grtt_response)
|
||||||
{
|
{
|
||||||
|
|
@ -2844,16 +2998,18 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
grtt_measured = NORM_GRTT_MIN;
|
grtt_measured = NORM_GRTT_MIN;
|
||||||
else if (grtt_measured > grtt_max)
|
else if (grtt_measured > grtt_max)
|
||||||
grtt_measured = grtt_max;
|
grtt_measured = grtt_max;
|
||||||
|
UINT8 grttQuantizedOld = grtt_quantized;
|
||||||
double pktInterval = (double)(44+segment_size)/tx_rate;
|
double pktInterval = (double)(44+segment_size)/tx_rate;
|
||||||
grtt_advertised = MAX(pktInterval, grtt_measured);
|
if (grtt_measured < pktInterval)
|
||||||
double grttQuantizedOld = grtt_quantized;
|
grtt_quantized = NormQuantizeRtt(pktInterval);
|
||||||
grtt_quantized = NormQuantizeRtt(grtt_advertised);
|
else
|
||||||
|
grtt_quantized = NormQuantizeRtt(grtt_measured);
|
||||||
// Recalculate grtt_advertise since quantization rounds upward
|
// Recalculate grtt_advertise since quantization rounds upward
|
||||||
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||||
grtt_response = false;
|
|
||||||
if (grttQuantizedOld != grtt_quantized)
|
if (grttQuantizedOld != grtt_quantized)
|
||||||
DMSG(4, "NormSession::OnProbeTimeout() node>%lu new grtt: %lf\n",
|
DMSG(4, "NormSession::OnProbeTimeout() node>%lu decreased to new grtt to: %lf sec\n",
|
||||||
LocalNodeId(), grtt_advertised);
|
LocalNodeId(), grtt_advertised);
|
||||||
|
grtt_response = false; // reset
|
||||||
}
|
}
|
||||||
grtt_age = 0.0;
|
grtt_age = 0.0;
|
||||||
}
|
}
|
||||||
|
|
@ -2876,10 +3032,9 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
cmd->Init();
|
cmd->Init();
|
||||||
cmd->SetDestination(address);
|
cmd->SetDestination(address);
|
||||||
cmd->SetGrtt(grtt_quantized);
|
cmd->SetGrtt(grtt_quantized);
|
||||||
|
|
||||||
cmd->SetBackoffFactor((unsigned char)backoff_factor);
|
cmd->SetBackoffFactor((unsigned char)backoff_factor);
|
||||||
cmd->SetGroupSize(gsize_quantized);
|
cmd->SetGroupSize(gsize_quantized);
|
||||||
// SetSendTime() when message is being sent (in OnTxTimeout())
|
// defer SetSendTime() to when message is being sent (in OnTxTimeout())
|
||||||
cmd->SetCCSequence(cc_sequence++);
|
cmd->SetCCSequence(cc_sequence++);
|
||||||
|
|
||||||
if (probe_proactive)
|
if (probe_proactive)
|
||||||
|
|
@ -2900,7 +3055,10 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
if (next->IsActive())
|
if (next->IsActive())
|
||||||
{
|
{
|
||||||
UINT8 ccFlags = 0;
|
UINT8 ccFlags = 0;
|
||||||
if (next->IsClr()) ccFlags |= (UINT8)NormCC::CLR;
|
if (next->IsClr())
|
||||||
|
ccFlags |= (UINT8)NormCC::CLR;
|
||||||
|
else if (next->IsPlr())
|
||||||
|
ccFlags |= (UINT8)NormCC::PLR;
|
||||||
ccFlags |= (UINT8)NormCC::RTT;
|
ccFlags |= (UINT8)NormCC::RTT;
|
||||||
UINT8 rttQuantized = NormQuantizeRtt(next->GetRtt());
|
UINT8 rttQuantized = NormQuantizeRtt(next->GetRtt());
|
||||||
if (cc_slow_start) ccFlags |= (UINT8)NormCC::START;
|
if (cc_slow_start) ccFlags |= (UINT8)NormCC::START;
|
||||||
|
|
@ -2911,14 +3069,26 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
ccFlags,
|
ccFlags,
|
||||||
rttQuantized,
|
rttQuantized,
|
||||||
rateQuantized);
|
rateQuantized);
|
||||||
if (!next->IsClr()) next->SetActive(false);
|
//if (!next->IsClr()) next->SetActive(false);
|
||||||
|
// Deactivate any nodes who have stopped providing feedback
|
||||||
|
struct timeval feedbackTime = next->GetFeedbackTime();
|
||||||
|
double feedbackAge = currentTime.tv_sec - feedbackTime.tv_sec;
|
||||||
|
if (currentTime.tv_usec > feedbackTime.tv_usec)
|
||||||
|
feedbackAge += 1.0e-06*((double)(currentTime.tv_usec - feedbackTime.tv_usec));
|
||||||
|
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
|
||||||
|
if (feedbackAge > maxFeedbackAge)
|
||||||
|
next->SetActive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AdjustRate(false);
|
AdjustRate(false);
|
||||||
|
|
||||||
// Determine next probe_interval
|
// Determine next probe_interval
|
||||||
const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head();
|
const NormCCNode* clr = static_cast<const NormCCNode*>(cc_node_list.Head());
|
||||||
probeInterval = clr ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised;
|
probeInterval = clr ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised;
|
||||||
//double nominalRate = ((double)segment_size)/((double)tx_rate);
|
//double nominalRate = ((double)segment_size)/((double)tx_rate);
|
||||||
//probeInterval = MAX(probeInterval, nominalRate);
|
//probeInterval = MAX(probeInterval, nominalRate);
|
||||||
|
|
@ -2944,7 +3114,7 @@ void NormSession::AdjustRate(bool onResponse)
|
||||||
const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head();
|
const NormCCNode* clr = (const NormCCNode*)cc_node_list.Head();
|
||||||
double ccRtt = clr ? clr->GetRtt() : grtt_measured;
|
double ccRtt = clr ? clr->GetRtt() : grtt_measured;
|
||||||
double ccLoss = clr ? clr->GetLoss() : 0.0;
|
double ccLoss = clr ? clr->GetLoss() : 0.0;
|
||||||
double oldRate = tx_rate;
|
double txRate = tx_rate;
|
||||||
if (onResponse)
|
if (onResponse)
|
||||||
{
|
{
|
||||||
// Adjust rate based on CLR feedback and
|
// Adjust rate based on CLR feedback and
|
||||||
|
|
@ -2953,28 +3123,28 @@ void NormSession::AdjustRate(bool onResponse)
|
||||||
// (TBD) check feedback age
|
// (TBD) check feedback age
|
||||||
if (cc_slow_start)
|
if (cc_slow_start)
|
||||||
{
|
{
|
||||||
tx_rate = clr->GetRate();
|
txRate = clr->GetRate();
|
||||||
DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
|
DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
|
||||||
clr->GetId(), tx_rate*8.0/1000.0, oldRate*8.0/1000.0, sent_rate*8.0/1000.0,
|
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);
|
clr->GetRate()*8.0/1000.0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double clrRate = clr->GetRate();
|
double clrRate = clr->GetRate();
|
||||||
if (clrRate > tx_rate)
|
if (clrRate > txRate)
|
||||||
{
|
{
|
||||||
double linRate = tx_rate + segment_size;
|
double linRate = txRate + segment_size;
|
||||||
tx_rate = MIN(clrRate, linRate);
|
txRate = MIN(clrRate, linRate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tx_rate = clrRate;
|
txRate = clrRate;
|
||||||
}
|
}
|
||||||
DMSG(6, "NormSession::AdjustRate(stdy state) clr>%lu newRate>%lf (rtt>%lf loss>%lf)\n",
|
DMSG(6, "NormSession::AdjustRate(stdy state) clr>%lu newRate>%lf (rtt>%lf loss>%lf)\n",
|
||||||
clr->GetId(), tx_rate*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
|
clr->GetId(), txRate*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (clr)
|
else if (clr && clr->IsActive())
|
||||||
{
|
{
|
||||||
// (TBD) fix CC feedback aging ...
|
// (TBD) fix CC feedback aging ...
|
||||||
/*int feedbackAge = abs((int)cc_sequence - (int)clr->GetCCSequence());
|
/*int feedbackAge = abs((int)cc_sequence - (int)clr->GetCCSequence());
|
||||||
|
|
@ -2983,33 +3153,38 @@ void NormSession::AdjustRate(bool onResponse)
|
||||||
|
|
||||||
if (feedbackAge > 50)
|
if (feedbackAge > 50)
|
||||||
{
|
{
|
||||||
double linRate = tx_rate - segment_size;
|
double linRate = txRate - segment_size;
|
||||||
linRate = MAX(linRate, 0.0);
|
linRate = MAX(linRate, 0.0);
|
||||||
double expRate = tx_rate * 0.5;
|
double expRate = txRate * 0.5;
|
||||||
if (feedbackAge > 4)
|
if (feedbackAge > 4)
|
||||||
tx_rate = MIN(linRate, expRate);
|
txRate = MIN(linRate, expRate);
|
||||||
else
|
else
|
||||||
tx_rate = MAX(linRate, expRate);
|
txRate = MAX(linRate, expRate);
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// reduce rate if no active clr
|
||||||
|
txRate *= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't let tx_rate below MIN(one segment per grtt, one segment per second)
|
// Don't let txRate below MIN(one segment per grtt, one segment per 4 seconds)
|
||||||
double minRate = ((double)segment_size) / grtt_measured;
|
double minRate = ((double)segment_size) / grtt_measured;
|
||||||
minRate = MIN((double)segment_size, minRate);
|
if (minRate > ((double)(segment_size >> 2)))
|
||||||
tx_rate = MAX(tx_rate, minRate);
|
minRate = (double)(segment_size >> 2);
|
||||||
|
if (txRate < minRate)
|
||||||
|
txRate = minRate;
|
||||||
|
|
||||||
// Keep "tx_rate" within user set rate bounds (if any)
|
// Keep "tx_rate" within user set rate bounds (if any)
|
||||||
if ((tx_rate_min >= 0.0) && (tx_rate < tx_rate_min))
|
if ((tx_rate_min >= 0.0) && (txRate < tx_rate_min))
|
||||||
tx_rate = tx_rate_min;
|
txRate = tx_rate_min;
|
||||||
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
|
if ((tx_rate_max >= 0.0) && (txRate > tx_rate_max))
|
||||||
tx_rate = tx_rate_max;
|
txRate = tx_rate_max;
|
||||||
|
|
||||||
struct timeval currentTime;
|
if (txRate != tx_rate) SetTxRateInternal(txRate);
|
||||||
::ProtoSystemTime(currentTime);
|
|
||||||
double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec);
|
/*if (txRate != oldRate)
|
||||||
|
|
||||||
if (tx_rate != oldRate)
|
|
||||||
{
|
{
|
||||||
if (tx_timer.IsActive())
|
if (tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
|
|
@ -3020,8 +3195,10 @@ void NormSession::AdjustRate(bool onResponse)
|
||||||
tx_timer.SetInterval(txInterval);
|
tx_timer.SetInterval(txInterval);
|
||||||
tx_timer.Reschedule();
|
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, tx_rate*(8.0/1000.0), ccRtt, ccLoss);
|
||||||
} // end NormSession::AdjustRate()
|
} // end NormSession::AdjustRate()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
class NormController
|
class NormController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~NormController() {}
|
||||||
enum Event
|
enum Event
|
||||||
{
|
{
|
||||||
EVENT_INVALID = 0,
|
EVENT_INVALID = 0,
|
||||||
|
|
@ -96,6 +97,7 @@ class NormSession
|
||||||
static const double DEFAULT_GSIZE_ESTIMATE;
|
static const double DEFAULT_GSIZE_ESTIMATE;
|
||||||
static const UINT16 DEFAULT_NDATA;
|
static const UINT16 DEFAULT_NDATA;
|
||||||
static const UINT16 DEFAULT_NPARITY;
|
static const UINT16 DEFAULT_NPARITY;
|
||||||
|
enum ProbingMode {PROBE_NONE, PROBE_PASSIVE, PROBE_ACTIVE};
|
||||||
|
|
||||||
// General methods
|
// General methods
|
||||||
const NormNodeId& LocalNodeId() const {return local_node_id;}
|
const NormNodeId& LocalNodeId() const {return local_node_id;}
|
||||||
|
|
@ -118,6 +120,7 @@ class NormSession
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
void SetTxPort(UINT16 txPort) {tx_port = txPort;}
|
void SetTxPort(UINT16 txPort) {tx_port = txPort;}
|
||||||
|
void SetRxPortReuse(bool state) {rx_port_reuse = state;}
|
||||||
static double CalculateRate(double size, double rtt, double loss);
|
static double CalculateRate(double size, double rtt, double loss);
|
||||||
|
|
||||||
NormSessionMgr& GetSessionMgr() {return session_mgr;}
|
NormSessionMgr& GetSessionMgr() {return session_mgr;}
|
||||||
|
|
@ -130,11 +133,23 @@ class NormSession
|
||||||
// Session parameters
|
// Session parameters
|
||||||
double TxRate() {return (tx_rate * 8.0);}
|
double TxRate() {return (tx_rate * 8.0);}
|
||||||
// (TBD) watch timer scheduling and min/max bounds
|
// (TBD) watch timer scheduling and min/max bounds
|
||||||
void SetTxRate(double txRate);
|
void SetTxRate(double txRate)
|
||||||
|
{
|
||||||
|
txRate /= 8.0; // convert to bytes/sec
|
||||||
|
SetTxRateInternal(txRate);
|
||||||
|
}
|
||||||
double BackoffFactor() {return backoff_factor;}
|
double BackoffFactor() {return backoff_factor;}
|
||||||
void SetBackoffFactor(double value) {backoff_factor = value;}
|
void SetBackoffFactor(double value) {backoff_factor = value;}
|
||||||
bool CongestionControl() {return cc_enable;}
|
bool CongestionControl() {return cc_enable;}
|
||||||
void SetCongestionControl(bool state) {cc_enable = state;}
|
void SetCongestionControl(bool state)
|
||||||
|
{
|
||||||
|
cc_enable = state;
|
||||||
|
}
|
||||||
|
// GRTT measurement management
|
||||||
|
void SetGrttProbingMode(ProbingMode probingMode);
|
||||||
|
void SetGrttProbingInterval(double intervalMin, double intervalMax);
|
||||||
|
void SetGrttMax(double grttMax) {grtt_max = grttMax;}
|
||||||
|
|
||||||
void SetTxRateBounds(double rateMin, double rateMax);
|
void SetTxRateBounds(double rateMin, double rateMax);
|
||||||
void SetTxCacheBounds(NormObjectSize sizeMax,
|
void SetTxCacheBounds(NormObjectSize sizeMax,
|
||||||
unsigned long countMin,
|
unsigned long countMin,
|
||||||
|
|
@ -321,13 +336,15 @@ class NormSession
|
||||||
void ServerUpdateGrttEstimate(double clientRtt);
|
void ServerUpdateGrttEstimate(double clientRtt);
|
||||||
double CalculateRtt(const struct timeval& currentTime,
|
double CalculateRtt(const struct timeval& currentTime,
|
||||||
const struct timeval& grttResponse);
|
const struct timeval& grttResponse);
|
||||||
void ServerHandleCCFeedback(NormNodeId nodeId,
|
void ServerHandleCCFeedback(struct timeval currentTime,
|
||||||
UINT8 ccFlags,
|
NormNodeId nodeId,
|
||||||
double ccRtt,
|
UINT8 ccFlags,
|
||||||
double ccLoss,
|
double ccRtt,
|
||||||
double ccRate,
|
double ccLoss,
|
||||||
UINT16 ccSequence);
|
double ccRate,
|
||||||
|
UINT16 ccSequence);
|
||||||
void AdjustRate(bool onResponse);
|
void AdjustRate(bool onResponse);
|
||||||
|
void SetTxRateInternal(double txRate); // here, txRate is bytes/sec
|
||||||
bool ServerQueueSquelch(NormObjectId objectId);
|
bool ServerQueueSquelch(NormObjectId objectId);
|
||||||
void ServerQueueFlush();
|
void ServerQueueFlush();
|
||||||
bool ServerQueueWatermarkFlush();
|
bool ServerQueueWatermarkFlush();
|
||||||
|
|
@ -359,6 +376,7 @@ class NormSession
|
||||||
ProtoAddress address; // session destination address & port
|
ProtoAddress address; // session destination address & port
|
||||||
UINT8 ttl; // session multicast ttl
|
UINT8 ttl; // session multicast ttl
|
||||||
bool loopback; // to receive own traffic
|
bool loopback; // to receive own traffic
|
||||||
|
bool rx_port_reuse; // enable port reuse
|
||||||
char interface_name[32];
|
char interface_name[32];
|
||||||
double tx_rate; // bytes per second
|
double tx_rate; // bytes per second
|
||||||
double tx_rate_min;
|
double tx_rate_min;
|
||||||
|
|
@ -409,6 +427,7 @@ class NormSession
|
||||||
bool probe_proactive;
|
bool probe_proactive;
|
||||||
bool probe_pending; // true while CMD(CC) enqueued
|
bool probe_pending; // true while CMD(CC) enqueued
|
||||||
bool probe_reset;
|
bool probe_reset;
|
||||||
|
struct timeval probe_time_last;
|
||||||
|
|
||||||
double grtt_interval; // current GRTT update interval
|
double grtt_interval; // current GRTT update interval
|
||||||
double grtt_interval_min; // minimum GRTT update interval
|
double grtt_interval_min; // minimum GRTT update interval
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,10 @@
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
#include <unistd.h> // for "sleep()"
|
#include <unistd.h> // for "sleep()"
|
||||||
#endif // UNIX
|
#endif // UNIX
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
printf("normTest starting (sizeof(NormSize) = %d)...\n", sizeof(NormSize));
|
printf("normTest starting (sizeof(NormSize) = %d)...\n", (int)sizeof(NormSize));
|
||||||
|
|
||||||
NormInstanceHandle instance = NormCreateInstance();
|
NormInstanceHandle instance = NormCreateInstance();
|
||||||
|
|
||||||
|
|
@ -26,27 +27,62 @@ int main(int argc, char* argv[])
|
||||||
#endif // if/else WIN32/UNIX
|
#endif // if/else WIN32/UNIX
|
||||||
|
|
||||||
NormSetCacheDirectory(instance, cachePath);
|
NormSetCacheDirectory(instance, cachePath);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Here's a trick to generate a _hopefully_ unique NormNodeId
|
||||||
|
// based on an XOR of the system's IP address and the process id.
|
||||||
|
// (We use ProtoAddress::GetEndIdentifier() to get the local
|
||||||
|
// "default" IP address for the system)
|
||||||
|
// (Note that passing "NORM_NODE_ANY" to the last arg of
|
||||||
|
// NormCreateSession() does a similar thing but without
|
||||||
|
// the process id ... perhaps we should add the process id
|
||||||
|
// hack to that default NormNodeId picker?
|
||||||
|
ProtoAddress localAddr;
|
||||||
|
if (!localAddr.ResolveLocalAddress())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "normTest: error resolving local IP address\n");
|
||||||
|
NormDestroyInstance(instance);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
NormNodeId localId = localAddr.EndIdentifier();
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD processId = GetCurrentProcessId();
|
||||||
|
#else
|
||||||
|
pid_t processId = getpid();
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
|
localId ^= (NormNodeId)processId;
|
||||||
|
|
||||||
|
// If needed, permutate to a valid, random NormNodeId
|
||||||
|
while ((NORM_NODE_ANY == localId) ||
|
||||||
|
(NORM_NODE_NONE == localId))
|
||||||
|
{
|
||||||
|
localId ^= (NormNodeId)rand();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NormSessionHandle session = NormCreateSession(instance,
|
NormSessionHandle session = NormCreateSession(instance,
|
||||||
"224.1.2.3",
|
"224.1.2.3",
|
||||||
6003,
|
6003,
|
||||||
NORM_NODE_ANY);
|
localId);
|
||||||
|
|
||||||
// NOTE: These are debugging routines available (not for normal app use)
|
// NOTE: These are debugging routines available (not for normal app use)
|
||||||
SetDebugLevel(2);
|
SetDebugLevel(2);
|
||||||
// Uncomment to turn on debug NORM message tracing
|
// Uncomment to turn on debug NORM message tracing
|
||||||
//NormSetMessageTrace(session, true);
|
//NormSetMessageTrace(session, true);
|
||||||
// Uncomment to turn on some random packet loss
|
// Uncomment to turn on some random packet loss
|
||||||
NormSetTxLoss(session, 10.0); // 10% packet loss
|
//NormSetTxLoss(session, 10.0); // 10% packet loss
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
ProtoSystemTime(currentTime);
|
ProtoSystemTime(currentTime);
|
||||||
// Uncomment to get different packet loss patterns from run to run
|
// Uncomment to get different packet loss patterns from run to run
|
||||||
// (and a different sender sessionId)
|
// (and a different sender sessionId)
|
||||||
srand(currentTime.tv_sec); // seed random number generator
|
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, 60.0e+03); // in bits/second
|
NormSetTransmitRate(session, 6000.0e+03); // in bits/second
|
||||||
|
|
||||||
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
||||||
|
|
||||||
|
|
@ -56,25 +92,32 @@ int main(int argc, char* argv[])
|
||||||
// possible!
|
// possible!
|
||||||
//NormSetTxPort(session, 6001);
|
//NormSetTxPort(session, 6001);
|
||||||
|
|
||||||
|
|
||||||
|
// Uncomment to allow reuse of rx port
|
||||||
|
// (This allows multiple "normTest" instances on the same machine
|
||||||
|
// for the same NormSession - note those instances must use
|
||||||
|
// unique local NormNodeIds (see NormCreateSession() above).
|
||||||
|
NormSetRxPortReuse(session, true);
|
||||||
|
|
||||||
// Uncomment to receive your own traffic
|
// Uncomment to receive your own traffic
|
||||||
NormSetLoopback(session, true);
|
NormSetLoopback(session, true);
|
||||||
|
|
||||||
// Uncomment this line to participate as a receiver
|
// Uncomment this line to participate as a receiver
|
||||||
NormStartReceiver(session, 1024*1024);
|
//NormStartReceiver(session, 1024*1024);
|
||||||
|
|
||||||
// Uncomment to set large rx socket buffer size
|
// Uncomment to set large rx socket buffer size
|
||||||
// (might be needed for high rate sessions)
|
// (might be needed for high rate sessions)
|
||||||
// NormSetRxSocketBuffer(session, 512000);
|
NormSetRxSocketBuffer(session, 512000);
|
||||||
|
|
||||||
// Uncomment to enable TCP-friendly congestion control
|
// Uncomment to enable TCP-friendly congestion control
|
||||||
//NormSetCongestionControl(session, true);
|
NormSetCongestionControl(session, true);
|
||||||
|
|
||||||
// We use a random "sessionId"
|
// We use a random "sessionId"
|
||||||
NormSessionId sessionId = (NormSessionId)rand();
|
NormSessionId sessionId = (NormSessionId)rand();
|
||||||
|
|
||||||
|
|
||||||
// Uncomment the following line to start sender
|
// Uncomment the following line to start sender
|
||||||
NormStartSender(session, sessionId, 4096*1024, 1400, 64, 0);
|
NormStartSender(session, sessionId, 1024*1024, 1420, 64, 0);
|
||||||
|
|
||||||
// Uncomment to set large tx socket buffer size
|
// Uncomment to set large tx socket buffer size
|
||||||
// (might be needed for high rate sessions)
|
// (might be needed for high rate sessions)
|
||||||
|
|
@ -87,7 +130,7 @@ int main(int argc, char* argv[])
|
||||||
const char* fileName = "ferrari.jpg";
|
const char* fileName = "ferrari.jpg";
|
||||||
|
|
||||||
// Uncomment this line to send a stream instead of the file
|
// Uncomment this line to send a stream instead of the file
|
||||||
//stream = NormStreamOpen(session, 4096*1024);
|
stream = NormStreamOpen(session, 10*1024*1024);
|
||||||
|
|
||||||
// NORM_FLUSH_PASSIVE automatically flushes full writes to
|
// NORM_FLUSH_PASSIVE automatically flushes full writes to
|
||||||
// the stream.
|
// the stream.
|
||||||
|
|
@ -115,7 +158,7 @@ int main(int argc, char* argv[])
|
||||||
// TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
// TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
||||||
case NORM_TX_QUEUE_EMPTY:
|
case NORM_TX_QUEUE_EMPTY:
|
||||||
//TRACE("NORM_TX_QUEUE_EMPTY ...\n");
|
//TRACE("NORM_TX_QUEUE_EMPTY ...\n");
|
||||||
if (sendCount >= sendMax) break;
|
//if (sendCount >= sendMax) break;
|
||||||
if (NORM_OBJECT_INVALID != stream)
|
if (NORM_OBJECT_INVALID != stream)
|
||||||
{
|
{
|
||||||
// We loop here to keep stream buffer full ....
|
// We loop here to keep stream buffer full ....
|
||||||
|
|
@ -150,7 +193,7 @@ int main(int argc, char* argv[])
|
||||||
// after "sendMax" messages
|
// after "sendMax" messages
|
||||||
//NormStreamClose(stream, true);
|
//NormStreamClose(stream, true);
|
||||||
//keepWriting = false;
|
//keepWriting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -251,6 +294,8 @@ int main(int argc, char* argv[])
|
||||||
// TRACE("validated recv msg len:%d\n", len);
|
// TRACE("validated recv msg len:%d\n", len);
|
||||||
}
|
}
|
||||||
recvCount = value;
|
recvCount = value;
|
||||||
|
//if (0 == msgCount % 100)
|
||||||
|
// TRACE("recv stream msg count: %d\n", msgCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,6 @@
|
||||||
|
|
||||||
#ifndef _NORM_VERSION
|
#ifndef _NORM_VERSION
|
||||||
#define _NORM_VERSION
|
#define _NORM_VERSION
|
||||||
#define VERSION "1.3b4"
|
#define VERSION "1.3b5"
|
||||||
#endif // _NORM_VERSION
|
#endif // _NORM_VERSION
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ NS = ../ns
|
||||||
|
|
||||||
INCLUDES = $(SYSTEM_INCLUDES) -I$(UNIX) -I$(COMMON) -I$(PROTOLIB)/common
|
INCLUDES = $(SYSTEM_INCLUDES) -I$(UNIX) -I$(COMMON) -I$(PROTOLIB)/common
|
||||||
|
|
||||||
CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 -O -fPIC -Wall -pedantic -Wcast-align $(SYSTEM_HAVES) $(INCLUDES)
|
CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 -O $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES)
|
||||||
|
|
||||||
LDFLAGS = $(SYSTEM_LDFLAGS)
|
LDFLAGS = $(SYSTEM_LDFLAGS)
|
||||||
|
|
||||||
|
|
@ -44,12 +44,14 @@ NORM_OBJ = $(NORM_SRC:.cpp=.o)
|
||||||
LIB_SRC = $(NORM_SRC)
|
LIB_SRC = $(NORM_SRC)
|
||||||
LIB_OBJ = $(LIB_SRC:.cpp=.o)
|
LIB_OBJ = $(LIB_SRC:.cpp=.o)
|
||||||
|
|
||||||
|
# NORM as a static library
|
||||||
libnorm.a: $(LIB_OBJ)
|
libnorm.a: $(LIB_OBJ)
|
||||||
$(AR) rcv $@ $(LIB_OBJ)
|
$(AR) rcv $@ $(LIB_OBJ)
|
||||||
$(RANLIB) $@
|
$(RANLIB) $@
|
||||||
|
|
||||||
.cpp-sim.o:
|
# NORM as a shared library
|
||||||
$(CC) -c $(CFLAGS) -DSIMULATE -o $*-sim.o $*.cpp
|
libnorm.so: $(LIB_OBJ)
|
||||||
|
$(CC) $(SYSTEM_SOFLAGS) $(LIB_OBJ) $(LIBS) -o $@
|
||||||
|
|
||||||
SIM_SRC = $(NORM_SRC) $(COMMON)/normSimAgent.cpp
|
SIM_SRC = $(NORM_SRC) $(COMMON)/normSimAgent.cpp
|
||||||
SIM_OBJ = $(SIM_SRC:.cpp=-sim.o)
|
SIM_OBJ = $(SIM_SRC:.cpp=-sim.o)
|
||||||
|
|
@ -82,7 +84,8 @@ raft: $(RAFT_OBJ) $(LIBPROTO)
|
||||||
$(CC) $(CFLAGS) -o $@ $(RAFT_OBJ) $(LDFLAGS) $(LIBPROTO) $(LIBS)
|
$(CC) $(CFLAGS) -o $@ $(RAFT_OBJ) $(LDFLAGS) $(LIBPROTO) $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(COMMON)/*.o $(UNIX)/*.o $(UNIX)/libnorm.a $(UNIX)/norm $(NS)/*.o;
|
rm -f $(COMMON)/*.o $(UNIX)/*.o $(UNIX)/libnorm.a \
|
||||||
|
$(UNIX)/libnorm.so $(UNIX)/norm $(NS)/*.o;
|
||||||
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) clean
|
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) clean
|
||||||
|
|
||||||
# DO NOT DELETE THIS LINE -- mkdep uses it.
|
# DO NOT DELETE THIS LINE -- mkdep uses it.
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,6 @@ SYSTEM_LIBS =
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The PROTOLIB code's use of offset pointers requires special treatment
|
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
|
||||||
#
|
|
||||||
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
|
|
@ -41,10 +37,12 @@ SYSTEM_LIBS =
|
||||||
|
|
||||||
SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC)
|
SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC)
|
||||||
|
|
||||||
SYSTEM_SRC = bsdRouteMgr.cpp
|
SYSTEM_SRC =
|
||||||
|
|
||||||
SYSTEM = freebsd
|
SYSTEM = freebsd
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
|
||||||
|
SYSTEM_SOFLAGS = -shared
|
||||||
RANLIB = ranlib
|
RANLIB = ranlib
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,13 @@
|
||||||
#
|
#
|
||||||
# HPUX Protean Makefile definitions
|
# HPUX Protean Makefile definitions
|
||||||
#
|
# (This file is likely out of date)
|
||||||
|
|
||||||
# TO BUILD THE TK GUI VERSION OF MDP EDIT THE FOLLOWING NUMBERED
|
|
||||||
# ITEMS AS NEEDED FOR YOUR SYSTEM
|
|
||||||
# (This has only been tested with TCL/TK 8.0 but it probably
|
|
||||||
# will work with Tcl7.x/Tk4.x with a little tweaking to
|
|
||||||
# the list of TCL_SCRIPTS (library scripts) given below)
|
|
||||||
|
|
||||||
# 1) Where to find the Tcl standard library scripts
|
# System specific additional libraries, include paths, etc
|
||||||
# (e.g. init.tcl, ...)
|
|
||||||
TCL_SCRIPT_PATH = /opt/tcl-8.0/lib
|
|
||||||
|
|
||||||
# 2) Where to find the Tk standard library scripts
|
|
||||||
# (e.g. button.tcl, entry.tcl, ...)
|
|
||||||
TK_SCRIPT_PATH = /opt/tk-8.0/lib/X11
|
|
||||||
|
|
||||||
# 3) Where to find Tcl/Tk header files
|
|
||||||
# (e.g. tcl.h, tk.h, ...)
|
|
||||||
TCL_INCL_PATH = -I/opt/tcl-8.0/include -I/opt/tk-8.0/include/X11
|
|
||||||
|
|
||||||
# 4) Point to specific libtcl.a and libtk.a to use
|
|
||||||
TCL_LIB = ./hpux-libtcl8.0.a
|
|
||||||
TK_LIB = ./hpux-libtk8.0.a
|
|
||||||
|
|
||||||
# 5) System specific additional libraries, include paths, etc
|
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
SYSTEM_INCLUDES =
|
SYSTEM_INCLUDES =
|
||||||
SYSTEM_LDFLAGS = -Xlinker +b -Xlinker /usr/lib/X11R5:/usr/lib/X11R6:/usr/local/X11R5/lib:/usr/local/X11R6/lib:/usr/lib:/usr/lib/X11R4\
|
SYSTEM_LDFLAGS =
|
||||||
-Xlinker +s -L/home/macker/mdp/X11R5/lib
|
|
||||||
SYTSTEM_LIBS =
|
SYTSTEM_LIBS =
|
||||||
|
|
||||||
# 6) System specific capabilities
|
# 6) System specific capabilities
|
||||||
|
|
@ -48,10 +26,6 @@ SYTSTEM_LIBS =
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The MDP code's use of offset pointers requires special treatment
|
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
|
||||||
#
|
|
||||||
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
|
|
@ -62,10 +36,12 @@ SYTSTEM_LIBS =
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
export SYSTEM_HAVES = -DHAVE_CUSERID -DHAVE_LOCKF
|
SYSTEM_HAVES = -DHAVE_CUSERID -DHAVE_LOCKF
|
||||||
|
|
||||||
export CC = gcc
|
CC = gcc
|
||||||
export RANLIB = touch
|
SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
|
||||||
export AR = ar
|
SYSTEM_SOFLAGS = -shared
|
||||||
|
RANLIB = touch
|
||||||
|
AR = ar
|
||||||
|
|
||||||
include Makefile.common
|
include Makefile.common
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,7 @@
|
||||||
#
|
#
|
||||||
# Linux Protean Makefile definitions
|
# Linux NORM Makefile definitions
|
||||||
#
|
#
|
||||||
|
|
||||||
# TO BUILD THE TK GUI VERSION OF MDP EDIT THE FOLLOWING NUMBERED
|
|
||||||
# ITEMS AS NEEDED FOR YOUR SYSTEM
|
|
||||||
# (This has only been tested with TCL/TK 8.0 but it probably
|
|
||||||
# will work with Tcl7.x/Tk4.x with a little tweaking to
|
|
||||||
# the list of TCL_SCRIPTS (library scripts) given below)
|
|
||||||
|
|
||||||
# 1) Where to find the Tcl standard library scripts
|
|
||||||
# (e.g. init.tcl, ...)
|
|
||||||
TCL_SCRIPT_PATH = /usr/lib/tcl
|
|
||||||
|
|
||||||
# 2) Where to find the Tk standard library scripts
|
|
||||||
# (e.g. button.tcl, entry.tcl, ...)
|
|
||||||
TK_SCRIPT_PATH = /usr/lib/tk
|
|
||||||
|
|
||||||
# 3) Where to find Tcl/Tk header files
|
|
||||||
# (e.g. tcl.h, tk.h, ...)
|
|
||||||
TCL_INCL_PATH = -I/usr/local/include
|
|
||||||
|
|
||||||
# 4) Point to specific libtcl.a and libtk.a to use
|
|
||||||
TCL_LIB = -ltcl #/usr/local/lib/libtcl8.0.a
|
|
||||||
TK_LIB = -ltk #/usr/local/lib/libtk8.0.a
|
|
||||||
|
|
||||||
|
|
||||||
# 5) System specific additional libraries, include paths, etc
|
# 5) System specific additional libraries, include paths, etc
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
|
|
@ -48,10 +25,6 @@ SYSTEM_LIBS = -ldl
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The MDP code's use of offset pointers requires special treatment
|
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
|
||||||
#
|
|
||||||
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
|
|
@ -70,6 +43,8 @@ SYSTEM_SRC =
|
||||||
SYSTEM = linux
|
SYSTEM = linux
|
||||||
|
|
||||||
export CC = g++
|
export CC = g++
|
||||||
|
export SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
|
||||||
|
export SYSTEM_SOFLAGS = -shared
|
||||||
export RANLIB = ranlib
|
export RANLIB = ranlib
|
||||||
export AR = ar
|
export AR = ar
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,14 +37,16 @@ SYSTEM_LIBS = -lresolv
|
||||||
#
|
#
|
||||||
|
|
||||||
SYSTEM_HAVES = -DMACOSX -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK \
|
SYSTEM_HAVES = -DMACOSX -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK \
|
||||||
-D_FILE_OFFSET_BITS=64 -DHAVE_DIRFD -DSOCKLEN_T=int
|
-D_FILE_OFFSET_BITS=64 -DHAVE_DIRFD
|
||||||
|
|
||||||
SYSTEM_SRC = bsdRouteMgr.cpp
|
SYSTEM_SRC =
|
||||||
|
|
||||||
# The "SYSTEM" keyword can be used for dependent makes
|
# The "SYSTEM" keyword can be used for dependent makes
|
||||||
SYSTEM = macosx
|
SYSTEM = macosx
|
||||||
|
|
||||||
CC = g++
|
CC = g++
|
||||||
|
SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
|
||||||
|
SYSTEM_SOFLAGS = -shared
|
||||||
RANLIB = ranlib
|
RANLIB = ranlib
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,7 @@
|
||||||
#
|
#
|
||||||
# MDPv2 NetBSD Makefile
|
# NORM mklinux Makefile
|
||||||
#
|
#
|
||||||
|
|
||||||
# TO BUILD THE TK GUI VERSION OF MDP EDIT THE FOLLOWING NUMBERED
|
|
||||||
# ITEMS AS NEEDED FOR YOUR SYSTEM
|
|
||||||
# (This has only been tested with TCL/TK 8.0 but it probably
|
|
||||||
# will work with Tcl7.x/Tk4.x with a little tweaking to
|
|
||||||
# the list of TCL_SCRIPTS (library scripts) given below)
|
|
||||||
|
|
||||||
# 1) Where to find the Tcl standard library scripts
|
|
||||||
# (e.g. init.tcl, ...)
|
|
||||||
TCL_SCRIPT_PATH = /usr/local/lib/tcl8.0
|
|
||||||
|
|
||||||
# 2) Where to find the Tk standard library scripts
|
|
||||||
# (e.g. button.tcl, entry.tcl, ...)
|
|
||||||
TK_SCRIPT_PATH = /usr/local/lib/tk8.0
|
|
||||||
|
|
||||||
# 3) Where to find Tcl/Tk header files
|
|
||||||
# (e.g. tcl.h, tk.h, ...)
|
|
||||||
TCL_INCL_PATH = -I/usr/local/include
|
|
||||||
|
|
||||||
# 4) Point to specific libtcl.a and libtk.a to use
|
|
||||||
TCL_LIB = /usr/local/lib/libtcl8.0.a
|
|
||||||
TK_LIB = /usr/local/lib/libtk8.0.a
|
|
||||||
|
|
||||||
|
|
||||||
# 5) System specific additional libraries, include paths, etc
|
# 5) System specific additional libraries, include paths, etc
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
|
|
@ -49,10 +27,6 @@ SYSTEM_LIBS = -ldl
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The MDP code's use of offset pointers requires special treatment
|
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
|
||||||
#
|
|
||||||
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
|
|
@ -66,6 +40,8 @@ SYSTEM_LIBS = -ldl
|
||||||
export SYSTEM_HAVES = -DHAVE_CUSERID -DHAVE_LOCKF -DHAVE_DIRFD $(NETSEC)
|
export SYSTEM_HAVES = -DHAVE_CUSERID -DHAVE_LOCKF -DHAVE_DIRFD $(NETSEC)
|
||||||
|
|
||||||
export CC = gcc
|
export CC = gcc
|
||||||
|
export SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
|
||||||
|
export SYSTEM_SOFLAGS = -shared
|
||||||
export RANLIB = ranlib
|
export RANLIB = ranlib
|
||||||
export AR = ar
|
export AR = ar
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,7 @@
|
||||||
#
|
#
|
||||||
# MDPv2 NetBSD Makefile
|
# NORM NetBSD Makefile
|
||||||
#
|
#
|
||||||
|
|
||||||
# TO BUILD THE TK GUI VERSION OF MDP EDIT THE FOLLOWING NUMBERED
|
|
||||||
# ITEMS AS NEEDED FOR YOUR SYSTEM
|
|
||||||
# (This has only been tested with TCL/TK 8.0 but it probably
|
|
||||||
# will work with Tcl7.x/Tk4.x with a little tweaking to
|
|
||||||
# the list of TCL_SCRIPTS (library scripts) given below)
|
|
||||||
|
|
||||||
# 1) Where to find the Tcl standard library scripts
|
|
||||||
# (e.g. init.tcl, ...)
|
|
||||||
TCL_SCRIPT_PATH = /usr/local/lib/tcl8.0
|
|
||||||
|
|
||||||
# 2) Where to find the Tk standard library scripts
|
|
||||||
# (e.g. button.tcl, entry.tcl, ...)
|
|
||||||
TK_SCRIPT_PATH = /usr/local/lib/tk8.0
|
|
||||||
|
|
||||||
# 3) Where to find Tcl/Tk header files
|
|
||||||
# (e.g. tcl.h, tk.h, ...)
|
|
||||||
TCL_INCL_PATH = -I/usr/local/include
|
|
||||||
|
|
||||||
# 4) Point to specific libtcl.a and libtk.a to use
|
|
||||||
TCL_LIB = /usr/local/lib/libtcl80.a
|
|
||||||
TK_LIB = /usr/local/lib/libtk80.a
|
|
||||||
|
|
||||||
|
|
||||||
# 5) System specific additional libraries, include paths, etc
|
# 5) System specific additional libraries, include paths, etc
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
|
|
@ -48,10 +25,6 @@ SYSTEM_LIBS =
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The MDP code's use of offset pointers requires special treatment
|
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
|
||||||
#
|
|
||||||
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
|
|
@ -62,10 +35,12 @@ SYSTEM_LIBS =
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
export SYSTEM_HAVES = -DHAVE_GETLOGIN -DHAVE_ASSERT -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC)
|
SYSTEM_HAVES = -DHAVE_GETLOGIN -DHAVE_ASSERT -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC)
|
||||||
|
|
||||||
export CC = gcc
|
CC = gcc
|
||||||
export RANLIB = ranlib
|
SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
|
||||||
export AR = ar
|
SYSTEM_SOFLAGS = -shared
|
||||||
|
RANLIB = ranlib
|
||||||
|
AR = ar
|
||||||
|
|
||||||
include Makefile.common
|
include Makefile.common
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,6 @@ SYSTEM_LIBS =
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The MDP code's use of offset pointers requires special treatment
|
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
|
||||||
#
|
|
||||||
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
|
|
@ -46,7 +42,15 @@ SYSTEM_SRC =
|
||||||
|
|
||||||
SYSTEM = sgi
|
SYSTEM = sgi
|
||||||
|
|
||||||
|
# g++
|
||||||
|
#CC = g++
|
||||||
|
#SYSTEM_CFLAGS = -Wall -Wcast-align -pedantic -fPIC
|
||||||
|
|
||||||
|
# SGI CC
|
||||||
CC = CC
|
CC = CC
|
||||||
|
SYSTEM_CFLAGS = -KPIC -pedantic
|
||||||
|
|
||||||
|
SYSTEM_SOFLAGS = -shared
|
||||||
RANLIB = touch
|
RANLIB = touch
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,15 +35,16 @@ SYSTEM_LIBS = -ldl -lnsl -lsocket -lresolv
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF \
|
SYSTEM_HAVES = -DHAVE_DIRFD -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF \
|
||||||
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DSOLARIS
|
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DSOLARIS
|
||||||
|
|
||||||
SYSTEM = solaris
|
SYSTEM = solaris
|
||||||
|
|
||||||
CC = g++
|
CC = CC
|
||||||
|
# -xarch=v9 makes the output run only on 64-bit Solaris
|
||||||
|
SYSTEM_CFLAGS = -KPIC -Wall -Wcast-align
|
||||||
|
SYSTEM_SOFLAGS = -shared
|
||||||
RANLIB = touch
|
RANLIB = touch
|
||||||
|
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
include Makefile.common
|
include Makefile.common
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,16 @@ SYSTEM_LIBS = -ldl -lnsl -lsocket
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
export SYSTEM_HAVES = -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF $(NETSEC) -DSOLARIS
|
SYSTEM_HAVES = -DHAVE_DIRFD -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF \
|
||||||
|
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DSOLARIS
|
||||||
|
|
||||||
export CC = gcc
|
SYSTEM = solaris
|
||||||
export RANLIB = touch
|
|
||||||
export AR = ar
|
SYSTEM_CFLAGS = -PIC -Wall -Wcast-align
|
||||||
|
CC = gcc
|
||||||
|
SYSTEM_SOFLAGS = -shared
|
||||||
|
RANLIB = touch
|
||||||
|
AR = ar
|
||||||
|
|
||||||
include Makefile.common
|
include Makefile.common
|
||||||
|
|
||||||
|
|
|
||||||
BIN
win32/Norm.suo
BIN
win32/Norm.suo
Binary file not shown.
|
|
@ -26,6 +26,7 @@
|
||||||
PreprocessorDefinitions="_DEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CONSOLE"
|
PreprocessorDefinitions="_DEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CONSOLE"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
|
BufferSecurityCheck="TRUE"
|
||||||
UsePrecompiledHeader="2"
|
UsePrecompiledHeader="2"
|
||||||
PrecompiledHeaderFile=".\Debug/normTest.pch"
|
PrecompiledHeaderFile=".\Debug/normTest.pch"
|
||||||
AssemblerListingLocation=".\Debug/"
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
|
@ -41,7 +42,7 @@
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="iphlpapi.lib ws2_32.lib odbc32.lib odbccp32.lib"
|
AdditionalDependencies="iphlpapi.lib ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
OutputFile=".\Debug/normTest.exe"
|
OutputFile=".\Debug/normTest.exe"
|
||||||
LinkIncremental="1"
|
LinkIncremental="0"
|
||||||
SuppressStartupBanner="TRUE"
|
SuppressStartupBanner="TRUE"
|
||||||
GenerateDebugInformation="TRUE"
|
GenerateDebugInformation="TRUE"
|
||||||
ProgramDatabaseFile=".\Debug/normTest.pdb"
|
ProgramDatabaseFile=".\Debug/normTest.pdb"
|
||||||
|
|
|
||||||
BIN
wince/Norm.vco
BIN
wince/Norm.vco
Binary file not shown.
Loading…
Reference in New Issue