pull/2/head
Jeff Weston 2019-09-11 11:42:54 -04:00
parent f451a006f6
commit 700519ec12
18 changed files with 3895 additions and 638 deletions

2885
NormDeveloperGuide.html Normal file

File diff suppressed because it is too large Load Diff

BIN
NormDeveloperGuide.pdf Normal file

Binary file not shown.

View File

@ -1,9 +1,14 @@
NORM Version History NORM Version History
Version 1.2b5
=============
- Initial release with theoretically-working API
(including "Norm Developer's Guide!")
Version 1.2b4 Version 1.2b4
============= =============
- Finally remembered to update this file! - Finally remembered to update this file!
- Added "help" command to "norm" demo app (Thanks Marinho Barcellos) - Added "help" command to "norm" demo app (Thanks Marinho Barcellos!)
- New rxbuffer mgmnt scheme to better use limited buffer space. - New rxbuffer mgmnt scheme to better use limited buffer space.
- Removed explicit rate limit on receiver feedback messages - Removed explicit rate limit on receiver feedback messages
- API more complete and established better API naming conventions - API more complete and established better API naming conventions
@ -12,6 +17,7 @@ Version 1.2b4
- NORM RFC 3940 was released and this version is in compliance. - NORM RFC 3940 was released and this version is in compliance.
- Added optional positive acknowledgements for sender-defined - Added optional positive acknowledgements for sender-defined
"watermarks". "watermarks".
- Fixed multicast leave problem when interfaceName was used for join
Version 1.1b9 Version 1.1b9
============= =============

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,8 @@
#include <windows.h> #include <windows.h>
#endif // WIN32 #endif // WIN32
#include <sys/types.h> // for "off_t" type
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// IMPORTANT NOTICE // IMPORTANT NOTICE
// The NORM API is _very_ much in a developmental phase // The NORM API is _very_ much in a developmental phase
@ -18,106 +20,27 @@
// is removed, the API shouldn't be considered final. // is removed, the API shouldn't be considered final.
/** NORM API Data Types and Constants
* These are data types and constants defined
* for the NORM API
*/
typedef const void* NormInstanceHandle; typedef const void* NormInstanceHandle;
extern const NormInstanceHandle NORM_INSTANCE_INVALID; extern const NormInstanceHandle NORM_INSTANCE_INVALID;
NormInstanceHandle NormCreateInstance();
void NormDestroyInstance(NormInstanceHandle instanceHandle);
// NORM session creation and control
typedef const void* NormSessionHandle; typedef const void* NormSessionHandle;
extern const NormSessionHandle NORM_SESSION_INVALID; extern const NormSessionHandle NORM_SESSION_INVALID;
typedef const void* NormNodeHandle;
extern const NormNodeHandle NORM_NODE_INVALID;
typedef unsigned long NormNodeId; typedef unsigned long NormNodeId;
extern const NormNodeId NORM_NODE_NONE; extern const NormNodeId NORM_NODE_NONE;
extern const NormNodeId NORM_NODE_ANY; extern const NormNodeId NORM_NODE_ANY;
NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
const char* sessionAddress,
unsigned short sessionPort,
NormNodeId localNodeId);
void NormDestroySession(NormSessionHandle sessionHandle);
// Session management and parameters
void NormSetTransmitRate(NormSessionHandle sessionHandle,
double bitsPerSecond);
void NormSetGrttEstimate(NormSessionHandle sessionHandle,
double grttEstimate);
NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle);
bool NormSetLoopback(NormSessionHandle sessionHandle, bool state);
// Debug parameters
void NormSetMessageTrace(NormSessionHandle sessionHandle, bool state);
void NormSetTxLoss(NormSessionHandle sessionHandle, double percent);
void NormSetRxLoss(NormSessionHandle sessionHandle, double percent);
// Sender control & parameters
bool NormStartSender(NormSessionHandle sessionHandle,
unsigned long bufferSpace,
unsigned short segmentSize,
unsigned char numData,
unsigned char numParity);
void NormStopSender(NormSessionHandle sessionHandle);
bool NormAddAckingNode(NormSessionHandle sessionHandle,
NormNodeId nodeId);
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
NormNodeId nodeId);
// Receiver control & parameters
bool NormStartReceiver(NormSessionHandle sessionHandle,
unsigned long bufferSpace);
void NormStopReceiver(NormSessionHandle sessionHandle);
void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle,
bool state);
typedef const void* NormNodeHandle;
extern const NormNodeHandle NORM_NODE_INVALID;
typedef const void* NormObjectHandle; typedef const void* NormObjectHandle;
extern const NormObjectHandle NORM_OBJECT_INVALID; extern const NormObjectHandle NORM_OBJECT_INVALID;
typedef unsigned short NormObjectTransportId; typedef unsigned short NormObjectTransportId;
enum NormNackingMode
{
NORM_NACK_NONE,
NORM_NACK_INFO_ONLY,
NORM_NACK_NORMAL
};
void NormSetDefaultNackingMode(NormSessionHandle sessionHandle,
NormNackingMode nackingMode);
enum NormRepairBoundary
{
NORM_BOUNDARY_BLOCK,
NORM_BOUNDARY_OBJECT
};
void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle,
NormRepairBoundary repairBoundary);
NormRepairBoundary NormNodeGetRepairBoundary(NormNodeHandle nodeHandle);
void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle,
NormRepairBoundary repairBoundary);
NormNodeId NormNodeGetId(NormNodeHandle nodeHandle);
void NormNodeSetNackingMode(NormNodeHandle nodeHandle,
NormNackingMode nackingMode);
// General NormObject functions
enum NormObjectType enum NormObjectType
{ {
NORM_OBJECT_NONE, NORM_OBJECT_NONE,
@ -126,95 +49,27 @@ enum NormObjectType
NORM_OBJECT_STREAM NORM_OBJECT_STREAM
}; };
NormObjectType NormObjectGetType(NormObjectHandle objectHandle);
bool NormObjectGetInfo(NormObjectHandle objectHandle,
char* infoBuffer,
unsigned short* infoLen);
NormObjectTransportId NormObjectGetTransportId(NormObjectHandle objectHandle);
void NormObjectCancel(NormObjectHandle objectHandle);
void NormObjectReNormObjectRetaintain(NormObjectHandle objectHandle);
void NormObjectRelease(NormObjectHandle objectHandle);
// Receiver-only NormObject functions
NormNackingMode NormObjectGetNackingMode(NormObjectHandle objectHandle);
void NormObjectSetNackingMode(NormObjectHandle objectHandle,
NormNackingMode nackingMode);
// Sender-only NormObject functions
bool NormSetWatermark(NormSessionHandle sessionHandle,
NormObjectHandle objectHandle);
// NormStreamObject functions
NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
unsigned long bufferSize);
void NormStreamClose(NormObjectHandle streamHandle);
enum NormFlushMode enum NormFlushMode
{ {
NORM_FLUSH_NONE, NORM_FLUSH_NONE,
NORM_FLUSH_PASSIVE, NORM_FLUSH_PASSIVE,
NORM_FLUSH_ACTIVE NORM_FLUSH_ACTIVE
}; };
void NormStreamSetFlushMode(NormObjectHandle streamHandle, enum NormNackingMode
NormFlushMode flushMode); {
NORM_NACK_NONE,
void NormStreamSetPushMode(NormObjectHandle streamHandle, NORM_NACK_INFO_ONLY,
bool state); NORM_NACK_NORMAL
};
unsigned int NormStreamWrite(NormObjectHandle streamHandle,
const char* buffer, enum NormRepairBoundary
unsigned int numBytes); {
NORM_BOUNDARY_BLOCK,
void NormStreamFlush(NormObjectHandle streamHandle, bool eom = false); NORM_BOUNDARY_OBJECT
};
void NormStreamMarkEom(NormObjectHandle streamHandle);
bool NormStreamRead(NormObjectHandle streamHandle,
char* buffer,
unsigned int* numBytes);
bool NormStreamSeekMsgStart(NormObjectHandle streamHandle);
// NormFileObject Functions
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
const char* fileName,
const char* infoPtr = (const char*)0,
unsigned int infoLen = 0);
bool NormSetCacheDirectory(NormInstanceHandle instanceHandle,
const char* cachePath);
bool NormFileGetName(NormObjectHandle fileHandle,
char* nameBuffer,
unsigned int bufferLen);
bool NormFileRename(NormObjectHandle fileHandle,
const char* fileName);
// NormDataObject Functions
bool NormDataEnqueue(const char* dataPtr,
unsigned long dataLen,
const char* infoPtr = (const char*)0,
unsigned int infoLen = 0);
// NORM Event Notification Routines
enum NormEventType enum NormEventType
{ {
NORM_EVENT_INVALID = 0, NORM_EVENT_INVALID = 0,
@ -224,11 +79,12 @@ enum NormEventType
NORM_TX_OBJECT_PURGED, NORM_TX_OBJECT_PURGED,
NORM_LOCAL_SERVER_CLOSED, NORM_LOCAL_SERVER_CLOSED,
NORM_REMOTE_SERVER_NEW, NORM_REMOTE_SERVER_NEW,
NORM_REMOTE_SERVER_INACTIVE,
NORM_REMOTE_SERVER_ACTIVE, NORM_REMOTE_SERVER_ACTIVE,
NORM_REMOTE_SERVER_INACTIVE,
NORM_REMOTE_SERVER_PURGED,
NORM_RX_OBJECT_NEW, NORM_RX_OBJECT_NEW,
NORM_RX_OBJECT_INFO, NORM_RX_OBJECT_INFO,
NORM_RX_OBJECT_UPDATE, NORM_RX_OBJECT_UPDATED,
NORM_RX_OBJECT_COMPLETED, NORM_RX_OBJECT_COMPLETED,
NORM_RX_OBJECT_ABORTED NORM_RX_OBJECT_ABORTED
}; };
@ -240,7 +96,17 @@ typedef struct
NormNodeHandle sender; NormNodeHandle sender;
NormObjectHandle object; NormObjectHandle object;
} NormEvent; } NormEvent;
/** NORM API General Initialization and Operation Functions */
NormInstanceHandle NormCreateInstance();
void NormDestroyInstance(NormInstanceHandle instanceHandle);
// This MUST be set to enable NORM_OBJECT_FILE reception!
bool NormSetCacheDirectory(NormInstanceHandle instanceHandle,
const char* cachePath);
// This call blocks until the next NormEvent is ready unless asynchronous // This call blocks until the next NormEvent is ready unless asynchronous
// notification is used (see below) // notification is used (see below)
@ -252,7 +118,7 @@ bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent);
// with system calls like "WaitForSingleEvent()", and on Unix the // with system calls like "WaitForSingleEvent()", and on Unix the
// returned descriptor can be used in a "select()" call. If this type // returned descriptor can be used in a "select()" call. If this type
// of asynchronous notification is used, calls to "NormGetNextEvent()" will // of asynchronous notification is used, calls to "NormGetNextEvent()" will
// not block. // not block when the notification is posted.
#ifdef WIN32 #ifdef WIN32
typedef HANDLE NormDescriptor; typedef HANDLE NormDescriptor;
@ -261,4 +127,184 @@ typedef int NormDescriptor;
#endif // if/else WIN32/UNIX #endif // if/else WIN32/UNIX
NormDescriptor NormGetDescriptor(NormInstanceHandle instanceHandle); NormDescriptor NormGetDescriptor(NormInstanceHandle instanceHandle);
/** NORM Session Creation and Control Functions */
NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle,
const char* sessionAddress,
unsigned short sessionPort,
NormNodeId localNodeId);
void NormDestroySession(NormSessionHandle sessionHandle);
NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle);
bool NormSetMulticastInterface(NormSessionHandle sessionHandle,
const char* interfaceName);
bool NormSetTTL(NormSessionHandle sessionHandle,
unsigned char ttl);
bool NormSetTOS(NormSessionHandle sessionHandle,
unsigned char tos);
bool NormSetLoopback(NormSessionHandle sessionHandle,
bool loopback);
// Special functions for debug support
void NormSetMessageTrace(NormSessionHandle sessionHandle, bool state);
void NormSetTxLoss(NormSessionHandle sessionHandle, double percent);
void NormSetRxLoss(NormSessionHandle sessionHandle, double percent);
/** NORM Sender Functions */
bool NormStartSender(NormSessionHandle sessionHandle,
unsigned long bufferSpace,
unsigned short segmentSize,
unsigned char numData,
unsigned char numParity);
void NormStopSender(NormSessionHandle sessionHandle);
void NormSetTransmitRate(NormSessionHandle sessionHandle,
double bitsPerSecond);
void NormSetCongestionControl(NormSessionHandle sessionHandle,
bool state);
void NormSetTransmitRateBounds(NormSessionHandle sessionHandle,
double rateMin,
double rateMax);
void NormSetAutoParity(NormSessionHandle sessionHandle,
unsigned char autoParity);
void NormSetGrttEstimate(NormSessionHandle sessionHandle,
double grttEstimate);
bool NormAddAckingNode(NormSessionHandle sessionHandle,
NormNodeId nodeId);
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
NormNodeId nodeId);
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
const char* fileName,
const char* infoPtr = (const char*)0,
unsigned int infoLen = 0);
bool NormDataEnqueue(const char* dataPtr,
unsigned long dataLen,
const char* infoPtr = (const char*)0,
unsigned int infoLen = 0);
NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle,
unsigned long bufferSize);
void NormStreamClose(NormObjectHandle streamHandle);
unsigned int NormStreamWrite(NormObjectHandle streamHandle,
const char* buffer,
unsigned int numBytes);
void NormStreamFlush(NormObjectHandle streamHandle,
bool eom = false,
NormFlushMode flushMode = NORM_FLUSH_PASSIVE);
void NormStreamSetAutoFlush(NormObjectHandle streamHandle,
NormFlushMode flushMode);
void NormStreamSetPushEnable(NormObjectHandle streamHandle,
bool pushEnable);
void NormStreamMarkEom(NormObjectHandle streamHandle);
bool NormSetWatermark(NormSessionHandle sessionHandle,
NormObjectHandle objectHandle);
/** NORM Receiver Functions */
bool NormStartReceiver(NormSessionHandle sessionHandle,
unsigned long bufferSpace);
void NormStopReceiver(NormSessionHandle sessionHandle);
void NormSetSilentReceiver(NormSessionHandle sessionHandle,
bool silent);
void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle,
bool unicastNacks);
void NormNodeSetUnicastNack(NormNodeHandle remoteSender,
bool unicastNacks);
void NormSetDefaultNackingMode(NormSessionHandle sessionHandle,
NormNackingMode nackingMode);
void NormNodeSetNackingMode(NormNodeHandle nodeHandle,
NormNackingMode nackingMode);
void NormObjectSetNackingMode(NormObjectHandle objectHandle,
NormNackingMode nackingMode);
void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle,
NormRepairBoundary repairBoundary);
void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle,
NormRepairBoundary repairBoundary);
bool NormStreamRead(NormObjectHandle streamHandle,
char* buffer,
unsigned int* numBytes);
bool NormStreamSeekMsgStart(NormObjectHandle streamHandle);
unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle);
/** NORM Object Functions */
NormObjectType NormObjectGetType(NormObjectHandle objectHandle);
bool NormObjectHasInfo(NormObjectHandle objectHandle);
unsigned short NormObjectGetInfoLength(NormObjectHandle objectHandle);
unsigned short NormObjectGetInfo(NormObjectHandle objectHandle,
char* buffer,
unsigned short bufferLen);
off_t NormObjectGetSize(NormObjectHandle objectHandle);
void NormObjectCancel(NormObjectHandle objectHandle);
void NormObjectRetain(NormObjectHandle objectHandle);
void NormObjectRelease(NormObjectHandle objectHandle);
bool NormFileGetName(NormObjectHandle fileHandle,
char* nameBuffer,
unsigned int bufferLen);
bool NormFileRename(NormObjectHandle fileHandle,
const char* fileName);
const char*volatile NormDataAccessData(NormObjectHandle objectHandle);
char* NormDataDetachData(NormObjectHandle objectHandle);
NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle);
/** NORM Node Functions */
NormNodeId NormNodeGetId(NormNodeHandle nodeHandle);
void NormNodeRetain(NormNodeHandle nodeHandle);
void NormNodeRelease(NormNodeHandle nodeHandle);
#endif // _NORM_API #endif // _NORM_API

View File

@ -761,7 +761,7 @@ bool NormApp::OnCommand(const char* cmd, const char* val)
else if (!strncmp("unicastNacks", cmd, len)) else if (!strncmp("unicastNacks", cmd, len))
{ {
unicast_nacks = true; unicast_nacks = true;
if (session) session->SetUnicastNacks(true); if (session) session->ClientSetUnicastNacks(true);
} }
else if (!strncmp("silentClient", cmd, len)) else if (!strncmp("silentClient", cmd, len))
{ {
@ -1198,8 +1198,8 @@ void NormApp::Notify(NormController::Event event,
} // end switch(object->GetType()) } // end switch(object->GetType())
break; break;
case RX_OBJECT_UPDATE: case RX_OBJECT_UPDATED:
//DMSG(0, "NormApp::Notify(RX_OBJECT_UPDATE) ...\n"); //DMSG(0, "NormApp::Notify(RX_OBJECT_UPDATED) ...\n");
switch (object->GetType()) switch (object->GetType())
{ {
case NormObject::FILE: case NormObject::FILE:
@ -1212,7 +1212,7 @@ void NormApp::Notify(NormController::Event event,
{ {
if (object != rx_stream) if (object != rx_stream)
{ {
DMSG(0, "NormApp::Notify(RX_OBJECT_UPDATE) update for invalid stream\n"); DMSG(0, "NormApp::Notify(RX_OBJECT_UPDATED) update for invalid stream\n");
break; break;
} }
// Read the stream when it's updated // Read the stream when it's updated
@ -1532,7 +1532,7 @@ bool NormApp::OnStartup(int argc, const char*const* argv)
if (output || rx_cache_path) if (output || rx_cache_path)
{ {
// StartClient(bufferMax (per-sender)) // StartClient(bufferMax (per-sender))
session->SetUnicastNacks(unicast_nacks); session->ClientSetUnicastNacks(unicast_nacks);
session->ClientSetSilent(silent_client); session->ClientSetSilent(silent_client);
if (!session->StartClient(rx_buffer_size, interface_name)) if (!session->StartClient(rx_buffer_size, interface_name))
{ {

View File

@ -8,6 +8,7 @@
#include <string.h> // for memcpy(), etc #include <string.h> // for memcpy(), etc
#include <math.h> #include <math.h>
#include <stdlib.h> // for rand(), etc #include <stdlib.h> // for rand(), etc
#include <sys/types.h> // for off_t
#ifdef SIMULATE #ifdef SIMULATE
#define SIM_PAYLOAD_MAX (36+8) // MGEN message size + StreamPayloadHeaderLen() #define SIM_PAYLOAD_MAX (36+8) // MGEN message size + StreamPayloadHeaderLen()
@ -94,7 +95,9 @@ inline double NormUnquantizeRate(unsigned short rate)
} }
// This class is used to describe object "size" and/or "offset" // This class is used to describe object "size" and/or "offset"
// (TBD) This hokey implementation should use "off_t" // (TBD) This hokey implementation should use "off_t" as it's
// native storage format and get rid of this custom crap !!!
// (We should just get rid of this class !!!!!!!!)
class NormObjectSize class NormObjectSize
{ {
public: public:
@ -109,6 +112,7 @@ class NormObjectSize
size >>= 32; size >>= 32;
ASSERT(0 == (size & 0xffff0000)); ASSERT(0 == (size & 0xffff0000));
msb = size & 0x0000ffff; msb = size & 0x0000ffff;
msb = 0;
} }
UINT16 MSB() const {return msb;} UINT16 MSB() const {return msb;}
@ -159,6 +163,7 @@ class NormObjectSize
NormObjectSize operator/(const NormObjectSize& b) const; NormObjectSize operator/(const NormObjectSize& b) const;
off_t GetOffset() const off_t GetOffset() const
{ {
off_t offset = msb; off_t offset = msb;
offset <<= 32; offset <<= 32;
offset += lsb; offset += lsb;

View File

@ -59,7 +59,7 @@ NormServerNode::NormServerNode(class NormSession& theSession, NormNodeId nodeId)
repair_boundary = session.ClientGetDefaultRepairBoundary(); repair_boundary = session.ClientGetDefaultRepairBoundary();
default_nacking_mode = session.ClientGetDefaultNackingMode(); default_nacking_mode = session.ClientGetDefaultNackingMode();
unicast_nacks = session.UnicastNacks(); unicast_nacks = session.ClientGetUnicastNacks();
// (TBD) get "max_pending_range" value from NormSession parameter // (TBD) get "max_pending_range" value from NormSession parameter
repair_timer.SetListener(this, &NormServerNode::OnRepairTimeout); repair_timer.SetListener(this, &NormServerNode::OnRepairTimeout);
@ -1706,6 +1706,7 @@ void NormServerNode::Activate()
activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR); activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
session.ActivateTimer(activity_timer); session.ActivateTimer(activity_timer);
server_active = false; server_active = false;
session.Notify(NormController::REMOTE_SERVER_ACTIVE, this, NULL);
} }
else else
{ {
@ -1725,7 +1726,7 @@ bool NormServerNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
DMSG(0, "NormServerNode::OnActivityTimeout() node>%lu server>%lu gone inactive?\n", DMSG(0, "NormServerNode::OnActivityTimeout() node>%lu server>%lu gone inactive?\n",
LocalNodeId(), GetId()); LocalNodeId(), GetId());
FreeBuffers(); FreeBuffers();
// (TBD) Notify application session.Notify(NormController::REMOTE_SERVER_INACTIVE, this, NULL);
} }
else else
{ {

View File

@ -16,6 +16,8 @@ class NormNode
public: public:
NormNode(class NormSession& theSession, NormNodeId nodeId); NormNode(class NormSession& theSession, NormNodeId nodeId);
virtual ~NormNode(); virtual ~NormNode();
NormSession& GetSession() const {return session;}
void Retain(); void Retain();
void Release(); void Release();

View File

@ -11,7 +11,7 @@ NormObject::NormObject(NormObject::Type theType,
transport_id(transportId), segment_size(0), pending_info(false), repair_info(false), transport_id(transportId), segment_size(0), pending_info(false), repair_info(false),
current_block_id(0), next_segment_id(0), current_block_id(0), next_segment_id(0),
max_pending_block(0), max_pending_segment(0), max_pending_block(0), max_pending_segment(0),
info(NULL), info_len(0), accepted(false), notify_on_update(true) info_ptr(NULL), info_len(0), accepted(false), notify_on_update(true)
{ {
if (theServer) if (theServer)
nacking_mode = theServer->GetDefaultNackingMode(); nacking_mode = theServer->GetDefaultNackingMode();
@ -22,10 +22,10 @@ NormObject::NormObject(NormObject::Type theType,
NormObject::~NormObject() NormObject::~NormObject()
{ {
Close(); Close();
if (info) if (info_ptr)
{ {
delete info; delete info_ptr;
info = NULL; info_ptr = NULL;
} }
} }
@ -73,7 +73,7 @@ bool NormObject::Open(const NormObjectSize& objectSize,
{ {
pending_info = true; pending_info = true;
info_len = 0; info_len = 0;
if (!(info = new char[segmentSize])) if (!(info_ptr = new char[segmentSize]))
{ {
DMSG(0, "NormObject::Open() info allocation error\n"); DMSG(0, "NormObject::Open() info allocation error\n");
return false; return false;
@ -84,20 +84,20 @@ bool NormObject::Open(const NormObjectSize& objectSize,
{ {
if (infoPtr) if (infoPtr)
{ {
if (info) delete []info; if (info_ptr) delete []info_ptr;
if (infoLen > segmentSize) if (infoLen > segmentSize)
{ {
DMSG(0, "NormObject::Open() info too big error\n"); DMSG(0, "NormObject::Open() info too big error\n");
info_len = 0; info_len = 0;
return false; return false;
} }
if (!(info = new char[infoLen])) if (!(info_ptr = new char[infoLen]))
{ {
DMSG(0, "NormObject::Open() info allocation error\n"); DMSG(0, "NormObject::Open() info allocation error\n");
info_len = 0; info_len = 0;
return false; return false;
} }
memcpy(info, infoPtr, infoLen); memcpy(info_ptr, infoPtr, infoLen);
info_len = infoLen; info_len = infoLen;
pending_info = true; pending_info = true;
} }
@ -207,7 +207,7 @@ void NormObject::Close()
bool NormObject::HandleInfoRequest() bool NormObject::HandleInfoRequest()
{ {
bool increasedRepair = false; bool increasedRepair = false;
if (info) if (info_ptr)
{ {
if (!repair_info) if (!repair_info)
{ {
@ -1047,7 +1047,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
"Warning! info too long.\n", LocalNodeId(), server->GetId(), "Warning! info too long.\n", LocalNodeId(), server->GetId(),
(UINT16)transport_id); (UINT16)transport_id);
} }
memcpy(info, infoMsg.GetInfo(), info_len); memcpy(info_ptr, infoMsg.GetInfo(), info_len);
pending_info = false; pending_info = false;
session.Notify(NormController::RX_OBJECT_INFO, server, this); session.Notify(NormController::RX_OBJECT_INFO, server, this);
} }
@ -1219,9 +1219,10 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
block->SetPending(nextSegment); block->SetPending(nextSegment);
block->IncrementErasureCount(); block->IncrementErasureCount();
// Clear any erasure/retrieval segments // Clear any erasure/retrieval segments
for (UINT16 i = 0; i < erasureCount; i++) UINT16 i;
for (i = 0; i < erasureCount; i++)
block->DetachSegment(server->GetErasureLoc(i)); block->DetachSegment(server->GetErasureLoc(i));
for (UINT16 i = 0; i < retrievalCount; i++) for (i = 0; i < retrievalCount; i++)
block->DetachSegment(server->GetRetrievalLoc(i)); block->DetachSegment(server->GetRetrievalLoc(i));
return; return;
} }
@ -1272,7 +1273,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (objectUpdated && notify_on_update) if (objectUpdated && notify_on_update)
{ {
notify_on_update = false; notify_on_update = false;
session.Notify(NormController::RX_OBJECT_UPDATE, server, this); session.Notify(NormController::RX_OBJECT_UPDATED, server, this);
} }
} }
else else
@ -1418,7 +1419,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
default: default:
break; break;
} }
if (info) msg->SetFlag(NormObjectMsg::FLAG_INFO); if (info_ptr) msg->SetFlag(NormObjectMsg::FLAG_INFO);
msg->SetFecId(129); msg->SetFecId(129);
msg->SetObjectId(transport_id); msg->SetObjectId(transport_id);
@ -1435,7 +1436,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
{ {
// (TBD) set REPAIR_FLAG for retransmitted info // (TBD) set REPAIR_FLAG for retransmitted info
NormInfoMsg* infoMsg = (NormInfoMsg*)msg; NormInfoMsg* infoMsg = (NormInfoMsg*)msg;
infoMsg->SetInfo(info, info_len); infoMsg->SetInfo(info_ptr, info_len);
pending_info = false; pending_info = false;
return true; return true;
} }
@ -1938,7 +1939,7 @@ NormDataObject::NormDataObject(class NormSession& theSession,
const NormObjectId& objectId) const NormObjectId& objectId)
: NormObject(DATA, theSession, theServer, objectId), : NormObject(DATA, theSession, theServer, objectId),
large_block_length(0,0), small_block_length(0,0), large_block_length(0,0), small_block_length(0,0),
data_ptr(NULL), data_max(0) data_ptr(NULL), data_max(0), data_released(false)
{ {
} }
@ -1946,11 +1947,21 @@ NormDataObject::NormDataObject(class NormSession& theSession,
NormDataObject::~NormDataObject() NormDataObject::~NormDataObject()
{ {
Close(); Close();
if (data_released)
{
if (data_ptr)
{
delete data_ptr;
data_ptr = NULL;
}
data_released = false;
}
} }
// Assign data object to data ptr // Assign data object to data ptr
bool NormDataObject::Open(char* dataPtr, bool NormDataObject::Open(char* dataPtr,
UINT32 dataLen, UINT32 dataLen,
bool dataRelease,
const char* infoPtr, const char* infoPtr,
UINT16 infoLen) UINT16 infoLen)
{ {
@ -1976,15 +1987,16 @@ bool NormDataObject::Open(char* dataPtr,
} }
data_ptr = dataPtr; data_ptr = dataPtr;
data_max = dataLen; data_max = dataLen;
data_released = dataRelease;
large_block_length = NormObjectSize(large_block_size) * segment_size; large_block_length = NormObjectSize(large_block_size) * segment_size;
small_block_length = NormObjectSize(small_block_size) * segment_size; small_block_length = NormObjectSize(small_block_size) * segment_size;
return true; return true;
} // end NormDataObject::Open() } // end NormDataObject::Open()
bool NormDataObject::Accept(char* dataPtr, UINT32 dataMax) bool NormDataObject::Accept(char* dataPtr, UINT32 dataMax, bool dataRelease)
{ {
ASSERT(NULL == server); ASSERT(NULL == server);
if (Open(dataPtr, dataMax)) if (Open(dataPtr, dataMax, dataRelease))
{ {
NormObject::Accept(); NormObject::Accept();
return true; return true;
@ -2005,6 +2017,11 @@ bool NormDataObject::WriteSegment(NormBlockId blockId,
const char* buffer, const char* buffer,
bool /*msgStart*/) bool /*msgStart*/)
{ {
if (NULL == data_ptr)
{
DMSG(0, "NormDataObject::WriteSegment() error: NULL data_ptr\n");
return false;
}
UINT16 len; UINT16 len;
if (blockId == final_block_id) if (blockId == final_block_id)
{ {
@ -2046,6 +2063,11 @@ UINT16 NormDataObject::ReadSegment(NormBlockId blockId,
char* buffer, char* buffer,
bool* /*msgStart*/) bool* /*msgStart*/)
{ {
if (NULL == data_ptr)
{
DMSG(0, "NormDataObject::ReadSegment() error: NULL data_ptr\n");
return 0;
}
// Determine segment length from blockId::segmentId // Determine segment length from blockId::segmentId
UINT16 len; UINT16 len;
if (blockId == final_block_id) if (blockId == final_block_id)
@ -2075,14 +2097,23 @@ UINT16 NormDataObject::ReadSegment(NormBlockId blockId,
segmentSize*segmentId; segmentSize*segmentId;
} }
ASSERT(0 == segmentOffset.MSB()); ASSERT(0 == segmentOffset.MSB());
ASSERT(data_max >= (segmentOffset.LSB() + len)); if (data_max <= segmentOffset.LSB())
return 0;
else if (data_max <= (segmentOffset.LSB() + len))
len -= (segmentOffset.LSB() + len - data_max);
memcpy(buffer, data_ptr + segmentOffset.LSB(), len); memcpy(buffer, data_ptr + segmentOffset.LSB(), len);
return true; return len;
} // end NormDataObject::ReadSegment() } // end NormDataObject::ReadSegment()
char* NormDataObject::RetrieveSegment(NormBlockId blockId, char* NormDataObject::RetrieveSegment(NormBlockId blockId,
NormSegmentId segmentId) NormSegmentId segmentId)
{ {
if (NULL == data_ptr)
{
DMSG(0, "NormDataObject::RetrieveSegment() error: NULL data_ptr\n");
return NULL;
}
// Determine segment length from blockId::segmentId // Determine segment length from blockId::segmentId
UINT16 len; UINT16 len;
if (blockId == final_block_id) if (blockId == final_block_id)
@ -2101,7 +2132,7 @@ char* NormDataObject::RetrieveSegment(NormBlockId blockId,
if (server) if (server)
{ {
char* segment = server->GetRetrievalSegment(); char* segment = server->GetRetrievalSegment();
ReadSegment(blockId, segmentId, segment); len = ReadSegment(blockId, segmentId, segment);
memset(segment+len, 0, segment_size-len); memset(segment+len, 0, segment_size-len);
return segment; return segment;
} }
@ -2490,7 +2521,7 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
block->GetFirstPending(read_index.segment); block->GetFirstPending(read_index.segment);
NormBlock* tempBlock = block; NormBlock* tempBlock = block;
UINT32 tempOffset = read_offset; UINT32 tempOffset = read_offset;
session.Notify(NormController::RX_OBJECT_UPDATE, server, this); session.Notify(NormController::RX_OBJECT_UPDATED, server, this);
block = stream_buffer.Find(stream_buffer.RangeLo()); block = stream_buffer.Find(stream_buffer.RangeLo());
if (tempBlock == block) if (tempBlock == block)
{ {
@ -2954,6 +2985,18 @@ NormSimObject::~NormSimObject()
} }
bool NormSimObject::Open(UINT32 objectSize,
const char* infoPtr ,
UINT16 infoLen)
{
return (server ?
true :
NormObject::Open(objectSize, infoPtr, infoLen,
session.ServerSegmentSize(),
session.ServerBlockSize(),
session.ServerNumParity()));
} // end NormSimObject::Open()
UINT16 NormSimObject::ReadSegment(NormBlockId blockId, UINT16 NormSimObject::ReadSegment(NormBlockId blockId,
NormSegmentId segmentId, NormSegmentId segmentId,
char* buffer, char* buffer,
@ -2975,6 +3018,12 @@ UINT16 NormSimObject::ReadSegment(NormBlockId blockId,
return len; return len;
} // end NormSimObject::ReadSegment() } // end NormSimObject::ReadSegment()
char* NormSimObject::RetrieveSegment(NormBlockId blockId,
NormSegmentId segmentId)
{
return server ? server->GetRetrievalSegment() : NULL;
} // end NormSimObject::RetrieveSegment()
#endif // SIMULATE #endif // SIMULATE
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////

View File

@ -51,7 +51,9 @@ class NormObject
const NormObjectId& GetId() const {return transport_id;} const NormObjectId& GetId() const {return transport_id;}
const NormObjectSize& GetSize() const {return object_size;} const NormObjectSize& GetSize() const {return object_size;}
bool HaveInfo() const {return (info_len > 0);} bool HaveInfo() const {return (info_len > 0);}
const char* GetInfo() const {return info;} bool HasInfo() const {return (NULL != info_ptr);}
const char* GetInfo() const {return info_ptr;}
UINT16 GetInfoLength() const {return info_len;} UINT16 GetInfoLength() const {return info_len;}
bool IsStream() const {return (STREAM == type);} bool IsStream() const {return (STREAM == type);}
@ -257,7 +259,7 @@ class NormObject
NormBlockId final_block_id; NormBlockId final_block_id;
UINT16 final_segment_size; UINT16 final_segment_size;
NackingMode nacking_mode; NackingMode nacking_mode;
char* info; char* info_ptr;
UINT16 info_len; UINT16 info_len;
// Here are some members used to let us know // Here are some members used to let us know
@ -321,12 +323,19 @@ class NormDataObject : public NormObject
bool Open(char* dataPtr, bool Open(char* dataPtr,
UINT32 dataLen, UINT32 dataLen,
bool dataRelease,
const char* infoPtr = NULL, const char* infoPtr = NULL,
UINT16 infoLen = 0); UINT16 infoLen = 0);
bool Accept(char* dataPtr, UINT32 dataMax); bool Accept(char* dataPtr, UINT32 dataMax, bool dataRelease);
void Close(); void Close();
const char* GetData() {return data_ptr;} const char* GetData() {return data_ptr;}
char* DetachData()
{
char* dataPtr = data_ptr;
data_ptr = NULL;
return dataPtr;
}
virtual bool WriteSegment(NormBlockId blockId, virtual bool WriteSegment(NormBlockId blockId,
NormSegmentId segmentId, NormSegmentId segmentId,
@ -346,6 +355,8 @@ class NormDataObject : public NormObject
NormObjectSize small_block_length; NormObjectSize small_block_length;
char* data_ptr; char* data_ptr;
UINT32 data_max; UINT32 data_max;
bool data_released; // when true, data_ptr is deleted
// on NormDataObject destruction
}; // end class NormDataObject }; // end class NormDataObject
@ -357,7 +368,7 @@ class NormStreamObject : public NormObject
const NormObjectId& objectId); const NormObjectId& objectId);
~NormStreamObject(); ~NormStreamObject();
bool Open(UINT32 bufferSize, bool Open(UINT32 bufferSize,
const char* infoPtr = NULL, const char* infoPtr = NULL,
UINT16 infoLen = 0); UINT16 infoLen = 0);
void Close(); void Close();
@ -477,12 +488,9 @@ class NormSimObject : public NormObject
const NormObjectId& objectId); const NormObjectId& objectId);
~NormSimObject(); ~NormSimObject();
bool Open(UINT32 objectSize, bool Open(UINT32 objectSize,
const char* infoPtr = NULL, const char* infoPtr = NULL,
UINT16 infoLen = 0) UINT16 infoLen = 0);
{
return server ? true : NormObject::Open(objectSize, infoPtr, infoLen);
}
bool Accept() {NormObject::Accept(); return true;} bool Accept() {NormObject::Accept(); return true;}
void Close() {NormObject::Close();} void Close() {NormObject::Close();}
@ -497,10 +505,7 @@ class NormSimObject : public NormObject
bool* msgStart = NULL); bool* msgStart = NULL);
virtual char* RetrieveSegment(NormBlockId blockId, virtual char* RetrieveSegment(NormBlockId blockId,
NormSegmentId segmentId) NormSegmentId segmentId);
{
return server ? server->GetRetrievalSegment() : NULL;
}
}; // end class NormSimObject }; // end class NormSimObject
#endif // SIMULATE #endif // SIMULATE

View File

@ -20,7 +20,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
tx_socket(ProtoSocket::UDP), rx_socket(ProtoSocket::UDP), tx_socket(ProtoSocket::UDP), rx_socket(ProtoSocket::UDP),
local_node_id(localNodeId), local_node_id(localNodeId),
ttl(DEFAULT_TTL), loopback(false), ttl(DEFAULT_TTL), loopback(false),
tx_rate(DEFAULT_TRANSMIT_RATE/8.0), tx_rate(DEFAULT_TRANSMIT_RATE/8.0), tx_rate_min(-1.0), tx_rate_max(-1.0),
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0), backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0),
ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0), ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0),
next_tx_object_id(0), tx_cache_count_min(8), tx_cache_count_max(256), next_tx_object_id(0), tx_cache_count_min(8), tx_cache_count_max(256),
@ -112,12 +112,6 @@ bool NormSession::Open(const char* interfaceName)
if (address.IsMulticast()) if (address.IsMulticast())
{ {
if (!rx_socket.JoinGroup(address, interfaceName))
{
DMSG(0, "NormSession::Open() rx_socket join group error\n");
Close();
return false;
}
if (!tx_socket.SetTTL(ttl)) if (!tx_socket.SetTTL(ttl))
{ {
DMSG(0, "NormSession::Open() tx_socket set ttl error\n"); DMSG(0, "NormSession::Open() tx_socket set ttl error\n");
@ -132,11 +126,27 @@ bool NormSession::Open(const char* interfaceName)
} }
if (interfaceName) if (interfaceName)
{ {
rx_socket.SetMulticastInterface(interfaceName);
tx_socket.SetMulticastInterface(interfaceName);
strncpy(interface_name, interfaceName, 31); strncpy(interface_name, interfaceName, 31);
interface_name[31] = '\0'; interface_name[31] = '\0';
} }
if ('\0' != interface_name[0])
{
bool result = rx_socket.SetMulticastInterface(interface_name);
result &= tx_socket.SetMulticastInterface(interface_name);
if (!result)
{
DMSG(0, "NormSession::Open() error setting multicast interface\n");
Close();
return false;
}
interfaceName = interface_name;
}
if (!rx_socket.JoinGroup(address, interfaceName))
{
DMSG(0, "NormSession::Open() rx_socket join group error\n");
Close();
return false;
}
} }
for (unsigned int i = 0; i < DEFAULT_MESSAGE_POOL_DEPTH; i++) for (unsigned int i = 0; i < DEFAULT_MESSAGE_POOL_DEPTH; i++)
{ {
@ -179,6 +189,24 @@ void NormSession::Close()
} // end NormSession::Close() } // end NormSession::Close()
bool NormSession::SetMulticastInterface(const char* interfaceName)
{
if (interfaceName)
{
bool result = true;
if (rx_socket.IsOpen())
result &= rx_socket.SetMulticastInterface(interfaceName);
if (tx_socket.IsOpen())
result &= tx_socket.SetMulticastInterface(interfaceName);
return result;
}
else
{
interface_name[0] = '\0';
return true;
}
} // end NormSession::SetMulticastInterface()
void NormSession::SetTxRate(double txRate) void NormSession::SetTxRate(double txRate)
{ {
txRate /= 8.0; // convert to bytes/sec txRate /= 8.0; // convert to bytes/sec
@ -193,7 +221,7 @@ void NormSession::SetTxRate(double txRate)
} }
tx_rate = txRate; tx_rate = txRate;
} }
else if (0.0 == tx_rate) else if ((0.0 == tx_rate) && IsOpen())
{ {
tx_rate = txRate; tx_rate = txRate;
tx_timer.SetInterval(0.0); tx_timer.SetInterval(0.0);
@ -205,6 +233,37 @@ void NormSession::SetTxRate(double txRate)
} }
} // end NormSession::SetTxRate() } // end NormSession::SetTxRate()
void NormSession::SetTxRateBounds(double rateMin, double rateMax)
{
// Make sure min <= max
if ((rateMin >= 0.0) && (rateMax >= 0.0))
{
if (rateMin > rateMax)
{
double temp = rateMin;
rateMin = rateMax;
rateMax = temp;
}
}
if (rateMin < 0.0)
tx_rate_min = -1.0;
else
tx_rate_min = rateMin/8.0; // convert to bytes/second
if (rateMax < 0.0)
tx_rate_max = -1.0;
else
tx_rate_max = rateMax/8.0; // convert to bytes/second
if (cc_enable)
{
if ((tx_rate_min >= 0.0) && (tx_rate < tx_rate_min))
tx_rate = tx_rate_min;
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
tx_rate = tx_rate_max;
SetTxRate(tx_rate*8.0);
}
} // end NormSession::SetTxRateBounds()
bool NormSession::StartServer(UINT32 bufferSpace, bool NormSession::StartServer(UINT32 bufferSpace,
UINT16 segmentSize, UINT16 segmentSize,
UINT16 numData, UINT16 numData,
@ -285,7 +344,15 @@ bool NormSession::StartServer(UINT32 bufferSpace,
//probe_timer.SetInterval(0.0); //probe_timer.SetInterval(0.0);
probe_pending = probe_reset = false; probe_pending = probe_reset = false;
if (cc_enable) tx_rate = segmentSize; if (cc_enable)
{
tx_rate = segmentSize;
if ((tx_rate_min >= 0.0) && (tx_rate < tx_rate_min))
tx_rate = tx_rate_min;
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
tx_rate = tx_rate_max;
}
OnProbeTimeout(probe_timer); OnProbeTimeout(probe_timer);
ActivateTimer(probe_timer); ActivateTimer(probe_timer);
return true; return true;
@ -782,7 +849,7 @@ NormDataObject* NormSession::QueueTxData(const char* dataPtr,
strerror(errno)); strerror(errno));
return NULL; return NULL;
} }
if (!obj->Open((char*)dataPtr, dataLen, infoPtr, infoLen)) if (!obj->Open((char*)dataPtr, dataLen, false, infoPtr, infoLen))
{ {
DMSG(0, "NormSession::QueueTxData() object open error\n"); DMSG(0, "NormSession::QueueTxData() object open error\n");
delete obj; delete obj;
@ -1263,6 +1330,7 @@ void NormSession::ClientHandleObjectMessage(const struct timeval& currentTime,
{ {
if ((theServer = new NormServerNode(*this, msg.GetSourceId()))) if ((theServer = new NormServerNode(*this, msg.GetSourceId())))
{ {
Notify(NormController::REMOTE_SERVER_NEW, theServer, NULL);
if (theServer->Open(msg.GetSessionId())) if (theServer->Open(msg.GetSessionId()))
{ {
server_tree.AttachNode(theServer); server_tree.AttachNode(theServer);
@ -2821,10 +2889,18 @@ void NormSession::AdjustRate(bool onResponse)
}*/ }*/
} }
// Don't let tx_rate below MIN(one segment per grtt, one segment per second)
double minRate = ((double)segment_size) / grtt_measured; double minRate = ((double)segment_size) / grtt_measured;
minRate = MIN((double)segment_size, minRate); minRate = MIN((double)segment_size, minRate);
tx_rate = MAX(tx_rate, minRate); tx_rate = MAX(tx_rate, minRate);
// Keep "tx_rate" within user set rate bounds (if any)
if ((tx_rate_min >= 0.0) && (tx_rate < tx_rate_min))
tx_rate = tx_rate_min;
if ((tx_rate_max >= 0.0) && (tx_rate > tx_rate_max))
tx_rate = tx_rate_max;
struct timeval currentTime; struct timeval currentTime;
::ProtoSystemTime(currentTime); ::ProtoSystemTime(currentTime);
double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec); double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec);

View File

@ -20,11 +20,12 @@ class NormController
TX_OBJECT_PURGED, TX_OBJECT_PURGED,
LOCAL_SERVER_CLOSED, LOCAL_SERVER_CLOSED,
REMOTE_SERVER_NEW, REMOTE_SERVER_NEW,
REMOTE_SERVER_INACTIVE,
REMOTE_SERVER_ACTIVE, REMOTE_SERVER_ACTIVE,
REMOTE_SERVER_INACTIVE,
REMOTE_SERVER_PURGED,
RX_OBJECT_NEW, RX_OBJECT_NEW,
RX_OBJECT_INFO, RX_OBJECT_INFO,
RX_OBJECT_UPDATE, RX_OBJECT_UPDATED,
RX_OBJECT_COMPLETED, RX_OBJECT_COMPLETED,
RX_OBJECT_ABORTED RX_OBJECT_ABORTED
}; };
@ -102,6 +103,7 @@ class NormSession
bool IsOpen() {return (rx_socket.IsOpen() || tx_socket.IsOpen());} bool IsOpen() {return (rx_socket.IsOpen() || tx_socket.IsOpen());}
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 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;
@ -129,6 +131,7 @@ class NormSession
void SetBackoffFactor(double value) {backoff_factor = value;} void SetBackoffFactor(double value) {backoff_factor = value;}
bool CongestionControl() {return cc_enable;} bool CongestionControl() {return cc_enable;}
void SetCongestionControl(bool state) {cc_enable = state;} void SetCongestionControl(bool state) {cc_enable = state;}
void SetTxRateBounds(double rateMin, double rateMax);
void Notify(NormController::Event event, void Notify(NormController::Event event,
class NormServerNode* server, class NormServerNode* server,
@ -249,8 +252,8 @@ class NormSession
bool IsClient() const {return is_client;} bool IsClient() const {return is_client;}
unsigned long RemoteServerBufferSize() const unsigned long RemoteServerBufferSize() const
{return remote_server_buffer_size;} {return remote_server_buffer_size;}
void SetUnicastNacks(bool state) {unicast_nacks = state;} void ClientSetUnicastNacks(bool state) {unicast_nacks = state;}
bool UnicastNacks() const {return unicast_nacks;} bool ClientGetUnicastNacks() const {return unicast_nacks;}
void ClientSetSilent(bool state) {client_silent = state;} void ClientSetSilent(bool state) {client_silent = state;}
bool ClientIsSilent() const {return client_silent;} bool ClientIsSilent() const {return client_silent;}
@ -342,6 +345,8 @@ class NormSession
bool loopback; // to receive own traffic bool loopback; // to receive own traffic
char interface_name[32]; char interface_name[32];
double tx_rate; // bytes per second double tx_rate; // bytes per second
double tx_rate_min;
double tx_rate_max;
double backoff_factor; double backoff_factor;
// Server parameters and state // Server parameters and state

View File

@ -20,7 +20,7 @@ NormSimAgent::NormSimAgent(ProtoTimerMgr& timerMgr,
tx_object_size(0), tx_object_interval(0.0), tx_object_size(0), tx_object_interval(0.0),
tx_object_size_min(0), tx_object_size_max(0), tx_object_size_min(0), tx_object_size_max(0),
tx_repeat_count(0), tx_repeat_interval(0.0), tx_repeat_count(0), tx_repeat_interval(0.0),
stream(NULL), auto_stream(false), push_stream(false), stream(NULL), auto_stream(false), push_mode(false),
flush_mode(NormStreamObject::FLUSH_PASSIVE), flush_mode(NormStreamObject::FLUSH_PASSIVE),
mgen(NULL), msg_sync(false), mgen_bytes(0), mgen_pending_bytes(0), mgen(NULL), msg_sync(false), mgen_bytes(0), mgen_pending_bytes(0),
tracing(false), tx_loss(0.0), rx_loss(0.0) tracing(false), tx_loss(0.0), rx_loss(0.0)
@ -397,6 +397,8 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
DMSG(0, "NormSimAgent::ProcessCommand(sendStream) error opening stream!\n"); DMSG(0, "NormSimAgent::ProcessCommand(sendStream) error opening stream!\n");
return false; return false;
} }
stream->SetFlushMode(flush_mode);
stream->SetPushMode(push_mode);
auto_stream = true; auto_stream = true;
} }
else else
@ -430,6 +432,8 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
DMSG(0, "NormSimAgent::ProcessCommand(openStream) error opening stream!\n"); DMSG(0, "NormSimAgent::ProcessCommand(openStream) error opening stream!\n");
return false; return false;
} }
stream->SetFlushMode(flush_mode);
stream->SetPushMode(push_mode);
auto_stream = false; auto_stream = false;
tx_msg_len = tx_msg_index = 0; tx_msg_len = tx_msg_index = 0;
} }
@ -469,9 +473,9 @@ bool NormSimAgent::ProcessCommand(const char* cmd, const char* val)
else if (!strncmp("push", cmd, len)) else if (!strncmp("push", cmd, len))
{ {
if (!strcmp(val, "on")) if (!strcmp(val, "on"))
push_stream = true; push_mode = true;
else if (!strcmp(val, "off")) else if (!strcmp(val, "off"))
push_stream = false; push_mode = false;
else else
{ {
DMSG(0, "NormSimAgent::ProcessCommand(push) invalid argument!\n"); DMSG(0, "NormSimAgent::ProcessCommand(push) invalid argument!\n");
@ -592,13 +596,12 @@ void NormSimAgent::OnInputReady()
{ {
unsigned int bytesWrote = stream->Write(tx_msg_buffer+tx_msg_index, unsigned int bytesWrote = stream->Write(tx_msg_buffer+tx_msg_index,
tx_msg_len - tx_msg_index, tx_msg_len - tx_msg_index,
NormStreamObject::FLUSH_NONE, false);
false, push_stream);
tx_msg_index += bytesWrote; tx_msg_index += bytesWrote;
if (tx_msg_index == tx_msg_len) if (tx_msg_index == tx_msg_len)
{ {
// Provide EOM indication to norm stream // Mark EOM _and_ flush (using set flush mode)
stream->Write(NULL, 0, flush_mode, true, false); stream->Write(NULL, 0, true);
tx_msg_index = tx_msg_len = 0; tx_msg_index = tx_msg_len = 0;
} }
} }
@ -609,7 +612,7 @@ bool NormSimAgent::FlushStream()
{ {
if (stream && session && session->IsServer()) if (stream && session && session->IsServer())
{ {
stream->Write(NULL, 0, NormStreamObject::FLUSH_ACTIVE, false, false); stream->Flush(true);
return true; return true;
} }
else else
@ -636,9 +639,7 @@ void NormSimAgent::Notify(NormController::Event event,
// sending a dummy byte stream // sending a dummy byte stream
char buffer[NormMsg::MAX_SIZE]; char buffer[NormMsg::MAX_SIZE];
unsigned int count = unsigned int count =
stream->Write(buffer, segment_size, stream->Write(buffer, segment_size, false);
NormStreamObject::FLUSH_NONE,
false, false);
} }
else else
{ {

View File

@ -78,8 +78,8 @@ class NormSimAgent : public NormController
NormStreamObject* stream; NormStreamObject* stream;
bool auto_stream; bool auto_stream;
bool push_stream; bool push_mode;
NormStreamObject::FlushType flush_mode; NormStreamObject::FlushMode flush_mode;
char* tx_msg_buffer; char* tx_msg_buffer;
unsigned int tx_msg_len; unsigned int tx_msg_len;
unsigned int tx_msg_index; unsigned int tx_msg_index;

View File

@ -64,7 +64,7 @@ int main(int argc, char* argv[])
// NORM_FLUSH_PASSIVE automatically flushes full writes to // NORM_FLUSH_PASSIVE automatically flushes full writes to
// the stream. // the stream.
NormStreamSetFlushMode(stream, NORM_FLUSH_PASSIVE); NormStreamSetAutoFlush(stream, NORM_FLUSH_PASSIVE);
// Some variable for stream input/output // Some variable for stream input/output
@ -143,18 +143,11 @@ int main(int argc, char* argv[])
// Assume info contains '/' delimited <path/fileName> string // Assume info contains '/' delimited <path/fileName> string
if (NORM_OBJECT_FILE == NormObjectGetType(theEvent.object)) if (NORM_OBJECT_FILE == NormObjectGetType(theEvent.object))
{ {
NormObjectTransportId id = NormObjectGetTransportId(theEvent.object);
if (0 != (id & 0x01))
{
//NormObjectCancel(theEvent.object);
//break;
}
char fileName[PATH_MAX]; char fileName[PATH_MAX];
strcpy(fileName, cachePath); strcpy(fileName, cachePath);
int pathLen = strlen(fileName); int pathLen = strlen(fileName);
unsigned short nameLen = PATH_MAX - pathLen; unsigned short nameLen = PATH_MAX - pathLen;
NormObjectGetInfo(theEvent.object, fileName+pathLen, &nameLen); nameLen = NormObjectGetInfo(theEvent.object, fileName+pathLen, nameLen);
fileName[nameLen + pathLen] = '\0'; fileName[nameLen + pathLen] = '\0';
char* ptr = fileName + 5; char* ptr = fileName + 5;
while ('\0' != *ptr) while ('\0' != *ptr)
@ -170,7 +163,7 @@ int main(int argc, char* argv[])
} }
break; break;
case NORM_RX_OBJECT_UPDATE: case NORM_RX_OBJECT_UPDATED:
{ {
//TRACE("normTest: NORM_RX_OBJECT_UPDATE event ...\n"); //TRACE("normTest: NORM_RX_OBJECT_UPDATE event ...\n");
if (NORM_OBJECT_STREAM != NormObjectGetType(theEvent.object)) if (NORM_OBJECT_STREAM != NormObjectGetType(theEvent.object))

View File

@ -32,6 +32,6 @@
#ifndef _NORM_VERSION #ifndef _NORM_VERSION
#define _NORM_VERSION #define _NORM_VERSION
#define VERSION "1.2b4" #define VERSION "1.2b5"
#endif // _NORM_VERSION #endif // _NORM_VERSION

Binary file not shown.