v1.1b2
parent
02fcae4cb0
commit
541a4bfa9b
|
|
@ -6,8 +6,10 @@ command-line application can be built which can send and receive
|
||||||
a set of files _or_ a stream piped to/from stdin/stdout. The command-
|
a set of files _or_ a stream piped to/from stdin/stdout. The command-
|
||||||
line options are not yet fully documented.
|
line options are not yet fully documented.
|
||||||
|
|
||||||
The current code only has Makefiles for Unix platforms, but the
|
I do have a PDF file which explains some of the command-line options.
|
||||||
code could be assembled as Win32 project under VC++.
|
Email me for it.
|
||||||
|
|
||||||
|
We're getting there ;-)
|
||||||
|
|
||||||
The NORM code depends upon the current "Protolib" release.
|
The NORM code depends upon the current "Protolib" release.
|
||||||
See <http://pf.itd.nrl.navy.mil> for that code.
|
See <http://pf.itd.nrl.navy.mil> for that code.
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ NormApp::NormApp()
|
||||||
// Init tx_timer for 1.0 second interval, infinite repeats
|
// Init tx_timer for 1.0 second interval, infinite repeats
|
||||||
session_mgr.SetController(this);
|
session_mgr.SetController(this);
|
||||||
|
|
||||||
interval_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormApp::OnIntervalTimeout);
|
interval_timer.SetListener(this, &NormApp::OnIntervalTimeout);
|
||||||
interval_timer.SetInterval(0.0);
|
interval_timer.SetInterval(0.0);
|
||||||
interval_timer.SetRepeat(0);
|
interval_timer.SetRepeat(0);
|
||||||
|
|
||||||
|
|
@ -707,7 +707,9 @@ void NormApp::OnInputReady()
|
||||||
|
|
||||||
if (writeLength || flush)
|
if (writeLength || flush)
|
||||||
{
|
{
|
||||||
unsigned int wroteLength = tx_stream->Write(input_buffer+input_index, writeLength, flush, false, push_stream);
|
unsigned int wroteLength = tx_stream->Write(input_buffer+input_index,
|
||||||
|
writeLength, flush, false,
|
||||||
|
push_stream);
|
||||||
input_length -= wroteLength;
|
input_length -= wroteLength;
|
||||||
if (0 == input_length)
|
if (0 == input_length)
|
||||||
input_index = 0;
|
input_index = 0;
|
||||||
|
|
@ -947,6 +949,7 @@ void NormApp::Notify(NormController::Event event,
|
||||||
findMsgSync = false;
|
findMsgSync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(!((NormStreamObject*)object)->Read(output_buffer+output_index,
|
if(!((NormStreamObject*)object)->Read(output_buffer+output_index,
|
||||||
&readLength, findMsgSync))
|
&readLength, findMsgSync))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,6 @@ void NormEncoder::Encode(const char *data, char **pVec)
|
||||||
|
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
UINT16 vecSize = MIN(SIM_PAYLOAD_MAX, vector_size);
|
UINT16 vecSize = MIN(SIM_PAYLOAD_MAX, vector_size);
|
||||||
vecSize = MAX(vecSize, NormDataMsg::PayloadHeaderLength());
|
|
||||||
#else
|
#else
|
||||||
UINT16 vecSize = vector_size;
|
UINT16 vecSize = vector_size;
|
||||||
#endif // if/else SIMULATE
|
#endif // if/else SIMULATE
|
||||||
|
|
@ -339,7 +338,6 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
||||||
int nvecs = npar + ndata;
|
int nvecs = npar + ndata;
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
int vecSize = MIN(SIM_PAYLOAD_MAX, vector_size);
|
int vecSize = MIN(SIM_PAYLOAD_MAX, vector_size);
|
||||||
vecSize = MAX(NormDataMsg::PayloadHeaderLength(), vecSize);
|
|
||||||
#else
|
#else
|
||||||
int vecSize = vector_size;
|
int vecSize = vector_size;
|
||||||
#endif // if/else SIMUATE
|
#endif // if/else SIMUATE
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include <stdlib.h> // for rand(), etc
|
#include <stdlib.h> // for rand(), etc
|
||||||
|
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
#define SIM_PAYLOAD_MAX 36 // MGEN message size
|
#define SIM_PAYLOAD_MAX (36+8) // MGEN message size + StreamPayloadHeaderLen()
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
|
|
||||||
const UINT8 NORM_PROTOCOL_VERSION = 1;
|
const UINT8 NORM_PROTOCOL_VERSION = 1;
|
||||||
|
|
@ -380,6 +380,7 @@ class NormObjectMsg : public NormMsg
|
||||||
UINT8 GetGroupSize() const {return (buffer[GSIZE_OFFSET] & 0x0f);}
|
UINT8 GetGroupSize() const {return (buffer[GSIZE_OFFSET] & 0x0f);}
|
||||||
bool FlagIsSet(NormObjectMsg::Flag flag) const
|
bool FlagIsSet(NormObjectMsg::Flag flag) const
|
||||||
{return (0 != (flag & buffer[FLAGS_OFFSET]));}
|
{return (0 != (flag & buffer[FLAGS_OFFSET]));}
|
||||||
|
bool IsStream() const {return FlagIsSet(FLAG_STREAM);}
|
||||||
UINT8 GetFecId() const {return buffer[FEC_ID_OFFSET];}
|
UINT8 GetFecId() const {return buffer[FEC_ID_OFFSET];}
|
||||||
NormObjectId GetObjectId() const
|
NormObjectId GetObjectId() const
|
||||||
{
|
{
|
||||||
|
|
@ -546,30 +547,28 @@ class NormDataMsg : public NormObjectMsg
|
||||||
memcpy(buffer+SYMBOL_ID_OFFSET, &symbolId, 2);
|
memcpy(buffer+SYMBOL_ID_OFFSET, &symbolId, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Three ways to set payload content:
|
// Two ways to set payload content:
|
||||||
// 1) Directly access payload to copy segment, then set data message length
|
// 1) Directly access payload to copy segment, then set data message length
|
||||||
// (segment must include "payload_len", "payload_offset", and "payload_data"
|
// (Note NORM_STREAM_OBJECT segments must already include "payload_len"
|
||||||
|
// and "payload_offset" with the "payload_data"
|
||||||
char* AccessPayload() {return (buffer+header_length);}
|
char* AccessPayload() {return (buffer+header_length);}
|
||||||
void SetDataPayloadLength(UINT16 dataLength)
|
// For NORM_STREAM_OBJECT segments, "dataLength" must include the PAYLOAD_HEADER_LENGTH
|
||||||
|
void SetPayloadLength(UINT16 payloadLength)
|
||||||
{
|
{
|
||||||
length = header_length + PAYLOAD_DATA_OFFSET + dataLength;
|
length = header_length + payloadLength;
|
||||||
}
|
}
|
||||||
// 2) Set data segment payload with "offset", "data" ptr, and "len"
|
// Set "payload" directly (useful for FEC parity segments)
|
||||||
void SetDataPayload(const NormObjectSize& offset, char* data, UINT16 len)
|
|
||||||
{
|
|
||||||
WritePayloadLength(AccessPayload(), len);
|
|
||||||
WritePayloadOffset(AccessPayload(), offset);
|
|
||||||
memcpy(buffer+header_length+PAYLOAD_DATA_OFFSET, data, len);
|
|
||||||
length = header_length + PAYLOAD_DATA_OFFSET + len;
|
|
||||||
}
|
|
||||||
// 3) Set "payload" directly (useful for FEC parity segments)
|
|
||||||
void SetPayload(char* payload, UINT16 payloadLength)
|
void SetPayload(char* payload, UINT16 payloadLength)
|
||||||
{
|
{
|
||||||
memcpy(buffer+header_length, payload, payloadLength);
|
memcpy(buffer+header_length, payload, payloadLength);
|
||||||
length = header_length + payloadLength;
|
length = header_length + payloadLength;
|
||||||
}
|
}
|
||||||
// AccessPayloadData() for ZERO padding
|
// AccessPayloadData() (useful for setting ZERO padding)
|
||||||
char* AccessPayloadData() {return (buffer+header_length+PAYLOAD_DATA_OFFSET);}
|
char* AccessPayloadData()
|
||||||
|
{
|
||||||
|
UINT16 payloadIndex = IsStream() ? header_length+PAYLOAD_DATA_OFFSET : header_length;
|
||||||
|
return (buffer+payloadIndex);
|
||||||
|
}
|
||||||
|
|
||||||
// Message processing methods
|
// Message processing methods
|
||||||
NormBlockId GetFecBlockId() const
|
NormBlockId GetFecBlockId() const
|
||||||
|
|
@ -582,36 +581,46 @@ class NormDataMsg : public NormObjectMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT16 GetFecSymbolId() const
|
UINT16 GetFecSymbolId() const
|
||||||
{
|
{return (ntohs(*((UINT16*)(buffer+SYMBOL_ID_OFFSET))));}
|
||||||
return (ntohs(*((UINT16*)(buffer+SYMBOL_ID_OFFSET))));
|
bool IsData() const
|
||||||
}
|
{return (GetFecSymbolId() < GetFecBlockLen());}
|
||||||
bool IsData() const {return (GetFecSymbolId() < GetFecBlockLen());}
|
|
||||||
const char* GetPayloadData() const {return (buffer + header_length + PAYLOAD_DATA_OFFSET);}
|
|
||||||
UINT16 GetPayloadDataLength() const {return (length - (header_length + PAYLOAD_DATA_OFFSET));}
|
|
||||||
|
|
||||||
// Note: "payload" includes "payload_len", "payload_offset", and "payload_data" fields
|
// Note: For NORM_OBJECT_STREAM, "payload" includes "payload_reserved",
|
||||||
|
// "payload_len", "payload_offset", and "payload_data" fields
|
||||||
|
// For NORM_OBJECT_FILE and NORM_OBJECT_DATA, "payload" includes
|
||||||
|
// "payload_data" only
|
||||||
const char* GetPayload() const {return (buffer + header_length);}
|
const char* GetPayload() const {return (buffer + header_length);}
|
||||||
UINT16 GetPayloadLength() const {return (length - header_length);}
|
UINT16 GetPayloadLength() const {return (length - header_length);}
|
||||||
|
|
||||||
|
const char* GetPayloadData() const
|
||||||
|
{
|
||||||
|
UINT16 dataIndex = IsStream() ? header_length+PAYLOAD_DATA_OFFSET : header_length;
|
||||||
|
return (buffer + dataIndex);
|
||||||
|
}
|
||||||
|
UINT16 GetPayloadDataLength() const
|
||||||
|
{
|
||||||
|
UINT16 dataIndex = IsStream() ? header_length+PAYLOAD_DATA_OFFSET : header_length;
|
||||||
|
return (length - dataIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These routines are only applicable to messages containing NORM_OBJECT_STREAM content
|
||||||
// Some static helper routines for reading/writing embedded payload length/offsets
|
// Some static helper routines for reading/writing embedded payload length/offsets
|
||||||
static UINT16 PayloadHeaderLength() {return (PAYLOAD_DATA_OFFSET);}
|
static UINT16 GetStreamPayloadHeaderLength() {return (PAYLOAD_DATA_OFFSET);}
|
||||||
static void WritePayloadLength(char* payload, UINT16 len)
|
static void WriteStreamPayloadLength(char* payload, UINT16 len)
|
||||||
{
|
{
|
||||||
*((UINT16*)(payload+PAYLOAD_LENGTH_OFFSET)) = htons(len);
|
*((UINT16*)(payload+PAYLOAD_LENGTH_OFFSET)) = htons(len);
|
||||||
}
|
}
|
||||||
static void WritePayloadOffset(char* payload, const NormObjectSize& offset)
|
static void WriteStreamPayloadOffset(char* payload, UINT32 offset)
|
||||||
{
|
{
|
||||||
*((UINT16*)(payload+PAYLOAD_OFFSET_OFFSET)) = htons(offset.MSB());
|
*((UINT32*)(payload+PAYLOAD_OFFSET_OFFSET)) = htonl(offset);
|
||||||
*((UINT32*)(payload+PAYLOAD_OFFSET_OFFSET+2)) = htonl(offset.LSB());
|
|
||||||
}
|
}
|
||||||
static UINT16 ReadPayloadLength(const char* payload)
|
static UINT16 ReadStreamPayloadLength(const char* payload)
|
||||||
{
|
{
|
||||||
return (ntohs(*((UINT16*)(payload+PAYLOAD_LENGTH_OFFSET))));
|
return (ntohs(*((UINT16*)(payload+PAYLOAD_LENGTH_OFFSET))));
|
||||||
}
|
}
|
||||||
static NormObjectSize ReadPayloadOffset(const char* payload)
|
static UINT32 ReadStreamPayloadOffset(const char* payload)
|
||||||
{
|
{
|
||||||
return NormObjectSize(ntohs(*((UINT16*)(payload+PAYLOAD_OFFSET_OFFSET))),
|
return ntohl(*((UINT32*)(payload+PAYLOAD_OFFSET_OFFSET)));
|
||||||
ntohl(*((UINT32*)(payload+PAYLOAD_OFFSET_OFFSET+2))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -624,9 +633,10 @@ class NormDataMsg : public NormObjectMsg
|
||||||
};
|
};
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PAYLOAD_LENGTH_OFFSET = 0,
|
PAYLOAD_RESERVED_OFFSET = 0,
|
||||||
|
PAYLOAD_LENGTH_OFFSET = PAYLOAD_RESERVED_OFFSET + 2,
|
||||||
PAYLOAD_OFFSET_OFFSET = PAYLOAD_LENGTH_OFFSET + 2,
|
PAYLOAD_OFFSET_OFFSET = PAYLOAD_LENGTH_OFFSET + 2,
|
||||||
PAYLOAD_DATA_OFFSET = PAYLOAD_OFFSET_OFFSET + 6
|
PAYLOAD_DATA_OFFSET = PAYLOAD_OFFSET_OFFSET + 4
|
||||||
};
|
};
|
||||||
}; // end class NormDataMsg
|
}; // end class NormDataMsg
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,15 +37,15 @@ NormServerNode::NormServerNode(class NormSession* theSession, NormNodeId nodeId)
|
||||||
recv_total(0), recv_goodput(0), resync_count(0),
|
recv_total(0), recv_goodput(0), resync_count(0),
|
||||||
nack_count(0), suppress_count(0), completion_count(0), failure_count(0)
|
nack_count(0), suppress_count(0), completion_count(0), failure_count(0)
|
||||||
{
|
{
|
||||||
repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnRepairTimeout);
|
repair_timer.SetListener(this, &NormServerNode::OnRepairTimeout);
|
||||||
repair_timer.SetInterval(0.0);
|
repair_timer.SetInterval(0.0);
|
||||||
repair_timer.SetRepeat(1);
|
repair_timer.SetRepeat(1);
|
||||||
|
|
||||||
activity_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnActivityTimeout);
|
activity_timer.SetListener(this, &NormServerNode::OnActivityTimeout);
|
||||||
activity_timer.SetInterval(NormSession::DEFAULT_GRTT_ESTIMATE*NORM_ROBUST_FACTOR);
|
activity_timer.SetInterval(NormSession::DEFAULT_GRTT_ESTIMATE*NORM_ROBUST_FACTOR);
|
||||||
activity_timer.SetRepeat(NORM_ROBUST_FACTOR);
|
activity_timer.SetRepeat(NORM_ROBUST_FACTOR);
|
||||||
|
|
||||||
cc_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnCCTimeout);
|
cc_timer.SetListener(this, &NormServerNode::OnCCTimeout);
|
||||||
cc_timer.SetInterval(0.0);
|
cc_timer.SetInterval(0.0);
|
||||||
cc_timer.SetRepeat(1);
|
cc_timer.SetRepeat(1);
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ bool NormServerNode::Open(UINT16 sessionId, UINT16 segmentSize, UINT16 numData,
|
||||||
unsigned long blockSpace = sizeof(NormBlock) +
|
unsigned long blockSpace = sizeof(NormBlock) +
|
||||||
blockSize * sizeof(char*) +
|
blockSize * sizeof(char*) +
|
||||||
2*maskSize +
|
2*maskSize +
|
||||||
numData * (segmentSize + NormDataMsg::PayloadHeaderLength());
|
numData * (segmentSize + NormDataMsg::GetStreamPayloadHeaderLength());
|
||||||
unsigned long bufferSpace = session->RemoteServerBufferSize();
|
unsigned long bufferSpace = session->RemoteServerBufferSize();
|
||||||
unsigned long numBlocks = bufferSpace / blockSpace;
|
unsigned long numBlocks = bufferSpace / blockSpace;
|
||||||
if (bufferSpace > (numBlocks*blockSpace)) numBlocks++;
|
if (bufferSpace > (numBlocks*blockSpace)) numBlocks++;
|
||||||
|
|
@ -118,14 +118,14 @@ bool NormServerNode::Open(UINT16 sessionId, UINT16 segmentSize, UINT16 numData,
|
||||||
// The extra byte of segments is used for marking segments
|
// The extra byte of segments is used for marking segments
|
||||||
// which are "start segments" for messages encapsulated in
|
// which are "start segments" for messages encapsulated in
|
||||||
// a NormStreamObject
|
// a NormStreamObject
|
||||||
if (!segment_pool.Init(numSegments, segmentSize+NormDataMsg::PayloadHeaderLength()+1))
|
if (!segment_pool.Init(numSegments, segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()+1))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() segment_pool init error\n");
|
DMSG(0, "NormServerNode::Open() segment_pool init error\n");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decoder.Init(numParity, segmentSize+NormDataMsg::PayloadHeaderLength()))
|
if (!decoder.Init(numParity, segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::Open() decoder init error: %s\n",
|
DMSG(0, "NormServerNode::Open() decoder init error: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
@ -166,6 +166,7 @@ void NormServerNode::Close()
|
||||||
rx_table.Destroy();
|
rx_table.Destroy();
|
||||||
segment_size = ndata = nparity = 0;
|
segment_size = ndata = nparity = 0;
|
||||||
is_open = false;
|
is_open = false;
|
||||||
|
synchronized = false;
|
||||||
} // end NormServerNode::Close()
|
} // end NormServerNode::Close()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -709,6 +710,8 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
|
|
||||||
if (!IsOpen())
|
if (!IsOpen())
|
||||||
{
|
{
|
||||||
|
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu opening server>%lu ...\n",
|
||||||
|
LocalNodeId(), GetId());
|
||||||
// Currently,, our implementation requires the FEC Object Transmission Information
|
// Currently,, our implementation requires the FEC Object Transmission Information
|
||||||
// to properly allocate resources
|
// to properly allocate resources
|
||||||
NormFtiExtension fti;
|
NormFtiExtension fti;
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,6 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
NormObjectSize numBlocks = numSegments / NormObjectSize(numData);
|
NormObjectSize numBlocks = numSegments / NormObjectSize(numData);
|
||||||
ASSERT(0 == numBlocks.MSB());
|
ASSERT(0 == numBlocks.MSB());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!block_buffer.Init(numBlocks.LSB()))
|
if (!block_buffer.Init(numBlocks.LSB()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormObject::Open() init block_buffer error\n");
|
DMSG(0, "NormObject::Open() init block_buffer error\n");
|
||||||
|
|
@ -212,7 +208,8 @@ bool NormObject::HandleBlockRequest(NormBlockId nextId, NormBlockId lastId)
|
||||||
DMSG(6, "NormObject::HandleBlockRequest() node>%lu blk>%lu -> blk>%lu\n",
|
DMSG(6, "NormObject::HandleBlockRequest() node>%lu blk>%lu -> blk>%lu\n",
|
||||||
LocalNodeId(), (UINT32)nextId, (UINT32)lastId);
|
LocalNodeId(), (UINT32)nextId, (UINT32)lastId);
|
||||||
bool increasedRepair = false;
|
bool increasedRepair = false;
|
||||||
while (nextId <= lastId)
|
lastId++;
|
||||||
|
while (nextId != lastId)
|
||||||
{
|
{
|
||||||
if (!repair_mask.Test(nextId))
|
if (!repair_mask.Test(nextId))
|
||||||
{
|
{
|
||||||
|
|
@ -267,7 +264,8 @@ bool NormObject::TxResetBlocks(NormBlockId nextId, NormBlockId lastId)
|
||||||
{
|
{
|
||||||
bool increasedRepair = false;
|
bool increasedRepair = false;
|
||||||
UINT16 autoParity = session->ServerAutoParity();
|
UINT16 autoParity = session->ServerAutoParity();
|
||||||
while (nextId <= lastId)
|
lastId++;
|
||||||
|
while (nextId != lastId)
|
||||||
{
|
{
|
||||||
if (!pending_mask.Test(nextId))
|
if (!pending_mask.Test(nextId))
|
||||||
{
|
{
|
||||||
|
|
@ -282,8 +280,6 @@ bool NormObject::TxResetBlocks(NormBlockId nextId, NormBlockId lastId)
|
||||||
return increasedRepair;
|
return increasedRepair;
|
||||||
} // end NormObject::TxResetBlocks()
|
} // end NormObject::TxResetBlocks()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool NormObject::ActivateRepairs()
|
bool NormObject::ActivateRepairs()
|
||||||
{
|
{
|
||||||
bool repairsActivated = false;
|
bool repairsActivated = false;
|
||||||
|
|
@ -949,8 +945,8 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
(UINT16)id);
|
(UINT16)id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UINT16 segmentLen = data.GetPayloadDataLength();
|
UINT16 segmentLength = data.GetPayloadDataLength();
|
||||||
if (segmentLen > segment_size)
|
if (segmentLength > segment_size)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"Error! segment too large ...\n", LocalNodeId(), server->GetId(),
|
"Error! segment too large ...\n", LocalNodeId(), server->GetId(),
|
||||||
|
|
@ -958,28 +954,19 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
server->PutFreeSegment(segment);
|
server->PutFreeSegment(segment);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
UINT16 payloadLength = data.GetPayloadLength();
|
||||||
|
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
// For simulations, we just need the payload header (size & offset)
|
// For simulations, we may need to cap the payloadLength
|
||||||
UINT16 simLen = MIN(segmentLen, SIM_PAYLOAD_MAX);
|
payloadMax = MIN(payloadMax, SIM_PAYLOAD_MAX);
|
||||||
memcpy(segment, data.GetPayload(), simLen+NormDataMsg::PayloadHeaderLength());
|
#endif // SIMULATE
|
||||||
simLen = MIN(segment_size, SIM_PAYLOAD_MAX);
|
if (payloadLength < payloadMax)
|
||||||
if (segmentLen < simLen)
|
memset(segment+payloadLength, 0, payloadMax-payloadLength);
|
||||||
memset(segment+segmentLen+NormDataMsg::PayloadHeaderLength(), 0, simLen - segmentLen);
|
memcpy(segment, data.GetPayload(), payloadLength);
|
||||||
if (data.FlagIsSet(NormObjectMsg::FLAG_MSG_START))
|
if (data.FlagIsSet(NormObjectMsg::FLAG_MSG_START))
|
||||||
segment[simLen+NormDataMsg::PayloadHeaderLength()] =
|
segment[payloadMax] = NormObjectMsg::FLAG_MSG_START;
|
||||||
NormObjectMsg::FLAG_MSG_START;
|
|
||||||
else
|
else
|
||||||
segment[simLen+NormDataMsg::PayloadHeaderLength()] = 0;
|
segment[payloadMax] = 0;
|
||||||
#else
|
|
||||||
memcpy(segment, data.GetPayload(), segmentLen+NormDataMsg::PayloadHeaderLength());
|
|
||||||
if (segmentLen < segment_size)
|
|
||||||
memset(segment+segmentLen+NormDataMsg::PayloadHeaderLength(), 0, segment_size - segmentLen);
|
|
||||||
if (data.FlagIsSet(NormObjectMsg::FLAG_MSG_START))
|
|
||||||
segment[segment_size+NormDataMsg::PayloadHeaderLength()] =
|
|
||||||
NormObjectMsg::FLAG_MSG_START;
|
|
||||||
else
|
|
||||||
segment[segment_size+NormDataMsg::PayloadHeaderLength()] = 0;
|
|
||||||
#endif // if/else SIMULATE
|
|
||||||
block->AttachSegment(segmentId, segment);
|
block->AttachSegment(segmentId, segment);
|
||||||
block->UnsetPending(segmentId);
|
block->UnsetPending(segmentId);
|
||||||
// 2) Write segment to object (if it's data)
|
// 2) Write segment to object (if it's data)
|
||||||
|
|
@ -987,7 +974,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
{
|
{
|
||||||
block->DecrementErasureCount();
|
block->DecrementErasureCount();
|
||||||
if (WriteSegment(blockId, segmentId, segment))
|
if (WriteSegment(blockId, segmentId, segment))
|
||||||
server->IncrementRecvGoodput(segmentLen);
|
server->IncrementRecvGoodput(segmentLength);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1019,12 +1006,11 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
// (TBD) Dump the block ...???
|
// (TBD) Dump the block ...???
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
UINT16 simLen = MIN(segment_size, SIM_PAYLOAD_MAX);
|
payloadMax = MIN(payloadMax, SIM_PAYLOAD_MAX);
|
||||||
memset(segment, 0, simLen + NormDataMsg::PayloadHeaderLength()+1);
|
#endif // SIMULATE
|
||||||
#else
|
memset(segment, 0, payloadMax+1);
|
||||||
memset(segment, 0, segment_size+NormDataMsg::PayloadHeaderLength()+1);
|
|
||||||
#endif // !SIMULATE
|
|
||||||
block->SetSegment(nextErasure, segment);
|
block->SetSegment(nextErasure, segment);
|
||||||
}
|
}
|
||||||
nextErasure = block->NextPending(nextErasure+1);
|
nextErasure = block->NextPending(nextErasure+1);
|
||||||
|
|
@ -1041,7 +1027,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
if (WriteSegment(blockId, sid, block->Segment(sid)))
|
if (WriteSegment(blockId, sid, block->Segment(sid)))
|
||||||
{
|
{
|
||||||
// For statistics only (TBD) #ifdef NORM_DEBUG
|
// For statistics only (TBD) #ifdef NORM_DEBUG
|
||||||
server->IncrementRecvGoodput(NormDataMsg::ReadPayloadLength(block->Segment(sid)));
|
server->IncrementRecvGoodput(segmentLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1224,12 +1210,11 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
|
||||||
char* s = session->ServerGetFreeSegment(id, blockId);
|
char* s = session->ServerGetFreeSegment(id, blockId);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
|
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
UINT16 simLen = MIN(segment_size, SIM_PAYLOAD_MAX);
|
payloadMax = MIN(payloadMax, SIM_PAYLOAD_MAX);
|
||||||
memset(s, 0, simLen + NormDataMsg::PayloadHeaderLength()+1);
|
#endif // SIMULATE
|
||||||
#else
|
memset(s, 0, payloadMax+1); // extra byte for msg flags
|
||||||
memset(s, 0, segment_size + NormDataMsg::PayloadHeaderLength()+1);
|
|
||||||
#endif // if/else SIMULATE
|
|
||||||
block->AttachSegment(i, s);
|
block->AttachSegment(i, s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1260,30 +1245,26 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
|
||||||
// Try to read segment
|
// Try to read segment
|
||||||
if (segmentId < numData)
|
if (segmentId < numData)
|
||||||
{
|
{
|
||||||
// Try to read data segment
|
// Try to read data segment (Note "ReadSegment" copies in offset/length info also)
|
||||||
char* buffer = data->AccessPayload();
|
char* buffer = data->AccessPayload();
|
||||||
if (!ReadSegment(blockId, segmentId, buffer))
|
UINT16 payloadLength = ReadSegment(blockId, segmentId, buffer);
|
||||||
|
if (0 == payloadLength)
|
||||||
{
|
{
|
||||||
// (TBD) deal with read error
|
// (TBD) deal with read error
|
||||||
//(for streams, it currently means the stream is non-pending)
|
//(for streams, it currently means the stream is non-pending)
|
||||||
if (!IsStream())
|
if (!IsStream()) DMSG(0, "NormObject::NextServerMsg() ReadSegment() error\n");
|
||||||
DMSG(0, "NormObject::NextServerMsg() ReadSegment() error\n");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UINT16 length = NormDataMsg::ReadPayloadLength(buffer);
|
data->SetPayloadLength(payloadLength);
|
||||||
data->SetDataPayloadLength(length);
|
|
||||||
|
|
||||||
if (IsStream())
|
if (IsStream())
|
||||||
{
|
{
|
||||||
// Look for FLAG_MSG_START
|
// Look for FLAG_MSG_START
|
||||||
|
UINT16 payloadMax = segment_size+NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
UINT16 simLen = MIN(segment_size, SIM_PAYLOAD_MAX);
|
payloadMax = MIN(payloadMax, SIM_PAYLOAD_MAX);
|
||||||
if (buffer[simLen+NormDataMsg::PayloadHeaderLength()])
|
#endif // SIMULATE
|
||||||
data->SetFlag(NormObjectMsg::FLAG_MSG_START);
|
if (buffer[payloadMax]) data->SetFlag(NormObjectMsg::FLAG_MSG_START);
|
||||||
#else
|
|
||||||
if (buffer[segment_size+NormDataMsg::PayloadHeaderLength()])
|
|
||||||
data->SetFlag(NormObjectMsg::FLAG_MSG_START);
|
|
||||||
#endif // if/else SIMULATE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform incremental FEC encoding as needed
|
// Perform incremental FEC encoding as needed
|
||||||
|
|
@ -1292,8 +1273,12 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
|
||||||
{
|
{
|
||||||
// (TBD) for non-stream objects, catch alternate "last block/segment len"
|
// (TBD) for non-stream objects, catch alternate "last block/segment len"
|
||||||
// ZERO pad any "runt" segments before encoding
|
// ZERO pad any "runt" segments before encoding
|
||||||
if (length < segment_size)
|
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
memset(buffer+NormDataMsg::PayloadHeaderLength()+length, 0, segment_size-length);
|
#ifdef SIMULATE
|
||||||
|
payloadMax = MIN(payloadMax, SIM_PAYLOAD_MAX);
|
||||||
|
#endif // SIMULATE
|
||||||
|
if (payloadLength < payloadMax)
|
||||||
|
memset(buffer+payloadLength, 0, payloadMax-payloadLength);
|
||||||
// (TBD) the encode routine could update the block's parity readiness
|
// (TBD) the encode routine could update the block's parity readiness
|
||||||
session->ServerEncode(data->AccessPayload(), block->SegmentList(numData));
|
session->ServerEncode(data->AccessPayload(), block->SegmentList(numData));
|
||||||
block->IncreaseParityReadiness();
|
block->IncreaseParityReadiness();
|
||||||
|
|
@ -1309,7 +1294,9 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
|
||||||
ASSERT(block->ParityReady(numData));
|
ASSERT(block->ParityReady(numData));
|
||||||
char* segment = block->Segment(segmentId);
|
char* segment = block->Segment(segmentId);
|
||||||
ASSERT(segment);
|
ASSERT(segment);
|
||||||
data->SetPayload(segment, segment_size+NormDataMsg::PayloadHeaderLength());
|
UINT16 payloadLength = segment_size;
|
||||||
|
if (IsStream()) payloadLength += NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
|
data->SetPayload(segment, payloadLength);
|
||||||
}
|
}
|
||||||
block->UnsetPending(segmentId);
|
block->UnsetPending(segmentId);
|
||||||
if (block->InRepair())
|
if (block->InRepair())
|
||||||
|
|
@ -1348,6 +1335,7 @@ void NormStreamObject::StreamAdvance()
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
if (!block->IsTransmitPending())
|
if (!block->IsTransmitPending())
|
||||||
{
|
{
|
||||||
|
// ??? (TBD) Should this block be returned to the pool right now???
|
||||||
if (pending_mask.Set(nextBlockId))
|
if (pending_mask.Set(nextBlockId))
|
||||||
stream_next_id++;
|
stream_next_id++;
|
||||||
else
|
else
|
||||||
|
|
@ -1372,11 +1360,15 @@ bool NormObject::CalculateBlockParity(NormBlock* block)
|
||||||
UINT16 numData = GetBlockSize(block->Id());
|
UINT16 numData = GetBlockSize(block->Id());
|
||||||
for (UINT16 i = 0; i < numData; i++)
|
for (UINT16 i = 0; i < numData; i++)
|
||||||
{
|
{
|
||||||
if (ReadSegment(block->Id(), i, buffer))
|
UINT16 payloadLength = ReadSegment(block->Id(), i, buffer);
|
||||||
|
if (0 != payloadLength)
|
||||||
{
|
{
|
||||||
UINT16 length = NormDataMsg::ReadPayloadLength(buffer);
|
UINT16 payloadMax = segment_size+NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
if (length < segment_size)
|
#ifdef SIMULATE
|
||||||
memset(buffer+NormDataMsg::PayloadHeaderLength()+length, 0, segment_size-length);
|
payloadMax = MIN(payloadMax, SIM_PAYLOAD_MAX);
|
||||||
|
#endif // SIMULATE
|
||||||
|
if (payloadLength < payloadMax)
|
||||||
|
memset(buffer+payloadLength, 0, payloadMax-payloadLength);
|
||||||
session->ServerEncode(buffer, block->SegmentList(numData));
|
session->ServerEncode(buffer, block->SegmentList(numData));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1403,12 +1395,11 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
|
||||||
char* s = session->ServerGetFreeSegment(id, blockId);
|
char* s = session->ServerGetFreeSegment(id, blockId);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
|
UINT16 payloadMax = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
UINT16 simLen = MIN(segment_size, SIM_PAYLOAD_MAX);
|
payloadMax = MIN(payloadMax, SIM_PAYLOAD_MAX);
|
||||||
memset(s, 0, simLen + NormDataMsg::PayloadHeaderLength());
|
#endif // SIMULATE
|
||||||
#else
|
memset(s, 0, payloadMax+1); // extra byte for msg flags
|
||||||
memset(s, 0, segment_size + NormDataMsg::PayloadHeaderLength());
|
|
||||||
#endif // if/else SIMULATE
|
|
||||||
block->AttachSegment(i, s);
|
block->AttachSegment(i, s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1511,8 +1502,6 @@ bool NormFileObject::Open(const char* thePath,
|
||||||
file.Close();
|
file.Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
large_block_length = NormObjectSize(large_block_size) * segment_size;
|
|
||||||
small_block_length = NormObjectSize(small_block_size) * segment_size;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1520,6 +1509,8 @@ bool NormFileObject::Open(const char* thePath,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
large_block_length = NormObjectSize(large_block_size) * segment_size;
|
||||||
|
small_block_length = NormObjectSize(small_block_size) * segment_size;
|
||||||
strncpy(path, thePath, PATH_MAX);
|
strncpy(path, thePath, PATH_MAX);
|
||||||
unsigned int len = strlen(thePath);
|
unsigned int len = strlen(thePath);
|
||||||
len = MIN(len, PATH_MAX);
|
len = MIN(len, PATH_MAX);
|
||||||
|
|
@ -1562,23 +1553,36 @@ bool NormFileObject::WriteSegment(NormBlockId blockId,
|
||||||
{
|
{
|
||||||
len = segment_size;
|
len = segment_size;
|
||||||
}
|
}
|
||||||
NormObjectSize segmentOffset = NormDataMsg::ReadPayloadOffset(buffer);
|
// Determine segment offset from blockId::segmentId
|
||||||
|
NormObjectSize segmentOffset;
|
||||||
|
NormObjectSize segmentSize = NormObjectSize(segment_size);
|
||||||
|
if ((UINT32)blockId < large_block_count)
|
||||||
|
{
|
||||||
|
segmentOffset = large_block_length*(UINT32)blockId + segmentSize*segmentId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
segmentOffset = large_block_length*large_block_count; // (TBD) pre-calc this
|
||||||
|
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
|
||||||
|
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
||||||
|
segmentSize*segmentId;
|
||||||
|
}
|
||||||
off_t offsetScaleMSB = 0xffffffff + 1;
|
off_t offsetScaleMSB = 0xffffffff + 1;
|
||||||
off_t offset = (off_t)segmentOffset.LSB() + ((off_t)segmentOffset.MSB() * offsetScaleMSB);
|
off_t offset = (off_t)segmentOffset.LSB() + ((off_t)segmentOffset.MSB() * offsetScaleMSB);
|
||||||
if (offset != file.GetOffset())
|
if (offset != file.GetOffset())
|
||||||
{
|
{
|
||||||
if (!file.Seek(offset)) return false;
|
if (!file.Seek(offset)) return false;
|
||||||
}
|
}
|
||||||
UINT16 nbytes = file.Write(buffer+NormDataMsg::PayloadHeaderLength(), len);
|
UINT16 nbytes = file.Write(buffer, len);
|
||||||
return (nbytes == len);
|
return (nbytes == len);
|
||||||
} // end NormFileObject::WriteSegment()
|
} // end NormFileObject::WriteSegment()
|
||||||
|
|
||||||
|
|
||||||
bool NormFileObject::ReadSegment(NormBlockId blockId,
|
UINT16 NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer)
|
char* buffer)
|
||||||
{
|
{
|
||||||
// Determine segment length
|
// Determine segment length from blockId::segmentId
|
||||||
UINT16 len;
|
UINT16 len;
|
||||||
if (blockId == final_block_id)
|
if (blockId == final_block_id)
|
||||||
{
|
{
|
||||||
|
|
@ -1591,6 +1595,8 @@ bool NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
{
|
{
|
||||||
len = segment_size;
|
len = segment_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Determine segment offset from blockId::segmentId
|
// Determine segment offset from blockId::segmentId
|
||||||
NormObjectSize segmentOffset;
|
NormObjectSize segmentOffset;
|
||||||
NormObjectSize segmentSize = NormObjectSize(segment_size);
|
NormObjectSize segmentSize = NormObjectSize(segment_size);
|
||||||
|
|
@ -1600,13 +1606,11 @@ bool NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
segmentOffset = large_block_length*large_block_count;
|
segmentOffset = large_block_length*large_block_count; // (TBD) pre-calc this
|
||||||
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
|
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
|
||||||
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
||||||
segmentSize *segmentId;
|
segmentSize*segmentId;
|
||||||
}
|
}
|
||||||
NormDataMsg::WritePayloadLength(buffer, len);
|
|
||||||
NormDataMsg::WritePayloadOffset(buffer, segmentOffset);
|
|
||||||
off_t offsetScaleMSB = 0xffffffff + 1;
|
off_t offsetScaleMSB = 0xffffffff + 1;
|
||||||
off_t offset = (off_t)segmentOffset.LSB() + ((off_t)segmentOffset.MSB() * offsetScaleMSB);
|
off_t offset = (off_t)segmentOffset.LSB() + ((off_t)segmentOffset.MSB() * offsetScaleMSB);
|
||||||
if (offset != file.GetOffset())
|
if (offset != file.GetOffset())
|
||||||
|
|
@ -1614,8 +1618,8 @@ bool NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
if (!file.Seek(offset))
|
if (!file.Seek(offset))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UINT16 nbytes = file.Read(buffer+NormDataMsg::PayloadHeaderLength(), len);
|
UINT16 nbytes = file.Read(buffer, len);
|
||||||
return (len == nbytes);
|
return (len == nbytes) ? len : 0;
|
||||||
} // end NormFileObject::ReadSegment()
|
} // end NormFileObject::ReadSegment()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1673,7 +1677,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!segment_pool.Init(numSegments, segmentSize+NormDataMsg::PayloadHeaderLength()+1))
|
if (!segment_pool.Init(numSegments, segmentSize+NormDataMsg::GetStreamPayloadHeaderLength()+1))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Open() segment_pool init error\n");
|
DMSG(0, "NormStreamObject::Open() segment_pool init error\n");
|
||||||
Close();
|
Close();
|
||||||
|
|
@ -1690,7 +1694,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
|
||||||
// since our objects are exclusively read _or_ write
|
// since our objects are exclusively read _or_ write
|
||||||
write_index.block = write_index.segment = 0;
|
write_index.block = write_index.segment = 0;
|
||||||
read_index.block = read_index.segment = 0;
|
read_index.block = read_index.segment = 0;
|
||||||
write_offset = read_offset = NormObjectSize((UINT32)0);
|
write_offset = read_offset = 0;
|
||||||
if (!server)
|
if (!server)
|
||||||
{
|
{
|
||||||
if (!NormObject::Open(NormObjectSize((UINT32)bufferSize), infoPtr, infoLen))
|
if (!NormObject::Open(NormObjectSize((UINT32)bufferSize), infoPtr, infoLen))
|
||||||
|
|
@ -1721,7 +1725,7 @@ bool NormStreamObject::Accept(unsigned long bufferSize)
|
||||||
void NormStreamObject::Close()
|
void NormStreamObject::Close()
|
||||||
{
|
{
|
||||||
NormObject::Close();
|
NormObject::Close();
|
||||||
write_offset = read_offset = NormObjectSize((UINT32)0);
|
write_offset = read_offset = 0;
|
||||||
NormBlock* b;
|
NormBlock* b;
|
||||||
while ((b = stream_buffer.Find(stream_buffer.RangeLo())))
|
while ((b = stream_buffer.Find(stream_buffer.RangeLo())))
|
||||||
{
|
{
|
||||||
|
|
@ -1844,9 +1848,9 @@ bool NormStreamObject::StreamUpdateStatus(NormBlockId blockId)
|
||||||
} // end NormStreamObject::StreamUpdateStatus()
|
} // end NormStreamObject::StreamUpdateStatus()
|
||||||
|
|
||||||
|
|
||||||
bool NormStreamObject::ReadSegment(NormBlockId blockId,
|
UINT16 NormStreamObject::ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer)
|
char* buffer)
|
||||||
{
|
{
|
||||||
// (TBD) compare blockId with stream_buffer.RangeLo() and stream_buffer.RangeHi()
|
// (TBD) compare blockId with stream_buffer.RangeLo() and stream_buffer.RangeHi()
|
||||||
NormBlock* block = stream_buffer.Find(blockId);
|
NormBlock* block = stream_buffer.Find(blockId);
|
||||||
|
|
@ -1864,19 +1868,19 @@ bool NormStreamObject::ReadSegment(NormBlockId blockId,
|
||||||
block->UnsetPending(segmentId);
|
block->UnsetPending(segmentId);
|
||||||
char* segment = block->Segment(segmentId);
|
char* segment = block->Segment(segmentId);
|
||||||
ASSERT(segment != NULL);
|
ASSERT(segment != NULL);
|
||||||
UINT16 length = NormDataMsg::ReadPayloadLength(segment);
|
UINT16 segmentLength = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||||
ASSERT(length <= segment_size);
|
ASSERT(segmentLength <= segment_size);
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
length = MIN(length, SIM_PAYLOAD_MAX);
|
UINT16 simLen = segmentLength + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
UINT16 simLen = MIN(SIM_PAYLOAD_MAX, segment_size);
|
simLen = MIN(simLen, SIM_PAYLOAD_MAX);
|
||||||
buffer[simLen+NormDataMsg::PayloadHeaderLength()] =
|
buffer[simLen] = segment[simLen];
|
||||||
segment[simLen+NormDataMsg::PayloadHeaderLength()];
|
|
||||||
#else
|
#else
|
||||||
buffer[segment_size+NormDataMsg::PayloadHeaderLength()] =
|
buffer[segment_size+NormDataMsg::GetStreamPayloadHeaderLength()] =
|
||||||
segment[segment_size+NormDataMsg::PayloadHeaderLength()];
|
segment[segment_size+NormDataMsg::GetStreamPayloadHeaderLength()];
|
||||||
#endif // if/else SIMULATE
|
#endif // if/else SIMULATE
|
||||||
memcpy(buffer, segment, length+NormDataMsg::PayloadHeaderLength());
|
UINT16 payloadLength = segmentLength+NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
return true;
|
memcpy(buffer, segment, payloadLength);
|
||||||
|
return payloadLength;
|
||||||
} // end NormStreamObject::ReadSegment()
|
} // end NormStreamObject::ReadSegment()
|
||||||
|
|
||||||
bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
|
|
@ -1891,11 +1895,13 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
return false;
|
return false;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
UINT32 segmentOffset = NormDataMsg::ReadStreamPayloadOffset(segment);
|
||||||
NormObjectSize segmentOffset = NormDataMsg::ReadPayloadOffset(segment);
|
// if (segmentOffset < read_offset)
|
||||||
if (read_offset > segmentOffset)
|
UINT32 diff = segmentOffset - read_offset;
|
||||||
|
if ((diff > 0x80000000) || ((0x80000000 == diff) && (segmentOffset > read_offset)))
|
||||||
{
|
{
|
||||||
//DMSG(0, "NormStreamObject::WriteSegment() segmentOffset < read_offset!?\n");
|
DMSG(0, "NormStreamObject::WriteSegment() diff:%lu segmentOffset:%lu < read_offset:%lu \n",
|
||||||
|
diff, segmentOffset, read_offset);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1916,7 +1922,7 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
read_index.block = block->Id();
|
read_index.block = block->Id();
|
||||||
read_index.segment = block->FirstPending();
|
read_index.segment = block->FirstPending();
|
||||||
NormBlock* tempBlock = block;
|
NormBlock* tempBlock = block;
|
||||||
NormObjectSize tempOffset = read_offset;
|
UINT32 tempOffset = read_offset;
|
||||||
session->Notify(NormController::RX_OBJECT_UPDATE, server, this);
|
session->Notify(NormController::RX_OBJECT_UPDATE, server, this);
|
||||||
block = stream_buffer.Find(stream_buffer.RangeLo());
|
block = stream_buffer.Find(stream_buffer.RangeLo());
|
||||||
if (tempBlock == block)
|
if (tempBlock == block)
|
||||||
|
|
@ -1968,17 +1974,14 @@ bool NormStreamObject::WriteSegment(NormBlockId blockId,
|
||||||
{
|
{
|
||||||
char* s = segment_pool.Get();
|
char* s = segment_pool.Get();
|
||||||
ASSERT(s != NULL); // for now, this should always succeed
|
ASSERT(s != NULL); // for now, this should always succeed
|
||||||
UINT16 length = NormDataMsg::ReadPayloadLength(segment);
|
UINT16 segmentLength = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||||
|
UINT16 flagsOffset = segment_size + NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
length = MIN(length, SIM_PAYLOAD_MAX);
|
flagsOffset = MIN(SIM_PAYLOAD_MAX, flagsOffset);
|
||||||
UINT16 simLen = MIN(segment_size, SIM_PAYLOAD_MAX);
|
segmentLength = MIN((SIM_PAYLOAD_MAX-NormDataMsg::GetStreamPayloadHeaderLength()), segmentLength);
|
||||||
s[simLen+NormDataMsg::PayloadHeaderLength()] =
|
|
||||||
segment[simLen+NormDataMsg::PayloadHeaderLength()];
|
|
||||||
#else
|
|
||||||
s[segment_size+NormDataMsg::PayloadHeaderLength()] =
|
|
||||||
segment[segment_size+NormDataMsg::PayloadHeaderLength()];
|
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
memcpy(s, segment, length + NormDataMsg::PayloadHeaderLength());
|
s[flagsOffset] = segment[flagsOffset];
|
||||||
|
memcpy(s, segment, segmentLength + NormDataMsg::GetStreamPayloadHeaderLength());
|
||||||
block->AttachSegment(segmentId, s);
|
block->AttachSegment(segmentId, s);
|
||||||
block->SetPending(segmentId);
|
block->SetPending(segmentId);
|
||||||
ASSERT(block->Segment(segmentId) == s);
|
ASSERT(block->Segment(segmentId) == s);
|
||||||
|
|
@ -2035,26 +2038,25 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStar
|
||||||
char* segment = block->Segment(read_index.segment);
|
char* segment = block->Segment(read_index.segment);
|
||||||
if (!segment)
|
if (!segment)
|
||||||
{
|
{
|
||||||
//DMSG(0, "NormStreamObject::Read() stream buffer empty (2)\n");
|
//DMSG(0, "NormStreamObject::Read(%lu:%hu) stream buffer empty (2)\n",
|
||||||
|
// (UINT32)read_index.block, read_index.segment);
|
||||||
*buflen = bytesRead;
|
*buflen = bytesRead;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NormObjectSize segmentOffset = NormDataMsg::ReadPayloadOffset(segment);
|
UINT32 segmentOffset = NormDataMsg::ReadStreamPayloadOffset(segment);
|
||||||
if (segmentOffset > read_offset)
|
// if (read_offset < segmentOffset)
|
||||||
|
UINT32 diff = read_offset - segmentOffset;
|
||||||
|
if ((diff > 0x80000000) || ((0x80000000 == diff) && (read_offset > segmentOffset)))
|
||||||
{
|
{
|
||||||
DMSG(4, "NormStreamObject::Read() node>%lu broken stream!\n", LocalNodeId());
|
DMSG(0, "NormStreamObject::Read() node>%lu broken stream!\n", LocalNodeId());
|
||||||
read_offset = segmentOffset;
|
read_offset = segmentOffset;
|
||||||
*buflen = bytesRead;
|
*buflen = bytesRead;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NormObjectSize delta = read_offset - segmentOffset;
|
UINT32 index = read_offset - segmentOffset;
|
||||||
|
UINT16 length = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||||
ASSERT(!delta.MSB());
|
|
||||||
UINT16 index = delta.LSB();
|
|
||||||
UINT16 length = NormDataMsg::ReadPayloadLength(segment);
|
|
||||||
|
|
||||||
if (index >= length)
|
if (index >= length)
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Read() node>%lu mangled stream! index:%hu length:%hu\n",
|
DMSG(0, "NormStreamObject::Read() node>%lu mangled stream! index:%hu length:%hu\n",
|
||||||
|
|
@ -2077,14 +2079,11 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStar
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
UINT16 flagsOffset = segment_size+NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
UINT16 simLen = MIN(segment_size, SIM_PAYLOAD_MAX);
|
flagsOffset = MIN(flagsOffset, SIM_PAYLOAD_MAX);
|
||||||
msgStart = (NormObjectMsg::FLAG_MSG_START ==
|
|
||||||
segment[simLen+NormDataMsg::PayloadHeaderLength()]);
|
|
||||||
#else
|
|
||||||
msgStart = (NormObjectMsg::FLAG_MSG_START ==
|
|
||||||
segment[segment_size+NormDataMsg::PayloadHeaderLength()]);
|
|
||||||
#endif // if/else SIMULATE
|
#endif // if/else SIMULATE
|
||||||
|
msgStart = (NormObjectMsg::FLAG_MSG_START == segment[flagsOffset]);
|
||||||
}
|
}
|
||||||
if (!msgStart)
|
if (!msgStart)
|
||||||
{
|
{
|
||||||
|
|
@ -2107,9 +2106,9 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStar
|
||||||
UINT16 simCount = ((index+count) < SIM_PAYLOAD_MAX) ?
|
UINT16 simCount = ((index+count) < SIM_PAYLOAD_MAX) ?
|
||||||
count : ((index < SIM_PAYLOAD_MAX) ?
|
count : ((index < SIM_PAYLOAD_MAX) ?
|
||||||
(SIM_PAYLOAD_MAX - index) : 0);
|
(SIM_PAYLOAD_MAX - index) : 0);
|
||||||
memcpy(buffer+bytesRead, segment+index+NormDataMsg::PayloadHeaderLength(), simCount);
|
memcpy(buffer+bytesRead, segment+index+NormDataMsg::GetStreamPayloadHeaderLength(), simCount);
|
||||||
#else
|
#else
|
||||||
memcpy(buffer+bytesRead, segment+index+NormDataMsg::PayloadHeaderLength(), count);
|
memcpy(buffer+bytesRead, segment+index+NormDataMsg::GetStreamPayloadHeaderLength(), count);
|
||||||
#endif // if/else SIMULATE
|
#endif // if/else SIMULATE
|
||||||
index += count;
|
index += count;
|
||||||
bytesRead += count;
|
bytesRead += count;
|
||||||
|
|
@ -2134,10 +2133,11 @@ bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStar
|
||||||
return true;
|
return true;
|
||||||
} // end NormStreamObject::Read()
|
} // end NormStreamObject::Read()
|
||||||
|
|
||||||
unsigned long NormStreamObject::Write(const char* buffer, unsigned long len, bool flush, bool eom, bool push)
|
unsigned long NormStreamObject::Write(const char* buffer, unsigned long len,
|
||||||
|
bool flush, bool eom, bool push)
|
||||||
{
|
{
|
||||||
unsigned long nBytes = 0;
|
unsigned long nBytes = 0;
|
||||||
while (nBytes < len)
|
do
|
||||||
{
|
{
|
||||||
NormBlock* block = stream_buffer.Find(write_index.block);
|
NormBlock* block = stream_buffer.Find(write_index.block);
|
||||||
if (!block)
|
if (!block)
|
||||||
|
|
@ -2201,32 +2201,31 @@ unsigned long NormStreamObject::Write(const char* buffer, unsigned long len, boo
|
||||||
segment = segment_pool.Get();
|
segment = segment_pool.Get();
|
||||||
ASSERT(segment);
|
ASSERT(segment);
|
||||||
}
|
}
|
||||||
NormDataMsg::WritePayloadOffset(segment, write_offset);
|
NormDataMsg::WriteStreamPayloadOffset(segment, write_offset);
|
||||||
NormDataMsg::WritePayloadLength(segment, 0);
|
NormDataMsg::WriteStreamPayloadLength(segment, 0);
|
||||||
block->AttachSegment(write_index.segment, segment);
|
block->AttachSegment(write_index.segment, segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT16 index = NormDataMsg::ReadPayloadLength(segment);
|
UINT16 index = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||||
|
|
||||||
if (0 == index)
|
if (0 == index)
|
||||||
{
|
{
|
||||||
// On first write to segment, mark MSG_START flag as appropriate
|
char msgStartValue = 0;
|
||||||
char msgStartValue;
|
if (msg_start && len)
|
||||||
if (msg_start)
|
|
||||||
{
|
{
|
||||||
msg_start = false;
|
ASSERT(0 == index);
|
||||||
msgStartValue = NormObjectMsg::FLAG_MSG_START;
|
msgStartValue = NormObjectMsg::FLAG_MSG_START;
|
||||||
|
msg_start = false;
|
||||||
}
|
}
|
||||||
else
|
UINT16 flagsOffset = segment_size+NormDataMsg::GetStreamPayloadHeaderLength();
|
||||||
{
|
|
||||||
msgStartValue = 0;
|
|
||||||
}
|
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
UINT16 simLen = MIN(SIM_PAYLOAD_MAX, segment_size);
|
flagsOffset = MIN(SIM_PAYLOAD_MAX, flagsOffset);
|
||||||
segment[simLen+NormDataMsg::PayloadHeaderLength()] = msgStartValue;
|
#endif // SIMULATE
|
||||||
#else
|
segment[flagsOffset] = msgStartValue;
|
||||||
segment[segment_size+NormDataMsg::PayloadHeaderLength()] = msgStartValue;
|
}
|
||||||
#endif // if/else SIMULATE
|
else
|
||||||
|
{
|
||||||
|
msg_start = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT16 count = (UINT16)(len - nBytes);
|
UINT16 count = (UINT16)(len - nBytes);
|
||||||
|
|
@ -2236,17 +2235,16 @@ unsigned long NormStreamObject::Write(const char* buffer, unsigned long len, boo
|
||||||
UINT16 simCount = ((index+count) < SIM_PAYLOAD_MAX) ?
|
UINT16 simCount = ((index+count) < SIM_PAYLOAD_MAX) ?
|
||||||
count : ((index < SIM_PAYLOAD_MAX) ?
|
count : ((index < SIM_PAYLOAD_MAX) ?
|
||||||
(SIM_PAYLOAD_MAX - index) : 0);
|
(SIM_PAYLOAD_MAX - index) : 0);
|
||||||
memcpy(segment+index+NormDataMsg::PayloadHeaderLength(), buffer+nBytes, simCount);
|
memcpy(segment+index+NormDataMsg::GetStreamPayloadHeaderLength(), buffer+nBytes, simCount);
|
||||||
#else
|
#else
|
||||||
memcpy(segment+index+NormDataMsg::PayloadHeaderLength(), buffer+nBytes, count);
|
memcpy(segment+index+NormDataMsg::GetStreamPayloadHeaderLength(), buffer+nBytes, count);
|
||||||
#endif // if/else SIMULATE
|
#endif // if/else SIMULATE
|
||||||
NormDataMsg::WritePayloadLength(segment, index+count);
|
NormDataMsg::WriteStreamPayloadLength(segment, index+count);
|
||||||
nBytes += count;
|
nBytes += count;
|
||||||
write_offset += count;
|
write_offset += count;
|
||||||
// Is the segment full? or flushing, or end-of-message
|
// Is the segment full? or flushing
|
||||||
if ((count == space) || ((flush || eom) && (index > 0)))
|
if ((count == space) || ((flush || eom) && (index > 0) && (nBytes == len)))
|
||||||
{
|
{
|
||||||
if (eom) ASSERT(0);
|
|
||||||
block->SetPending(write_index.segment);
|
block->SetPending(write_index.segment);
|
||||||
if (++write_index.segment >= ndata)
|
if (++write_index.segment >= ndata)
|
||||||
{
|
{
|
||||||
|
|
@ -2254,13 +2252,13 @@ unsigned long NormStreamObject::Write(const char* buffer, unsigned long len, boo
|
||||||
write_index.segment = 0;
|
write_index.segment = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (nBytes < len);
|
||||||
|
|
||||||
// if this was end-of-message next Write() will be considered a new message
|
// if this was end-of-message next Write() will be considered a new message
|
||||||
|
|
||||||
if (nBytes == len)
|
if (nBytes == len)
|
||||||
{
|
{
|
||||||
if (eom) msg_start = true;
|
if (eom)
|
||||||
|
msg_start = true;
|
||||||
if (flush)
|
if (flush)
|
||||||
flush_pending = true;
|
flush_pending = true;
|
||||||
else
|
else
|
||||||
|
|
@ -2293,20 +2291,24 @@ NormSimObject::~NormSimObject()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NormSimObject::ReadSegment(NormBlockId blockId,
|
UINT16 NormSimObject::ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer)
|
char* buffer)
|
||||||
{
|
{
|
||||||
// Determine segment length
|
// Determine segment length
|
||||||
UINT16 len;
|
UINT16 len;
|
||||||
if ((blockId == last_block_id) &&
|
if (blockId == final_block_id)
|
||||||
(segmentId == (last_block_size - 1)))
|
{
|
||||||
len = last_segment_size;
|
if (segmentId == (GetBlockSize(blockId)-1))
|
||||||
|
len = final_segment_size;
|
||||||
|
else
|
||||||
|
len = segment_size;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
len = segment_size;
|
len = segment_size;
|
||||||
// the "len" is needed to build the correct size message
|
}
|
||||||
NormDataMsg::WritePayloadLength(buffer, len);
|
return len;
|
||||||
return true;
|
|
||||||
} // end NormSimObject::ReadSegment()
|
} // end NormSimObject::ReadSegment()
|
||||||
|
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,9 @@ class NormObject
|
||||||
virtual bool WriteSegment(NormBlockId blockId,
|
virtual bool WriteSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
const char* buffer) = 0;
|
const char* buffer) = 0;
|
||||||
virtual bool ReadSegment(NormBlockId blockId,
|
virtual UINT16 ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer) = 0;
|
char* buffer) = 0;
|
||||||
|
|
||||||
// These are only valid after object is open
|
// These are only valid after object is open
|
||||||
NormBlockId GetFinalBlockId() const {return final_block_id;}
|
NormBlockId GetFinalBlockId() const {return final_block_id;}
|
||||||
|
|
@ -197,9 +197,9 @@ class NormFileObject : public NormObject
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
const char* buffer);
|
const char* buffer);
|
||||||
|
|
||||||
virtual bool ReadSegment(NormBlockId blockId,
|
virtual UINT16 ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer);
|
char* buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
@ -231,9 +231,9 @@ class NormStreamObject : public NormObject
|
||||||
virtual bool WriteSegment(NormBlockId blockId,
|
virtual bool WriteSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
const char* buffer);
|
const char* buffer);
|
||||||
virtual bool ReadSegment(NormBlockId blockId,
|
virtual UINT16 ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer);
|
char* buffer);
|
||||||
|
|
||||||
bool Read(char* buffer, unsigned int* buflen, bool findMsgStart = false);
|
bool Read(char* buffer, unsigned int* buflen, bool findMsgStart = false);
|
||||||
unsigned long Write(const char* buffer, unsigned long len, bool flush, bool eom, bool push);
|
unsigned long Write(const char* buffer, unsigned long len, bool flush, bool eom, bool push);
|
||||||
|
|
@ -271,9 +271,9 @@ class NormStreamObject : public NormObject
|
||||||
NormSegmentPool segment_pool;
|
NormSegmentPool segment_pool;
|
||||||
NormBlockBuffer stream_buffer;
|
NormBlockBuffer stream_buffer;
|
||||||
Index write_index;
|
Index write_index;
|
||||||
NormObjectSize write_offset;
|
UINT32 write_offset;
|
||||||
Index read_index;
|
Index read_index;
|
||||||
NormObjectSize read_offset;
|
UINT32 read_offset;
|
||||||
bool flush_pending;
|
bool flush_pending;
|
||||||
bool msg_start;
|
bool msg_start;
|
||||||
}; // end class NormStreamObject
|
}; // end class NormStreamObject
|
||||||
|
|
@ -302,9 +302,9 @@ class NormSimObject : public NormObject
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
const char* buffer) {return true;}
|
const char* buffer) {return true;}
|
||||||
|
|
||||||
virtual bool ReadSegment(NormBlockId blockId,
|
virtual UINT16 ReadSegment(NormBlockId blockId,
|
||||||
NormSegmentId segmentId,
|
NormSegmentId segmentId,
|
||||||
char* buffer);
|
char* buffer);
|
||||||
}; // end class NormSimObject
|
}; // end class NormSimObject
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
flush_count(NORM_ROBUST_FACTOR+1),
|
flush_count(NORM_ROBUST_FACTOR+1),
|
||||||
posted_tx_queue_empty(false), advertise_repairs(false),
|
posted_tx_queue_empty(false), advertise_repairs(false),
|
||||||
suppress_nonconfirmed(false), suppress_rate(-1.0), suppress_rtt(-1.0),
|
suppress_nonconfirmed(false), suppress_rate(-1.0), suppress_rtt(-1.0),
|
||||||
probe_proactive(true), grtt_interval(0.5),
|
probe_proactive(true), probe_pending(false), probe_reset(false),
|
||||||
|
grtt_interval(0.5),
|
||||||
grtt_interval_min(DEFAULT_GRTT_INTERVAL_MIN),
|
grtt_interval_min(DEFAULT_GRTT_INTERVAL_MIN),
|
||||||
grtt_interval_max(DEFAULT_GRTT_INTERVAL_MAX),
|
grtt_interval_max(DEFAULT_GRTT_INTERVAL_MAX),
|
||||||
grtt_max(DEFAULT_GRTT_MAX),
|
grtt_max(DEFAULT_GRTT_MAX),
|
||||||
|
|
@ -38,24 +39,24 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
next(NULL)
|
next(NULL)
|
||||||
{
|
{
|
||||||
tx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
tx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
||||||
tx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::TxSocketRecvHandler);
|
tx_socket.SetListener(this, &NormSession::TxSocketRecvHandler);
|
||||||
|
|
||||||
rx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
rx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
||||||
rx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::RxSocketRecvHandler);
|
rx_socket.SetListener(this, &NormSession::RxSocketRecvHandler);
|
||||||
|
|
||||||
tx_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnTxTimeout);
|
tx_timer.SetListener(this, &NormSession::OnTxTimeout);
|
||||||
tx_timer.SetInterval(0.0);
|
tx_timer.SetInterval(0.0);
|
||||||
tx_timer.SetRepeat(-1);
|
tx_timer.SetRepeat(-1);
|
||||||
|
|
||||||
repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnRepairTimeout);
|
repair_timer.SetListener(this, &NormSession::OnRepairTimeout);
|
||||||
repair_timer.SetInterval(0.0);
|
repair_timer.SetInterval(0.0);
|
||||||
repair_timer.SetRepeat(1);
|
repair_timer.SetRepeat(1);
|
||||||
|
|
||||||
flush_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnFlushTimeout);
|
flush_timer.SetListener(this, &NormSession::OnFlushTimeout);
|
||||||
flush_timer.SetInterval(0.0);
|
flush_timer.SetInterval(0.0);
|
||||||
flush_timer.SetRepeat(0);
|
flush_timer.SetRepeat(0);
|
||||||
|
|
||||||
probe_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnProbeTimeout);
|
probe_timer.SetListener(this, &NormSession::OnProbeTimeout);
|
||||||
probe_timer.SetInterval(0.0);
|
probe_timer.SetInterval(0.0);
|
||||||
probe_timer.SetRepeat(-1);
|
probe_timer.SetRepeat(-1);
|
||||||
|
|
||||||
|
|
@ -70,7 +71,7 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
// This timer is for printing out occasional status reports
|
// This timer is for printing out occasional status reports
|
||||||
// (It may be used to trigger transmission of report messages
|
// (It may be used to trigger transmission of report messages
|
||||||
// in the future for debugging, etc
|
// in the future for debugging, etc
|
||||||
report_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&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);
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +190,7 @@ bool NormSession::StartServer(unsigned long bufferSpace,
|
||||||
unsigned long blockSpace = sizeof(NormBlock) +
|
unsigned long blockSpace = sizeof(NormBlock) +
|
||||||
blockSize * sizeof(char*) +
|
blockSize * sizeof(char*) +
|
||||||
2*maskSize +
|
2*maskSize +
|
||||||
numParity * (segmentSize + NormDataMsg::PayloadHeaderLength());
|
numParity * (segmentSize + NormDataMsg::GetStreamPayloadHeaderLength());
|
||||||
|
|
||||||
unsigned long numBlocks = bufferSpace / blockSpace;
|
unsigned long numBlocks = bufferSpace / blockSpace;
|
||||||
if (bufferSpace > (numBlocks*blockSpace)) numBlocks++;
|
if (bufferSpace > (numBlocks*blockSpace)) numBlocks++;
|
||||||
|
|
@ -204,7 +205,7 @@ bool NormSession::StartServer(unsigned long bufferSpace,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!segment_pool.Init(numSegments, segmentSize + NormDataMsg::PayloadHeaderLength()))
|
if (!segment_pool.Init(numSegments, segmentSize + NormDataMsg::GetStreamPayloadHeaderLength() + 1))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::StartServer() segment_pool init error\n");
|
DMSG(0, "NormSession::StartServer() segment_pool init error\n");
|
||||||
StopServer();
|
StopServer();
|
||||||
|
|
@ -213,7 +214,7 @@ bool NormSession::StartServer(unsigned long bufferSpace,
|
||||||
|
|
||||||
if (numParity)
|
if (numParity)
|
||||||
{
|
{
|
||||||
if (!encoder.Init(numParity, segmentSize + NormDataMsg::PayloadHeaderLength()))
|
if (!encoder.Init(numParity, segmentSize + NormDataMsg::GetStreamPayloadHeaderLength()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::StartServer() encoder init error\n");
|
DMSG(0, "NormSession::StartServer() encoder init error\n");
|
||||||
StopServer();
|
StopServer();
|
||||||
|
|
@ -231,6 +232,7 @@ bool NormSession::StartServer(unsigned long bufferSpace,
|
||||||
is_server = true;
|
is_server = true;
|
||||||
flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor
|
flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor
|
||||||
//probe_timer.SetInterval(0.0);
|
//probe_timer.SetInterval(0.0);
|
||||||
|
probe_pending = probe_reset = false;
|
||||||
OnProbeTimeout(probe_timer);
|
OnProbeTimeout(probe_timer);
|
||||||
ActivateTimer(probe_timer);
|
ActivateTimer(probe_timer);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -269,7 +271,6 @@ void NormSession::StopClient()
|
||||||
if (!is_server) Close();
|
if (!is_server) Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NormSession::Serve()
|
void NormSession::Serve()
|
||||||
{
|
{
|
||||||
// Only send new data when no other messages are queued for transmission
|
// Only send new data when no other messages are queued for transmission
|
||||||
|
|
@ -876,7 +877,6 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
|
|
||||||
void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
||||||
{
|
{
|
||||||
ASSERT(this == session_mgr.top_session);
|
|
||||||
// Drop some rx messages for testing
|
// Drop some rx messages for testing
|
||||||
if (UniformRand(100.0) < rx_loss_rate)
|
if (UniformRand(100.0) < rx_loss_rate)
|
||||||
{
|
{
|
||||||
|
|
@ -1318,6 +1318,8 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
|
||||||
|
|
||||||
void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, NormNackMsg& nack)
|
void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, NormNackMsg& nack)
|
||||||
{
|
{
|
||||||
|
// (TBD) maintain average of "numErasures" for SEGMENT repair requests
|
||||||
|
// to use as input to a an automatic "auto parity" adjustor
|
||||||
// Update GRTT estimate
|
// Update GRTT estimate
|
||||||
struct timeval grttResponse;
|
struct timeval grttResponse;
|
||||||
nack.GetGrttResponse(grttResponse);
|
nack.GetGrttResponse(grttResponse);
|
||||||
|
|
@ -2090,6 +2092,7 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
ProtoSystemTime(currentTime);
|
ProtoSystemTime(currentTime);
|
||||||
|
|
||||||
bool clientMsg = false;
|
bool clientMsg = false;
|
||||||
|
bool isProbe = false;
|
||||||
|
|
||||||
// Fill in any last minute timestamps
|
// Fill in any last minute timestamps
|
||||||
// (TBD) fill in SessionId fields on all messages as needed
|
// (TBD) fill in SessionId fields on all messages as needed
|
||||||
|
|
@ -2105,6 +2108,7 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
{
|
{
|
||||||
case NormCmdMsg::CC:
|
case NormCmdMsg::CC:
|
||||||
((NormCmdCCMsg&)msg).SetSendTime(currentTime);
|
((NormCmdCCMsg&)msg).SetSendTime(currentTime);
|
||||||
|
isProbe = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -2153,8 +2157,7 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tx_socket.SendTo(msg.GetBuffer(),
|
if (tx_socket.SendTo(msg.GetBuffer(), msgSize,
|
||||||
msgSize,
|
|
||||||
msg.GetDestination()))
|
msg.GetDestination()))
|
||||||
{
|
{
|
||||||
// Separate send/recv tracing
|
// Separate send/recv tracing
|
||||||
|
|
@ -2195,13 +2198,31 @@ bool NormSession::SendMessage(NormMsg& msg)
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result && isProbe)
|
||||||
|
{
|
||||||
|
probe_pending = false;
|
||||||
|
if (probe_reset)
|
||||||
|
{
|
||||||
|
probe_reset = false;
|
||||||
|
OnProbeTimeout(probe_timer);
|
||||||
|
ActivateTimer(probe_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
tx_timer.SetInterval(((double)msgSize) / tx_rate);
|
tx_timer.SetInterval(((double)msgSize) / tx_rate);
|
||||||
return result;
|
return result;
|
||||||
} // end NormSession::SendMessage()
|
} // end NormSession::SendMessage()
|
||||||
|
|
||||||
bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
// 1) Update grtt_estimate _if_ sufficient time elapsed.
|
// 1) Temporarily kill probe_timer if CMD(CC) not yet tx'd
|
||||||
|
if (probe_pending)
|
||||||
|
{
|
||||||
|
probe_reset = true;
|
||||||
|
probe_timer.Deactivate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Update grtt_estimate _if_ sufficient time elapsed.
|
||||||
grtt_age += probe_timer.GetInterval();
|
grtt_age += probe_timer.GetInterval();
|
||||||
if (grtt_age >= grtt_interval)
|
if (grtt_age >= grtt_interval)
|
||||||
{
|
{
|
||||||
|
|
@ -2249,7 +2270,7 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
if (grtt_interval > grtt_interval_max)
|
if (grtt_interval > grtt_interval_max)
|
||||||
grtt_interval = grtt_interval_max;
|
grtt_interval = grtt_interval_max;
|
||||||
|
|
||||||
// 2) Build probe message and determine next probe interval
|
// 3) Build a NORM_CMD(CC) message
|
||||||
NormCmdCCMsg* cmd = (NormCmdCCMsg*)GetMessageFromPool();
|
NormCmdCCMsg* cmd = (NormCmdCCMsg*)GetMessageFromPool();
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
{
|
{
|
||||||
|
|
@ -2257,7 +2278,6 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
LocalNodeId());
|
LocalNodeId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Build a NORM_CMD(CC) message
|
|
||||||
cmd->Init();
|
cmd->Init();
|
||||||
cmd->SetDestination(address);
|
cmd->SetDestination(address);
|
||||||
cmd->SetGrtt(grtt_quantized);
|
cmd->SetGrtt(grtt_quantized);
|
||||||
|
|
@ -2276,7 +2296,7 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
double probeInterval;
|
double probeInterval;
|
||||||
if (cc_enable)
|
if (cc_enable)
|
||||||
{
|
{
|
||||||
// Iterate over cc_node_list and append
|
// Iterate over cc_node_list and append cc_nodes ...
|
||||||
NormNodeListIterator iterator(cc_node_list);
|
NormNodeListIterator iterator(cc_node_list);
|
||||||
NormCCNode* next;
|
NormCCNode* next;
|
||||||
while ((next = (NormCCNode*)iterator.GetNextNode()))
|
while ((next = (NormCCNode*)iterator.GetNextNode()))
|
||||||
|
|
@ -2314,6 +2334,7 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueMessage(cmd);
|
QueueMessage(cmd);
|
||||||
|
probe_pending = true;
|
||||||
|
|
||||||
// 3) Set probe_timer interval
|
// 3) Set probe_timer interval
|
||||||
probe_timer.SetInterval(probeInterval);
|
probe_timer.SetInterval(probeInterval);
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ class NormSessionMgr
|
||||||
ProtoTimerMgr& GetTimerMgr() {return timer_mgr;}
|
ProtoTimerMgr& GetTimerMgr() {return timer_mgr;}
|
||||||
ProtoSocket::Notifier& GetSocketNotifier() {return socket_notifier;}
|
ProtoSocket::Notifier& GetSocketNotifier() {return socket_notifier;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProtoTimerMgr& timer_mgr;
|
ProtoTimerMgr& timer_mgr;
|
||||||
ProtoSocket::Notifier& socket_notifier;
|
ProtoSocket::Notifier& socket_notifier;
|
||||||
NormController* controller;
|
NormController* controller;
|
||||||
|
|
@ -320,6 +320,8 @@ class NormSession
|
||||||
|
|
||||||
ProtoTimer probe_timer; // GRTT/congestion control probes
|
ProtoTimer probe_timer; // GRTT/congestion control probes
|
||||||
bool probe_proactive;
|
bool probe_proactive;
|
||||||
|
bool probe_pending; // true while CMD(CC) enqueued
|
||||||
|
bool probe_reset;
|
||||||
|
|
||||||
double grtt_interval; // current GRTT update interval
|
double grtt_interval; // current GRTT update interval
|
||||||
double grtt_interval_min; // minimum GRTT update interval
|
double grtt_interval_min; // minimum GRTT update interval
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ NormSimAgent::NormSimAgent(ProtoTimerMgr& timerMgr,
|
||||||
// Bind NormSessionMgr to this agent and simulation environment
|
// Bind NormSessionMgr to this agent and simulation environment
|
||||||
session_mgr.SetController(static_cast<NormController*>(this));
|
session_mgr.SetController(static_cast<NormController*>(this));
|
||||||
|
|
||||||
interval_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSimAgent::OnIntervalTimeout);
|
interval_timer.SetListener(this, &NormSimAgent::OnIntervalTimeout);
|
||||||
interval_timer.SetInterval(0.0);
|
interval_timer.SetInterval(0.0);
|
||||||
interval_timer.SetRepeat(0);
|
interval_timer.SetRepeat(0);
|
||||||
|
|
||||||
|
|
@ -593,7 +593,7 @@ void NormSimAgent::Notify(NormController::Event event,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OnIntervalTimeout();
|
OnIntervalTimeout(interval_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -790,7 +790,7 @@ void NormSimAgent::Notify(NormController::Event event,
|
||||||
} // end NormSimAgent::Notify()
|
} // end NormSimAgent::Notify()
|
||||||
|
|
||||||
|
|
||||||
bool NormSimAgent::OnIntervalTimeout()
|
bool NormSimAgent::OnIntervalTimeout(ProtoTimer& theTimer)
|
||||||
{
|
{
|
||||||
if (tx_repeat_count)
|
if (tx_repeat_count)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class NormSimAgent : public NormController
|
||||||
void ActivateTimer(ProtoTimer& theTimer)
|
void ActivateTimer(ProtoTimer& theTimer)
|
||||||
{session_mgr.ActivateTimer(theTimer);}
|
{session_mgr.ActivateTimer(theTimer);}
|
||||||
|
|
||||||
bool OnIntervalTimeout();
|
bool OnIntervalTimeout(ProtoTimer& theTimer);
|
||||||
|
|
||||||
static const char* const cmd_list[];
|
static const char* const cmd_list[];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,6 @@
|
||||||
|
|
||||||
#ifndef _NORM_VERSION
|
#ifndef _NORM_VERSION
|
||||||
#define _NORM_VERSION
|
#define _NORM_VERSION
|
||||||
#define VERSION "1.1b1"
|
#define VERSION "1.1b2"
|
||||||
#endif // _NORM_VERSION
|
#endif // _NORM_VERSION
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,521 @@
|
||||||
|
|
||||||
|
#include "protokit.h"
|
||||||
|
#include <stdio.h> // for sscanf()
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif // UNIX
|
||||||
|
|
||||||
|
|
||||||
|
class RaftApp : public ProtoApp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RaftApp();
|
||||||
|
~RaftApp();
|
||||||
|
|
||||||
|
// Overrides from ProtoApp base
|
||||||
|
bool OnStartup(int argc, const char*const* argv);
|
||||||
|
bool ProcessCommands(int argc, const char*const* argv);
|
||||||
|
void OnShutdown();
|
||||||
|
|
||||||
|
bool OnCommand(const char* cmd, const char* arg = NULL);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void Usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: raft [listen [<groupAddr>/]<port>][dest <addr>/<port>]\n");
|
||||||
|
}
|
||||||
|
enum CmdType {CMD_INVALID, CMD_NOARG, CMD_ARG};
|
||||||
|
static CmdType GetCommandType(const char* cmd);
|
||||||
|
static const char* const CMD_LIST[];
|
||||||
|
|
||||||
|
// Tunnel related members ...
|
||||||
|
void OnRxSocketEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
static void DoInputReady(ProtoDispatcher::Descriptor descriptor,
|
||||||
|
ProtoDispatcher::Event event,
|
||||||
|
const void* userData);
|
||||||
|
void OnInputReady();
|
||||||
|
|
||||||
|
ProtoSocket rx_socket;
|
||||||
|
ProtoSocket tx_socket;
|
||||||
|
ProtoAddress tx_address;
|
||||||
|
char tx_msg_buffer[8194];
|
||||||
|
UINT16 tx_msg_length;
|
||||||
|
UINT16 tx_msg_index;
|
||||||
|
|
||||||
|
// RTSP proxy related members ...
|
||||||
|
void OnProxySocketEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
void OnClientSocketEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
|
||||||
|
ProtoSocket rtsp_proxy_socket;
|
||||||
|
char* rtsp_url;
|
||||||
|
ProtoAddress rtsp_server_address;
|
||||||
|
ProtoSocket rtsp_client_socket;
|
||||||
|
|
||||||
|
}; // end class RaftApp
|
||||||
|
|
||||||
|
const char* const RaftApp::CMD_LIST[] =
|
||||||
|
{
|
||||||
|
"+debug", // debug <level>
|
||||||
|
"+listen", // recv [<mcastAddr>/]<port>
|
||||||
|
"+dest", // send <addr>/<port>
|
||||||
|
"+rtspProxy", // rtsp <rtspUrl>
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
RaftApp::RaftApp()
|
||||||
|
: rx_socket(ProtoSocket::UDP),
|
||||||
|
tx_socket(ProtoSocket::UDP), tx_msg_length(0), tx_msg_index(0),
|
||||||
|
rtsp_proxy_socket(ProtoSocket::TCP), rtsp_url(NULL),
|
||||||
|
rtsp_client_socket(ProtoSocket::TCP)
|
||||||
|
{
|
||||||
|
rx_socket.SetNotifier(&GetSocketNotifier());
|
||||||
|
rx_socket.SetListener(this, &RaftApp::OnRxSocketEvent);
|
||||||
|
|
||||||
|
rtsp_proxy_socket.SetNotifier(&GetSocketNotifier());
|
||||||
|
rtsp_proxy_socket.SetListener(this, &RaftApp::OnProxySocketEvent);
|
||||||
|
rtsp_client_socket.SetNotifier(&GetSocketNotifier());
|
||||||
|
rtsp_client_socket.SetListener(this, &RaftApp::OnClientSocketEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
RaftApp::~RaftApp()
|
||||||
|
{
|
||||||
|
if (rtsp_proxy_socket.IsOpen())
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
if (rtsp_client_socket.IsOpen())
|
||||||
|
rtsp_client_socket.Close();
|
||||||
|
if (rtsp_url)
|
||||||
|
{
|
||||||
|
delete rtsp_url;
|
||||||
|
rtsp_url = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RaftApp::OnStartup(int argc, const char*const* argv)
|
||||||
|
{
|
||||||
|
bool result = ProcessCommands(argc, argv);
|
||||||
|
if (result && !dispatcher.IsPending())
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
OnShutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} // end RaftApp::OnStartup()
|
||||||
|
|
||||||
|
void RaftApp::OnShutdown()
|
||||||
|
{
|
||||||
|
if (rtsp_proxy_socket.IsOpen())
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
if (rtsp_client_socket.IsOpen())
|
||||||
|
rtsp_client_socket.Close();
|
||||||
|
if (rtsp_url)
|
||||||
|
{
|
||||||
|
delete rtsp_url;
|
||||||
|
rtsp_url = NULL;
|
||||||
|
}
|
||||||
|
} // end RaftApp::OnShutdown()
|
||||||
|
|
||||||
|
bool RaftApp::OnCommand(const char* cmd, const char* arg)
|
||||||
|
{
|
||||||
|
if (!strncmp(cmd, "dest", strlen(cmd)))
|
||||||
|
{
|
||||||
|
char host[256];
|
||||||
|
char* ptr = strchr(arg, '/');
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
unsigned int len = ptr - arg;
|
||||||
|
strncpy(host, arg, len);
|
||||||
|
host[len] = '\0';
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() invalid \"dest\" command\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!tx_address.ResolveFromString(host))
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() invalid dest address\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UINT16 port;
|
||||||
|
if (1 != sscanf(ptr, "%hu", &port))
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() invalid dest port\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tx_address.SetPort(port);
|
||||||
|
int fd = fileno(stdin);
|
||||||
|
if(-1 == fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK))
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() warning: fcntl(stdout, F_SETFL(O_NONBLOCK)) error: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
tx_msg_length = tx_msg_index = 0;
|
||||||
|
dispatcher.InstallGenericInput(fileno(stdin), RaftApp::DoInputReady, this);
|
||||||
|
}
|
||||||
|
else if (!strncmp(cmd, "listen", strlen(cmd)))
|
||||||
|
{
|
||||||
|
ProtoAddress groupAddr;
|
||||||
|
const char* ptr = strchr(arg, '/');
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
char group[256];
|
||||||
|
unsigned int len = ptr - arg;
|
||||||
|
strncpy(group, arg, len);
|
||||||
|
group[len] = '\0';
|
||||||
|
if (!groupAddr.ResolveFromString(group) ||
|
||||||
|
!groupAddr.IsMulticast())
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() invalid recv multicast address\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr = arg;
|
||||||
|
}
|
||||||
|
UINT16 port;
|
||||||
|
if (1 != sscanf(ptr, "%hu", &port))
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() invalid recv port\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!rx_socket.Open(port))
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() rx_socket.Open() error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (groupAddr.IsValid())
|
||||||
|
{
|
||||||
|
if (!rx_socket.JoinGroup(groupAddr))
|
||||||
|
{
|
||||||
|
DMSG(0, "Raft::OnCommand() rx_socket.JoinGroup() error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strncmp(cmd, "rtspProxy", strlen(cmd)))
|
||||||
|
{
|
||||||
|
if (!rtsp_proxy_socket.Listen(554))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnCommand() error: rtsp_proxy_socket.Listen() failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rtsp_url) delete rtsp_url;
|
||||||
|
if (!(rtsp_url = new char[strlen(arg) + 1]))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnCommand() new rtsp_url error: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strcpy(rtsp_url, arg);
|
||||||
|
char* ptr = strstr(rtsp_url, "rtsp://");
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnCommand() error: invalid rtsp_url\n");
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ptr += 7;
|
||||||
|
char hostName[256];
|
||||||
|
if (1 != sscanf(ptr, "%255s", hostName))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnCommand() error: no rtsp_url hostname\n");
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char* sptr = strchr(hostName, '/');
|
||||||
|
if (sptr) *sptr = '\0';
|
||||||
|
if (!rtsp_server_address.ResolveFromString(hostName))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnCommand() error: invalid rtsp_url hostname:%s\n",
|
||||||
|
hostName);
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rtsp_server_address.SetPort(554);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnCommand() error: invalid command!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // end RaftApp::OnCommand()
|
||||||
|
|
||||||
|
bool RaftApp::ProcessCommands(int argc, const char*const* argv)
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
while (i < argc)
|
||||||
|
{
|
||||||
|
switch (GetCommandType(argv[i]))
|
||||||
|
{
|
||||||
|
case CMD_ARG:
|
||||||
|
if (!OnCommand(argv[i], argv[i+1]))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::ProcessCommands() %s command error\n", argv[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case CMD_NOARG:
|
||||||
|
if (!OnCommand(argv[i]))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::ProcessCommands() %s command error\n", argv[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DMSG(0, "RaftApp::ProcessCommands() invalid command\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // end RaftApp::ProcessCommands()
|
||||||
|
|
||||||
|
void RaftApp::DoInputReady(ProtoDispatcher::Descriptor /*descriptor*/,
|
||||||
|
ProtoDispatcher::Event /*event*/,
|
||||||
|
const void* userData)
|
||||||
|
{
|
||||||
|
((RaftApp*)userData)->OnInputReady();
|
||||||
|
} // end RaftApp::DoInputReady()
|
||||||
|
|
||||||
|
void RaftApp::OnInputReady()
|
||||||
|
{
|
||||||
|
// Read from stdin ...
|
||||||
|
unsigned int want = tx_msg_length ? tx_msg_length - tx_msg_index : 2 - tx_msg_index;
|
||||||
|
if (want)
|
||||||
|
{
|
||||||
|
int result = fread(tx_msg_buffer+tx_msg_index, 1, want, stdin);
|
||||||
|
if (result > 0)
|
||||||
|
{
|
||||||
|
tx_msg_index += result;
|
||||||
|
}
|
||||||
|
else if (ferror(stdin))
|
||||||
|
{
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
|
case EINTR:
|
||||||
|
case EAGAIN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DMSG(0, "raft: input error:%s\n", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
clearerr(stdin);
|
||||||
|
}
|
||||||
|
else if (feof(stdin))
|
||||||
|
{
|
||||||
|
DMSG(0, "raft: input end-of-file\n");
|
||||||
|
dispatcher.RemoveGenericInput(fileno(stdin));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 == tx_msg_length)
|
||||||
|
{
|
||||||
|
if (2 == tx_msg_index)
|
||||||
|
{
|
||||||
|
memcpy(&tx_msg_length, tx_msg_buffer, 2);
|
||||||
|
tx_msg_length = ntohs(tx_msg_length);
|
||||||
|
if ((tx_msg_length < 2) || (tx_msg_length > 8194))
|
||||||
|
{
|
||||||
|
DMSG(0, "raft: input error: invalid tx_msg_length: %u\n", tx_msg_length);
|
||||||
|
dispatcher.RemoveGenericInput(fileno(stdin));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OnInputReady();
|
||||||
|
}
|
||||||
|
else if (tx_msg_index == tx_msg_length)
|
||||||
|
{
|
||||||
|
if (!tx_socket.SendTo(tx_msg_buffer+2, tx_msg_length-2, tx_address))
|
||||||
|
{
|
||||||
|
DMSG(0, "raft: tx_socket.SendTo() error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tx_msg_index = tx_msg_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end RaftApp::OnInputReady()
|
||||||
|
|
||||||
|
void RaftApp::OnRxSocketEvent(ProtoSocket& /*theSocket*/,
|
||||||
|
ProtoSocket::Event theEvent)
|
||||||
|
{
|
||||||
|
char buffer[8194];
|
||||||
|
unsigned int numBytes = 8192;
|
||||||
|
ProtoAddress srcAddr;
|
||||||
|
if (!rx_socket.RecvFrom(buffer+2, numBytes, srcAddr))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnRxSocketEvent() rx_socket.RecvFrom() error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
numBytes += 2;
|
||||||
|
UINT16 msgLength = htons((UINT16)numBytes);
|
||||||
|
memcpy(buffer, &msgLength, 2);
|
||||||
|
unsigned int put = 0;
|
||||||
|
while (put < numBytes)
|
||||||
|
{
|
||||||
|
size_t result = fwrite(buffer+put, 1, numBytes-put, stdout);
|
||||||
|
if (result > 0)
|
||||||
|
{
|
||||||
|
put += result;
|
||||||
|
}
|
||||||
|
else if (EINTR != errno)
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnRxSocketEvent() fwrite() error: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
} // end RaftApp::OnRxSocketEvent()
|
||||||
|
|
||||||
|
void RaftApp::OnProxySocketEvent(ProtoSocket& /*theSocket*/,
|
||||||
|
ProtoSocket::Event theEvent)
|
||||||
|
{
|
||||||
|
//TRACE("RaftApp::OnProxySocketEvent() ...\n");
|
||||||
|
switch (theEvent)
|
||||||
|
{
|
||||||
|
case ProtoSocket::ACCEPT:
|
||||||
|
{
|
||||||
|
if (!rtsp_proxy_socket.Accept())
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnProxySocketEvent() rtsp_proxy_socket.Accept() error\n");
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
if (!rtsp_proxy_socket.Listen(554))
|
||||||
|
DMSG(0, "raft: rtsp_proxy_socket.Listen() error\n");
|
||||||
|
}
|
||||||
|
TRACE("calling rtsp_client_socket.Connect() ...\n");
|
||||||
|
if (!rtsp_client_socket.Connect(rtsp_server_address))
|
||||||
|
{
|
||||||
|
DMSG(0, "RaftApp::OnProxySocketEvent() rtsp_client_socket.Connect() error\n");
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
}
|
||||||
|
TRACE(" rtsp_client_socket.Connect() complete.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ProtoSocket::RECV:
|
||||||
|
{
|
||||||
|
//TRACE("rtsp_proxy_socket RECV event (connected:%d)...\n",
|
||||||
|
// rtsp_client_socket.IsConnected());
|
||||||
|
if (rtsp_client_socket.IsConnected())
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
unsigned int buflen = 1023;
|
||||||
|
while (rtsp_proxy_socket.Recv(buffer, buflen))
|
||||||
|
{
|
||||||
|
unsigned int put = 0;
|
||||||
|
while (put < buflen)
|
||||||
|
{
|
||||||
|
unsigned int numBytes = buflen - put;
|
||||||
|
if (!rtsp_client_socket.Send(buffer+put, numBytes))
|
||||||
|
{
|
||||||
|
DMSG(0, "rtsp_client_socket.Send() error\n");
|
||||||
|
rtsp_client_socket.Close();
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
if (!rtsp_proxy_socket.Listen(554))
|
||||||
|
DMSG(0, "raft: rtsp_proxy_socket.Listen() error\n");
|
||||||
|
}
|
||||||
|
put += numBytes;
|
||||||
|
}
|
||||||
|
TRACE("rtsp_client sent %u bytes ....\n", put);
|
||||||
|
buflen = 1023;
|
||||||
|
}
|
||||||
|
TRACE("proxy socket RECV completed.\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ProtoSocket::DISCONNECT:
|
||||||
|
{
|
||||||
|
TRACE("rtsp_proxy_socket DISCONNECT event ...\n");
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
rtsp_client_socket.Close();
|
||||||
|
if (!rtsp_proxy_socket.Listen(554))
|
||||||
|
DMSG(0, "raft: rtsp_proxy_socket.Listen() error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
TRACE("rtsp_proxy_socket UNKNOWN event ...\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end RaftApp::OnProxySocketEvent()
|
||||||
|
|
||||||
|
void RaftApp::OnClientSocketEvent(ProtoSocket& /*theSocket*/,
|
||||||
|
ProtoSocket::Event theEvent)
|
||||||
|
{
|
||||||
|
TRACE("RaftApp::OnClientSocketEvent() ...\n");
|
||||||
|
switch (theEvent)
|
||||||
|
{
|
||||||
|
case ProtoSocket::CONNECT:
|
||||||
|
{
|
||||||
|
TRACE("RaftApp::OnClientSocketEvent() CONNECT ...\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ProtoSocket::RECV:
|
||||||
|
{
|
||||||
|
TRACE("rtsp_client_socket RECV event ..\n");
|
||||||
|
char buffer[1024];
|
||||||
|
unsigned int buflen = 1023;
|
||||||
|
while (rtsp_client_socket.Recv(buffer, buflen))
|
||||||
|
{
|
||||||
|
buffer[buflen] = '\0';
|
||||||
|
TRACE("%s");
|
||||||
|
}
|
||||||
|
TRACE("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ProtoSocket::DISCONNECT:
|
||||||
|
{
|
||||||
|
TRACE("rtsp_client_socket DISCONNECT event ...\n");
|
||||||
|
rtsp_client_socket.Close();
|
||||||
|
rtsp_proxy_socket.Close();
|
||||||
|
if (!rtsp_proxy_socket.Listen(554))
|
||||||
|
DMSG(0, "raft: rtsp_proxy_socket.Listen() error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
TRACE("rtsp_client_socket UNKNOWN event ...\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end RaftApp::OnClientSocketEvent()
|
||||||
|
|
||||||
|
RaftApp::CmdType RaftApp::GetCommandType(const char* cmd)
|
||||||
|
{
|
||||||
|
if (!cmd) return CMD_INVALID;
|
||||||
|
unsigned int len = strlen(cmd);
|
||||||
|
bool matched = false;
|
||||||
|
CmdType type = CMD_INVALID;
|
||||||
|
const char* const* nextCmd = CMD_LIST;
|
||||||
|
while (*nextCmd)
|
||||||
|
{
|
||||||
|
if (!strncmp(cmd, *nextCmd+1, len))
|
||||||
|
{
|
||||||
|
if (matched)
|
||||||
|
{
|
||||||
|
// ambiguous command (command should match only once)
|
||||||
|
return CMD_INVALID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matched = true;
|
||||||
|
if ('+' == *nextCmd[0])
|
||||||
|
type = CMD_ARG;
|
||||||
|
else
|
||||||
|
type = CMD_NOARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextCmd++;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
} // end RaftApp::GetCommandType()
|
||||||
|
|
||||||
|
PROTO_INSTANTIATE_APP(RaftApp)
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# COMMON MDP MAKEFILE STUFF
|
# COMMON NORM MAKEFILE STUFF
|
||||||
#
|
#
|
||||||
|
|
||||||
SHELL=/bin/sh
|
SHELL=/bin/sh
|
||||||
|
|
@ -40,13 +40,13 @@ TCL_SCRIPTS = ${TCL_SCRIPT_PATH}/init.tcl \
|
||||||
${TK_SCRIPT_PATH}/text.tcl \
|
${TK_SCRIPT_PATH}/text.tcl \
|
||||||
${TK_SCRIPT_PATH}/optMenu.tcl
|
${TK_SCRIPT_PATH}/optMenu.tcl
|
||||||
|
|
||||||
TARGETS = mdp tkMdp
|
TARGETS = norm raft
|
||||||
|
|
||||||
# Rule for C++ .cpp extension
|
# Rule for C++ .cpp extension
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
$(CC) -c $(CFLAGS) -o $*.o $*.cpp
|
$(CC) -c $(CFLAGS) -o $*.o $*.cpp
|
||||||
|
|
||||||
# MDP depends upon the NRL Protean Group's development library
|
# NORM depends upon the NRL Protean Group's development library
|
||||||
LIBPROTO = $(PROTOLIB)/unix/libProtokit.a
|
LIBPROTO = $(PROTOLIB)/unix/libProtokit.a
|
||||||
$(PROTOLIB)/unix/libProtokit.a:
|
$(PROTOLIB)/unix/libProtokit.a:
|
||||||
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProtokit.a
|
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProtokit.a
|
||||||
|
|
@ -76,7 +76,7 @@ libnormSim.a: $(SIM_OBJ)
|
||||||
ar rcv $@ $(SIM_OBJ)
|
ar rcv $@ $(SIM_OBJ)
|
||||||
ranlib $@
|
ranlib $@
|
||||||
|
|
||||||
# (mdp) command-line file broadcaster/receiver
|
# (norm) command-line file broadcaster/receiver
|
||||||
APP_SRC = $(COMMON)/normApp.cpp $(COMMON)/normPostProcess.cpp \
|
APP_SRC = $(COMMON)/normApp.cpp $(COMMON)/normPostProcess.cpp \
|
||||||
$(UNIX)/unixPostProcess.cpp
|
$(UNIX)/unixPostProcess.cpp
|
||||||
APP_OBJ = $(APP_SRC:.cpp=.o)
|
APP_OBJ = $(APP_SRC:.cpp=.o)
|
||||||
|
|
@ -84,6 +84,13 @@ APP_OBJ = $(APP_SRC:.cpp=.o)
|
||||||
norm: $(APP_OBJ) libnorm.a $(LIBPROTO)
|
norm: $(APP_OBJ) libnorm.a $(LIBPROTO)
|
||||||
$(CC) $(CFLAGS) -o $@ $(APP_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
|
$(CC) $(CFLAGS) -o $@ $(APP_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS)
|
||||||
|
|
||||||
|
# (raft) command-line reliable tunnel helper
|
||||||
|
RAFT_SRC = $(COMMON)/raft.cpp
|
||||||
|
RAFT_OBJ = $(RAFT_SRC:.cpp=.o)
|
||||||
|
|
||||||
|
raft: $(RAFT_OBJ) $(LIBPROTO)
|
||||||
|
$(CC) $(CFLAGS) -o $@ $(RAFT_OBJ) $(LDFLAGS) $(LIBPROTO) $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(COMMON)/*.o $(UNIX)/*.o $(UNIX)/libnorm.a $(UNIX)/norm $(NS)/*.o;
|
rm -f $(COMMON)/*.o $(UNIX)/*.o $(UNIX)/libnorm.a $(UNIX)/norm $(NS)/*.o;
|
||||||
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) clean
|
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) clean
|
||||||
|
|
|
||||||
BIN
win32/Norm.opt
BIN
win32/Norm.opt
Binary file not shown.
|
|
@ -63,8 +63,8 @@ LIB32=link.exe -lib
|
||||||
# PROP Output_Dir "Debug"
|
# PROP Output_Dir "Debug"
|
||||||
# PROP Intermediate_Dir "Debug"
|
# PROP Intermediate_Dir "Debug"
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "_DEBUG" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
# ADD CPP /nologo /W3 /GX /Od /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "_DEBUG" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
|
@ -89,11 +89,11 @@ SOURCE=..\common\galois.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -104,11 +104,11 @@ SOURCE=..\common\normBitmask.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -119,11 +119,11 @@ SOURCE=..\common\normEncoder.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -134,11 +134,11 @@ SOURCE=..\common\normFile.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -149,11 +149,11 @@ SOURCE=..\common\normMessage.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -164,11 +164,11 @@ SOURCE=..\common\normNode.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -179,11 +179,11 @@ SOURCE=..\common\normObject.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -194,11 +194,11 @@ SOURCE=..\common\normSegment.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
@ -209,11 +209,11 @@ SOURCE=..\common\normSession.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "NormLib - Win32 Release"
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
# ADD CPP /MD /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MD /vmg /I "..\win32"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
# ADD CPP /MDd /vmg /I "..\common" /I "..\win32" /I "..\protolib\common" /I "..\protolib\win32" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT"
|
# ADD CPP /MDd /vmg /I "..\win32"
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ LINK32=link.exe
|
||||||
# PROP Ignore_Export_Lib 0
|
# PROP Ignore_Export_Lib 0
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm /vmg /GX /ZI /Od /I "..\..\common" /I "..\..\protolib\common" /I "..\..\protolib\win32" /D "_DEBUG" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
# ADD CPP /nologo /MDd /W3 /vmg /GX /Od /I "..\..\common" /I "..\..\protolib\common" /I "..\..\protolib\win32" /D "_DEBUG" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue