v1.3b3
parent
9c3ea04ba8
commit
14d4ab80c6
|
|
@ -3,10 +3,10 @@
|
||||||
<HEAD>
|
<HEAD>
|
||||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-15">
|
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-15">
|
||||||
<TITLE>NORM Developer’s Guide</TITLE>
|
<TITLE>NORM Developer’s Guide</TITLE>
|
||||||
<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.2 (Linux)">
|
<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3 (Linux)">
|
||||||
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
||||||
<META NAME="CREATED" CONTENT="20040824;15180000">
|
<META NAME="CREATED" CONTENT="20040824;15180000">
|
||||||
<META NAME="CHANGED" CONTENT="20050427;11094100">
|
<META NAME="CHANGED" CONTENT="20050609;13321500">
|
||||||
<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>
|
||||||
|
|
@ -70,7 +70,7 @@ Engineering Task Force RFC 3940.</P>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM protocol is
|
<P CLASS="western" STYLE="font-style: normal">The NORM protocol is
|
||||||
designed to provide end-to-end reliable transport of bulk data
|
designed to provide end-to-end reliable transport of bulk data
|
||||||
objects or streams over generic IP multicast routing and forwarding
|
objects or streams over generic IP multicast routing and forwarding
|
||||||
services. NORM uses a selective, negative acknowledgment (NACK)
|
services. NORM uses a selective, negative acknowledgement (NACK)
|
||||||
mechanism for transport reliability and offers additional protocol
|
mechanism for transport reliability and offers additional protocol
|
||||||
mechanisms to conduct reliable multicast sessions with limited "a
|
mechanisms to conduct reliable multicast sessions with limited "a
|
||||||
priori" coordination among senders and receivers. A congestion
|
priori" coordination among senders and receivers. A congestion
|
||||||
|
|
@ -84,6 +84,18 @@ to allow different types of applications or possibly other higher
|
||||||
level transport protocols to utilize its service in different ways.
|
level transport protocols to utilize its service in different ways.
|
||||||
The protocol leverages the use of FEC-based repair and other proven
|
The protocol leverages the use of FEC-based repair and other proven
|
||||||
reliable multicast transport techniques in its design.</P>
|
reliable multicast transport techniques in its design.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The NRL NORM library
|
||||||
|
attempts to provide a general useful capability for development of
|
||||||
|
reliable multicast applications for bulk file or other data delivery
|
||||||
|
as well as support of stream-based transport with possible real-time
|
||||||
|
delivery requirements. The API allows access to many NORM protocol
|
||||||
|
parameters and control functions to tailor performance for specific
|
||||||
|
applications. While default parameters, where provided, can be
|
||||||
|
useful to a potential wide range of requirements, the many different
|
||||||
|
possible group communication paradigms dictate different needs for
|
||||||
|
different applications. Even with NORM, the developer should have a
|
||||||
|
thorough understanding of the specific application's group
|
||||||
|
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">
|
||||||
|
|
@ -95,103 +107,113 @@ of Contents</H1>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||||
Data Transport</B></FONT></P>
|
Data Transport</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
||||||
Data Transmission </FONT></P>
|
Data Transmission</FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
||||||
Data Reception </FONT></P>
|
Data Reception</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
|
||||||
Event Notification</B></FONT></P>
|
Event Notification</B></FONT></P>
|
||||||
|
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>Build
|
||||||
|
Notes</B></FONT></P>
|
||||||
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Unix
|
||||||
|
Platforms</B></FONT></P>
|
||||||
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Win32/WiNCE
|
||||||
|
Platforms</B></FONT></P>
|
||||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>API
|
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>API
|
||||||
Reference</B></FONT></P>
|
Reference</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
|
||||||
Variable Types and Constants</B></FONT></P>
|
Variable Types and Constants</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormInstanceHandle">NormInstanceHandle</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormInstanceHandle">NormInstanceHandle</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionHandle">NormSessionHandle</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionHandle">NormSessionHandle</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeHandle">NormNodeHandle</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionId">NormSessionId</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeId">NormNodeId</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeHandle">NormNodeHandle</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectHandle">NormObjectHandle</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeId">NormNodeId</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectType">NormObjectType</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectHandle">NormObjectHandle</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectTransportId">NormObjectTransportId</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectType">NormObjectType</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="#NormSize">NormSize</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="#NormObjectTransportId">NormObjectTransportId</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="#NormDescriptor">NormDescriptor</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>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetCacheDirectory()">NormSetCacheDirectory()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetCacheDirectory()">NormSetCacheDirectory()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetDescriptor()">NormGetDescriptor()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetDescriptor()">NormGetDescriptor()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Session
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Session
|
||||||
Creation and Control</B></FONT></P>
|
Creation and Control</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateSession()">NormCreateSession()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroySession()">NormDestroySession()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroySession()">NormDestroySession()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetUserData()">NormSetUserData()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetUserData()">NormSetUserData()</A></FONT></P>
|
||||||
<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="#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>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetLoopback()">NormSetLoopback()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetLoopback()">NormSetLoopback()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||||
Sender Functions</B></FONT></P>
|
Sender Functions</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartSender()">NormStartSender()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartSender()">NormStartSender()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopSender()">NormStopSender()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopSender()">NormStopSender()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitRate()">NormSetTransmitRate()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitRate()">NormSetTransmitRate()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTxSocketBuffer()">NormSetTxSocketBuffer()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTxSocketBuffer()">NormSetTxSocketBuffer()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetCongestionControl()">NormSetCongestionControl()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetCongestionControl()">NormSetCongestionControl()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitRateBounds()">NormSetTransmitRateBounds()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitRateBounds()">NormSetTransmitRateBounds()</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="#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>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataEnqueue()">NormDataEnqueue()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataEnqueue()">NormDataEnqueue()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamOpen()">NormStreamOpen()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamClose()">NormStreamClose()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamClose()">NormStreamClose()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamWrite()">NormStreamWrite()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamFlush()">NormStreamFlush()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamFlush()">NormStreamFlush()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSetAutoFlush()">NormStreamSetAutoFlush()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSetAutoFlush()">NormStreamSetAutoFlush()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSetPushEnable()">NormStreamSetPushEnable()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSetPushEnable()">NormStreamSetPushEnable()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamHasVacancy()">NormStreamHasVacancy()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamHasVacancy()">NormStreamHasVacancy()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamMarkEom()">NormStreamMarkEom()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamMarkEom()">NormStreamMarkEom()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetWatermark()">NormSetWatermark()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||||
Receiver Functions</B></FONT></P>
|
Receiver Functions</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartReceiver()">NormStartReceiver()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopReceiver()">NormStopReceiver()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopReceiver()">NormStopReceiver()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetRxSocketBuffer()">NormSetRxSocketBuffer()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetRxSocketBuffer()">NormSetRxSocketBuffer()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetSilentReceiver()">NormSetSilentReceiver()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetSilentReceiver()">NormSetSilentReceiver()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetDefaultUnicastNack()">NormSetDefaultUnicastNack()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetDefaultUnicastNack()">NormSetDefaultUnicastNack()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeSetUnicastNack()">NormNodeSetUnicastNack()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeSetUnicastNack()">NormNodeSetUnicastNack()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetDefaultNackingMode()">NormSetDefaultNackingMode()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetDefaultNackingMode()">NormSetDefaultNackingMode()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeSetNackingMode()">NormNodeSetNackingMode()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeSetNackingMode()">NormNodeSetNackingMode()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectSetNackingMode()">NormObjectSetNackingMode()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectSetNackingMode()">NormObjectSetNackingMode()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetDefaultRepairBoundary()">NormSetDefaultRepairBoundary()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetDefaultRepairBoundary()">NormSetDefaultRepairBoundary()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeSetRepairBoundary()">NormNodeSetRepairBoundary()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeSetRepairBoundary()">NormNodeSetRepairBoundary()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamRead()">NormStreamRead()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamRead()">NormStreamRead()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSeekMsgStart()">NormStreamSeekMsgStart()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSeekMsgStart()">NormStreamSeekMsgStart()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamGetReadOffset()">NormStreamGetReadOffset()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamGetReadOffset()">NormStreamGetReadOffset()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||||
Object Functions</B></FONT></P>
|
Object Functions</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetType()">NormObjectGetType()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetType()">NormObjectGetType()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectHasInfo()">NormObjectHasInfo()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectHasInfo()">NormObjectHasInfo()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetInfoLength()">NormObjectGetInfoLength()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetInfoLength()">NormObjectGetInfoLength()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetInfo()">NormObjectGetInfo()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetInfo()">NormObjectGetInfo()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetSize()">NormObjectGetSize()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetSize()">NormObjectGetSize()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectCancel()">NormObjectCancel()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetBytesPending()">NormObjectGetBytesPending()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectRetain()">NormObjectRetain()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectCancel()">NormObjectCancel()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectRelease()">NormObjectRelease()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectRetain()">NormObjectRetain()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileGetName()">NormFileGetName()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectRelease()">NormObjectRelease()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileRename()">NormFileRename()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileGetName()">NormFileGetName()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataAccessData()">NormDataAccessData()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileRename()">NormFileRename()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataDetachData()">NormDataDetachData()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataAccessData()">NormDataAccessData()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetSender()">NormObjectGetSender()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataDetachData()">NormDataDetachData()</A></FONT></P>
|
||||||
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetSender()">NormObjectGetSender()</A></FONT></P>
|
||||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||||
Node Functions</B></FONT></P>
|
Node Functions</B></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetId()">NormNodeGetId()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetId()">NormNodeGetId()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetAddress()">NormNodeGetAddress()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetAddress()">NormNodeGetAddress()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRetain()">NormNodeRetain()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRetain()">NormNodeRetain()</A></FONT></P>
|
||||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRelease()">NormNodeRelease()</A> </FONT></P>
|
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRelease()">NormNodeRelease()</A></FONT></P>
|
||||||
</DIV>
|
</DIV>
|
||||||
<H1 CLASS="western" STYLE="page-break-before: always">Overview</H1>
|
<H1 CLASS="western" STYLE="page-break-before: always">Overview</H1>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The NORM API has been
|
<P CLASS="western" STYLE="font-style: normal">The NORM API has been
|
||||||
|
|
@ -358,7 +380,76 @@ disabling receiver feedback (silent receiver operation) entirely.</P>
|
||||||
<H2 CLASS="western">API Event Notification</H2>
|
<H2 CLASS="western">API Event Notification</H2>
|
||||||
<P CLASS="western" STYLE="font-style: normal">An asynchronous event
|
<P CLASS="western" STYLE="font-style: normal">An asynchronous event
|
||||||
dispatching mechanism is provided to notify the application of
|
dispatching mechanism is provided to notify the application of
|
||||||
significant NORM protocol events ...</P>
|
significant NORM protocol events. The centerpiece of this is the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT> function which can be
|
||||||
|
used to retrieve the next NORM protocol engine event in the form of a
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT> structure. This function will
|
||||||
|
typically block until a <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT> occurs.
|
||||||
|
However, non-blocking operation may be achieved by using the
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormGetDescriptor()">NormGetDescriptor()</A></FONT> call to get a value
|
||||||
|
(file descriptor (Unix) or HANDLE (Win32) suitable for use in a
|
||||||
|
asynchronous I/O monitoring functions such as <I>select()</I> (Unix)
|
||||||
|
or <I>MsgWaitForMultipleObjects()</I> (Win32). The descriptor will
|
||||||
|
be signaled when a <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT> is
|
||||||
|
available. For Win32 platforms, dispatching of a user-defined
|
||||||
|
Windows message for NORM event notification is also planned for a
|
||||||
|
future update to the API.</P>
|
||||||
|
<H1 CLASS="western">Build Notes</H1>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">To build applications
|
||||||
|
that use the NORM library, a path to the "normApi.h" header
|
||||||
|
file must be provided and the linker step needs to reference the NORM
|
||||||
|
library file ("libnorm.a" for Unix platforms and "Norm.lib"
|
||||||
|
for Win32 platforms). NORM also depends upon the NRL Protean
|
||||||
|
Protocol Prototyping toolkit"Protokit" library (a.k.a
|
||||||
|
"Protolib") (static library files "libProtokit.a"
|
||||||
|
for Unix and "Protokit.lib" for Win32). Depending upon the
|
||||||
|
platform, some additional library dependencies may be required to
|
||||||
|
support the needs of NORM and/or Protokit. These are described
|
||||||
|
below.</P>
|
||||||
|
<H2 CLASS="western">Unix Platforms</H2>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">NORM has been built and
|
||||||
|
tested on Linux (various architectures), MacOS (BSD), Solaris, and
|
||||||
|
IRIX (SGI) platforms. The code should be readily portable to other
|
||||||
|
Unix platforms.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">To support IPv6
|
||||||
|
operation, the NORM and the Protokit library must be compiled with
|
||||||
|
the "HAVE_IPV6" macro defined. This is default in the NORM
|
||||||
|
and Protokit Makefiles for platforms that support IPv6. It is
|
||||||
|
important that NORM and Protokit be built with this macro defined the
|
||||||
|
same. With NORM, it is recommended that "large file support"
|
||||||
|
options be enabled when possible.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The NORM API uses
|
||||||
|
threading so that the NORM protocol engine may run independent of the
|
||||||
|
application. Thus the "Posix Threads" library must be
|
||||||
|
included ("-'pthread") in the linking step. MacOS/BSD also
|
||||||
|
requires the addition of the "-lresolv" (resolver) library
|
||||||
|
and Solaris requires the dynamic loader, network/socket, and resolver
|
||||||
|
libraries ("-ldl –lnsl –lsocket –lresolv")
|
||||||
|
to achieve successful compilation. The Makefiles in the NORM source
|
||||||
|
code distribution are a reference for these requirements.</P>
|
||||||
|
<H2 CLASS="western">Win32/WiNCE Platforms</H2>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">NORM has been built
|
||||||
|
using Microsoft's Visual C++ (6.0 and .NET) and Embedded VC++ 4.2
|
||||||
|
environments. In addition to proper macro definitions (e.g.,
|
||||||
|
HAVE_IPV6, etc) that are included in the respective "Protokit"
|
||||||
|
and "NORM" project files, it is important that common code
|
||||||
|
generation settings be used when building the NORM application. The
|
||||||
|
NORM and Protokit projects are built with the "Multithreading
|
||||||
|
DLL" library usage set. The NORM API requires multithreading
|
||||||
|
support. This is a critical setting and numerous compiler and linker
|
||||||
|
errors will result if this is not properly set for your application
|
||||||
|
project.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">NORM and Protokit also
|
||||||
|
depend on the Winsock 2.0 ("ws2_32.lib" (or "ws2.lib"
|
||||||
|
(WinCE)) and the IP Helper API ("iphlpapi.lib") libraries
|
||||||
|
and these must be included in the project "Link"
|
||||||
|
attributes.</P>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">An additional note is
|
||||||
|
that a bug in VC++ 6.0 and earlier compilers (includes embedded VC++
|
||||||
|
4.x compilers) prevent compilation of Protokit-based code with
|
||||||
|
debugging capabilities enabled. However, this has been resolved in
|
||||||
|
VC++ .NET and is hoped to be resolved in the future for the WinCE
|
||||||
|
build tools.</P>
|
||||||
<H1 CLASS="western">API Reference</H1>
|
<H1 CLASS="western">API Reference</H1>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This section provides a
|
<P CLASS="western" STYLE="font-style: normal">This section provides a
|
||||||
reference to the NORM API variable types, constants and functions.</P>
|
reference to the NORM API variable types, constants and functions.</P>
|
||||||
|
|
@ -388,6 +479,22 @@ call. Multiple <FONT FACE="Courier">NormSessionHandles</FONT> may be
|
||||||
associated with a given <FONT FACE="Courier"><A HREF="#NormInstanceHandle">NormInstanceHandle</A></FONT>.
|
associated with a given <FONT FACE="Courier"><A HREF="#NormInstanceHandle">NormInstanceHandle</A></FONT>.
|
||||||
The special value <FONT FACE="Courier">NORM_SESSION_INVALID </FONT>is
|
The special value <FONT FACE="Courier">NORM_SESSION_INVALID </FONT>is
|
||||||
used to refer to invalid session references.</P>
|
used to refer to invalid session references.</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormSessionId">NormSessionId</A></H3>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormSessionId">NormSessionId</A></FONT>
|
||||||
|
type is used by applications to uniquely identify their instance of
|
||||||
|
participation as a sender within a <I>NormSession</I>. This type is
|
||||||
|
a parameter to the <FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT>
|
||||||
|
function. Robust applications can use different <FONT FACE="Courier"><A HREF="#NormSessionId">NormSessionId</A></FONT>
|
||||||
|
values when initiating sender operation so that receivers can
|
||||||
|
discriminate when a sender has terminated and restarted (whether
|
||||||
|
intentional or due to system failure). For example, an application
|
||||||
|
could cache its prior <FONT FACE="Courier"><A HREF="#NormSessionId">NormSessionId</A></FONT> value
|
||||||
|
in non-volatile storage which could then be recovered and incremented
|
||||||
|
(for example) upon system restart to produce a new value. The
|
||||||
|
<FONT FACE="Courier"><A HREF="#NormSessionId">NormSessionId</A></FONT> value is used for the value
|
||||||
|
of the <I>instance_id</I> field in NORM protocol sender messages (see
|
||||||
|
the NORM protocol specification) and receivers use this field to
|
||||||
|
detect sender restart within a <I>NormSession</I>.</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormNodeHandle">NormNodeHandle</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormNodeHandle">NormNodeHandle</A></H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormNodeHandle">NormNodeHandle</A>
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormNodeHandle">NormNodeHandle</A>
|
||||||
</FONT>type is used to reference state kept by the NORM
|
</FONT>type is used to reference state kept by the NORM
|
||||||
|
|
@ -441,6 +548,17 @@ function call. A special <FONT FACE="Courier"><A HREF="#NormObjectType">NormObj
|
||||||
value, <I><FONT FACE="Courier">NORM_OBJECT_NONE</FONT></I>, indicates
|
value, <I><FONT FACE="Courier">NORM_OBJECT_NONE</FONT></I>, indicates
|
||||||
an invalid object type.
|
an invalid object type.
|
||||||
</P>
|
</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormSize">NormSize</A></H3>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
||||||
|
is the type used for <I>NormObject</I> size information. For
|
||||||
|
example, the <FONT FACE="Courier"><A HREF="#NormObjectGetSize()">NormObjectGetSize()</A></FONT> function
|
||||||
|
returns a value of type <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>. The
|
||||||
|
range of <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT> values depends upon the
|
||||||
|
operating system and NORM library compilation settings. With "large
|
||||||
|
file support" enabled, as is the case with distributed NORM
|
||||||
|
library "Makefiles", the <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
||||||
|
type is a 64-bit integer. However, some platforms may support only
|
||||||
|
32-bit object sizes.</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormObjectTransportId">NormObjectTransportId</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormObjectTransportId">NormObjectTransportId</A></H3>
|
||||||
<P CLASS="western" STYLE="font-style: normal">The
|
<P CLASS="western" STYLE="font-style: normal">The
|
||||||
<FONT FACE="Courier"><A HREF="#NormObjectTransportId">NormObjectTransportId</A></FONT> type is a 16-bit
|
<FONT FACE="Courier"><A HREF="#NormObjectTransportId">NormObjectTransportId</A></FONT> type is a 16-bit
|
||||||
|
|
@ -452,7 +570,7 @@ values in a monotonically increasing fashion during the course of a
|
||||||
session as part of protocol operation. Typically, the application
|
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 function 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() function (TBD) is implemented using handles only,
|
NormObjectRequeue() function (TBD) is implemented using handles only,
|
||||||
but _some_ applications requiring persistence even after a system
|
but _some_ applications requiring persistence even after a system
|
||||||
|
|
@ -483,7 +601,17 @@ and <FONT FACE="Courier">object</FONT> fields indicate the applicable
|
||||||
and <FONT FACE="Courier"><A HREF="#NormObjectHandle">NormObjectHandle</A></FONT>, respectively, to
|
and <FONT FACE="Courier"><A HREF="#NormObjectHandle">NormObjectHandle</A></FONT>, respectively, to
|
||||||
which the event applies. NORM protocol events are made available to
|
which the event applies. NORM protocol events are made available to
|
||||||
the application via the <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>
|
the application via the <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>
|
||||||
function call.
|
function call.</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormDescriptor">NormDescriptor</A></H3>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormDescriptor">NormDescriptor</A></FONT>
|
||||||
|
type provides reference to a file descriptor (Unix) or HANDLE
|
||||||
|
(Win32). For a given <FONT FACE="Courier"><A HREF="#NormInstanceHandle">NormInstanceHandle</A></FONT>,
|
||||||
|
the <FONT FACE="Courier"><A HREF="#NormGetDescriptor()">NormGetDescriptor()</A></FONT> function can be
|
||||||
|
used to retrieve a <A HREF="#NormDescriptor">NormDescriptor</A> value that may, in turn, used in
|
||||||
|
appropriate system calls (e.g. <I>select()</I> or
|
||||||
|
<I>MsgWaitForMultipleObjects()</I>) to asynchronously monitor the
|
||||||
|
NORM protocol engine for notification events (see <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT>
|
||||||
|
description).
|
||||||
</P>
|
</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
|
||||||
|
|
@ -640,6 +768,26 @@ function call.</P>
|
||||||
objects for transmission.</P>
|
objects for transmission.</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD WIDTH=269>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
<FONT FACE="Courier"><I>NORM_TX_FLUSH_COMPLETED</I></FONT></P>
|
||||||
|
</TD>
|
||||||
|
<TD WIDTH=293>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
This event indicates that the flushing process the NORM sender
|
||||||
|
observes when it no longer has data ready for transmission has
|
||||||
|
completed. The completion of the flushing process is a reasonable
|
||||||
|
indicator (with a sufficient NORM "robust factor" value)
|
||||||
|
that the receiver set no longer has any pending repair requests.
|
||||||
|
Note the use of NORM's optional positive acknowledgement feature
|
||||||
|
is more deterministic in this regards, but this notification is
|
||||||
|
useful when there are non-acking (NACK-only) receivers. The
|
||||||
|
default NORM robust factor of 20 (20 flush messages are sent at
|
||||||
|
end-of-transmission) provides a high assurance of reliable
|
||||||
|
transmission, even with packet loss rates of 50%.</P>
|
||||||
|
</TD>
|
||||||
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD WIDTH=269>
|
<TD WIDTH=269>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
|
@ -843,14 +991,14 @@ events if undesired)).</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>NormDescriptor
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2><A HREF="#NormDescriptor">NormDescriptor</A>
|
||||||
NormGetDescriptor(<A HREF="#NormInstanceHandle">NormInstanceHandle</A> instance);</FONT></FONT></P>
|
NormGetDescriptor(<A HREF="#NormInstanceHandle">NormInstanceHandle</A> instance);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function is used
|
<P CLASS="western" STYLE="font-style: normal">This function is used
|
||||||
to retrieve a <FONT FACE="Courier">NormDescriptor</FONT> (integer
|
to retrieve a <FONT FACE="Courier"><A HREF="#NormDescriptor">NormDescriptor</A></FONT> (integer
|
||||||
file descriptor (UNIX) or HANDLE (WIN32)) suitable for asynchronous
|
file descriptor (UNIX) or HANDLE (WIN32)) suitable for asynchronous
|
||||||
I/O notification to avoid blocking calls to <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>.
|
I/O notification to avoid blocking calls to <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>.
|
||||||
A <FONT FACE="Courier">NormDescriptor</FONT> is available for each
|
A <FONT FACE="Courier"><A HREF="#NormDescriptor">NormDescriptor</A></FONT> is available for each
|
||||||
protocol engine <U><FONT FACE="Courier">instance</FONT></U>. The
|
protocol engine <U><FONT FACE="Courier">instance</FONT></U>. The
|
||||||
descriptor (or WIN32 HANDLE) is suitable for use as an input (or
|
descriptor (or WIN32 HANDLE) is suitable for use as an input (or
|
||||||
"read") descriptor which is signaled when a NORM protocol
|
"read") descriptor which is signaled when a NORM protocol
|
||||||
|
|
@ -858,7 +1006,7 @@ event is ready for retrieval via <FONT FACE="Courier"><A HREF="#NormGetNextEvent
|
||||||
Hence, a call to <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT> will
|
Hence, a call to <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT> will
|
||||||
not block when the descriptor has been signaled. The <I><FONT FACE="Courier">select()</FONT></I>
|
not block when the descriptor has been signaled. The <I><FONT FACE="Courier">select()</FONT></I>
|
||||||
system call (UNIX) (or <I><FONT FACE="Courier">WaitForMultipleObjects()</FONT></I>
|
system call (UNIX) (or <I><FONT FACE="Courier">WaitForMultipleObjects()</FONT></I>
|
||||||
(WIN32)) can be used to detect when the returned <FONT FACE="Courier">NormDescriptor</FONT>
|
(WIN32)) can be used to detect when the returned <FONT FACE="Courier"><A HREF="#NormDescriptor">NormDescriptor</A></FONT>
|
||||||
is signaled. For the <FONT FACE="Courier">select()</FONT> call
|
is signaled. For the <FONT FACE="Courier">select()</FONT> call
|
||||||
usage, the NORM descriptor should be treated as a "read"
|
usage, the NORM descriptor should be treated as a "read"
|
||||||
descriptor.</P>
|
descriptor.</P>
|
||||||
|
|
@ -1186,7 +1334,7 @@ Functions</H2>
|
||||||
<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>bool
|
||||||
NormStartSender(<A HREF="#NormSessionHandle">NormSessionHandle</A> session<BR> unsigned
|
NormStartSender(<A HREF="#NormSessionHandle">NormSessionHandle</A> sessionHandle<BR> <A HREF="#NormSessionId">NormSessionId</A> sessionId<BR> unsigned
|
||||||
long bufferSpace<BR> unsigned
|
long bufferSpace<BR> unsigned
|
||||||
short segmentSize,<BR> unsigned
|
short segmentSize,<BR> unsigned
|
||||||
char blockSize,<BR> unsigned
|
char blockSize,<BR> unsigned
|
||||||
|
|
@ -1200,25 +1348,44 @@ feedback collection and application API activity such as posting of
|
||||||
sender-related <I>NormEvents</I>. The parameters required for this
|
sender-related <I>NormEvents</I>. The parameters required for this
|
||||||
function call include:</P>
|
function call include:</P>
|
||||||
<TABLE WIDTH=590 BORDER=0 CELLPADDING=7 CELLSPACING=0>
|
<TABLE WIDTH=590 BORDER=0 CELLPADDING=7 CELLSPACING=0>
|
||||||
<COL WIDTH=106>
|
<COL WIDTH=125>
|
||||||
<COL WIDTH=456>
|
<COL WIDTH=437>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD WIDTH=106>
|
<TD WIDTH=125>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
<FONT FACE="Courier"><U>session</U></FONT></P>
|
<FONT FACE="Courier"><U>sessionHandle</U></FONT></P>
|
||||||
</TD>
|
</TD>
|
||||||
<TD WIDTH=456>
|
<TD WIDTH=437>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
This must be a valid <FONT FACE="Courier"><A HREF="#NormSessionHandle">NormSessionHandle</A></FONT>
|
This must be a valid <FONT FACE="Courier"><A HREF="#NormSessionHandle">NormSessionHandle</A></FONT>
|
||||||
previously obtained with a call to <FONT FACE="Courier"><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT>.</P>
|
previously obtained with a call to <FONT FACE="Courier"><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT>.</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD WIDTH=106>
|
<TD WIDTH=125>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
<FONT FACE="Courier"><U>sessionId</U></FONT></P>
|
||||||
|
</TD>
|
||||||
|
<TD WIDTH=437>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
|
Application-defined value used as the <I>instance_id</I> field of
|
||||||
|
NORM sender messages for the application's participation within a
|
||||||
|
session. Receivers can detect when a sender has terminated and
|
||||||
|
restarted if the application uses different <FONT FACE="Courier"><U>sessionId</U></FONT>
|
||||||
|
values when initiating sender operation. For example, a robust
|
||||||
|
application could cache previous <FONT FACE="Courier"><U>sessionId</U></FONT>
|
||||||
|
values in non-volatile storage and gracefully recover (without
|
||||||
|
confusing receivers) from a total system shutdown and reboot by
|
||||||
|
using a new <FONT FACE="Courier"><U>sessionId</U></FONT> value
|
||||||
|
upon restart.</P>
|
||||||
|
</TD>
|
||||||
|
</TR>
|
||||||
|
<TR VALIGN=TOP>
|
||||||
|
<TD WIDTH=125>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
<FONT FACE="Courier"><U>bufferSpace</U></FONT></P>
|
<FONT FACE="Courier"><U>bufferSpace</U></FONT></P>
|
||||||
</TD>
|
</TD>
|
||||||
<TD WIDTH=456>
|
<TD WIDTH=437>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
This specifies the maximum memory space the NORM protocol engine
|
This specifies the maximum memory space the NORM protocol engine
|
||||||
is allowed to use to buffer any sender calculated FEC segments and
|
is allowed to use to buffer any sender calculated FEC segments and
|
||||||
|
|
@ -1236,11 +1403,11 @@ function call include:</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD WIDTH=106>
|
<TD WIDTH=125>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
<FONT FACE="Courier"><U>segmentSize</U></FONT></P>
|
<FONT FACE="Courier"><U>segmentSize</U></FONT></P>
|
||||||
</TD>
|
</TD>
|
||||||
<TD WIDTH=456>
|
<TD WIDTH=437>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
This parameter sets the maximum <I>payload</I> size (in bytes) of
|
This parameter sets the maximum <I>payload</I> size (in bytes) of
|
||||||
NORM sender messages (<I>not</I> including any NORM message header
|
NORM sender messages (<I>not</I> including any NORM message header
|
||||||
|
|
@ -1262,11 +1429,11 @@ function call include:</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD WIDTH=106>
|
<TD WIDTH=125>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
<FONT FACE="Courier"><U>blockSize</U></FONT></P>
|
<FONT FACE="Courier"><U>blockSize</U></FONT></P>
|
||||||
</TD>
|
</TD>
|
||||||
<TD WIDTH=456>
|
<TD WIDTH=437>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
This parameter sets the number of source symbol segments (packets)
|
This parameter sets the number of source symbol segments (packets)
|
||||||
per coding block, for the systematic Reed-Solomon FEC code used in
|
per coding block, for the systematic Reed-Solomon FEC code used in
|
||||||
|
|
@ -1286,11 +1453,11 @@ function call include:</P>
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
<TR VALIGN=TOP>
|
<TR VALIGN=TOP>
|
||||||
<TD WIDTH=106>
|
<TD WIDTH=125>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
<FONT FACE="Courier"><U>numParity</U></FONT></P>
|
<FONT FACE="Courier"><U>numParity</U></FONT></P>
|
||||||
</TD>
|
</TD>
|
||||||
<TD WIDTH=456>
|
<TD WIDTH=437>
|
||||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||||
This parameter sets the maximum number of parity symbol segments
|
This parameter sets the maximum number of parity symbol segments
|
||||||
(packets) the sender is willing to <I>calculate</I> per FEC coding
|
(packets) the sender is willing to <I>calculate</I> per FEC coding
|
||||||
|
|
@ -2713,8 +2880,8 @@ yet been received (or is non-existent) for the specified object.</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>off_t
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2><A HREF="#NormSize">NormSize</A>
|
||||||
NormObjectHasInfo(<A HREF="#NormObjectHandle">NormObjectHandle</A> objectHandle);</FONT></FONT></P>
|
NormObjectGetSize(<A HREF="#NormObjectHandle">NormObjectHandle</A> objectHandle);</FONT></FONT></P>
|
||||||
<H4 CLASS="western">Description</H4>
|
<H4 CLASS="western">Description</H4>
|
||||||
<P CLASS="western" STYLE="font-style: normal">This function can be
|
<P CLASS="western" STYLE="font-style: normal">This function can be
|
||||||
used to determine the size (in bytes) of the transport object
|
used to determine the size (in bytes) of the transport object
|
||||||
|
|
@ -2724,11 +2891,9 @@ parameter. NORM can support large object sizes for the
|
||||||
typically the NORM library is built with any necessary, related
|
typically the NORM library is built with any necessary, related
|
||||||
macros defined such that operating system large file support is
|
macros defined such that operating system large file support is
|
||||||
enabled (e.g., "<FONT FACE="Courier">#define _FILE_OFFSET_BITS
|
enabled (e.g., "<FONT FACE="Courier">#define _FILE_OFFSET_BITS
|
||||||
64</FONT>" or equivalent). Developers should configure their
|
64</FONT>" or equivalent). The <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
||||||
build environment to correspond with the NORM library used to ensure
|
type is defined accordingly, so the application should be built with
|
||||||
that the "<FONT SIZE=2><FONT FACE="Courier">off_t</FONT></FONT>"
|
the same large file support configuration.</P>
|
||||||
type is appropriately defined.
|
|
||||||
</P>
|
|
||||||
<P CLASS="western" STYLE="font-style: normal">For objects of type
|
<P CLASS="western" STYLE="font-style: normal">For objects of type
|
||||||
<FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>, the size
|
<FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>, the size
|
||||||
returned here corresponds to the stream buffer size set by the sender
|
returned here corresponds to the stream buffer size set by the sender
|
||||||
|
|
@ -2738,6 +2903,28 @@ application when opening the referenced stream object.</P>
|
||||||
content of the specified object, in bytes, is returned. Note that it
|
content of the specified object, in bytes, is returned. Note that it
|
||||||
may be possible that some objects have zero data content, but do have
|
may be possible that some objects have zero data content, but do have
|
||||||
NORM_INFO content available.</P>
|
NORM_INFO content available.</P>
|
||||||
|
<H3 CLASS="functionheading-western"><A NAME="NormObjectGetBytesPending()">NormObjectGetBytesPending()</A></H3>
|
||||||
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
<normApi.h></FONT></FONT></P>
|
||||||
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2><A HREF="#NormSize">NormSize</A>
|
||||||
|
NormObjectGetBytesPending(<A HREF="#NormObjectHandle">NormObjectHandle</A> objectHandle);</FONT></FONT></P>
|
||||||
|
<H4 CLASS="western">Description</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">This function can be
|
||||||
|
used to determine the progress of reception of the NORM transport
|
||||||
|
object identified by the <FONT FACE="Courier"><U>objectHandle</U></FONT>
|
||||||
|
parameter. This function indicates the number of bytes that are
|
||||||
|
pending reception (I.e., when the object is completely received,
|
||||||
|
"bytes pending" will equal ZERO). This function is not
|
||||||
|
necessarily applicable to objects of type NORM_OBJECT_STREAM which do
|
||||||
|
not have a finite size. Note it is possible that this function might
|
||||||
|
also be useful to query the "transmit pending" status of
|
||||||
|
sender objects, but it does not account for pending FEC repair
|
||||||
|
transmissions and thus may not produce useful results for this
|
||||||
|
purpose.</P>
|
||||||
|
<H4 CLASS="western">Return Values</H4>
|
||||||
|
<P CLASS="western" STYLE="font-style: normal">A number of object
|
||||||
|
source data bytes pending reception (or transmission) is returned.</P>
|
||||||
<H3 CLASS="functionheading-western"><A NAME="NormObjectCancel()">NormObjectCancel()</A></H3>
|
<H3 CLASS="functionheading-western"><A NAME="NormObjectCancel()">NormObjectCancel()</A></H3>
|
||||||
<H4 CLASS="western">Synopsis</H4>
|
<H4 CLASS="western">Synopsis</H4>
|
||||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,5 +1,14 @@
|
||||||
NORM Version History
|
NORM Version History
|
||||||
|
|
||||||
|
Version 1.3b3
|
||||||
|
=============
|
||||||
|
- Added NORM_TX_FLUSH_COMPLETE notification so the sender app
|
||||||
|
can make an educated guess as to when his receivers are
|
||||||
|
all happy.
|
||||||
|
- Added NORM API sample code in "examples" directory.
|
||||||
|
- Added NormObjectGetBytesPending() call for receivers to
|
||||||
|
use to monitor reception progress.
|
||||||
|
|
||||||
Version 1.3b2
|
Version 1.3b2
|
||||||
=============
|
=============
|
||||||
- Added "graceful" stream shutdown option to
|
- Added "graceful" stream shutdown option to
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "normApi.h"
|
#include "normApi.h"
|
||||||
#include "normSession.h"
|
#include "normSession.h"
|
||||||
|
|
||||||
|
|
@ -143,8 +142,10 @@ class NormInstance : public NormController
|
||||||
NormInstance::Notification::Queue::Queue()
|
NormInstance::Notification::Queue::Queue()
|
||||||
: head(NULL), tail(NULL)
|
: head(NULL), tail(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NormInstance::Notification::Queue::~Queue()
|
NormInstance::Notification::Queue::~Queue()
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
@ -168,7 +169,7 @@ NormInstance::NormInstance()
|
||||||
#else
|
#else
|
||||||
notify_fd[0] = notify_fd[1] = -1;
|
notify_fd[0] = notify_fd[1] = -1;
|
||||||
#endif // if/else WIN32/UNIX
|
#endif // if/else WIN32/UNIX
|
||||||
session_mgr.SetController(this);
|
session_mgr.SetController(static_cast<NormController*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
NormInstance::~NormInstance()
|
NormInstance::~NormInstance()
|
||||||
|
|
@ -314,6 +315,7 @@ void NormInstance::Notify(NormController::Event event,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we're ignoring files
|
// we're ignoring files
|
||||||
|
DMSG(8, "NormInstance::Notify() warning: receive file but no cache directory set, so ignoring file\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -849,6 +851,7 @@ void NormSetRxLoss(NormSessionHandle sessionHandle, double percent)
|
||||||
/** NORM Sender Functions */
|
/** NORM Sender Functions */
|
||||||
|
|
||||||
bool NormStartSender(NormSessionHandle sessionHandle,
|
bool NormStartSender(NormSessionHandle sessionHandle,
|
||||||
|
NormSessionId sessionId,
|
||||||
unsigned long bufferSpace,
|
unsigned long bufferSpace,
|
||||||
unsigned short segmentSize,
|
unsigned short segmentSize,
|
||||||
unsigned char numData,
|
unsigned char numData,
|
||||||
|
|
@ -860,7 +863,7 @@ bool NormStartSender(NormSessionHandle sessionHandle,
|
||||||
{
|
{
|
||||||
NormSession* session = (NormSession*)sessionHandle;
|
NormSession* session = (NormSession*)sessionHandle;
|
||||||
if (session)
|
if (session)
|
||||||
result = session->StartServer(bufferSpace, segmentSize, numData, numParity);
|
result = session->StartServer(sessionId, bufferSpace, segmentSize, numData, numParity);
|
||||||
else
|
else
|
||||||
result = false;
|
result = false;
|
||||||
instance->dispatcher.ResumeThread();
|
instance->dispatcher.ResumeThread();
|
||||||
|
|
@ -1362,11 +1365,26 @@ unsigned short NormObjectGetInfo(NormObjectHandle objectHandle,
|
||||||
return result;
|
return result;
|
||||||
} // end NormObjectGetInfo()
|
} // end NormObjectGetInfo()
|
||||||
|
|
||||||
off_t NormObjectGetSize(NormObjectHandle objectHandle)
|
NormSize NormObjectGetSize(NormObjectHandle objectHandle)
|
||||||
{
|
{
|
||||||
return ((NormObject*)objectHandle)->GetSize().GetOffset();
|
return ((NormSize)((NormObject*)objectHandle)->GetSize().GetOffset());
|
||||||
} // end NormObjectGetSize()
|
} // end NormObjectGetSize()
|
||||||
|
|
||||||
|
NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle)
|
||||||
|
{
|
||||||
|
NormSize bytesPending = 0;
|
||||||
|
if (NORM_OBJECT_INVALID != objectHandle)
|
||||||
|
{
|
||||||
|
NormInstance* instance = NormInstance::GetInstanceFromObject(objectHandle);
|
||||||
|
if (instance && instance->dispatcher.SuspendThread())
|
||||||
|
{
|
||||||
|
bytesPending = ((NormSize)((NormObject*)objectHandle)->GetBytesPending().GetOffset());
|
||||||
|
instance->dispatcher.ResumeThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytesPending;
|
||||||
|
} // end NormObjectGetBytesPending()
|
||||||
|
|
||||||
void NormObjectCancel(NormObjectHandle objectHandle)
|
void NormObjectCancel(NormObjectHandle objectHandle)
|
||||||
{
|
{
|
||||||
if (NORM_OBJECT_INVALID != objectHandle)
|
if (NORM_OBJECT_INVALID != objectHandle)
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,10 @@
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h> // for "off_t"
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
|
||||||
#include <stdio.h>
|
|
||||||
//typedef fpos_t off_t;
|
|
||||||
typedef long off_t;
|
|
||||||
#else
|
|
||||||
#include <sys/types.h> // for "off_t" type
|
|
||||||
#endif // if/else _WIN32_WCE
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// IMPORTANT NOTICE
|
// IMPORTANT NOTICE
|
||||||
// The NORM API is _very_ much in a developmental phase
|
// The NORM API is _very_ much in a developmental phase
|
||||||
|
|
@ -35,6 +30,7 @@ extern const NormInstanceHandle NORM_INSTANCE_INVALID;
|
||||||
|
|
||||||
typedef const void* NormSessionHandle;
|
typedef const void* NormSessionHandle;
|
||||||
extern const NormSessionHandle NORM_SESSION_INVALID;
|
extern const NormSessionHandle NORM_SESSION_INVALID;
|
||||||
|
typedef unsigned short NormSessionId;
|
||||||
|
|
||||||
typedef const void* NormNodeHandle;
|
typedef const void* NormNodeHandle;
|
||||||
extern const NormNodeHandle NORM_NODE_INVALID;
|
extern const NormNodeHandle NORM_NODE_INVALID;
|
||||||
|
|
@ -46,6 +42,12 @@ typedef const void* NormObjectHandle;
|
||||||
extern const NormObjectHandle NORM_OBJECT_INVALID;
|
extern const NormObjectHandle NORM_OBJECT_INVALID;
|
||||||
typedef unsigned short NormObjectTransportId;
|
typedef unsigned short NormObjectTransportId;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
typedef __int64 NormSize;
|
||||||
|
#else
|
||||||
|
typedef off_t NormSize;
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
enum NormObjectType
|
enum NormObjectType
|
||||||
{
|
{
|
||||||
NORM_OBJECT_NONE,
|
NORM_OBJECT_NONE,
|
||||||
|
|
@ -80,6 +82,7 @@ enum NormEventType
|
||||||
NORM_EVENT_INVALID = 0,
|
NORM_EVENT_INVALID = 0,
|
||||||
NORM_TX_QUEUE_VACANCY,
|
NORM_TX_QUEUE_VACANCY,
|
||||||
NORM_TX_QUEUE_EMPTY,
|
NORM_TX_QUEUE_EMPTY,
|
||||||
|
NORM_TX_FLUSH_COMPLETED,
|
||||||
NORM_TX_OBJECT_SENT,
|
NORM_TX_OBJECT_SENT,
|
||||||
NORM_TX_OBJECT_PURGED,
|
NORM_TX_OBJECT_PURGED,
|
||||||
NORM_LOCAL_SERVER_CLOSED,
|
NORM_LOCAL_SERVER_CLOSED,
|
||||||
|
|
@ -172,6 +175,7 @@ void NormSetRxLoss(NormSessionHandle sessionHandle, double percent);
|
||||||
/** NORM Sender Functions */
|
/** NORM Sender Functions */
|
||||||
|
|
||||||
bool NormStartSender(NormSessionHandle sessionHandle,
|
bool NormStartSender(NormSessionHandle sessionHandle,
|
||||||
|
NormSessionId sessionId,
|
||||||
unsigned long bufferSpace,
|
unsigned long bufferSpace,
|
||||||
unsigned short segmentSize,
|
unsigned short segmentSize,
|
||||||
unsigned char numData,
|
unsigned char numData,
|
||||||
|
|
@ -298,7 +302,9 @@ unsigned short NormObjectGetInfo(NormObjectHandle objectHandle,
|
||||||
char* buffer,
|
char* buffer,
|
||||||
unsigned short bufferLen);
|
unsigned short bufferLen);
|
||||||
|
|
||||||
off_t NormObjectGetSize(NormObjectHandle objectHandle);
|
NormSize NormObjectGetSize(NormObjectHandle objectHandle);
|
||||||
|
|
||||||
|
NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle);
|
||||||
|
|
||||||
void NormObjectCancel(NormObjectHandle objectHandle);
|
void NormObjectCancel(NormObjectHandle objectHandle);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -353,7 +353,7 @@ bool NormApp::OnCommand(const char* cmd, const char* val)
|
||||||
len = strlen(buffer);
|
len = strlen(buffer);
|
||||||
len = (len > 8191) ? 8191 : len;
|
len = (len > 8191) ? 8191 : len;
|
||||||
buffer[len++] = '\0';
|
buffer[len++] = '\0';
|
||||||
if (!control_pipe.Send(buffer, len))
|
if (!control_pipe.Send(buffer, (unsigned int)len))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::OnCommand() error sending command to remote instance\n");
|
DMSG(0, "NormApp::OnCommand() error sending command to remote instance\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1104,10 +1104,10 @@ void NormApp::Notify(NormController::Event event,
|
||||||
// object Size() has recommended buffering size
|
// object Size() has recommended buffering size
|
||||||
NormObjectSize size;
|
NormObjectSize size;
|
||||||
if (silent_client)
|
if (silent_client)
|
||||||
size = NormObjectSize((UINT32)rx_buffer_size);
|
size = rx_buffer_size;
|
||||||
else
|
else
|
||||||
size = object->GetSize();
|
size = (UINT32)object->GetSize().LSB();
|
||||||
|
ASSERT(0 == size.MSB());
|
||||||
if (((NormStreamObject*)object)->Accept(size.LSB()))
|
if (((NormStreamObject*)object)->Accept(size.LSB()))
|
||||||
{
|
{
|
||||||
rx_stream = (NormStreamObject*)object;
|
rx_stream = (NormStreamObject*)object;
|
||||||
|
|
@ -1544,7 +1544,9 @@ bool NormApp::OnStartup(int argc, const char*const* argv)
|
||||||
session->SetBackoffFactor(backoff_factor);
|
session->SetBackoffFactor(backoff_factor);
|
||||||
session->ServerSetGrtt(grtt_estimate);
|
session->ServerSetGrtt(grtt_estimate);
|
||||||
session->ServerSetGroupSize(group_size);
|
session->ServerSetGroupSize(group_size);
|
||||||
if (!session->StartServer(tx_buffer_size, segment_size, ndata, nparity, interface_name))
|
// We also use the baseId as our server's "instance id" for illustrative purposes
|
||||||
|
UINT16 instanceId = baseId;
|
||||||
|
if (!session->StartServer(instanceId, tx_buffer_size, segment_size, ndata, nparity, interface_name))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::OnStartup() start server error!\n");
|
DMSG(0, "NormApp::OnStartup() start server error!\n");
|
||||||
session_mgr.Destroy();
|
session_mgr.Destroy();
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,7 @@ int NormFile::Read(char* buffer, int len)
|
||||||
#else
|
#else
|
||||||
int result = read(fd, buffer, len);
|
int result = read(fd, buffer, len);
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
if (result > 0) offset += (off_t)result;
|
if (result > 0) offset += (Offset)result;
|
||||||
return result;
|
return result;
|
||||||
} // end NormFile::Read()
|
} // end NormFile::Read()
|
||||||
|
|
||||||
|
|
@ -360,24 +360,24 @@ int NormFile::Write(const char* buffer, int len)
|
||||||
#else
|
#else
|
||||||
int result = write(fd, buffer, len);
|
int result = write(fd, buffer, len);
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
if (result > 0) offset += (off_t)result;
|
if (result > 0) offset += (Offset)result;
|
||||||
return result;
|
return result;
|
||||||
} // end NormFile::Write()
|
} // end NormFile::Write()
|
||||||
|
|
||||||
bool NormFile::Seek(off_t theOffset)
|
bool NormFile::Seek(Offset theOffset)
|
||||||
{
|
{
|
||||||
ASSERT(IsOpen());
|
ASSERT(IsOpen());
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
// (TBD) properly support big files on WinCE
|
// (TBD) properly support big files on WinCE
|
||||||
off_t result = fseek(file_ptr, (long)theOffset, SEEK_SET);
|
Offset result = fseek(file_ptr, (long)theOffset, SEEK_SET);
|
||||||
#else
|
#else
|
||||||
off_t result = _lseek(fd, theOffset, SEEK_SET);
|
Offset result = _lseeki64(fd, theOffset, SEEK_SET);
|
||||||
#endif // if/else _WIN32_WCE
|
#endif // if/else _WIN32_WCE
|
||||||
#else
|
#else
|
||||||
off_t result = lseek(fd, theOffset, SEEK_SET);
|
Offset result = lseek(fd, theOffset, SEEK_SET);
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
if (result == (off_t)-1)
|
if (result == (Offset)-1)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormFile::Seek() lseek() error: %s", GetErrorString());
|
DMSG(0, "NormFile::Seek() lseek() error: %s", GetErrorString());
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -389,12 +389,12 @@ bool NormFile::Seek(off_t theOffset)
|
||||||
}
|
}
|
||||||
} // end NormFile::Seek()
|
} // end NormFile::Seek()
|
||||||
|
|
||||||
off_t NormFile::GetSize() const
|
NormFile::Offset NormFile::GetSize() const
|
||||||
{
|
{
|
||||||
ASSERT(IsOpen());
|
ASSERT(IsOpen());
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
DWORD fileSize = GetFileSize(_fileno(file_ptr), NULL);
|
DWORD fileSize = GetFileSize(_fileno(file_ptr), NULL);
|
||||||
return ((off_t)fileSize);
|
return ((Offset)fileSize);
|
||||||
#else
|
#else
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
struct _stat info;
|
struct _stat info;
|
||||||
|
|
@ -787,7 +787,7 @@ NormFile::Type NormFile::GetType(const char* path)
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
} // end NormFile::GetType()
|
} // end NormFile::GetType()
|
||||||
|
|
||||||
off_t NormFile::GetSize(const char* path)
|
NormFile::Offset NormFile::GetSize(const char* path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
WIN32_FIND_DATA findData;
|
WIN32_FIND_DATA findData;
|
||||||
|
|
@ -799,7 +799,10 @@ off_t NormFile::GetSize(const char* path)
|
||||||
if (INVALID_HANDLE_VALUE != FindFirstFile(path, &findData))
|
if (INVALID_HANDLE_VALUE != FindFirstFile(path, &findData))
|
||||||
#endif // if/else _UNICODE
|
#endif // if/else _UNICODE
|
||||||
{
|
{
|
||||||
return ((off_t)findData.nFileSizeLow); // (TBD) support big files
|
Offset fileSize = findData.nFileSizeLow;
|
||||||
|
if (sizeof(Offset) > 4)
|
||||||
|
fileSize |= ((Offset)findData.nFileSizeHigh) << (8*sizeof(DWORD));
|
||||||
|
return fileSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
//typedef fpos_t off_t;
|
|
||||||
typedef long off_t;
|
|
||||||
#else
|
#else
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif // if/else _WIN32_WCE
|
#endif // if/else _WIN32_WCE
|
||||||
|
|
@ -45,8 +43,12 @@ enum
|
||||||
|
|
||||||
class NormFile
|
class NormFile
|
||||||
{
|
{
|
||||||
// Methods
|
|
||||||
public:
|
public:
|
||||||
|
#ifdef WIN32
|
||||||
|
typedef __int64 Offset;
|
||||||
|
#else
|
||||||
|
typedef off_t Offset;
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
enum Type {INVALID, NORMAL, DIRECTORY};
|
enum Type {INVALID, NORMAL, DIRECTORY};
|
||||||
NormFile();
|
NormFile();
|
||||||
~NormFile();
|
~NormFile();
|
||||||
|
|
@ -66,13 +68,13 @@ class NormFile
|
||||||
}
|
}
|
||||||
int Read(char* buffer, int len);
|
int Read(char* buffer, int len);
|
||||||
int Write(const char* buffer, int len);
|
int Write(const char* buffer, int len);
|
||||||
bool Seek(off_t theOffset);
|
bool Seek(Offset theOffset);
|
||||||
off_t GetOffset() const {return (offset);}
|
NormFile::Offset GetOffset() const {return (offset);}
|
||||||
off_t GetSize() const;
|
NormFile::Offset GetSize() const;
|
||||||
|
|
||||||
// static helper methods
|
// static helper methods
|
||||||
static NormFile::Type GetType(const char *path);
|
static NormFile::Type GetType(const char *path);
|
||||||
static off_t GetSize(const char* path);
|
static NormFile::Offset GetSize(const char* path);
|
||||||
static time_t GetUpdateTime(const char* path);
|
static time_t GetUpdateTime(const char* path);
|
||||||
static bool IsLocked(const char *path);
|
static bool IsLocked(const char *path);
|
||||||
|
|
||||||
|
|
@ -117,7 +119,11 @@ class NormFile
|
||||||
int fd;
|
int fd;
|
||||||
#endif // if/else _WIN32_WCE
|
#endif // if/else _WIN32_WCE
|
||||||
int flags;
|
int flags;
|
||||||
|
#ifdef WIN32
|
||||||
|
__int64 offset;
|
||||||
|
#else
|
||||||
off_t offset;
|
off_t offset;
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
}; // end class NormFile
|
}; // end class NormFile
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -204,7 +210,7 @@ class NormFileList
|
||||||
FileItem(const char* thePath);
|
FileItem(const char* thePath);
|
||||||
virtual ~FileItem();
|
virtual ~FileItem();
|
||||||
NormFile::Type GetType() {return NormFile::GetType(path);}
|
NormFile::Type GetType() {return NormFile::GetType(path);}
|
||||||
off_t Size() const {return size;}
|
NormFile::Offset Size() const {return size;}
|
||||||
virtual bool GetNextFile(char* thePath,
|
virtual bool GetNextFile(char* thePath,
|
||||||
bool reset,
|
bool reset,
|
||||||
bool updatesOnly,
|
bool updatesOnly,
|
||||||
|
|
@ -215,10 +221,10 @@ class NormFileList
|
||||||
protected:
|
protected:
|
||||||
const char* Path() {return path;}
|
const char* Path() {return path;}
|
||||||
|
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
off_t size;
|
NormFile::Offset size;
|
||||||
FileItem* prev;
|
FileItem* prev;
|
||||||
FileItem* next;
|
FileItem* next;
|
||||||
};
|
};
|
||||||
class DirectoryItem : public FileItem
|
class DirectoryItem : public FileItem
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -431,111 +431,3 @@ unsigned char NormQuantizeRtt(double rtt)
|
||||||
return ((unsigned char)(ceil(255.0 - (13.0*log(NORM_RTT_MAX/rtt)))));
|
return ((unsigned char)(ceil(255.0 - (13.0*log(NORM_RTT_MAX/rtt)))));
|
||||||
} // end NormQuantizeRtt()
|
} // end NormQuantizeRtt()
|
||||||
|
|
||||||
NormObjectSize NormObjectSize::operator+(const NormObjectSize& size) const
|
|
||||||
{
|
|
||||||
NormObjectSize total;
|
|
||||||
total.msb = msb + size.msb;
|
|
||||||
total.lsb = lsb + size.lsb;
|
|
||||||
if ((total.lsb < lsb) || (total.lsb < size.lsb)) total.msb++;
|
|
||||||
return total;
|
|
||||||
} // end NormObjectSize::operator+(NormObjectSize id)
|
|
||||||
|
|
||||||
NormObjectSize NormObjectSize::operator-(const NormObjectSize& b) const
|
|
||||||
{
|
|
||||||
NormObjectSize result;
|
|
||||||
result.lsb = lsb - b.lsb;
|
|
||||||
result.msb = msb - b.msb;
|
|
||||||
if (lsb < b.lsb) result.msb--;
|
|
||||||
return result;
|
|
||||||
} // end NormObjectSize::operator-(NormObjectSize id)
|
|
||||||
|
|
||||||
NormObjectSize NormObjectSize::operator*(const NormObjectSize& b) const
|
|
||||||
{
|
|
||||||
UINT32 ll = (lsb & 0x0000ffff) * (b.lsb & 0x0000ffff);
|
|
||||||
UINT32 lm = (lsb & 0x0000ffff) * ((b.lsb >> 16) & 0x0000ffff);
|
|
||||||
UINT32 ml = ((lsb >> 16) & 0x0000ffff) * (b.lsb & 0x0000ffff);
|
|
||||||
UINT32 lu = (lsb & 0x0000ffff) * (UINT32)b.msb;
|
|
||||||
UINT32 mm = ((lsb >> 16) & 0x0000ffff) *
|
|
||||||
((b.lsb >> 16) & 0x0000ffff);
|
|
||||||
NormObjectSize result;
|
|
||||||
result.lsb = ll + (lm << 16) + (ml << 16);
|
|
||||||
result.msb = lu + mm + ((lm >> 16) & 0x0000ffff) +
|
|
||||||
((ml >> 16) & 0x0000ffff);
|
|
||||||
return result;
|
|
||||||
} // end NormObjectSize::operator*(NormObjectSize size)
|
|
||||||
|
|
||||||
// Note: This always rounds up if there is _any_ remainder
|
|
||||||
NormObjectSize NormObjectSize::operator/(const NormObjectSize& b) const
|
|
||||||
{
|
|
||||||
// Zero dividend is special case
|
|
||||||
if ((0 == lsb) && (0 == msb)) return NormObjectSize(0, 0);
|
|
||||||
// Zero divisor is special case
|
|
||||||
if ((0 == b.lsb) && (0 == b.msb)) return NormObjectSize(0xffff, 0xffffffff);
|
|
||||||
// Divisor >= dividend is special case
|
|
||||||
if ((b.lsb >= lsb) && (b.msb >= msb)) return NormObjectSize(0,1);
|
|
||||||
// divisor
|
|
||||||
UINT32 divisor[2];
|
|
||||||
divisor[0] = (UINT32)b.msb;
|
|
||||||
divisor[1] = b.lsb;
|
|
||||||
// dividend
|
|
||||||
UINT32 dividend[2];
|
|
||||||
dividend[0] = msb;
|
|
||||||
dividend[1] = (UINT32)lsb;
|
|
||||||
// remainder
|
|
||||||
UINT32 remainder[2];
|
|
||||||
remainder[0] = remainder[1] = 0;
|
|
||||||
unsigned int numBits = 64;
|
|
||||||
UINT32 d[2];
|
|
||||||
while (((divisor[1] > remainder[1]) && (divisor[0] == remainder[0])) ||
|
|
||||||
(divisor[0] > remainder[0]))
|
|
||||||
{
|
|
||||||
remainder[0] <<= 1;
|
|
||||||
remainder[0] |= (remainder[1] >> 31) & 0x00000001;
|
|
||||||
remainder[1] <<= 1;
|
|
||||||
remainder[1] |= (dividend[0] >> 31) & 0x00000001;
|
|
||||||
d[0] = dividend[0];
|
|
||||||
d[1] = dividend[1];
|
|
||||||
dividend[0] <<= 1;
|
|
||||||
dividend[0] |= (dividend[1] >> 31) & 0x00000001;
|
|
||||||
dividend[1] <<= 1;
|
|
||||||
numBits--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: above loop goes one step too far
|
|
||||||
// so we incr numBits, use old dividend (d)
|
|
||||||
numBits++;
|
|
||||||
UINT32 quotient[2];
|
|
||||||
quotient[0] = quotient[1] = 0;
|
|
||||||
bool extra = false;
|
|
||||||
for (unsigned int i = 0; i < numBits; i++)
|
|
||||||
{
|
|
||||||
UINT32 t[2];
|
|
||||||
t[0] = remainder[0] - divisor[0];
|
|
||||||
t[1] = remainder[1] - divisor[1];
|
|
||||||
if (remainder[1] < divisor[1]) t[0]--;
|
|
||||||
UINT32 q = ((t[0] >> 31) & 0x00000001) ^ 0x00000001;
|
|
||||||
d[0] <<= 1;
|
|
||||||
d[0] |= (d[1] >> 31) & 0x00000001;
|
|
||||||
d[1] <<= 1;
|
|
||||||
quotient[0] <<= 1;
|
|
||||||
quotient[1] = (quotient[1] << 1) | q;
|
|
||||||
if (q)
|
|
||||||
{
|
|
||||||
remainder[0] = t[0];
|
|
||||||
remainder[1] = t[1];
|
|
||||||
}
|
|
||||||
if (remainder[0] || remainder[1])
|
|
||||||
extra = true;
|
|
||||||
else
|
|
||||||
extra = false;
|
|
||||||
remainder[0] <<= 1;
|
|
||||||
remainder[0] |= (remainder[1] >> 31) & 0x00000001;
|
|
||||||
remainder[1] <<= 1;
|
|
||||||
remainder[1] |= (d[0] >> 31) & 0x00000001;
|
|
||||||
}
|
|
||||||
NormObjectSize result((UINT16)quotient[0], quotient[1]);
|
|
||||||
// If there was _any_ remainder, round up
|
|
||||||
if (extra) result++;
|
|
||||||
return result;
|
|
||||||
} // end NormObjectSize::operator/(NormObjectSize b)
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
//typedef fpos_t off_t;
|
|
||||||
typedef long off_t;
|
|
||||||
#else
|
#else
|
||||||
#include <sys/types.h> // for off_t
|
#include <sys/types.h> // for off_t
|
||||||
#endif // if/else _WIN32_WCE
|
#endif // if/else _WIN32_WCE
|
||||||
|
|
@ -23,9 +21,6 @@ typedef long off_t;
|
||||||
|
|
||||||
const UINT8 NORM_PROTOCOL_VERSION = 1;
|
const UINT8 NORM_PROTOCOL_VERSION = 1;
|
||||||
|
|
||||||
// (TBD) Alot of the "memcpy()" calls could be eliminated by
|
|
||||||
// taking advantage of the alignment of NORM messsages
|
|
||||||
|
|
||||||
const int NORM_ROBUST_FACTOR = 20; // default robust factor
|
const int NORM_ROBUST_FACTOR = 20; // default robust factor
|
||||||
|
|
||||||
// Pick a random number from 0..max
|
// Pick a random number from 0..max
|
||||||
|
|
@ -101,85 +96,66 @@ inline double NormUnquantizeRate(unsigned short rate)
|
||||||
return mantissa * pow(10.0, exponent);
|
return mantissa * pow(10.0, exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This class is used to describe object "size" and/or "offset"
|
|
||||||
// (TBD) This hokey implementation should just use "off_t" as it's
|
|
||||||
// native storage format and get rid of this custom crap !!!
|
|
||||||
// (We should just get rid of this class !!!!!!!!)
|
|
||||||
class NormObjectSize
|
class NormObjectSize
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NormObjectSize() : msb(0), lsb(0) {}
|
#ifdef WIN32
|
||||||
NormObjectSize(UINT16 upper, UINT32 lower) : msb(upper), lsb(lower) {}
|
typedef __int64 Offset;
|
||||||
NormObjectSize(UINT32 size) : msb(0), lsb(size) {}
|
#else
|
||||||
NormObjectSize(UINT16 size) : msb(0), lsb(size) {}
|
typedef off_t Offset;
|
||||||
NormObjectSize(const NormObjectSize& size) : msb(size.msb), lsb(size.lsb) {}
|
#endif
|
||||||
NormObjectSize(off_t size)
|
NormObjectSize() : size(0) {}
|
||||||
|
NormObjectSize(Offset theSize) : size(theSize) {}
|
||||||
|
NormObjectSize(UINT16 msb, UINT32 lsb)
|
||||||
{
|
{
|
||||||
lsb = (unsigned long)(size & 0x00000000ffffffff);
|
size = (Offset)lsb;
|
||||||
size >>= 32;
|
size |= (sizeof(Offset) > 4) ? (((Offset)msb) << 32): (Offset)0;
|
||||||
ASSERT(0 == (size & 0xffff0000));
|
|
||||||
msb = (unsigned short)(size & 0x0000ffff);
|
|
||||||
msb = 0;
|
|
||||||
}
|
}
|
||||||
|
Offset GetOffset() const {return size;}
|
||||||
|
UINT16 MSB() const
|
||||||
|
{return ((sizeof(Offset) > 4) ? (UINT16)((size >> 32) & 0x0000ffff) : 0);}
|
||||||
|
UINT32 LSB() const
|
||||||
|
{return ((UINT32)(size & 0xffffffff));}
|
||||||
|
|
||||||
UINT16 MSB() const {return msb;}
|
// Operators
|
||||||
UINT32 LSB() const {return lsb;}
|
bool operator==(const NormObjectSize& b) const
|
||||||
bool operator==(const NormObjectSize& size) const
|
{return (b.size == size);}
|
||||||
{return ((msb == size.msb) && (lsb == size.lsb));}
|
NormObjectSize operator+(const NormObjectSize& b) const
|
||||||
bool operator>(const NormObjectSize& size) const
|
|
||||||
{
|
{
|
||||||
return ((msb == size.msb) ?
|
NormObjectSize result(size);
|
||||||
(lsb > size.lsb) :
|
result.size += b.size;
|
||||||
(msb > size.msb));
|
return result;
|
||||||
}
|
}
|
||||||
bool operator<(const NormObjectSize& size) const
|
void operator+=(const NormObjectSize& b)
|
||||||
|
{size += b.size;}
|
||||||
|
NormObjectSize operator-(const NormObjectSize& b) const
|
||||||
{
|
{
|
||||||
return ((msb == size.msb) ?
|
NormObjectSize result(size);
|
||||||
(lsb < size.lsb) :
|
result.size -= b.size;
|
||||||
(msb < size.msb));
|
return result;
|
||||||
}
|
}
|
||||||
bool operator<=(const NormObjectSize& size) const
|
void operator-=(const NormObjectSize& b)
|
||||||
{return ((*this == size) || (*this<size));}
|
{size -= b.size;}
|
||||||
bool operator>=(const NormObjectSize& size) const
|
void operator+=(Offset increment)
|
||||||
{return ((*this == size) || (*this>size));}
|
{size += increment;}
|
||||||
bool operator!=(const NormObjectSize& size) const
|
bool operator>(const NormObjectSize& b) const
|
||||||
{return ((lsb != size.lsb) || (msb != size.msb));}
|
{return (size > b.size);}
|
||||||
NormObjectSize operator+(const NormObjectSize& size) const;
|
NormObjectSize operator*(const NormObjectSize& b) const
|
||||||
NormObjectSize operator-(const NormObjectSize& size) const;
|
|
||||||
void operator+=(UINT32 increment)
|
|
||||||
{
|
{
|
||||||
UINT32 temp32 = lsb + increment;
|
NormObjectSize result(size);
|
||||||
if (temp32 < lsb) msb++;
|
result.size *= b.size;
|
||||||
lsb = temp32;
|
return result;
|
||||||
}
|
}
|
||||||
NormObjectSize operator+(UINT32 increment) const
|
// Note: this is a "round-upwards" division operator
|
||||||
|
NormObjectSize operator/(const NormObjectSize& b) const
|
||||||
{
|
{
|
||||||
NormObjectSize total;
|
NormObjectSize result(size);
|
||||||
total.msb = msb;
|
result.size /= b.size;
|
||||||
total.lsb = lsb + increment;
|
result.size = ((result.size * b.size) < size) ? result.size + 1 : result.size;
|
||||||
if (total.lsb < lsb) total.msb++;
|
return result;
|
||||||
return total;
|
|
||||||
}
|
}
|
||||||
NormObjectSize& operator++(int)
|
|
||||||
{
|
|
||||||
lsb++;
|
|
||||||
if (0 == lsb) msb++;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
NormObjectSize operator*(const NormObjectSize& b) const;
|
|
||||||
NormObjectSize operator/(const NormObjectSize& b) const;
|
|
||||||
off_t GetOffset() const
|
|
||||||
{
|
|
||||||
|
|
||||||
off_t offset = msb;
|
|
||||||
offset <<= 32;
|
|
||||||
offset += lsb;
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UINT16 msb;
|
Offset size;
|
||||||
UINT32 lsb;
|
|
||||||
}; // end class NormObjectSize
|
}; // end class NormObjectSize
|
||||||
|
|
||||||
#ifndef _NORM_API
|
#ifndef _NORM_API
|
||||||
|
|
@ -426,9 +402,9 @@ class NormObjectMsg : public NormMsg
|
||||||
FLAG_STREAM = 0x20,
|
FLAG_STREAM = 0x20,
|
||||||
FLAG_MSG_START = 0x40
|
FLAG_MSG_START = 0x40
|
||||||
};
|
};
|
||||||
UINT16 GetSessionId() const
|
UINT16 GetInstanceId() const
|
||||||
{
|
{
|
||||||
return (ntohs(((UINT16*)buffer)[SESSION_ID_OFFSET]));
|
return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));
|
||||||
}
|
}
|
||||||
UINT8 GetGrtt() const {return ((UINT8*)buffer)[GRTT_OFFSET];}
|
UINT8 GetGrtt() const {return ((UINT8*)buffer)[GRTT_OFFSET];}
|
||||||
UINT8 GetBackoffFactor() const {return ((((UINT8*)buffer)[GSIZE_OFFSET] >> 4) & 0x0f);}
|
UINT8 GetBackoffFactor() const {return ((((UINT8*)buffer)[GSIZE_OFFSET] >> 4) & 0x0f);}
|
||||||
|
|
@ -443,9 +419,9 @@ class NormObjectMsg : public NormMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message building routines
|
// Message building routines
|
||||||
void SetSessionId(UINT16 sessionId)
|
void SetInstanceId(UINT16 instanceId)
|
||||||
{
|
{
|
||||||
((UINT16*)buffer)[SESSION_ID_OFFSET] = htons(sessionId);
|
((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);
|
||||||
}
|
}
|
||||||
void SetGrtt(UINT8 grtt) {((UINT8*)buffer)[GRTT_OFFSET] = grtt;}
|
void SetGrtt(UINT8 grtt) {((UINT8*)buffer)[GRTT_OFFSET] = grtt;}
|
||||||
void SetBackoffFactor(UINT8 backoff)
|
void SetBackoffFactor(UINT8 backoff)
|
||||||
|
|
@ -467,8 +443,8 @@ class NormObjectMsg : public NormMsg
|
||||||
protected:
|
protected:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SESSION_ID_OFFSET = MSG_OFFSET/2,
|
INSTANCE_ID_OFFSET = MSG_OFFSET/2,
|
||||||
GRTT_OFFSET = (SESSION_ID_OFFSET*2)+2,
|
GRTT_OFFSET = (INSTANCE_ID_OFFSET*2)+2,
|
||||||
BACKOFF_OFFSET = GRTT_OFFSET+1,
|
BACKOFF_OFFSET = GRTT_OFFSET+1,
|
||||||
GSIZE_OFFSET = BACKOFF_OFFSET,
|
GSIZE_OFFSET = BACKOFF_OFFSET,
|
||||||
FLAGS_OFFSET = GSIZE_OFFSET+1,
|
FLAGS_OFFSET = GSIZE_OFFSET+1,
|
||||||
|
|
@ -733,9 +709,9 @@ class NormCmdMsg : public NormMsg
|
||||||
};
|
};
|
||||||
|
|
||||||
// Message building
|
// Message building
|
||||||
void SetSessionId(UINT16 sessionId)
|
void SetInstanceId(UINT16 instanceId)
|
||||||
{
|
{
|
||||||
((UINT16*)buffer)[SESSION_ID_OFFSET] = htons(sessionId);
|
((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);
|
||||||
}
|
}
|
||||||
void SetGrtt(UINT8 quantizedGrtt)
|
void SetGrtt(UINT8 quantizedGrtt)
|
||||||
{((UINT8*)buffer)[GRTT_OFFSET] = quantizedGrtt;}
|
{((UINT8*)buffer)[GRTT_OFFSET] = quantizedGrtt;}
|
||||||
|
|
@ -751,7 +727,7 @@ class NormCmdMsg : public NormMsg
|
||||||
{((UINT8*)buffer)[FLAVOR_OFFSET] = (UINT8)flavor;}
|
{((UINT8*)buffer)[FLAVOR_OFFSET] = (UINT8)flavor;}
|
||||||
|
|
||||||
// Message processing
|
// Message processing
|
||||||
UINT16 GetSessionId() const {return (ntohs(((UINT16*)buffer)[SESSION_ID_OFFSET]));}
|
UINT16 GetInstanceId() const {return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));}
|
||||||
UINT8 GetGrtt() const {return ((UINT8*)buffer)[GRTT_OFFSET];}
|
UINT8 GetGrtt() const {return ((UINT8*)buffer)[GRTT_OFFSET];}
|
||||||
UINT8 GetBackoffFactor() const {return ((((UINT8*)buffer)[GSIZE_OFFSET] >> 4) & 0x0f);}
|
UINT8 GetBackoffFactor() const {return ((((UINT8*)buffer)[GSIZE_OFFSET] >> 4) & 0x0f);}
|
||||||
UINT8 GetGroupSize() const {return (((UINT8*)buffer)[GSIZE_OFFSET] & 0x0f);}
|
UINT8 GetGroupSize() const {return (((UINT8*)buffer)[GSIZE_OFFSET] & 0x0f);}
|
||||||
|
|
@ -761,8 +737,8 @@ class NormCmdMsg : public NormMsg
|
||||||
friend class NormMsg;
|
friend class NormMsg;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SESSION_ID_OFFSET = MSG_OFFSET/2,
|
INSTANCE_ID_OFFSET = MSG_OFFSET/2,
|
||||||
GRTT_OFFSET = (SESSION_ID_OFFSET*2)+2,
|
GRTT_OFFSET = (INSTANCE_ID_OFFSET*2)+2,
|
||||||
BACKOFF_OFFSET = GRTT_OFFSET + 1,
|
BACKOFF_OFFSET = GRTT_OFFSET + 1,
|
||||||
GSIZE_OFFSET = BACKOFF_OFFSET,
|
GSIZE_OFFSET = BACKOFF_OFFSET,
|
||||||
FLAVOR_OFFSET = GSIZE_OFFSET + 1
|
FLAVOR_OFFSET = GSIZE_OFFSET + 1
|
||||||
|
|
@ -1396,9 +1372,9 @@ class NormNackMsg : public NormMsg
|
||||||
{
|
{
|
||||||
buffer[SERVER_ID_OFFSET] = htonl(serverId);
|
buffer[SERVER_ID_OFFSET] = htonl(serverId);
|
||||||
}
|
}
|
||||||
void SetSessionId(UINT16 sessionId)
|
void SetInstanceId(UINT16 instanceId)
|
||||||
{
|
{
|
||||||
((UINT16*)buffer)[SESSION_ID_OFFSET] = htons(sessionId);
|
((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);
|
||||||
}
|
}
|
||||||
void SetGrttResponse(const struct timeval& grttResponse)
|
void SetGrttResponse(const struct timeval& grttResponse)
|
||||||
{
|
{
|
||||||
|
|
@ -1424,9 +1400,9 @@ class NormNackMsg : public NormMsg
|
||||||
{
|
{
|
||||||
return (ntohl(buffer[SERVER_ID_OFFSET]));
|
return (ntohl(buffer[SERVER_ID_OFFSET]));
|
||||||
}
|
}
|
||||||
UINT16 GetSessionId() const
|
UINT16 GetInstanceId() const
|
||||||
{
|
{
|
||||||
return (ntohs(((UINT16*)buffer)[SESSION_ID_OFFSET]));
|
return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));
|
||||||
}
|
}
|
||||||
void GetGrttResponse(struct timeval& grttResponse) const
|
void GetGrttResponse(struct timeval& grttResponse) const
|
||||||
{
|
{
|
||||||
|
|
@ -1449,8 +1425,8 @@ class NormNackMsg : public NormMsg
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SERVER_ID_OFFSET = MSG_OFFSET/4,
|
SERVER_ID_OFFSET = MSG_OFFSET/4,
|
||||||
SESSION_ID_OFFSET = ((SERVER_ID_OFFSET*4)+4)/2,
|
INSTANCE_ID_OFFSET = ((SERVER_ID_OFFSET*4)+4)/2,
|
||||||
RESERVED_OFFSET = ((SESSION_ID_OFFSET*2)+2)/2,
|
RESERVED_OFFSET = ((INSTANCE_ID_OFFSET*2)+2)/2,
|
||||||
GRTT_RESPONSE_SEC_OFFSET = ((RESERVED_OFFSET*2)+2)/4,
|
GRTT_RESPONSE_SEC_OFFSET = ((RESERVED_OFFSET*2)+2)/4,
|
||||||
GRTT_RESPONSE_USEC_OFFSET = ((GRTT_RESPONSE_SEC_OFFSET*4)+4)/4,
|
GRTT_RESPONSE_USEC_OFFSET = ((GRTT_RESPONSE_SEC_OFFSET*4)+4)/4,
|
||||||
NACK_HEADER_LEN = (GRTT_RESPONSE_USEC_OFFSET*4)+4
|
NACK_HEADER_LEN = (GRTT_RESPONSE_USEC_OFFSET*4)+4
|
||||||
|
|
@ -1472,9 +1448,9 @@ class NormAckMsg : public NormMsg
|
||||||
{
|
{
|
||||||
buffer[SERVER_ID_OFFSET] = htonl(serverId);
|
buffer[SERVER_ID_OFFSET] = htonl(serverId);
|
||||||
}
|
}
|
||||||
void SetSessionId(UINT16 sessionId)
|
void SetInstanceId(UINT16 instanceId)
|
||||||
{
|
{
|
||||||
((UINT16*)buffer)[SESSION_ID_OFFSET] = htons(sessionId);
|
((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);
|
||||||
}
|
}
|
||||||
void SetAckType(NormAck::Type ackType) {((UINT8*)buffer)[ACK_TYPE_OFFSET] = (UINT8)ackType;}
|
void SetAckType(NormAck::Type ackType) {((UINT8*)buffer)[ACK_TYPE_OFFSET] = (UINT8)ackType;}
|
||||||
void SetAckId(UINT8 ackId) {((UINT8*)buffer)[ACK_ID_OFFSET] = ackId;}
|
void SetAckId(UINT8 ackId) {((UINT8*)buffer)[ACK_ID_OFFSET] = ackId;}
|
||||||
|
|
@ -1496,9 +1472,9 @@ class NormAckMsg : public NormMsg
|
||||||
{
|
{
|
||||||
return (ntohl(buffer[SERVER_ID_OFFSET]));
|
return (ntohl(buffer[SERVER_ID_OFFSET]));
|
||||||
}
|
}
|
||||||
UINT16 GetSessionId() const
|
UINT16 GetInstanceId() const
|
||||||
{
|
{
|
||||||
return (ntohs(((UINT16*)buffer)[SESSION_ID_OFFSET]));
|
return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));
|
||||||
}
|
}
|
||||||
void GetGrttResponse(struct timeval& grttResponse) const
|
void GetGrttResponse(struct timeval& grttResponse) const
|
||||||
{
|
{
|
||||||
|
|
@ -1514,8 +1490,8 @@ class NormAckMsg : public NormMsg
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SERVER_ID_OFFSET = MSG_OFFSET/4,
|
SERVER_ID_OFFSET = MSG_OFFSET/4,
|
||||||
SESSION_ID_OFFSET = ((SERVER_ID_OFFSET*4)+4)/2,
|
INSTANCE_ID_OFFSET = ((SERVER_ID_OFFSET*4)+4)/2,
|
||||||
ACK_TYPE_OFFSET = (SESSION_ID_OFFSET*2)+2,
|
ACK_TYPE_OFFSET = (INSTANCE_ID_OFFSET*2)+2,
|
||||||
ACK_ID_OFFSET = ACK_TYPE_OFFSET + 1,
|
ACK_ID_OFFSET = ACK_TYPE_OFFSET + 1,
|
||||||
GRTT_RESPONSE_SEC_OFFSET = (ACK_ID_OFFSET + 1)/4,
|
GRTT_RESPONSE_SEC_OFFSET = (ACK_ID_OFFSET + 1)/4,
|
||||||
GRTT_RESPONSE_USEC_OFFSET = ((GRTT_RESPONSE_SEC_OFFSET*4)+4)/4,
|
GRTT_RESPONSE_USEC_OFFSET = ((GRTT_RESPONSE_SEC_OFFSET*4)+4)/4,
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ NormCCNode::~NormCCNode()
|
||||||
|
|
||||||
|
|
||||||
NormServerNode::NormServerNode(class NormSession& theSession, NormNodeId nodeId)
|
NormServerNode::NormServerNode(class NormSession& theSession, NormNodeId nodeId)
|
||||||
: NormNode(theSession, nodeId), session_id(0), synchronized(false), sync_id(0),
|
: NormNode(theSession, nodeId), instance_id(0), synchronized(false), sync_id(0),
|
||||||
max_pending_range(256), is_open(false), segment_size(0), ndata(0), nparity(0),
|
max_pending_range(256), is_open(false), segment_size(0), ndata(0), nparity(0),
|
||||||
repair_boundary(BLOCK_BOUNDARY), erasure_loc(NULL),
|
repair_boundary(BLOCK_BOUNDARY), erasure_loc(NULL),
|
||||||
retrieval_loc(NULL), retrieval_pool(NULL),
|
retrieval_loc(NULL), retrieval_pool(NULL),
|
||||||
|
|
@ -100,9 +100,9 @@ NormServerNode::~NormServerNode()
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NormServerNode::Open(UINT16 sessionId)
|
bool NormServerNode::Open(UINT16 instanceId)
|
||||||
{
|
{
|
||||||
session_id = sessionId;
|
instance_id = instanceId;
|
||||||
if (!rx_table.Init(max_pending_range))
|
if (!rx_table.Init(max_pending_range))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() rx_table init error\n");
|
DMSG(0, "NormServerNode::Open() rx_table init error\n");
|
||||||
|
|
@ -123,6 +123,7 @@ bool NormServerNode::Open(UINT16 sessionId)
|
||||||
}
|
}
|
||||||
is_open = true;
|
is_open = true;
|
||||||
synchronized = false;
|
synchronized = false;
|
||||||
|
resync_count = 0; // reset resync_count
|
||||||
return true;
|
return true;
|
||||||
} // end NormServerNode::Open()
|
} // end NormServerNode::Open()
|
||||||
|
|
||||||
|
|
@ -178,7 +179,7 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
||||||
|
|
||||||
if (!block_pool.Init(numBlocks, blockSize))
|
if (!block_pool.Init(numBlocks, blockSize))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() block_pool init error\n");
|
DMSG(0, "NormServerNode::AllocateBuffers() block_pool init error\n");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -188,7 +189,7 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
||||||
// a NormStreamObject
|
// a NormStreamObject
|
||||||
if (!segment_pool.Init(numSegments, segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()+1))
|
if (!segment_pool.Init(numSegments, segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()+1))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() segment_pool init error\n");
|
DMSG(0, "NormServerNode::AllocateBuffers() segment_pool init error\n");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +199,7 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
||||||
// needed for block decoding (new rx buffer mgmt scheme)
|
// needed for block decoding (new rx buffer mgmt scheme)
|
||||||
if (!(retrieval_pool = new char*[numData]))
|
if (!(retrieval_pool = new char*[numData]))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() new retrieval_pool error: %s\n", GetErrorString());
|
DMSG(0, "NormServerNode::AllocateBuffers() new retrieval_pool error: %s\n", GetErrorString());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +209,7 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
||||||
char* s = new char[segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()];
|
char* s = new char[segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()];
|
||||||
if (NULL == s)
|
if (NULL == s)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() new retrieval segment error: %s\n", GetErrorString());
|
DMSG(0, "NormServerNode::AllocateBuffers() new retrieval segment error: %s\n", GetErrorString());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -218,20 +219,20 @@ bool NormServerNode::AllocateBuffers(UINT16 segmentSize,
|
||||||
|
|
||||||
if (!(retrieval_loc = new UINT16[numData]))
|
if (!(retrieval_loc = new UINT16[numData]))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() retrieval_loc allocation error: %s\n", GetErrorString());
|
DMSG(0, "NormServerNode::AllocateBuffers() retrieval_loc allocation error: %s\n", GetErrorString());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decoder.Init(numParity, segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()))
|
if (!decoder.Init(numParity, segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() decoder init error\n");
|
DMSG(0, "NormServerNode::AllocateBuffers() decoder init error\n");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!(erasure_loc = new UINT16[numParity]))
|
if (!(erasure_loc = new UINT16[numParity]))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() erasure_loc allocation error: %s\n", GetErrorString());
|
DMSG(0, "NormServerNode::AllocateBuffers() erasure_loc allocation error: %s\n", GetErrorString());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -966,7 +967,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NormObject* obj = NULL;
|
NormObject* obj = NULL;
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
|
|
@ -1006,6 +1007,8 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
|
|
||||||
if (obj)
|
if (obj)
|
||||||
{
|
{
|
||||||
|
rx_table.Insert(obj);
|
||||||
|
obj->Retain();
|
||||||
NormFtiExtension fti;
|
NormFtiExtension fti;
|
||||||
while (msg.GetNextExtension(fti))
|
while (msg.GetNextExtension(fti))
|
||||||
{
|
{
|
||||||
|
|
@ -1021,8 +1024,6 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
session.Notify(NormController::RX_OBJECT_NEW, this, obj);
|
session.Notify(NormController::RX_OBJECT_NEW, this, obj);
|
||||||
if (obj->Accepted())
|
if (obj->Accepted())
|
||||||
{
|
{
|
||||||
rx_table.Insert(obj);
|
|
||||||
obj->Retain();
|
|
||||||
// (TBD) Do I _need_ to call "StreamUpdateStatus()" here?
|
// (TBD) Do I _need_ to call "StreamUpdateStatus()" here?
|
||||||
if (obj->IsStream())
|
if (obj->IsStream())
|
||||||
(static_cast<NormStreamObject*>(obj))->StreamUpdateStatus(blockId);
|
(static_cast<NormStreamObject*>(obj))->StreamUpdateStatus(blockId);
|
||||||
|
|
@ -1031,12 +1032,14 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DMSG(0, "NormServerNode::HandleObjectMessage() object not accepted\n");
|
||||||
DeleteObject(obj);
|
DeleteObject(obj);
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DMSG(0, "NormServerNode::HandleObjectMessage() error opening object\n");
|
||||||
DeleteObject(obj);
|
DeleteObject(obj);
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1608,7 +1611,7 @@ bool NormServerNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
|
||||||
}
|
}
|
||||||
// Queue NACK for transmission
|
// Queue NACK for transmission
|
||||||
nack->SetServerId(GetId());
|
nack->SetServerId(GetId());
|
||||||
nack->SetSessionId(session_id);
|
nack->SetInstanceId(instance_id);
|
||||||
// GRTT response is deferred until transmit time
|
// GRTT response is deferred until transmit time
|
||||||
|
|
||||||
if (unicast_nacks)
|
if (unicast_nacks)
|
||||||
|
|
@ -1742,7 +1745,7 @@ bool NormServerNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
|
||||||
NormObject* objMax = rx_table.Find(max_pending_object);
|
NormObject* objMax = rx_table.Find(max_pending_object);
|
||||||
if (NULL != objMax)
|
if (NULL != objMax)
|
||||||
{
|
{
|
||||||
NormSegmentId segMax = objMax->GetMaxPendingSegmentId();
|
/*NormSegmentId segMax = objMax->GetMaxPendingSegmentId();
|
||||||
if (0 != segMax)
|
if (0 != segMax)
|
||||||
RepairCheck(NormObject::THRU_SEGMENT,
|
RepairCheck(NormObject::THRU_SEGMENT,
|
||||||
max_pending_object,
|
max_pending_object,
|
||||||
|
|
@ -1752,7 +1755,10 @@ bool NormServerNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
|
||||||
RepairCheck(NormObject::TO_BLOCK,
|
RepairCheck(NormObject::TO_BLOCK,
|
||||||
max_pending_object,
|
max_pending_object,
|
||||||
objMax->GetMaxPendingBlockId(),
|
objMax->GetMaxPendingBlockId(),
|
||||||
0);
|
0);*/
|
||||||
|
// Let's try this instead
|
||||||
|
RepairCheck(NormObject::THRU_OBJECT, // (TBD) thru object???
|
||||||
|
max_pending_object, 0, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
RepairCheck(NormObject::TO_BLOCK, // (TBD) thru object???
|
RepairCheck(NormObject::TO_BLOCK, // (TBD) thru object???
|
||||||
|
|
@ -1837,7 +1843,7 @@ bool NormServerNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
|
||||||
}
|
}
|
||||||
ack->Init();
|
ack->Init();
|
||||||
ack->SetServerId(GetId());
|
ack->SetServerId(GetId());
|
||||||
ack->SetSessionId(session_id);
|
ack->SetInstanceId(instance_id);
|
||||||
ack->SetAckType(NormAck::CC);
|
ack->SetAckType(NormAck::CC);
|
||||||
ack->SetAckId(0);
|
ack->SetAckId(0);
|
||||||
|
|
||||||
|
|
@ -1878,7 +1884,7 @@ bool NormServerNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
ack->Init();
|
ack->Init();
|
||||||
ack->SetServerId(GetId());
|
ack->SetServerId(GetId());
|
||||||
ack->SetSessionId(session_id);
|
ack->SetInstanceId(instance_id);
|
||||||
ack->SetAckId(0);
|
ack->SetAckId(0);
|
||||||
AttachCCFeedback(*ack);
|
AttachCCFeedback(*ack);
|
||||||
ack->SetObjectId(watermark_object_id);
|
ack->SetObjectId(watermark_object_id);
|
||||||
|
|
|
||||||
|
|
@ -245,8 +245,8 @@ class NormServerNode : public NormNode
|
||||||
void HandleNackMessage(const NormNackMsg& nack);
|
void HandleNackMessage(const NormNackMsg& nack);
|
||||||
void HandleAckMessage(const NormAckMsg& ack);
|
void HandleAckMessage(const NormAckMsg& ack);
|
||||||
|
|
||||||
bool Open(UINT16 sessionId);
|
bool Open(UINT16 instanceId);
|
||||||
UINT16 GetSessionId() {return session_id;}
|
UINT16 GetInstanceId() {return instance_id;}
|
||||||
bool IsOpen() const {return is_open;}
|
bool IsOpen() const {return is_open;}
|
||||||
void Close();
|
void Close();
|
||||||
bool AllocateBuffers(UINT16 segmentSize, UINT16 numData, UINT16 numParity);
|
bool AllocateBuffers(UINT16 segmentSize, UINT16 numData, UINT16 numParity);
|
||||||
|
|
@ -371,7 +371,7 @@ class NormServerNode : public NormNode
|
||||||
void AttachCCFeedback(NormAckMsg& ack);
|
void AttachCCFeedback(NormAckMsg& ack);
|
||||||
void HandleRepairContent(const UINT32* buffer, UINT16 bufferLen);
|
void HandleRepairContent(const UINT32* buffer, UINT16 bufferLen);
|
||||||
|
|
||||||
UINT16 session_id;
|
UINT16 instance_id;
|
||||||
bool synchronized;
|
bool synchronized;
|
||||||
NormObjectId sync_id; // only valid if(synchronized)
|
NormObjectId sync_id; // only valid if(synchronized)
|
||||||
NormObjectId next_id; // only valid if(synchronized)
|
NormObjectId next_id; // only valid if(synchronized)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,10 @@ void NormObject::Release()
|
||||||
if (reference_count)
|
if (reference_count)
|
||||||
reference_count--;
|
reference_count--;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DMSG(0, "NormObject::Release() releasing non-retained object?!\n");
|
DMSG(0, "NormObject::Release() releasing non-retained object?!\n");
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
if (0 == reference_count) delete this;
|
if (0 == reference_count) delete this;
|
||||||
} // end NormObject::Release()
|
} // end NormObject::Release()
|
||||||
|
|
||||||
|
|
@ -109,11 +112,11 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute number of segments and coding blocks for the object
|
// Compute number of segments and coding blocks for the object
|
||||||
// (Note NormObjectSize divide operator always rounds _up_)
|
// (Note NormObjectSize divide operator always rounds _upwards_)
|
||||||
NormObjectSize numSegments = objectSize / NormObjectSize(segmentSize);
|
NormObjectSize numSegments = objectSize / NormObjectSize(segmentSize);
|
||||||
NormObjectSize numBlocks = numSegments / NormObjectSize(numData);
|
NormObjectSize numBlocks = numSegments / NormObjectSize(numData);
|
||||||
ASSERT(0 == numBlocks.MSB());
|
ASSERT(0 == numBlocks.MSB());
|
||||||
|
|
||||||
if (!block_buffer.Init(numBlocks.LSB()))
|
if (!block_buffer.Init(numBlocks.LSB()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormObject::Open() init block_buffer error\n");
|
DMSG(0, "NormObject::Open() init block_buffer error\n");
|
||||||
|
|
@ -124,7 +127,8 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
// Init pending_mask (everything pending)
|
// Init pending_mask (everything pending)
|
||||||
if (!pending_mask.Init(numBlocks.LSB(), 0xffffffff))
|
if (!pending_mask.Init(numBlocks.LSB(), 0xffffffff))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormObject::Open() init pending_mask error\n");
|
DMSG(0, "NormObject::Open() init pending_mask (%lu) error: %s\n",
|
||||||
|
numBlocks.GetOffset(), GetErrorString());
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -206,7 +210,42 @@ void NormObject::Close()
|
||||||
pending_mask.Destroy();
|
pending_mask.Destroy();
|
||||||
block_buffer.Destroy();
|
block_buffer.Destroy();
|
||||||
segment_size = 0;
|
segment_size = 0;
|
||||||
} // end NormObject::Close();
|
} // end NormObject::Close()
|
||||||
|
|
||||||
|
NormObjectSize NormObject::GetBytesPending() const
|
||||||
|
{
|
||||||
|
NormObjectSize bytesCompleted;
|
||||||
|
NormBlockId nextId;
|
||||||
|
if (GetFirstPending(nextId))
|
||||||
|
{
|
||||||
|
NormObjectSize largeBlockBytes = NormObjectSize(large_block_size) *
|
||||||
|
NormObjectSize(segment_size);
|
||||||
|
NormObjectSize smallBlockBytes = NormObjectSize(small_block_size) *
|
||||||
|
NormObjectSize(segment_size);
|
||||||
|
NormObjectSize lastBlockBytes = smallBlockBytes - NormObjectSize(segment_size) +
|
||||||
|
NormObjectSize(final_segment_size);
|
||||||
|
NormObjectSize pendingBytes(0);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
NormBlock* block = block_buffer.Find(nextId);
|
||||||
|
if (block)
|
||||||
|
pendingBytes += block->GetBytesPending(GetBlockSize(nextId), segment_size,
|
||||||
|
final_block_id, final_segment_size);
|
||||||
|
else if ((UINT32)nextId < large_block_count)
|
||||||
|
pendingBytes += largeBlockBytes;
|
||||||
|
else if (nextId == final_block_id)
|
||||||
|
pendingBytes += lastBlockBytes;
|
||||||
|
else
|
||||||
|
pendingBytes += smallBlockBytes;
|
||||||
|
nextId++;
|
||||||
|
} while (GetNextPending(nextId));
|
||||||
|
return pendingBytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NormObjectSize(0);
|
||||||
|
}
|
||||||
|
} // end NormObject::GetBytesCompleted()
|
||||||
|
|
||||||
// Used by server
|
// Used by server
|
||||||
bool NormObject::HandleInfoRequest()
|
bool NormObject::HandleInfoRequest()
|
||||||
|
|
@ -1732,7 +1771,7 @@ NormFileObject::NormFileObject(class NormSession& theSession,
|
||||||
class NormServerNode* theServer,
|
class NormServerNode* theServer,
|
||||||
const NormObjectId& objectId)
|
const NormObjectId& objectId)
|
||||||
: NormObject(FILE, theSession, theServer, objectId),
|
: NormObject(FILE, theSession, theServer, objectId),
|
||||||
large_block_length(0,0), small_block_length(0,0)
|
large_block_length(0), small_block_length(0)
|
||||||
{
|
{
|
||||||
path[0] = '\0';
|
path[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
@ -1775,7 +1814,7 @@ bool NormFileObject::Open(const char* thePath,
|
||||||
// We're sending this file
|
// We're sending this file
|
||||||
if (file.Open(thePath, O_RDONLY))
|
if (file.Open(thePath, O_RDONLY))
|
||||||
{
|
{
|
||||||
off_t size = file.GetSize();
|
NormObjectSize::Offset size = file.GetSize();
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
if (!NormObject::Open(NormObjectSize(size),
|
if (!NormObject::Open(NormObjectSize(size),
|
||||||
|
|
@ -1861,7 +1900,7 @@ bool NormFileObject::WriteSegment(NormBlockId blockId,
|
||||||
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
||||||
segmentSize*segmentId;
|
segmentSize*segmentId;
|
||||||
}
|
}
|
||||||
off_t offset = segmentOffset.GetOffset();
|
NormFile::Offset offset = segmentOffset.GetOffset();
|
||||||
if (offset != file.GetOffset())
|
if (offset != file.GetOffset())
|
||||||
{
|
{
|
||||||
if (!file.Seek(offset)) return false;
|
if (!file.Seek(offset)) return false;
|
||||||
|
|
@ -1903,9 +1942,7 @@ UINT16 NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
||||||
segmentSize*segmentId;
|
segmentSize*segmentId;
|
||||||
}
|
}
|
||||||
//off_t offsetScaleMSB = 0xffffffff + 1; // yuk! can't we do better
|
NormFile::Offset offset = segmentOffset.GetOffset();
|
||||||
//off_t offset = (off_t)segmentOffset.LSB() + ((off_t)segmentOffset.MSB() * offsetScaleMSB);
|
|
||||||
off_t offset = segmentOffset.GetOffset();
|
|
||||||
if (offset != file.GetOffset())
|
if (offset != file.GetOffset())
|
||||||
{
|
{
|
||||||
if (!file.Seek(offset))
|
if (!file.Seek(offset))
|
||||||
|
|
@ -1952,7 +1989,7 @@ NormDataObject::NormDataObject(class NormSession& theSession,
|
||||||
class NormServerNode* theServer,
|
class NormServerNode* theServer,
|
||||||
const NormObjectId& objectId)
|
const NormObjectId& objectId)
|
||||||
: NormObject(DATA, theSession, theServer, objectId),
|
: NormObject(DATA, theSession, theServer, objectId),
|
||||||
large_block_length(0,0), small_block_length(0,0),
|
large_block_length(0), small_block_length(0),
|
||||||
data_ptr(NULL), data_max(0), data_released(false)
|
data_ptr(NULL), data_max(0), data_released(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -2709,9 +2746,9 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStar
|
||||||
{
|
{
|
||||||
if (stream_closing)
|
if (stream_closing)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Read() attempted to read from closed stream\n");
|
DMSG(4, "NormStreamObject::Read() attempted to read from closed stream\n");
|
||||||
*buflen = 0;
|
*buflen = 0;
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
Retain();
|
Retain();
|
||||||
SetNotifyOnUpdate(true); // reset notification when streams are read
|
SetNotifyOnUpdate(true); // reset notification when streams are read
|
||||||
|
|
@ -3220,7 +3257,7 @@ char* NormSimObject::RetrieveSegment(NormBlockId blockId,
|
||||||
|
|
||||||
NormObjectTable::NormObjectTable()
|
NormObjectTable::NormObjectTable()
|
||||||
: table((NormObject**)NULL), range_max(0), range(0),
|
: table((NormObject**)NULL), range_max(0), range(0),
|
||||||
count(0), size(0,0)
|
count(0), size(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,8 @@ class NormObject
|
||||||
small_block_size);
|
small_block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NormObjectSize GetBytesPending() const;
|
||||||
|
|
||||||
bool IsPending(bool flush = true) const;
|
bool IsPending(bool flush = true) const;
|
||||||
bool IsRepairPending() const;
|
bool IsRepairPending() const;
|
||||||
bool IsPendingInfo() {return pending_info;}
|
bool IsPendingInfo() {return pending_info;}
|
||||||
|
|
@ -542,7 +544,7 @@ class NormObjectTable
|
||||||
NormObjectId RangeHi() const {return range_hi;}
|
NormObjectId RangeHi() const {return range_hi;}
|
||||||
bool IsEmpty() const {return (0 == range);}
|
bool IsEmpty() const {return (0 == range);}
|
||||||
UINT32 Count() const {return count;}
|
UINT32 Count() const {return count;}
|
||||||
const NormObjectSize& Size() const {return size;}
|
const NormObjectSize& GetSize() const {return size;}
|
||||||
|
|
||||||
class Iterator
|
class Iterator
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -474,6 +474,34 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
|
||||||
return true;
|
return true;
|
||||||
} // end NormBlock::AppendRepairAdv()
|
} // end NormBlock::AppendRepairAdv()
|
||||||
|
|
||||||
|
NormObjectSize NormBlock::GetBytesPending(UINT16 numData,
|
||||||
|
UINT16 segmentSize,
|
||||||
|
NormBlockId finalBlockId,
|
||||||
|
UINT16 finalSegmentSize) const
|
||||||
|
{
|
||||||
|
NormObjectSize pendingBytes(0);
|
||||||
|
NormSegmentId nextId;
|
||||||
|
if (GetFirstPending(nextId))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (nextId < numData)
|
||||||
|
pendingBytes += NormObjectSize(segmentSize);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
nextId++;
|
||||||
|
} while (GetNextPending(nextId));
|
||||||
|
}
|
||||||
|
// Correct for final_segment_size, if applicable
|
||||||
|
if ((id == finalBlockId) &&
|
||||||
|
(IsPending(numData - 1)))
|
||||||
|
{
|
||||||
|
pendingBytes -= NormObjectSize(segmentSize);
|
||||||
|
pendingBytes += NormObjectSize(finalSegmentSize);
|
||||||
|
}
|
||||||
|
return pendingBytes;
|
||||||
|
} // end NormBlock::GetBytesPending()
|
||||||
|
|
||||||
// Called by client
|
// Called by client
|
||||||
// (TBD) this should return true iff something appended, false otherwise
|
// (TBD) this should return true iff something appended, false otherwise
|
||||||
bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
|
bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
|
||||||
|
|
|
||||||
|
|
@ -219,6 +219,11 @@ class NormBlock
|
||||||
bool IsTransmitPending() const
|
bool IsTransmitPending() const
|
||||||
{return (pending_mask.IsSet() || repair_mask.IsSet());}
|
{return (pending_mask.IsSet() || repair_mask.IsSet());}
|
||||||
|
|
||||||
|
NormObjectSize GetBytesPending(UINT16 numData,
|
||||||
|
UINT16 segmentSize,
|
||||||
|
NormBlockId finalBlockId,
|
||||||
|
UINT16 finalSegmentSize) const;
|
||||||
|
|
||||||
bool AppendRepairRequest(NormNackMsg& nack,
|
bool AppendRepairRequest(NormNackMsg& nack,
|
||||||
UINT16 numData,
|
UINT16 numData,
|
||||||
UINT16 numParity,
|
UINT16 numParity,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
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),
|
||||||
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), session_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),
|
||||||
next_tx_object_id(0), tx_cache_count_min(8), tx_cache_count_max(256),
|
next_tx_object_id(0), tx_cache_count_min(8), tx_cache_count_max(256),
|
||||||
tx_cache_size_max((UINT32)20*1024*1024),
|
tx_cache_size_max((UINT32)20*1024*1024),
|
||||||
|
|
@ -269,7 +269,8 @@ void NormSession::SetTxRateBounds(double rateMin, double rateMax)
|
||||||
} // end NormSession::SetTxRateBounds()
|
} // end NormSession::SetTxRateBounds()
|
||||||
|
|
||||||
|
|
||||||
bool NormSession::StartServer(UINT32 bufferSpace,
|
bool NormSession::StartServer(UINT16 instanceId,
|
||||||
|
UINT32 bufferSpace,
|
||||||
UINT16 segmentSize,
|
UINT16 segmentSize,
|
||||||
UINT16 numData,
|
UINT16 numData,
|
||||||
UINT16 numParity,
|
UINT16 numParity,
|
||||||
|
|
@ -337,6 +338,7 @@ bool NormSession::StartServer(UINT32 bufferSpace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance_id = instanceId;
|
||||||
segment_size = segmentSize;
|
segment_size = segmentSize;
|
||||||
sent_rate = 0.0;
|
sent_rate = 0.0;
|
||||||
prev_update_time.tv_sec = prev_update_time.tv_usec = 0;
|
prev_update_time.tv_sec = prev_update_time.tv_usec = 0;
|
||||||
|
|
@ -622,6 +624,10 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
||||||
LocalNodeId());
|
LocalNodeId());
|
||||||
|
|
||||||
|
Notify(NormController::TX_FLUSH_COMPLETED,
|
||||||
|
(NormServerNode*)NULL,
|
||||||
|
(NormObject*)NULL);
|
||||||
flush_count++;
|
flush_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -993,7 +999,7 @@ bool NormSession::QueueTxObject(NormObject* obj)
|
||||||
unsigned long count = tx_table.Count();
|
unsigned long count = tx_table.Count();
|
||||||
while ((count >= tx_cache_count_min) &&
|
while ((count >= tx_cache_count_min) &&
|
||||||
((count >= tx_cache_count_max) ||
|
((count >= tx_cache_count_max) ||
|
||||||
((tx_table.Size() + obj->GetSize()) > tx_cache_size_max)))
|
((tx_table.GetSize() + obj->GetSize()) > tx_cache_size_max)))
|
||||||
{
|
{
|
||||||
// Remove oldest non-pending
|
// Remove oldest non-pending
|
||||||
NormObject* oldest = tx_table.Find(tx_table.RangeLo());
|
NormObject* oldest = tx_table.Find(tx_table.RangeLo());
|
||||||
|
|
@ -1172,10 +1178,7 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
"CMD(REPAIR_ADV)",
|
"CMD(REPAIR_ADV)",
|
||||||
"CMD(ACK_REQ)",
|
"CMD(ACK_REQ)",
|
||||||
"CMD(APP)"
|
"CMD(APP)"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const char* REQ_NAME[] =
|
static const char* REQ_NAME[] =
|
||||||
{
|
{
|
||||||
"INVALID",
|
"INVALID",
|
||||||
|
|
@ -1202,26 +1205,26 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
#else
|
#else
|
||||||
struct tm* ct = gmtime((time_t*)¤tTime.tv_sec);
|
struct tm* ct = gmtime((time_t*)¤tTime.tv_sec);
|
||||||
#endif // if/else _WIN32_WCE
|
#endif // if/else _WIN32_WCE
|
||||||
DMSG(0, "trace>%02d:%02d:%02d.%06lu node>%lu %s>%s seq>%hu ",
|
DMSG(0, "trace>%02d:%02d:%02d.%06lu node>%lu %s>%s ",
|
||||||
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec,
|
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec,
|
||||||
(UINT32)localId, status, addr.GetHostString(), seq);
|
(UINT32)localId, status, addr.GetHostString());
|
||||||
bool clrFlag = false;
|
bool clrFlag = false;
|
||||||
switch (msgType)
|
switch (msgType)
|
||||||
{
|
{
|
||||||
case NormMsg::INFO:
|
case NormMsg::INFO:
|
||||||
{
|
{
|
||||||
const NormInfoMsg& info = (const NormInfoMsg&)msg;
|
const NormInfoMsg& info = (const NormInfoMsg&)msg;
|
||||||
DMSG(0, "INFO obj>%hu ", (UINT16)info.GetObjectId());
|
DMSG(0, "inst>%hu seq>%hu INFO obj>%hu ",
|
||||||
|
info.GetInstanceId(), seq, (UINT16)info.GetObjectId());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NormMsg::DATA:
|
case NormMsg::DATA:
|
||||||
{
|
{
|
||||||
const NormDataMsg& data = (const NormDataMsg&)msg;
|
const NormDataMsg& data = (const NormDataMsg&)msg;
|
||||||
if (data.IsData())
|
DMSG(0, "inst>%hu seq>%hu %s obj>%hu blk>%lu seg>%hu ",
|
||||||
DMSG(0, "DATA ");
|
data.GetInstanceId(),
|
||||||
else
|
seq,
|
||||||
DMSG(0, "PRTY ");
|
data.IsData() ? "DATA" : "PRTY",
|
||||||
DMSG(0, "obj>%hu blk>%lu seg>%hu ",
|
|
||||||
(UINT16)data.GetObjectId(),
|
(UINT16)data.GetObjectId(),
|
||||||
(UINT32)data.GetFecBlockId(),
|
(UINT32)data.GetFecBlockId(),
|
||||||
(UINT16)data.GetFecSymbolId());
|
(UINT16)data.GetFecSymbolId());
|
||||||
|
|
@ -1242,8 +1245,9 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
}
|
}
|
||||||
case NormMsg::CMD:
|
case NormMsg::CMD:
|
||||||
{
|
{
|
||||||
NormCmdMsg::Flavor flavor = ((const NormCmdMsg&)msg).GetFlavor();
|
const NormCmdMsg& cmd = static_cast<const NormCmdMsg&>(msg);
|
||||||
DMSG(0, "%s ", CMD_NAME[flavor]);
|
NormCmdMsg::Flavor flavor = cmd.GetFlavor();
|
||||||
|
DMSG(0, "inst>%hu seq>%hu %s ", cmd.GetInstanceId(), seq, CMD_NAME[flavor]);
|
||||||
switch (flavor)
|
switch (flavor)
|
||||||
{
|
{
|
||||||
case NormCmdMsg::ACK_REQ:
|
case NormCmdMsg::ACK_REQ:
|
||||||
|
|
@ -1255,7 +1259,8 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
}
|
}
|
||||||
case NormCmdMsg::SQUELCH:
|
case NormCmdMsg::SQUELCH:
|
||||||
{
|
{
|
||||||
const NormCmdSquelchMsg& squelch = (const NormCmdSquelchMsg&)msg;
|
const NormCmdSquelchMsg& squelch =
|
||||||
|
static_cast<const NormCmdSquelchMsg&>(msg);
|
||||||
DMSG(0, " obj>%hu blk>%lu seg>%hu ",
|
DMSG(0, " obj>%hu blk>%lu seg>%hu ",
|
||||||
(UINT16)squelch.GetObjectId(),
|
(UINT16)squelch.GetObjectId(),
|
||||||
(UINT32)squelch.GetFecBlockId(),
|
(UINT32)squelch.GetFecBlockId(),
|
||||||
|
|
@ -1264,7 +1269,8 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
}
|
}
|
||||||
case NormCmdMsg::FLUSH:
|
case NormCmdMsg::FLUSH:
|
||||||
{
|
{
|
||||||
const NormCmdFlushMsg& flush = (const NormCmdFlushMsg&)msg;
|
const NormCmdFlushMsg& flush =
|
||||||
|
static_cast<const NormCmdFlushMsg&>(msg);
|
||||||
DMSG(0, " obj>%hu blk>%lu seg>%hu ",
|
DMSG(0, " obj>%hu blk>%lu seg>%hu ",
|
||||||
(UINT16)flush.GetObjectId(),
|
(UINT16)flush.GetObjectId(),
|
||||||
(UINT32)flush.GetFecBlockId(),
|
(UINT32)flush.GetFecBlockId(),
|
||||||
|
|
@ -1273,7 +1279,8 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
}
|
}
|
||||||
case NormCmdMsg::CC:
|
case NormCmdMsg::CC:
|
||||||
{
|
{
|
||||||
const NormCmdCCMsg& cc = (const NormCmdCCMsg&)msg;
|
const NormCmdCCMsg& cc =
|
||||||
|
static_cast<const NormCmdCCMsg&>(msg);
|
||||||
DMSG(0, " seq>%u ", cc.GetCCSequence());
|
DMSG(0, " seq>%u ", cc.GetCCSequence());
|
||||||
NormHeaderExtension ext;
|
NormHeaderExtension ext;
|
||||||
while (cc.GetNextExtension(ext))
|
while (cc.GetNextExtension(ext))
|
||||||
|
|
@ -1382,12 +1389,12 @@ void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
|
||||||
NormServerNode* theServer = (NormServerNode*)server_tree.FindNodeById(sourceId);
|
NormServerNode* theServer = (NormServerNode*)server_tree.FindNodeById(sourceId);
|
||||||
if (theServer)
|
if (theServer)
|
||||||
{
|
{
|
||||||
if (msg.GetSessionId() != theServer->GetSessionId())
|
if (msg.GetInstanceId() != theServer->GetInstanceId())
|
||||||
{
|
{
|
||||||
DMSG(2, "NormSession::ClientHandleObjectMessage() node>%lu server>%lu sessionId change - resyncing.\n",
|
DMSG(2, "NormSession::ClientHandleObjectMessage() node>%lu server>%lu instanceId change - resyncing.\n",
|
||||||
LocalNodeId(), theServer->GetId());
|
LocalNodeId(), theServer->GetId());
|
||||||
theServer->Close();
|
theServer->Close();
|
||||||
if (!theServer->Open(msg.GetSessionId()))
|
if (!theServer->Open(msg.GetInstanceId()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::ClientHandleObjectMessage() node>%lu error re-opening NormServerNode\n");
|
DMSG(0, "NormSession::ClientHandleObjectMessage() node>%lu error re-opening NormServerNode\n");
|
||||||
// (TBD) notify application of error
|
// (TBD) notify application of error
|
||||||
|
|
@ -1400,7 +1407,7 @@ void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
|
||||||
if ((theServer = new NormServerNode(*this, msg.GetSourceId())))
|
if ((theServer = new NormServerNode(*this, msg.GetSourceId())))
|
||||||
{
|
{
|
||||||
Notify(NormController::REMOTE_SERVER_NEW, theServer, NULL);
|
Notify(NormController::REMOTE_SERVER_NEW, theServer, NULL);
|
||||||
if (theServer->Open(msg.GetSessionId()))
|
if (theServer->Open(msg.GetInstanceId()))
|
||||||
{
|
{
|
||||||
server_tree.AttachNode(theServer);
|
server_tree.AttachNode(theServer);
|
||||||
theServer->Retain();
|
theServer->Retain();
|
||||||
|
|
@ -1438,12 +1445,12 @@ void NormSession::ClientHandleCommand(const struct timeval& currentTime,
|
||||||
NormServerNode* theServer = (NormServerNode*)server_tree.FindNodeById(sourceId);
|
NormServerNode* theServer = (NormServerNode*)server_tree.FindNodeById(sourceId);
|
||||||
if (theServer)
|
if (theServer)
|
||||||
{
|
{
|
||||||
if (cmd.GetSessionId() != theServer->GetSessionId())
|
if (cmd.GetInstanceId() != theServer->GetInstanceId())
|
||||||
{
|
{
|
||||||
DMSG(2, "NormSession::ClientHandleCommand() node>%lu server>%lu sessionId change - resyncing.\n",
|
DMSG(2, "NormSession::ClientHandleCommand() node>%lu server>%lu instanceId change - resyncing.\n",
|
||||||
LocalNodeId(), theServer->GetId());
|
LocalNodeId(), theServer->GetId());
|
||||||
theServer->Close();
|
theServer->Close();
|
||||||
if (!theServer->Open(cmd.GetSessionId()))
|
if (!theServer->Open(cmd.GetInstanceId()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::ClientHandleCommand() node>%lu error re-opening NormServerNode\n");
|
DMSG(0, "NormSession::ClientHandleCommand() node>%lu error re-opening NormServerNode\n");
|
||||||
// (TBD) notify application of error
|
// (TBD) notify application of error
|
||||||
|
|
@ -1457,7 +1464,8 @@ void NormSession::ClientHandleCommand(const struct timeval& currentTime,
|
||||||
// LocalNodeId());
|
// LocalNodeId());
|
||||||
if ((theServer = new NormServerNode(*this, cmd.GetSourceId())))
|
if ((theServer = new NormServerNode(*this, cmd.GetSourceId())))
|
||||||
{
|
{
|
||||||
if (theServer->Open(cmd.GetSessionId()))
|
Notify(NormController::REMOTE_SERVER_NEW, theServer, NULL);
|
||||||
|
if (theServer->Open(cmd.GetInstanceId()))
|
||||||
{
|
{
|
||||||
server_tree.AttachNode(theServer);
|
server_tree.AttachNode(theServer);
|
||||||
theServer->Retain();
|
theServer->Retain();
|
||||||
|
|
@ -2645,16 +2653,16 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
bool isProbe = false;
|
bool isProbe = false;
|
||||||
|
|
||||||
// Fill in any last minute timestamps
|
// Fill in any last minute timestamps
|
||||||
// (TBD) fill in SessionId fields on all messages as needed
|
// (TBD) fill in InstanceId fields on all messages as needed
|
||||||
switch (msg.GetType())
|
switch (msg.GetType())
|
||||||
{
|
{
|
||||||
case NormMsg::INFO:
|
case NormMsg::INFO:
|
||||||
case NormMsg::DATA:
|
case NormMsg::DATA:
|
||||||
((NormObjectMsg&)msg).SetSessionId(session_id);
|
((NormObjectMsg&)msg).SetInstanceId(instance_id);
|
||||||
msg.SetSequence(tx_sequence++); // (TBD) set for session dst msgs
|
msg.SetSequence(tx_sequence++); // (TBD) set for session dst msgs
|
||||||
break;
|
break;
|
||||||
case NormMsg::CMD:
|
case NormMsg::CMD:
|
||||||
((NormCmdMsg&)msg).SetSessionId(session_id);
|
((NormCmdMsg&)msg).SetInstanceId(instance_id);
|
||||||
switch (((NormCmdMsg&)msg).GetFlavor())
|
switch (((NormCmdMsg&)msg).GetFlavor())
|
||||||
{
|
{
|
||||||
case NormCmdMsg::CC:
|
case NormCmdMsg::CC:
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class NormController
|
||||||
EVENT_INVALID = 0,
|
EVENT_INVALID = 0,
|
||||||
TX_QUEUE_VACANCY,
|
TX_QUEUE_VACANCY,
|
||||||
TX_QUEUE_EMPTY,
|
TX_QUEUE_EMPTY,
|
||||||
|
TX_FLUSH_COMPLETED,
|
||||||
TX_OBJECT_SENT,
|
TX_OBJECT_SENT,
|
||||||
TX_OBJECT_PURGED,
|
TX_OBJECT_PURGED,
|
||||||
LOCAL_SERVER_CLOSED,
|
LOCAL_SERVER_CLOSED,
|
||||||
|
|
@ -158,10 +159,11 @@ class NormSession
|
||||||
void ServerSetBaseObjectId(NormObjectId baseId)
|
void ServerSetBaseObjectId(NormObjectId baseId)
|
||||||
{
|
{
|
||||||
next_tx_object_id = IsServer() ? next_tx_object_id : baseId;
|
next_tx_object_id = IsServer() ? next_tx_object_id : baseId;
|
||||||
session_id = IsServer() ? session_id : (UINT16)baseId;
|
//instance_id = IsServer() ? instance_id : (UINT16)baseId;
|
||||||
}
|
}
|
||||||
bool IsServer() {return is_server;}
|
bool IsServer() {return is_server;}
|
||||||
bool StartServer(UINT32 bufferSpace,
|
bool StartServer(UINT16 instanceId,
|
||||||
|
UINT32 bufferSpace,
|
||||||
UINT16 segmentSize,
|
UINT16 segmentSize,
|
||||||
UINT16 numData,
|
UINT16 numData,
|
||||||
UINT16 numParity,
|
UINT16 numParity,
|
||||||
|
|
@ -363,7 +365,7 @@ class NormSession
|
||||||
|
|
||||||
// Server parameters and state
|
// Server parameters and state
|
||||||
bool is_server;
|
bool is_server;
|
||||||
UINT16 session_id;
|
UINT16 instance_id;
|
||||||
UINT16 segment_size;
|
UINT16 segment_size;
|
||||||
UINT16 ndata;
|
UINT16 ndata;
|
||||||
UINT16 nparity;
|
UINT16 nparity;
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,7 @@
|
||||||
#endif // UNIX
|
#endif // UNIX
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
printf("normTest starting ...\n");
|
printf("normTest starting (sizeof(NormOffset) = %d)...\n", sizeof(NormOffset));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NormInstanceHandle instance = NormCreateInstance();
|
NormInstanceHandle instance = NormCreateInstance();
|
||||||
|
|
||||||
|
|
@ -40,17 +35,18 @@ int main(int argc, char* argv[])
|
||||||
// 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, 1.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
|
||||||
//srand(currentTime.tv_sec); // seed random number generator
|
// (and a different sender sessionId)
|
||||||
|
srand(currentTime.tv_sec); // seed random number generator
|
||||||
|
|
||||||
NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
||||||
|
|
||||||
NormSetTransmitRate(session, 60.0e+06); // in bits/second
|
NormSetTransmitRate(session, 60.0e+03); // in bits/second
|
||||||
|
|
||||||
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
||||||
|
|
||||||
|
|
@ -64,7 +60,7 @@ int main(int argc, char* argv[])
|
||||||
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)
|
||||||
|
|
@ -73,8 +69,12 @@ int main(int argc, char* argv[])
|
||||||
// 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"
|
||||||
|
NormSessionId sessionId = (NormSessionId)rand();
|
||||||
|
|
||||||
|
|
||||||
// Uncomment the following line to start sender
|
// Uncomment the following line to start sender
|
||||||
NormStartSender(session, 4096*1024, 1400, 64, 0);
|
NormStartSender(session, sessionId, 4096*1024, 1400, 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 +87,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, 4096*1024);
|
||||||
|
|
||||||
// NORM_FLUSH_PASSIVE automatically flushes full writes to
|
// NORM_FLUSH_PASSIVE automatically flushes full writes to
|
||||||
// the stream.
|
// the stream.
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,6 @@
|
||||||
|
|
||||||
#ifndef _NORM_VERSION
|
#ifndef _NORM_VERSION
|
||||||
#define _NORM_VERSION
|
#define _NORM_VERSION
|
||||||
#define VERSION "1.3b2"
|
#define VERSION "1.3b3"
|
||||||
#endif // _NORM_VERSION
|
#endif // _NORM_VERSION
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
NORM API Examples
|
||||||
|
=================
|
||||||
|
|
||||||
|
This directory contains some purposely simplified examples of NORM
|
||||||
|
API usage. See comments in the source code files on how to build
|
||||||
|
these on Unix platforms. Eventually, "Makefiles" (and hopefully
|
||||||
|
"configure" scripts) will be provided as well as Visual C++
|
||||||
|
project files for Win32 builds.
|
||||||
|
|
||||||
|
The following example programs are included:
|
||||||
|
|
||||||
|
|
||||||
|
normFileSend.cpp - simple file transmission program. Sends one
|
||||||
|
file and exits.
|
||||||
|
|
||||||
|
normFileRecv.cpp - simple file reception program. Receives one
|
||||||
|
file and exits.
|
||||||
|
|
||||||
|
(These two programs use a hard-coded multicast address and port,
|
||||||
|
but take a file name and directory name, respectively, as a
|
||||||
|
command-line argument to determine the file sent and the
|
||||||
|
directory to which receive files are stored.)
|
||||||
|
|
||||||
|
|
||||||
|
Other examples will be added later including examples using the
|
||||||
|
"NormGetDescriptor()" function to allow NORM API events to be
|
||||||
|
multiplexed with other possible application events (e.g. other I/O
|
||||||
|
or Windows messages, etc).
|
||||||
|
|
||||||
|
------------- Brian Adamson <mailto:adamson@itd.nrl.navy.mil> 9
|
||||||
|
June 2005
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
/******************************************************************************
|
||||||
|
Simple NORM file receiver example app using the NORM API
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
|
||||||
|
normRecvFile <rxCacheDirectory>
|
||||||
|
|
||||||
|
BUILD (Unix):
|
||||||
|
|
||||||
|
g++ -o normRecvFile normRecvFile.cpp -I../common/ -I../protolib/common \
|
||||||
|
-DPROTO_DEBUG ../unix/libnorm.a ../protolib/unix/libProtokit.a -lpthread
|
||||||
|
|
||||||
|
(for MacOS/BSD, add "-lresolv")
|
||||||
|
(for Solaris, add "-ldl -lnsl -lsocket -lresolv")
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// Notes:
|
||||||
|
// 1) The program exits once a single file has been received ...
|
||||||
|
// 2) The received file is written to the <rxCacheDirectory>
|
||||||
|
// 3) The program also will exit on <CTRL-C> from user
|
||||||
|
// 4) "normFileRecv" should be started before "normFileSend"
|
||||||
|
|
||||||
|
#include "normApi.h" // for NORM API
|
||||||
|
|
||||||
|
#include "protoDefs.h" // for ProtoSystemTime
|
||||||
|
#include "protoDebug.h" // for SetDebugLevel(), etc
|
||||||
|
|
||||||
|
#include <stdio.h> // for printf(), etc
|
||||||
|
#include <stdlib.h> // for srand()
|
||||||
|
#include <string.h> // for strrchr()
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
const char DIR_DELIMITER = '\\';
|
||||||
|
#else
|
||||||
|
const char DIR_DELIMITER = '/';
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
// 0) The rxCachePath should be argv[1] ...
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "normFileRecv error: invalid argument(s)\n");
|
||||||
|
fprintf(stderr, "Usage: normRecvFile <rxCachePath>\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const char* rxCachePath = argv[1];
|
||||||
|
|
||||||
|
// 1) Create a NORM API "NormInstance"
|
||||||
|
NormInstanceHandle instance = NormCreateInstance();
|
||||||
|
|
||||||
|
// 2) Create a NormSession using default "automatic" local node id
|
||||||
|
NormSessionHandle session = NormCreateSession(instance,
|
||||||
|
"224.1.2.3",
|
||||||
|
6003,
|
||||||
|
NORM_NODE_ANY);
|
||||||
|
|
||||||
|
// NOTE: These are debugging routines available
|
||||||
|
// (not necessary for normal app use)
|
||||||
|
// (Need to include "protolib/common/protoDebug.h" for this
|
||||||
|
//SetDebugLevel(2);
|
||||||
|
// Uncomment to turn on debug NORM message tracing
|
||||||
|
//NormSetMessageTrace(session, true);
|
||||||
|
// Uncomment to turn on some random packet loss for testing
|
||||||
|
//NormSetRxLoss(session, 10.0); // 10% packet loss
|
||||||
|
struct timeval currentTime;
|
||||||
|
ProtoSystemTime(currentTime);
|
||||||
|
// Uncomment to get different packet loss patterns from run to run
|
||||||
|
srand(currentTime.tv_sec); // seed random number generator
|
||||||
|
|
||||||
|
// 3) Set receiver file cache path (where received files are mstored)
|
||||||
|
if (!NormSetCacheDirectory(instance, rxCachePath))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "normFileReceive: error setting cache directory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Start the receiver with 1 Mbyte buffer per sender
|
||||||
|
NormStartReceiver(session, 1024*1024);
|
||||||
|
|
||||||
|
// 5) Enter NORM event loop
|
||||||
|
bool keepGoing = true;
|
||||||
|
NormEvent theEvent;
|
||||||
|
while (keepGoing && NormGetNextEvent(instance, &theEvent))
|
||||||
|
{
|
||||||
|
switch (theEvent.type)
|
||||||
|
{
|
||||||
|
case NORM_RX_OBJECT_NEW:
|
||||||
|
fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_NEW event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_RX_OBJECT_INFO:
|
||||||
|
// Assume info contains '/' delimited <path/fileName> string
|
||||||
|
fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_INFO event ...\n");
|
||||||
|
if (NORM_OBJECT_FILE == NormObjectGetType(theEvent.object))
|
||||||
|
{
|
||||||
|
char fileName[PATH_MAX];
|
||||||
|
strcpy(fileName, rxCachePath);
|
||||||
|
int pathLen = strlen(fileName);
|
||||||
|
if (DIR_DELIMITER != fileName[pathLen-1])
|
||||||
|
{
|
||||||
|
fileName[pathLen++] = DIR_DELIMITER;
|
||||||
|
fileName[pathLen] = '\0';
|
||||||
|
}
|
||||||
|
unsigned short nameLen = PATH_MAX - pathLen;
|
||||||
|
nameLen = NormObjectGetInfo(theEvent.object, fileName+pathLen, nameLen);
|
||||||
|
fileName[nameLen + pathLen] = '\0';
|
||||||
|
char* ptr = fileName + 5;
|
||||||
|
while ('\0' != *ptr)
|
||||||
|
{
|
||||||
|
if ('/' == *ptr) *ptr = DIR_DELIMITER;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
if (!NormFileRename(theEvent.object, fileName))
|
||||||
|
fprintf(stderr, "normFileRecv: NormSetFileName(%s) error\n", fileName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_RX_OBJECT_UPDATED:
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_UPDATE event ...\n");
|
||||||
|
// Uncomment this stuff to monitor file receive progress
|
||||||
|
// (At high packet rates, you may want to be careful here and
|
||||||
|
// only calculate/post updates occasionally rather than for
|
||||||
|
// each and every RX_OBJECT_UPDATE event)
|
||||||
|
NormSize objectSize = NormObjectGetSize(theEvent.object);
|
||||||
|
NormSize completed = objectSize - NormObjectGetBytesPending(theEvent.object);
|
||||||
|
double percentComplete = 100.0 * ((double)completed/(double)objectSize);
|
||||||
|
fprintf(stderr, "normFileRecv: completion status %lu/%lu (%3.0lf%%)\n",
|
||||||
|
completed, objectSize, percentComplete);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NORM_RX_OBJECT_COMPLETED:
|
||||||
|
fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_COMPLETED event ...\n");
|
||||||
|
keepGoing = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_RX_OBJECT_ABORTED:
|
||||||
|
fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_ABORTED event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_REMOTE_SERVER_NEW:
|
||||||
|
fprintf(stderr, "normFileRecv: NORM_REMOTE_SERVER_NEW event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_REMOTE_SERVER_ACTIVE:
|
||||||
|
fprintf(stderr, "normFileRecv: NORM_REMOTE_SERVER_ACTIVE event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_REMOTE_SERVER_INACTIVE:
|
||||||
|
fprintf(stderr, "normFileRecv: NORM_REMOTE_SERVER_INACTIVE event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "normFileRecv: Got event type: %d\n", theEvent.type);
|
||||||
|
} // end switch(theEvent.type)
|
||||||
|
}
|
||||||
|
NormStopReceiver(session);
|
||||||
|
NormDestroySession(session);
|
||||||
|
NormDestroyInstance(instance);
|
||||||
|
|
||||||
|
fprintf(stderr, "normFileRecv: Done.\n");
|
||||||
|
return 0;
|
||||||
|
} // end main()
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
/******************************************************************************
|
||||||
|
Simple NORM file sender example app using the NORM API
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
|
||||||
|
normSendFile <fileName>
|
||||||
|
|
||||||
|
BUILD (Unix):
|
||||||
|
|
||||||
|
g++ -o normFileSend normFileSend.cpp -I../common/ -I../protolib/common \
|
||||||
|
../unix/libnorm.a ../protolib/unix/libProtokit.a -lpthread
|
||||||
|
|
||||||
|
(for MacOS/BSD, add "-lresolv")
|
||||||
|
(for Solaris, add "-ldl -lnsl -lsocket -lresolv")
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// Notes:
|
||||||
|
// 1) A single file is sent.
|
||||||
|
// 2) The program exits upon NORM_TX_FLUSH_COMPLETED notification (or user <CTRL-C>)
|
||||||
|
// 3) NORM receiver should be started first (before sender starts)
|
||||||
|
|
||||||
|
|
||||||
|
#include "normApi.h" // for NORM API
|
||||||
|
|
||||||
|
#include "protoDefs.h" // for ProtoSystemTime
|
||||||
|
#include "protoDebug.h" // for SetDebugLevel(), etc
|
||||||
|
|
||||||
|
#include <stdio.h> // for printf(), etc
|
||||||
|
#include <stdlib.h> // for srand()
|
||||||
|
#include <string.h> // for strrchr()
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
const char DIR_DELIMITER = '\\';
|
||||||
|
#else
|
||||||
|
const char DIR_DELIMITER = '/';
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
// 0) The filePath should be argv[1] ...
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "normFileSend error: invalid argument(s)\n");
|
||||||
|
fprintf(stderr, "Usage: normFileSend <file>\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const char* filePath = argv[1];
|
||||||
|
// Here we determine the "name" portion of the filePath
|
||||||
|
// (The file "name" is later used for NORM_INFO content)
|
||||||
|
const char* fileName = strrchr(filePath, DIR_DELIMITER);
|
||||||
|
if (fileName)
|
||||||
|
fileName++;
|
||||||
|
else
|
||||||
|
fileName = filePath;
|
||||||
|
|
||||||
|
|
||||||
|
// 1) Create a NORM API "NormInstance"
|
||||||
|
NormInstanceHandle instance = NormCreateInstance();
|
||||||
|
|
||||||
|
// 2) Create a NormSession using default "automatic" local node id
|
||||||
|
NormSessionHandle session = NormCreateSession(instance,
|
||||||
|
"224.1.2.3",
|
||||||
|
6003,
|
||||||
|
NORM_NODE_ANY);
|
||||||
|
|
||||||
|
// NOTE: These are some debugging routines available
|
||||||
|
// (not necessary for normal app use)
|
||||||
|
// (Need to include "protolib/common/protoDebug.h" for this
|
||||||
|
//SetDebugLevel(2);
|
||||||
|
// Uncomment to turn on debug NORM message tracing
|
||||||
|
//NormSetMessageTrace(session, true);
|
||||||
|
// Uncomment to turn on some random packet loss
|
||||||
|
// NormSetTxLoss(session, 10.0); // 10% packet loss
|
||||||
|
struct timeval currentTime;
|
||||||
|
ProtoSystemTime(currentTime);
|
||||||
|
// Uncomment to get different packet loss patterns from run to run
|
||||||
|
// (and a different sender sessionId)
|
||||||
|
srand(currentTime.tv_sec); // seed random number generator
|
||||||
|
|
||||||
|
// 3) Set transmission rate
|
||||||
|
NormSetTransmitRate(session, 256.0e+03); // in bits/second
|
||||||
|
|
||||||
|
// Uncomment to use a _specific_ transmit port number
|
||||||
|
// (Can be the same as session port (rx port), but this
|
||||||
|
// is _not_ recommended when unicast feedback may be
|
||||||
|
// possible! - must be called _before_ NormStartSender())
|
||||||
|
//NormSetTxPort(session, 6001);
|
||||||
|
|
||||||
|
// Uncomment to enable TCP-friendly congestion control
|
||||||
|
//NormSetCongestionControl(session, true);
|
||||||
|
|
||||||
|
// 4) Start the sender using a random "sessionId"
|
||||||
|
NormSessionId sessionId = (NormSessionId)rand();
|
||||||
|
NormStartSender(session, sessionId, 1024*1024, 1400, 64, 16);
|
||||||
|
|
||||||
|
// Uncomment to set large tx socket buffer size
|
||||||
|
// (might be needed for high rate sessions)
|
||||||
|
//NormSetTxSocketBuffer(session, 512000);
|
||||||
|
|
||||||
|
|
||||||
|
// 5) Enqueue the file for transmission
|
||||||
|
// (We use the file _name_ for NORM_INFO)
|
||||||
|
//
|
||||||
|
NormObjectHandle txFile =
|
||||||
|
NormFileEnqueue(session, filePath,
|
||||||
|
fileName, strlen(fileName));
|
||||||
|
|
||||||
|
// 6) Enter NORM event loop
|
||||||
|
bool keepGoing = true;
|
||||||
|
NormEvent theEvent;
|
||||||
|
while (keepGoing && NormGetNextEvent(instance, &theEvent))
|
||||||
|
{
|
||||||
|
switch (theEvent.type)
|
||||||
|
{
|
||||||
|
case NORM_TX_QUEUE_VACANCY:
|
||||||
|
fprintf(stderr, "normFileSend: NORM_TX_QUEUE_VACANCY event...\n");
|
||||||
|
break;
|
||||||
|
case NORM_TX_QUEUE_EMPTY:
|
||||||
|
fprintf(stderr, "normFileSend: NORM_TX_QUEUE_EMPTY event...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_TX_OBJECT_PURGED:
|
||||||
|
fprintf(stderr, "normFileSend: NORM_TX_OBJECT_PURGED event ...\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORM_TX_FLUSH_COMPLETED:
|
||||||
|
fprintf(stderr, "normFileSend: NORM_TX_FLUSH_COMPLETED event ...\n");
|
||||||
|
keepGoing = false; // our file has been sent (we think)
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
TRACE("normFileSend: Got event type: %d\n", theEvent.type);
|
||||||
|
} // end switch(theEvent.type)
|
||||||
|
} // end while (NormGetNextEvent())
|
||||||
|
|
||||||
|
NormStopSender(session);
|
||||||
|
NormDestroySession(session);
|
||||||
|
NormDestroyInstance(instance);
|
||||||
|
|
||||||
|
fprintf(stderr, "normFileSend: Done.\n");
|
||||||
|
return 0;
|
||||||
|
} // end main()
|
||||||
BIN
win32/Norm.suo
BIN
win32/Norm.suo
Binary file not shown.
BIN
wince/Norm.vco
BIN
wince/Norm.vco
Binary file not shown.
Loading…
Reference in New Issue