pull/2/head
Jeff Weston 2019-09-11 12:11:22 -04:00
parent 5be33c4e24
commit 76edf0c18d
52 changed files with 3973 additions and 545 deletions

View File

@ -1,5 +1,20 @@
NORM Version History NORM Version History
Version 1.5r5
=============
- Added NORM_REMOTE_SENDER_RESET event to notify app when the sender
has been reset due to instance id, etc change
- Fixed possibly critical issue in Protolib ProtoDispatcher where
threaded dispatcher use (as the NORM API uses) could possibly result
in timers not being serviced properly. Most likely the issue could
only occur under certain, heavier NORM API usage patterns. Nonetheless,
this is an important fix. (Thanks to Michael Savisko of Arris).
- Fixed FreeBSD build (Thanks to Hans Duedal)
- Changed from 'b' (build) numbering schema to 'r' (release) to reduce
confusion with respect to "beta" versus "stable" releases.
- Note there are some "in-progress" API extensions in this release that
are not yet described in the developer's guide documentation.
Version 1.5b4 Version 1.5b4
============= =============
- Corrected change in behavior of non-blocking version of - Corrected change in behavior of non-blocking version of
@ -24,7 +39,7 @@ Version 1.5b2
notification check acking status). Acknowledged, graceful shutdown streams, notification check acking status). Acknowledged, graceful shutdown streams,
are automatically closed. are automatically closed.
- Fixed issue with compilation for NormObjectSize constructor, MSB(), and LSB() - Fixed issue with compilation for NormObjectSize constructor, MSB(), and LSB()
methods on 32-bit systems. Thanks to Bill Skiba. methods on 32-bit systems. (Thanks to Bill Skiba).
Version 1.5b1 Version 1.5b1
============= =============

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -5,9 +5,9 @@
<articleinfo> <articleinfo>
<title><inlinemediaobject> <title><inlinemediaobject>
<imageobject> <imageobject>
<imagedata align="center" fileref="NormLogo.gif" scale="50" /> <imagedata align="center" fileref="NormLogo.gif" scale="50"/>
</imageobject> </imageobject>
</inlinemediaobject> NORM Developer's Guide (version 1.4b4)</title> </inlinemediaobject> NORM Developer's Guide (version 1.5b5)</title>
<titleabbrev>NORM Developer's Guide</titleabbrev> <titleabbrev>NORM Developer's Guide</titleabbrev>
@ -1234,9 +1234,9 @@ bool <link linkend="NormGetNextEvent"><literal>NormGetNextEvent</literal></link>
<informaltable frame="all"> <informaltable frame="all">
<tgroup cols="2"> <tgroup cols="2">
<colspec colnum="1" colwidth="1*" /> <colspec colnum="1" colwidth="1*"/>
<colspec colnum="2" colwidth="2.5*" /> <colspec colnum="2" colwidth="2.5*"/>
<tbody> <tbody>
<row> <row>
@ -1430,8 +1430,8 @@ bool <link linkend="NormGetNextEvent"><literal>NormGetNextEvent</literal></link>
<entry><para><literal>NORM_REMOTE_SENDER_ACTIVE</literal></para></entry> <entry><para><literal>NORM_REMOTE_SENDER_ACTIVE</literal></para></entry>
<entry><para>This event is posted when a previously inactive <entry><para>This event is posted when a previously inactive
(or new) remote <anchor id="OLE_LINK5" /> <anchor (or new) remote <anchor id="OLE_LINK5"/> <anchor
id="OLE_LINK4" />sender is detected operating as an active id="OLE_LINK4"/>sender is detected operating as an active
sender within the session.</para></entry> sender within the session.</para></entry>
</row> </row>
@ -1675,9 +1675,9 @@ NormSessionHandle</literal></link> <link linkend="NormCreateSession"><literal>No
<informaltable frame="all"> <informaltable frame="all">
<tgroup cols="2"> <tgroup cols="2">
<colspec colnum="1" colwidth="1*" /> <colspec colnum="1" colwidth="1*"/>
<colspec colnum="2" colwidth="5*" /> <colspec colnum="2" colwidth="5*"/>
<tbody> <tbody>
<row> <row>
@ -1886,7 +1886,7 @@ const void* <link linkend="NormGetUserData"><literal>NormGetUserData</literal></
</sect4> </sect4>
<sect4> <sect4>
<title>Return Values</title> <title>Return Valuess</title>
<para>The returned value indicates the <emphasis>NormNode</emphasis> <para>The returned value indicates the <emphasis>NormNode</emphasis>
identifier used by the NORM protocol engine for the local identifier used by the NORM protocol engine for the local
@ -2185,8 +2185,8 @@ NormSetMulticastInterface</literal></link>(session, "interface2");</programlisti
<para>A return value of <constant>true</constant> indicates success <para>A return value of <constant>true</constant> indicates success
while a return value of <constant>false</constant> indicates that while a return value of <constant>false</constant> indicates that
the specified interface was valid. This function will always return the specified interface was invalid. This function will always
<constant>true</constant> if made before calls to <link return <constant>true</constant> if made before calls to <link
linkend="NormStartSender"><literal>NormStartSender()</literal></link> linkend="NormStartSender"><literal>NormStartSender()</literal></link>
or <link or <link
linkend="NormStartReceiver"><literal>NormStartReceiver()</literal></link>. linkend="NormStartReceiver"><literal>NormStartReceiver()</literal></link>.
@ -2195,6 +2195,50 @@ NormSetMulticastInterface</literal></link>(session, "interface2");</programlisti
</sect4> </sect4>
</sect3> </sect3>
<sect3 id="NormSetMulticastInterface">
<title>NormSetSSM()</title>
<sect4>
<title>Synopsis</title>
<programlisting>#include &lt;normApi.h&gt;
bool <link linkend="NormSetMulticastInterface"><literal>NormSetSSM</literal></link>(<link
linkend="NormSessionHandle"><literal>NormSessionHandle</literal></link> session,
const char* sourceAddress);</programlisting>
</sect4>
<sect4>
<title>Description</title>
<para>This function sets the source address for Source-Specific
Multicast (SSM) operation. This should be called
<emphasis>before</emphasis> any call to <link
linkend="NormStartSender"><literal>NormStartSender()</literal></link>
or <link
linkend="NormStartReceiver"><literal>NormStartReceiver()</literal></link>
is made so that the proper group join is done. The receiver
application MUST also use the <link
linkend="NormSetDefaultUnicastNack"><literal>NormSetDefaultUnicastNack()</literal></link>
call so that feedback traffic is directed back to appropriate
sender.</para>
</sect4>
<sect4>
<title>Return Values</title>
<para>A return value of <constant>true</constant> indicates success
while a return value of <constant>false</constant> indicates that
the specified source address was invalid. Note that if a valid IP
address is specified but is improper for SSM (e.g., an IP multicast
address) the later calls to <link
linkend="NormStartSender"><literal>NormStartSender()</literal></link>
or <link
linkend="NormStartReceiver"><literal>NormStartReceiver()</literal></link>
may fail.</para>
</sect4>
</sect3>
<sect3 id="NormSetTTL"> <sect3 id="NormSetTTL">
<title>NormSetTTL()</title> <title>NormSetTTL()</title>
@ -2352,8 +2396,7 @@ bool <link linkend="NormSetFragmentation"><literal>NormSetFragmentation</literal
Multicast destinations, some operating systems may always set the DF Multicast destinations, some operating systems may always set the DF
bit of transmitted packets, regardless of the setting here and the bit of transmitted packets, regardless of the setting here and the
underlying socket option status. Typically, the DF bit is set (i.e., underlying socket option status. Typically, the DF bit is set (i.e.,
fragmentation disabled) by default on most operating systems. fragmentation disabled) by default on most operating systems.</para>
</para>
<para>This call is not currently functional on the Mac OSX system <para>This call is not currently functional on the Mac OSX system
that does not support the needed that does not support the needed
@ -2371,7 +2414,7 @@ bool <link linkend="NormSetFragmentation"><literal>NormSetFragmentation</literal
</sect2> </sect2>
<sect2> <sect2>
<title><anchor id="_NORM_Sender_Functions" />NORM Sender <title><anchor id="_NORM_Sender_Functions"/>NORM Sender
Functions</title> Functions</title>
<para>The functions described in this section apply only to NORM sender <para>The functions described in this section apply only to NORM sender
@ -2412,9 +2455,9 @@ bool <link linkend="NormStartSender"><literal>NormStartSender</literal></link>(<
<informaltable frame="all"> <informaltable frame="all">
<tgroup cols="2"> <tgroup cols="2">
<colspec colnum="1" colwidth="1*" /> <colspec colnum="1" colwidth="1*"/>
<colspec colnum="2" colwidth="5*" /> <colspec colnum="2" colwidth="5*"/>
<tbody> <tbody>
<row> <row>

296
examples/normClient.cpp Normal file
View File

@ -0,0 +1,296 @@
#include "normSocket.h"
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <fcntl.h> // for, well, fnctl()
#include <errno.h> // obvious child
// BUILD: (assumes "normApi.h" in "include" ...
// g++ -I../include -o normClient normClient.cpp normSocket.cpp ../lib/libnorm.a ../protolib/lib/libprotokit.a -lresolv
// NOTES:
// 1) THIS IS A WORK IN PROGRESS AND NOT YET FUNCTIONAL!
// 2) Some of the functions here may be added to the NORM API in the future.
// Client initiates connection to "server". When the "client" gets a NORM_REMOTE_SENDER_NEW
// from the "server", it knows its connection has been accepted.
// To deny a connection, the "server" can send a stream close??? Which means the server will have
// to establish state just to deny a client a connection (yuck!)
const unsigned int MSG_LENGTH_MAX = 64;
int main(int argc, char* argv[])
{
char serverAddr[64];
strcpy(serverAddr, "127.0.0.1");
UINT16 serverPort = 5000;
char groupAddr[64];
const char* groupAddrPtr = NULL;
const char* mcastInterface = NULL;
NormNodeId clientId = 2;
bool trace = false;
unsigned int debugLevel = 0;
for (int i = 1; i < argc; i++)
{
const char* cmd = argv[i];
unsigned int len = strlen(cmd);
if (0 == strncmp(cmd, "connect", len))
{
// connect <serverAddr>/<port>[,<groupAddr>
const char* val = argv[++i];
const char* portPtr = strchr(val, '/');
if (NULL == portPtr)
{
fprintf(stderr, "normClient error: missing <port> number\n");
return -1;
}
portPtr++;
unsigned int addrTextLen = portPtr - val;
if (addrTextLen > 0)
{
addrTextLen -= 1;
strncpy(serverAddr, val, addrTextLen);
serverAddr[addrTextLen] = '\0';
}
else
{
fprintf(stderr, "normClient error: missing <serverAddr>\n");
return -1;
}
char portText[32];
const char* groupPtr = strchr(portPtr, ',');
if (NULL == groupPtr)
{
strcpy(portText, portPtr);
}
else
{
groupPtr++;
unsigned int portTextLen = groupPtr - portPtr - 1;
strncpy(portText, portPtr, portTextLen);
portText[portTextLen] = '\0';
}
if (1 != sscanf(portText, "%hu", &serverPort))
{
fprintf(stderr, "normClient error: invalid <port>\n");
return -1;
}
if (NULL != groupPtr)
{
strcpy(groupAddr, groupPtr);
groupAddrPtr = groupAddr;
}
}
else if (0 == strncmp(cmd, "interface", len))
{
mcastInterface = argv[++i];
}
else if (0 == strncmp(cmd, "trace", len))
{
trace = true;
}
else if (0 == strncmp(cmd, "debug", len))
{
if (1 != sscanf(argv[++i], "%u", &debugLevel))
{
fprintf(stderr, "normServer error: invalid debug level\n");
return -1;
}
}
else if (0 == strncmp(cmd, "id", len))
{
const char* val = argv[++i];
unsigned long id;
if (1 != sscanf(val, "%lu", &id))
{
fprintf(stderr, "normClient error: invalid 'id' value\n");
return -1;
}
clientId = id;
}
else
{
fprintf(stderr, "normServer error: invalid command \"%s\"\n", cmd);
return -1;
}
}
NormInstanceHandle instance = NormCreateInstance();
// Initate connection to server ...
fprintf(stderr, "normClient: connecting to %s/%hu ...\n", serverAddr, serverPort);
NormSocketHandle normSocket = NormConnect(instance, serverAddr, serverPort, groupAddrPtr, clientId);
if (trace)
{
NormSetMessageTrace(NormGetSession(normSocket), true);
if (NULL != groupAddrPtr)
NormSetMessageTrace(NormGetMulticastSession(normSocket), true);
}
if (0 != debugLevel) NormSetDebugLevel(debugLevel);
//NormSetDebugLevel(3);
//NormSetMessageTrace(NormGetSession(normSocket), true);
// We use a select() call to multiplex input reading and NormSocket handling
fd_set fdset;
FD_ZERO(&fdset);
// Get our input (STDIN) descriptor and set non-blocking
FILE* inputFile = stdin;
int inputfd = fileno(inputFile);
if (-1 == fcntl(inputfd, F_SETFL, fcntl(inputfd, F_GETFL, 0) | O_NONBLOCK))
perror("normClient: fcntl(inputfd, O_NONBLOCK) error");
// Get our NormInstance descriptor
int normfd = NormGetDescriptor(instance);
bool keepGoing = true;
bool writeReady = false;
unsigned int inputLength = 0;
unsigned int bytesWritten = 0;
const unsigned int BUFFER_LENGTH = 2048;
char inputBuffer[BUFFER_LENGTH];
bool inputNeeded = false; // will be set to "true" upon CONNECT
while (keepGoing)
{
FD_SET(normfd, &fdset);
int maxfd = normfd;
if (inputNeeded)
{
FD_SET(inputfd, &fdset);
if (inputfd > maxfd) maxfd = inputfd;
}
else
{
FD_CLR(inputfd, &fdset);
}
int result = select(maxfd+1, &fdset, NULL, NULL, NULL);
if (result <= 0)
{
perror("normClient: select() error");
break;
}
if (FD_ISSET(inputfd, &fdset))
{
// Read input into our txBuffer
inputLength = fread(inputBuffer, 1, BUFFER_LENGTH, inputFile);
if (inputLength > 0)
{
// We got our input
bytesWritten = 0;
inputNeeded = false;
}
else if (feof(inputFile))
{
// TBD - initiate client shutdown
if (NULL == groupAddrPtr)
{
fprintf(stderr, "normClient: CLOSING connection to server ...\n");
NormShutdown(normSocket);
}
inputNeeded = false; // TBD -should we also fclose(inputFile)???
// else stick around to receive stuff from the server
}
else if (ferror(inputFile))
{
switch (errno)
{
case EINTR:
// interupted, try again
break;
case EAGAIN:
// input starved, wait for next notification
break;
default:
perror("normClient: error reading input");
break;
}
}
}
if (FD_ISSET(normfd, &fdset))
{
// There's a NORM event pending
NormSocketEvent event;
if (NormGetSocketEvent(instance, &event))
{
switch (event.type)
{
case NORM_SOCKET_ACCEPT:
// shouldn't happen
break;
case NORM_SOCKET_CONNECT:
{
fprintf(stderr, "normClient: CONNECTED to server ...\n");
inputNeeded = true;
writeReady = true;
break;
}
case NORM_SOCKET_READ:
{
// This is a cue to try to read data from stream
// For our test app here, the data is read and output to STDOUT
bool rxReady = true;
while (rxReady)
{
char buffer[1024];
ssize_t bytesRead = NormRead(event.socket, buffer, 1024);
if (bytesRead < 0)
{
// This shouldn't happen with ack-based flow control used
fprintf(stderr, "normClient: broken stream ...\n");
continue;
}
if (bytesRead > 0)
fwrite(buffer, sizeof(char), bytesRead, stdout);
if (bytesRead < 1024) rxReady = false;
}
break;
}
case NORM_SOCKET_WRITE:
writeReady = true;
break;
case NORM_SOCKET_CLOSING:
fprintf(stderr, "normClient: server CLOSING connection ...\n");
inputNeeded = false;
break;
case NORM_SOCKET_CLOSED:
{
fprintf(stderr, "normClient: connection to server CLOSED.\n");
inputNeeded = false;
keepGoing = false;
break;
}
case NORM_SOCKET_NONE:
break;
} // end switch(event.type)
}
else
{
fprintf(stderr, "normClient: NormGetSocketEvent() returned false\n");
}
} // end if FD_ISSET(normfd)
// If we have data in our inputBuffer and the NormSocket is "writeReady", then send it
if (writeReady && (inputLength > 0))
{
bytesWritten += NormWrite(normSocket, inputBuffer + bytesWritten, inputLength - bytesWritten);
if (bytesWritten < inputLength)
{
// Couldn't write whole inputBuffer, need to wait for NORM_SOCKET_WRITE event
writeReady = false;
}
else
{
// inputBuffer has been completely written
inputLength = 0;
inputNeeded = true;
NormFlush(normSocket);
}
}
} // end while(keepGoing)
}

View File

@ -1,6 +1,8 @@
#include "normApi.h" #include "normApi.h"
#include "protoCheck.h"
#include <stdio.h> // for printf(), etc #include <stdio.h> // for printf(), etc
#include <stdlib.h> // for srand() #include <stdlib.h> // for srand()
#include <string.h> // for strrchr(), memset(), etc #include <string.h> // for strrchr(), memset(), etc
@ -49,8 +51,8 @@ class NormMsgr
char* AccessBuffer() char* AccessBuffer()
{return msg_buffer;} {return msg_buffer;}
void ResetIndex() void ResetIndex(unsigned int index = 0)
{msg_index = 0;} {msg_index = index;}
void IncrementIndex(unsigned int count) void IncrementIndex(unsigned int count)
{msg_index += count;} {msg_index += count;}
unsigned int GetIndex() const unsigned int GetIndex() const
@ -151,6 +153,15 @@ class NormMsgr
{return output_pending;} {return output_pending;}
bool WriteOutput(); bool WriteOutput();
void OmitHeader(bool state)
{omit_header = state;}
// These can only be called post-OpenNormSession
void SetSilentReceiver(bool state)
{NormSetSilentReceiver(norm_session, true);}
void SetTxLoss(double txloss)
{NormSetTxLoss(norm_session, txloss);}
private: private:
bool is_running; bool is_running;
FILE* input_file; // stdin by default FILE* input_file; // stdin by default
@ -159,6 +170,7 @@ class NormMsgr
MessageQueue input_msg_list; // list of enqueued messages (in norm sender cache) MessageQueue input_msg_list; // list of enqueued messages (in norm sender cache)
NormSessionHandle norm_session; NormSessionHandle norm_session;
bool is_multicast;
unsigned int norm_tx_queue_max; // max number of objects that can be enqueued at once unsigned int norm_tx_queue_max; // max number of objects that can be enqueued at once
unsigned int norm_tx_queue_count; // count of unacknowledged enqueued objects (TBD - optionally track size too) unsigned int norm_tx_queue_count; // count of unacknowledged enqueued objects (TBD - optionally track size too)
bool norm_tx_watermark_pending; bool norm_tx_watermark_pending;
@ -170,14 +182,19 @@ class NormMsgr
bool output_pending; bool output_pending;
Message* output_msg; Message* output_msg;
MessageQueue output_msg_queue; MessageQueue output_msg_queue;
// These are some options mainly for testing purposes
bool omit_header; // if "true", receive message length header is _not_ written to output
bool rx_silent;
double tx_loss;
}; // end class NormMsgr }; // end class NormMsgr
NormMsgr::NormMsgr() NormMsgr::NormMsgr()
: input_file(stdin), input_needed(true), input_msg(NULL), : input_file(stdin), input_needed(false), input_msg(NULL),
norm_session(NORM_SESSION_INVALID), norm_tx_queue_max(2048), norm_tx_queue_count(0), norm_session(NORM_SESSION_INVALID), is_multicast(false), norm_tx_queue_max(2048), norm_tx_queue_count(0),
norm_tx_watermark_pending(false), norm_tx_vacancy(true), norm_acking(false), norm_tx_watermark_pending(false), norm_tx_vacancy(true), norm_acking(false),
output_file(stdout), output_ready(true), output_pending(false), output_msg(NULL) output_file(stdout), output_ready(true), output_pending(false), output_msg(NULL),
omit_header(false), rx_silent(false), tx_loss(0.0)
{ {
} }
@ -191,12 +208,25 @@ NormMsgr::~NormMsgr()
bool NormMsgr::OpenNormSession(NormInstanceHandle instance, const char* addr, unsigned short port, NormNodeId nodeId) bool NormMsgr::OpenNormSession(NormInstanceHandle instance, const char* addr, unsigned short port, NormNodeId nodeId)
{ {
if (NormIsUnicastAddress(addr))
is_multicast = false;
else
is_multicast = true;
norm_session = NormCreateSession(instance, addr, port, nodeId); norm_session = NormCreateSession(instance, addr, port, nodeId);
if (NORM_SESSION_INVALID == norm_session) if (NORM_SESSION_INVALID == norm_session)
{ {
fprintf(stderr, "normMsgr error: unable to create NORM session\n"); fprintf(stderr, "normMsgr error: unable to create NORM session\n");
return false; return false;
} }
if (is_multicast)
{
NormSetRxPortReuse(norm_session, true);
// TBD - make full loopback a command line option?
NormSetMulticastLoopback(norm_session, true);
}
// Set some default parameters (maybe we should put parameter setting in Start()) // Set some default parameters (maybe we should put parameter setting in Start())
NormSetRxCacheLimit(norm_session, norm_tx_queue_max); NormSetRxCacheLimit(norm_session, norm_tx_queue_max);
NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_ALL); NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_ALL);
@ -205,6 +235,9 @@ bool NormMsgr::OpenNormSession(NormInstanceHandle instance, const char* addr, un
NormSetTxCacheBounds(norm_session, 10*1024*1024, norm_tx_queue_max, norm_tx_queue_max); NormSetTxCacheBounds(norm_session, 10*1024*1024, norm_tx_queue_max, norm_tx_queue_max);
//NormSetMessageTrace(norm_session, true); //NormSetMessageTrace(norm_session, true);
NormSetTxRobustFactor(norm_session, 2);
return true; return true;
} // end NormMsgr::OpenNormSession() } // end NormMsgr::OpenNormSession()
@ -268,6 +301,7 @@ bool NormMsgr::Start(bool sender, bool receiver)
if (receiver) NormStopReceiver(norm_session); if (receiver) NormStopReceiver(norm_session);
return false; return false;
} }
input_needed = true;
} }
is_running = true; is_running = true;
return true; return true;
@ -379,6 +413,7 @@ bool NormMsgr::WriteOutput()
bufferPtr = output_msg->GetBuffer() + offset; bufferPtr = output_msg->GetBuffer() + offset;
} }
size_t result = fwrite(bufferPtr, 1, writeLength, output_file); size_t result = fwrite(bufferPtr, 1, writeLength, output_file);
output_msg->IncrementIndex(result); output_msg->IncrementIndex(result);
if (result < writeLength) if (result < writeLength)
{ {
@ -389,6 +424,7 @@ bool NormMsgr::WriteOutput()
} }
else if (ferror(input_file)) else if (ferror(input_file))
{ {
fprintf(stderr, "normMsgr: output error detected ...\n");
switch (errno) switch (errno)
{ {
case EINTR: case EINTR:
@ -406,12 +442,20 @@ bool NormMsgr::WriteOutput()
} }
if (output_msg->IsComplete()) if (output_msg->IsComplete())
{ {
fflush(output_file);
delete output_msg; delete output_msg;
output_msg = output_msg_queue.RemoveHead(); output_msg = output_msg_queue.RemoveHead();
if (NULL != output_msg) if (NULL != output_msg)
output_msg->ResetIndex(); {
if (omit_header)
output_msg->ResetIndex(MSG_HEADER_SIZE);
else
output_msg->ResetIndex();
}
else else
{
output_pending = false; output_pending = false;
}
break; break;
} }
} }
@ -490,6 +534,7 @@ bool NormMsgr::EnqueueMessageObject()
void NormMsgr::HandleNormEvent(const NormEvent& event) void NormMsgr::HandleNormEvent(const NormEvent& event)
{ {
bool logAllocs = false;
switch (event.type) switch (event.type)
{ {
case NORM_TX_QUEUE_EMPTY: case NORM_TX_QUEUE_EMPTY:
@ -528,6 +573,18 @@ void NormMsgr::HandleNormEvent(const NormEvent& event)
} }
break; break;
} }
case NORM_REMOTE_SENDER_INACTIVE:
//fprintf(stderr, "REMOTE SENDER INACTIVE node: %u\n", NormNodeGetId(event.sender));
//NormNodeDelete(event.sender);
//logAllocs = true;
break;
case NORM_RX_OBJECT_ABORTED:
//fprintf(stderr, "NORM_RX_OBJECT_ABORTED\n");// %hu\n", NormObjectGetTransportId(event.object));
logAllocs = true;
break;
case NORM_RX_OBJECT_COMPLETED: case NORM_RX_OBJECT_COMPLETED:
{ {
char* data = NormDataDetachData(event.object); char* data = NormDataDetachData(event.object);
@ -536,7 +593,7 @@ void NormMsgr::HandleNormEvent(const NormEvent& event)
Message* msg = new Message(data, NormObjectGetSize(event.object)); Message* msg = new Message(data, NormObjectGetSize(event.object));
if (NULL == msg) if (NULL == msg)
{ {
perror("normMsgr new receive Message error"); perror("normMsgr: new Message() error");
delete[] data; // TBD - may need to finally implement NormDelete() function! delete[] data; // TBD - may need to finally implement NormDelete() function!
// TBD Stop() as a fatal out of memory error? // TBD Stop() as a fatal out of memory error?
break; break;
@ -544,7 +601,10 @@ void NormMsgr::HandleNormEvent(const NormEvent& event)
if (NULL == output_msg) if (NULL == output_msg)
{ {
output_msg = msg; output_msg = msg;
output_msg->ResetIndex(); if (omit_header)
output_msg->ResetIndex(MSG_HEADER_SIZE);
else
output_msg->ResetIndex();
output_pending = true; output_pending = true;
} }
else else
@ -559,13 +619,23 @@ void NormMsgr::HandleNormEvent(const NormEvent& event)
default: default:
break; break;
} }
//NormReleasePreviousEvent(NormGetInstance(norm_session));
if (logAllocs)
{
#ifdef USE_PROTO_CHECK
ProtoCheckLogAllocations(stderr);
#endif // USE_PROTO_CHECK
}
} // end NormMsgr::HandleNormEvent() } // end NormMsgr::HandleNormEvent()
void Usage() void Usage()
{ {
fprintf(stderr, "Usage: normMsgr id <nodeId> {send &| recv} [addr <addr>[/<port>]][ack <node1>[,<node2>,...]\n" fprintf(stderr, "Usage: normMsgr id <nodeId> {send &| recv} [addr <addr>[/<port>]][ack <node1>[,<node2>,...]\n"
" [cc|cce|ccl|rate <bitsPerSecond>][interface <name>][debug <level>][trace]\n"); " [cc|cce|ccl|rate <bitsPerSecond>][interface <name>][debug <level>][trace]\n"
" [omit][silent][txloss <lossFraction>]\n");
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
@ -587,6 +657,9 @@ int main(int argc, char* argv[])
int debugLevel = 0; int debugLevel = 0;
bool trace = false; bool trace = false;
bool omitHeaderOnOutput = false;
bool silentReceiver = false;
double txloss = 0.0;
// Parse command-line // Parse command-line
int i = 1; int i = 1;
@ -700,6 +773,23 @@ int main(int argc, char* argv[])
} }
mcastIface = argv[i++]; mcastIface = argv[i++];
} }
else if (0 == strncmp(cmd, "omit", len))
{
omitHeaderOnOutput = true;
}
else if (0 == strncmp(cmd, "silent", len))
{
silentReceiver = true;
}
else if (0 == strncmp(cmd, "txloss", len))
{
if (1 != sscanf(argv[i++], "%lf", &txloss))
{
fprintf(stderr, "nodeMsgr error: invalid 'txloss' value!\n");
Usage();
return -1;
}
}
else if (0 == strncmp(cmd, "debug", len)) else if (0 == strncmp(cmd, "debug", len))
{ {
if (i >= argc) if (i >= argc)
@ -746,6 +836,8 @@ int main(int argc, char* argv[])
NormMsgr normMsgr; NormMsgr normMsgr;
if (omitHeaderOnOutput) normMsgr.OmitHeader(true);
if (!normMsgr.OpenNormSession(normInstance, sessionAddr, sessionPort, (NormNodeId)nodeId)) if (!normMsgr.OpenNormSession(normInstance, sessionAddr, sessionPort, (NormNodeId)nodeId))
{ {
fprintf(stderr, "normMsgr error: unable to open NORM session\n"); fprintf(stderr, "normMsgr error: unable to open NORM session\n");
@ -753,6 +845,10 @@ int main(int argc, char* argv[])
return false; return false;
} }
if (silentReceiver) normMsgr.SetSilentReceiver(true);
if (txloss > 0.0) normMsgr.SetTxLoss(txloss);
for (unsigned int i = 0; i < ackingNodeCount; i++) for (unsigned int i = 0; i < ackingNodeCount; i++)
normMsgr.AddAckingNode(ackingNodeList[i]); normMsgr.AddAckingNode(ackingNodeList[i]);
@ -848,6 +944,9 @@ int main(int argc, char* argv[])
normMsgr.WriteOutput(); // TBD - implement output async i/o notification as needed normMsgr.WriteOutput(); // TBD - implement output async i/o notification as needed
} // end while(normMsgr.IsRunning() } // end while(normMsgr.IsRunning()
fprintf(stderr, "normMsgr exiting ...\n");
NormDestroyInstance(normInstance); NormDestroyInstance(normInstance);
} // end main() } // end main()
@ -865,6 +964,8 @@ NormMsgr::Message::Message(char* buffer, unsigned int size)
uint16_t msgSize = size + MSG_HEADER_SIZE; uint16_t msgSize = size + MSG_HEADER_SIZE;
msgSize = htons(msgSize); msgSize = htons(msgSize);
memcpy(msg_header, &msgSize, MSG_HEADER_SIZE); memcpy(msg_header, &msgSize, MSG_HEADER_SIZE);
fprintf(stderr, "output msg ctor data = %.20s\n", buffer);
} }
NormMsgr::Message::~Message() NormMsgr::Message::~Message()

463
examples/normServer.cpp Normal file
View File

@ -0,0 +1,463 @@
// This example NORM application acts as unicast "server". A NORM receive-only session "listens"
// on a "serverPort". When new remote senders are detected, the sender is assigned to a
// newly create "client" NormSession that is "connected" to the remote sender/client addr/port.
// The NormSetRxPortReuse() call provides an option to "connect" the underlying NORM UDP socket
// to the remote sender/client address/port. Note this is not yet supported for NORM-CCE (ECN)
// congestion control operation.
// By creating "client" NormSessions for each client connection, this enables multiple clients
// from the same host (with the same NormNodeId to connect to the server at the same time.
// Otherwise, clients with the same NormNodeId would "collide" at the server receive session.
// Even the approach here is not perfect as a packet from a another client instance with the
// same NormNodeId might change the given "remote sender" source addr/port before the
// connected "client" session is created as a sort of race condition.
// A potential enhancement to NORM would be to allow tracking of multiple remote senders
// with the same NormNodeId but different instanceIds ...
// BUILD: (assumes "normApi.h" in "include" ...
// g++ -I../include -o normServer normServer.cpp normSocket.cpp ../lib/libnorm.a ../protolib/lib/libprotokit.a -lresolv
// EXAMPLE NOTES:
//
// 0) THIS IS A WORK IN PROGRESS AND NOT YET FUNCTIONAL!
//
// 1) Some of the functions here may be added to the NORM API in the future.
//
// 2) The "main()" below is a single-threaded example with a single NormInstance and a
// single NormGetNextEvent() main loop. Note that the NormAccept() call allows for a
// new instance (and hence new NormDescriptor) for each accepted client, so multiple
// threads or event thread-pooling versions of this could be implemented for
// performance or application design purposes. A future version of the NORM API and
// this could even provide for very "socket-like" API calls where each "client"
// session has its own descriptor independent of threading (e.g. a "normSocket.h" API
// that is implemented around the current low level NORM API). This sort of "NORM
// socket" approach could be supported for unicast and SSM streams without too much
// difficulty.
#include "normSocket.h"
#include <arpa/inet.h> // for inet_ntoa
#include <stdio.h> // for fprintf()
#include <string.h> // for memcmp()
#include <map> // for std::map<>
#include <sys/select.h>
#include <fcntl.h> // for, well, fnctl()
#include <errno.h> // obvious child
// Our "server" indexes clients by their source addr/port
class ClientInfo
{
public:
ClientInfo(UINT8 ipVersion = 0, const char* theAddr = NULL, UINT16 thePort = 0);
bool operator < (const ClientInfo& a) const;
int GetAddressFamily() const;
const char* GetAddress() const
{return client_addr;}
UINT16 GetPort() const
{return client_port;}
const char* GetAddressString() const;
void Print(FILE* filePtr) const;
private:
UINT8 addr_version; // 4 or 6
char client_addr[16]; // big enough for IPv6
UINT16 client_port;
}; // end class ClientInfo
ClientInfo::ClientInfo(UINT8 addrVersion, const char* clientAddr, UINT16 clientPort)
: addr_version(addrVersion), client_port(clientPort)
{
if (NULL == clientAddr) addrVersion = 0; // forces zero initialization
switch (addrVersion)
{
case 4:
memcpy(client_addr, clientAddr, 4);
memset(client_addr+4, 0, 12);
break;
case 6:
memcpy(client_addr, clientAddr, 16);
break;
default:
memset(client_addr, 0, 16);
break;
}
}
// returns "true" if "this" less than "a" (used by C++ map)
bool ClientInfo::operator <(const ClientInfo& a) const
{
if (addr_version != a.addr_version)
return (addr_version < a.addr_version);
else if (client_port != a.client_port)
return (client_port < a.client_port);
else if (4 == addr_version)
return (0 > memcmp(client_addr, a.client_addr, 4));
else
return (0 > memcmp(client_addr, a.client_addr, 16));
} // end ClientInfo::operator <()
int ClientInfo::GetAddressFamily() const
{
if (4 == addr_version)
return AF_INET;
else
return AF_INET6;
} // end ClientInfo::GetAddressFamily()
const char* ClientInfo::GetAddressString() const
{
static char text[64];
text[63] = '\0';
int addrFamily;
if (4 == addr_version)
addrFamily = AF_INET;
else
addrFamily = AF_INET6;
inet_ntop(addrFamily, client_addr, text, 63);
return text;
} // end ClientInfo::GetAddressString()
void ClientInfo::Print(FILE* filePtr) const
{
char text[64];
text[63] = '\0';
int addrFamily;
if (4 == addr_version)
addrFamily = AF_INET;
else
addrFamily = AF_INET6;
inet_ntop(addrFamily, client_addr, text, 63);
fprintf(filePtr, "%s/%hu", text, client_port);
} // end ClientInfo::Print()
// C++ map used to index client sessions by the client source addr/port
typedef std::map<ClientInfo, NormSocketHandle> ClientMap;
ClientInfo NormGetClientInfo(NormNodeHandle client)
{
char addr[16]; // big enough for IPv6
unsigned int addrLen = 16;
UINT16 port;
NormNodeGetAddress(client, addr, &addrLen, &port);
int addrFamily;
UINT8 version;
if (4 == addrLen)
{
addrFamily = AF_INET;
version = 4;
}
else
{
addrFamily = AF_INET6;
version = 6;
}
return ClientInfo(version, addr, port);
} // end NormGetClientInfo()
NormSocketHandle FindClientSocket(ClientMap& clientMap, const ClientInfo& clientInfo)
{
ClientMap::iterator it = clientMap.find(clientInfo);
if (clientMap.end() != it)
return &(it->second);
else
return NORM_SOCKET_INVALID;
} // end FindClientSocket()
int main(int argc, char* argv[])
{
ClientMap clientMap;
UINT16 serverPort = 5000;
UINT16 serverInstanceId = 1;
char groupAddr[64];
const char* groupAddrPtr = NULL;
const char* mcastInterface = NULL;
bool trace = false;
unsigned int debugLevel = 0;
for (int i = 1; i < argc; i++)
{
const char* cmd = argv[i];
unsigned int len = strlen(cmd);
if (0 == strncmp(cmd, "listen", len))
{
// listen [<groupAddr>/]<port>
const char* val = argv[++i];
const char* portPtr = strchr(val, '/');
if (NULL != portPtr)
portPtr++;
else
portPtr = val;
unsigned int addrTextLen = portPtr - val;
if (addrTextLen > 0)
{
addrTextLen -= 1;
strncpy(groupAddr, val, addrTextLen);
groupAddr[addrTextLen] = '\0';
groupAddrPtr = groupAddr;
}
if (1 != sscanf(portPtr, "%hu", &serverPort))
{
fprintf(stderr, "normServer error: invalid <port> \"%s\"\n", portPtr);
return -1;
}
}
else if (0 == strncmp(cmd, "interface", len))
{
mcastInterface = argv[++i];
}
else if (0 == strncmp(cmd, "trace", len))
{
trace = true;
}
else if (0 == strncmp(cmd, "debug", len))
{
if (1 != sscanf(argv[++i], "%u", &debugLevel))
{
fprintf(stderr, "normServer error: invalid debug level\n");
return -1;
}
}
else
{
fprintf(stderr, "normServer error: invalid command \"%s\"\n", cmd);
return -1;
}
}
// For unicast operation in this demo app, the server only "talks back"
// to one client on a first come, first serve basis. (Multiple clients
// can connect and send data _to_ the server, but in this simple example,
// the server only sends to one at a time. For the multicast server case,
// the server multicasts to the entire group.
NormSocketHandle firstClientSocket = NORM_SOCKET_INVALID;
NormInstanceHandle instance = NormCreateInstance();
NormSocketHandle serverSocket = NormListen(instance, serverPort, groupAddrPtr);
if (trace) NormSetMessageTrace(NormGetSession(serverSocket), true);
if (0 != debugLevel) NormSetDebugLevel(debugLevel);
//NormSetDebugLevel(8);
//NormSetMessageTrace(NormGetSession(serverSocket), true);
// We use a select() call to multiplex input reading and NormSocket handling
fd_set fdset;
FD_ZERO(&fdset);
// Get our input (STDIN) descriptor and set non-blocking
FILE* inputFile = stdin;
int inputfd = fileno(inputFile);
if (-1 == fcntl(inputfd, F_SETFL, fcntl(inputfd, F_GETFL, 0) | O_NONBLOCK))
perror("normClient: fcntl(inputfd, O_NONBLOCK) error");
// Get our NormInstance descriptor
int normfd = NormGetDescriptor(instance);
bool keepGoing = true;
bool writeReady = false;
unsigned int inputLength = 0;
unsigned int bytesWritten = 0;
const unsigned int BUFFER_LENGTH = 2048;
char inputBuffer[BUFFER_LENGTH];
bool inputNeeded = false; // will be set to "true" upon CONNECT
while (keepGoing)
{
FD_SET(normfd, &fdset);
int maxfd = normfd;
if (inputNeeded)
{
FD_SET(inputfd, &fdset);
if (inputfd > maxfd) maxfd = inputfd;
}
else
{
FD_CLR(inputfd, &fdset);
}
int result = select(maxfd+1, &fdset, NULL, NULL, NULL);
if (result <= 0)
{
perror("normClient: select() error");
break;
}
if (FD_ISSET(inputfd, &fdset))
{
// Read input into our txBuffer
inputLength = fread(inputBuffer, 1, BUFFER_LENGTH, inputFile);
if (inputLength > 0)
{
// We got our input
bytesWritten = 0;
inputNeeded = false;
}
else if (feof(inputFile))
{
// TBD - initiate server shutdown if it's job is
// only until the input is closed
// Meanwhile, we just stick around to receive stuff from the clients
inputNeeded = false; // TBD - should also fclose(inputFile)??
}
else if (ferror(inputFile))
{
switch (errno)
{
case EINTR:
// interupted, try again
break;
case EAGAIN:
// input starved, wait for next notification
break;
default:
perror("normClient: error reading input");
break;
}
}
}
if (FD_ISSET(normfd, &fdset))
{
// There's a NORM event pending
NormSocketEvent event;
if (NormGetSocketEvent(instance, &event))
{
ClientInfo clientInfo;
if (NORM_NODE_INVALID != event.sender)
clientInfo = NormGetClientInfo(event.sender);
switch (event.type)
{
case NORM_SOCKET_ACCEPT:
{
if (event.socket == serverSocket)
{
// Possibly a new "client" connecting to our "server"
// First confirm that this really is a new client.
if (NORM_SOCKET_INVALID != FindClientSocket(clientMap, clientInfo))
{
// We think we're already connected to this client
fprintf(stderr, "normServer: duplicative %s client ...\n",
(NORM_REMOTE_SENDER_NEW == event.event.type) ? "new" : "reset");
continue;
}
NormSocketHandle clientSocket = NormAccept(serverSocket, event.sender);
// TBD - For multicast, if we are sending a tx_stream, we could flush it here to
// bring the new receiver "up to date" ... probably would be best to
// do this on some sort of timer-basis in the case of a bunch of receivers
// joining in a short window of time ...
if (trace) // note we're already tracing the mcast session
NormSetMessageTrace(NormGetSession(clientSocket), true);
//NormSetMessageTrace(NormGetSession(clientSocket), true);
clientMap[clientInfo] = clientSocket;
fprintf(stderr, "normServer: ACCEPTED connection from %s/%hu\n",
clientInfo.GetAddressString(), clientInfo.GetPort());
// We have at least one client, so lets serve up some juicy input
inputNeeded = true;
writeReady = true;
}
else
{
// shouldn't happen
}
break;
}
case NORM_SOCKET_CONNECT:
{
fprintf(stderr, "normServer: CONNECTED to %s/%hu ...\n",
clientInfo.GetAddressString(), clientInfo.GetPort());
if (NORM_SOCKET_INVALID == firstClientSocket)
firstClientSocket = event.socket;
break;
}
case NORM_SOCKET_READ:
{
// This is a cue to try to read data from stream
// For our test app here, the data is read and output to STDOUT
bool rxReady = true;
while (rxReady)
{
char buffer[1024];
ssize_t bytesRead = NormRead(event.socket, buffer, 1024);
if (bytesRead < 0)
{
// This shouldn't happen with ack-based flow control used
fprintf(stderr, "normServer: broken stream ...\n");
continue;
}
if (bytesRead > 0)
fwrite(buffer, sizeof(char), bytesRead, stdout);
if (bytesRead < 1024) rxReady = false;
}
break;
}
case NORM_SOCKET_WRITE:
// We only demo server data transmission for the multicast server case
// (see comment below)
if ((NULL != groupAddrPtr) || (event.socket == firstClientSocket))
writeReady = true;
break;
case NORM_SOCKET_CLOSING:
fprintf(stderr, "normServer: client %s/%hu CLOSING connection ...\n",
clientInfo.GetAddressString(), clientInfo.GetPort());
if (event.socket == firstClientSocket)
firstClientSocket = NORM_SOCKET_INVALID;
break;
case NORM_SOCKET_CLOSED:
{
fprintf(stderr, "normServer: connection to client %s/%hu CLOSED ...\n",
clientInfo.GetAddressString(), clientInfo.GetPort());
if (event.socket == firstClientSocket)
firstClientSocket = NORM_SOCKET_INVALID;
clientMap.erase(clientInfo);
break;
}
case NORM_SOCKET_NONE:
break;
break;
} // end switch(event.type)
}
else
{
fprintf(stderr, "normServer: NormGetNextSocketEvent() returned false\n");
}
} // end if FD_ISSET(normfd)
// For our _multicast_ "normServer" example, the server can send to the group
// (For a unicast "normServer", we would need to do something more complex
// to manage sending data to each individual client that connects to us.
// So, for the moment, the unicast "normServer" only sends to the "firstClientSocket"
NormSocketHandle sendSocket = (NULL != groupAddrPtr) ? serverSocket : firstClientSocket;
if (NORM_SOCKET_INVALID != sendSocket)
{
if (writeReady && (inputLength > 0))
{
// We have data in our inputBuffer and the NormSocket is "writeReady", so send it
bytesWritten += NormWrite(sendSocket, inputBuffer + bytesWritten, inputLength - bytesWritten);
if (bytesWritten < inputLength)
{
// Couldn't write whole inputBuffer, need to wait for NORM_SOCKET_WRITE event
writeReady = false;
}
else
{
// inputBuffer has been completely written
inputLength = 0;
inputNeeded = true;
NormFlush(sendSocket);
}
}
}
} // end while (keepGoing)
} // end main()

1037
examples/normSocket.cpp Normal file

File diff suppressed because it is too large Load Diff

120
examples/normSocket.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef _NORM_SOCKET
#define _NORM_SOCKET
// IMPORTANT NOTE: THIS IS A WORK IN PROGRESS. This code, if/when fully developed, will be
// "promoted" from the 'examples' directory to a standard part of the NORM
// library if appropriate.
// This provides a higher level API that facilitates a socket-like programming interface
// to use NORM for a specific usage pattern. The usage pattern uses NORM_OBJECT_STREAM
// (as a byte-stream initially with eventual support for NORM's message-stream capability, too)
// where "clients" explicitly connect to a "server" and bi-directional stream communication is
// established. This enables ACK-based flow control to/from the server and client(s). This
// is supported for NORM unicast and also (as this is completed) an asymmetric model where the
// server can multicast to the clients while the clients unicast back to the server.
// TODO:
//
// 0) Make "NormInstanceHandle" optional for Listen/Connect/Accept
// (for eventual blocking usage, it wouldn't be needed)
// 1) Support asymmetric server->multicast, client->unicast model
// 2) Provide non-blocking option for read/write calls
// 3) leverage ICMP (e.g., port unreachable) feedback to detect connect() failure (DONE)
// 4) provide means for connect() to time out??? (DONE)
// 5) Separate socket open (i.e. session creation) from connect/accept to allow
// opportunity for application to set NORM parameters prior to sender/receiver start
// 6) Extend to include message stream, and data/file object sockets
// 7) Option to associate NORM_INFO w/ stream (or objects eventually)
// Here is a list of NORM parameters that need to be set _before_ sender or receiver
// startup. These will need to be "NormSocket" parameters that can be set after
// NormOpen() but before NormListen(), NormAccept(), or NormConnect():
//
// a) SSM source address (perhaps incorporate into NormListen() and NormConnect()?)
// b) TTL (could be set _after_ connect/accept, but may be something convenient to preset?
// c) TOS (same as for TTL)
// d) Fragmentation (not one to worry much about initially?)
// e) FEC parameters (block size, parity count, segment size, "auto" parity)
// f) Buffer size (sender, stream, receiver)
// g) cache bounds / limits
#include "normApi.h"
typedef const void* NormSocketHandle;
extern const NormSocketHandle NORM_SOCKET_INVALID;
extern const double NORM_DEFAULT_CONNECT_TIMEOUT;
#ifndef NULL
#define NULL 0
#endif // !NULL
// Main NormSocket API Functions
NormSocketHandle NormOpen(NormInstanceHandle instance = NORM_INSTANCE_INVALID);
NormSocketHandle NormListen(NormInstanceHandle instance, UINT16 serverPort, const char* groupAddr = NULL);
NormSocketHandle NormConnect(NormInstanceHandle instance,
const char* serverAddr,
UINT16 serverPort,
const char* groupAddr = NULL,
NormNodeId clientId = NORM_NODE_NONE);
NormSocketHandle NormAccept(NormSocketHandle serverSocket, NormNodeHandle clientNode, NormInstanceHandle instance = NORM_INSTANCE_INVALID);
void NormShutdown(NormSocketHandle normSocket);
void NormClose(NormSocketHandle normSocket);
ssize_t NormRead(NormSocketHandle normSocket, void *buf, size_t nbyte);
ssize_t NormWrite(NormSocketHandle normSocket, const void *buf, size_t nbyte);
int NormFlush(NormSocketHandle normSocket);
// Helper API functions
NormSessionHandle NormGetSession(NormSocketHandle normSocket);
NormSessionHandle NormGetMulticastSession(NormSocketHandle normSocket);
typedef enum NormSocketEventType
{
NORM_SOCKET_NONE = 0,
NORM_SOCKET_ACCEPT, // only issued for listening server sockets
NORM_SOCKET_CONNECT, // notification confirming connection to server
NORM_SOCKET_READ, // edge-triggered notification that socket is ready for reading
NORM_SOCKET_WRITE, // edge-triggered notification that socket is ready for writing
NORM_SOCKET_CLOSING, // indicates remote endpoint is closing socket (only read data at this point)
NORM_SOCKET_CLOSED // indicates socket is now closed (invalid for further operations)
} NormSocketEventType;
typedef struct
{
NormSocketEventType type;
NormSocketHandle socket;
// The underlying NormEvent is embedded. The union
// here lets us access the NormEvent fields directly.
// (E.g., *.sender, *.object, etc. as needed)
union
{
NormEvent event; // underlying NormEvent that evoked this socketEvent
struct
{
NormEventType etype; // underlying NormEventType
NormSessionHandle session; // NormEvent session
NormNodeHandle sender; // NormEvent sender
NormObjectHandle object; // NormEvent object
};
};
} NormSocketEvent;
bool NormGetSocketEvent(NormInstanceHandle normInstance, NormSocketEvent* event, bool waitForEvent = true);
#endif // !_NORM_SOCKET

View File

@ -173,6 +173,8 @@ typedef enum NormEventType
NORM_TX_RATE_CHANGED, NORM_TX_RATE_CHANGED,
NORM_LOCAL_SENDER_CLOSED, NORM_LOCAL_SENDER_CLOSED,
NORM_REMOTE_SENDER_NEW, NORM_REMOTE_SENDER_NEW,
NORM_REMOTE_SENDER_RESET, // remote sender instanceId or FEC params changed
NORM_REMOTE_SENDER_ADDRESS, // remote sender src addr and/or port changed
NORM_REMOTE_SENDER_ACTIVE, NORM_REMOTE_SENDER_ACTIVE,
NORM_REMOTE_SENDER_INACTIVE, NORM_REMOTE_SENDER_INACTIVE,
NORM_REMOTE_SENDER_PURGED, // not yet implemented NORM_REMOTE_SENDER_PURGED, // not yet implemented
@ -184,7 +186,10 @@ typedef enum NormEventType
NORM_RX_OBJECT_ABORTED, NORM_RX_OBJECT_ABORTED,
NORM_GRTT_UPDATED, NORM_GRTT_UPDATED,
NORM_CC_ACTIVE, NORM_CC_ACTIVE,
NORM_CC_INACTIVE NORM_CC_INACTIVE,
NORM_ACKING_NODE_NEW, // whe NormSetAutoAcking xxx
NORM_SEND_ERROR, // ICMP error (e.g. destination unreachable)
NORM_USER_TIMEOUT // issues when timeout set by NormSetUserTimer() expires
} NormEventType; } NormEventType;
typedef struct typedef struct
@ -222,7 +227,6 @@ NORM_API_LINKAGE
void NormResumeInstance(NormInstanceHandle instanceHandle); void NormResumeInstance(NormInstanceHandle instanceHandle);
// This MUST be set to enable NORM_OBJECT_FILE reception! // This MUST be set to enable NORM_OBJECT_FILE reception!
// (otherwise received files are ignored) // (otherwise received files are ignored)
NORM_API_LINKAGE NORM_API_LINKAGE
@ -263,6 +267,9 @@ NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
NORM_API_LINKAGE NORM_API_LINKAGE
void NormDestroySession(NormSessionHandle sessionHandle); void NormDestroySession(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
NormInstanceHandle NormGetInstance(NormSessionHandle sessionHandle);
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormIsUnicastAddress(const char* address); bool NormIsUnicastAddress(const char* address);
@ -272,10 +279,19 @@ void NormSetUserData(NormSessionHandle sessionHandle, const void* userData);
NORM_API_LINKAGE NORM_API_LINKAGE
const void* NormGetUserData(NormSessionHandle sessionHandle); const void* NormGetUserData(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
void NormSetUserTimer(NormSessionHandle sessionHandle, double seconds);
NORM_API_LINKAGE
void NormCancelUserTimer(NormSessionHandle sessionHandle);
NORM_API_LINKAGE NORM_API_LINKAGE
NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle); NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle);
NORM_API_LINKAGE
UINT16 NormGetRxPort(NormSessionHandle sessionHandle);
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormSetTxPort(NormSessionHandle sessionHandle, bool NormSetTxPort(NormSessionHandle sessionHandle,
UINT16 txPortNumber, UINT16 txPortNumber,
@ -291,12 +307,13 @@ void NormSetTxOnly(NormSessionHandle sessionHandle,
bool connectToSessionAddress DEFAULT(false)); bool connectToSessionAddress DEFAULT(false));
// This does not affect the rx_socket binding if already bound // This does not affect the rx_socket binding if already bound (sender or receiver already started)
// (i.e., just affects where NORM packets are sent) // (i.e., just affects where NORM packets are sent)
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormChangeDestination(NormSessionHandle sessionHandle, bool NormChangeDestination(NormSessionHandle sessionHandle,
const char* sessionAddress, const char* sessionAddress,
UINT16 sessionPort); UINT16 sessionPort,
bool connectToSessionAddress DEFAULT(false));
NORM_API_LINKAGE NORM_API_LINKAGE
void NormSetRxPortReuse(NormSessionHandle sessionHandle, void NormSetRxPortReuse(NormSessionHandle sessionHandle,
@ -319,6 +336,10 @@ NORM_API_LINKAGE
bool NormSetMulticastInterface(NormSessionHandle sessionHandle, bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
const char* interfaceName); const char* interfaceName);
NORM_API_LINKAGE
bool NormSetSSM(NormSessionHandle sessionHandle,
const char* sourceAddress);
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormSetTTL(NormSessionHandle sessionHandle, bool NormSetTTL(NormSessionHandle sessionHandle,
unsigned char ttl); unsigned char ttl);
@ -331,6 +352,10 @@ NORM_API_LINKAGE
bool NormSetLoopback(NormSessionHandle sessionHandle, bool NormSetLoopback(NormSessionHandle sessionHandle,
bool loopback); bool loopback);
NORM_API_LINKAGE
bool NormSetMulticastLoopback(NormSessionHandle sessionHandle,
bool loopback);
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormSetFragmentation(NormSessionHandle sessionHandle, bool NormSetFragmentation(NormSessionHandle sessionHandle,
@ -375,13 +400,17 @@ double NormGetReportInterval(NormSessionHandle sessionHandle);
NORM_API_LINKAGE NORM_API_LINKAGE
NormSessionId NormGetRandomSessionId(); NormSessionId NormGetRandomSessionId();
// This function has been updated so that 16-bit Reed-Solomon
// codecs can be accessed. This may cause an issue for linking
// to older versions of the NORM library
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormStartSender(NormSessionHandle sessionHandle, bool NormStartSender(NormSessionHandle sessionHandle,
NormSessionId instanceId, NormSessionId instanceId,
UINT32 bufferSpace, UINT32 bufferSpace,
UINT16 segmentSize, UINT16 segmentSize,
unsigned char numData, UINT16 numData,
unsigned char numParity); UINT16 numParity);
NORM_API_LINKAGE NORM_API_LINKAGE
void NormStopSender(NormSessionHandle sessionHandle); void NormStopSender(NormSessionHandle sessionHandle);
@ -529,6 +558,10 @@ NORM_API_LINKAGE
void NormRemoveAckingNode(NormSessionHandle sessionHandle, void NormRemoveAckingNode(NormSessionHandle sessionHandle,
NormNodeId nodeId); NormNodeId nodeId);
NORM_API_LINKAGE
NormNodeHandle NormGetAckingNodeHandle(NormSessionHandle sessionHandle,
NormNodeId nodeId);
NORM_API_LINKAGE NORM_API_LINKAGE
void NormSetAutoAckingNodes(NormSessionHandle sessionHandle, void NormSetAutoAckingNodes(NormSessionHandle sessionHandle,
NormTrackingStatus trackingStatus); NormTrackingStatus trackingStatus);
@ -540,7 +573,7 @@ NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormGetNextAckingNode(NormSessionHandle sessionHandle, bool NormGetNextAckingNode(NormSessionHandle sessionHandle,
NormNodeId* nodeId, NormNodeId* nodeId,
NormAckingStatus* ackingStatus); NormAckingStatus* ackingStatus DEFAULT(0));
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormSendCommand(NormSessionHandle sessionHandle, bool NormSendCommand(NormSessionHandle sessionHandle,
@ -687,6 +720,12 @@ bool NormNodeGetAddress(NormNodeHandle nodeHandle,
unsigned int* bufferLen, unsigned int* bufferLen,
UINT16* port DEFAULT((UINT16*)0)); UINT16* port DEFAULT((UINT16*)0));
NORM_API_LINKAGE
void NormNodeSetUserData(NormNodeHandle nodeHandle, const void* userData);
NORM_API_LINKAGE
const void* NormNodeGetUserData(NormNodeHandle nodeHandle);
NORM_API_LINKAGE NORM_API_LINKAGE
double NormNodeGetGrtt(NormNodeHandle remoteSender); double NormNodeGetGrtt(NormNodeHandle remoteSender);
@ -702,7 +741,22 @@ void NormNodeFreeBuffers(NormNodeHandle remoteSender);
NORM_API_LINKAGE NORM_API_LINKAGE
void NormNodeDelete(NormNodeHandle remoteSender); void NormNodeDelete(NormNodeHandle remoteSender);
// The next 4 functions have not yet been implemented NORM_API_LINKAGE
void NormNodeRetain(NormNodeHandle nodeHandle);
NORM_API_LINKAGE
void NormNodeRelease(NormNodeHandle nodeHandle);
/** Some experimental functions */
NORM_API_LINKAGE
void NormReleasePreviousEvent(NormInstanceHandle instanceHandle);
NORM_API_LINKAGE
UINT32 NormCountCompletedObjects(NormSessionHandle sessionHandle);
// The next functions have _not_ yet been implemented
// (work in progress) // (work in progress)
NORM_API_LINKAGE NORM_API_LINKAGE
void NormNodeSetAutoDelete(NormNodeHandle remoteSender, void NormNodeSetAutoDelete(NormNodeHandle remoteSender,
@ -714,18 +768,6 @@ bool NormNodeAllowSender(NormNodeId senderId);
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormNodeDenySender(NormNodeId senderId); bool NormNodeDenySender(NormNodeId senderId);
NORM_API_LINKAGE
void NormNodeRetain(NormNodeHandle nodeHandle);
NORM_API_LINKAGE
void NormNodeRelease(NormNodeHandle nodeHandle);
/** Some experimental functions */
NORM_API_LINKAGE
UINT32 NormCountCompletedObjects(NormSessionHandle sessionHandle);
#ifdef __cplusplus #ifdef __cplusplus
} // end extern "C" } // end extern "C"
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@ -120,12 +120,12 @@ class NormObjectSize
NormObjectSize(UINT16 msb, UINT32 lsb) NormObjectSize(UINT16 msb, UINT32 lsb)
{ {
size = (Offset)lsb; size = (Offset)lsb;
#if _FILE_OFFSET_BITS > 32 #if (_FILE_OFFSET_BITS > 32) && !defined(ANDROID)
size |= ((Offset)msb) << 32; size |= ((Offset)msb) << 32;
#endif #endif
} }
Offset GetOffset() const {return size;} Offset GetOffset() const {return size;}
#if _FILE_OFFSET_BITS > 32 #if (_FILE_OFFSET_BITS > 32) && !defined(ANDROID)
UINT16 MSB() const {return ((UINT16)((size >> 32) & 0x0000ffff));} UINT16 MSB() const {return ((UINT16)((size >> 32) & 0x0000ffff));}
#else #else
UINT16 MSB() const {return 0;} UINT16 MSB() const {return 0;}

View File

@ -14,13 +14,28 @@ class NormNode
friend class NormNodeListIterator; friend class NormNodeListIterator;
public: public:
NormNode(class NormSession& theSession, NormNodeId nodeId); enum Type
{
ACKER,
SENDER,
CC_NODE
};
NormNode(Type theType, class NormSession& theSession, NormNodeId nodeId);
virtual ~NormNode(); virtual ~NormNode();
Type GetType() const
{return node_type;}
NormSession& GetSession() const {return session;} NormSession& GetSession() const {return session;}
void Retain(); void Retain();
void Release(); void Release();
void SetUserData(const void* userData)
{user_data = userData;}
const void* GetUserData() const
{return user_data;}
const ProtoAddress& GetAddress() const {return addr;} const ProtoAddress& GetAddress() const {return addr;}
void SetAddress(const ProtoAddress& address) {addr = address;} void SetAddress(const ProtoAddress& address) {addr = address;}
const NormNodeId& GetId() const {return id;} const NormNodeId& GetId() const {return id;}
@ -52,9 +67,11 @@ class NormNode
class NormSession& session; class NormSession& session;
private: private:
Type node_type;
NormNodeId id; NormNodeId id;
ProtoAddress addr; ProtoAddress addr;
unsigned int reference_count; unsigned int reference_count;
const void* user_data;
// We keep NormNodes in a binary tree (TBD) make this a ProtoTree // We keep NormNodes in a binary tree (TBD) make this a ProtoTree
NormNode* parent; NormNode* parent;
NormNode* right; NormNode* right;
@ -544,6 +561,7 @@ class NormSenderNode : public NormNode
// Watermark acknowledgement // Watermark acknowledgement
ProtoTimer ack_timer; ProtoTimer ack_timer;
bool ack_pending;
NormObjectId watermark_object_id; NormObjectId watermark_object_id;
NormBlockId watermark_block_id; NormBlockId watermark_block_id;
NormSegmentId watermark_segment_id; NormSegmentId watermark_segment_id;

View File

@ -40,6 +40,8 @@ class NormController
TX_RATE_CHANGED, TX_RATE_CHANGED,
LOCAL_SENDER_CLOSED, LOCAL_SENDER_CLOSED,
REMOTE_SENDER_NEW, REMOTE_SENDER_NEW,
REMOTE_SENDER_RESET,
REMOTE_SENDER_ADDRESS,
REMOTE_SENDER_ACTIVE, REMOTE_SENDER_ACTIVE,
REMOTE_SENDER_INACTIVE, REMOTE_SENDER_INACTIVE,
REMOTE_SENDER_PURGED, REMOTE_SENDER_PURGED,
@ -51,13 +53,16 @@ class NormController
RX_OBJECT_ABORTED, RX_OBJECT_ABORTED,
GRTT_UPDATED, GRTT_UPDATED,
CC_ACTIVE, // posted when cc feedback is detected CC_ACTIVE, // posted when cc feedback is detected
CC_INACTIVE // posted when no cc feedback and min rate reached CC_INACTIVE, // posted when no cc feedback and min rate reached
ACKING_NODE_NEW,
SEND_ERROR,
USER_TIMEOUT
}; };
virtual void Notify(NormController::Event event, virtual void Notify(NormController::Event event,
class NormSessionMgr* sessionMgr, class NormSessionMgr* sessionMgr,
class NormSession* session, class NormSession* session,
class NormSenderNode* sender, class NormNode* node,
class NormObject* object) = 0; class NormObject* object) = 0;
}; // end class NormController }; // end class NormController
@ -81,11 +86,11 @@ class NormSessionMgr
void Notify(NormController::Event event, void Notify(NormController::Event event,
class NormSession* session, class NormSession* session,
class NormSenderNode* sender, class NormNode* node,
class NormObject* object) class NormObject* object)
{ {
if (controller) if (controller)
controller->Notify(event, this, session, sender, object); controller->Notify(event, this, session, node, object);
} }
void ActivateTimer(ProtoTimer& timer) {timer_mgr.ActivateTimer(timer);} void ActivateTimer(ProtoTimer& timer) {timer_mgr.ActivateTimer(timer);}
@ -163,6 +168,7 @@ class NormSession
const ProtoAddress& Address() {return address;} const ProtoAddress& Address() {return address;}
void SetAddress(const ProtoAddress& addr) {address = addr;} void SetAddress(const ProtoAddress& addr) {address = addr;}
bool SetMulticastInterface(const char* interfaceName); bool SetMulticastInterface(const char* interfaceName);
bool SetSSM(const char* sourceAddress);
bool SetTTL(UINT8 theTTL) bool SetTTL(UINT8 theTTL)
{ {
bool result = tx_socket->IsOpen() ? tx_socket->SetTTL(theTTL) : true; bool result = tx_socket->IsOpen() ? tx_socket->SetTTL(theTTL) : true;
@ -179,11 +185,18 @@ class NormSession
} }
bool SetLoopback(bool state) bool SetLoopback(bool state)
{ {
bool result = tx_socket->IsOpen() ? tx_socket->SetLoopback(state) : true; bool result = state ? SetMulticastLoopback(true) : true;
loopback = result ? state : loopback; loopback = result ? state : loopback;
return result; return result;
} }
bool SetMulticastLoopback(bool state)
{
bool result = tx_socket->IsOpen() ? tx_socket->SetLoopback(state) : true;
mcast_loopback = result ? state : mcast_loopback;
return result;
}
bool SetFragmentation(bool state) bool SetFragmentation(bool state)
{ {
bool result = tx_socket->IsOpen() ? tx_socket->SetFragmentation(state) : true; bool result = tx_socket->IsOpen() ? tx_socket->SetFragmentation(state) : true;
@ -289,11 +302,11 @@ class NormSession
unsigned long countMin, unsigned long countMin,
unsigned long countMax); unsigned long countMax);
void Notify(NormController::Event event, void Notify(NormController::Event event,
class NormSenderNode* sender, class NormNode* node,
class NormObject* object) class NormObject* object)
{ {
notify_pending = true; notify_pending = true;
session_mgr.Notify(event, this, sender, object); session_mgr.Notify(event, this, node, object);
notify_pending = false; notify_pending = false;
} }
@ -308,6 +321,8 @@ class NormSession
const void* GetUserData() const const void* GetUserData() const
{return user_data;} {return user_data;}
void SetUserTimer(double seconds); // set to value less than zero to cancel
// Sender methods // Sender methods
void SenderSetBaseObjectId(NormObjectId baseId) void SenderSetBaseObjectId(NormObjectId baseId)
{ {
@ -322,6 +337,8 @@ class NormSession
UINT16 numParity); UINT16 numParity);
void StopSender(); void StopSender();
void SetTxOnly(bool txOnly, bool connectToSessionAddress = false); void SetTxOnly(bool txOnly, bool connectToSessionAddress = false);
bool GetTxOnly() const
{return tx_only;}
NormStreamObject* QueueTxStream(UINT32 bufferSize, NormStreamObject* QueueTxStream(UINT32 bufferSize,
bool doubleBuffer = false, bool doubleBuffer = false,
@ -353,12 +370,17 @@ class NormSession
void SenderSetAutoAckingNodes(TrackingStatus trackingStatus) void SenderSetAutoAckingNodes(TrackingStatus trackingStatus)
{acking_auto_populate = trackingStatus;} {acking_auto_populate = trackingStatus;}
bool SenderAddAckingNode(NormNodeId nodeId); NormAckingNode* SenderAddAckingNode(NormNodeId nodeId, const ProtoAddress* srcAddr = NULL);
void SenderRemoveAckingNode(NormNodeId nodeId); void SenderRemoveAckingNode(NormNodeId nodeId);
AckingStatus SenderGetAckingStatus(NormNodeId nodeId); AckingStatus SenderGetAckingStatus(NormNodeId nodeId);
// Set "prevNodeId = NORM_NODE_NONE" to init this iteration (returns "false" when done) // Set "prevNodeId = NORM_NODE_NONE" to init this iteration (returns "false" when done)
bool SenderGetNextAckingNode(NormNodeId& prevNodeId, AckingStatus* ackingStatus = NULL); bool SenderGetNextAckingNode(NormNodeId& prevNodeId, AckingStatus* ackingStatus = NULL);
NormAckingNode* SenderFindAckingNode(NormNodeId nodeId) const
{
return static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
}
// App-defined command support methods // App-defined command support methods
bool SenderSendCmd(const char* cmdBuffer, unsigned int cmdLength, bool robust); bool SenderSendCmd(const char* cmdBuffer, unsigned int cmdLength, bool robust);
void SenderCancelCmd(); void SenderCancelCmd();
@ -557,6 +579,7 @@ class NormSession
bool OnReportTimeout(ProtoTimer& theTimer); bool OnReportTimeout(ProtoTimer& theTimer);
bool OnCmdTimeout(ProtoTimer& theTimer); bool OnCmdTimeout(ProtoTimer& theTimer);
bool OnFlowControlTimeout(ProtoTimer& theTimer); bool OnFlowControlTimeout(ProtoTimer& theTimer);
bool OnUserTimeout(ProtoTimer& theTimer);
void TxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent); void TxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
void RxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent); void RxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
@ -624,12 +647,14 @@ class NormSession
// General session parameters // General session parameters
NormNodeId local_node_id; NormNodeId local_node_id;
ProtoAddress address; // session destination address/port ProtoAddress address; // session destination address/port
UINT8 ttl; // session multicast ttl ProtoAddress ssm_source_addr; // optional SSM source address
UINT8 tos; // session IPv4 TOS (or IPv6 traffic class - TBD) UINT8 ttl; // session multicast ttl
bool loopback; // receive own traffic it true UINT8 tos; // session IPv4 TOS (or IPv6 traffic class - TBD)
bool fragmentation; // enable UDP/IP fragmentation (i.e. clear DF bit) if true bool loopback; // receive own traffic it true
bool ecn_enabled; // set true to get raw packets and check for ECN status bool mcast_loopback; // enable socket multicast loopback if true
bool fragmentation; // enable UDP/IP fragmentation (i.e. clear DF bit) if true
bool ecn_enabled; // set true to get raw packets and check for ECN status
char interface_name[IFACE_NAME_MAX+1]; char interface_name[IFACE_NAME_MAX+1];
double tx_rate; // bytes per second double tx_rate; // bytes per second
@ -763,6 +788,7 @@ class NormSession
double rx_loss_rate; // for uncorrelated loss double rx_loss_rate; // for uncorrelated loss
double report_timer_interval; double report_timer_interval;
ProtoTimer user_timer;
const void* user_data; const void* user_data;
// Linkers // Linkers
@ -774,6 +800,7 @@ void NormTrace(const struct timeval& currentTime,
NormNodeId localId, NormNodeId localId,
const NormMsg& msg, const NormMsg& msg,
bool sent, bool sent,
UINT8 fecM); UINT8 fecM,
UINT16 instId = 0); // this might not always be available to caller
#endif // _NORM_SESSION #endif // _NORM_SESSION

View File

@ -36,6 +36,6 @@
#ifndef _NORM_VERSION #ifndef _NORM_VERSION
#define _NORM_VERSION #define _NORM_VERSION
#define VERSION "1.5b4" #define VERSION "1.5r5"
#endif // _NORM_VERSION #endif // _NORM_VERSION

View File

@ -15,6 +15,7 @@ NS = ../src/sim/ns
INCLUDES = $(SYSTEM_INCLUDES) -I$(UNIX) -I../include -I$(PROTOLIB)/include INCLUDES = $(SYSTEM_INCLUDES) -I$(UNIX) -I../include -I$(PROTOLIB)/include
CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 -O $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES) CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 -O $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES)
#CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES)
LDFLAGS = $(SYSTEM_LDFLAGS) LDFLAGS = $(SYSTEM_LDFLAGS)
@ -239,7 +240,7 @@ gtf: $(GTF_OBJ)
cp $@ ../bin/$@ cp $@ ../bin/$@
clean: clean:
rm -f $(COMMON)/*.o $(UNIX)/*.o $(NS)/*.o \ rm -f $(COMMON)/*.o $(UNIX)/*.o $(NS)/*.o $(EXAMPLE)/*.o \
libnorm.a libnorm.$(SYSTEM_SOEXT) ../lib/libnorm.a ../lib/libnorm.$(SYSTEM_SOEXT) \ libnorm.a libnorm.$(SYSTEM_SOEXT) ../lib/libnorm.a ../lib/libnorm.$(SYSTEM_SOEXT) \
norm raft normTest normTest2 normThreadTest normThreadTest2 ../bin/*; norm raft normTest normTest2 normThreadTest normThreadTest2 ../bin/*;
$(MAKE) -C $(PROTOLIB)/makefiles -f Makefile.$(SYSTEM) clean $(MAKE) -C $(PROTOLIB)/makefiles -f Makefile.$(SYSTEM) clean

View File

@ -40,9 +40,10 @@ SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DI
SYSTEM_SRC = SYSTEM_SRC =
SYSTEM = freebsd SYSTEM = freebsd
CC = g++ CC = c++
SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align
SYSTEM_SOFLAGS = -shared SYSTEM_SOFLAGS = -shared
SYSTEM_SOEXT = so
RANLIB = ranlib RANLIB = ranlib
AR = ar AR = ar

View File

@ -37,7 +37,7 @@ SYSTEM_LIBS = -lresolv -lpcap
# #
SYSTEM_HAVES = -DMACOSX -DECN_SUPPORT -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK \ SYSTEM_HAVES = -DMACOSX -DECN_SUPPORT -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK \
-D_FILE_OFFSET_BITS=64 -DHAVE_DIRFD -D_FILE_OFFSET_BITS=64 -DHAVE_DIRFD -DUSE_SELECT
SYSTEM_SRC = ../protolib/src/unix/bpfCap.cpp SYSTEM_SRC = ../protolib/src/unix/bpfCap.cpp

View File

@ -0,0 +1,63 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormLib", "NormLib.vcproj", "{D7B0023C-8798-4918-8DA0-05C9054D70B9}"
ProjectSection(ProjectDependencies) = postProject
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "norm", "norm\norm.vcproj", "{6E1308A6-D40F-489E-A4F1-40D859380D64}"
ProjectSection(ProjectDependencies) = postProject
{D7B0023C-8798-4918-8DA0-05C9054D70B9} = {D7B0023C-8798-4918-8DA0-05C9054D70B9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "normTest", "normTest.vcproj", "{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}"
ProjectSection(ProjectDependencies) = postProject
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}
{182006F3-188F-466E-89FE-8421C0478691} = {182006F3-188F-466E-89FE-8421C0478691}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormDll", "NormDll.vcproj", "{182006F3-188F-466E-89FE-8421C0478691}"
ProjectSection(ProjectDependencies) = postProject
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npc", "npc.vcproj", "{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}"
ProjectSection(ProjectDependencies) = postProject
{D7B0023C-8798-4918-8DA0-05C9054D70B9} = {D7B0023C-8798-4918-8DA0-05C9054D70B9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Protokit", "..\..\protolib\makefiles\win32\Protokit.vcproj", "{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D7B0023C-8798-4918-8DA0-05C9054D70B9}.Debug|Win32.ActiveCfg = Debug|Win32
{D7B0023C-8798-4918-8DA0-05C9054D70B9}.Debug|Win32.Build.0 = Debug|Win32
{D7B0023C-8798-4918-8DA0-05C9054D70B9}.Release|Win32.ActiveCfg = Release|Win32
{D7B0023C-8798-4918-8DA0-05C9054D70B9}.Release|Win32.Build.0 = Release|Win32
{6E1308A6-D40F-489E-A4F1-40D859380D64}.Debug|Win32.ActiveCfg = Debug|Win32
{6E1308A6-D40F-489E-A4F1-40D859380D64}.Debug|Win32.Build.0 = Debug|Win32
{6E1308A6-D40F-489E-A4F1-40D859380D64}.Release|Win32.ActiveCfg = Release|Win32
{6E1308A6-D40F-489E-A4F1-40D859380D64}.Release|Win32.Build.0 = Release|Win32
{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug|Win32.ActiveCfg = Debug|Win32
{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug|Win32.Build.0 = Debug|Win32
{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release|Win32.ActiveCfg = Release|Win32
{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release|Win32.Build.0 = Release|Win32
{182006F3-188F-466E-89FE-8421C0478691}.Debug|Win32.ActiveCfg = Debug|Win32
{182006F3-188F-466E-89FE-8421C0478691}.Debug|Win32.Build.0 = Debug|Win32
{182006F3-188F-466E-89FE-8421C0478691}.Release|Win32.ActiveCfg = Release|Win32
{182006F3-188F-466E-89FE-8421C0478691}.Release|Win32.Build.0 = Release|Win32
{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Debug|Win32.ActiveCfg = Debug|Win32
{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Release|Win32.ActiveCfg = Release|Win32
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug|Win32.ActiveCfg = Debug|Win32
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug|Win32.Build.0 = Debug|Win32
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|Win32.ActiveCfg = Release|Win32
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,32 +1,18 @@
Microsoft Visual Studio Solution File, Format Version 10.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2008 # Visual Studio Express 2013 for Windows Desktop
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormLib", "NormLib.vcproj", "{D7B0023C-8798-4918-8DA0-05C9054D70B9}" VisualStudioVersion = 12.0.30723.0
ProjectSection(ProjectDependencies) = postProject MinimumVisualStudioVersion = 10.0.40219.1
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormLib", "NormLib.vcxproj", "{D7B0023C-8798-4918-8DA0-05C9054D70B9}"
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "norm", "norm\norm.vcproj", "{6E1308A6-D40F-489E-A4F1-40D859380D64}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "norm", "norm\norm.vcxproj", "{6E1308A6-D40F-489E-A4F1-40D859380D64}"
ProjectSection(ProjectDependencies) = postProject
{D7B0023C-8798-4918-8DA0-05C9054D70B9} = {D7B0023C-8798-4918-8DA0-05C9054D70B9}
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "normTest", "normTest.vcproj", "{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "normTest", "normTest.vcxproj", "{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}"
ProjectSection(ProjectDependencies) = postProject
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}
{182006F3-188F-466E-89FE-8421C0478691} = {182006F3-188F-466E-89FE-8421C0478691}
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormDll", "NormDll.vcproj", "{182006F3-188F-466E-89FE-8421C0478691}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormDll", "NormDll.vcxproj", "{182006F3-188F-466E-89FE-8421C0478691}"
ProjectSection(ProjectDependencies) = postProject
{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npc", "npc.vcproj", "{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npc", "npc.vcxproj", "{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}"
ProjectSection(ProjectDependencies) = postProject
{D7B0023C-8798-4918-8DA0-05C9054D70B9} = {D7B0023C-8798-4918-8DA0-05C9054D70B9}
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Protokit", "..\..\protolib\makefiles\win32\Protokit.vcproj", "{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Protokit", "..\..\protolib\makefiles\win32\Protokit.vcxproj", "{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

Binary file not shown.

125
makefiles/win32/NormDll.vcxproj Executable file
View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{182006F3-188F-466E-89FE-8421C0478691}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>Debug\</OutDir>
<IntDir>Debug\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>Release\</OutDir>
<IntDir>Release\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NORM_USE_DLL;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)Norm.dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)NormDll.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<ImportLibrary>$(OutDir)Norm.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NORM_USE_DLL;NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)Norm.dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<ImportLibrary>$(OutDir)Norm.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\common\galois.cpp" />
<ClCompile Include="..\..\src\common\normApi.cpp" />
<ClCompile Include="..\..\src\common\normEncoder.cpp" />
<ClCompile Include="..\..\src\common\normEncoderMDP.cpp" />
<ClCompile Include="..\..\src\common\normEncoderRS16.cpp" />
<ClCompile Include="..\..\src\common\normEncoderRS8.cpp" />
<ClCompile Include="..\..\src\common\normFile.cpp" />
<ClCompile Include="..\..\src\common\normMessage.cpp" />
<ClCompile Include="..\..\src\common\normNode.cpp" />
<ClCompile Include="..\..\src\common\normObject.cpp" />
<ClCompile Include="..\..\src\common\normSegment.cpp" />
<ClCompile Include="..\..\src\common\normSession.cpp" />
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\protolib\makefiles\win32\Protokit.vcxproj">
<Project>{de94f096-a09b-44b6-8efe-c7bf1f65c4c9}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

121
makefiles/win32/NormLib.vcxproj Executable file
View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D7B0023C-8798-4918-8DA0-05C9054D70B9}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\Debug\</OutDir>
<IntDir>.\Debug\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.\Release\</OutDir>
<IntDir>.\Release\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Debug/NormLib.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Lib>
<OutputFile>.\Debug\NormLib.lib</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Release/NormLib.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Lib>
<OutputFile>.\Release\NormLib.lib</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\common\galois.cpp" />
<ClCompile Include="..\..\src\common\normApi.cpp" />
<ClCompile Include="..\..\src\common\normEncoder.cpp" />
<ClCompile Include="..\..\src\common\normEncoderMDP.cpp" />
<ClCompile Include="..\..\src\common\normEncoderRS16.cpp" />
<ClCompile Include="..\..\src\common\normEncoderRS8.cpp" />
<ClCompile Include="..\..\src\common\normFile.cpp" />
<ClCompile Include="..\..\src\common\normMessage.cpp" />
<ClCompile Include="..\..\src\common\normNode.cpp" />
<ClCompile Include="..\..\src\common\normObject.cpp" />
<ClCompile Include="..\..\src\common\normSegment.cpp" />
<ClCompile Include="..\..\src\common\normSession.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

15
makefiles/win32/README.TXT Executable file
View File

@ -0,0 +1,15 @@
Visual Studio 2012 and 2013 require different versions of the Platform Toolset:
Visual Studio 2012 v110 (or v110_xp for applications that need to run
under Windows XP)
Visual Studio 2013 v120 (or v120_xp for applications that need to run
under Windows XP)
For each project included by the solution file modify the Platform
Toolset under project Configuration Properties, General as appropriate
for your Visual Studio version.
A Visual Studio solutions file and associated .vcproj files are
included as a convenience for those using earlier versions of visual
studio (2008 and 2010): Norm-2008.sln

155
makefiles/win32/norm/norm.vcxproj Executable file
View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{6E1308A6-D40F-489E-A4F1-40D859380D64}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>11.0.61030.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\Debug\</OutDir>
<IntDir>.\Debug\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.\Release\</OutDir>
<IntDir>.\Release\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Debug/norm.tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<AdditionalOptions>/vmg %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\include;..\..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Debug/norm.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Debug/norm.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/norm.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Release/norm.tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<AdditionalOptions>/vmg %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\include;..\..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Release/norm.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Release/norm.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ProgramDatabaseFile>.\Release/norm.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\common\normApp.cpp" />
<ClCompile Include="..\..\..\src\common\normPostProcess.cpp" />
<ClCompile Include="..\win32PostProcess.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\protolib\makefiles\win32\Protokit.vcxproj">
<Project>{de94f096-a09b-44b6-8efe-c7bf1f65c4c9}</Project>
</ProjectReference>
<ProjectReference Include="..\NormLib.vcxproj">
<Project>{d7b0023c-8798-4918-8da0-05c9054d70b9}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

149
makefiles/win32/normTest.vcxproj Executable file
View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}</ProjectGuid>
<RootNamespace>normTest</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\Debug\</OutDir>
<IntDir>.\Debug\</IntDir>
<LinkIncremental />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.\Release\</OutDir>
<IntDir>.\Release\</IntDir>
<IgnoreImportLibrary>false</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<TypeLibraryName>.\Debug/normTest.tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NORM_USE_DLL;PROTO_DEBUG;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Debug/normTest.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Debug/normTest.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>./;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/normTest.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<TypeLibraryName>.\Release/normTest.tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NORM_USE_DLL;PROTO_DEBUG;WIN32;HAVE_ASSERT;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Release/normTest.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Release/normTest.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ProgramDatabaseFile>.\Release/normTest.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\common\normTest.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\protolib\makefiles\win32\Protokit.vcxproj">
<Project>{de94f096-a09b-44b6-8efe-c7bf1f65c4c9}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="NormDll.vcxproj">
<Project>{182006f3-188f-466e-89fe-8421c0478691}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

141
makefiles/win32/npc.vcxproj Executable file
View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}</ProjectGuid>
<RootNamespace>normTest</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\Debug\</OutDir>
<IntDir>.\Debug\</IntDir>
<LinkIncremental />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.\Release\</OutDir>
<IntDir>.\Release\</IntDir>
<IgnoreImportLibrary>false</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<TypeLibraryName>.\Debug/normTest.tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Debug/normTest.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>./;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<TypeLibraryName>.\Release/normTest.tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>.\Release/normTest.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\common\normPrecode.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="NormLib.vcxproj">
<Project>{d7b0023c-8798-4918-8da0-05c9054d70b9}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -40,7 +40,7 @@ class NormInstance : public NormController
void Notify(NormController::Event event, void Notify(NormController::Event event,
class NormSessionMgr* sessionMgr, class NormSessionMgr* sessionMgr,
class NormSession* session, class NormSession* session,
class NormSenderNode* sender, class NormNode* node,
class NormObject* object); class NormObject* object);
bool Startup(bool priorityBoost = false); bool Startup(bool priorityBoost = false);
@ -68,10 +68,13 @@ class NormInstance : public NormController
bool GetNextEvent(NormEvent* theEvent); bool GetNextEvent(NormEvent* theEvent);
bool SetCacheDirectory(const char* cachePath); bool SetCacheDirectory(const char* cachePath);
void ReleasePreviousEvent();
bool NotifyQueueIsEmpty() const bool NotifyQueueIsEmpty() const
{return notify_queue.IsEmpty();} {return notify_queue.IsEmpty();}
void PurgeSessionNotifications(NormSessionHandle sessionHandle); void PurgeSessionNotifications(NormSessionHandle sessionHandle);
void PurgeNodeNotifications(NormNodeHandle nodeHandle);
void PurgeObjectNotifications(NormObjectHandle objectHandle); void PurgeObjectNotifications(NormObjectHandle objectHandle);
void PurgeNotifications(NormSessionHandle sessionHandle, NormEventType eventType); void PurgeNotifications(NormSessionHandle sessionHandle, NormEventType eventType);
@ -96,7 +99,7 @@ class NormInstance : public NormController
static NormInstance* GetInstanceFromNode(NormNodeHandle nodeHandle) static NormInstance* GetInstanceFromNode(NormNodeHandle nodeHandle)
{ {
if (NORM_NODE_INVALID == nodeHandle) return ((NormInstance*)NULL); if (NORM_NODE_INVALID == nodeHandle) return ((NormInstance*)NULL);
NormSession& session = ((NormSenderNode*)nodeHandle)->GetSession(); NormSession& session = ((NormNode*)nodeHandle)->GetSession();
return static_cast<NormInstance*>(session.GetSessionMgr().GetController()); return static_cast<NormInstance*>(session.GetSessionMgr().GetController());
} }
static NormInstance* GetInstanceFromObject(NormObjectHandle objectHandle) static NormInstance* GetInstanceFromObject(NormObjectHandle objectHandle)
@ -158,6 +161,17 @@ class NormInstance : public NormController
NormSessionMgr session_mgr; NormSessionMgr session_mgr;
private: private:
void ResetNotificationEvent()
{
#ifdef WIN32
if (0 == ResetEvent(notify_event))
PLOG(PL_ERROR, "NormInstance::GetNextEvent() ResetEvent error: %s\n", GetErrorString());
#else
char byte[32];
while (read(notify_fd[0], byte, 32) > 0); // TBD - error check
#endif // if/else WIN32/UNIX
}
Notification::Queue notify_pool; Notification::Queue notify_pool;
Notification::Queue notify_queue; Notification::Queue notify_queue;
Notification* previous_notification; Notification* previous_notification;
@ -248,7 +262,7 @@ bool NormInstance::SetCacheDirectory(const char* cachePath)
void NormInstance::Notify(NormController::Event event, void NormInstance::Notify(NormController::Event event,
class NormSessionMgr* sessionMgr, class NormSessionMgr* sessionMgr,
class NormSession* session, class NormSession* session,
class NormSenderNode* sender, class NormNode* node,
class NormObject* object) class NormObject* object)
{ {
// (TBD) set a limit on how many pending notifications // (TBD) set a limit on how many pending notifications
@ -389,13 +403,13 @@ void NormInstance::Notify(NormController::Event event,
// "Retain" any valid "object" or "sender" handles for API access // "Retain" any valid "object" or "sender" handles for API access
if (NORM_OBJECT_INVALID != object) if (NORM_OBJECT_INVALID != object)
((NormObject*)object)->Retain(); ((NormObject*)object)->Retain();
else if (NORM_NODE_INVALID != sender) else if (NORM_NODE_INVALID != node)
((NormSenderNode*)sender)->Retain(); ((NormNode*)node)->Retain();
bool doNotify = notify_queue.IsEmpty(); bool doNotify = notify_queue.IsEmpty();
n->event.type = (NormEventType)event; n->event.type = (NormEventType)event;
n->event.session = session; n->event.session = session;
n->event.sender = sender; n->event.sender = node;
n->event.object = object; n->event.object = object;
notify_queue.Append(n); notify_queue.Append(n);
@ -422,6 +436,7 @@ void NormInstance::Notify(NormController::Event event,
} }
} // end NormInstance::Notify() } // end NormInstance::Notify()
// Purge any notifications associated with a specific object
void NormInstance::PurgeObjectNotifications(NormObjectHandle objectHandle) void NormInstance::PurgeObjectNotifications(NormObjectHandle objectHandle)
{ {
if (NORM_OBJECT_INVALID == objectHandle) return; if (NORM_OBJECT_INVALID == objectHandle) return;
@ -449,17 +464,28 @@ void NormInstance::PurgeObjectNotifications(NormObjectHandle objectHandle)
next = next->GetNext(); next = next->GetNext();
} }
} }
if ((NULL != previous_notification) && (objectHandle == previous_notification->event.object))
{
// "Release" any previously-retained object or node handle
((NormObject*)(previous_notification->event.object))->Release();
notify_pool.Append(previous_notification);
previous_notification = NULL;
}
// TBD - check if event queue is emptied and reset event/fd // TBD - check if event queue is emptied and reset event/fd
} // end NormInstance::PurgeObjectNotifications() } // end NormInstance::PurgeObjectNotifications()
void NormInstance::PurgeSessionNotifications(NormSessionHandle sessionHandle) // Purge any notifications associated with a specific object
void NormInstance::PurgeNodeNotifications(NormNodeHandle nodeHandle)
{ {
if (NORM_NODE_INVALID == nodeHandle) return;
Notification* prev = NULL; Notification* prev = NULL;
Notification* next = notify_queue.GetHead(); Notification* next = notify_queue.GetHead();
while (NULL != next) while (next)
{ {
if (next->event.session == sessionHandle) if (nodeHandle == next->event.sender)
{ {
// "Release" the previously-retained object handle
((NormNode*)nodeHandle)->Release();
// Remove this notification from queue and return to pool // Remove this notification from queue and return to pool
Notification* current = next; Notification* current = next;
next = next->GetNext(); next = next->GetNext();
@ -476,11 +502,65 @@ void NormInstance::PurgeSessionNotifications(NormSessionHandle sessionHandle)
next = next->GetNext(); next = next->GetNext();
} }
} }
// TBD - check if event queue is emptied and reset event/fd if ((NULL != previous_notification) && (nodeHandle == previous_notification->event.sender))
{
// "Release" any previously-retained object or node handle
if (NORM_OBJECT_INVALID != previous_notification->event.object)
((NormObject*)(previous_notification->event.object))->Release();
else if (NORM_NODE_INVALID != previous_notification->event.sender)
((NormNode*)(previous_notification->event.sender))->Release();
notify_pool.Append(previous_notification);
previous_notification = NULL;
}
if (notify_queue.IsEmpty()) ResetNotificationEvent();
} // end NormInstance::PurgeNodeNotifications()
void NormInstance::PurgeSessionNotifications(NormSessionHandle sessionHandle)
{
if (NORM_SESSION_INVALID == sessionHandle) return;
Notification* prev = NULL;
Notification* next = notify_queue.GetHead();
while (NULL != next)
{
if (next->event.session == sessionHandle)
{
// Remove this notification from queue and return to pool
Notification* current = next;
next = next->GetNext();
if (NULL != prev)
prev->Append(next);
else
notify_queue.RemoveHead();
if (NULL == next) notify_queue.SetTail(prev);
if (NORM_OBJECT_INVALID != current->event.object)
((NormObject*)current->event.object)->Release();
else if (NORM_NODE_INVALID != current->event.sender)
((NormNode*)current->event.sender)->Release();
notify_pool.Append(current);
}
else
{
prev = next;
next = next->GetNext();
}
}
if ((NULL != previous_notification) && (sessionHandle == previous_notification->event.session))
{
// "Release" any previously-retained object or node handle
if (NORM_OBJECT_INVALID != previous_notification->event.object)
((NormObject*)(previous_notification->event.object))->Release();
else if (NORM_NODE_INVALID != previous_notification->event.sender)
((NormNode*)(previous_notification->event.sender))->Release();
notify_pool.Append(previous_notification);
previous_notification = NULL;
}
if (notify_queue.IsEmpty()) ResetNotificationEvent();
} // end NormInstance::PurgeSessionNotifications() } // end NormInstance::PurgeSessionNotifications()
// Purges notifications of a specific type for a specific session
void NormInstance::PurgeNotifications(NormSessionHandle sessionHandle, NormEventType eventType) void NormInstance::PurgeNotifications(NormSessionHandle sessionHandle, NormEventType eventType)
{ {
if (NORM_SESSION_INVALID == sessionHandle) return;
Notification* prev = NULL; Notification* prev = NULL;
Notification* next = notify_queue.GetHead(); Notification* next = notify_queue.GetHead();
while (next) while (next)
@ -496,6 +576,10 @@ void NormInstance::PurgeNotifications(NormSessionHandle sessionHandle, NormEvent
else else
notify_queue.RemoveHead(); notify_queue.RemoveHead();
if (NULL == next) notify_queue.SetTail(prev); if (NULL == next) notify_queue.SetTail(prev);
if (NORM_OBJECT_INVALID != current->event.object)
((NormObject*)current->event.object)->Release();
else if (NORM_NODE_INVALID != current->event.sender)
((NormNode*)current->event.sender)->Release();
notify_pool.Append(current); notify_pool.Append(current);
} }
else else
@ -504,7 +588,7 @@ void NormInstance::PurgeNotifications(NormSessionHandle sessionHandle, NormEvent
next = next->GetNext(); next = next->GetNext();
} }
} }
// TBD - check if event queue is emptied and reset event/fd if (notify_queue.IsEmpty()) ResetNotificationEvent();
} // end NormInstance::PurgeNotifications() } // end NormInstance::PurgeNotifications()
// NormInstance::dispatcher MUST be suspended _before_ calling this // NormInstance::dispatcher MUST be suspended _before_ calling this
@ -517,7 +601,7 @@ bool NormInstance::GetNextEvent(NormEvent* theEvent)
if (NORM_OBJECT_INVALID != previous_notification->event.object) if (NORM_OBJECT_INVALID != previous_notification->event.object)
((NormObject*)(previous_notification->event.object))->Release(); ((NormObject*)(previous_notification->event.object))->Release();
else if (NORM_NODE_INVALID != previous_notification->event.sender) else if (NORM_NODE_INVALID != previous_notification->event.sender)
((NormSenderNode*)(previous_notification->event.sender))->Release(); ((NormNode*)(previous_notification->event.sender))->Release();
notify_pool.Append(previous_notification); notify_pool.Append(previous_notification);
previous_notification = NULL; previous_notification = NULL;
} }
@ -556,23 +640,17 @@ bool NormInstance::GetNextEvent(NormEvent* theEvent)
else if (NULL != theEvent) else if (NULL != theEvent)
{ {
theEvent->type = NORM_EVENT_INVALID; theEvent->type = NORM_EVENT_INVALID;
theEvent->session = NORM_SESSION_INVALID; theEvent->session = NORM_SESSION_INVALID;
theEvent->sender = NORM_SESSION_INVALID; theEvent->sender = NORM_NODE_INVALID;
theEvent->object = NORM_SESSION_INVALID; theEvent->object = NORM_OBJECT_INVALID;
} }
if (notify_queue.IsEmpty()) if (notify_queue.IsEmpty())
{ ResetNotificationEvent();
#ifdef WIN32
if (0 == ResetEvent(notify_event))
PLOG(PL_ERROR, "NormInstance::GetNextEvent() ResetEvent error: %s\n", GetErrorString());
#else
char byte[32];
while (read(notify_fd[0], byte, 32) > 0); // TBD - error check
#endif // if/else WIN32/UNIX
}
return (NULL != n); return (NULL != n);
} // end NormInstance::GetNextEvent() } // end NormInstance::GetNextEvent()
bool NormInstance::WaitForEvent() bool NormInstance::WaitForEvent()
{ {
if (!dispatcher.IsThreaded()) if (!dispatcher.IsThreaded())
@ -640,6 +718,35 @@ bool NormInstance::Startup(bool priorityBoost)
return dispatcher.StartThread(priorityBoost); return dispatcher.StartThread(priorityBoost);
} // end NormInstance::Startup() } // end NormInstance::Startup()
void NormInstance::ReleasePreviousEvent()
{
// Garbage collect our "previous_notification"
if (NULL != previous_notification)
{
// Release any previously-retained object or node handles
if (NORM_OBJECT_INVALID != previous_notification->event.object)
((NormObject*)(previous_notification->event.object))->Release();
else if (NORM_NODE_INVALID != previous_notification->event.sender)
((NormNode*)(previous_notification->event.sender))->Release();
notify_pool.Append(previous_notification);
previous_notification = NULL;
}
} // end NormInstance::ReleasePreviousEvent()
NORM_API_LINKAGE
void NormReleasePreviousEvent(NormInstanceHandle instanceHandle)
{
NormInstance* instance = (NormInstance*)instanceHandle;
if (instance && instance->dispatcher.SuspendThread())
{
instance->ReleasePreviousEvent();
instance->dispatcher.ResumeThread();
}
} // end NormReleasePreviousEvent()
void NormInstance::Shutdown() void NormInstance::Shutdown()
{ {
dispatcher.Stop(); dispatcher.Stop();
@ -670,7 +777,7 @@ void NormInstance::Shutdown()
if (NORM_OBJECT_INVALID != previous_notification->event.object) if (NORM_OBJECT_INVALID != previous_notification->event.object)
((NormObject*)(previous_notification->event.object))->Release(); ((NormObject*)(previous_notification->event.object))->Release();
else if (NORM_NODE_INVALID != previous_notification->event.sender) else if (NORM_NODE_INVALID != previous_notification->event.sender)
((NormSenderNode*)(previous_notification->event.sender))->Release(); ((NormNode*)(previous_notification->event.sender))->Release();
notify_pool.Append(previous_notification); notify_pool.Append(previous_notification);
previous_notification = NULL; previous_notification = NULL;
} }
@ -699,7 +806,7 @@ void NormInstance::Shutdown()
if (NORM_OBJECT_INVALID != n->event.object) if (NORM_OBJECT_INVALID != n->event.object)
((NormObject*)(n->event.object))->Release(); ((NormObject*)(n->event.object))->Release();
else if (NORM_NODE_INVALID != n->event.sender) else if (NORM_NODE_INVALID != n->event.sender)
((NormSenderNode*)(n->event.sender))->Release(); ((NormNode*)(n->event.sender))->Release();
delete n; delete n;
} }
notify_pool.Destroy(); notify_pool.Destroy();
@ -838,8 +945,8 @@ bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent, bo
if (!instance->WaitForEvent()) if (!instance->WaitForEvent())
{ {
// Indication that NormInstance is dead // Indication that NormInstance is dead
// TBD - how do we inform app although this shouldn't // TBD - how do we inform app although this shouldn't
// happen unless the app destroys the "instance" // happen unless the app destroys the "instance"
return false; return false;
} }
// re-suspend thread after wait // re-suspend thread after wait
@ -857,6 +964,7 @@ bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent, bo
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormIsUnicastAddress(const char* address) bool NormIsUnicastAddress(const char* address)
{ {
// TBD - is this really a thread-safe thing to do?
ProtoAddress addr; ProtoAddress addr;
if ((NULL != address) && addr.ResolveFromString(address)) if ((NULL != address) && addr.ResolveFromString(address))
return addr.IsUnicast(); return addr.IsUnicast();
@ -873,11 +981,13 @@ NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
{ {
// (TBD) wrap this with SuspendThread/ResumeThread ??? // (TBD) wrap this with SuspendThread/ResumeThread ???
NormInstance* instance = (NormInstance*)instanceHandle; NormInstance* instance = (NormInstance*)instanceHandle;
if (instance) if (instance && instance->dispatcher.SuspendThread())
{ {
NormSession* session = NormSession* session =
instance->session_mgr.NewSession(sessionAddr, sessionPort, localNodeId); instance->session_mgr.NewSession(sessionAddr, sessionPort, localNodeId);
if (session) return ((NormSessionHandle)session); instance->dispatcher.ResumeThread();
if (session)
return ((NormSessionHandle)session);
} }
return NORM_SESSION_INVALID; return NORM_SESSION_INVALID;
} // end NormCreateSession() } // end NormCreateSession()
@ -886,34 +996,35 @@ NORM_API_LINKAGE
void NormDestroySession(NormSessionHandle sessionHandle) void NormDestroySession(NormSessionHandle sessionHandle)
{ {
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle); NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
if (instance) if (instance && instance->dispatcher.SuspendThread())
{ {
if (instance->dispatcher.SuspendThread()) NormSession* session = (NormSession*)sessionHandle;
if (NULL != session)
{ {
NormSession* session = (NormSession*)sessionHandle; session->Close();
if (NULL != session) session->GetSessionMgr().DeleteSession(session);
{ instance->PurgeSessionNotifications(sessionHandle);
session->Close();
session->GetSessionMgr().DeleteSession(session);
instance->PurgeSessionNotifications(sessionHandle);
}
instance->dispatcher.ResumeThread();
} }
instance->dispatcher.ResumeThread();
} }
} // end NormDestroySession() } // end NormDestroySession()
NORM_API_LINKAGE
NormInstanceHandle NormGetInstance(NormSessionHandle sessionHandle)
{
return (NormInstanceHandle)NormInstance::GetInstanceFromSession(sessionHandle);
} // end NormGetIntance()
NORM_API_LINKAGE NORM_API_LINKAGE
void NormSetUserData(NormSessionHandle sessionHandle, const void* userData) void NormSetUserData(NormSessionHandle sessionHandle, const void* userData)
{ {
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle); NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
if (instance) if (instance && instance->dispatcher.SuspendThread())
{ {
if (instance->dispatcher.SuspendThread()) NormSession* session = (NormSession*)sessionHandle;
{ if (session) session->SetUserData(userData);
NormSession* session = (NormSession*)sessionHandle; instance->dispatcher.ResumeThread();
if (session) session->SetUserData(userData);
instance->dispatcher.ResumeThread();
}
} }
} // end NormSetUserData() } // end NormSetUserData()
@ -935,6 +1046,40 @@ const void* NormGetUserData(NormSessionHandle sessionHandle)
return userData; return userData;
} // end NormGetUserData() } // end NormGetUserData()
NORM_API_LINKAGE
void NormSetUserTimer(NormSessionHandle sessionHandle, double seconds)
{
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
if (instance)
{
if (instance->dispatcher.SuspendThread())
{
NormSession* session = (NormSession*)sessionHandle;
if (session) session->SetUserTimer(seconds);
instance->PurgeNotifications(sessionHandle, NORM_USER_TIMEOUT);
instance->dispatcher.ResumeThread();
}
}
} // end NormSetUserTimer()
NORM_API_LINKAGE
void NormCancelUserTimer(NormSessionHandle sessionHandle)
{
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
if (instance)
{
if (instance->dispatcher.SuspendThread())
{
NormSession* session = (NormSession*)sessionHandle;
if (session) session->SetUserTimer(-1.0); // interval less than zero cancels timer
instance->PurgeNotifications(sessionHandle, NORM_USER_TIMEOUT);
instance->dispatcher.ResumeThread();
}
}
} // end NormCancelUserTimer()
NORM_API_LINKAGE NORM_API_LINKAGE
NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle) NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle)
{ {
@ -945,6 +1090,17 @@ NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle)
return NORM_NODE_NONE; return NORM_NODE_NONE;
} // end NormGetLocalNodeId() } // end NormGetLocalNodeId()
NORM_API_LINKAGE
UINT16 NormGetRxPort(NormSessionHandle sessionHandle)
{
NormSession* session = (NormSession*)sessionHandle;
if (NULL != session)
return session->GetRxPort();
else
return 0;
} // end NormGetRxPort()
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormSetTxPort(NormSessionHandle sessionHandle, bool NormSetTxPort(NormSessionHandle sessionHandle,
UINT16 txPort, UINT16 txPort,
@ -993,7 +1149,8 @@ void NormSetTxOnly(NormSessionHandle sessionHandle,
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormChangeDestination(NormSessionHandle sessionHandle, bool NormChangeDestination(NormSessionHandle sessionHandle,
const char* sessionAddress, const char* sessionAddress,
UINT16 sessionPort) UINT16 sessionPort,
bool connectToSessionAddress)
{ {
// First, see if we can make a valid ProtoAddress // First, see if we can make a valid ProtoAddress
ProtoAddress dest; ProtoAddress dest;
@ -1004,7 +1161,12 @@ bool NormChangeDestination(NormSessionHandle sessionHandle,
if (instance && instance->dispatcher.SuspendThread()) if (instance && instance->dispatcher.SuspendThread())
{ {
NormSession* session = (NormSession*)sessionHandle; NormSession* session = (NormSession*)sessionHandle;
if (session) session->SetAddress(dest); if (session)
{
session->SetAddress(dest);
if (connectToSessionAddress)
session->SetTxOnly(session->GetTxOnly(), true);
}
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
return true; return true;
@ -1029,16 +1191,6 @@ void NormSetRxPortReuse(NormSessionHandle sessionHandle,
} }
} // end NormSetRxPortReuse() } // end NormSetRxPortReuse()
NORM_API_LINKAGE
UINT16 NormGetRxPort(NormSessionHandle sessionHandle)
{
NormSession* session = (NormSession*)sessionHandle;
if (NULL != session)
return session->GetRxPort();
else
return 0;
} // end NormGetRxPort()
NORM_API_LINKAGE NORM_API_LINKAGE
void NormSetEcnSupport(NormSessionHandle sessionHandle, bool ecnEnable, bool ignoreLoss, bool tolerateLoss) void NormSetEcnSupport(NormSessionHandle sessionHandle, bool ecnEnable, bool ignoreLoss, bool tolerateLoss)
@ -1074,6 +1226,25 @@ bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
return result; return result;
} // end NormSetMulticastInterface() } // end NormSetMulticastInterface()
NORM_API_LINKAGE
bool NormSetSSM(NormSessionHandle sessionHandle,
const char* sourceAddress)
{
bool result = false;
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
if (NULL != instance)
{
if (instance->dispatcher.SuspendThread())
{
NormSession* session = (NormSession*)sessionHandle;
if (session)
result = session->SetSSM(sourceAddress);
instance->dispatcher.ResumeThread();
}
}
return result;
} // end NormSetSSM()
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormSetTTL(NormSessionHandle sessionHandle, bool NormSetTTL(NormSessionHandle sessionHandle,
unsigned char ttl) unsigned char ttl)
@ -1125,6 +1296,16 @@ bool NormSetLoopback(NormSessionHandle sessionHandle, bool state)
} // end NormSetLoopback() } // end NormSetLoopback()
NORM_API_LINKAGE
bool NormSetMulticastLoopback(NormSessionHandle sessionHandle, bool state)
{
NormSession* session = (NormSession*)sessionHandle;
if (session)
return session->SetMulticastLoopback(state);
else
return false;
} // end NormSetLoopback()
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormSetFragmentation(NormSessionHandle sessionHandle, bool state) bool NormSetFragmentation(NormSessionHandle sessionHandle, bool state)
{ {
@ -1263,10 +1444,10 @@ NormSessionId NormGetRandomSessionId()
NORM_API_LINKAGE NORM_API_LINKAGE
bool NormStartSender(NormSessionHandle sessionHandle, bool NormStartSender(NormSessionHandle sessionHandle,
NormSessionId sessionId, NormSessionId sessionId,
UINT32 bufferSpace, UINT32 bufferSpace,
UINT16 segmentSize, UINT16 segmentSize,
unsigned char numData, UINT16 numData,
unsigned char numParity) UINT16 numParity)
{ {
bool result = false; bool result = false;
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle); NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
@ -1727,6 +1908,8 @@ bool NormSetWatermark(NormSessionHandle sessionHandle,
NormObject* obj = (NormObject*)objectHandle; NormObject* obj = (NormObject*)objectHandle;
if (session && obj) if (session && obj)
{ {
// Purge any existing to NORM_TX_WATERMARK_COMPLETED notification to be safe
instance->PurgeNotifications(sessionHandle, NORM_TX_WATERMARK_COMPLETED);
// (segmentId doesn't matter for non-stream) // (segmentId doesn't matter for non-stream)
if (obj->IsStream()) if (obj->IsStream())
{ {
@ -1791,7 +1974,7 @@ bool NormAddAckingNode(NormSessionHandle sessionHandle,
{ {
NormSession* session = (NormSession*)sessionHandle; NormSession* session = (NormSession*)sessionHandle;
if (session) if (session)
result = session->SenderAddAckingNode(nodeId); result = (NULL != session->SenderAddAckingNode(nodeId));
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
return result; return result;
@ -1810,6 +1993,20 @@ void NormRemoveAckingNode(NormSessionHandle sessionHandle,
} }
} // end NormRemoveAckingNode() } // end NormRemoveAckingNode()
NORM_API_LINKAGE
NormNodeHandle NormGetAckingNodeHandle(NormSessionHandle sessionHandle,
NormNodeId nodeId)
{
if (NORM_SESSION_INVALID != sessionHandle)
{
NormSession* session = (NormSession*)sessionHandle;
NormAckingNode* acker = session->SenderFindAckingNode(nodeId);
if (NULL != acker)
return ((NormNodeHandle)static_cast<NormNode*>(acker));
}
return NORM_NODE_INVALID;
} // end NormGetAckingNodeHandle()
NORM_API_LINKAGE NORM_API_LINKAGE
void NormSetAutoAckingNodes(NormSessionHandle sessionHandle, void NormSetAutoAckingNodes(NormSessionHandle sessionHandle,
NormTrackingStatus trackingStatus) NormTrackingStatus trackingStatus)
@ -1994,8 +2191,12 @@ void NormNodeSetUnicastNack(NormNodeHandle nodeHandle,
bool unicastNacks) bool unicastNacks)
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
if (node) node->SetUnicastNacks(unicastNacks); if ((NULL != node) && (NormNode::SENDER == node->GetType()))
{
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
sender->SetUnicastNacks(unicastNacks);
}
} // end NormNodeSetUnicastNack() } // end NormNodeSetUnicastNack()
NORM_API_LINKAGE NORM_API_LINKAGE
@ -2018,8 +2219,12 @@ NORM_API_LINKAGE
void NormNodeSetNackingMode(NormNodeHandle nodeHandle, void NormNodeSetNackingMode(NormNodeHandle nodeHandle,
NormNackingMode nackingMode) NormNackingMode nackingMode)
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
if (node) node->SetDefaultNackingMode((NormObject::NackingMode)nackingMode); if ((NULL != node) && (NormNode::SENDER == node->GetType()))
{
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
sender->SetDefaultNackingMode((NormObject::NackingMode)nackingMode);
}
} // end NormNodeSetNackingMode() } // end NormNodeSetNackingMode()
NORM_API_LINKAGE NORM_API_LINKAGE
@ -2043,9 +2248,12 @@ NORM_API_LINKAGE
void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle, void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle,
NormRepairBoundary repairBoundary) NormRepairBoundary repairBoundary)
{ {
NormSenderNode* node = static_cast<NormSenderNode*>((NormSenderNode*)nodeHandle); NormNode* node = (NormNode*)nodeHandle;
if (node) if ((NULL != node) && (NormNode::SENDER == node->GetType()))
node->SetRepairBoundary((NormSenderNode::RepairBoundary)repairBoundary); {
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
sender->SetRepairBoundary((NormSenderNode::RepairBoundary)repairBoundary);
}
} // end NormNodeSetRepairBoundary() } // end NormNodeSetRepairBoundary()
@ -2071,8 +2279,12 @@ void NormNodeSetRxRobustFactor(NormNodeHandle nodeHandle,
NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle); NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle);
if (instance && instance->dispatcher.SuspendThread()) if (instance && instance->dispatcher.SuspendThread())
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
node->SetRobustFactor(robustFactor); if (NormNode::SENDER == node->GetType())
{
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
sender->SetRobustFactor(robustFactor);
}
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
} }
@ -2322,9 +2534,15 @@ const char* NormDataAccessData(NormObjectHandle dataHandle)
NORM_API_LINKAGE NORM_API_LINKAGE
char* NormDataDetachData(NormObjectHandle dataHandle) char* NormDataDetachData(NormObjectHandle dataHandle)
{ {
NormDataObject* dataObj = char* ptr = NULL;
static_cast<NormDataObject*>((NormObject*)dataHandle); NormInstance* instance = NormInstance::GetInstanceFromObject(dataHandle);
return dataObj->DetachData(); if (instance && instance->dispatcher.SuspendThread())
{
NormDataObject* dataObj = static_cast<NormDataObject*>((NormObject*)dataHandle);
ptr = dataObj->DetachData();
instance->dispatcher.ResumeThread();
}
return ptr;
} // end NormDataDetachData() } // end NormDataDetachData()
NORM_API_LINKAGE NORM_API_LINKAGE
@ -2339,7 +2557,7 @@ NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle)
NORM_API_LINKAGE NORM_API_LINKAGE
NormNodeId NormNodeGetId(NormNodeHandle nodeHandle) NormNodeId NormNodeGetId(NormNodeHandle nodeHandle)
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
if (NULL != node) if (NULL != node)
return node->GetId(); return node->GetId();
else else
@ -2355,10 +2573,10 @@ bool NormNodeGetAddress(NormNodeHandle nodeHandle,
bool result = false; bool result = false;
if (NORM_NODE_INVALID != nodeHandle) if (NORM_NODE_INVALID != nodeHandle)
{ {
NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle); //NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle);
if (instance && instance->dispatcher.SuspendThread()) //if (instance && instance->dispatcher.SuspendThread())
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormSenderNode*)nodeHandle;
const ProtoAddress& nodeAddr = node->GetAddress(); const ProtoAddress& nodeAddr = node->GetAddress();
unsigned int addrLen = nodeAddr.GetLength(); unsigned int addrLen = nodeAddr.GetLength();
if (addrBuffer && bufferLen && (addrLen <= *bufferLen)) if (addrBuffer && bufferLen && (addrLen <= *bufferLen))
@ -2372,20 +2590,45 @@ bool NormNodeGetAddress(NormNodeHandle nodeHandle,
} }
if (bufferLen) *bufferLen = addrLen; if (bufferLen) *bufferLen = addrLen;
if (port) *port = nodeAddr.GetPort(); if (port) *port = nodeAddr.GetPort();
instance->dispatcher.ResumeThread(); //instance->dispatcher.ResumeThread();
} }
} }
return result; return result;
} // end NormNodeGetId() } // end NormNodeGetAddress()
NORM_API_LINKAGE
void NormNodeSetUserData(NormNodeHandle nodeHandle, const void* userData)
{
if (NORM_NODE_INVALID != nodeHandle)
{
NormNode* node = (NormNode*)nodeHandle;
return node->SetUserData(userData);
}
}
NORM_API_LINKAGE
const void* NormNodeGetUserData(NormNodeHandle nodeHandle)
{
NormNode* node = (NormNode*)nodeHandle;
if (NULL != node)
return node->GetUserData();
else
return NULL;
} // end NormNodeGetUserData()
NORM_API_LINKAGE NORM_API_LINKAGE
double NormNodeGetGrtt(NormNodeHandle nodeHandle) double NormNodeGetGrtt(NormNodeHandle nodeHandle)
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
if (NULL != node) if ((NULL != node) && (NormNode::SENDER == node->GetType()))
return node->GetGrttEstimate(); {
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
return sender->GetGrttEstimate();
}
else else
{
return -1.0; return -1.0;
}
} // end NormNodeGetGrtt() } // end NormNodeGetGrtt()
NORM_API_LINKAGE NORM_API_LINKAGE
@ -2399,8 +2642,12 @@ bool NormNodeGetCommand(NormNodeHandle nodeHandle,
NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle); NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle);
if (instance && instance->dispatcher.SuspendThread()) if (instance && instance->dispatcher.SuspendThread())
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
result = node->ReadNextCmd(cmdBuffer, cmdLength); if (NormNode::SENDER == node->GetType())
{
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
result = sender->ReadNextCmd(cmdBuffer, cmdLength);
}
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
} }
@ -2415,8 +2662,14 @@ void NormNodeFreeBuffers(NormNodeHandle nodeHandle)
NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle); NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle);
if (instance && instance->dispatcher.SuspendThread()) if (instance && instance->dispatcher.SuspendThread())
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
node->FreeBuffers(); if (NormNode::SENDER == node->GetType())
{
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
sender->FreeBuffers();
// Since this results in aborted objects, should we purge those object notifications?
// or let the be delivered since the app may have associate state
}
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
} }
@ -2430,8 +2683,14 @@ void NormNodeDelete(NormNodeHandle nodeHandle)
NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle); NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle);
if (instance && instance->dispatcher.SuspendThread()) if (instance && instance->dispatcher.SuspendThread())
{ {
NormSenderNode* node = (NormSenderNode*)nodeHandle; NormNode* node = (NormNode*)nodeHandle;
node->GetSession().DeleteRemoteSender(*node); if (NormNode::SENDER == node->GetType())
{
NormSenderNode* sender = static_cast<NormSenderNode*>(node);
sender->GetSession().DeleteRemoteSender(*sender);
}
// else if NormNode::ACKER, should we remove from acking node list???
instance->PurgeNodeNotifications(nodeHandle);
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
} }
@ -2445,7 +2704,7 @@ void NormNodeRetain(NormNodeHandle nodeHandle)
NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle); NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle);
if (instance && instance->dispatcher.SuspendThread()) if (instance && instance->dispatcher.SuspendThread())
{ {
((NormSenderNode*)nodeHandle)->Retain(); ((NormNode*)nodeHandle)->Retain();
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
} }
@ -2459,7 +2718,7 @@ void NormNodeRelease(NormNodeHandle nodeHandle)
NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle); NormInstance* instance = NormInstance::GetInstanceFromNode(nodeHandle);
if (instance && instance->dispatcher.SuspendThread()) if (instance && instance->dispatcher.SuspendThread())
{ {
((NormSenderNode*)nodeHandle)->Release(); ((NormNode*)nodeHandle)->Release();
instance->dispatcher.ResumeThread(); instance->dispatcher.ResumeThread();
} }
} }

View File

@ -76,7 +76,7 @@ class NormApp : public NormController, public ProtoApp
virtual void Notify(NormController::Event event, virtual void Notify(NormController::Event event,
class NormSessionMgr* sessionMgr, class NormSessionMgr* sessionMgr,
class NormSession* session, class NormSession* session,
class NormSenderNode* sender, class NormNode* node,
class NormObject* object); class NormObject* object);
bool OnIntervalTimeout(ProtoTimer& theTimer); bool OnIntervalTimeout(ProtoTimer& theTimer);
@ -490,8 +490,9 @@ 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, (unsigned int&)len)) unsigned int numBytes = (unsigned int)len;
{ if (!control_pipe.Send(buffer, numBytes))
{
PLOG(PL_FATAL, "NormApp::OnCommand() error sending command to remote instance\n"); PLOG(PL_FATAL, "NormApp::OnCommand() error sending command to remote instance\n");
return false; return false;
} }
@ -1494,7 +1495,7 @@ void NormApp::OnInputReady()
void NormApp::Notify(NormController::Event event, void NormApp::Notify(NormController::Event event,
class NormSessionMgr* sessionMgr, class NormSessionMgr* sessionMgr,
class NormSession* session, class NormSession* session,
class NormSenderNode* sender, class NormNode* sender,
class NormObject* object) class NormObject* object)
{ {
switch (event) switch (event)
@ -1558,7 +1559,8 @@ void NormApp::Notify(NormController::Event event,
case REMOTE_SENDER_INACTIVE: case REMOTE_SENDER_INACTIVE:
PLOG(PL_DEBUG, "NormApp::Notify(REMOTE_SENDER_INACTIVE) ...\n"); PLOG(PL_DEBUG, "NormApp::Notify(REMOTE_SENDER_INACTIVE) ...\n");
if (!rx_persistent) sender->FreeBuffers(); if (!rx_persistent)
static_cast<NormSenderNode*>(sender)->FreeBuffers();
break; break;

View File

@ -764,13 +764,13 @@ int NormDecoderRS16::Decode(char** vectorList, unsigned int numData, unsigned i
bool NormDecoderRS16::InvertDecodingMatrix() bool NormDecoderRS16::InvertDecodingMatrix()
{ {
gf* src = (gf*)dec_matrix; gf* src = (gf*)dec_matrix;
int k = ndata; unsigned int k = ndata;
memset(inv_id_row, 0, k*sizeof(gf)); memset(inv_id_row, 0, k*sizeof(gf));
// inv_pivt marks elements already used as pivots. // inv_pivt marks elements already used as pivots.
memset(inv_pivt, 0, k*sizeof(unsigned int)); memset(inv_pivt, 0, k*sizeof(unsigned int));
for (int col = 0; col < k ; col++) for (unsigned int col = 0; col < k ; col++)
{ {
/* /*
* Zeroing column 'col', look for a non-zero element. * Zeroing column 'col', look for a non-zero element.
@ -788,7 +788,7 @@ bool NormDecoderRS16::InvertDecodingMatrix()
{ {
if (inv_pivt[row] != 1) if (inv_pivt[row] != 1)
{ {
for (int ix = 0 ; ix < k ; ix++) for (unsigned int ix = 0 ; ix < k ; ix++)
{ {
if (inv_pivt[ix] == 0) if (inv_pivt[ix] == 0)
{ {
@ -821,7 +821,7 @@ bool NormDecoderRS16::InvertDecodingMatrix()
*/ */
if (irow != icol) if (irow != icol)
{ {
for (int ix = 0 ; ix < k ; ix++ ) for (unsigned int ix = 0 ; ix < k ; ix++ )
SWAP(src[irow*k + ix], src[icol*k + ix], gf); SWAP(src[irow*k + ix], src[icol*k + ix], gf);
} }
inv_ndxr[col] = irow ; inv_ndxr[col] = irow ;
@ -841,7 +841,7 @@ bool NormDecoderRS16::InvertDecodingMatrix()
*/ */
c = inverse[ c ] ; c = inverse[ c ] ;
pivotRow[icol] = 1 ; pivotRow[icol] = 1 ;
for (int ix = 0 ; ix < k ; ix++ ) for (unsigned int ix = 0 ; ix < k ; ix++ )
pivotRow[ix] = gf_mul(c, pivotRow[ix] ); pivotRow[ix] = gf_mul(c, pivotRow[ix] );
} }
/* /*
@ -869,11 +869,11 @@ bool NormDecoderRS16::InvertDecodingMatrix()
for (int col = k - 1 ; col >= 0 ; col-- ) for (int col = k - 1 ; col >= 0 ; col-- )
{ {
if (inv_ndxr[col] < 0 || inv_ndxr[col] >= (unsigned int)k) if (inv_ndxr[col] >= k)
{ {
PLOG(PL_ERROR, "NormDecoderRS16::InvertDecodingMatrix() error: AARGH, inv_ndxr[col] %d\n", inv_ndxr[col]); PLOG(PL_ERROR, "NormDecoderRS16::InvertDecodingMatrix() error: AARGH, inv_ndxr[col] %d\n", inv_ndxr[col]);
} }
else if (inv_ndxc[col] <0 || inv_ndxc[col] >= (unsigned int)k) else if (inv_ndxc[col] >= k)
{ {
PLOG(PL_ERROR, "NormDecoderRS16::InvertDecodingMatrix() error: AARGH, indxc[col] %d\n", inv_ndxc[col]); PLOG(PL_ERROR, "NormDecoderRS16::InvertDecodingMatrix() error: AARGH, indxc[col] %d\n", inv_ndxc[col]);
} }

View File

@ -52,7 +52,7 @@
*/ */
#define GF_BITS 8 // 8-bit RS code #define GF_BITS 8 // 8-bit RS code
#if (GF_BITS < 2 && GF_BITS > 16) #if (GF_BITS < 2) || (GF_BITS > 16)
#error "GF_BITS must be 2 .. 16" #error "GF_BITS must be 2 .. 16"
#endif #endif
#if (GF_BITS <= 8) #if (GF_BITS <= 8)
@ -766,13 +766,13 @@ int NormDecoderRS8::Decode(char** vectorList, unsigned int numData, unsigned in
bool NormDecoderRS8::InvertDecodingMatrix() bool NormDecoderRS8::InvertDecodingMatrix()
{ {
gf* src = (gf*)dec_matrix; gf* src = (gf*)dec_matrix;
int k = ndata; unsigned int k = ndata;
memset(inv_id_row, 0, k*sizeof(gf)); memset(inv_id_row, 0, k*sizeof(gf));
// inv_pivt marks elements already used as pivots. // inv_pivt marks elements already used as pivots.
memset(inv_pivt, 0, k*sizeof(unsigned int)); memset(inv_pivt, 0, k*sizeof(unsigned int));
for (int col = 0; col < k ; col++) for (unsigned int col = 0; col < k ; col++)
{ {
/* /*
* Zeroing column 'col', look for a non-zero element. * Zeroing column 'col', look for a non-zero element.
@ -786,11 +786,11 @@ bool NormDecoderRS8::InvertDecodingMatrix()
icol = col ; icol = col ;
goto found_piv ; goto found_piv ;
} }
for (int row = 0 ; row < k ; row++) for (unsigned int row = 0 ; row < k ; row++)
{ {
if (inv_pivt[row] != 1) if (inv_pivt[row] != 1)
{ {
for (int ix = 0 ; ix < k ; ix++) for (unsigned int ix = 0 ; ix < k ; ix++)
{ {
if (inv_pivt[ix] == 0) if (inv_pivt[ix] == 0)
{ {
@ -823,7 +823,7 @@ bool NormDecoderRS8::InvertDecodingMatrix()
*/ */
if (irow != icol) if (irow != icol)
{ {
for (int ix = 0 ; ix < k ; ix++ ) for (unsigned int ix = 0 ; ix < k ; ix++ )
SWAP(src[irow*k + ix], src[icol*k + ix], gf); SWAP(src[irow*k + ix], src[icol*k + ix], gf);
} }
inv_ndxr[col] = irow ; inv_ndxr[col] = irow ;
@ -843,7 +843,7 @@ bool NormDecoderRS8::InvertDecodingMatrix()
*/ */
c = inverse[ c ] ; c = inverse[ c ] ;
pivotRow[icol] = 1 ; pivotRow[icol] = 1 ;
for (int ix = 0 ; ix < k ; ix++ ) for (unsigned int ix = 0 ; ix < k ; ix++ )
pivotRow[ix] = gf_mul(c, pivotRow[ix] ); pivotRow[ix] = gf_mul(c, pivotRow[ix] );
} }
/* /*
@ -871,17 +871,17 @@ bool NormDecoderRS8::InvertDecodingMatrix()
for (int col = k - 1 ; col >= 0 ; col-- ) for (int col = k - 1 ; col >= 0 ; col-- )
{ {
if (inv_ndxr[col] < 0 || inv_ndxr[col] >= (unsigned int)k) if (inv_ndxr[col] >= k)
{ {
PLOG(PL_ERROR, "NormDecoderRS8::InvertDecodingMatrix() error: AARGH, inv_ndxr[col] %d\n", inv_ndxr[col]); PLOG(PL_ERROR, "NormDecoderRS8::InvertDecodingMatrix() error: AARGH, inv_ndxr[col] %d\n", inv_ndxr[col]);
} }
else if (inv_ndxc[col] <0 || inv_ndxc[col] >= (unsigned int)k) else if (inv_ndxc[col] >= k)
{ {
PLOG(PL_ERROR, "NormDecoderRS8::InvertDecodingMatrix() error: AARGH, indxc[col] %d\n", inv_ndxc[col]); PLOG(PL_ERROR, "NormDecoderRS8::InvertDecodingMatrix() error: AARGH, indxc[col] %d\n", inv_ndxc[col]);
} }
else if (inv_ndxr[col] != inv_ndxc[col] ) else if (inv_ndxr[col] != inv_ndxc[col] )
{ {
for (int row = 0 ; row < k ; row++ ) for (unsigned int row = 0 ; row < k ; row++ )
SWAP( src[row*k + inv_ndxr[col]], src[row*k + inv_ndxc[col]], gf) ; SWAP( src[row*k + inv_ndxr[col]], src[row*k + inv_ndxc[col]], gf) ;
} }
} }

View File

@ -5,8 +5,8 @@
#include "normEncoderRS8.h" // 8-bit Reed-Solomon encoder of RFC 5510 #include "normEncoderRS8.h" // 8-bit Reed-Solomon encoder of RFC 5510
#include "normEncoderRS16.h" // 16-bit Reed-Solomon encoder of RFC 5510 #include "normEncoderRS16.h" // 16-bit Reed-Solomon encoder of RFC 5510
NormNode::NormNode(class NormSession& theSession, NormNodeId nodeId) NormNode::NormNode(Type nodeType, class NormSession& theSession, NormNodeId nodeId)
: session(theSession), id(nodeId), reference_count(1), : session(theSession), node_type(nodeType), id(nodeId), reference_count(1), user_data(NULL),
parent(NULL), right(NULL), left(NULL) parent(NULL), right(NULL), left(NULL)
{ {
@ -14,8 +14,10 @@ NormNode::NormNode(class NormSession& theSession, NormNodeId nodeId)
NormNode::~NormNode() NormNode::~NormNode()
{ {
//TRACE("NormNode %lu dtor ...\n", (unsigned long)id);
} }
void NormNode::Retain() void NormNode::Retain()
{ {
reference_count++; reference_count++;
@ -40,9 +42,8 @@ NormNode::Accumulator::Accumulator()
} }
NormCCNode::NormCCNode(class NormSession& theSession, NormNodeId nodeId) NormCCNode::NormCCNode(class NormSession& theSession, NormNodeId nodeId)
: NormNode(theSession, nodeId) : NormNode(CC_NODE, theSession, nodeId)
{ {
} }
@ -65,11 +66,11 @@ const double NormSenderNode::DEFAULT_NOMINAL_INTERVAL = 2*NormSession::DEFAULT_G
const double NormSenderNode::ACTIVITY_INTERVAL_MIN = 1.0; // 1 second min activity timeout const double NormSenderNode::ACTIVITY_INTERVAL_MIN = 1.0; // 1 second min activity timeout
NormSenderNode::NormSenderNode(class NormSession& theSession, NormNodeId nodeId) NormSenderNode::NormSenderNode(class NormSession& theSession, NormNodeId nodeId)
: NormNode(theSession, nodeId), instance_id(0), robust_factor(session.GetRxRobustFactor()), : NormNode(SENDER, theSession, nodeId), instance_id(0), robust_factor(session.GetRxRobustFactor()),
synchronized(false), sync_id(0), synchronized(false), sync_id(0),
is_open(false), segment_size(0), fec_m(0), ndata(0), nparity(0), is_open(false), segment_size(0), fec_m(0), ndata(0), nparity(0),
repair_boundary(BLOCK_BOUNDARY), decoder(NULL), erasure_loc(NULL), repair_boundary(BLOCK_BOUNDARY), decoder(NULL), erasure_loc(NULL),
retrieval_loc(NULL), retrieval_pool(NULL), retrieval_loc(NULL), retrieval_pool(NULL), ack_pending(false),
cc_sequence(0), cc_enable(false), cc_feedback_needed(false), cc_rate(0.0), cc_sequence(0), cc_enable(false), cc_feedback_needed(false), cc_rate(0.0),
rtt_confirmed(false), is_clr(false), is_plr(false), rtt_confirmed(false), is_clr(false), is_plr(false),
slow_start(true), send_rate(0.0), recv_rate(0.0), recv_rate_prev(0.0), slow_start(true), send_rate(0.0), recv_rate(0.0), recv_rate_prev(0.0),
@ -160,6 +161,7 @@ void NormSenderNode::Close()
if (activity_timer.IsActive()) activity_timer.Deactivate(); if (activity_timer.IsActive()) activity_timer.Deactivate();
if (repair_timer.IsActive()) repair_timer.Deactivate(); if (repair_timer.IsActive()) repair_timer.Deactivate();
if (cc_timer.IsActive()) cc_timer.Deactivate(); if (cc_timer.IsActive()) cc_timer.Deactivate();
if (ack_timer.IsActive()) ack_timer.Deactivate();
FreeBuffers(); FreeBuffers();
// Delete any command buffers from cmd_buffer queue // Delete any command buffers from cmd_buffer queue
@ -566,7 +568,7 @@ void NormSenderNode::HandleCommand(const struct timeval& currentTime,
} }
// 1) Sync to squelch (discards all objects prior to squelch objectId) // 1) Sync to squelch (discards all objects prior to squelch objectId)
NormObjectId objectId = squelch.GetObjectId(); NormObjectId objectId = squelch.GetObjectId();
Sync(objectId); Sync(objectId);
// 2) Prune stream object if applicable // 2) Prune stream object if applicable
NormObject* obj = rx_table.Find(objectId); NormObject* obj = rx_table.Find(objectId);
if ((NULL != obj) && (NormObject::STREAM == obj->GetType())) if ((NULL != obj) && (NormObject::STREAM == obj->GetType()))
@ -638,7 +640,6 @@ void NormSenderNode::HandleCommand(const struct timeval& currentTime,
is_clr = is_plr = false; is_clr = is_plr = false;
} }
double maxBackoff; double maxBackoff;
if (is_clr || is_plr || !session.Address().IsMulticast()) if (is_clr || is_plr || !session.Address().IsMulticast())
{ {
// Respond immediately (i.e., no backoff, holdoff etc) // Respond immediately (i.e., no backoff, holdoff etc)
@ -757,6 +758,7 @@ void NormSenderNode::HandleCommand(const struct timeval& currentTime,
{ {
double ackBackoff = session.Address().IsMulticast() ? UniformRand(grtt_estimate) : 0.0; double ackBackoff = session.Address().IsMulticast() ? UniformRand(grtt_estimate) : 0.0;
ack_timer.SetInterval(ackBackoff); ack_timer.SetInterval(ackBackoff);
ack_pending = true;
session.ActivateTimer(ack_timer); session.ActivateTimer(ack_timer);
} }
break; // no pending repairs, skip regular "RepairCheck" break; // no pending repairs, skip regular "RepairCheck"
@ -1546,9 +1548,7 @@ void NormSenderNode::HandleObjectMessage(const NormObjectMsg& msg)
break; break;
} // end switch(status) } // end switch(status)
if (NULL != obj)
if (obj)
{ {
obj->HandleObjectMessage(msg, msgType, blockId, segmentId); obj->HandleObjectMessage(msg, msgType, blockId, segmentId);
@ -1742,11 +1742,9 @@ NormSenderNode::ObjectStatus NormSenderNode::UpdateSyncStatus(const NormObjectId
{ {
NormObjectId lastPending(65535); NormObjectId lastPending(65535);
GetLastPending(lastPending); GetLastPending(lastPending);
TRACE("lp:%hu\n", (UINT16)lastPending);
if (syncId > lastPending) if (syncId > lastPending)
{ {
UINT16 delta = syncId - lastPending; UINT16 delta = syncId - lastPending;
TRACE("SYNC DELTA = %d\n", delta);
if (delta < max_pending_range) if (delta < max_pending_range)
{ {
syncId -= (max_pending_range - 1); syncId -= (max_pending_range - 1);
@ -2179,7 +2177,6 @@ bool NormSenderNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
default: default:
break; break;
} }
if (NULL != obj) if (NULL != obj)
{ {
if (obj->IsPending(nextId != max_pending_object)) if (obj->IsPending(nextId != max_pending_object))
@ -2401,8 +2398,8 @@ bool NormSenderNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
} }
else if (0 == activity_timer.GetRepeatCount()) else if (0 == activity_timer.GetRepeatCount())
{ {
// Serve completely inactive? // Remote sender completely inactive?
PLOG(PL_ERROR, "NormSenderNode::OnActivityTimeout() node>%lu sender>%lu gone inactive?\n", PLOG(PL_INFO, "NormSenderNode::OnActivityTimeout() node>%lu sender>%lu gone inactive?\n",
LocalNodeId(), GetId()); LocalNodeId(), GetId());
//FreeBuffers(); This now needs to be done by the app as of norm version 1.4b3 //FreeBuffers(); This now needs to be done by the app as of norm version 1.4b3
session.Notify(NormController::REMOTE_SENDER_INACTIVE, this, NULL); session.Notify(NormController::REMOTE_SENDER_INACTIVE, this, NULL);
@ -2419,7 +2416,7 @@ bool NormSenderNode::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,
@ -2429,10 +2426,14 @@ bool NormSenderNode::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??? // The above has been reinstated because the alternative "THRU_OBJECT" here
max_pending_object, 0, 0); // causes gratuitous NACKing when the sender goes IDLE ..
// Or we could do this instead (possibly some unnecessary NACKing for NORM_OBJECT_STREAM will occur here)
//RepairCheck(NormObject::THRU_OBJECT, // (TBD) thru object???
// max_pending_object, 0, 0);
// (TBD) What should we really do here? Our current NormNode::RepairCheck() and // (TBD) What should we really do here? Our current NormNode::RepairCheck() and
// NormObject::ReceiverRepairCheck() methods update the "max_pending" indices // NormObject::ReceiverRepairCheck() methods update the "max_pending" indices
@ -2445,7 +2446,12 @@ bool NormSenderNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
// I guess the activity timeout NACK isn't perfect ... but could help some // I guess the activity timeout NACK isn't perfect ... but could help some
// so we leave it as it is for the moment ("THRU_OBJECT") ... perhaps we could // so we leave it as it is for the moment ("THRU_OBJECT") ... perhaps we could
// add a parameter so NormObject::ReceiverRepairCheck() doesn't update its // add a parameter so NormObject::ReceiverRepairCheck() doesn't update its
// "max_pending" indices - or would this break NACK building // "max_pending" indices - or would this break NACK building?
// Maybe we should do THRU_OBJECT when the remote sender is fully inactive as
// opposed to this inactivity timeout that only pays attend to NORM_DATA. I.e.,
// do the above refined RepairCheck() when we still have NORM_CMD activity but
// no NORM_DATA activity??? We'd still have potentially a lot of EOT NACKing
} }
else else
{ {
@ -2455,7 +2461,7 @@ bool NormSenderNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
// max_pending_object, 0, 0); // max_pending_object, 0, 0);
} }
} }
// We manually managed the "repeat_count" here to avoid the // We manually manage the "repeat_count" here to avoid the
// case where "bursty" receiver scheduling may lead to false // case where "bursty" receiver scheduling may lead to false
// inactivity indication // inactivity indication
int repeatCount = activity_timer.GetRepeatCount(); int repeatCount = activity_timer.GetRepeatCount();
@ -2572,6 +2578,14 @@ void NormSenderNode::AttachCCFeedback(NormAckMsg& ack)
bool NormSenderNode::OnCCTimeout(ProtoTimer& /*theTimer*/) bool NormSenderNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
{ {
// Build and send NORM_ACK(CC) // Build and send NORM_ACK(CC)
if (ack_pending && (1 == cc_timer.GetRepeatCount()))
{
// Send ACK flush right away (CC feedback is included
if (ack_timer.IsActive()) ack_timer.Deactivate();
if (cc_timer.IsActive()) cc_timer.Deactivate(); // will be reactivated if needed
OnAckTimeout(ack_timer);
return false;
}
switch (cc_timer.GetRepeatCount()) switch (cc_timer.GetRepeatCount())
{ {
case 0: case 0:
@ -2601,23 +2615,31 @@ bool NormSenderNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
ack->SetDestination(GetAddress()); ack->SetDestination(GetAddress());
else else
ack->SetDestination(session.Address()); ack->SetDestination(session.Address());
session.SendMessage(*ack); bool success = session.SendMessage(*ack);
session.ReturnMessageToPool(ack); session.ReturnMessageToPool(ack);
cc_feedback_needed = false; if (success)
// Begin cc_timer "holdoff" phase
if (!is_clr && !is_plr && session.Address().IsMulticast())
{ {
cc_timer.SetInterval(grtt_estimate*backoff_factor); cc_feedback_needed = false;
return true; // Begin cc_timer "holdoff" phase
if (!is_clr && !is_plr && session.Address().IsMulticast())
{
cc_timer.SetInterval(grtt_estimate*backoff_factor);
}
else if (cc_timer.IsActive())
{
cc_timer.Deactivate();
return false;
}
} }
else if (cc_timer.IsActive()) else
{ {
cc_timer.Deactivate(); // TBD - queue ack so it gets send retry?
PLOG(PL_ERROR, "NormSenderNode::OnCCTimeout() error: SendMessage(ack) failure\n");
if (cc_timer.IsActive()) cc_timer.Deactivate();
return false;
} }
break; break;
} }
default: default:
// Should never occur // Should never occur
ASSERT(0); ASSERT(0);
@ -2630,7 +2652,7 @@ bool NormSenderNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
{ {
// Build and send NORM_ACK(FLUSH) // Build and send NORM_ACK(FLUSH)
NormAckFlushMsg* ack = (NormAckFlushMsg*)session.GetMessageFromPool(); NormAckFlushMsg* ack = (NormAckFlushMsg*)session.GetMessageFromPool();
if (ack) if (NULL != ack)
{ {
ack->Init(); ack->Init();
ack->SetSenderId(GetId()); ack->SetSenderId(GetId());
@ -2657,24 +2679,31 @@ bool NormSenderNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
ack->SetDestination(session.Address()); ack->SetDestination(session.Address());
// Don't rate limit feedback messages // Don't rate limit feedback messages
session.SendMessage(*ack); if (session.SendMessage(*ack))
session.ReturnMessageToPool(ack); {
cc_feedback_needed = false; ack_pending = false;
if (cc_enable && !is_clr && !is_plr && session.Address().IsMulticast()) cc_feedback_needed = false;
if (cc_enable && !is_clr && !is_plr && session.Address().IsMulticast())
{
// Install cc feedback holdoff
cc_timer.SetInterval(grtt_estimate*backoff_factor);
if (cc_timer.IsActive())
cc_timer.Reschedule();
else
session.ActivateTimer(cc_timer);
cc_timer.DecrementRepeatCount(); // put timer into "holdoff" phase
}
else if (cc_timer.IsActive())
{
cc_timer.Deactivate();
}
}
else
{ {
// Install cc feedback holdoff // TBD - should we queue the message so it can get a send retry?
cc_timer.SetInterval(grtt_estimate*backoff_factor); PLOG(PL_ERROR, "NormSenderNode::OnAckTimeout() error: SendMessage(ack) failure\n");
if (cc_timer.IsActive())
cc_timer.Reschedule();
else
session.ActivateTimer(cc_timer);
cc_timer.DecrementRepeatCount(); // put timer into "holdoff" phase
}
else if (cc_timer.IsActive())
{
cc_timer.Deactivate();
return false;
} }
session.ReturnMessageToPool(ack);
} }
else else
{ {
@ -2685,7 +2714,7 @@ bool NormSenderNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
NormAckingNode::NormAckingNode(class NormSession& theSession, NormNodeId nodeId) NormAckingNode::NormAckingNode(class NormSession& theSession, NormNodeId nodeId)
: NormNode(theSession, nodeId), ack_received(false), req_count(theSession.GetTxRobustFactor()) : NormNode(ACKER, theSession, nodeId), ack_received(false), req_count(theSession.GetTxRobustFactor())
{ {
} }

View File

@ -47,6 +47,10 @@ void NormObject::Retain()
void NormObject::Release() void NormObject::Release()
{ {
//if ((NULL != sender) && (reference_count == 1))
// TRACE("NormObject final release node>%lu object>%hu\n", (unsigned long)sender->GetId(), (unsigned short)transport_id);
if (sender) sender->Release(); if (sender) sender->Release();
if (reference_count) if (reference_count)
{ {
@ -235,7 +239,7 @@ void NormObject::Close()
NormObjectSize NormObject::GetBytesPending() const NormObjectSize NormObject::GetBytesPending() const
{ {
NormBlockId nextId; NormBlockId nextId;
if (GetFirstPending(nextId)) if (!IsStream() && GetFirstPending(nextId))
{ {
NormObjectSize largeBlockBytes = NormObjectSize(large_block_size) * NormObjectSize largeBlockBytes = NormObjectSize(large_block_size) *
NormObjectSize(segment_size); NormObjectSize(segment_size);
@ -264,7 +268,7 @@ NormObjectSize NormObject::GetBytesPending() const
{ {
return NormObjectSize(0); return NormObjectSize(0);
} }
} // end NormObject::GetBytesCompleted() } // end NormObject::GetBytesPending()
// Used by sender // Used by sender
bool NormObject::HandleInfoRequest(bool holdoff) bool NormObject::HandleInfoRequest(bool holdoff)
@ -824,7 +828,7 @@ bool NormObject::ReceiverRepairCheck(CheckLevel level,
if (segmentId >= max_pending_segment) if (segmentId >= max_pending_segment)
max_pending_segment = segmentId + 1; max_pending_segment = segmentId + 1;
} }
if (blockId == final_block_id) if (!IsStream() && (blockId == final_block_id))
{ {
unsigned int finalSegment = GetBlockSize(blockId) - 1; unsigned int finalSegment = GetBlockSize(blockId) - 1;
if (finalSegment <= segmentId) if (finalSegment <= segmentId)
@ -858,7 +862,6 @@ bool NormObject::ReceiverRepairCheck(CheckLevel level,
} }
else else
{ {
NormBlockId firstPending; NormBlockId firstPending;
if (GetFirstPending(firstPending)) if (GetFirstPending(firstPending))
{ {
@ -901,7 +904,7 @@ bool NormObject::ReceiverRepairCheck(CheckLevel level,
max_pending_block = blockId; max_pending_block = blockId;
max_pending_segment = GetBlockSize(blockId); max_pending_segment = GetBlockSize(blockId);
} }
if (blockId == final_block_id) if (!IsStream() && (blockId == final_block_id))
thruObject = true; thruObject = true;
if (timerActive) if (timerActive)
{ {
@ -1178,7 +1181,7 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
return requestAppended; return requestAppended;
} }
} }
if (flush || (nextId != max_pending_block)) if (flush || (nextId != max_pending_block))
{ {
block->AppendRepairRequest(nack, fec_id, fec_m, numData, nparity, transport_id, block->AppendRepairRequest(nack, fec_id, fec_m, numData, nparity, transport_id,
pending_info, segment_size); // (TBD) error check pending_info, segment_size); // (TBD) error check
@ -1192,10 +1195,10 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
block->AppendRepairRequest(nack, fec_id, fec_m, numData, nparity, transport_id, block->AppendRepairRequest(nack, fec_id, fec_m, numData, nparity, transport_id,
pending_info, segment_size); // (TBD) error check pending_info, segment_size); // (TBD) error check
} }
requestAppended = true; requestAppended = true;
prevForm = NormRepairRequest::INVALID;
} }
consecutiveCount = 0; consecutiveCount = 0;
prevForm = NormRepairRequest::INVALID;
} }
else if (iterating) else if (iterating)
{ {
@ -2832,7 +2835,7 @@ bool NormStreamObject::StreamUpdateStatus(NormBlockId blockId)
{ {
// This is a fresh rx stream, so init the read indices // This is a fresh rx stream, so init the read indices
read_init = false; read_init = false;
read_index.block = blockId; read_index.block = blockId; // for initial SYNC_STREAM sync, this will be zero (stream beginning)
read_index.segment = 0; read_index.segment = 0;
read_offset = 0; read_offset = 0;
} }
@ -3940,6 +3943,7 @@ void NormObjectTable::Destroy()
{ {
// TBD - should we issue PURGED/ABORTED notifications here??? // TBD - should we issue PURGED/ABORTED notifications here???
// (We haven't since this is destroyed only when session is terminated) // (We haven't since this is destroyed only when session is terminated)
// or when a NormSenderNode is deleted
Remove(obj); Remove(obj);
obj->Release(); obj->Release();
} }

View File

@ -32,7 +32,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
: session_mgr(sessionMgr), notify_pending(false), tx_port(0), tx_port_reuse(false), : session_mgr(sessionMgr), notify_pending(false), tx_port(0), tx_port_reuse(false),
tx_socket_actual(ProtoSocket::UDP), tx_socket(&tx_socket_actual), tx_socket_actual(ProtoSocket::UDP), tx_socket(&tx_socket_actual),
rx_socket(ProtoSocket::UDP), rx_cap(NULL), rx_port_reuse(false), local_node_id(localNodeId), rx_socket(ProtoSocket::UDP), rx_cap(NULL), rx_port_reuse(false), local_node_id(localNodeId),
ttl(DEFAULT_TTL), tos(0), loopback(false), fragmentation(false), ecn_enabled(false), ttl(DEFAULT_TTL), tos(0), loopback(false), mcast_loopback(false), fragmentation(false), ecn_enabled(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_sender(false), backoff_factor(DEFAULT_BACKOFF_FACTOR), is_sender(false),
tx_robust_factor(DEFAULT_ROBUST_FACTOR), instance_id(0), tx_robust_factor(DEFAULT_ROBUST_FACTOR), instance_id(0),
@ -66,8 +66,8 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
user_data(NULL), next(NULL) user_data(NULL), next(NULL)
{ {
interface_name[0] = '\0'; interface_name[0] = '\0';
tx_socket->SetNotifier(&sessionMgr.GetSocketNotifier()); tx_socket_actual.SetNotifier(&sessionMgr.GetSocketNotifier());
tx_socket->SetListener(this, &NormSession::TxSocketRecvHandler); tx_socket_actual.SetListener(this, &NormSession::TxSocketRecvHandler);
tx_address.Invalidate(); tx_address.Invalidate();
rx_socket.SetNotifier(&sessionMgr.GetSocketNotifier()); rx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
@ -112,10 +112,15 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
report_timer.SetListener(this, &NormSession::OnReportTimeout); report_timer.SetListener(this, &NormSession::OnReportTimeout);
report_timer.SetInterval(10.0); report_timer.SetInterval(10.0);
report_timer.SetRepeat(-1); report_timer.SetRepeat(-1);
user_timer.SetListener(this, &NormSession::OnUserTimeout);
user_timer.SetInterval(0.0);
user_timer.SetRepeat(0);
} }
NormSession::~NormSession() NormSession::~NormSession()
{ {
if (user_timer.IsActive()) user_timer.Deactivate();
if (NULL != preset_sender) if (NULL != preset_sender)
{ {
delete preset_sender; delete preset_sender;
@ -170,7 +175,6 @@ bool NormSession::Open()
{ {
tx_socket = &rx_socket; tx_socket = &rx_socket;
} }
} }
if (!rx_socket.IsOpen() && (!tx_only || (&rx_socket == tx_socket))) if (!rx_socket.IsOpen() && (!tx_only || (&rx_socket == tx_socket)))
{ {
@ -180,6 +184,7 @@ bool NormSession::Open()
Close(); Close();
return false; return false;
} }
rx_socket.EnableRecvDstAddr();
if (rx_port_reuse) if (rx_port_reuse)
{ {
// Enable port/addr reuse and bind socket to destination address // Enable port/addr reuse and bind socket to destination address
@ -204,7 +209,7 @@ bool NormSession::Open()
Close(); Close();
return false; return false;
} }
if (rx_connect_addr.IsValid()) if (rx_connect_addr.IsValid() && (0 != rx_connect_addr.GetPort()))
{ {
// For unicast, we use the "connect()" call to effectively // For unicast, we use the "connect()" call to effectively
// uniquely "bind" our rx_socket to the remote addr. // uniquely "bind" our rx_socket to the remote addr.
@ -243,7 +248,7 @@ bool NormSession::Open()
Close(); Close();
return false; return false;
} }
if (!tx_socket->SetLoopback(loopback)) if (!tx_socket->SetLoopback(mcast_loopback))
{ {
// TBD - Should this be set on the rx_socket instead??? // TBD - Should this be set on the rx_socket instead???
PLOG(PL_FATAL, "NormSession::Open() tx_socket.SetLoopback() error\n"); PLOG(PL_FATAL, "NormSession::Open() tx_socket.SetLoopback() error\n");
@ -265,7 +270,7 @@ bool NormSession::Open()
} }
if (!tx_only) if (!tx_only)
{ {
if (!rx_socket.JoinGroup(address, interfaceName)) if (!rx_socket.JoinGroup(address, interfaceName, ssm_source_addr.IsValid() ? &ssm_source_addr : NULL))
{ {
PLOG(PL_FATAL, "NormSession::Open() rx_socket.JoinGroup error\n"); PLOG(PL_FATAL, "NormSession::Open() rx_socket.JoinGroup error\n");
Close(); Close();
@ -371,7 +376,7 @@ void NormSession::Close()
{ {
const char* interfaceName = ('\0' != interface_name[0]) ? const char* interfaceName = ('\0' != interface_name[0]) ?
interface_name : NULL; interface_name : NULL;
rx_socket.LeaveGroup(address, interfaceName); rx_socket.LeaveGroup(address, interfaceName, ssm_source_addr.IsValid() ? &ssm_source_addr : NULL);
} }
rx_socket.Close(); rx_socket.Close();
} }
@ -406,6 +411,27 @@ bool NormSession::SetMulticastInterface(const char* interfaceName)
} }
} // end NormSession::SetMulticastInterface() } // end NormSession::SetMulticastInterface()
bool NormSession::SetSSM(const char* sourceAddress)
{
if (NULL != sourceAddress)
{
if (ssm_source_addr.ResolveFromString(sourceAddress))
{
return true;
}
else
{
PLOG(PL_ERROR, "NormSession::SetSSM() error: invalid source address\n");
return false;
}
}
else
{
ssm_source_addr.Invalidate();
return true;
}
} // end NormSession::SetSSM()
bool NormSession::SetRxPortReuse(bool enableReuse, bool NormSession::SetRxPortReuse(bool enableReuse,
const char* rxBindAddress, // bind() to <rxBindAddress>/<sessionPort> const char* rxBindAddress, // bind() to <rxBindAddress>/<sessionPort>
const char* senderAddress, // connect() to <senderAddress>/<senderPort> const char* senderAddress, // connect() to <senderAddress>/<senderPort>
@ -424,6 +450,7 @@ bool NormSession::SetRxPortReuse(bool enableReuse,
} }
if (NULL != senderAddress) if (NULL != senderAddress)
{ {
// TBD - if open, connect() to sender?
if (rx_connect_addr.ResolveFromString(senderAddress)) if (rx_connect_addr.ResolveFromString(senderAddress))
{ {
rx_connect_addr.SetPort(senderPort); rx_connect_addr.SetPort(senderPort);
@ -491,18 +518,21 @@ void NormSession::SetTxOnly(bool txOnly, bool connectToSessionAddress)
{ {
tx_only = txOnly; tx_only = txOnly;
tx_connect = connectToSessionAddress; tx_connect = connectToSessionAddress;
if (txOnly && IsOpen()) if (IsOpen())
{ {
if (IsReceiver()) StopReceiver(); if (txOnly)
if (rx_socket.IsOpen()) rx_socket.Close();
#ifdef ECN_SUPPORT
if (NULL != rx_cap)
{ {
rx_cap->Close(); if (IsReceiver()) StopReceiver();
delete rx_cap; if (rx_socket.IsOpen()) rx_socket.Close();
rx_cap = NULL; #ifdef ECN_SUPPORT
} if (NULL != rx_cap)
{
rx_cap->Close();
delete rx_cap;
rx_cap = NULL;
}
#endif // ECN_SUPPORT #endif // ECN_SUPPORT
}
// We connect tx_only session sockets when tx port // We connect tx_only session sockets when tx port
// reuse is set _and_ it is a unicast session // reuse is set _and_ it is a unicast session
// (This makes sure unicast NACKs get back to the right tx_socket!) // (This makes sure unicast NACKs get back to the right tx_socket!)
@ -530,13 +560,14 @@ double NormSession::GetTxRate()
} // end NormSession::GetTxRate() } // end NormSession::GetTxRate()
/*
// This hack can be uncommented give us a tx rate interval that is POISSON instead of PERIODIC
static double PoissonRand(double mean) static double PoissonRand(double mean)
{ {
return(-log(((double)rand())/((double)RAND_MAX))*mean); return(-log(((double)rand())/((double)RAND_MAX))*mean);
} }
*/
// This hack can give us a tx rate interval that is POISSON instead of PERIODIC
static inline double GetTxInterval(unsigned int msgSize, double txRate) static inline double GetTxInterval(unsigned int msgSize, double txRate)
{ {
double interval = (double)msgSize / txRate; double interval = (double)msgSize / txRate;
@ -653,6 +684,17 @@ void NormSession::SetTxRateBounds(double rateMin, double rateMax)
} // end NormSession::SetTxRateBounds() } // end NormSession::SetTxRateBounds()
void NormSession::SetUserTimer(double seconds)
{
if (user_timer.IsActive()) user_timer.Deactivate();
if (seconds >= 0.0)
{
user_timer.SetInterval(seconds);
ActivateTimer(user_timer);
}
} // end NormSession::SetUserTimer()
bool NormSession::StartSender(UINT16 instanceId, bool NormSession::StartSender(UINT16 instanceId,
UINT32 bufferSpace, UINT32 bufferSpace,
UINT16 segmentSize, UINT16 segmentSize,
@ -797,7 +839,7 @@ bool NormSession::StartSender(UINT16 instanceId,
} }
else else
{ {
// Don't let txRate below MIN(one segment per grtt, one segment per seconds) // Don't let txRate below MIN(one segment per grtt, one segment per second)
txRate = ((double)segment_size) / grtt_measured; txRate = ((double)segment_size) / grtt_measured;
if (txRate > ((double)(segment_size))) if (txRate > ((double)(segment_size)))
txRate = (double)(segment_size); txRate = (double)(segment_size);
@ -898,7 +940,7 @@ void NormSession::StopReceiver()
// Iterate sender_tree and close/release sender nodes // Iterate sender_tree and close/release sender nodes
NormSenderNode* senderNode = NormSenderNode* senderNode =
static_cast<NormSenderNode*>(sender_tree.GetRoot()); static_cast<NormSenderNode*>(sender_tree.GetRoot());
while (senderNode) while (NULL != senderNode)
{ {
sender_tree.DetachNode(senderNode); sender_tree.DetachNode(senderNode);
senderNode->Close(); senderNode->Close();
@ -916,7 +958,7 @@ void NormSession::DeleteRemoteSender(NormSenderNode& senderNode)
sender_tree.DetachNode(&senderNode); sender_tree.DetachNode(&senderNode);
senderNode.Close(); senderNode.Close();
senderNode.Release(); senderNode.Release();
} // end NormSession::DeleteSender() } // end NormSession::DeleteRemoteSender()
bool NormSession::PreallocateRemoteSender(UINT16 segmentSize, bool NormSession::PreallocateRemoteSender(UINT16 segmentSize,
UINT16 numData, UINT16 numData,
@ -1153,7 +1195,7 @@ void NormSession::Serve()
{ {
SenderQueueFlush(); SenderQueueFlush();
} }
else if (GetTxRobustFactor() == flush_count) //xxx else if (GetTxRobustFactor() == flush_count)
{ {
PLOG(PL_TRACE, "NormSession::Serve() node>%lu sender stream flush complete ...\n", PLOG(PL_TRACE, "NormSession::Serve() node>%lu sender stream flush complete ...\n",
@ -1270,7 +1312,7 @@ void NormSession::SenderCancelWatermark()
watermark_pending = false; watermark_pending = false;
} // end NormSession::SenderCancelWatermark() } // end NormSession::SenderCancelWatermark()
bool NormSession::SenderAddAckingNode(NormNodeId nodeId) NormAckingNode* NormSession::SenderAddAckingNode(NormNodeId nodeId, const ProtoAddress* srcAddress)
{ {
NormAckingNode* theNode = static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId)); NormAckingNode* theNode = static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
if (NULL == theNode) if (NULL == theNode)
@ -1281,18 +1323,19 @@ bool NormSession::SenderAddAckingNode(NormNodeId nodeId)
theNode->Reset(GetTxRobustFactor()); theNode->Reset(GetTxRobustFactor());
acking_node_tree.AttachNode(theNode); acking_node_tree.AttachNode(theNode);
acking_node_count++; acking_node_count++;
return true;
} }
else else
{ {
PLOG(PL_ERROR, "NormSession::SenderAddAckingNode() new NormAckingNode error: %s\n", GetErrorString()); PLOG(PL_ERROR, "NormSession::SenderAddAckingNode() new NormAckingNode error: %s\n", GetErrorString());
return NULL;
} }
} }
else else
{ {
PLOG(PL_ERROR, "NormSession::SenderAddAckingNode() warning: node already in list!?\n"); PLOG(PL_WARN, "NormSession::SenderAddAckingNode() warning: node already in list!?\n");
} }
return true; if (NULL != srcAddress) theNode->SetAddress(*srcAddress);
return theNode;
} // end NormSession::AddAckingNode(NormNodeId nodeId) } // end NormSession::AddAckingNode(NormNodeId nodeId)
void NormSession::SenderRemoveAckingNode(NormNodeId nodeId) void NormSession::SenderRemoveAckingNode(NormNodeId nodeId)
@ -1967,33 +2010,45 @@ char* NormSession::SenderGetFreeSegment(NormObjectId objectId,
return segment_pool.Get(); return segment_pool.Get();
} // end NormSession::SenderGetFreeSegment() } // end NormSession::SenderGetFreeSegment()
void NormSession::TxSocketRecvHandler(ProtoSocket& /*theSocket*/, void NormSession::TxSocketRecvHandler(ProtoSocket& theSocket,
ProtoSocket::Event theEvent) ProtoSocket::Event theEvent)
{ {
if (ProtoSocket::RECV == theEvent) if (ProtoSocket::RECV == theEvent)
{ {
NormMsg msg; NormMsg msg;
unsigned int msgLength = NormMsg::MAX_SIZE; unsigned int msgLength = NormMsg::MAX_SIZE;
while (tx_socket->RecvFrom(msg.AccessBuffer(), while (true)
{
if (theSocket.RecvFrom(msg.AccessBuffer(),
msgLength, msgLength,
msg.AccessAddress())) msg.AccessAddress()))
{
if (0 == msgLength) break; // no more data to read
if (msg.InitFromBuffer(msgLength))
{ {
HandleReceiveMessage(msg, true); if (0 == msgLength) break; // no more data to read
msgLength = NormMsg::MAX_SIZE; if (msg.InitFromBuffer(msgLength))
{
// Since it arrived on the tx_socket, we know it was unicast
HandleReceiveMessage(msg, true);
msgLength = NormMsg::MAX_SIZE;
}
else
{
PLOG(PL_ERROR, "NormSession::TxSocketRecvHandler() warning: received bad message\n");
}
} }
else else
{ {
PLOG(PL_ERROR, "NormSession::TxSocketRecvHandler() warning: received bad message\n"); // Probably an ICMP "port unreachable" error
if (Address().IsUnicast())
Notify(NormController::SEND_ERROR, NULL, NULL);
break;
} }
} }
} }
else if (ProtoSocket::SEND == theEvent) else if (ProtoSocket::SEND == theEvent)
{ {
// This is a little cheesy, but ... // This is a little cheesy, but ...
tx_socket->StopOutputNotification(); theSocket.StopOutputNotification();
if (tx_timer.IsActive()) tx_timer.Deactivate(); if (tx_timer.IsActive()) tx_timer.Deactivate();
if (OnTxTimeout(tx_timer)) if (OnTxTimeout(tx_timer))
{ {
@ -2014,80 +2069,110 @@ int rxMeasureGapMax = 0;
#endif // RX_MEASURE_ONLY #endif // RX_MEASURE_ONLY
void NormSession::RxSocketRecvHandler(ProtoSocket& theSocket, void NormSession::RxSocketRecvHandler(ProtoSocket& theSocket,
ProtoSocket::Event /*theEvent*/) ProtoSocket::Event theEvent)
{ {
unsigned int recvCount = 0; if (ProtoSocket::RECV == theEvent)
NormMsg msg;
unsigned int msgLength = NormMsg::MAX_SIZE;
while (theSocket.RecvFrom(msg.AccessBuffer(),
msgLength,
msg.AccessAddress()))
{ {
if (0 == msgLength) break; unsigned int recvCount = 0;
if (msg.InitFromBuffer(msgLength)) NormMsg msg;
unsigned int msgLength = NormMsg::MAX_SIZE;
while (true)
{ {
ProtoAddress destAddr; // we get the pkt destAddr to determine unicast/multicast
if (theSocket.RecvFrom(msg.AccessBuffer(),
msgLength,
msg.AccessAddress(),
destAddr))
{
if (0 == msgLength) break;
if (msg.InitFromBuffer(msgLength))
{
#ifdef RX_MEASURE_ONLY #ifdef RX_MEASURE_ONLY
// Measure rx rate / loss stats only // Measure rx rate / loss stats only
struct timeval currentTime; struct timeval currentTime;
ProtoSystemTime(currentTime); ProtoSystemTime(currentTime);
UINT16 seq = msg.GetSequence(); UINT16 seq = msg.GetSequence();
if (rxMeasureInit) if (rxMeasureInit)
{ {
rxMeasureRefTime = currentTime; rxMeasureRefTime = currentTime;
rxMeasureSeqPrev = seq; rxMeasureSeqPrev = seq;
rxMeasurePktCount = rxMeasurePktTotal = 1; rxMeasurePktCount = rxMeasurePktTotal = 1;
rxMeasureByteTotal = msgLength; rxMeasureByteTotal = msgLength;
rxMeasureInit = false; rxMeasureInit = false;
return; return;
} }
int seqDelta = (int)seq - (int)rxMeasureSeqPrev; int seqDelta = (int)seq - (int)rxMeasureSeqPrev;
ASSERT(seqDelta > 0); ASSERT(seqDelta > 0);
rxMeasurePktTotal += seqDelta; // total should have received. rxMeasurePktTotal += seqDelta; // total should have received.
rxMeasurePktCount++; // total actually received rxMeasurePktCount++; // total actually received
rxMeasureByteTotal += msgLength; rxMeasureByteTotal += msgLength;
if (seqDelta > rxMeasureGapMax) if (seqDelta > rxMeasureGapMax)
rxMeasureGapMax = seqDelta; rxMeasureGapMax = seqDelta;
int deltaSec = currentTime.tv_sec - rxMeasureRefTime.tv_sec; int deltaSec = currentTime.tv_sec - rxMeasureRefTime.tv_sec;
if (deltaSec >= 10) if (deltaSec >= 10)
{ {
if (currentTime.tv_usec > rxMeasureRefTime.tv_usec) if (currentTime.tv_usec > rxMeasureRefTime.tv_usec)
deltaSec += 1.0e-06 * (double)(currentTime.tv_usec - rxMeasureRefTime.tv_usec); deltaSec += 1.0e-06 * (double)(currentTime.tv_usec - rxMeasureRefTime.tv_usec);
else else
deltaSec -= 1.0e-06 * (double)(rxMeasureRefTime.tv_usec - currentTime.tv_usec); deltaSec -= 1.0e-06 * (double)(rxMeasureRefTime.tv_usec - currentTime.tv_usec);
double rxRate = (8.0/1000.0) * (double)rxMeasureByteTotal / (double)deltaSec; double rxRate = (8.0/1000.0) * (double)rxMeasureByteTotal / (double)deltaSec;
double rxLoss = 100.0 * (1.0 - (double)rxMeasurePktCount / (double)rxMeasurePktTotal); double rxLoss = 100.0 * (1.0 - (double)rxMeasurePktCount / (double)rxMeasurePktTotal);
rxMeasureRefTime = currentTime; rxMeasureRefTime = currentTime;
rxMeasureByteTotal = rxMeasurePktCount = rxMeasurePktTotal = rxMeasureGapMax = 0; rxMeasureByteTotal = rxMeasurePktCount = rxMeasurePktTotal = rxMeasureGapMax = 0;
} }
rxMeasureSeqPrev = seq; rxMeasureSeqPrev = seq;
return; return;
#endif // RX_MEASURE_ONLY #endif // RX_MEASURE_ONLY
bool ecnStatus = false; bool ecnStatus = false;
#ifdef SIMULATE #ifdef SIMULATE
ecnStatus = theSocket.GetEcnStatus(); ecnStatus = theSocket.GetEcnStatus();
//if (ecnStatus) TRACE("NORM RECEIVED PACKET W/ ECN BIT SET!!!!!\n"); //if (ecnStatus) TRACE("NORM RECEIVED PACKET W/ ECN BIT SET!!!!!\n");
#endif // SIMULATE #endif // SIMULATE
HandleReceiveMessage(msg, false, ecnStatus); bool wasUnicast;
msgLength = NormMsg::MAX_SIZE; if (destAddr.IsValid())
} wasUnicast = destAddr.IsUnicast();
else else
{ wasUnicast = false;
PLOG(PL_ERROR, "NormSession::RxSocketRecvHandler() warning: received bad message\n"); HandleReceiveMessage(msg, wasUnicast, ecnStatus);
} msgLength = NormMsg::MAX_SIZE;
// If our system gets very busy reading sockets, we should occasionally }
// execute any timeouts to keep protocol operation smooth (i.e., sending feedback) else
// TBD - perhaps this should be time based {
if (++recvCount >= 100) PLOG(PL_ERROR, "NormSession::RxSocketRecvHandler() warning: received bad message\n");
{ }
break; // If our system gets very busy reading sockets, we should occasionally
//session_mgr.DoSystemTimeout(); // execute any timeouts to keep protocol operation smooth (i.e., sending feedback)
//recvCount = 0; // TBD - perhaps this should be time based
if (++recvCount >= 100)
{
break;
//session_mgr.DoSystemTimeout();
//recvCount = 0;
}
}
else
{
// Probably an ICMP "port unreachable" error
if (Address().IsUnicast())
Notify(NormController::SEND_ERROR, NULL, NULL);
break;
}
} }
} }
else if (ProtoSocket::SEND == theEvent)
{
// This is a little cheesy, but ...
theSocket.StopOutputNotification();
if (tx_timer.IsActive()) tx_timer.Deactivate();
if (OnTxTimeout(tx_timer))
{
if (!tx_timer.IsActive()) ActivateTimer(tx_timer);
}
} // end if/else (theEvent == RECV/SEND)
} // end NormSession::RxSocketRecvHandler() } // end NormSession::RxSocketRecvHandler()
@ -2176,8 +2261,24 @@ void NormSession::OnPktCapture(ProtoChannel& theChannel,
continue; // not a UDP packet for our session, go read next packet continue; // not a UDP packet for our session, go read next packet
// If our rx_socket is "connected", make sure source addr/port matches // If our rx_socket is "connected", make sure source addr/port matches
srcIp.SetPort(udpPkt.GetSrcPort()); srcIp.SetPort(udpPkt.GetSrcPort());
if (rx_connect_addr.IsValid() && !rx_connect_addr.IsEqual(srcIp)) // if socket is connected, validate that the packet's from the specified source addr
continue; // not from the remote tx_socket to which we are "connected" if (rx_connect_addr.IsValid())
{
if (0 != rx_connect_addr.GetPort())
{
// check host addr component only for match
if (!rx_connect_addr.HostIsEqual(srcIp)) continue;
}
else
{
// check for addr _and_ port match
if (!rx_connect_addr.IsEqual(srcIp)) continue;
}
}
// if we are using SSM multicast make sure it's the right source addr
if (ssm_source_addr.IsValid() && !ssm_source_addr.HostIsEqual(srcIp)) continue;
// IMPORTANT NOTE: We ignore the checksum for OUTBOUND packets since these // IMPORTANT NOTE: We ignore the checksum for OUTBOUND packets since these
// are often computed by the Ethernet hardware these days // are often computed by the Ethernet hardware these days
@ -2194,7 +2295,7 @@ void NormSession::OnPktCapture(ProtoChannel& theChannel,
{ {
msg.AccessAddress() = srcIp; msg.AccessAddress() = srcIp;
HandleReceiveMessage(msg, !dstIp.IsMulticast(), (ProtoSocket::ECN_CE == ecnStatus)); HandleReceiveMessage(msg, dstIp.IsUnicast(), (ProtoSocket::ECN_CE == ecnStatus));
} }
else else
{ {
@ -2209,7 +2310,8 @@ void NormTrace(const struct timeval& currentTime,
NormNodeId localId, NormNodeId localId,
const NormMsg& msg, const NormMsg& msg,
bool sent, bool sent,
UINT8 fecM) UINT8 fecM,
UINT16 instId)
{ {
static const char* MSG_NAME[] = static const char* MSG_NAME[] =
{ {
@ -2270,7 +2372,7 @@ void NormTrace(const struct timeval& currentTime,
{ {
const NormInfoMsg& info = (const NormInfoMsg&)msg; const NormInfoMsg& info = (const NormInfoMsg&)msg;
PLOG(PL_ALWAYS, "inst>%hu seq>%hu INFO obj>%hu ", PLOG(PL_ALWAYS, "inst>%hu seq>%hu INFO obj>%hu ",
info.GetInstanceId(), seq, (UINT16)info.GetObjectId()); info.GetInstanceId(), seq, (UINT16)info.GetObjectId());
break; break;
} }
case NormMsg::DATA: case NormMsg::DATA:
@ -2367,6 +2469,7 @@ void NormTrace(const struct timeval& currentTime,
case NormMsg::ACK: case NormMsg::ACK:
case NormMsg::NACK: case NormMsg::NACK:
{ {
PLOG(PL_ALWAYS, "inst>%hu ", instId);
// look for NormCCFeedback extension // look for NormCCFeedback extension
NormHeaderExtension ext; NormHeaderExtension ext;
while (msg.GetNextExtension(ext)) while (msg.GetNextExtension(ext))
@ -2394,7 +2497,7 @@ void NormTrace(const struct timeval& currentTime,
} }
else else
{ {
PLOG(PL_ALWAYS, "ACK(XXX) "); PLOG(PL_ALWAYS, "ACK(ZZZ) ");
} }
} }
else else
@ -2425,7 +2528,42 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast, bool ecnSt
struct timeval currentTime; struct timeval currentTime;
::ProtoSystemTime(currentTime); ::ProtoSystemTime(currentTime);
if (trace) NormTrace(currentTime, LocalNodeId(), msg, false, 16); // TBD don't assume m == 16 (i.e. for fec_id == 2) if (trace)
{
// Initially assume it's a message we generated (or similarly configured sender)
UINT8 fecM = fec_m;
UINT16 instId = instance_id;
NormNodeId senderId;
switch (msg.GetType())
{
case NormMsg::ACK:
senderId = static_cast<NormAckMsg&>(msg).GetSenderId();
break;
case NormMsg::NACK:
senderId = static_cast<NormAckMsg&>(msg).GetSenderId();
break;
default:
senderId = msg.GetSourceId();
break;
}
if (IsReceiver() && (senderId != LocalNodeId()))
{
// Use our receiver state to look up sender if possible
NormSenderNode* sender = static_cast<NormSenderNode*>(sender_tree.FindNodeById(senderId));
if (NULL != sender)
{
fecM = sender->GetFecFieldSize();
instId = sender->GetInstanceId();
}
else
{
fecM = 16; // reasonable assumption
instId = 0;
}
}
NormTrace(currentTime, LocalNodeId(), msg, false, fecM, instId); // TBD don't assume m == 16 (i.e. for fec_id == 2)
}
NormMsg::Type msgType = msg.GetType(); NormMsg::Type msgType = msg.GetType();
@ -2454,6 +2592,8 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast, bool ecnSt
{ {
if (!SenderAddAckingNode(msg.GetSourceId())) if (!SenderAddAckingNode(msg.GetSourceId()))
PLOG(PL_ERROR, "NormSession::HandleReceiveMessage() error: unable to add acking node!\n"); PLOG(PL_ERROR, "NormSession::HandleReceiveMessage() error: unable to add acking node!\n");
NormAckingNode* acker = (NormAckingNode*)acking_node_tree.FindNodeById(sourceId);
Notify(NormController::ACKING_NODE_NEW, acker, NULL);
} }
} }
} }
@ -2513,6 +2653,7 @@ void NormSession::ReceiverHandleObjectMessage(const struct timeval& currentTim
PLOG(PL_INFO, "NormSession::ReceiverHandleObjectMessage() node>%lu sender>%lu instanceId change - resyncing.\n", PLOG(PL_INFO, "NormSession::ReceiverHandleObjectMessage() node>%lu sender>%lu instanceId change - resyncing.\n",
LocalNodeId(), theSender->GetId()); LocalNodeId(), theSender->GetId());
theSender->Close(); theSender->Close();
Notify(NormController::REMOTE_SENDER_RESET, theSender, NULL);
if (!theSender->Open(msg.GetInstanceId())) if (!theSender->Open(msg.GetInstanceId()))
{ {
PLOG(PL_ERROR, "NormSession::ReceiverHandleObjectMessage() node>%lu error re-opening NormSenderNode\n"); PLOG(PL_ERROR, "NormSession::ReceiverHandleObjectMessage() node>%lu error re-opening NormSenderNode\n");
@ -2528,6 +2669,7 @@ void NormSession::ReceiverHandleObjectMessage(const struct timeval& currentTim
theSender = preset_sender; theSender = preset_sender;
preset_sender = NULL; preset_sender = NULL;
theSender->SetId(msg.GetSourceId()); theSender->SetId(msg.GetSourceId());
theSender->SetAddress(msg.GetSource());
theSender->SetInstanceId(msg.GetInstanceId()); theSender->SetInstanceId(msg.GetInstanceId());
sender_tree.AttachNode(theSender); sender_tree.AttachNode(theSender);
PLOG(PL_DEBUG, "NormSession::ReceiverHandleObjectMessage() node>%lu new remote sender:%lu ...\n", PLOG(PL_DEBUG, "NormSession::ReceiverHandleObjectMessage() node>%lu new remote sender:%lu ...\n",
@ -2535,6 +2677,7 @@ void NormSession::ReceiverHandleObjectMessage(const struct timeval& currentTim
} }
else if (NULL != (theSender = new NormSenderNode(*this, msg.GetSourceId()))) else if (NULL != (theSender = new NormSenderNode(*this, msg.GetSourceId())))
{ {
theSender->SetAddress(msg.GetSource());
Notify(NormController::REMOTE_SENDER_NEW, theSender, NULL); Notify(NormController::REMOTE_SENDER_NEW, theSender, NULL);
if (theSender->Open(msg.GetInstanceId())) if (theSender->Open(msg.GetInstanceId()))
{ {
@ -2558,7 +2701,12 @@ void NormSession::ReceiverHandleObjectMessage(const struct timeval& currentTim
} }
} }
theSender->Activate(true); theSender->Activate(true);
theSender->SetAddress(msg.GetSource()); if (!theSender->GetAddress().IsEqual(msg.GetSource()))
{
// sender source address has changed
theSender->SetAddress(msg.GetSource());
Notify(NormController::REMOTE_SENDER_ADDRESS, theSender, NULL);
}
theSender->UpdateRecvRate(currentTime, msg.GetLength()); theSender->UpdateRecvRate(currentTime, msg.GetLength());
//if (ecnStatus) TRACE("UPDATING LOSS EST w/ ECN pkt\n"); //if (ecnStatus) TRACE("UPDATING LOSS EST w/ ECN pkt\n");
theSender->UpdateLossEstimate(currentTime, msg.GetSequence(), ecnStatus); theSender->UpdateLossEstimate(currentTime, msg.GetSequence(), ecnStatus);
@ -2576,13 +2724,14 @@ void NormSession::ReceiverHandleCommand(const struct timeval& currentTime,
// Do common updates for senders we already know. // Do common updates for senders we already know.
NormNodeId sourceId = cmd.GetSourceId(); NormNodeId sourceId = cmd.GetSourceId();
NormSenderNode* theSender = (NormSenderNode*)sender_tree.FindNodeById(sourceId); NormSenderNode* theSender = (NormSenderNode*)sender_tree.FindNodeById(sourceId);
if (theSender) if (NULL != theSender)
{ {
if (cmd.GetInstanceId() != theSender->GetInstanceId()) if (cmd.GetInstanceId() != theSender->GetInstanceId())
{ {
PLOG(PL_INFO, "NormSession::ReceiverHandleCommand() node>%lu sender>%lu instanceId change - resyncing.\n", PLOG(PL_INFO, "NormSession::ReceiverHandleCommand() node>%lu sender>%lu instanceId change - resyncing.\n",
LocalNodeId(), theSender->GetId()); LocalNodeId(), theSender->GetId());
theSender->Close(); theSender->Close();
Notify(NormController::REMOTE_SENDER_RESET, theSender, NULL);
if (!theSender->Open(cmd.GetInstanceId())) if (!theSender->Open(cmd.GetInstanceId()))
{ {
PLOG(PL_ERROR, "NormSession::ReceiverHandleCommand() node>%lu error re-opening NormSenderNode\n"); PLOG(PL_ERROR, "NormSession::ReceiverHandleCommand() node>%lu error re-opening NormSenderNode\n");
@ -2600,6 +2749,7 @@ void NormSession::ReceiverHandleCommand(const struct timeval& currentTime,
theSender = preset_sender; theSender = preset_sender;
preset_sender = NULL; preset_sender = NULL;
theSender->SetId(cmd.GetSourceId()); theSender->SetId(cmd.GetSourceId());
theSender->SetAddress(cmd.GetSource());
theSender->SetInstanceId(cmd.GetInstanceId()); theSender->SetInstanceId(cmd.GetInstanceId());
sender_tree.AttachNode(theSender); sender_tree.AttachNode(theSender);
PLOG(PL_DEBUG, "NormSession::ReceiverHandleObjectMessage() node>%lu new remote sender:%lu ...\n", PLOG(PL_DEBUG, "NormSession::ReceiverHandleObjectMessage() node>%lu new remote sender:%lu ...\n",
@ -2608,6 +2758,7 @@ void NormSession::ReceiverHandleCommand(const struct timeval& currentTime,
else if ((theSender = new NormSenderNode(*this, cmd.GetSourceId()))) else if ((theSender = new NormSenderNode(*this, cmd.GetSourceId())))
{ {
Notify(NormController::REMOTE_SENDER_NEW, theSender, NULL); Notify(NormController::REMOTE_SENDER_NEW, theSender, NULL);
theSender->SetAddress(cmd.GetSource());
if (theSender->Open(cmd.GetInstanceId())) if (theSender->Open(cmd.GetInstanceId()))
{ {
sender_tree.AttachNode(theSender); sender_tree.AttachNode(theSender);
@ -2634,7 +2785,12 @@ void NormSession::ReceiverHandleCommand(const struct timeval& currentTime,
theSender->Activate(true); theSender->Activate(true);
else else
theSender->Activate(false); theSender->Activate(false);
theSender->SetAddress(cmd.GetSource()); if (!theSender->GetAddress().IsEqual(cmd.GetSource()))
{
// sender source address has changed
theSender->SetAddress(cmd.GetSource());
Notify(NormController::REMOTE_SENDER_ADDRESS, theSender, NULL);
}
theSender->UpdateRecvRate(currentTime, cmd.GetLength()); theSender->UpdateRecvRate(currentTime, cmd.GetLength());
theSender->UpdateLossEstimate(currentTime, cmd.GetSequence(), ecnStatus); theSender->UpdateLossEstimate(currentTime, cmd.GetSequence(), ecnStatus);
theSender->IncrementRecvTotal(cmd.GetLength()); // for statistics only (TBD) #ifdef NORM_DEBUG theSender->IncrementRecvTotal(cmd.GetLength()); // for statistics only (TBD) #ifdef NORM_DEBUG
@ -3076,14 +3232,14 @@ void NormSession::SenderHandleNackMessage(const struct timeval& currentTime, Nor
if (GetDebugLevel() >= PL_DEBUG) if (GetDebugLevel() >= PL_DEBUG)
{ {
PLOG(PL_ALWAYS, "node>%lu sender (tactive:%d)received NACK message with content:\n", PLOG(PL_ALWAYS, "node>%lu sender (tactive:%d) received NACK message with content:\n",
LocalNodeId(), repair_timer.IsActive()); LocalNodeId(), repair_timer.IsActive());
LogRepairContent(nack.GetRepairContent(), nack.GetRepairContentLength(), fec_id, fec_m); LogRepairContent(nack.GetRepairContent(), nack.GetRepairContentLength(), fec_id, fec_m);
PLOG(PL_ALWAYS, "\n"); PLOG(PL_ALWAYS, "\n");
} }
// (TBD) maintain average of "numErasures" for SEGMENT repair requests // (TBD) maintain average of "numErasures" for SEGMENT repair requests
// to use as input to a an automatic "auto parity" adjustor // to use as input to a future automatic "auto parity" adjustor???
// Update GRTT estimate // Update GRTT estimate
struct timeval grttResponse; struct timeval grttResponse;
nack.GetGrttResponse(grttResponse); nack.GetGrttResponse(grttResponse);
@ -3660,8 +3816,8 @@ void NormSession::ReceiverHandleAckMessage(const NormAckMsg& ack)
} }
else else
{ {
PLOG(PL_DEBUG, "NormSession::ReceiverHandleAckMessage() node>%lu heard ACK for unknown sender.\n", PLOG(PL_DEBUG, "NormSession::ReceiverHandleAckMessage() node>%lu heard ACK for unknown sender>%lu.\n",
LocalNodeId()); LocalNodeId(), ack.GetSenderId());
} }
} // end NormSession::ReceiverHandleAckMessage() } // end NormSession::ReceiverHandleAckMessage()
@ -4239,16 +4395,17 @@ bool NormSession::SendMessage(NormMsg& msg)
// (TBD) fill in InstanceId fields on all messages as needed // (TBD) fill in InstanceId fields on all messages as needed
// We need "fec_m" for the message for NormTrace() purposes // We need "fec_m" for the message for NormTrace() purposes
UINT8 fecM = fec_m; // assume it's a sender message (will be overridden otherwise) UINT8 fecM = fec_m; // assume it's a sender message (will be overridden otherwise)
UINT16 instId = instance_id; // assume it's a sender message (will be overridden otherwise)
switch (msg.GetType()) switch (msg.GetType())
{ {
case NormMsg::INFO: case NormMsg::INFO:
case NormMsg::DATA: case NormMsg::DATA:
((NormObjectMsg&)msg).SetInstanceId(instance_id); ((NormObjectMsg&)msg).SetInstanceId(instId);
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).SetInstanceId(instance_id); ((NormCmdMsg&)msg).SetInstanceId(instId);
switch (((NormCmdMsg&)msg).GetFlavor()) switch (((NormCmdMsg&)msg).GetFlavor())
{ {
case NormCmdMsg::CC: case NormCmdMsg::CC:
@ -4276,6 +4433,7 @@ bool NormSession::SendMessage(NormMsg& msg)
(NormSenderNode*)sender_tree.FindNodeById(nack.GetSenderId()); (NormSenderNode*)sender_tree.FindNodeById(nack.GetSenderId());
ASSERT(NULL != theSender); ASSERT(NULL != theSender);
fecM = theSender->GetFecFieldSize(); fecM = theSender->GetFecFieldSize();
instId = theSender->GetInstanceId();
struct timeval currentTime; struct timeval currentTime;
ProtoSystemTime(currentTime); ProtoSystemTime(currentTime);
struct timeval grttResponse; struct timeval grttResponse;
@ -4292,6 +4450,7 @@ bool NormSession::SendMessage(NormMsg& msg)
(NormSenderNode*)sender_tree.FindNodeById(ack.GetSenderId()); (NormSenderNode*)sender_tree.FindNodeById(ack.GetSenderId());
ASSERT(NULL != theSender); ASSERT(NULL != theSender);
fecM = theSender->GetFecFieldSize(); fecM = theSender->GetFecFieldSize();
instId = theSender->GetInstanceId();
struct timeval grttResponse; struct timeval grttResponse;
struct timeval currentTime; struct timeval currentTime;
ProtoSystemTime(currentTime); ProtoSystemTime(currentTime);
@ -4325,7 +4484,7 @@ bool NormSession::SendMessage(NormMsg& msg)
{ {
struct timeval currentTime; struct timeval currentTime;
ProtoSystemTime(currentTime); ProtoSystemTime(currentTime);
NormTrace(currentTime, LocalNodeId(), msg, true, fecM); NormTrace(currentTime, LocalNodeId(), msg, true, fecM, instId);
} }
// Update sent rate tracker even if dropped (for testing/debugging) // Update sent rate tracker even if dropped (for testing/debugging)
sent_accumulator.Increment(msgSize); sent_accumulator.Increment(msgSize);
@ -4340,7 +4499,7 @@ bool NormSession::SendMessage(NormMsg& msg)
{ {
struct timeval currentTime; struct timeval currentTime;
ProtoSystemTime(currentTime); ProtoSystemTime(currentTime);
NormTrace(currentTime, LocalNodeId(), msg, true, fecM); NormTrace(currentTime, LocalNodeId(), msg, true, fecM, instId);
} }
// To keep track of _actual_ sent rate // To keep track of _actual_ sent rate
sent_accumulator.Increment(msgSize); sent_accumulator.Increment(msgSize);
@ -4349,7 +4508,8 @@ bool NormSession::SendMessage(NormMsg& msg)
} }
else else
{ {
PLOG(PL_DETAIL, "NormSession::SendMessage() sendto() error: %s\n", GetErrorString()); PLOG(PL_ERROR, "NormSession::SendMessage() sendto(%s/%hu) error: %s\n",
msg.GetDestination().GetHostString(), msg.GetDestination().GetPort(), GetErrorString());
tx_sequence--; tx_sequence--;
return false; return false;
} }
@ -4876,10 +5036,19 @@ bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
struct tm* ct = &timeStruct; struct tm* ct = &timeStruct;
#else #else
time_t secs = (time_t)currentTime.tv_sec; time_t secs = (time_t)currentTime.tv_sec;
struct tm* ct = gmtime(&secs); struct tm timeStruct;
//struct tm* ct = gmtime(&secs);
#ifdef WIN32
gmtime_s(&timeStruct, &secs);
struct tm* ct = &timeStruct;
#else
struct tm* ct = gmtime_r(&secs, &timeStruct);
#endif
#endif // if/else _WIN32_WCE #endif // if/else _WIN32_WCE
ASSERT(NULL != ct);
PLOG(PL_INFO, "REPORT time>%02d:%02d:%02d.%06lu node>%lu ***************************************\n", PLOG(PL_INFO, "REPORT time>%02d:%02d:%02d.%06lu node>%lu ***************************************\n",
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, LocalNodeId()); ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, LocalNodeId());
if (IsSender()) if (IsSender())
{ {
PLOG(PL_INFO, "Local status:\n"); PLOG(PL_INFO, "Local status:\n");
@ -4925,6 +5094,14 @@ bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
return true; return true;
} // end NormSession::OnReportTimeout() } // end NormSession::OnReportTimeout()
bool NormSession::OnUserTimeout(ProtoTimer& /*theTimer*/)
{
Notify(NormController::USER_TIMEOUT, (NormSenderNode*)NULL, (NormObject*)NULL);
return true;
} // end NormSession::OnUserTimeout(
NormSessionMgr::NormSessionMgr(ProtoTimerMgr& timerMgr, NormSessionMgr::NormSessionMgr(ProtoTimerMgr& timerMgr,
ProtoSocket::Notifier& socketNotifier, ProtoSocket::Notifier& socketNotifier,
ProtoChannel::Notifier* channelNotifier) ProtoChannel::Notifier* channelNotifier)

View File

@ -342,7 +342,8 @@ void NormTrace2(const struct timeval& currentTime,
clrFlag = ((NormCCFeedbackExtension&)ext).CCFlagIsSet(NormCC::CLR); clrFlag = ((NormCCFeedbackExtension&)ext).CCFlagIsSet(NormCC::CLR);
// Print ccRtt (only valid if pcap file is from sender node) // Print ccRtt (only valid if pcap file is from sender node)
double ccRtt = NormUnquantizeRtt(((NormCCFeedbackExtension&)ext).GetCCRtt()); double ccRtt = NormUnquantizeRtt(((NormCCFeedbackExtension&)ext).GetCCRtt());
PLOG(PL_ALWAYS, "ccRtt:%lf ", ccRtt); double ccLoss = NormUnquantizeLoss32(((NormCCFeedbackExtension&)ext).GetCCLoss32());
PLOG(PL_ALWAYS, "ccRtt:%lf ccLoss:%lf ", ccRtt, ccLoss);
break; break;
} }
} }

View File

@ -6,8 +6,7 @@ JNIEXPORT jobject JNICALL PKGNAME(NormEvent_getObject)
NormObjectHandle objectHandle; NormObjectHandle objectHandle;
jobject object = NULL; jobject object = NULL;
objectHandle = (NormObjectHandle)env->GetLongField(obj, objectHandle = (NormObjectHandle)env->GetLongField(obj, fid_NormEvent_objectHandle);
fid_NormEvent_objectHandle);
switch (NormObjectGetType(objectHandle)) { switch (NormObjectGetType(objectHandle)) {
case NORM_OBJECT_DATA: case NORM_OBJECT_DATA:

View File

@ -95,6 +95,26 @@ JNIEXPORT void JNICALL PKGNAME(NormSession_setMulticastInterface)
env->ReleaseStringUTFChars(interfaceName, str); env->ReleaseStringUTFChars(interfaceName, str);
} }
JNIEXPORT void JNICALL PKGNAME(NormSession_setSSM)
(JNIEnv *env, jobject obj, jstring sourceAddr) {
NormSessionHandle session;
const char *str;
session = (NormSessionHandle)env->GetLongField(obj, fid_NormSession_handle);
str = env->GetStringUTFChars(sourceAddr, NULL);
if (!NormSetSSM(session, str)) {
env->ReleaseStringUTFChars(sourceAddr, str);
env->ThrowNew((jclass)env->NewLocalRef(jw_IOException), "Failed to set SSM source address");
return;
}
env->ReleaseStringUTFChars(sourceAddr, str);
}
JNIEXPORT void JNICALL PKGNAME(NormSession_setTTL) JNIEXPORT void JNICALL PKGNAME(NormSession_setTTL)
(JNIEnv *env, jobject obj, jbyte ttl) { (JNIEnv *env, jobject obj, jbyte ttl) {
NormSessionHandle session; NormSessionHandle session;

View File

@ -42,7 +42,7 @@ JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_setRxPortReuse
/* /*
* Class: mil_navy_nrl_norm_NormSession * Class: mil_navy_nrl_norm_NormSession
* Method: setEcnSupport * Method: setEcnSupport
* Signature: (ZZ)V * Signature: (ZZZ)V
*/ */
JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_setEcnSupport JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_setEcnSupport
(JNIEnv *, jobject, jboolean, jboolean, jboolean); (JNIEnv *, jobject, jboolean, jboolean, jboolean);
@ -55,6 +55,14 @@ JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_setEcnSupport
JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_setMulticastInterface JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_setMulticastInterface
(JNIEnv *, jobject, jstring); (JNIEnv *, jobject, jstring);
/*
* Class: mil_navy_nrl_norm_NormSession
* Method: setSSM
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_setSSM
(JNIEnv *, jobject, jstring);
/* /*
* Class: mil_navy_nrl_norm_NormSession * Class: mil_navy_nrl_norm_NormSession
* Method: setTTL * Method: setTTL
@ -321,7 +329,7 @@ JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_cancelWatermark
/* /*
* Class: mil_navy_nrl_norm_NormSession * Class: mil_navy_nrl_norm_NormSession
* Method: cancelWatermark * Method: resetWatermark
* Signature: ()V * Signature: ()V
*/ */
JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_resetWatermark JNIEXPORT void JNICALL Java_mil_navy_nrl_norm_NormSession_resetWatermark

View File

@ -31,7 +31,7 @@ public class NormEvent {
} }
/** /**
* @return Returns the node. * @return Returns the session.
*/ */
public NormSession getSession() { public NormSession getSession() {
if (sessionHandle == 0) { if (sessionHandle == 0) {
@ -51,6 +51,9 @@ public class NormEvent {
return new NormNode(nodeHandle); return new NormNode(nodeHandle);
} }
/**
* @return Returns the object.
*/
public native NormObject getObject(); public native NormObject getObject();
/** /**

View File

@ -11,7 +11,7 @@ import mil.navy.nrl.norm.enums.NormObjectType;
* @author Jason Rush * @author Jason Rush
*/ */
public class NormObject { public class NormObject {
private long handle; // The pointer to the native NormInstanceHandle private long handle; // The pointer to the native NormObjectHandle
NormObject(long handle) { NormObject(long handle) {
this.handle = handle; this.handle = handle;

View File

@ -19,7 +19,7 @@ import mil.navy.nrl.norm.enums.NormSyncPolicy;
public class NormSession { public class NormSession {
private static Map<Long, NormSession> normSessions = new HashMap<Long, NormSession>(); private static Map<Long, NormSession> normSessions = new HashMap<Long, NormSession>();
private long handle; // The pointer to the native NormInstanceHandle private long handle; // The pointer to the native NormSessionHandle
/** /**
* Package protected constructor is invoked by NormInstance * Package protected constructor is invoked by NormInstance
@ -38,7 +38,6 @@ public class NormSession {
public void destroySession() { public void destroySession() {
normSessions.remove(handle); normSessions.remove(handle);
destroySessionNative(); destroySessionNative();
} }
@ -64,6 +63,9 @@ public class NormSession {
public native void setMulticastInterface(String interfaceName) public native void setMulticastInterface(String interfaceName)
throws IOException; throws IOException;
public native void setSSM(String sourceAddr)
throws IOException;
public native void setTTL(byte ttl) throws IOException; public native void setTTL(byte ttl) throws IOException;
public native void setTOS(byte tos) throws IOException; public native void setTOS(byte tos) throws IOException;

View File

@ -19,6 +19,8 @@ public enum NormEventType {
NORM_TX_RATE_CHANGED, NORM_TX_RATE_CHANGED,
NORM_LOCAL_SENDER_CLOSED, NORM_LOCAL_SENDER_CLOSED,
NORM_REMOTE_SENDER_NEW, NORM_REMOTE_SENDER_NEW,
NORM_REMOTE_SENDER_RESET,
NORM_REMOTE_SENDER_ADDRESS,
NORM_REMOTE_SENDER_ACTIVE, NORM_REMOTE_SENDER_ACTIVE,
NORM_REMOTE_SENDER_INACTIVE, NORM_REMOTE_SENDER_INACTIVE,
NORM_REMOTE_SENDER_PURGED, NORM_REMOTE_SENDER_PURGED,

View File

@ -1,7 +1,4 @@
/*
* Copyright (c) 2010 by General Dynamics Advanced Information Systems
* Classification: UNCLASSIFIED
*/
package mil.navy.nrl.norm.enums; package mil.navy.nrl.norm.enums;
/** /**
@ -11,6 +8,7 @@ package mil.navy.nrl.norm.enums;
* *
* @author Jason Rush * @author Jason Rush
*/ */
public enum NormSyncPolicy { public enum NormSyncPolicy {
NORM_SYNC_CURRENT, NORM_SYNC_CURRENT,
NORM_SYNC_STREAM, NORM_SYNC_STREAM,

View File

@ -1,7 +1,4 @@
/*
* Copyright (c) 2010 by General Dynamics Advanced Information Systems
* Classification: UNCLASSIFIED
*/
package mil.navy.nrl.norm.io; package mil.navy.nrl.norm.io;
import mil.navy.nrl.norm.NormEvent; import mil.navy.nrl.norm.NormEvent;

View File

@ -1,7 +1,3 @@
/*
* Copyright (c) 2010 by General Dynamics Advanced Information Systems
* Classification: UNCLASSIFIED
*/
package mil.navy.nrl.norm.io; package mil.navy.nrl.norm.io;
import java.io.IOException; import java.io.IOException;
@ -33,6 +29,7 @@ public class NormInputStream extends InputStream {
private Object closeLock; private Object closeLock;
private boolean bufferIsEmpty; private boolean bufferIsEmpty;
private boolean receivedEof;
public NormInputStream(String address, int port) throws IOException { public NormInputStream(String address, int port) throws IOException {
// Create the NORM instance // Create the NORM instance
@ -50,6 +47,7 @@ public class NormInputStream extends InputStream {
closeLock = new Object(); closeLock = new Object();
bufferIsEmpty = true; bufferIsEmpty = true;
receivedEof = false;
} }
public synchronized void openDebugLog(String filename) throws IOException { public synchronized void openDebugLog(String filename) throws IOException {
@ -198,12 +196,12 @@ public class NormInputStream extends InputStream {
} }
do { do {
while (normInstance.hasNextEvent(0, 0)) { while (bufferIsEmpty || normInstance.hasNextEvent(0, 0)) {
processEvent(); processEvent();
}
while (bufferIsEmpty) { if (receivedEof) {
processEvent(); return -1;
}
} }
if (normStream == null) { if (normStream == null) {
@ -254,6 +252,9 @@ public class NormInputStream extends InputStream {
case NORM_RX_OBJECT_ABORTED: case NORM_RX_OBJECT_ABORTED:
case NORM_RX_OBJECT_COMPLETED: case NORM_RX_OBJECT_COMPLETED:
normStream = null; normStream = null;
// Signal that the stream has ended
receivedEof = true;
break; break;
default: default:

View File

@ -1,7 +1,4 @@
/*
* Copyright (c) 2010 by General Dynamics Advanced Information Systems
* Classification: UNCLASSIFIED
*/
package mil.navy.nrl.norm.io; package mil.navy.nrl.norm.io;
import java.io.IOException; import java.io.IOException;

View File

@ -1,7 +1,4 @@
/*
* Copyright (c) 2010 by General Dynamics Advanced Information Systems
* Classification: UNCLASSIFIED
*/
package mil.navy.nrl.norm.io; package mil.navy.nrl.norm.io;
import java.io.IOException; import java.io.IOException;

View File

@ -58,18 +58,20 @@ NORM_TX_OBJECT_PURGED = 7
NORM_TX_RATE_CHANGED = 8 NORM_TX_RATE_CHANGED = 8
NORM_LOCAL_SENDER_CLOSED = 9 NORM_LOCAL_SENDER_CLOSED = 9
NORM_REMOTE_SENDER_NEW = 10 NORM_REMOTE_SENDER_NEW = 10
NORM_REMOTE_SENDER_ACTIVE = 11 NORM_REMOTE_SENDER_RESET = 11
NORM_REMOTE_SENDER_INACTIVE = 12 NORM_REMOTE_SENDER_ADDRESS = 12
NORM_REMOTE_SENDER_PURGED = 13 NORM_REMOTE_SENDER_ACTIVE = 13
NORM_RX_CMD_NEW = 14 NORM_REMOTE_SENDER_INACTIVE = 14
NORM_RX_OBJECT_NEW = 15 NORM_REMOTE_SENDER_PURGED = 15
NORM_RX_OBJECT_INFO = 16 NORM_RX_CMD_NEW = 16
NORM_RX_OBJECT_UPDATED = 17 NORM_RX_OBJECT_NEW = 17
NORM_RX_OBJECT_COMPLETED = 18 NORM_RX_OBJECT_INFO = 18
NORM_RX_OBJECT_ABORTED = 19 NORM_RX_OBJECT_UPDATED = 19
NORM_GRTT_UPDATED = 20 NORM_RX_OBJECT_COMPLETED = 20
NORM_CC_ACTIVE = 21 NORM_RX_OBJECT_ABORTED = 21
NORM_CC_INACTIVE = 22 NORM_GRTT_UPDATED = 22
NORM_CC_ACTIVE = 23
NORM_CC_INACTIVE = 24

View File

@ -154,10 +154,13 @@ def get_libnorm():
ctypes.c_bool, ctypes.c_bool] ctypes.c_bool, ctypes.c_bool]
libnorm.NormSetMulticastInterface.restype = ctypes.c_bool libnorm.NormSetMulticastInterface.restype = ctypes.c_bool
libnorm.NormSetMulticastInterface.argtypes = [ctypes.c_void_p, libnorm.NormSetMulticastInterface.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
ctypes.c_char_p]
libnorm.NormSetMulticastInterface.errcheck = errcheck_bool libnorm.NormSetMulticastInterface.errcheck = errcheck_bool
libnorm.NormSetSSM.restype = ctypes.c_bool
libnorm.NormSetSSM.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
libnorm.NormSetSSM.errcheck = errcheck_bool
libnorm.NormSetTTL.restype = ctypes.c_bool libnorm.NormSetTTL.restype = ctypes.c_bool
libnorm.NormSetTTL.argtypes = [ctypes.c_void_p, ctypes.c_uint8] libnorm.NormSetTTL.argtypes = [ctypes.c_void_p, ctypes.c_uint8]
libnorm.NormSetTTL.errcheck = errcheck_bool libnorm.NormSetTTL.errcheck = errcheck_bool

View File

@ -63,6 +63,10 @@ class Event(object):
return "NORM_LOCAL_SENDER_CLOSED" return "NORM_LOCAL_SENDER_CLOSED"
elif self.type == c.NORM_REMOTE_SENDER_NEW: elif self.type == c.NORM_REMOTE_SENDER_NEW:
return "NORM_REMOTE_SENDER_NEW" return "NORM_REMOTE_SENDER_NEW"
elif self.type == c.NORM_REMOTE_SENDER_RESET:
return "NORM_REMOTE_SENDER_RESET"
elif self.type == c.NORM_REMOTE_SENDER_ADDRESS:
return "NORM_REMOTE_SENDER_ADDRESS"
elif self.type == c.NORM_REMOTE_SENDER_ACTIVE: elif self.type == c.NORM_REMOTE_SENDER_ACTIVE:
return "NORM_REMOTE_SENDER_ACTIVE" return "NORM_REMOTE_SENDER_ACTIVE"
elif self.type == c.NORM_REMOTE_SENDER_INACTIVE: elif self.type == c.NORM_REMOTE_SENDER_INACTIVE:

View File

@ -50,6 +50,9 @@ class Session(object):
def setMulticastInterface(self, iface): def setMulticastInterface(self, iface):
libnorm.NormSetMulticastInterface(self, iface) libnorm.NormSetMulticastInterface(self, iface)
def setSSM(self, srcAddr):
libnorm.NormSetSSM(self, srcAddr)
def setTTL(self, ttl): def setTTL(self, ttl):
libnorm.NormSetTTL(self, ttl) libnorm.NormSetTTL(self, ttl)

View File

@ -1,8 +1,6 @@
/* Process model C++ form file: norm_protolib.pr.cpp */ /* Process model C++ form file: norm_protolib.pr.cpp */
/* Portions of this file copyright 1992-2006 by OPNET Technologies, Inc. */ /* Portions of this file copyright 1992-2006 by OPNET Technologies, Inc. */
/* This variable carries the header into the object file */ /* This variable carries the header into the object file */
const char norm_protolib_pr_cpp [] = "MIL_3_Tfile_Hdr_ 120A 30A modeler 7 464DEF85 464DEF85 1 wn12jh Jim@Hauser 0 0 none none 0 0 none 0 0 0 0 0 0 0 0 10de 3 "; const char norm_protolib_pr_cpp [] = "MIL_3_Tfile_Hdr_ 120A 30A modeler 7 464DEF85 464DEF85 1 wn12jh Jim@Hauser 0 0 none none 0 0 none 0 0 0 0 0 0 0 0 10de 3 ";
#include <string.h> #include <string.h>

BIN
waf vendored

Binary file not shown.