v1.1b1
parent
d0417b042a
commit
02fcae4cb0
|
|
@ -1,31 +1,32 @@
|
||||||
|
|
||||||
// norm.cpp - Command-line NORM application
|
// normApp.cpp - Command-line NORM application
|
||||||
|
|
||||||
#include "protoLib.h"
|
#include "protokit.h"
|
||||||
#include "normSession.h"
|
#include "normSession.h"
|
||||||
#include "normPostProcess.h"
|
#include "normPostProcess.h"
|
||||||
|
|
||||||
#include <stdio.h> // for stdout/stderr printouts
|
#include <stdio.h> // for stdout/stderr printouts
|
||||||
#include <signal.h> // for SIGTERM/SIGINT handling
|
#include <signal.h> // for SIGTERM/SIGINT handling
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Command-line application using Protolib EventDispatcher
|
// Command-line application using Protolib EventDispatcher
|
||||||
class NormApp : public NormController
|
class NormApp : public NormController, public ProtoApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NormApp();
|
NormApp();
|
||||||
virtual ~NormApp();
|
virtual ~NormApp();
|
||||||
bool OnStartup();
|
|
||||||
int MainLoop() {return dispatcher.Run();}
|
// Overrides from ProtoApp or NsProtoSimAgent base
|
||||||
void Stop(int exitCode) {dispatcher.Stop(exitCode);}
|
bool OnStartup(int argc, const char*const* argv);
|
||||||
|
bool ProcessCommands(int argc, const char*const* argv);
|
||||||
void OnShutdown();
|
void OnShutdown();
|
||||||
|
|
||||||
bool ProcessCommand(const char* cmd, const char* val);
|
bool ProcessCommand(const char* cmd, const char* val);
|
||||||
bool ParseCommandLine(int argc, char* argv[]);
|
|
||||||
|
|
||||||
static void DoInputReady(EventDispatcher::Descriptor descriptor,
|
static void DoInputReady(ProtoDispatcher::Descriptor descriptor,
|
||||||
EventDispatcher::EventType theEvent,
|
ProtoDispatcher::Event theEvent,
|
||||||
const void* userData);
|
const void* userData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnInputReady();
|
void OnInputReady();
|
||||||
|
|
@ -39,17 +40,14 @@ class NormApp : public NormController
|
||||||
class NormServerNode* server,
|
class NormServerNode* server,
|
||||||
class NormObject* object);
|
class NormObject* object);
|
||||||
|
|
||||||
void InstallTimer(ProtocolTimer* timer)
|
bool OnIntervalTimeout(ProtoTimer& theTimer);
|
||||||
{dispatcher.InstallTimer(timer);}
|
|
||||||
bool OnIntervalTimeout();
|
|
||||||
|
|
||||||
static const char* const cmd_list[];
|
static const char* const cmd_list[];
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
static void SignalHandler(int sigNum);
|
static void SignalHandler(int sigNum);
|
||||||
bool IsPostProcessing() {return post_processor.IsActive();}
|
#endif // UNIX
|
||||||
void HandleSIGCHLD() {post_processor.HandleSIGCHLD();}
|
|
||||||
|
|
||||||
EventDispatcher dispatcher;
|
|
||||||
NormSessionMgr session_mgr;
|
NormSessionMgr session_mgr;
|
||||||
NormSession* session;
|
NormSession* session;
|
||||||
NormStreamObject* tx_stream;
|
NormStreamObject* tx_stream;
|
||||||
|
|
@ -91,13 +89,13 @@ class NormApp : public NormController
|
||||||
double tx_object_interval;
|
double tx_object_interval;
|
||||||
int tx_repeat_count;
|
int tx_repeat_count;
|
||||||
double tx_repeat_interval;
|
double tx_repeat_interval;
|
||||||
ProtocolTimer interval_timer;
|
ProtoTimer interval_timer;
|
||||||
|
|
||||||
// NormSession client-only parameters
|
// NormSession client-only parameters
|
||||||
unsigned long rx_buffer_size; // bytes
|
unsigned long rx_buffer_size; // bytes
|
||||||
NormFileList rx_file_cache;
|
NormFileList rx_file_cache;
|
||||||
char* rx_cache_path;
|
char* rx_cache_path;
|
||||||
NormPostProcessor post_processor;
|
NormPostProcessor* post_processor;
|
||||||
bool unicast_nacks;
|
bool unicast_nacks;
|
||||||
bool silent_client;
|
bool silent_client;
|
||||||
|
|
||||||
|
|
@ -109,7 +107,8 @@ class NormApp : public NormController
|
||||||
}; // end class NormApp
|
}; // end class NormApp
|
||||||
|
|
||||||
NormApp::NormApp()
|
NormApp::NormApp()
|
||||||
: session(NULL), tx_stream(NULL), rx_stream(NULL), input(NULL), output(NULL),
|
: session_mgr(GetTimerMgr(), GetSocketNotifier()),
|
||||||
|
session(NULL), tx_stream(NULL), rx_stream(NULL), input(NULL), output(NULL),
|
||||||
input_index(0), input_length(0), input_active(false),
|
input_index(0), input_length(0), input_active(false),
|
||||||
push_stream(false), input_messaging(false), input_msg_length(0), input_msg_index(0),
|
push_stream(false), input_messaging(false), input_msg_length(0), input_msg_index(0),
|
||||||
output_index(0), output_messaging(false), output_msg_length(0), output_msg_sync(false),
|
output_index(0), output_messaging(false), output_msg_length(0), output_msg_sync(false),
|
||||||
|
|
@ -122,14 +121,14 @@ NormApp::NormApp()
|
||||||
tracing(false), tx_loss(0.0), rx_loss(0.0)
|
tracing(false), tx_loss(0.0), rx_loss(0.0)
|
||||||
{
|
{
|
||||||
// Init tx_timer for 1.0 second interval, infinite repeats
|
// Init tx_timer for 1.0 second interval, infinite repeats
|
||||||
session_mgr.Init(EventDispatcher::TimerInstaller, &dispatcher,
|
session_mgr.SetController(this);
|
||||||
EventDispatcher::SocketInstaller, &dispatcher,
|
|
||||||
this);
|
interval_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormApp::OnIntervalTimeout);
|
||||||
interval_timer.Init(0.0, 0, (ProtocolTimerOwner*)this,
|
interval_timer.SetInterval(0.0);
|
||||||
(ProtocolTimeoutFunc)&NormApp::OnIntervalTimeout);
|
interval_timer.SetRepeat(0);
|
||||||
|
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
GetSystemTime(¤tTime);
|
ProtoSystemTime(currentTime);
|
||||||
srand(currentTime.tv_usec);
|
srand(currentTime.tv_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,6 +136,7 @@ NormApp::~NormApp()
|
||||||
{
|
{
|
||||||
if (address) delete address;
|
if (address) delete address;
|
||||||
if (rx_cache_path) delete rx_cache_path;
|
if (rx_cache_path) delete rx_cache_path;
|
||||||
|
if (post_processor) delete post_processor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -299,9 +299,9 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
||||||
else if (!strncmp("input", cmd, len))
|
else if (!strncmp("input", cmd, len))
|
||||||
{
|
{
|
||||||
if (!strcmp(val, "STDIN"))
|
if (!strcmp(val, "STDIN"))
|
||||||
{
|
{
|
||||||
input = stdin;
|
input = stdin;
|
||||||
}
|
}
|
||||||
else if (!(input = fopen(val, "rb")))
|
else if (!(input = fopen(val, "rb")))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n",
|
DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n",
|
||||||
|
|
@ -310,16 +310,18 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
||||||
}
|
}
|
||||||
input_index = input_length = 0;
|
input_index = input_length = 0;
|
||||||
input_messaging = false;
|
input_messaging = false;
|
||||||
|
#ifdef UNIX
|
||||||
// Set input non-blocking
|
// Set input non-blocking
|
||||||
if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK))
|
if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK))
|
||||||
perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error");
|
perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error");
|
||||||
|
#endif // UNIX
|
||||||
}
|
}
|
||||||
else if (!strncmp("output", cmd, len))
|
else if (!strncmp("output", cmd, len))
|
||||||
{
|
{
|
||||||
if (!strcmp(val, "STDOUT"))
|
if (!strcmp(val, "STDOUT"))
|
||||||
{
|
{
|
||||||
output = stdout;
|
output = stdout;
|
||||||
}
|
}
|
||||||
else if (!(output = fopen(val, "wb")))
|
else if (!(output = fopen(val, "wb")))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n",
|
DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n",
|
||||||
|
|
@ -333,9 +335,9 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
||||||
else if (!strncmp("minput", cmd, len))
|
else if (!strncmp("minput", cmd, len))
|
||||||
{
|
{
|
||||||
if (!strcmp(val, "STDIN"))
|
if (!strcmp(val, "STDIN"))
|
||||||
{
|
{
|
||||||
input = stdin;
|
input = stdin;
|
||||||
}
|
}
|
||||||
else if (!(input = fopen(val, "rb")))
|
else if (!(input = fopen(val, "rb")))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n",
|
DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n",
|
||||||
|
|
@ -344,16 +346,18 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
||||||
}
|
}
|
||||||
input_index = input_length = 0;
|
input_index = input_length = 0;
|
||||||
input_messaging = true;
|
input_messaging = true;
|
||||||
|
#ifdef UNIX
|
||||||
// Set input non-blocking
|
// Set input non-blocking
|
||||||
if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK))
|
if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK))
|
||||||
perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error");
|
perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error");
|
||||||
|
#endif // UNIX
|
||||||
}
|
}
|
||||||
else if (!strncmp("moutput", cmd, len))
|
else if (!strncmp("moutput", cmd, len))
|
||||||
{
|
{
|
||||||
if (!strcmp(val, "STDOUT"))
|
if (!strcmp(val, "STDOUT"))
|
||||||
{
|
{
|
||||||
output = stdout;
|
output = stdout;
|
||||||
}
|
}
|
||||||
else if (!(output = fopen(val, "wb")))
|
else if (!(output = fopen(val, "wb")))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n",
|
DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n",
|
||||||
|
|
@ -404,8 +408,8 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
||||||
else if (!strncmp("rxcachedir", cmd, len))
|
else if (!strncmp("rxcachedir", cmd, len))
|
||||||
{
|
{
|
||||||
unsigned int length = strlen(val);
|
unsigned int length = strlen(val);
|
||||||
// Make sure there is a trailing DIR_DELIMITER
|
// Make sure there is a trailing PROTO_PATH_DELIMITER
|
||||||
if (DIR_DELIMITER != val[length-1])
|
if (PROTO_PATH_DELIMITER != val[length-1])
|
||||||
length += 2;
|
length += 2;
|
||||||
else
|
else
|
||||||
length += 1;
|
length += 1;
|
||||||
|
|
@ -416,7 +420,7 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
strcpy(rx_cache_path, val);
|
strcpy(rx_cache_path, val);
|
||||||
rx_cache_path[length-2] = DIR_DELIMITER;
|
rx_cache_path[length-2] = PROTO_PATH_DELIMITER;
|
||||||
rx_cache_path[length-1] = '\0';
|
rx_cache_path[length-1] = '\0';
|
||||||
}
|
}
|
||||||
else if (!strncmp("segment", cmd, len))
|
else if (!strncmp("segment", cmd, len))
|
||||||
|
|
@ -514,7 +518,7 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
||||||
}
|
}
|
||||||
else if (!strncmp("processor", cmd, len))
|
else if (!strncmp("processor", cmd, len))
|
||||||
{
|
{
|
||||||
if (!post_processor.SetCommand(val))
|
if (!post_processor->SetCommand(val))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::ProcessCommand(processor) error!\n");
|
DMSG(0, "NormApp::ProcessCommand(processor) error!\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -555,7 +559,7 @@ NormApp::CmdType NormApp::CommandType(const char* cmd)
|
||||||
} // end NormApp::CommandType()
|
} // end NormApp::CommandType()
|
||||||
|
|
||||||
|
|
||||||
bool NormApp::ParseCommandLine(int argc, char* argv[])
|
bool NormApp::ProcessCommands(int argc, const char*const* argv)
|
||||||
{
|
{
|
||||||
int i = 1;
|
int i = 1;
|
||||||
while ( i < argc)
|
while ( i < argc)
|
||||||
|
|
@ -564,13 +568,13 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
|
||||||
switch (cmdType)
|
switch (cmdType)
|
||||||
{
|
{
|
||||||
case CMD_INVALID:
|
case CMD_INVALID:
|
||||||
DMSG(0, "NormApp::ParseCommandLine() Invalid command:%s\n",
|
DMSG(0, "NormApp::ProcessCommands() Invalid command:%s\n",
|
||||||
argv[i]);
|
argv[i]);
|
||||||
return false;
|
return false;
|
||||||
case CMD_NOARG:
|
case CMD_NOARG:
|
||||||
if (!ProcessCommand(argv[i], NULL))
|
if (!ProcessCommand(argv[i], NULL))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::ParseCommandLine() ProcessCommand(%s) error\n",
|
DMSG(0, "NormApp::ProcessCommands() ProcessCommand(%s) error\n",
|
||||||
argv[i]);
|
argv[i]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -579,7 +583,7 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
|
||||||
case CMD_ARG:
|
case CMD_ARG:
|
||||||
if (!ProcessCommand(argv[i], argv[i+1]))
|
if (!ProcessCommand(argv[i], argv[i+1]))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormApp::ParseCommandLine() ProcessCommand(%s, %s) error\n",
|
DMSG(0, "NormApp::ProcessCommands() ProcessCommand(%s, %s) error\n",
|
||||||
argv[i], argv[i+1]);
|
argv[i], argv[i+1]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -588,10 +592,10 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} // end NormApp::ParseCommandLine()
|
} // end NormApp::ProcessCommands()
|
||||||
|
|
||||||
void NormApp::DoInputReady(EventDispatcher::Descriptor /*descriptor*/,
|
void NormApp::DoInputReady(ProtoDispatcher::Descriptor /*descriptor*/,
|
||||||
EventDispatcher::EventType /*theEvent*/,
|
ProtoDispatcher::Event /*theEvent*/,
|
||||||
const void* userData)
|
const void* userData)
|
||||||
{
|
{
|
||||||
((NormApp*)userData)->OnInputReady();
|
((NormApp*)userData)->OnInputReady();
|
||||||
|
|
@ -607,6 +611,8 @@ void NormApp::OnInputReady()
|
||||||
// the stream has buffer space for input
|
// the stream has buffer space for input
|
||||||
while (input)
|
while (input)
|
||||||
{
|
{
|
||||||
|
bool inputStarved = false;
|
||||||
|
|
||||||
if (0 == input_length)
|
if (0 == input_length)
|
||||||
{
|
{
|
||||||
// We need input ...
|
// We need input ...
|
||||||
|
|
@ -667,7 +673,11 @@ void NormApp::OnInputReady()
|
||||||
DMSG(0, "norm: input end-of-file.\n");
|
DMSG(0, "norm: input end-of-file.\n");
|
||||||
if (input_active)
|
if (input_active)
|
||||||
{
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
ASSERT(0); // no Win32 support for stream i/o yet
|
||||||
|
#else
|
||||||
dispatcher.RemoveGenericInput(fileno(input));
|
dispatcher.RemoveGenericInput(fileno(input));
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
input_active = false;
|
input_active = false;
|
||||||
}
|
}
|
||||||
if (stdin != input) fclose(input);
|
if (stdin != input) fclose(input);
|
||||||
|
|
@ -679,8 +689,10 @@ void NormApp::OnInputReady()
|
||||||
switch (errno)
|
switch (errno)
|
||||||
{
|
{
|
||||||
case EINTR:
|
case EINTR:
|
||||||
|
continue;
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
// Input not ready, will get notification when ready
|
// Input not ready, will get notification when ready
|
||||||
|
inputStarved = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DMSG(0, "norm: input error:%s\n", strerror(errno));
|
DMSG(0, "norm: input error:%s\n", strerror(errno));
|
||||||
|
|
@ -716,30 +728,37 @@ void NormApp::OnInputReady()
|
||||||
{
|
{
|
||||||
// Stream buffer full, temporarily deactive "input" and
|
// Stream buffer full, temporarily deactive "input" and
|
||||||
// wait for next TX_QUEUE_EMPTY notification
|
// wait for next TX_QUEUE_EMPTY notification
|
||||||
//TRACE("stream buffer full ...\n");
|
|
||||||
if (input_active)
|
if (input_active)
|
||||||
{
|
{
|
||||||
dispatcher.RemoveGenericInput(fileno(input));
|
#ifdef WIN32
|
||||||
|
ASSERT(0); // no Win32 support for stream i/o yet
|
||||||
|
#else
|
||||||
|
dispatcher.RemoveGenericInput(fileno(input));
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
input_active = false;
|
input_active = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (inputStarved)
|
||||||
{
|
{
|
||||||
// Input not ready, wait for "input" to be ready
|
// Input not ready, wait for "input" to be ready
|
||||||
// (Activate/reactivate "input" as necessary
|
// (Activate/reactivate "input" as necessary
|
||||||
//TRACE("input starved ...\n");
|
|
||||||
if (!input_active)
|
if (!input_active)
|
||||||
{
|
{
|
||||||
if (dispatcher.AddGenericInput(fileno(input), NormApp::DoInputReady, this))
|
#ifdef WIN32
|
||||||
|
ASSERT(0); // no Win32 support for stream i/o yet
|
||||||
|
if (false)
|
||||||
|
#else
|
||||||
|
if (dispatcher.InstallGenericInput(fileno(input), NormApp::DoInputReady, this))
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
input_active = true;
|
input_active = true;
|
||||||
else
|
else
|
||||||
DMSG(0, "NormApp::Notify(TX_QUEUE_EMPTY) error adding input notification!\n");
|
DMSG(0, "NormApp::Notify(TX_QUEUE_EMPTY) error adding input notification!\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // end while (1)
|
} // end while (input)
|
||||||
} // NormApp::OnInputReady()
|
} // NormApp::OnInputReady()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -762,14 +781,10 @@ void NormApp::Notify(NormController::Event event,
|
||||||
{
|
{
|
||||||
// Can queue a new object for transmission
|
// Can queue a new object for transmission
|
||||||
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
||||||
if (interval_timer.Interval() > 0.0)
|
if (interval_timer.GetInterval() > 0.0)
|
||||||
{
|
ActivateTimer(interval_timer);
|
||||||
InstallTimer(&interval_timer);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
OnIntervalTimeout(interval_timer);
|
||||||
OnIntervalTimeout();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -789,7 +804,7 @@ void NormApp::Notify(NormController::Event event,
|
||||||
// object Size() has recommended buffering size
|
// object Size() has recommended buffering size
|
||||||
NormObjectSize size;
|
NormObjectSize size;
|
||||||
if (silent_client)
|
if (silent_client)
|
||||||
size = NormObjectSize(rx_buffer_size);
|
size = NormObjectSize((UINT32)rx_buffer_size);
|
||||||
else
|
else
|
||||||
size = object->Size();
|
size = object->Size();
|
||||||
|
|
||||||
|
|
@ -863,7 +878,7 @@ void NormApp::Notify(NormController::Event event,
|
||||||
for (UINT16 i = pathLen; i < (pathLen+len); i++)
|
for (UINT16 i = pathLen; i < (pathLen+len); i++)
|
||||||
{
|
{
|
||||||
if ('/' == fileName[i])
|
if ('/' == fileName[i])
|
||||||
fileName[i] = DIR_DELIMITER;
|
fileName[i] = PROTO_PATH_DELIMITER;
|
||||||
}
|
}
|
||||||
pathLen += len;
|
pathLen += len;
|
||||||
if (pathLen < PATH_MAX) fileName[pathLen] = '\0';
|
if (pathLen < PATH_MAX) fileName[pathLen] = '\0';
|
||||||
|
|
@ -947,7 +962,8 @@ void NormApp::Notify(NormController::Event event,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
output_msg_sync = true;
|
if (readLength > 0)
|
||||||
|
output_msg_sync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readLength)
|
if (readLength)
|
||||||
|
|
@ -1015,15 +1031,16 @@ void NormApp::Notify(NormController::Event event,
|
||||||
|
|
||||||
case RX_OBJECT_COMPLETE:
|
case RX_OBJECT_COMPLETE:
|
||||||
{
|
{
|
||||||
|
//TRACE("NormApp::Notify(RX_OBJECT_COMPLETE) ...\n");
|
||||||
switch(object->GetType())
|
switch(object->GetType())
|
||||||
{
|
{
|
||||||
case NormObject::FILE:
|
case NormObject::FILE:
|
||||||
{
|
{
|
||||||
const char* filePath = ((NormFileObject*)object)->Path();
|
const char* filePath = ((NormFileObject*)object)->Path();
|
||||||
//DMSG(0, "norm: Completed rx file: %s\n", filePath);
|
//DMSG(0, "norm: Completed rx file: %s\n", filePath);
|
||||||
if (post_processor.IsEnabled())
|
if (post_processor->IsEnabled())
|
||||||
{
|
{
|
||||||
if (!post_processor.ProcessFile(filePath))
|
if (!post_processor->ProcessFile(filePath))
|
||||||
{
|
{
|
||||||
DMSG(0, "norm: post processing error\n");
|
DMSG(0, "norm: post processing error\n");
|
||||||
}
|
}
|
||||||
|
|
@ -1044,7 +1061,7 @@ void NormApp::Notify(NormController::Event event,
|
||||||
} // end NormApp::Notify()
|
} // end NormApp::Notify()
|
||||||
|
|
||||||
|
|
||||||
bool NormApp::OnIntervalTimeout()
|
bool NormApp::OnIntervalTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
char fileName[PATH_MAX];
|
char fileName[PATH_MAX];
|
||||||
if (tx_file_list.GetNextFile(fileName))
|
if (tx_file_list.GetNextFile(fileName))
|
||||||
|
|
@ -1063,7 +1080,7 @@ bool NormApp::OnIntervalTimeout()
|
||||||
// Normalize directory delimiters in file name info
|
// Normalize directory delimiters in file name info
|
||||||
for (unsigned int i = 0; i < len; i++)
|
for (unsigned int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (DIR_DELIMITER == fileNameInfo[i])
|
if (PROTO_PATH_DELIMITER == fileNameInfo[i])
|
||||||
fileNameInfo[i] = '/';
|
fileNameInfo[i] = '/';
|
||||||
}
|
}
|
||||||
char temp[PATH_MAX];
|
char temp[PATH_MAX];
|
||||||
|
|
@ -1076,7 +1093,7 @@ bool NormApp::OnIntervalTimeout()
|
||||||
// Wait a second, then try the next file in the list
|
// Wait a second, then try the next file in the list
|
||||||
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
||||||
interval_timer.SetInterval(1.0);
|
interval_timer.SetInterval(1.0);
|
||||||
InstallTimer(&interval_timer);
|
ActivateTimer(interval_timer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//DMSG(0, "norm: File \"%s\" queued for transmission.\n", fileName);
|
//DMSG(0, "norm: File \"%s\" queued for transmission.\n", fileName);
|
||||||
|
|
@ -1091,12 +1108,12 @@ bool NormApp::OnIntervalTimeout()
|
||||||
{
|
{
|
||||||
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
||||||
interval_timer.SetInterval(tx_repeat_interval = tx_object_interval);
|
interval_timer.SetInterval(tx_repeat_interval = tx_object_interval);
|
||||||
InstallTimer(&interval_timer);
|
ActivateTimer(interval_timer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return OnIntervalTimeout();
|
return OnIntervalTimeout(interval_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1106,20 +1123,25 @@ bool NormApp::OnIntervalTimeout()
|
||||||
return true;
|
return true;
|
||||||
} // end NormApp::OnIntervalTimeout()
|
} // end NormApp::OnIntervalTimeout()
|
||||||
|
|
||||||
bool NormApp::OnStartup()
|
bool NormApp::OnStartup(int argc, const char*const* argv)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
|
||||||
if (!dispatcher.Win32Init())
|
|
||||||
{
|
|
||||||
fprintf(stderr, "norm:: Win32Init() error!\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
signal(SIGTERM, SignalHandler);
|
|
||||||
signal(SIGINT, SignalHandler);
|
|
||||||
signal(SIGCHLD, SignalHandler);
|
|
||||||
|
|
||||||
|
if (!(post_processor = NormPostProcessor::Create()))
|
||||||
|
{
|
||||||
|
DMSG(0, "NormApp::OnStartup() error creating post processor\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ProcessCommands(argc, argv))
|
||||||
|
{
|
||||||
|
DMSG(0, "NormApp::OnStartup() error processing command-line commands\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
signal(SIGCHLD, SignalHandler);
|
||||||
|
#endif // UNIX
|
||||||
|
|
||||||
// Validate our application settings
|
// Validate our application settings
|
||||||
if (!address)
|
if (!address)
|
||||||
{
|
{
|
||||||
|
|
@ -1200,7 +1222,11 @@ void NormApp::OnShutdown()
|
||||||
{
|
{
|
||||||
if (input_active)
|
if (input_active)
|
||||||
{
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
ASSERT(0); // no Win32 support for stream i/o yet
|
||||||
|
#else
|
||||||
dispatcher.RemoveGenericInput(fileno(input));
|
dispatcher.RemoveGenericInput(fileno(input));
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
input_active = false;
|
input_active = false;
|
||||||
}
|
}
|
||||||
if (stdin != input) fclose(input);
|
if (stdin != input) fclose(input);
|
||||||
|
|
@ -1211,97 +1237,32 @@ void NormApp::OnShutdown()
|
||||||
if (stdout != output) fclose(output);
|
if (stdout != output) fclose(output);
|
||||||
output = NULL;
|
output = NULL;
|
||||||
}
|
}
|
||||||
|
if (post_processor)
|
||||||
|
{
|
||||||
|
delete post_processor;
|
||||||
|
post_processor = NULL;
|
||||||
|
}
|
||||||
} // end NormApp::OnShutdown()
|
} // end NormApp::OnShutdown()
|
||||||
|
|
||||||
|
// Out application instance
|
||||||
|
PROTO_INSTANTIATE_APP(NormApp);
|
||||||
|
|
||||||
// Out application instance (global for SignalHandler)
|
#ifdef UNIX
|
||||||
NormApp theApp;
|
|
||||||
|
|
||||||
// Use "main()" for UNIX and WIN32 console apps,
|
|
||||||
// "WinMain()" for non-console WIN32
|
|
||||||
// (VC++ uses the "_CONSOLE_" macro to indicate build type)
|
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(_CONSOLE_)
|
|
||||||
int PASCAL WinMain(HINSTANCE instance, HINSTANCE prevInst, LPSTR cmdline, int cmdshow)
|
|
||||||
{
|
|
||||||
// (TBD) transform WinMain "cmdLine" to (argc, argv[]) values
|
|
||||||
int argc = 0;
|
|
||||||
char* argv[] = NULL;
|
|
||||||
#else
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
#ifdef WIN32
|
|
||||||
// Hack to determine if Win32 console application was launched
|
|
||||||
// independently or from a pre-existing console window
|
|
||||||
bool pauseForUser = false;
|
|
||||||
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
if (INVALID_HANDLE_VALUE != hConsoleOutput)
|
|
||||||
{
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
||||||
GetConsoleScreenBufferInfo(hConsoleOutput, &csbi);
|
|
||||||
pauseForUser = ((csbi.dwCursorPosition.X==0) && (csbi.dwCursorPosition.Y==0));
|
|
||||||
if ((csbi.dwSize.X<=0) || (csbi.dwSize.Y <= 0)) pauseForUser = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We're not a "console" application, so create one
|
|
||||||
// This could be commented out or made a command-line option
|
|
||||||
OpenDebugWindow();
|
|
||||||
pauseForUser = true;
|
|
||||||
}
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
int exitCode = 0;
|
|
||||||
if (theApp.ParseCommandLine(argc, argv))
|
|
||||||
{
|
|
||||||
if (theApp.OnStartup())
|
|
||||||
{
|
|
||||||
exitCode = theApp.MainLoop();
|
|
||||||
theApp.OnShutdown();
|
|
||||||
fprintf(stderr, "norm: Done.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "norm: Error initializing application!\n");
|
|
||||||
exitCode = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "norm: Error parsing command line!\n");
|
|
||||||
exitCode = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
// If Win32 console is going to disappear, pause for user before exiting
|
|
||||||
if (pauseForUser)
|
|
||||||
{
|
|
||||||
printf ("Program Finished - Hit <Enter> to exit");
|
|
||||||
getchar();
|
|
||||||
}
|
|
||||||
#endif // WIN32
|
|
||||||
return exitCode; // exitCode contains "signum" causing exit
|
|
||||||
} // end main();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void NormApp::SignalHandler(int sigNum)
|
void NormApp::SignalHandler(int sigNum)
|
||||||
{
|
{
|
||||||
switch(sigNum)
|
switch(sigNum)
|
||||||
{
|
{
|
||||||
case SIGTERM:
|
|
||||||
case SIGINT:
|
|
||||||
theApp.Stop(sigNum); // causes theApp's main loop to exit
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
if (theApp.IsPostProcessing()) theApp.HandleSIGCHLD();
|
{
|
||||||
|
NormApp* app = static_cast<NormApp*>(ProtoApp::GetApp());
|
||||||
|
if (app->post_processor) app->post_processor->OnDeath();
|
||||||
signal(SIGCHLD, SignalHandler);
|
signal(SIGCHLD, SignalHandler);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "norm: Unexpected signal: %d\n", sigNum);
|
fprintf(stderr, "norm: Unexpected signal: %d\n", sigNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // end NormApp::SignalHandler()
|
} // end NormApp::SignalHandler()
|
||||||
|
#endif // UNIX
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef _NORM_BITMASK_
|
#ifndef _NORM_BITMASK_
|
||||||
#define _NORM_BITMASK_
|
#define _NORM_BITMASK_
|
||||||
|
|
||||||
#include "debug.h" // for PROTO_DEBUG stuff
|
#include "protokit.h" // for PROTO_DEBUG stuff
|
||||||
|
|
||||||
#include <string.h> // for memset()
|
#include <string.h> // for memset()
|
||||||
#include <stdio.h> // for fprintf()
|
#include <stdio.h> // for fprintf()
|
||||||
|
|
||||||
|
|
@ -183,7 +184,6 @@ class NormSlidingMask
|
||||||
long start;
|
long start;
|
||||||
long end;
|
long end;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
unsigned char* mask2;
|
|
||||||
}; // end class NormSlidingMask
|
}; // end class NormSlidingMask
|
||||||
|
|
||||||
#endif // _NORM_BITMASK_
|
#endif // _NORM_BITMASK_
|
||||||
|
|
|
||||||
|
|
@ -146,13 +146,14 @@ bool NormEncoder::CreateGeneratorPolynomial()
|
||||||
for (int i = 0; i < degree; i++)
|
for (int i = 0; i < degree; i++)
|
||||||
{
|
{
|
||||||
memset(&tp2[degree], 0, degree*sizeof(unsigned char));
|
memset(&tp2[degree], 0, degree*sizeof(unsigned char));
|
||||||
|
int j;
|
||||||
// Scale tp2 by p1[i]
|
// Scale tp2 by p1[i]
|
||||||
for(int j=0; j<degree; j++) tp2[j]=gmult(tp1[j], tp[i]);
|
for(j=0; j<degree; j++) tp2[j]=gmult(tp1[j], tp[i]);
|
||||||
// Mult(shift) tp2 right by i
|
// Mult(shift) tp2 right by i
|
||||||
for (int j = (degree*2)-1; j >= i; j--) tp2[j] = tp2[j-i];
|
for (j = (degree*2)-1; j >= i; j--) tp2[j] = tp2[j-i];
|
||||||
memset(tp2, 0, i*sizeof(unsigned char));
|
memset(tp2, 0, i*sizeof(unsigned char));
|
||||||
// Add into partial product
|
// Add into partial product
|
||||||
for(int j=0; j < (npar+1); j++) genPoly[j] ^= tp2[j];
|
for(j=0; j < (npar+1); j++) genPoly[j] ^= tp2[j];
|
||||||
}
|
}
|
||||||
memcpy(tp1, genPoly, (npar+1)*sizeof(unsigned char));
|
memcpy(tp1, genPoly, (npar+1)*sizeof(unsigned char));
|
||||||
memset(&tp1[npar+1], 0, (2*degree)-(npar+1));
|
memset(&tp1[npar+1], 0, (2*degree)-(npar+1));
|
||||||
|
|
@ -343,7 +344,8 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
||||||
int vecSize = vector_size;
|
int vecSize = vector_size;
|
||||||
#endif // if/else SIMUATE
|
#endif // if/else SIMUATE
|
||||||
|
|
||||||
for (int i = 0; i < npar; i++)
|
int i;
|
||||||
|
for (i = 0; i < npar; i++)
|
||||||
{
|
{
|
||||||
int X = gexp(i+1);
|
int X = gexp(i+1);
|
||||||
unsigned char* synVec = sVec[i];
|
unsigned char* synVec = sVec[i];
|
||||||
|
|
@ -365,7 +367,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
||||||
int nvecsMinusOne = nvecs - 1;
|
int nvecsMinusOne = nvecs - 1;
|
||||||
memset(Lambda, 0, degree*sizeof(char));
|
memset(Lambda, 0, degree*sizeof(char));
|
||||||
Lambda[0] = 1;
|
Lambda[0] = 1;
|
||||||
for (int i = 0; i < erasureCount; i++)
|
for (i = 0; i < erasureCount; i++)
|
||||||
{
|
{
|
||||||
int X = gexp(nvecsMinusOne - erasureLocs[i]);
|
int X = gexp(nvecsMinusOne - erasureLocs[i]);
|
||||||
for(int j = (degree-1); j > 0; j--)
|
for(int j = (degree-1); j > 0; j--)
|
||||||
|
|
@ -373,7 +375,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
||||||
}
|
}
|
||||||
|
|
||||||
// (C) Compute modified Omega using Lambda
|
// (C) Compute modified Omega using Lambda
|
||||||
for(int i = 0; i < npar; i++)
|
for(i = 0; i < npar; i++)
|
||||||
{
|
{
|
||||||
int k = i;
|
int k = i;
|
||||||
memset(oVec[i], 0, vecSize*sizeof(char));
|
memset(oVec[i], 0, vecSize*sizeof(char));
|
||||||
|
|
@ -389,7 +391,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
||||||
}
|
}
|
||||||
|
|
||||||
// (D) Finally, fill in the erasures
|
// (D) Finally, fill in the erasures
|
||||||
for (int i = 0; i < erasureCount; i++)
|
for (i = 0; i < erasureCount; i++)
|
||||||
{
|
{
|
||||||
// Only fill _data_ erasures
|
// Only fill _data_ erasures
|
||||||
if (erasureLocs[i] >= ndata) break;//return erasureCount;
|
if (erasureLocs[i] >= ndata) break;//return erasureCount;
|
||||||
|
|
@ -398,14 +400,15 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
||||||
// ( all odd powers disappear)
|
// ( all odd powers disappear)
|
||||||
int k = nvecsMinusOne - erasureLocs[i];
|
int k = nvecsMinusOne - erasureLocs[i];
|
||||||
int denom = 0;
|
int denom = 0;
|
||||||
for (int j = 1; j < degree; j += 2)
|
int j;
|
||||||
|
for (j = 1; j < degree; j += 2)
|
||||||
denom ^= gmult(Lambda[j], gexp(((255-k)*(j-1)) % 255));
|
denom ^= gmult(Lambda[j], gexp(((255-k)*(j-1)) % 255));
|
||||||
// Invert for use computing errror value below
|
// Invert for use computing errror value below
|
||||||
denom = ginv(denom);
|
denom = ginv(denom);
|
||||||
|
|
||||||
// Now evaluate Omega at alpha^(-i) (numerator)
|
// Now evaluate Omega at alpha^(-i) (numerator)
|
||||||
unsigned char* eVec = (unsigned char*)dVec[erasureLocs[i]];
|
unsigned char* eVec = (unsigned char*)dVec[erasureLocs[i]];
|
||||||
for (int j = 0; j < npar; j++)
|
for (j = 0; j < npar; j++)
|
||||||
{
|
{
|
||||||
unsigned char* data = eVec;
|
unsigned char* data = eVec;
|
||||||
unsigned char* Omega = oVec[j];
|
unsigned char* Omega = oVec[j];
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
#ifndef _NORM_ENCODER
|
#ifndef _NORM_ENCODER
|
||||||
#define _NORM_ENCODER
|
#define _NORM_ENCODER
|
||||||
|
|
||||||
#include "sysdefs.h" // protolib stuff
|
#include "protokit.h" // protolib stuff
|
||||||
|
|
||||||
class NormEncoder
|
class NormEncoder
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <string.h> // for strerror()
|
#include <string.h> // for strerror()
|
||||||
#include <errno.h> // for errno
|
#include <errno.h> // for errno
|
||||||
|
#include <stdio.h> // for rename()
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <share.h>
|
#include <share.h>
|
||||||
|
|
@ -34,14 +34,14 @@ bool NormFile::Open(const char* thePath, int theFlags)
|
||||||
// Create sub-directories as needed.
|
// Create sub-directories as needed.
|
||||||
char tempPath[PATH_MAX];
|
char tempPath[PATH_MAX];
|
||||||
strncpy(tempPath, thePath, PATH_MAX);
|
strncpy(tempPath, thePath, PATH_MAX);
|
||||||
char* ptr = strrchr(tempPath, DIR_DELIMITER);
|
char* ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||||
if (ptr) *ptr = '\0';
|
if (ptr) *ptr = '\0';
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
while (!NormFile::Exists(tempPath))
|
while (!NormFile::Exists(tempPath))
|
||||||
{
|
{
|
||||||
char* ptr2 = ptr;
|
char* ptr2 = ptr;
|
||||||
ptr = strrchr(tempPath, DIR_DELIMITER);
|
ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||||
if (ptr2) *ptr2 = DIR_DELIMITER;
|
if (ptr2) *ptr2 = PROTO_PATH_DELIMITER;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
@ -52,18 +52,22 @@ bool NormFile::Open(const char* thePath, int theFlags)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ptr && ('\0' == *ptr)) *ptr++ = DIR_DELIMITER;
|
if (ptr && ('\0' == *ptr)) *ptr++ = PROTO_PATH_DELIMITER;
|
||||||
while (ptr)
|
while (ptr)
|
||||||
{
|
{
|
||||||
ptr = strchr(ptr, DIR_DELIMITER);
|
ptr = strchr(ptr, PROTO_PATH_DELIMITER);
|
||||||
if (ptr) *ptr = '\0';
|
if (ptr) *ptr = '\0';
|
||||||
|
#ifdef WIN32
|
||||||
|
if (mkdir(tempPath))
|
||||||
|
#else
|
||||||
if (mkdir(tempPath, 0755))
|
if (mkdir(tempPath, 0755))
|
||||||
|
#endif // if/else WIN32/UNIX
|
||||||
{
|
{
|
||||||
DMSG(0, "NormFile::Rename() mkdir(%s) error: %s\n",
|
DMSG(0, "NormFile::Rename() mkdir(%s) error: %s\n",
|
||||||
tempPath, strerror(errno));
|
tempPath, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ptr) *ptr++ = DIR_DELIMITER;
|
if (ptr) *ptr++ = PROTO_PATH_DELIMITER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
@ -82,8 +86,7 @@ bool NormFile::Open(const char* thePath, int theFlags)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMSG(0, "Error opening file \"%s\": %s\n", path,
|
DMSG(0, "Error opening file \"%s\": %s\n", thePath, strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +162,7 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
||||||
if (NormFile::IsLocked(newName)) return false;
|
if (NormFile::IsLocked(newName)) return false;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// In Win32, the new file can't already exist
|
// In Win32, the new file can't already exist
|
||||||
if (NormFile::Exists(newName) _unlink(newName);
|
if (NormFile::Exists(newName)) _unlink(newName);
|
||||||
// In Win32, the old file can't be open
|
// In Win32, the old file can't be open
|
||||||
int oldFlags = 0;
|
int oldFlags = 0;
|
||||||
if (IsOpen())
|
if (IsOpen())
|
||||||
|
|
@ -172,14 +175,14 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
||||||
// Create sub-directories as needed.
|
// Create sub-directories as needed.
|
||||||
char tempPath[PATH_MAX];
|
char tempPath[PATH_MAX];
|
||||||
strncpy(tempPath, newName, PATH_MAX);
|
strncpy(tempPath, newName, PATH_MAX);
|
||||||
char* ptr = strrchr(tempPath, DIR_DELIMITER);
|
char* ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||||
if (ptr) *ptr = '\0';
|
if (ptr) *ptr = '\0';
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
while (!NormFile::Exists(tempPath))
|
while (!NormFile::Exists(tempPath))
|
||||||
{
|
{
|
||||||
char* ptr2 = ptr;
|
char* ptr2 = ptr;
|
||||||
ptr = strrchr(tempPath, DIR_DELIMITER);
|
ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||||
if (ptr2) *ptr2 = DIR_DELIMITER;
|
if (ptr2) *ptr2 = PROTO_PATH_DELIMITER;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
@ -190,10 +193,10 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ptr && ('\0' == *ptr)) *ptr++ = DIR_DELIMITER;
|
if (ptr && ('\0' == *ptr)) *ptr++ = PROTO_PATH_DELIMITER;
|
||||||
while (ptr)
|
while (ptr)
|
||||||
{
|
{
|
||||||
ptr = strchr(ptr, DIR_DELIMITER);
|
ptr = strchr(ptr, PROTO_PATH_DELIMITER);
|
||||||
if (ptr) *ptr = '\0';
|
if (ptr) *ptr = '\0';
|
||||||
if (mkdir(tempPath, 0755))
|
if (mkdir(tempPath, 0755))
|
||||||
{
|
{
|
||||||
|
|
@ -201,7 +204,7 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
||||||
tempPath, strerror(errno));
|
tempPath, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ptr) *ptr++ = DIR_DELIMITER;
|
if (ptr) *ptr++ = PROTO_PATH_DELIMITER;
|
||||||
}
|
}
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
if (rename(oldName, newName))
|
if (rename(oldName, newName))
|
||||||
|
|
@ -367,7 +370,7 @@ bool NormDirectoryIterator::GetNextFile(char* fileName)
|
||||||
bool success = true;
|
bool success = true;
|
||||||
while(success)
|
while(success)
|
||||||
{
|
{
|
||||||
WIN32_findData findData;
|
WIN32_FIND_DATA findData;
|
||||||
if (current->hSearch == (HANDLE)-1)
|
if (current->hSearch == (HANDLE)-1)
|
||||||
{
|
{
|
||||||
// Construct search string
|
// Construct search string
|
||||||
|
|
@ -387,7 +390,7 @@ bool NormDirectoryIterator::GetNextFile(char* fileName)
|
||||||
// Do we have a candidate file?
|
// Do we have a candidate file?
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
char* ptr = strrchr(findData.cFileName, DIR_DELIMITER);
|
char* ptr = strrchr(findData.cFileName, PROTO_PATH_DELIMITER);
|
||||||
if (ptr)
|
if (ptr)
|
||||||
ptr += 1;
|
ptr += 1;
|
||||||
else
|
else
|
||||||
|
|
@ -535,9 +538,9 @@ NormDirectoryIterator::NormDirectory::NormDirectory(const char* thePath,
|
||||||
{
|
{
|
||||||
strncpy(path, thePath, PATH_MAX);
|
strncpy(path, thePath, PATH_MAX);
|
||||||
int len = MIN(PATH_MAX, strlen(path));
|
int len = MIN(PATH_MAX, strlen(path));
|
||||||
if ((len < PATH_MAX) && (DIR_DELIMITER != path[len-1]))
|
if ((len < PATH_MAX) && (PROTO_PATH_DELIMITER != path[len-1]))
|
||||||
{
|
{
|
||||||
path[len++] = DIR_DELIMITER;
|
path[len++] = PROTO_PATH_DELIMITER;
|
||||||
if (len < PATH_MAX) path[len] = '\0';
|
if (len < PATH_MAX) path[len] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -551,10 +554,10 @@ bool NormDirectoryIterator::NormDirectory::Open()
|
||||||
{
|
{
|
||||||
Close(); // in case it's already open
|
Close(); // in case it's already open
|
||||||
char fullName[PATH_MAX];
|
char fullName[PATH_MAX];
|
||||||
GetFullName(fullName);
|
GetFullName(fullName);
|
||||||
// Get rid of trailing DIR_DELIMITER
|
// Get rid of trailing PROTO_PATH_DELIMITER
|
||||||
int len = MIN(PATH_MAX, strlen(fullName));
|
int len = MIN(PATH_MAX, strlen(fullName));
|
||||||
if (DIR_DELIMITER == fullName[len-1]) fullName[len-1] = '\0';
|
if (PROTO_PATH_DELIMITER == fullName[len-1]) fullName[len-1] = '\0';
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
DWORD attr = GetFileAttributes(fullName);
|
DWORD attr = GetFileAttributes(fullName);
|
||||||
if (0xFFFFFFFF == attr)
|
if (0xFFFFFFFF == attr)
|
||||||
|
|
@ -581,8 +584,11 @@ void NormDirectoryIterator::NormDirectory::Close()
|
||||||
hSearch = (HANDLE)-1;
|
hSearch = (HANDLE)-1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
closedir(dptr);
|
if (dptr)
|
||||||
dptr = NULL;
|
{
|
||||||
|
closedir(dptr);
|
||||||
|
dptr = NULL;
|
||||||
|
}
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
} // end NormDirectoryIterator::NormDirectory::Close()
|
} // end NormDirectoryIterator::NormDirectory::Close()
|
||||||
|
|
||||||
|
|
@ -856,15 +862,15 @@ void NormFileList::GetCurrentBasePath(char* pathBuffer)
|
||||||
strncpy(pathBuffer, next->Path(), PATH_MAX);
|
strncpy(pathBuffer, next->Path(), PATH_MAX);
|
||||||
unsigned int len = strlen(pathBuffer);
|
unsigned int len = strlen(pathBuffer);
|
||||||
len = MIN(len, PATH_MAX);
|
len = MIN(len, PATH_MAX);
|
||||||
if (DIR_DELIMITER != pathBuffer[len-1])
|
if (PROTO_PATH_DELIMITER != pathBuffer[len-1])
|
||||||
{
|
{
|
||||||
if (len < PATH_MAX) pathBuffer[len++] = DIR_DELIMITER;
|
if (len < PATH_MAX) pathBuffer[len++] = PROTO_PATH_DELIMITER;
|
||||||
if (len < PATH_MAX) pathBuffer[len] = '\0';
|
if (len < PATH_MAX) pathBuffer[len] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // NormFile::NORMAL
|
else // NormFile::NORMAL
|
||||||
{
|
{
|
||||||
const char* ptr = strrchr(next->Path(), DIR_DELIMITER);
|
const char* ptr = strrchr(next->Path(), PROTO_PATH_DELIMITER);
|
||||||
if (ptr++)
|
if (ptr++)
|
||||||
{
|
{
|
||||||
unsigned int len = ptr - next->Path();
|
unsigned int len = ptr - next->Path();
|
||||||
|
|
@ -925,6 +931,7 @@ bool NormFileList::FileItem::GetNextFile(char* thePath,
|
||||||
NormFileList::DirectoryItem::DirectoryItem(const char* thePath)
|
NormFileList::DirectoryItem::DirectoryItem(const char* thePath)
|
||||||
: NormFileList::FileItem(thePath)
|
: NormFileList::FileItem(thePath)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NormFileList::DirectoryItem::~DirectoryItem()
|
NormFileList::DirectoryItem::~DirectoryItem()
|
||||||
|
|
@ -963,9 +970,9 @@ bool NormFileList::DirectoryItem::GetNextFile(char* thePath,
|
||||||
strncpy(thePath, path, PATH_MAX);
|
strncpy(thePath, path, PATH_MAX);
|
||||||
unsigned int len = strlen(thePath);
|
unsigned int len = strlen(thePath);
|
||||||
len = MIN(len, PATH_MAX);
|
len = MIN(len, PATH_MAX);
|
||||||
if ((DIR_DELIMITER != thePath[len-1]) && (len < PATH_MAX))
|
if ((PROTO_PATH_DELIMITER != thePath[len-1]) && (len < PATH_MAX))
|
||||||
{
|
{
|
||||||
thePath[len++] = DIR_DELIMITER;
|
thePath[len++] = PROTO_PATH_DELIMITER;
|
||||||
if (len < PATH_MAX) thePath[len] = '\0';
|
if (len < PATH_MAX) thePath[len] = '\0';
|
||||||
}
|
}
|
||||||
char tempPath[PATH_MAX];
|
char tempPath[PATH_MAX];
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
// From PROTOLIB
|
// From PROTOLIB
|
||||||
#include "sysdefs.h" // for bool definition, DIR_DELIMITER, PATH_MAX, etc
|
#include "protokit.h" // for Protolib stuff
|
||||||
#include "debug.h" // for DEBUG stuff
|
|
||||||
|
|
||||||
class NormFile
|
class NormFile
|
||||||
{
|
{
|
||||||
|
|
@ -61,11 +60,11 @@ class NormFile
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
DWORD attr = GetFileAttributes(path);
|
DWORD attr = GetFileAttributes(path);
|
||||||
return ((0xFFFFFFFF == attr) ?
|
return ((0xFFFFFFFF == attr) ?
|
||||||
false : (0 == (attr & FILE_ATTRIBUTE_READONLY)));
|
false : (0 == (attr & FILE_ATTRIBUTE_READONLY)));
|
||||||
#else
|
#else
|
||||||
return (0 == access(path, W_OK));
|
return (0 == access(path, W_OK));
|
||||||
}
|
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
|
|
@ -73,7 +72,9 @@ class NormFile
|
||||||
int fd;
|
int fd;
|
||||||
int flags;
|
int flags;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
};
|
}; // end class NormFile
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
* The NormDirectory and NormDirectoryIterator classes
|
* The NormDirectory and NormDirectoryIterator classes
|
||||||
|
|
@ -98,11 +99,11 @@ class NormDirectoryIterator
|
||||||
private:
|
private:
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
NormDirectory* parent;
|
NormDirectory* parent;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
HANDLE hSearch;
|
HANDLE hSearch;
|
||||||
#else
|
#else
|
||||||
DIR* dptr;
|
DIR* dptr;
|
||||||
#endif // if/else WIN32
|
#endif // if/else WIN32
|
||||||
NormDirectory(const char *thePath, NormDirectory* theParent = NULL);
|
NormDirectory(const char *thePath, NormDirectory* theParent = NULL);
|
||||||
~NormDirectory();
|
~NormDirectory();
|
||||||
void GetFullName(char* namePtr);
|
void GetFullName(char* namePtr);
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ bool NormRepairRequest::AppendRepairItem(const NormObjectId& objectId,
|
||||||
if (buffer_len >= (length+ITEM_LIST_OFFSET+RepairItemLength()))
|
if (buffer_len >= (length+ITEM_LIST_OFFSET+RepairItemLength()))
|
||||||
{
|
{
|
||||||
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
||||||
ptr[FEC_ID_OFFSET] = 129;
|
ptr[FEC_ID_OFFSET] = (char)129;
|
||||||
ptr[RESERVED_OFFSET] = 0;
|
ptr[RESERVED_OFFSET] = 0;
|
||||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
|
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
|
||||||
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId);
|
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId);
|
||||||
|
|
@ -181,7 +181,7 @@ bool NormRepairRequest::AppendRepairRange(const NormObjectId& startObjectId,
|
||||||
{
|
{
|
||||||
// range start
|
// range start
|
||||||
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
||||||
ptr[FEC_ID_OFFSET] = 129;
|
ptr[FEC_ID_OFFSET] = (char)129;
|
||||||
ptr[RESERVED_OFFSET] = 0;
|
ptr[RESERVED_OFFSET] = 0;
|
||||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)startObjectId);
|
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)startObjectId);
|
||||||
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)startBlockId);
|
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)startBlockId);
|
||||||
|
|
@ -189,7 +189,7 @@ bool NormRepairRequest::AppendRepairRange(const NormObjectId& startObjectId,
|
||||||
*((UINT16*)(ptr+SYMBOL_ID_OFFSET)) = htons((UINT16)startSymbolId);
|
*((UINT16*)(ptr+SYMBOL_ID_OFFSET)) = htons((UINT16)startSymbolId);
|
||||||
ptr += RepairItemLength();
|
ptr += RepairItemLength();
|
||||||
// range end
|
// range end
|
||||||
ptr[FEC_ID_OFFSET] = 129;
|
ptr[FEC_ID_OFFSET] = (char)129;
|
||||||
ptr[RESERVED_OFFSET] = 0;
|
ptr[RESERVED_OFFSET] = 0;
|
||||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)endObjectId);
|
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)endObjectId);
|
||||||
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)endBlockId);
|
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)endBlockId);
|
||||||
|
|
@ -212,7 +212,7 @@ bool NormRepairRequest::AppendErasureCount(const NormObjectId& objectId,
|
||||||
if (buffer_len >= (ITEM_LIST_OFFSET+length+ErasureItemLength()))
|
if (buffer_len >= (ITEM_LIST_OFFSET+length+ErasureItemLength()))
|
||||||
{
|
{
|
||||||
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
||||||
ptr[FEC_ID_OFFSET] = 129;
|
ptr[FEC_ID_OFFSET] = (char)129;
|
||||||
ptr[RESERVED_OFFSET] = 0;
|
ptr[RESERVED_OFFSET] = 0;
|
||||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
|
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
|
||||||
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId);
|
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId);
|
||||||
|
|
@ -425,8 +425,6 @@ unsigned char NormQuantizeRtt(double rtt)
|
||||||
return ((unsigned char)(ceil(255.0 - (13.0*log(NORM_RTT_MAX/rtt)))));
|
return ((unsigned char)(ceil(255.0 - (13.0*log(NORM_RTT_MAX/rtt)))));
|
||||||
} // end NormQuantizeRtt()
|
} // end NormQuantizeRtt()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool NormObjectSize::operator<(const NormObjectSize& size) const
|
bool NormObjectSize::operator<(const NormObjectSize& size) const
|
||||||
{
|
{
|
||||||
UINT16 diff = msb - size.msb;
|
UINT16 diff = msb - size.msb;
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,12 @@
|
||||||
#define _NORM_MESSAGE
|
#define _NORM_MESSAGE
|
||||||
|
|
||||||
// PROTOLIB includes
|
// PROTOLIB includes
|
||||||
#include "networkAddress.h" // for NetworkAddress class
|
#include "protokit.h"
|
||||||
#include "sysdefs.h" // for UINT typedefs
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
// standard includes
|
// standard includes
|
||||||
#include <string.h> // for memcpy(), etc
|
#include <string.h> // for memcpy(), etc
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdlib.h> // for rand(), etc
|
||||||
|
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
#define SIM_PAYLOAD_MAX 36 // MGEN message size
|
#define SIM_PAYLOAD_MAX 36 // MGEN message size
|
||||||
|
|
@ -22,6 +20,22 @@ const UINT8 NORM_PROTOCOL_VERSION = 1;
|
||||||
|
|
||||||
const int NORM_ROBUST_FACTOR = 20; // default robust factor
|
const int NORM_ROBUST_FACTOR = 20; // default robust factor
|
||||||
|
|
||||||
|
|
||||||
|
// Pick a random number from 0..max
|
||||||
|
inline double UniformRand(double max)
|
||||||
|
{
|
||||||
|
return (max * ((double)rand() / (double)RAND_MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick a random number from 0..max
|
||||||
|
// (truncated exponential dist. lambda = log(groupSize) + 1)
|
||||||
|
inline double ExponentialRand(double max, double groupSize)
|
||||||
|
{
|
||||||
|
double lambda = log(groupSize) + 1;
|
||||||
|
double x = UniformRand(lambda/max)+lambda/(max*(exp(lambda)-1));
|
||||||
|
return ((max/lambda)*log(x*(exp(lambda)-1)*(max/lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
// These are the GRTT estimation bounds set for the current
|
// These are the GRTT estimation bounds set for the current
|
||||||
// NORM protocol. (Note that our Grtt quantization routines
|
// NORM protocol. (Note that our Grtt quantization routines
|
||||||
// are good for the range of 1.0e-06 <= 1000.0)
|
// are good for the range of 1.0e-06 <= 1000.0)
|
||||||
|
|
@ -39,13 +53,20 @@ unsigned char NormQuantizeRtt(double rtt);
|
||||||
|
|
||||||
inline double NormUnquantizeGroupSize(unsigned char gsize)
|
inline double NormUnquantizeGroupSize(unsigned char gsize)
|
||||||
{
|
{
|
||||||
return ((double)(gsize >> 4) * pow(10.0, (double)(gsize & 0x0f)));
|
double exponent = (double)((gsize & 0x07) + 1);
|
||||||
|
double mantissa = (0 != (gsize & 0x08)) ? 5.0 : 1.0;
|
||||||
|
return (mantissa * pow(10.0, exponent));
|
||||||
}
|
}
|
||||||
inline unsigned char NormQuantizeGroupSize(double gsize)
|
inline unsigned char NormQuantizeGroupSize(double gsize)
|
||||||
{
|
{
|
||||||
unsigned char exponent = (unsigned char)log10(gsize);
|
unsigned char ebits = (unsigned char)log10(gsize);
|
||||||
exponent = MIN(exponent, 0x0f);
|
int mantissa = (int)((gsize/pow(10.0, (double)ebits)) + 0.5);
|
||||||
return ((((unsigned char)(gsize / pow(10.0, (double)exponent) + 0.5)) << 4) | exponent);
|
// round up quantized group size
|
||||||
|
unsigned char mbit = (mantissa > 1) ? ((mantissa > 5) ? 0x00 : 0x08) : 0x00;
|
||||||
|
ebits = (mantissa > 5) ? ebits : ebits+1;
|
||||||
|
mbit = (ebits > 0x07) ? 0x08 : mbit;
|
||||||
|
ebits = (ebits > 0x07) ? 0x07 : ebits;
|
||||||
|
return (mbit | ebits);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned short NormQuantizeLoss(double lossFraction)
|
inline unsigned short NormQuantizeLoss(double lossFraction)
|
||||||
|
|
@ -62,8 +83,7 @@ inline double NormUnquantizeLoss(unsigned short lossQuantized)
|
||||||
|
|
||||||
inline unsigned short NormQuantizeRate(double rate)
|
inline unsigned short NormQuantizeRate(double rate)
|
||||||
{
|
{
|
||||||
unsigned char exponent = (unsigned short)log10(rate);
|
unsigned char exponent = (unsigned char)log10(rate);
|
||||||
exponent = MIN(exponent, 0xff);
|
|
||||||
unsigned short mantissa = (unsigned short)((256.0/10.0) * rate / pow(10.0, (double)exponent));
|
unsigned short mantissa = (unsigned short)((256.0/10.0) * rate / pow(10.0, (double)exponent));
|
||||||
return ((mantissa << 8) | exponent);
|
return ((mantissa << 8) | exponent);
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +108,11 @@ class NormObjectSize
|
||||||
UINT32 LSB() const {return lsb;}
|
UINT32 LSB() const {return lsb;}
|
||||||
|
|
||||||
bool operator<(const NormObjectSize& size) const;
|
bool operator<(const NormObjectSize& size) const;
|
||||||
|
bool operator<=(const NormObjectSize& size) const
|
||||||
|
{return ((*this == size) || (*this<size));}
|
||||||
bool operator>(const NormObjectSize& size) const;
|
bool operator>(const NormObjectSize& size) const;
|
||||||
|
bool operator>=(const NormObjectSize& size) const
|
||||||
|
{return ((*this == size) || (*this>size));}
|
||||||
bool operator==(const NormObjectSize& size) const
|
bool operator==(const NormObjectSize& size) const
|
||||||
{return ((msb == size.msb) && (lsb == size.lsb));}
|
{return ((msb == size.msb) && (lsb == size.lsb));}
|
||||||
bool operator!=(const NormObjectSize& size) const
|
bool operator!=(const NormObjectSize& size) const
|
||||||
|
|
@ -135,7 +159,11 @@ class NormObjectId
|
||||||
NormObjectId(const NormObjectId& id) {value = id.value;}
|
NormObjectId(const NormObjectId& id) {value = id.value;}
|
||||||
operator UINT16() const {return value;}
|
operator UINT16() const {return value;}
|
||||||
bool operator<(const NormObjectId& id) const;
|
bool operator<(const NormObjectId& id) const;
|
||||||
|
bool operator<=(const NormObjectId& id) const
|
||||||
|
{return ((value == id.value) || (*this<id));}
|
||||||
bool operator>(const NormObjectId& id) const;
|
bool operator>(const NormObjectId& id) const;
|
||||||
|
bool operator>=(const NormObjectId& id) const
|
||||||
|
{return ((value == id.value) || (*this>id));}
|
||||||
bool operator==(const NormObjectId& id) const
|
bool operator==(const NormObjectId& id) const
|
||||||
{return (value == id.value);}
|
{return (value == id.value);}
|
||||||
bool operator!=(const NormObjectId& id) const
|
bool operator!=(const NormObjectId& id) const
|
||||||
|
|
@ -251,7 +279,7 @@ class NormMsg
|
||||||
{
|
{
|
||||||
*((UINT32*)(buffer+SOURCE_ID_OFFSET)) = htonl(sourceId);
|
*((UINT32*)(buffer+SOURCE_ID_OFFSET)) = htonl(sourceId);
|
||||||
}
|
}
|
||||||
void SetDestination(const NetworkAddress& dst) {addr = dst;}
|
void SetDestination(const ProtoAddress& dst) {addr = dst;}
|
||||||
|
|
||||||
void AttachExtension(NormHeaderExtension& extension)
|
void AttachExtension(NormHeaderExtension& extension)
|
||||||
{
|
{
|
||||||
|
|
@ -272,8 +300,8 @@ class NormMsg
|
||||||
{
|
{
|
||||||
return (ntohl(*((UINT32*)(buffer+SOURCE_ID_OFFSET))));
|
return (ntohl(*((UINT32*)(buffer+SOURCE_ID_OFFSET))));
|
||||||
}
|
}
|
||||||
const NetworkAddress& GetDestination() const {return addr;}
|
const ProtoAddress& GetDestination() const {return addr;}
|
||||||
const NetworkAddress& GetSource() const {return addr;}
|
const ProtoAddress& GetSource() const {return addr;}
|
||||||
const char* GetBuffer() {return buffer;}
|
const char* GetBuffer() {return buffer;}
|
||||||
UINT16 GetLength() const {return length;}
|
UINT16 GetLength() const {return length;}
|
||||||
|
|
||||||
|
|
@ -286,12 +314,11 @@ class NormMsg
|
||||||
bool result = (nextOffset < header_length);
|
bool result = (nextOffset < header_length);
|
||||||
ext.AttachBuffer(result ? (buffer+nextOffset) : NULL);
|
ext.AttachBuffer(result ? (buffer+nextOffset) : NULL);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// For message reception and misc.
|
// For message reception and misc.
|
||||||
char* AccessBuffer() {return buffer;}
|
char* AccessBuffer() {return buffer;}
|
||||||
NetworkAddress* AccessAddress() {return &addr;}
|
ProtoAddress& AccessAddress() {return addr;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Common message header offsets
|
// Common message header offsets
|
||||||
|
|
@ -321,7 +348,7 @@ class NormMsg
|
||||||
UINT16 length;
|
UINT16 length;
|
||||||
UINT16 header_length;
|
UINT16 header_length;
|
||||||
UINT16 header_length_base;
|
UINT16 header_length_base;
|
||||||
NetworkAddress addr; // src or dst address
|
ProtoAddress addr; // src or dst address
|
||||||
|
|
||||||
NormMsg* prev;
|
NormMsg* prev;
|
||||||
NormMsg* next;
|
NormMsg* next;
|
||||||
|
|
@ -349,7 +376,8 @@ class NormObjectMsg : public NormMsg
|
||||||
return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET))));
|
return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET))));
|
||||||
}
|
}
|
||||||
UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];}
|
UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];}
|
||||||
UINT8 GetGroupSize() const {return buffer[GSIZE_OFFSET];}
|
UINT8 GetBackoffFactor() const {return ((buffer[GSIZE_OFFSET] >> 4) & 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]));}
|
||||||
UINT8 GetFecId() const {return buffer[FEC_ID_OFFSET];}
|
UINT8 GetFecId() const {return buffer[FEC_ID_OFFSET];}
|
||||||
|
|
@ -364,7 +392,14 @@ class NormObjectMsg : public NormMsg
|
||||||
*((UINT16*)(buffer+SESSION_ID_OFFSET)) = htons(sessionId);
|
*((UINT16*)(buffer+SESSION_ID_OFFSET)) = htons(sessionId);
|
||||||
}
|
}
|
||||||
void SetGrtt(UINT8 grtt) {buffer[GRTT_OFFSET] = grtt;}
|
void SetGrtt(UINT8 grtt) {buffer[GRTT_OFFSET] = grtt;}
|
||||||
void SetGroupSize(UINT8 gsize) {buffer[GSIZE_OFFSET] = gsize;}
|
void SetBackoffFactor(UINT8 backoff)
|
||||||
|
{
|
||||||
|
buffer[BACKOFF_OFFSET] = (buffer[GSIZE_OFFSET] & 0x0f) | (backoff << 4);
|
||||||
|
}
|
||||||
|
void SetGroupSize(UINT8 gsize)
|
||||||
|
{
|
||||||
|
buffer[GSIZE_OFFSET] = (buffer[GSIZE_OFFSET] & 0xf0) | gsize;
|
||||||
|
}
|
||||||
void ResetFlags() {buffer[FLAGS_OFFSET] = 0;}
|
void ResetFlags() {buffer[FLAGS_OFFSET] = 0;}
|
||||||
void SetFlag(NormObjectMsg::Flag flag) {buffer[FLAGS_OFFSET] |= flag;}
|
void SetFlag(NormObjectMsg::Flag flag) {buffer[FLAGS_OFFSET] |= flag;}
|
||||||
void SetFecId(UINT8 fecId) {buffer[FEC_ID_OFFSET] = fecId;}
|
void SetFecId(UINT8 fecId) {buffer[FEC_ID_OFFSET] = fecId;}
|
||||||
|
|
@ -378,7 +413,8 @@ class NormObjectMsg : public NormMsg
|
||||||
{
|
{
|
||||||
SESSION_ID_OFFSET = MSG_OFFSET,
|
SESSION_ID_OFFSET = MSG_OFFSET,
|
||||||
GRTT_OFFSET = SESSION_ID_OFFSET + 2,
|
GRTT_OFFSET = SESSION_ID_OFFSET + 2,
|
||||||
GSIZE_OFFSET = GRTT_OFFSET + 1,
|
BACKOFF_OFFSET = GRTT_OFFSET + 1,
|
||||||
|
GSIZE_OFFSET = BACKOFF_OFFSET,
|
||||||
FLAGS_OFFSET = GSIZE_OFFSET + 1,
|
FLAGS_OFFSET = GSIZE_OFFSET + 1,
|
||||||
FEC_ID_OFFSET = FLAGS_OFFSET + 1,
|
FEC_ID_OFFSET = FLAGS_OFFSET + 1,
|
||||||
OBJ_ID_OFFSET = FEC_ID_OFFSET + 1,
|
OBJ_ID_OFFSET = FEC_ID_OFFSET + 1,
|
||||||
|
|
@ -448,11 +484,11 @@ class NormFtiExtension : public NormHeaderExtension
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
FEC_INSTANCE_OFFSET = LENGTH_OFFSET + 1,
|
OBJ_SIZE_OFFSET = LENGTH_OFFSET + 1,
|
||||||
FEC_NDATA_OFFSET = FEC_INSTANCE_OFFSET +2,
|
FEC_INSTANCE_OFFSET = OBJ_SIZE_OFFSET + 6,
|
||||||
FEC_NPARITY_OFFSET = FEC_NDATA_OFFSET + 2,
|
SEG_SIZE_OFFSET = FEC_INSTANCE_OFFSET +2,
|
||||||
SEG_SIZE_OFFSET = FEC_NPARITY_OFFSET+2,
|
FEC_NDATA_OFFSET = SEG_SIZE_OFFSET + 2,
|
||||||
OBJ_SIZE_OFFSET = SEG_SIZE_OFFSET + 2
|
FEC_NPARITY_OFFSET = FEC_NDATA_OFFSET + 2
|
||||||
};
|
};
|
||||||
}; // end class NormFtiExtension
|
}; // end class NormFtiExtension
|
||||||
|
|
||||||
|
|
@ -617,23 +653,32 @@ class NormCmdMsg : public NormMsg
|
||||||
}
|
}
|
||||||
void SetGrtt(UINT8 quantizedGrtt)
|
void SetGrtt(UINT8 quantizedGrtt)
|
||||||
{buffer[GRTT_OFFSET] = quantizedGrtt;}
|
{buffer[GRTT_OFFSET] = quantizedGrtt;}
|
||||||
void SetGroupSize(UINT8 quantizedGroupSize)
|
void SetBackoffFactor(UINT8 backoff)
|
||||||
{buffer[GSIZE_OFFSET] = quantizedGroupSize;}
|
{
|
||||||
|
buffer[BACKOFF_OFFSET] = (buffer[GSIZE_OFFSET] & 0x0f) | (backoff << 4);
|
||||||
|
}
|
||||||
|
void SetGroupSize(UINT8 gsize)
|
||||||
|
{
|
||||||
|
buffer[GSIZE_OFFSET] = (buffer[GSIZE_OFFSET] & 0xf0) | gsize;
|
||||||
|
}
|
||||||
void SetFlavor(NormCmdMsg::Flavor flavor)
|
void SetFlavor(NormCmdMsg::Flavor flavor)
|
||||||
{buffer[FLAVOR_OFFSET] = flavor;}
|
{buffer[FLAVOR_OFFSET] = flavor;}
|
||||||
|
|
||||||
// Message processing
|
// Message processing
|
||||||
UINT16 GetSessionId() const {return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET))));}
|
UINT16 GetSessionId() const {return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET))));}
|
||||||
UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];}
|
UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];}
|
||||||
UINT8 GetGroupSize() const {return buffer[GSIZE_OFFSET];}
|
UINT8 GetBackoffFactor() const {return ((buffer[GSIZE_OFFSET] >> 4) & 0x0f);}
|
||||||
|
UINT8 GetGroupSize() const {return (buffer[GSIZE_OFFSET] & 0x0f);}
|
||||||
NormCmdMsg::Flavor GetFlavor() const {return (Flavor)buffer[FLAVOR_OFFSET];}
|
NormCmdMsg::Flavor GetFlavor() const {return (Flavor)buffer[FLAVOR_OFFSET];}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend class NormMsg;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SESSION_ID_OFFSET = MSG_OFFSET,
|
SESSION_ID_OFFSET = MSG_OFFSET,
|
||||||
GRTT_OFFSET = SESSION_ID_OFFSET + 2,
|
GRTT_OFFSET = SESSION_ID_OFFSET + 2,
|
||||||
GSIZE_OFFSET = GRTT_OFFSET + 1,
|
BACKOFF_OFFSET = GRTT_OFFSET + 1,
|
||||||
|
GSIZE_OFFSET = BACKOFF_OFFSET,
|
||||||
FLAVOR_OFFSET = GSIZE_OFFSET + 1
|
FLAVOR_OFFSET = GSIZE_OFFSET + 1
|
||||||
};
|
};
|
||||||
}; // end class NormCmdMsg
|
}; // end class NormCmdMsg
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,18 @@ 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.Init(0.0, 1, (ProtocolTimerOwner*)this,
|
repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnRepairTimeout);
|
||||||
(ProtocolTimeoutFunc)&NormServerNode::OnRepairTimeout);
|
repair_timer.SetInterval(0.0);
|
||||||
activity_timer.Init(0.0, -1, (ProtocolTimerOwner*)this,
|
repair_timer.SetRepeat(1);
|
||||||
(ProtocolTimeoutFunc)&NormServerNode::OnActivityTimeout);
|
|
||||||
cc_timer.Init(0.0, 1, (ProtocolTimerOwner*)this,
|
activity_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnActivityTimeout);
|
||||||
(ProtocolTimeoutFunc)&NormServerNode::OnCCTimeout);
|
activity_timer.SetInterval(NormSession::DEFAULT_GRTT_ESTIMATE*NORM_ROBUST_FACTOR);
|
||||||
|
activity_timer.SetRepeat(NORM_ROBUST_FACTOR);
|
||||||
|
|
||||||
|
cc_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnCCTimeout);
|
||||||
|
cc_timer.SetInterval(0.0);
|
||||||
|
cc_timer.SetRepeat(1);
|
||||||
|
|
||||||
grtt_send_time.tv_sec = 0;
|
grtt_send_time.tv_sec = 0;
|
||||||
grtt_send_time.tv_usec = 0;
|
grtt_send_time.tv_usec = 0;
|
||||||
grtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE);
|
grtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE);
|
||||||
|
|
@ -50,6 +56,8 @@ NormServerNode::NormServerNode(class NormSession* theSession, NormNodeId nodeId)
|
||||||
gsize_quantized = NormQuantizeGroupSize(NormSession::DEFAULT_GSIZE_ESTIMATE);
|
gsize_quantized = NormQuantizeGroupSize(NormSession::DEFAULT_GSIZE_ESTIMATE);
|
||||||
gsize_estimate = NormUnquantizeGroupSize(gsize_quantized);
|
gsize_estimate = NormUnquantizeGroupSize(gsize_quantized);
|
||||||
|
|
||||||
|
backoff_factor = NormSession::DEFAULT_BACKOFF_FACTOR;
|
||||||
|
|
||||||
rtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE);
|
rtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE);
|
||||||
rtt_estimate = NormUnquantizeRtt(rtt_quantized);
|
rtt_estimate = NormUnquantizeRtt(rtt_quantized);
|
||||||
|
|
||||||
|
|
@ -142,6 +150,7 @@ bool NormServerNode::Open(UINT16 sessionId, UINT16 segmentSize, UINT16 numData,
|
||||||
|
|
||||||
void NormServerNode::Close()
|
void NormServerNode::Close()
|
||||||
{
|
{
|
||||||
|
if (activity_timer.IsActive()) activity_timer.Deactivate();
|
||||||
decoder.Destroy();
|
decoder.Destroy();
|
||||||
if (erasure_loc)
|
if (erasure_loc)
|
||||||
{
|
{
|
||||||
|
|
@ -169,9 +178,9 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
grtt_quantized = grttQuantized;
|
grtt_quantized = grttQuantized;
|
||||||
grtt_estimate = NormUnquantizeRtt(grttQuantized);
|
grtt_estimate = NormUnquantizeRtt(grttQuantized);
|
||||||
DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new grtt: %lf sec\n",
|
DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new grtt: %lf sec\n",
|
||||||
LocalNodeId(), Id(), grtt_estimate);
|
LocalNodeId(), GetId(), grtt_estimate);
|
||||||
activity_timer.SetInterval(grtt_estimate);
|
activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
|
||||||
activity_timer.Reset();
|
if (activity_timer.IsActive()) activity_timer.Reschedule();
|
||||||
}
|
}
|
||||||
UINT8 gsizeQuantized = cmd.GetGroupSize();
|
UINT8 gsizeQuantized = cmd.GetGroupSize();
|
||||||
if (gsizeQuantized != gsize_quantized)
|
if (gsizeQuantized != gsize_quantized)
|
||||||
|
|
@ -179,8 +188,9 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
gsize_quantized = gsizeQuantized;
|
gsize_quantized = gsizeQuantized;
|
||||||
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
|
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
|
||||||
DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new group size:%lf\n",
|
DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new group size:%lf\n",
|
||||||
LocalNodeId(), Id(), gsize_estimate);
|
LocalNodeId(), GetId(), gsize_estimate);
|
||||||
}
|
}
|
||||||
|
backoff_factor = (double)cmd.GetBackoffFactor();
|
||||||
|
|
||||||
NormCmdMsg::Flavor flavor = cmd.GetFlavor();
|
NormCmdMsg::Flavor flavor = cmd.GetFlavor();
|
||||||
switch (flavor)
|
switch (flavor)
|
||||||
|
|
@ -255,8 +265,8 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
{
|
{
|
||||||
// Respond immediately
|
// Respond immediately
|
||||||
if (cc_timer.IsActive()) cc_timer.Deactivate();
|
if (cc_timer.IsActive()) cc_timer.Deactivate();
|
||||||
cc_timer.ResetRepeats();
|
cc_timer.ResetRepeat();
|
||||||
OnCCTimeout();
|
OnCCTimeout(cc_timer);
|
||||||
}
|
}
|
||||||
else if (!cc_timer.IsActive())
|
else if (!cc_timer.IsActive())
|
||||||
{
|
{
|
||||||
|
|
@ -292,7 +302,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
cc_timer.SetInterval(backoffTime);
|
cc_timer.SetInterval(backoffTime);
|
||||||
DMSG(4, "NormServerNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
|
DMSG(4, "NormServerNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
|
||||||
LocalNodeId(), backoffTime);
|
LocalNodeId(), backoffTime);
|
||||||
session->InstallTimer(&cc_timer);
|
session->ActivateTimer(cc_timer);
|
||||||
}
|
}
|
||||||
} // end if (CC_RATE == ext.GetType())
|
} // end if (CC_RATE == ext.GetType())
|
||||||
} // end while (GetNextExtension())
|
} // end while (GetNextExtension())
|
||||||
|
|
@ -316,7 +326,8 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
{
|
{
|
||||||
const NormCmdRepairAdvMsg& repairAdv = (const NormCmdRepairAdvMsg&)cmd;
|
const NormCmdRepairAdvMsg& repairAdv = (const NormCmdRepairAdvMsg&)cmd;
|
||||||
// Does the CC feedback of this ACK suppress our CC feedback
|
// Does the CC feedback of this ACK suppress our CC feedback
|
||||||
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.RepeatCount())
|
if (!is_clr && !is_plr && cc_timer.IsActive() &&
|
||||||
|
cc_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
NormCCFeedbackExtension ext;
|
NormCCFeedbackExtension ext;
|
||||||
while (repairAdv.GetNextExtension(ext))
|
while (repairAdv.GetNextExtension(ext))
|
||||||
|
|
@ -328,7 +339,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (repair_timer.IsActive() && repair_timer.RepeatCount())
|
if (repair_timer.IsActive() && repair_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
HandleRepairContent(repairAdv.GetRepairContent(),
|
HandleRepairContent(repairAdv.GetRepairContent(),
|
||||||
repairAdv.GetRepairContentLength());
|
repairAdv.GetRepairContentLength());
|
||||||
|
|
@ -345,7 +356,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
||||||
|
|
||||||
void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
||||||
{
|
{
|
||||||
ASSERT(cc_timer.IsActive() && cc_timer.RepeatCount());
|
ASSERT(cc_timer.IsActive() && cc_timer.GetRepeatCount());
|
||||||
if (0 == (ccFlags & NormCC::CLR))
|
if (0 == (ccFlags & NormCC::CLR))
|
||||||
{
|
{
|
||||||
// We're suppressed by non-CLR receivers with no RTT confirmed
|
// We're suppressed by non-CLR receivers with no RTT confirmed
|
||||||
|
|
@ -386,7 +397,7 @@ void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
||||||
{
|
{
|
||||||
if (cc_timer.IsActive()) cc_timer.Deactivate();
|
if (cc_timer.IsActive()) cc_timer.Deactivate();
|
||||||
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
|
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
|
||||||
session->InstallTimer(&cc_timer);
|
session->ActivateTimer(cc_timer);
|
||||||
cc_timer.DecrementRepeatCount();
|
cc_timer.DecrementRepeatCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -395,7 +406,7 @@ void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
||||||
void NormServerNode::HandleAckMessage(const NormAckMsg& ack)
|
void NormServerNode::HandleAckMessage(const NormAckMsg& ack)
|
||||||
{
|
{
|
||||||
// Does the CC feedback of this ACK suppress our CC feedback
|
// Does the CC feedback of this ACK suppress our CC feedback
|
||||||
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.RepeatCount())
|
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
NormCCFeedbackExtension ext;
|
NormCCFeedbackExtension ext;
|
||||||
while (ack.GetNextExtension(ext))
|
while (ack.GetNextExtension(ext))
|
||||||
|
|
@ -412,7 +423,7 @@ void NormServerNode::HandleAckMessage(const NormAckMsg& ack)
|
||||||
void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
|
void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
|
||||||
{
|
{
|
||||||
// Does the CC feedback of this NACK suppress our CC feedback
|
// Does the CC feedback of this NACK suppress our CC feedback
|
||||||
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.RepeatCount())
|
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
NormCCFeedbackExtension ext;
|
NormCCFeedbackExtension ext;
|
||||||
while (nack.GetNextExtension(ext))
|
while (nack.GetNextExtension(ext))
|
||||||
|
|
@ -425,7 +436,7 @@ void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clients also care about recvd NACKS for NACK suppression
|
// Clients also care about recvd NACKS for NACK suppression
|
||||||
if (repair_timer.IsActive() && repair_timer.RepeatCount())
|
if (repair_timer.IsActive() && repair_timer.GetRepeatCount())
|
||||||
HandleRepairContent(nack.GetRepairContent(), nack.GetRepairContentLength());
|
HandleRepairContent(nack.GetRepairContent(), nack.GetRepairContentLength());
|
||||||
} // end NormServerNode::HandleNackMessage()
|
} // end NormServerNode::HandleNackMessage()
|
||||||
|
|
||||||
|
|
@ -441,7 +452,7 @@ void NormServerNode::HandleRepairContent(const char* buffer, UINT16 bufferLen)
|
||||||
NormObjectId prevObjectId;
|
NormObjectId prevObjectId;
|
||||||
NormObject* object = NULL;
|
NormObject* object = NULL;
|
||||||
bool freshBlock = true;
|
bool freshBlock = true;
|
||||||
NormBlockId prevBlockId;
|
NormBlockId prevBlockId = 0;
|
||||||
NormBlock* block = NULL;
|
NormBlock* block = NULL;
|
||||||
while ((requestLength = req.Unpack(buffer, bufferLen)))
|
while ((requestLength = req.Unpack(buffer, bufferLen)))
|
||||||
{
|
{
|
||||||
|
|
@ -670,9 +681,9 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
grtt_quantized = grttQuantized;
|
grtt_quantized = grttQuantized;
|
||||||
grtt_estimate = NormUnquantizeRtt(grttQuantized);
|
grtt_estimate = NormUnquantizeRtt(grttQuantized);
|
||||||
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new grtt: %lf sec\n",
|
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new grtt: %lf sec\n",
|
||||||
LocalNodeId(), Id(), grtt_estimate);
|
LocalNodeId(), GetId(), grtt_estimate);
|
||||||
activity_timer.SetInterval(grtt_estimate);
|
activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
|
||||||
activity_timer.Reset();
|
if (activity_timer.IsActive()) activity_timer.Reschedule();
|
||||||
}
|
}
|
||||||
UINT8 gsizeQuantized = msg.GetGroupSize();
|
UINT8 gsizeQuantized = msg.GetGroupSize();
|
||||||
if (gsizeQuantized != gsize_quantized)
|
if (gsizeQuantized != gsize_quantized)
|
||||||
|
|
@ -680,8 +691,9 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
gsize_quantized = gsizeQuantized;
|
gsize_quantized = gsizeQuantized;
|
||||||
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
|
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
|
||||||
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new group size: %lf\n",
|
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new group size: %lf\n",
|
||||||
LocalNodeId(), Id(), gsize_estimate);
|
LocalNodeId(), GetId(), gsize_estimate);
|
||||||
}
|
}
|
||||||
|
backoff_factor = (double)msg.GetBackoffFactor();
|
||||||
|
|
||||||
|
|
||||||
if (IsOpen())
|
if (IsOpen())
|
||||||
|
|
@ -689,7 +701,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
if (msg.GetSessionId() != session_id)
|
if (msg.GetSessionId() != session_id)
|
||||||
{
|
{
|
||||||
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu server>%lu sessionId change - resyncing.\n",
|
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu server>%lu sessionId change - resyncing.\n",
|
||||||
LocalNodeId(), Id());
|
LocalNodeId(), GetId());
|
||||||
Close();
|
Close();
|
||||||
resync_count++;
|
resync_count++;
|
||||||
}
|
}
|
||||||
|
|
@ -711,7 +723,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
fti.GetFecNumParity()))
|
fti.GetFecNumParity()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu open error\n",
|
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu open error\n",
|
||||||
LocalNodeId(), Id());
|
LocalNodeId(), GetId());
|
||||||
// (TBD) notify app of error ??
|
// (TBD) notify app of error ??
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -721,7 +733,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
if (!IsOpen())
|
if (!IsOpen())
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu - no FTI provided!\n",
|
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu - no FTI provided!\n",
|
||||||
LocalNodeId(), Id());
|
LocalNodeId(), GetId());
|
||||||
// (TBD) notify app of error ??
|
// (TBD) notify app of error ??
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -770,7 +782,8 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case OBJ_PENDING:
|
case OBJ_PENDING:
|
||||||
if ((obj = rx_table.Find(objectId))) break;
|
if ((obj = rx_table.Find(objectId)))
|
||||||
|
break;
|
||||||
case OBJ_NEW:
|
case OBJ_NEW:
|
||||||
{
|
{
|
||||||
if (msg.FlagIsSet(NormObjectMsg::FLAG_STREAM))
|
if (msg.FlagIsSet(NormObjectMsg::FLAG_STREAM))
|
||||||
|
|
@ -816,7 +829,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
((NormStreamObject*)obj)->StreamUpdateStatus(blockId);
|
((NormStreamObject*)obj)->StreamUpdateStatus(blockId);
|
||||||
rx_table.Insert(obj);
|
rx_table.Insert(obj);
|
||||||
DMSG(8, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new obj>%hu\n",
|
DMSG(8, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new obj>%hu\n",
|
||||||
LocalNodeId(), Id(), (UINT16)objectId);
|
LocalNodeId(), GetId(), (UINT16)objectId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -835,7 +848,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
if (obj && !obj->IsOpen())
|
if (obj && !obj->IsOpen())
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu "
|
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu "
|
||||||
"new obj>%hu - no FTI provided!\n", LocalNodeId(), Id(), (UINT16)objectId);
|
"new obj>%hu - no FTI provided!\n", LocalNodeId(), GetId(), (UINT16)objectId);
|
||||||
DeleteObject(obj);
|
DeleteObject(obj);
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -855,7 +868,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
obj->HandleObjectMessage(msg, msgType, blockId, segmentId);
|
obj->HandleObjectMessage(msg, msgType, blockId, segmentId);
|
||||||
if (!obj->IsPending())
|
if (!obj->IsPending())
|
||||||
{
|
{
|
||||||
|
// Reliable reception of this object has completed
|
||||||
if (NormObject::FILE == obj->GetType())
|
if (NormObject::FILE == obj->GetType())
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
((NormSimObject*)obj)->Close();
|
((NormSimObject*)obj)->Close();
|
||||||
|
|
@ -870,8 +883,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
||||||
completion_count++;
|
completion_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RepairCheck(NormObject::TO_BLOCK, objectId, blockId, segmentId);
|
RepairCheck(NormObject::TO_BLOCK, objectId, blockId, segmentId);
|
||||||
} // end NormServerNode::HandleObjectMessage()
|
} // end NormServerNode::HandleObjectMessage()
|
||||||
|
|
||||||
|
|
@ -897,8 +909,8 @@ void NormServerNode::Sync(NormObjectId objectId)
|
||||||
{
|
{
|
||||||
if (rx_pending_mask.IsSet())
|
if (rx_pending_mask.IsSet())
|
||||||
{
|
{
|
||||||
NormObjectId firstSet = NormObjectId(rx_pending_mask.FirstSet());
|
NormObjectId firstSet = NormObjectId((UINT16)rx_pending_mask.FirstSet());
|
||||||
if ((objectId > NormObjectId(rx_pending_mask.LastSet())) ||
|
if ((objectId > NormObjectId((UINT16)rx_pending_mask.LastSet())) ||
|
||||||
((next_id - objectId) > 256))
|
((next_id - objectId) > 256))
|
||||||
{
|
{
|
||||||
NormObject* obj;
|
NormObject* obj;
|
||||||
|
|
@ -949,7 +961,7 @@ NormServerNode::ObjectStatus NormServerNode::UpdateSyncStatus(const NormObjectId
|
||||||
// or revert to fresh sync if sync is totally lost,
|
// or revert to fresh sync if sync is totally lost,
|
||||||
// otherwise SQUELCH process will get things in order
|
// otherwise SQUELCH process will get things in order
|
||||||
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu re-syncing to server>%lu...\n",
|
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu re-syncing to server>%lu...\n",
|
||||||
LocalNodeId(), Id());
|
LocalNodeId(), GetId());
|
||||||
Sync(objectId);
|
Sync(objectId);
|
||||||
resync_count++;
|
resync_count++;
|
||||||
status = OBJ_NEW;
|
status = OBJ_NEW;
|
||||||
|
|
@ -975,7 +987,7 @@ void NormServerNode::SetPending(NormObjectId objectId)
|
||||||
rx_pending_mask.SetBits(next_id, objectId - next_id + 1);
|
rx_pending_mask.SetBits(next_id, objectId - next_id + 1);
|
||||||
next_id = objectId + 1;
|
next_id = objectId + 1;
|
||||||
// This prevents the "sync_id" from getting stale
|
// This prevents the "sync_id" from getting stale
|
||||||
sync_id = rx_pending_mask.FirstSet();
|
sync_id = (UINT16)rx_pending_mask.FirstSet();
|
||||||
}
|
}
|
||||||
} // end NormServerNode::SetPending()
|
} // end NormServerNode::SetPending()
|
||||||
|
|
||||||
|
|
@ -1024,7 +1036,7 @@ NormServerNode::ObjectStatus NormServerNode::GetObjectStatus(const NormObjectId&
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NormObjectId delta = objectId - next_id + 1;
|
NormObjectId delta = objectId - next_id + 1;
|
||||||
if (delta > NormObjectId(rx_pending_mask.Size()))
|
if (delta > NormObjectId((UINT16)rx_pending_mask.Size()))
|
||||||
{
|
{
|
||||||
return OBJ_INVALID;
|
return OBJ_INVALID;
|
||||||
}
|
}
|
||||||
|
|
@ -1056,8 +1068,8 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
||||||
if (rx_pending_mask.IsSet())
|
if (rx_pending_mask.IsSet())
|
||||||
{
|
{
|
||||||
if (rx_repair_mask.IsSet()) rx_repair_mask.Clear();
|
if (rx_repair_mask.IsSet()) rx_repair_mask.Clear();
|
||||||
NormObjectId nextId = rx_pending_mask.FirstSet();
|
NormObjectId nextId = (UINT16)rx_pending_mask.FirstSet();
|
||||||
NormObjectId lastId = rx_pending_mask.LastSet();
|
NormObjectId lastId = (UINT16)rx_pending_mask.LastSet();
|
||||||
if (objectId < lastId) lastId = objectId;
|
if (objectId < lastId) lastId = objectId;
|
||||||
while (nextId <= lastId)
|
while (nextId <= lastId)
|
||||||
{
|
{
|
||||||
|
|
@ -1077,7 +1089,7 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
||||||
startTimer = true;
|
startTimer = true;
|
||||||
}
|
}
|
||||||
nextId++;
|
nextId++;
|
||||||
nextId = rx_pending_mask.NextSet(nextId);
|
nextId = (UINT16)rx_pending_mask.NextSet(nextId);
|
||||||
}
|
}
|
||||||
current_object_id = objectId;
|
current_object_id = objectId;
|
||||||
if (startTimer)
|
if (startTimer)
|
||||||
|
|
@ -1090,11 +1102,11 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
||||||
repair_timer.SetInterval(backoffInterval);
|
repair_timer.SetInterval(backoffInterval);
|
||||||
DMSG(3, "NormServerNode::RepairCheck() node>%lu begin NACK back-off: %lf sec)...\n",
|
DMSG(3, "NormServerNode::RepairCheck() node>%lu begin NACK back-off: %lf sec)...\n",
|
||||||
LocalNodeId(), backoffInterval);
|
LocalNodeId(), backoffInterval);
|
||||||
session->InstallTimer(&repair_timer);
|
session->ActivateTimer(repair_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (repair_timer.RepeatCount())
|
else if (repair_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
// Repair timer in backoff phase
|
// Repair timer in backoff phase
|
||||||
// Trim server current transmit position reference
|
// Trim server current transmit position reference
|
||||||
|
|
@ -1115,7 +1127,7 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
||||||
if (rewindDetected)
|
if (rewindDetected)
|
||||||
{
|
{
|
||||||
repair_timer.Deactivate();
|
repair_timer.Deactivate();
|
||||||
DMSG(0, "NormServerNode::RepairCheck() node>%lu server rewind detected, ending NACK hold-off ...\n",
|
DMSG(4, "NormServerNode::RepairCheck() node>%lu server rewind detected, ending NACK hold-off ...\n",
|
||||||
LocalNodeId());
|
LocalNodeId());
|
||||||
|
|
||||||
RepairCheck(checkLevel, objectId, blockId, segmentId);
|
RepairCheck(checkLevel, objectId, blockId, segmentId);
|
||||||
|
|
@ -1125,10 +1137,10 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
||||||
|
|
||||||
// When repair timer fires, possibly build a NACK
|
// When repair timer fires, possibly build a NACK
|
||||||
// and queue for transmission to this server node
|
// and queue for transmission to this server node
|
||||||
bool NormServerNode::OnRepairTimeout()
|
bool NormServerNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch(repair_timer.RepeatCount())
|
switch(repair_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
case 0: // hold-off time complete
|
case 0: // hold-off time complete
|
||||||
DMSG(4, "NormServerNode::OnRepairTimeout() node>%lu end NACK hold-off ...\n",
|
DMSG(4, "NormServerNode::OnRepairTimeout() node>%lu end NACK hold-off ...\n",
|
||||||
|
|
@ -1143,8 +1155,8 @@ bool NormServerNode::OnRepairTimeout()
|
||||||
if (rx_pending_mask.IsSet())
|
if (rx_pending_mask.IsSet())
|
||||||
{
|
{
|
||||||
bool repairPending = false;
|
bool repairPending = false;
|
||||||
NormObjectId nextId = rx_pending_mask.FirstSet();
|
NormObjectId nextId = (UINT16)rx_pending_mask.FirstSet();
|
||||||
NormObjectId lastId = rx_pending_mask.LastSet();
|
NormObjectId lastId = (UINT16)rx_pending_mask.LastSet();
|
||||||
if (current_object_id < lastId) lastId = current_object_id;
|
if (current_object_id < lastId) lastId = current_object_id;
|
||||||
while (nextId <= lastId)
|
while (nextId <= lastId)
|
||||||
{
|
{
|
||||||
|
|
@ -1158,7 +1170,7 @@ bool NormServerNode::OnRepairTimeout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nextId++;
|
nextId++;
|
||||||
nextId = rx_pending_mask.NextSet(nextId);
|
nextId = (UINT16)rx_pending_mask.NextSet(nextId);
|
||||||
} // end while (nextId <= current_block_id)
|
} // end while (nextId <= current_block_id)
|
||||||
if (repairPending)
|
if (repairPending)
|
||||||
{
|
{
|
||||||
|
|
@ -1208,7 +1220,7 @@ bool NormServerNode::OnRepairTimeout()
|
||||||
{
|
{
|
||||||
cc_timer.Deactivate();
|
cc_timer.Deactivate();
|
||||||
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
|
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
|
||||||
session->InstallTimer(&cc_timer);
|
session->ActivateTimer(cc_timer);
|
||||||
cc_timer.DecrementRepeatCount();
|
cc_timer.DecrementRepeatCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1217,8 +1229,8 @@ bool NormServerNode::OnRepairTimeout()
|
||||||
NormObjectId prevId;
|
NormObjectId prevId;
|
||||||
UINT16 reqCount = 0;
|
UINT16 reqCount = 0;
|
||||||
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
|
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
|
||||||
nextId = rx_pending_mask.FirstSet();
|
nextId = (UINT16)rx_pending_mask.FirstSet();
|
||||||
lastId = rx_pending_mask.LastSet();
|
lastId = (UINT16)rx_pending_mask.LastSet();
|
||||||
if (max_pending_object < lastId) lastId = max_pending_object;
|
if (max_pending_object < lastId) lastId = max_pending_object;
|
||||||
lastId++; // force loop to fully flush nack building.
|
lastId++; // force loop to fully flush nack building.
|
||||||
while ((nextId <= lastId) || (reqCount > 0))
|
while ((nextId <= lastId) || (reqCount > 0))
|
||||||
|
|
@ -1298,12 +1310,12 @@ bool NormServerNode::OnRepairTimeout()
|
||||||
}
|
}
|
||||||
nextId++;
|
nextId++;
|
||||||
if (nextId <= lastId)
|
if (nextId <= lastId)
|
||||||
nextId = rx_pending_mask.NextSet(nextId);
|
nextId = (UINT16)rx_pending_mask.NextSet(nextId);
|
||||||
} // end while(nextId <= lastId)
|
} // end while(nextId <= lastId)
|
||||||
if (NormRepairRequest::INVALID != prevForm)
|
if (NormRepairRequest::INVALID != prevForm)
|
||||||
nack->PackRepairRequest(req); // (TBD) error check
|
nack->PackRepairRequest(req); // (TBD) error check
|
||||||
// Queue NACK for transmission
|
// Queue NACK for transmission
|
||||||
nack->SetServerId(Id());
|
nack->SetServerId(GetId());
|
||||||
nack->SetSessionId(session_id);
|
nack->SetSessionId(session_id);
|
||||||
// GRTT response is deferred until transmit time
|
// GRTT response is deferred until transmit time
|
||||||
|
|
||||||
|
|
@ -1382,29 +1394,30 @@ void NormServerNode::Activate()
|
||||||
{
|
{
|
||||||
if (activity_timer.IsActive())
|
if (activity_timer.IsActive())
|
||||||
{
|
{
|
||||||
activity_timer.ResetRepeats();
|
activity_timer.ResetRepeat();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
activity_timer.SetInterval(grtt_estimate);
|
activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
|
||||||
session->InstallTimer(&activity_timer);
|
session->ActivateTimer(activity_timer);
|
||||||
}
|
}
|
||||||
} // end NormServerNode::Activate()
|
} // end NormServerNode::Activate()
|
||||||
|
|
||||||
bool NormServerNode::OnActivityTimeout()
|
bool NormServerNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
if ((activity_timer.Repeats() - activity_timer.RepeatCount()) > 1)
|
if ((activity_timer.GetRepeat() - activity_timer.GetRepeatCount()) > 1)
|
||||||
{
|
{
|
||||||
DMSG(4, "NormServerNode::OnActivityTimeout() node>%lu for server>%lu\n",
|
DMSG(4, "NormServerNode::OnActivityTimeout() node>%lu for server>%lu\n",
|
||||||
LocalNodeId(), Id());
|
LocalNodeId(), GetId());
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
::GetSystemTime(¤tTime);
|
::ProtoSystemTime(currentTime);
|
||||||
UpdateRecvRate(currentTime, 0);
|
UpdateRecvRate(currentTime, 0);
|
||||||
}
|
}
|
||||||
if (!activity_timer.RepeatCount())
|
if (0 == activity_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
DMSG(0, "NormServerNode::OnActivityTimeout() node>%lu server>%lu gone inactive?\n",
|
DMSG(0, "NormServerNode::OnActivityTimeout() node>%lu server>%lu gone inactive?\n",
|
||||||
LocalNodeId(), Id());
|
LocalNodeId(), GetId());
|
||||||
|
Close();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} // end NormServerNode::OnActivityTimeout()
|
} // end NormServerNode::OnActivityTimeout()
|
||||||
|
|
@ -1427,10 +1440,10 @@ bool NormServerNode::UpdateLossEstimate(const struct timeval& currentTime,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NormServerNode::OnCCTimeout()
|
bool NormServerNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
// Build and queue ACK()
|
// Build and queue ACK()
|
||||||
switch (cc_timer.RepeatCount())
|
switch (cc_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
// "hold-off" time has ended
|
// "hold-off" time has ended
|
||||||
|
|
@ -1448,7 +1461,7 @@ bool NormServerNode::OnCCTimeout()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ack->Init();
|
ack->Init();
|
||||||
ack->SetServerId(Id());
|
ack->SetServerId(GetId());
|
||||||
ack->SetSessionId(session_id);
|
ack->SetSessionId(session_id);
|
||||||
ack->SetAckType(NormAck::CC);
|
ack->SetAckType(NormAck::CC);
|
||||||
ack->SetAckId(0);
|
ack->SetAckId(0);
|
||||||
|
|
@ -1522,7 +1535,7 @@ NormNodeTree::~NormNodeTree()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NormNode *NormNodeTree::FindNodeById(unsigned long nodeId) const
|
NormNode *NormNodeTree::FindNodeById(NormNodeId nodeId) const
|
||||||
{
|
{
|
||||||
NormNode* x = root;
|
NormNode* x = root;
|
||||||
while(x && (x->id != nodeId))
|
while(x && (x->id != nodeId))
|
||||||
|
|
@ -1854,7 +1867,8 @@ double NormLossEstimator::LossFraction()
|
||||||
double s0 = 0.0;
|
double s0 = 0.0;
|
||||||
const double* wptr = weight;
|
const double* wptr = weight;
|
||||||
const unsigned int* h = history;
|
const unsigned int* h = history;
|
||||||
for (unsigned int i = 0; i < DEPTH; i++)
|
unsigned int i;
|
||||||
|
for (i = 0; i < DEPTH; i++)
|
||||||
{
|
{
|
||||||
if (0 == *h) break;
|
if (0 == *h) break;
|
||||||
s0 += *wptr * *h++;
|
s0 += *wptr * *h++;
|
||||||
|
|
@ -1866,7 +1880,7 @@ double NormLossEstimator::LossFraction()
|
||||||
double s1 = 0.0;
|
double s1 = 0.0;
|
||||||
wptr = weight;
|
wptr = weight;
|
||||||
h = history + 1;
|
h = history + 1;
|
||||||
for (unsigned int i = 0; i < DEPTH; i++)
|
for (i = 0; i < DEPTH; i++)
|
||||||
{
|
{
|
||||||
if (0 == *h) break;
|
if (0 == *h) break;
|
||||||
s1 += *wptr * *h++; // ave loss interval w/out current interval
|
s1 += *wptr * *h++; // ave loss interval w/out current interval
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@
|
||||||
#include "normMessage.h"
|
#include "normMessage.h"
|
||||||
#include "normObject.h"
|
#include "normObject.h"
|
||||||
#include "normEncoder.h"
|
#include "normEncoder.h"
|
||||||
#include "protocolTimer.h"
|
#include "protokit.h"
|
||||||
|
|
||||||
class NormNode
|
class NormNode
|
||||||
{
|
{
|
||||||
friend class NormNodeTree;
|
friend class NormNodeTree;
|
||||||
|
|
@ -16,28 +17,22 @@ class NormNode
|
||||||
NormNode(class NormSession* theSession, NormNodeId nodeId);
|
NormNode(class NormSession* theSession, NormNodeId nodeId);
|
||||||
virtual ~NormNode();
|
virtual ~NormNode();
|
||||||
|
|
||||||
void SetAddress(const NetworkAddress& address) {addr = address;}
|
const ProtoAddress& GetAddress() const {return addr;}
|
||||||
const NetworkAddress& GetAddress() const {return addr;}
|
void SetAddress(const ProtoAddress& address) {addr = address;}
|
||||||
|
const NormNodeId& GetId() const {return id;}
|
||||||
const NormNodeId& Id() const {return id;}
|
|
||||||
inline const NormNodeId& LocalNodeId() const;
|
|
||||||
|
|
||||||
void SetId(const NormNodeId& nodeId) {id = nodeId;}
|
void SetId(const NormNodeId& nodeId) {id = nodeId;}
|
||||||
|
inline const NormNodeId& LocalNodeId() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class NormSession* session;
|
class NormSession* session;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NormNodeId id;
|
NormNodeId id;
|
||||||
NetworkAddress addr;
|
ProtoAddress addr;
|
||||||
|
// We keep NormNodes in a binary tree
|
||||||
NormNode* parent;
|
NormNode* parent;
|
||||||
NormNode* right;
|
NormNode* right;
|
||||||
NormNode* left;
|
NormNode* left;
|
||||||
|
|
||||||
//NormNode* prev;
|
|
||||||
//NormNode* next;
|
|
||||||
|
|
||||||
}; // end class NormNode
|
}; // end class NormNode
|
||||||
|
|
||||||
// Weighted-history loss event estimator
|
// Weighted-history loss event estimator
|
||||||
|
|
@ -156,7 +151,7 @@ class NormCCNode : public NormNode
|
||||||
double GetRtt() const {return rtt;}
|
double GetRtt() const {return rtt;}
|
||||||
double GetLoss() const {return loss;}
|
double GetLoss() const {return loss;}
|
||||||
double GetRate() const {return rate;}
|
double GetRate() const {return rate;}
|
||||||
UINT8 GetCCSequence() const {return cc_sequence;}
|
UINT16 GetCCSequence() const {return cc_sequence;}
|
||||||
|
|
||||||
void SetActive(bool state) {is_active = state;}
|
void SetActive(bool state) {is_active = state;}
|
||||||
void SetClrStatus(bool state) {is_clr = state;}
|
void SetClrStatus(bool state) {is_clr = state;}
|
||||||
|
|
@ -169,7 +164,7 @@ class NormCCNode : public NormNode
|
||||||
}
|
}
|
||||||
void SetLoss(double value) {loss = value;}
|
void SetLoss(double value) {loss = value;}
|
||||||
void SetRate(double value) {rate = value;}
|
void SetRate(double value) {rate = value;}
|
||||||
void SetCCSequence(UINT8 value) {cc_sequence = value;}
|
void SetCCSequence(UINT16 value) {cc_sequence = value;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_clr; // true if worst path representative
|
bool is_clr; // true if worst path representative
|
||||||
|
|
@ -179,7 +174,7 @@ class NormCCNode : public NormNode
|
||||||
double rtt; // in seconds
|
double rtt; // in seconds
|
||||||
double loss; // loss fraction
|
double loss; // loss fraction
|
||||||
double rate; // in bytes per second
|
double rate; // in bytes per second
|
||||||
UINT8 cc_sequence;
|
UINT16 cc_sequence;
|
||||||
}; // end class NormCCNode
|
}; // end class NormCCNode
|
||||||
|
|
||||||
class NormServerNode : public NormNode
|
class NormServerNode : public NormNode
|
||||||
|
|
@ -275,9 +270,9 @@ class NormServerNode : public NormNode
|
||||||
NormBlockId blockId,
|
NormBlockId blockId,
|
||||||
NormSegmentId segmentId);
|
NormSegmentId segmentId);
|
||||||
|
|
||||||
bool OnActivityTimeout();
|
bool OnActivityTimeout(ProtoTimer& theTimer);
|
||||||
bool OnRepairTimeout();
|
bool OnRepairTimeout(ProtoTimer& theTimer);
|
||||||
bool OnCCTimeout();
|
bool OnCCTimeout(ProtoTimer& theTimer);
|
||||||
void HandleRepairContent(const char* buffer, UINT16 bufferLen);
|
void HandleRepairContent(const char* buffer, UINT16 bufferLen);
|
||||||
|
|
||||||
UINT16 session_id;
|
UINT16 session_id;
|
||||||
|
|
@ -298,25 +293,26 @@ class NormServerNode : public NormNode
|
||||||
NormDecoder decoder;
|
NormDecoder decoder;
|
||||||
UINT16* erasure_loc;
|
UINT16* erasure_loc;
|
||||||
|
|
||||||
ProtocolTimer activity_timer;
|
ProtoTimer activity_timer;
|
||||||
ProtocolTimer repair_timer;
|
ProtoTimer repair_timer;
|
||||||
NormObjectId current_object_id; // index for suppression
|
NormObjectId current_object_id; // index for suppression
|
||||||
NormObjectId max_pending_object; // index for NACK construction
|
NormObjectId max_pending_object; // index for NACK construction
|
||||||
|
|
||||||
|
// Remote server grtt measurement state
|
||||||
double grtt_estimate;
|
double grtt_estimate;
|
||||||
UINT8 grtt_quantized;
|
UINT8 grtt_quantized;
|
||||||
struct timeval grtt_send_time;
|
struct timeval grtt_send_time;
|
||||||
struct timeval grtt_recv_time;
|
struct timeval grtt_recv_time;
|
||||||
double gsize_estimate;
|
double gsize_estimate;
|
||||||
UINT8 gsize_quantized;
|
UINT8 gsize_quantized;
|
||||||
|
double backoff_factor;
|
||||||
|
|
||||||
// Congestion control state
|
// Remote server congestion control state
|
||||||
NormLossEstimator2 loss_estimator;
|
NormLossEstimator2 loss_estimator;
|
||||||
//NormLossEstimator loss_estimator;
|
UINT16 cc_sequence;
|
||||||
UINT8 cc_sequence;
|
|
||||||
bool cc_enable;
|
bool cc_enable;
|
||||||
double cc_rate; // ccRate at start of cc_timer
|
double cc_rate; // ccRate at start of cc_timer
|
||||||
ProtocolTimer cc_timer;
|
ProtoTimer cc_timer;
|
||||||
double rtt_estimate;
|
double rtt_estimate;
|
||||||
UINT8 rtt_quantized;
|
UINT8 rtt_quantized;
|
||||||
bool rtt_confirmed;
|
bool rtt_confirmed;
|
||||||
|
|
@ -330,13 +326,13 @@ class NormServerNode : public NormNode
|
||||||
double nominal_packet_size;
|
double nominal_packet_size;
|
||||||
|
|
||||||
// For statistics tracking
|
// For statistics tracking
|
||||||
unsigned long recv_total; // total recvd accumulator
|
unsigned long recv_total; // total recvd accumulator
|
||||||
unsigned long recv_goodput; // goodput recvd accumulator
|
unsigned long recv_goodput; // goodput recvd accumulator
|
||||||
unsigned long resync_count;
|
unsigned long resync_count;
|
||||||
unsigned long nack_count;
|
unsigned long nack_count;
|
||||||
unsigned long suppress_count;
|
unsigned long suppress_count;
|
||||||
unsigned long completion_count;
|
unsigned long completion_count;
|
||||||
unsigned long failure_count; // due to re-syncs
|
unsigned long failure_count; // usually due to re-syncs
|
||||||
|
|
||||||
}; // end class NormServerNode
|
}; // end class NormServerNode
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,8 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
segmentSize = server->SegmentSize();
|
segmentSize = server->SegmentSize();
|
||||||
numData = server->BlockSize();
|
numData = server->BlockSize(); // max source symbols per FEC block
|
||||||
numParity = server->NumParity();
|
numParity = server->NumParity(); // max parity symbols per FEC block
|
||||||
if (infoLen > 0)
|
if (infoLen > 0)
|
||||||
{
|
{
|
||||||
pending_info = true;
|
pending_info = true;
|
||||||
|
|
@ -65,8 +65,8 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
segmentSize = session->ServerSegmentSize();
|
segmentSize = session->ServerSegmentSize();
|
||||||
numData = session->ServerBlockSize();
|
numData = session->ServerBlockSize(); // max source symbols per FEC block
|
||||||
numParity = session->ServerNumParity();
|
numParity = session->ServerNumParity(); // max parity symbols per FEC block
|
||||||
if (infoPtr)
|
if (infoPtr)
|
||||||
{
|
{
|
||||||
if (info) delete []info;
|
if (info) delete []info;
|
||||||
|
|
@ -88,11 +88,16 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure object size and block/segment sizes are compatible
|
// Compute number of segments and coding blocks for the object
|
||||||
NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData);
|
// (Note NormObjectSize divide operator always rounds _up_)
|
||||||
NormObjectSize numBlocks = objectSize / blockSize;
|
NormObjectSize numSegments = objectSize / NormObjectSize(segmentSize);
|
||||||
|
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");
|
||||||
|
|
@ -119,28 +124,44 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
||||||
}
|
}
|
||||||
repair_mask.Clear();
|
repair_mask.Clear();
|
||||||
|
|
||||||
|
|
||||||
if (STREAM == type)
|
if (STREAM == type)
|
||||||
{
|
{
|
||||||
last_block_id = 0; // not applicable for STREAM
|
small_block_size = large_block_size = numData;
|
||||||
last_block_size = numData; // assumed for STREAM
|
small_block_count = large_block_count = numBlocks.LSB();
|
||||||
|
final_segment_size = segmentSize;
|
||||||
NormStreamObject* stream = static_cast<NormStreamObject*>(this);
|
NormStreamObject* stream = static_cast<NormStreamObject*>(this);
|
||||||
stream->StreamResync(numBlocks.LSB());
|
stream->StreamResync(numBlocks.LSB());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
last_block_id = numBlocks.LSB() - 1;
|
// Compute FEC block structure per NORM Protocol Spec Section 5.1.1
|
||||||
NormObjectSize lastBlockBytes = NormObjectSize(last_block_id) * blockSize;
|
// (Note NormObjectSize divide operator always rounds _up_)
|
||||||
lastBlockBytes = objectSize - lastBlockBytes;
|
NormObjectSize largeBlockSize = numSegments / numBlocks;
|
||||||
NormObjectSize lastBlockSize = lastBlockBytes / NormObjectSize(segmentSize);
|
ASSERT(0 == largeBlockSize.MSB());
|
||||||
ASSERT(!lastBlockSize.MSB());
|
large_block_size = largeBlockSize.LSB();
|
||||||
ASSERT(lastBlockSize.LSB() <= numData);
|
if (numSegments == (numBlocks*largeBlockSize))
|
||||||
last_block_size = lastBlockSize.LSB();
|
{
|
||||||
NormObjectSize lastSegmentSize =
|
small_block_size = large_block_size;
|
||||||
NormObjectSize(0,last_block_size-1) * NormObjectSize(segmentSize);
|
small_block_count = numBlocks.LSB();
|
||||||
lastSegmentSize = lastBlockBytes - lastSegmentSize;
|
large_block_count = 0;
|
||||||
ASSERT(!lastSegmentSize.MSB());
|
}
|
||||||
ASSERT(lastSegmentSize.LSB() <= segmentSize);
|
else
|
||||||
last_segment_size = lastSegmentSize.LSB();
|
{
|
||||||
|
small_block_size = large_block_size - 1;
|
||||||
|
NormObjectSize largeBlockCount = numSegments - numBlocks*small_block_size;
|
||||||
|
ASSERT(0 == largeBlockCount.MSB());
|
||||||
|
large_block_count = largeBlockCount.LSB();
|
||||||
|
NormObjectSize smallBlockCount = numBlocks - largeBlockCount;
|
||||||
|
ASSERT(0 == smallBlockCount.MSB());
|
||||||
|
small_block_count = smallBlockCount.LSB();
|
||||||
|
}
|
||||||
|
|
||||||
|
final_block_id = large_block_count + small_block_count - 1; // not used for STREAM objects
|
||||||
|
NormObjectSize finalSegmentSize =
|
||||||
|
objectSize - (numSegments - NormObjectSize((UINT32)1))*segmentSize;
|
||||||
|
ASSERT(0 == finalSegmentSize.MSB());
|
||||||
|
final_segment_size = finalSegmentSize.LSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
object_size = objectSize;
|
object_size = objectSize;
|
||||||
|
|
@ -233,7 +254,7 @@ bool NormObject::TxReset(NormBlockId firstBlock)
|
||||||
NormBlockId blockId = block->Id();
|
NormBlockId blockId = block->Id();
|
||||||
if (blockId >= firstBlock)
|
if (blockId >= firstBlock)
|
||||||
{
|
{
|
||||||
increasedRepair |= block->TxReset(BlockSize(blockId),
|
increasedRepair |= block->TxReset(GetBlockSize(blockId),
|
||||||
nparity,
|
nparity,
|
||||||
session->ServerAutoParity(),
|
session->ServerAutoParity(),
|
||||||
segment_size);
|
segment_size);
|
||||||
|
|
@ -255,7 +276,7 @@ bool NormObject::TxResetBlocks(NormBlockId nextId, NormBlockId lastId)
|
||||||
}
|
}
|
||||||
NormBlock* block = block_buffer.Find(nextId);
|
NormBlock* block = block_buffer.Find(nextId);
|
||||||
if (block)
|
if (block)
|
||||||
increasedRepair |= block->TxReset(BlockSize(block->Id()), nparity, autoParity, segment_size);
|
increasedRepair |= block->TxReset(GetBlockSize(block->Id()), nparity, autoParity, segment_size);
|
||||||
nextId++;
|
nextId++;
|
||||||
}
|
}
|
||||||
return increasedRepair;
|
return increasedRepair;
|
||||||
|
|
@ -286,7 +307,7 @@ bool NormObject::ActivateRepairs()
|
||||||
while (nextId <= lastId)
|
while (nextId <= lastId)
|
||||||
{
|
{
|
||||||
NormBlock* block = block_buffer.Find(nextId);
|
NormBlock* block = block_buffer.Find(nextId);
|
||||||
if (block) block->TxReset(BlockSize(nextId), nparity, autoParity, segment_size);
|
if (block) block->TxReset(GetBlockSize(nextId), nparity, autoParity, segment_size);
|
||||||
// (TBD) This check can be eventually eliminated if everything else is done right
|
// (TBD) This check can be eventually eliminated if everything else is done right
|
||||||
if (!pending_mask.Set(nextId))
|
if (!pending_mask.Set(nextId))
|
||||||
DMSG(0, "NormObject::ActivateRepairs() pending_mask.Set(%lu) error!\n",
|
DMSG(0, "NormObject::ActivateRepairs() pending_mask.Set(%lu) error!\n",
|
||||||
|
|
@ -526,12 +547,15 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
|
||||||
if (blockId > max_pending_block)
|
if (blockId > max_pending_block)
|
||||||
{
|
{
|
||||||
max_pending_block = blockId;
|
max_pending_block = blockId;
|
||||||
max_pending_segment = BlockSize(blockId);
|
max_pending_segment = GetBlockSize(blockId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case THRU_OBJECT:
|
case THRU_OBJECT:
|
||||||
if (!IsStream()) max_pending_block = last_block_id;
|
if (!IsStream())
|
||||||
max_pending_segment = BlockSize(max_pending_block);
|
max_pending_block = final_block_id;
|
||||||
|
else if (blockId > max_pending_block)
|
||||||
|
max_pending_block = blockId;
|
||||||
|
max_pending_segment = GetBlockSize(max_pending_block);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
} // end switch (level)
|
} // end switch (level)
|
||||||
|
|
@ -568,7 +592,7 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
|
||||||
if (blockId < current_block_id)
|
if (blockId < current_block_id)
|
||||||
{
|
{
|
||||||
current_block_id = blockId;
|
current_block_id = blockId;
|
||||||
next_segment_id = BlockSize(blockId);
|
next_segment_id = GetBlockSize(blockId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -633,14 +657,14 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
|
||||||
break;
|
break;
|
||||||
case THRU_BLOCK:
|
case THRU_BLOCK:
|
||||||
current_block_id = blockId;
|
current_block_id = blockId;
|
||||||
next_segment_id = BlockSize(blockId);
|
next_segment_id = GetBlockSize(blockId);
|
||||||
break;
|
break;
|
||||||
case THRU_OBJECT:
|
case THRU_OBJECT:
|
||||||
if (IsStream())
|
if (IsStream())
|
||||||
current_block_id = max_pending_block;
|
current_block_id = max_pending_block;
|
||||||
else
|
else
|
||||||
current_block_id = last_block_id;
|
current_block_id = final_block_id;
|
||||||
next_segment_id = BlockSize(current_block_id);
|
next_segment_id = GetBlockSize(current_block_id);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -665,7 +689,7 @@ bool NormObject::IsRepairPending(bool flush)
|
||||||
if (block)
|
if (block)
|
||||||
{
|
{
|
||||||
bool isPending;
|
bool isPending;
|
||||||
UINT16 numData = BlockSize(nextId);
|
UINT16 numData = GetBlockSize(nextId);
|
||||||
if (flush || (nextId < lastId))
|
if (flush || (nextId < lastId))
|
||||||
{
|
{
|
||||||
isPending = block->IsRepairPending(numData, nparity);
|
isPending = block->IsRepairPending(numData, nparity);
|
||||||
|
|
@ -788,7 +812,7 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
|
||||||
} // end if/else (!blockPending && reqCount && (reqCount == (nextId - prevId)))
|
} // end if/else (!blockPending && reqCount && (reqCount == (nextId - prevId)))
|
||||||
if (blockPending)
|
if (blockPending)
|
||||||
{
|
{
|
||||||
UINT16 numData = BlockSize(nextId);
|
UINT16 numData = GetBlockSize(nextId);
|
||||||
if (NormRepairRequest::INVALID != prevForm)
|
if (NormRepairRequest::INVALID != prevForm)
|
||||||
nack.PackRepairRequest(req); // (TBD) error check
|
nack.PackRepairRequest(req); // (TBD) error check
|
||||||
reqCount = 0;
|
reqCount = 0;
|
||||||
|
|
@ -846,7 +870,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
{
|
{
|
||||||
info_len = segment_size;
|
info_len = segment_size;
|
||||||
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"Warning! info too long.\n", LocalNodeId(), server->Id(), (UINT16)id);
|
"Warning! info too long.\n", LocalNodeId(), server->GetId(), (UINT16)id);
|
||||||
}
|
}
|
||||||
memcpy(info, infoMsg.GetInfo(), info_len);
|
memcpy(info, infoMsg.GetInfo(), info_len);
|
||||||
pending_info = false;
|
pending_info = false;
|
||||||
|
|
@ -857,7 +881,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
// (TBD) Verify info hasn't changed?
|
// (TBD) Verify info hasn't changed?
|
||||||
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"received duplicate info ...\n", LocalNodeId(),
|
"received duplicate info ...\n", LocalNodeId(),
|
||||||
server->Id(), (UINT16)id);
|
server->GetId(), (UINT16)id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // NORM_MSG_DATA
|
else // NORM_MSG_DATA
|
||||||
|
|
@ -870,7 +894,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
if (!stream->StreamUpdateStatus(blockId))
|
if (!stream->StreamUpdateStatus(blockId))
|
||||||
{
|
{
|
||||||
DMSG(4, "NormObject::HandleObjectMessage() node:%lu server:%lu obj>%hu blk>%lu "
|
DMSG(4, "NormObject::HandleObjectMessage() node:%lu server:%lu obj>%hu blk>%lu "
|
||||||
"broken stream ...\n", LocalNodeId(), server->Id(), (UINT16)id, (UINT32)blockId);
|
"broken stream ...\n", LocalNodeId(), server->GetId(), (UINT16)id, (UINT32)blockId);
|
||||||
|
|
||||||
//ASSERT(0);
|
//ASSERT(0);
|
||||||
// ??? Ignore this new packet and try to fix stream ???
|
// ??? Ignore this new packet and try to fix stream ???
|
||||||
|
|
@ -898,7 +922,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UINT16 numData = BlockSize(blockId);
|
UINT16 numData = GetBlockSize(blockId);
|
||||||
if (pending_mask.Test(blockId))
|
if (pending_mask.Test(blockId))
|
||||||
{
|
{
|
||||||
NormBlock* block = block_buffer.Find(blockId);
|
NormBlock* block = block_buffer.Find(blockId);
|
||||||
|
|
@ -907,7 +931,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
if (!(block = server->GetFreeBlock(id, blockId)))
|
if (!(block = server->GetFreeBlock(id, blockId)))
|
||||||
{
|
{
|
||||||
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"Warning! no free blocks ...\n", LocalNodeId(), server->Id(),
|
"Warning! no free blocks ...\n", LocalNodeId(), server->GetId(),
|
||||||
(UINT16)id);
|
(UINT16)id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -921,7 +945,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
if (!segment)
|
if (!segment)
|
||||||
{
|
{
|
||||||
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"Warning! no free segments ...\n", LocalNodeId(), server->Id(),
|
"Warning! no free segments ...\n", LocalNodeId(), server->GetId(),
|
||||||
(UINT16)id);
|
(UINT16)id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -929,7 +953,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
if (segmentLen > segment_size)
|
if (segmentLen > 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->Id(),
|
"Error! segment too large ...\n", LocalNodeId(), server->GetId(),
|
||||||
(UINT16)id);
|
(UINT16)id);
|
||||||
server->PutFreeSegment(segment);
|
server->PutFreeSegment(segment);
|
||||||
return;
|
return;
|
||||||
|
|
@ -975,7 +999,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
// Decode (if pending_mask.FirstSet() < numData)
|
// Decode (if pending_mask.FirstSet() < numData)
|
||||||
// and write any decoded data segments to object
|
// and write any decoded data segments to object
|
||||||
DMSG(8, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu blk>%lu "
|
DMSG(8, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu blk>%lu "
|
||||||
"completed block ...\n", LocalNodeId(), server->Id(),
|
"completed block ...\n", LocalNodeId(), server->GetId(),
|
||||||
(UINT16)id, (UINT32)block->Id());
|
(UINT16)id, (UINT32)block->Id());
|
||||||
UINT16 nextErasure = block->FirstPending();
|
UINT16 nextErasure = block->FirstPending();
|
||||||
UINT16 erasureCount = 0;
|
UINT16 erasureCount = 0;
|
||||||
|
|
@ -990,7 +1014,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
if (!(segment = server->GetFreeSegment(id, blockId)))
|
if (!(segment = server->GetFreeSegment(id, blockId)))
|
||||||
{
|
{
|
||||||
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"Warning! no free segments ...\n", LocalNodeId(), server->Id(),
|
"Warning! no free segments ...\n", LocalNodeId(), server->GetId(),
|
||||||
(UINT16)id);
|
(UINT16)id);
|
||||||
// (TBD) Dump the block ...???
|
// (TBD) Dump the block ...???
|
||||||
return;
|
return;
|
||||||
|
|
@ -1040,14 +1064,14 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
||||||
{
|
{
|
||||||
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"received duplicate segment ...\n", LocalNodeId(),
|
"received duplicate segment ...\n", LocalNodeId(),
|
||||||
server->Id(), (UINT16)id);
|
server->GetId(), (UINT16)id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||||
"received duplicate block message ...\n", LocalNodeId(),
|
"received duplicate block message ...\n", LocalNodeId(),
|
||||||
server->Id(), (UINT16)id);
|
server->GetId(), (UINT16)id);
|
||||||
} // end if/else pending_mask.Test(blockId)
|
} // end if/else pending_mask.Test(blockId)
|
||||||
} // end if/else (NORM_MSG_INFO)
|
} // end if/else (NORM_MSG_INFO)
|
||||||
} // end NormObject::HandleObjectMessage()
|
} // end NormObject::HandleObjectMessage()
|
||||||
|
|
@ -1183,7 +1207,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
|
||||||
NormDataMsg* data = (NormDataMsg*)msg;
|
NormDataMsg* data = (NormDataMsg*)msg;
|
||||||
|
|
||||||
NormBlockId blockId = pending_mask.FirstSet();
|
NormBlockId blockId = pending_mask.FirstSet();
|
||||||
UINT16 numData = BlockSize(blockId);
|
UINT16 numData = GetBlockSize(blockId);
|
||||||
NormBlock* block = block_buffer.Find(blockId);
|
NormBlock* block = block_buffer.Find(blockId);
|
||||||
if (!block)
|
if (!block)
|
||||||
{
|
{
|
||||||
|
|
@ -1345,7 +1369,7 @@ void NormStreamObject::StreamAdvance()
|
||||||
bool NormObject::CalculateBlockParity(NormBlock* block)
|
bool NormObject::CalculateBlockParity(NormBlock* block)
|
||||||
{
|
{
|
||||||
char buffer[NormMsg::MAX_SIZE];
|
char buffer[NormMsg::MAX_SIZE];
|
||||||
UINT16 numData = BlockSize(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))
|
if (ReadSegment(block->Id(), i, buffer))
|
||||||
|
|
@ -1369,7 +1393,7 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
|
||||||
NormBlock* block = session->ServerGetFreeBlock(id, blockId);
|
NormBlock* block = session->ServerGetFreeBlock(id, blockId);
|
||||||
if (block)
|
if (block)
|
||||||
{
|
{
|
||||||
UINT16 numData = BlockSize(blockId);
|
UINT16 numData = GetBlockSize(blockId);
|
||||||
// Init block parameters
|
// Init block parameters
|
||||||
block->TxRecover(blockId, numData, nparity);
|
block->TxRecover(blockId, numData, nparity);
|
||||||
// Fill block with zero initialized parity segments
|
// Fill block with zero initialized parity segments
|
||||||
|
|
@ -1427,7 +1451,8 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
|
||||||
NormFileObject::NormFileObject(class NormSession* theSession,
|
NormFileObject::NormFileObject(class NormSession* theSession,
|
||||||
class NormServerNode* theServer,
|
class NormServerNode* theServer,
|
||||||
const NormObjectId& objectId)
|
const NormObjectId& objectId)
|
||||||
: NormObject(FILE, theSession, theServer, objectId), block_size(0,0)
|
: NormObject(FILE, theSession, theServer, objectId),
|
||||||
|
large_block_length(0,0), small_block_length(0,0)
|
||||||
{
|
{
|
||||||
path[0] = '\0';
|
path[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
@ -1462,15 +1487,15 @@ bool NormFileObject::Open(const char* thePath,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
block_size = NormObjectSize(server->BlockSize()) *
|
//block_size = NormObjectSize(server->BlockSize()) *
|
||||||
NormObjectSize(server->SegmentSize());
|
// NormObjectSize(server->SegmentSize());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We're sending this file
|
// We're sending this file
|
||||||
if (file.Open(thePath, O_RDONLY))
|
if (file.Open(thePath, O_RDONLY))
|
||||||
{
|
{
|
||||||
unsigned long size = file.GetSize();
|
UINT32 size = file.GetSize();
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
if (!NormObject::Open(size, infoPtr, infoLen))
|
if (!NormObject::Open(size, infoPtr, infoLen))
|
||||||
|
|
@ -1486,8 +1511,8 @@ bool NormFileObject::Open(const char* thePath,
|
||||||
file.Close();
|
file.Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
block_size = NormObjectSize(session->ServerBlockSize()) *
|
large_block_length = NormObjectSize(large_block_size) * segment_size;
|
||||||
NormObjectSize(session->ServerSegmentSize());
|
small_block_length = NormObjectSize(small_block_size) * segment_size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1526,13 +1551,20 @@ bool NormFileObject::WriteSegment(NormBlockId blockId,
|
||||||
const char* buffer)
|
const char* buffer)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
}
|
||||||
NormObjectSize segmentOffset = NormDataMsg::ReadPayloadOffset(buffer);
|
NormObjectSize segmentOffset = NormDataMsg::ReadPayloadOffset(buffer);
|
||||||
off_t offset = segmentOffset.LSB() + (segmentOffset.MSB() * 0x100000000LL);
|
off_t offsetScaleMSB = 0xffffffff + 1;
|
||||||
|
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;
|
||||||
|
|
@ -1548,20 +1580,39 @@ bool NormFileObject::ReadSegment(NormBlockId blockId,
|
||||||
{
|
{
|
||||||
// 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;
|
||||||
|
}
|
||||||
// Determine segment offset from blockId::segmentId
|
// Determine segment offset from blockId::segmentId
|
||||||
NormObjectSize segmentOffset = NormObjectSize(blockId) * block_size;
|
NormObjectSize segmentOffset;
|
||||||
segmentOffset = segmentOffset + (NormObjectSize(segmentId) * NormObjectSize(segment_size));
|
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;
|
||||||
|
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
|
||||||
|
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
||||||
|
segmentSize *segmentId;
|
||||||
|
}
|
||||||
NormDataMsg::WritePayloadLength(buffer, len);
|
NormDataMsg::WritePayloadLength(buffer, len);
|
||||||
NormDataMsg::WritePayloadOffset(buffer, segmentOffset);
|
NormDataMsg::WritePayloadOffset(buffer, segmentOffset);
|
||||||
off_t offset = segmentOffset.LSB() + (segmentOffset.MSB() * 0x100000000LL);
|
off_t offsetScaleMSB = 0xffffffff + 1;
|
||||||
|
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.Read(buffer+NormDataMsg::PayloadHeaderLength(), len);
|
UINT16 nbytes = file.Read(buffer+NormDataMsg::PayloadHeaderLength(), len);
|
||||||
return (len == nbytes);
|
return (len == nbytes);
|
||||||
|
|
@ -1609,7 +1660,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData);
|
NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData);
|
||||||
NormObjectSize numBlocks = NormObjectSize(bufferSize) / blockSize;
|
NormObjectSize numBlocks = NormObjectSize((UINT32)bufferSize) / blockSize;
|
||||||
ASSERT(0 == numBlocks.MSB());
|
ASSERT(0 == numBlocks.MSB());
|
||||||
// Buffering requires at least 2 blocks
|
// Buffering requires at least 2 blocks
|
||||||
numBlocks = MAX(2, numBlocks.LSB());
|
numBlocks = MAX(2, numBlocks.LSB());
|
||||||
|
|
@ -1642,7 +1693,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
|
||||||
write_offset = read_offset = NormObjectSize((UINT32)0);
|
write_offset = read_offset = NormObjectSize((UINT32)0);
|
||||||
if (!server)
|
if (!server)
|
||||||
{
|
{
|
||||||
if (!NormObject::Open(NormObjectSize(bufferSize), infoPtr, infoLen))
|
if (!NormObject::Open(NormObjectSize((UINT32)bufferSize), infoPtr, infoLen))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormStreamObject::Open() object open error\n");
|
DMSG(0, "NormStreamObject::Open() object open error\n");
|
||||||
Close();
|
Close();
|
||||||
|
|
@ -1970,8 +2021,8 @@ void NormStreamObject::Prune(NormBlockId blockId)
|
||||||
// Sequential (in order) read/write routines (TBD) Add a "Seek()" method
|
// Sequential (in order) read/write routines (TBD) Add a "Seek()" method
|
||||||
bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStart)
|
bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStart)
|
||||||
{
|
{
|
||||||
unsigned long bytesRead = 0;
|
unsigned int bytesRead = 0;
|
||||||
unsigned long bytesToRead = *buflen;
|
unsigned int bytesToRead = *buflen;
|
||||||
while (bytesToRead > 0)
|
while (bytesToRead > 0)
|
||||||
{
|
{
|
||||||
NormBlock* block = stream_buffer.Find(read_index.block);
|
NormBlock* block = stream_buffer.Find(read_index.block);
|
||||||
|
|
@ -2178,7 +2229,7 @@ unsigned long NormStreamObject::Write(const char* buffer, unsigned long len, boo
|
||||||
#endif // if/else SIMULATE
|
#endif // if/else SIMULATE
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT16 count = len - nBytes;
|
UINT16 count = (UINT16)(len - nBytes);
|
||||||
UINT16 space = segment_size - index;
|
UINT16 space = segment_size - index;
|
||||||
count = MIN(count, space);
|
count = MIN(count, space);
|
||||||
#ifdef SIMULATE
|
#ifdef SIMULATE
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ class NormObject
|
||||||
THRU_OBJECT
|
THRU_OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
void Verify() const;
|
|
||||||
|
|
||||||
virtual ~NormObject();
|
virtual ~NormObject();
|
||||||
|
|
||||||
|
// Object information
|
||||||
NormObject::Type GetType() const {return type;}
|
NormObject::Type GetType() const {return type;}
|
||||||
const NormObjectId& Id() const {return id;}
|
const NormObjectId& Id() const {return id;}
|
||||||
const NormObjectSize& Size() const {return object_size;}
|
const NormObjectSize& Size() const {return object_size;}
|
||||||
|
|
@ -60,10 +60,12 @@ class NormObject
|
||||||
char* buffer) = 0;
|
char* buffer) = 0;
|
||||||
|
|
||||||
// These are only valid after object is open
|
// These are only valid after object is open
|
||||||
NormBlockId LastBlockId() const {return last_block_id;}
|
NormBlockId GetFinalBlockId() const {return final_block_id;}
|
||||||
NormSegmentId LastBlockSize() const {return last_block_size;}
|
UINT32 GetBlockSize(NormBlockId blockId)
|
||||||
NormSegmentId BlockSize(NormBlockId blockId)
|
{
|
||||||
{return ((blockId == last_block_id) ? last_block_size : ndata);}
|
return (((UINT32)blockId < large_block_count) ? large_block_size :
|
||||||
|
small_block_size);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsPending(bool flush = true) const;
|
bool IsPending(bool flush = true) const;
|
||||||
bool IsRepairPending() const;
|
bool IsRepairPending() const;
|
||||||
|
|
@ -84,12 +86,12 @@ class NormObject
|
||||||
{
|
{
|
||||||
NormBlockId blockId = theBlock->Id();
|
NormBlockId blockId = theBlock->Id();
|
||||||
bool result = theBlock->TxUpdate(firstSegmentId, lastSegmentId,
|
bool result = theBlock->TxUpdate(firstSegmentId, lastSegmentId,
|
||||||
BlockSize(blockId), nparity,
|
GetBlockSize(blockId), nparity,
|
||||||
numErasures);
|
numErasures);
|
||||||
ASSERT(result ? pending_mask.Set(blockId) : true);
|
ASSERT(result ? pending_mask.Set(blockId) : true);
|
||||||
result = result ? pending_mask.Set(blockId) : false;
|
result = result ? pending_mask.Set(blockId) : false;
|
||||||
return result;
|
return result;
|
||||||
} // end NormObject::TxUpdateBlock()
|
}
|
||||||
bool HandleInfoRequest();
|
bool HandleInfoRequest();
|
||||||
bool HandleBlockRequest(NormBlockId nextId, NormBlockId lastId);
|
bool HandleBlockRequest(NormBlockId nextId, NormBlockId lastId);
|
||||||
bool SetPending(NormBlockId blockId) {return pending_mask.Set(blockId);}
|
bool SetPending(NormBlockId blockId) {return pending_mask.Set(blockId);}
|
||||||
|
|
@ -98,7 +100,7 @@ class NormObject
|
||||||
bool IsRepairSet(NormBlockId blockId) {return repair_mask.Test(blockId);}
|
bool IsRepairSet(NormBlockId blockId) {return repair_mask.Test(blockId);}
|
||||||
bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd);
|
bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd);
|
||||||
|
|
||||||
// Used by session server for resource management scheme
|
// Used by sender for resource management scheme
|
||||||
NormBlock* StealNonPendingBlock(bool excludeBlock, NormBlockId excludeId = 0);
|
NormBlock* StealNonPendingBlock(bool excludeBlock, NormBlockId excludeId = 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -110,7 +112,7 @@ class NormObject
|
||||||
NormSegmentId segmentId);
|
NormSegmentId segmentId);
|
||||||
|
|
||||||
|
|
||||||
// Used by remote server node for resource management scheme
|
// Used by receiver for resource management scheme
|
||||||
NormBlock* StealNewestBlock(bool excludeBlock, NormBlockId excludeId = 0);
|
NormBlock* StealNewestBlock(bool excludeBlock, NormBlockId excludeId = 0);
|
||||||
NormBlock* StealOldestBlock(bool excludeBlock, NormBlockId excludeId = 0);
|
NormBlock* StealOldestBlock(bool excludeBlock, NormBlockId excludeId = 0);
|
||||||
|
|
||||||
|
|
@ -129,7 +131,7 @@ class NormObject
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NormObject(NormObject::Type theType,
|
NormObject(Type theType,
|
||||||
class NormSession* theSession,
|
class NormSession* theSession,
|
||||||
class NormServerNode* theServer,
|
class NormServerNode* theServer,
|
||||||
const NormObjectId& objectId);
|
const NormObjectId& objectId);
|
||||||
|
|
@ -154,17 +156,18 @@ class NormObject
|
||||||
NormSegmentId next_segment_id; // for suppression
|
NormSegmentId next_segment_id; // for suppression
|
||||||
NormBlockId max_pending_block; // for NACK construction
|
NormBlockId max_pending_block; // for NACK construction
|
||||||
NormSegmentId max_pending_segment; // for NACK construction
|
NormSegmentId max_pending_segment; // for NACK construction
|
||||||
NormBlockId last_block_id;
|
UINT32 large_block_count;
|
||||||
NormSegmentId last_block_size;
|
UINT32 large_block_size;
|
||||||
UINT16 last_segment_size;
|
UINT32 small_block_count;
|
||||||
|
UINT32 small_block_size;
|
||||||
|
NormBlockId final_block_id;
|
||||||
|
UINT16 final_segment_size;
|
||||||
|
|
||||||
char* info;
|
char* info;
|
||||||
UINT16 info_len;
|
UINT16 info_len;
|
||||||
|
|
||||||
bool accepted;
|
bool accepted;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NormObject* next;
|
NormObject* next;
|
||||||
}; // end class NormObject
|
}; // end class NormObject
|
||||||
|
|
||||||
|
|
@ -201,7 +204,8 @@ class NormFileObject : public NormObject
|
||||||
private:
|
private:
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
NormFile file;
|
NormFile file;
|
||||||
NormObjectSize block_size;
|
NormObjectSize large_block_length;
|
||||||
|
NormObjectSize small_block_length;
|
||||||
}; // end class NormFileObject
|
}; // end class NormFileObject
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -345,14 +349,14 @@ class NormObjectTable
|
||||||
private:
|
private:
|
||||||
NormObject* Next(NormObject* o) const {return o->next;}
|
NormObject* Next(NormObject* o) const {return o->next;}
|
||||||
|
|
||||||
NormObject** table;
|
NormObject** table;
|
||||||
unsigned long hash_mask;
|
UINT16 hash_mask;
|
||||||
unsigned long range_max; // max range of objects that can be kept
|
UINT16 range_max; // max range of objects that can be kept
|
||||||
unsigned long range; // zero if "object table" is empty
|
UINT16 range; // zero if "object table" is empty
|
||||||
NormObjectId range_lo;
|
NormObjectId range_lo;
|
||||||
NormObjectId range_hi;
|
NormObjectId range_hi;
|
||||||
unsigned long count;
|
UINT16 count;
|
||||||
NormObjectSize size;
|
NormObjectSize size;
|
||||||
}; // end class NormObjectTable
|
}; // end class NormObjectTable
|
||||||
|
|
||||||
#endif // _NORM_OBJECT
|
#endif // _NORM_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,66 @@
|
||||||
#include "normPostProcess.h"
|
#include "normPostProcess.h"
|
||||||
#include "protoLib.h"
|
#include "protoDebug.h"
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#ifdef UNIX
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif // UNIX
|
|
||||||
|
|
||||||
typedef void (*sighandler_t)(int);
|
|
||||||
|
|
||||||
NormPostProcessor::NormPostProcessor()
|
NormPostProcessor::NormPostProcessor()
|
||||||
: process_argv(NULL)
|
: process_argv(NULL), process_argc(0)
|
||||||
#ifdef UNIX
|
|
||||||
,process_id(0)
|
|
||||||
#endif // UNIX
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NormPostProcessor::~NormPostProcessor()
|
NormPostProcessor::~NormPostProcessor()
|
||||||
{
|
{
|
||||||
if (IsActive()) Kill();
|
|
||||||
SetCommand(NULL);
|
SetCommand(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NormPostProcessor::GetCommand(char* buffer, unsigned int buflen)
|
||||||
|
{
|
||||||
|
if (process_argv && buffer)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (buflen && (i < process_argc))
|
||||||
|
{
|
||||||
|
strncpy(buffer, process_argv[i], buflen);
|
||||||
|
unsigned int len = strlen(process_argv[i]);
|
||||||
|
if (len < buflen)
|
||||||
|
{
|
||||||
|
buflen -= len;
|
||||||
|
buffer += len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buflen = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
if (i < process_argc)
|
||||||
|
{
|
||||||
|
*buffer++= ' ';
|
||||||
|
buflen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (buflen && buffer)
|
||||||
|
{
|
||||||
|
if (buflen < 4)
|
||||||
|
buffer[0] = '\0';
|
||||||
|
else
|
||||||
|
strncpy(buffer, "none", 4);
|
||||||
|
if (buflen > 4) buffer[4] = '\0';
|
||||||
|
}
|
||||||
|
} // end NormPostProcessor::GetCommand()
|
||||||
|
|
||||||
bool NormPostProcessor::SetCommand(const char* cmd)
|
bool NormPostProcessor::SetCommand(const char* cmd)
|
||||||
{
|
{
|
||||||
|
|
||||||
// 1) Delete old command resources
|
// 1) Delete old command resources
|
||||||
if (process_argv)
|
if (process_argv)
|
||||||
{
|
{
|
||||||
const char** arg = process_argv;
|
char** arg = process_argv;
|
||||||
while (*arg)
|
while (*arg)
|
||||||
{
|
{
|
||||||
delete *arg;
|
delete *arg;
|
||||||
|
|
@ -60,7 +87,7 @@ bool NormPostProcessor::SetCommand(const char* cmd)
|
||||||
|
|
||||||
// 3) Allocate new process_argv array (2 extra slots, one for "target",
|
// 3) Allocate new process_argv array (2 extra slots, one for "target",
|
||||||
// and one for terminating NULL pointer.
|
// and one for terminating NULL pointer.
|
||||||
if (!(process_argv = new const char*[argCount+2]))
|
if (!(process_argv = new char*[argCount+2]))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormPostProcessor::SetCommand new(process_argv) error: %s\n",
|
DMSG(0, "NormPostProcessor::SetCommand new(process_argv) error: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
@ -92,74 +119,3 @@ bool NormPostProcessor::SetCommand(const char* cmd)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} // end NormPostProcessor::SetCommand()
|
} // end NormPostProcessor::SetCommand()
|
||||||
|
|
||||||
bool NormPostProcessor::ProcessFile(const char* path)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (IsActive()) Kill();
|
|
||||||
|
|
||||||
#ifdef UNIX
|
|
||||||
// 1) temporarily disable signal handling
|
|
||||||
sighandler_t sigtermHandler = signal(SIGTERM, SIG_DFL);
|
|
||||||
sighandler_t sigintHandler = signal(SIGINT, SIG_DFL);
|
|
||||||
sighandler_t sigchldHandler = signal(SIGCHLD, SIG_DFL);
|
|
||||||
|
|
||||||
process_argv[process_argc] = path;
|
|
||||||
|
|
||||||
switch((process_id = fork()))
|
|
||||||
{
|
|
||||||
case -1: // error
|
|
||||||
DMSG(0, "NormPostProcessor::ProcessFile fork() error: %s\n", strerror(errno));
|
|
||||||
process_id = 0;
|
|
||||||
process_argv[process_argc] = NULL;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case 0: // child
|
|
||||||
if (execvp((char*)process_argv[0], (char**)process_argv) < 0)
|
|
||||||
{
|
|
||||||
DMSG(0, "NormPostProcessor::ProcessFile execvp() error: %s\n", strerror(errno));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // parent
|
|
||||||
process_argv[process_argc] = NULL;
|
|
||||||
// Restore signal handlers for parent
|
|
||||||
signal(SIGTERM, sigtermHandler);
|
|
||||||
signal(SIGINT, sigintHandler);
|
|
||||||
signal(SIGCHLD, sigchldHandler);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif // UNIX
|
|
||||||
return true;
|
|
||||||
} // end NormPostProcessor::ProcessFile()
|
|
||||||
|
|
||||||
void NormPostProcessor::Kill()
|
|
||||||
{
|
|
||||||
if (!IsActive()) return;
|
|
||||||
#ifdef UNIX
|
|
||||||
int count = 0;
|
|
||||||
while((kill(process_id, SIGTERM) != 0) && count < 10)
|
|
||||||
{
|
|
||||||
if (errno == ESRCH) break;
|
|
||||||
count++;
|
|
||||||
DMSG(0, "NormPostProcessor::Kill kill() error: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
count = 0;
|
|
||||||
int status;
|
|
||||||
while((waitpid(process_id, &status, 0) != process_id) && count < 10)
|
|
||||||
{
|
|
||||||
if (errno == ECHILD) break;
|
|
||||||
count++;
|
|
||||||
DMSG(0, "NormPostProcessor::Kill waitpid() error: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
process_id = 0;
|
|
||||||
#endif // UNIX
|
|
||||||
} // end NormPostProcessor::Kill()
|
|
||||||
|
|
||||||
void NormPostProcessor::HandleSIGCHLD()
|
|
||||||
{
|
|
||||||
// See if processor exited itself
|
|
||||||
int status;
|
|
||||||
if (wait(&status) == process_id) process_id = 0;
|
|
||||||
} // end NormPostProcessor::HandleSIGCHLD()
|
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,29 @@
|
||||||
|
|
||||||
#ifndef _NORM_POST_PROCESS
|
#ifndef _NORM_POST_PROCESS
|
||||||
#define _NORM_POST_PROCESS
|
#define _NORM_POST_PROCESS
|
||||||
|
|
||||||
|
#include "protoDefs.h" // for NULL
|
||||||
|
|
||||||
class NormPostProcessor
|
class NormPostProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NormPostProcessor();
|
NormPostProcessor();
|
||||||
~NormPostProcessor();
|
virtual ~NormPostProcessor();
|
||||||
|
// Implement this per derivation
|
||||||
|
static NormPostProcessor* Create();
|
||||||
|
|
||||||
bool IsEnabled() {return (0 != process_argv);}
|
bool IsEnabled() {return (NULL != process_argv);}
|
||||||
bool SetCommand(const char* cmd);
|
bool SetCommand(const char* cmd);
|
||||||
bool ProcessFile(const char* path);
|
void GetCommand(char* buffer, unsigned int buflen);
|
||||||
void Kill();
|
|
||||||
bool IsActive()
|
|
||||||
{
|
|
||||||
#ifdef UNIX
|
|
||||||
return (0 != process_id);
|
|
||||||
#endif // UNIX
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleSIGCHLD();
|
virtual bool ProcessFile(const char* path) = 0;
|
||||||
|
virtual void Kill() = 0;
|
||||||
|
virtual bool IsActive() = 0;
|
||||||
|
virtual void OnDeath() {};
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
const char** process_argv;
|
char** process_argv;
|
||||||
unsigned int process_argc;
|
unsigned int process_argc;
|
||||||
#ifdef UNIX
|
|
||||||
int process_id;
|
|
||||||
#endif
|
|
||||||
#ifdef WIN32
|
|
||||||
HANDLE process_handle;
|
|
||||||
#endif
|
|
||||||
}; // end class NormPostProcessor
|
}; // end class NormPostProcessor
|
||||||
|
|
||||||
#endif // _NORM_POST_PROCESS
|
#endif // _NORM_POST_PROCESS
|
||||||
|
|
|
||||||
|
|
@ -184,14 +184,14 @@ bool NormBlock::IsRepairPending(UINT16 ndata, UINT16 nparity)
|
||||||
if (nparity)
|
if (nparity)
|
||||||
{
|
{
|
||||||
UINT16 i = nparity;
|
UINT16 i = nparity;
|
||||||
NormSegmentId nextId = pending_mask.FirstSet();
|
NormSegmentId nextId = (UINT16)pending_mask.FirstSet();
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
// (TBD) for more NACK suppression, we could skip ahead
|
// (TBD) for more NACK suppression, we could skip ahead
|
||||||
// if this bit is already set in repair_mask?
|
// if this bit is already set in repair_mask?
|
||||||
repair_mask.Set(nextId); // set bit a parity can fill
|
repair_mask.Set(nextId); // set bit a parity can fill
|
||||||
nextId++;
|
nextId++;
|
||||||
nextId = pending_mask.NextSet(nextId);
|
nextId = (UINT16)pending_mask.NextSet(nextId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (size > ndata)
|
else if (size > ndata)
|
||||||
|
|
@ -390,7 +390,7 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
|
||||||
NormRepairRequest req;
|
NormRepairRequest req;
|
||||||
req.SetFlag(NormRepairRequest::SEGMENT);
|
req.SetFlag(NormRepairRequest::SEGMENT);
|
||||||
if (repairInfo) req.SetFlag(NormRepairRequest::INFO);
|
if (repairInfo) req.SetFlag(NormRepairRequest::INFO);
|
||||||
UINT16 nextId = repair_mask.FirstSet();
|
UINT16 nextId = (UINT16)repair_mask.FirstSet();
|
||||||
UINT16 blockSize = size;
|
UINT16 blockSize = size;
|
||||||
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
|
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
|
||||||
UINT16 segmentCount = 0;
|
UINT16 segmentCount = 0;
|
||||||
|
|
@ -398,7 +398,7 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
|
||||||
while (nextId < blockSize)
|
while (nextId < blockSize)
|
||||||
{
|
{
|
||||||
UINT16 currentId = nextId;
|
UINT16 currentId = nextId;
|
||||||
nextId = repair_mask.NextSet(++nextId);
|
nextId = (UINT16)repair_mask.NextSet(++nextId);
|
||||||
if (!segmentCount) firstId = currentId;
|
if (!segmentCount) firstId = currentId;
|
||||||
|
|
||||||
segmentCount++;
|
segmentCount++;
|
||||||
|
|
@ -467,19 +467,19 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
|
||||||
if (erasure_count > nparity)
|
if (erasure_count > nparity)
|
||||||
{
|
{
|
||||||
// Request explicit repair
|
// Request explicit repair
|
||||||
nextId = pending_mask.FirstSet();
|
nextId = (UINT16)pending_mask.FirstSet();
|
||||||
UINT16 i = nparity;
|
UINT16 i = nparity;
|
||||||
// Skip nparity missing data segments
|
// Skip nparity missing data segments
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
nextId++;
|
nextId++;
|
||||||
endId = pending_mask.NextSet(nextId);
|
endId = (UINT16)pending_mask.NextSet(nextId);
|
||||||
}
|
}
|
||||||
endId = ndata + nparity;
|
endId = ndata + nparity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nextId = pending_mask.NextSet(ndata);
|
nextId = (UINT16)pending_mask.NextSet(ndata);
|
||||||
endId = ndata + erasure_count;
|
endId = ndata + erasure_count;
|
||||||
}
|
}
|
||||||
NormRepairRequest req;
|
NormRepairRequest req;
|
||||||
|
|
@ -492,7 +492,7 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
|
||||||
while (nextId < endId)
|
while (nextId < endId)
|
||||||
{
|
{
|
||||||
UINT16 currentId = nextId;
|
UINT16 currentId = nextId;
|
||||||
nextId = pending_mask.NextSet(++nextId);
|
nextId = (UINT16)pending_mask.NextSet(++nextId);
|
||||||
if (0 == segmentCount) firstId = currentId;
|
if (0 == segmentCount) firstId = currentId;
|
||||||
segmentCount++;
|
segmentCount++;
|
||||||
// Check for break in consecutive series or end
|
// Check for break in consecutive series or end
|
||||||
|
|
|
||||||
|
|
@ -157,9 +157,9 @@ class NormBlock
|
||||||
UINT16 ParityCount() const {return parity_count;}
|
UINT16 ParityCount() const {return parity_count;}
|
||||||
|
|
||||||
NormSymbolId FirstPending() const
|
NormSymbolId FirstPending() const
|
||||||
{return pending_mask.FirstSet();}
|
{return (NormSymbolId)pending_mask.FirstSet();}
|
||||||
NormSymbolId FirstRepair() const
|
NormSymbolId FirstRepair() const
|
||||||
{return repair_mask.FirstSet();}
|
{return (NormSymbolId)repair_mask.FirstSet();}
|
||||||
bool SetPending(NormSymbolId s)
|
bool SetPending(NormSymbolId s)
|
||||||
{return pending_mask.Set(s);}
|
{return pending_mask.Set(s);}
|
||||||
bool SetPending(NormSymbolId firstId, UINT16 count)
|
bool SetPending(NormSymbolId firstId, UINT16 count)
|
||||||
|
|
@ -192,7 +192,7 @@ class NormBlock
|
||||||
|
|
||||||
|
|
||||||
NormSymbolId NextPending(NormSymbolId index) const
|
NormSymbolId NextPending(NormSymbolId index) const
|
||||||
{return pending_mask.NextSet(index);}
|
{return ((NormSymbolId)pending_mask.NextSet(index));}
|
||||||
|
|
||||||
|
|
||||||
bool AppendRepairRequest(NormNackMsg& nack,
|
bool AppendRepairRequest(NormNackMsg& nack,
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,14 @@ const UINT16 NormSession::DEFAULT_NDATA = 64;
|
||||||
const UINT16 NormSession::DEFAULT_NPARITY = 32;
|
const UINT16 NormSession::DEFAULT_NPARITY = 32;
|
||||||
|
|
||||||
NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
: session_mgr(sessionMgr), notify_pending(false), local_node_id(localNodeId),
|
: session_mgr(sessionMgr), notify_pending(false),
|
||||||
|
tx_socket(ProtoSocket::UDP), rx_socket(ProtoSocket::UDP),
|
||||||
|
local_node_id(localNodeId),
|
||||||
ttl(DEFAULT_TTL), tx_rate(DEFAULT_TRANSMIT_RATE/8.0),
|
ttl(DEFAULT_TTL), tx_rate(DEFAULT_TRANSMIT_RATE/8.0),
|
||||||
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0),
|
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0),
|
||||||
ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0),
|
ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0),
|
||||||
next_tx_object_id(0), tx_cache_count_min(1), tx_cache_count_max(256),
|
next_tx_object_id(0), tx_cache_count_min(1), tx_cache_count_max(256),
|
||||||
tx_cache_size_max((unsigned long)20*1024*1024),
|
tx_cache_size_max((UINT32)20*1024*1024),
|
||||||
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),
|
||||||
|
|
@ -35,24 +37,27 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
|
||||||
trace(false), tx_loss_rate(0.0), rx_loss_rate(0.0),
|
trace(false), tx_loss_rate(0.0), rx_loss_rate(0.0),
|
||||||
next(NULL)
|
next(NULL)
|
||||||
{
|
{
|
||||||
tx_socket.Init((UdpSocketOwner*) this,
|
tx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
||||||
(UdpSocketRecvHandler)&NormSession::TxSocketRecvHandler,
|
tx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::TxSocketRecvHandler);
|
||||||
sessionMgr.SocketInstaller(),
|
|
||||||
sessionMgr.SocketInstallData());
|
|
||||||
rx_socket.Init((UdpSocketOwner*) this,
|
|
||||||
(UdpSocketRecvHandler)&NormSession::RxSocketRecvHandler,
|
|
||||||
sessionMgr.SocketInstaller(),
|
|
||||||
sessionMgr.SocketInstallData());
|
|
||||||
|
|
||||||
tx_timer.Init(0.0, -1,
|
rx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
||||||
(ProtocolTimerOwner *)this,
|
rx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::RxSocketRecvHandler);
|
||||||
(ProtocolTimeoutFunc)&NormSession::OnTxTimeout);
|
|
||||||
repair_timer.Init(0.0, 1, (ProtocolTimerOwner*)this,
|
tx_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnTxTimeout);
|
||||||
(ProtocolTimeoutFunc)&NormSession::OnRepairTimeout);
|
tx_timer.SetInterval(0.0);
|
||||||
flush_timer.Init(0.0, 0, (ProtocolTimerOwner*)this,
|
tx_timer.SetRepeat(-1);
|
||||||
(ProtocolTimeoutFunc)&NormSession::OnFlushTimeout);
|
|
||||||
probe_timer.Init(0.0, -1, (ProtocolTimerOwner*)this,
|
repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnRepairTimeout);
|
||||||
(ProtocolTimeoutFunc)&NormSession::OnProbeTimeout);
|
repair_timer.SetInterval(0.0);
|
||||||
|
repair_timer.SetRepeat(1);
|
||||||
|
|
||||||
|
flush_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnFlushTimeout);
|
||||||
|
flush_timer.SetInterval(0.0);
|
||||||
|
flush_timer.SetRepeat(0);
|
||||||
|
|
||||||
|
probe_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnProbeTimeout);
|
||||||
|
probe_timer.SetInterval(0.0);
|
||||||
|
probe_timer.SetRepeat(-1);
|
||||||
|
|
||||||
grtt_quantized = NormQuantizeRtt(DEFAULT_GRTT_ESTIMATE);
|
grtt_quantized = NormQuantizeRtt(DEFAULT_GRTT_ESTIMATE);
|
||||||
grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized);
|
||||||
|
|
@ -65,8 +70,9 @@ 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.Init(30.0, -1, (ProtocolTimerOwner*)this,
|
report_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnReportTimeout);
|
||||||
(ProtocolTimeoutFunc)&NormSession::OnReportTimeout);
|
report_timer.SetInterval(10.0);
|
||||||
|
report_timer.SetRepeat(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NormSession::~NormSession()
|
NormSession::~NormSession()
|
||||||
|
|
@ -75,13 +81,12 @@ NormSession::~NormSession()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool NormSession::Open()
|
bool NormSession::Open()
|
||||||
{
|
{
|
||||||
ASSERT(address.IsValid());
|
ASSERT(address.IsValid());
|
||||||
if (!tx_socket.IsOpen())
|
if (!tx_socket.IsOpen())
|
||||||
{
|
{
|
||||||
if (UDP_SOCKET_ERROR_NONE != tx_socket.Open())
|
if (!tx_socket.Open())
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::Open() tx_socket open error\n");
|
DMSG(0, "NormSession::Open() tx_socket open error\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -89,7 +94,7 @@ bool NormSession::Open()
|
||||||
}
|
}
|
||||||
if (!rx_socket.IsOpen())
|
if (!rx_socket.IsOpen())
|
||||||
{
|
{
|
||||||
if (UDP_SOCKET_ERROR_NONE != rx_socket.Open(address.Port()))
|
if (!rx_socket.Open(address.GetPort()))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::Open() rx_socket open error\n");
|
DMSG(0, "NormSession::Open() rx_socket open error\n");
|
||||||
Close();
|
Close();
|
||||||
|
|
@ -99,13 +104,13 @@ bool NormSession::Open()
|
||||||
|
|
||||||
if (address.IsMulticast())
|
if (address.IsMulticast())
|
||||||
{
|
{
|
||||||
if (UDP_SOCKET_ERROR_NONE != rx_socket.JoinGroup(&address))
|
if (!rx_socket.JoinGroup(address))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::Open() rx_socket join group error\n");
|
DMSG(0, "NormSession::Open() rx_socket join group error\n");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (UDP_SOCKET_ERROR_NONE != tx_socket.SetTTL(ttl))
|
if (!tx_socket.SetTTL(ttl))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSession::Open() tx_socket set ttl error\n");
|
DMSG(0, "NormSession::Open() tx_socket set ttl error\n");
|
||||||
Close();
|
Close();
|
||||||
|
|
@ -126,7 +131,7 @@ bool NormSession::Open()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstallTimer(&report_timer);
|
ActivateTimer(report_timer);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // end NormSession::Open()
|
} // end NormSession::Open()
|
||||||
|
|
@ -142,7 +147,7 @@ void NormSession::Close()
|
||||||
if (tx_socket.IsOpen()) tx_socket.Close();
|
if (tx_socket.IsOpen()) tx_socket.Close();
|
||||||
if (rx_socket.IsOpen())
|
if (rx_socket.IsOpen())
|
||||||
{
|
{
|
||||||
if (address.IsMulticast()) rx_socket.LeaveGroup(&address);
|
if (address.IsMulticast()) rx_socket.LeaveGroup(address);
|
||||||
rx_socket.Close();
|
rx_socket.Close();
|
||||||
}
|
}
|
||||||
} // end NormSession::Close()
|
} // end NormSession::Close()
|
||||||
|
|
@ -226,8 +231,8 @@ 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);
|
||||||
OnProbeTimeout();
|
OnProbeTimeout(probe_timer);
|
||||||
InstallTimer(&probe_timer);
|
ActivateTimer(probe_timer);
|
||||||
return true;
|
return true;
|
||||||
} // end NormSession::StartServer()
|
} // end NormSession::StartServer()
|
||||||
|
|
||||||
|
|
@ -274,7 +279,7 @@ void NormSession::Serve()
|
||||||
// Queue next server message
|
// Queue next server message
|
||||||
if (tx_pending_mask.IsSet())
|
if (tx_pending_mask.IsSet())
|
||||||
{
|
{
|
||||||
NormObjectId objectId(tx_pending_mask.FirstSet());
|
NormObjectId objectId((unsigned short)tx_pending_mask.FirstSet());
|
||||||
obj = tx_table.Find(objectId);
|
obj = tx_table.Find(objectId);
|
||||||
ASSERT(obj);
|
ASSERT(obj);
|
||||||
}
|
}
|
||||||
|
|
@ -293,6 +298,7 @@ void NormSession::Serve()
|
||||||
|
|
||||||
if (obj)
|
if (obj)
|
||||||
{
|
{
|
||||||
|
|
||||||
NormObjectMsg* msg = (NormObjectMsg*)GetMessageFromPool();
|
NormObjectMsg* msg = (NormObjectMsg*)GetMessageFromPool();
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
|
|
@ -300,6 +306,7 @@ void NormSession::Serve()
|
||||||
{
|
{
|
||||||
msg->SetDestination(address);
|
msg->SetDestination(address);
|
||||||
msg->SetGrtt(grtt_quantized);
|
msg->SetGrtt(grtt_quantized);
|
||||||
|
msg->SetBackoffFactor((unsigned char)backoff_factor);
|
||||||
msg->SetGroupSize(gsize_quantized);
|
msg->SetGroupSize(gsize_quantized);
|
||||||
QueueMessage(msg);
|
QueueMessage(msg);
|
||||||
flush_count = 0;
|
flush_count = 0;
|
||||||
|
|
@ -378,8 +385,8 @@ void NormSession::ServerQueueFlush()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
objectId = obj->Id();
|
objectId = obj->Id();
|
||||||
blockId = obj->LastBlockId();
|
blockId = obj->GetFinalBlockId();
|
||||||
segmentId = obj->LastBlockSize() - 1;
|
segmentId = obj->GetBlockSize(blockId) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -389,7 +396,7 @@ void NormSession::ServerQueueFlush()
|
||||||
{
|
{
|
||||||
flush_count++;
|
flush_count++;
|
||||||
flush_timer.SetInterval(2*grtt_advertised);
|
flush_timer.SetInterval(2*grtt_advertised);
|
||||||
InstallTimer(&flush_timer);
|
ActivateTimer(flush_timer);
|
||||||
}
|
}
|
||||||
DMSG(8, "NormSession::ServerQueueFlush() node>%lu squelch queued (flush_count:%u)...\n",
|
DMSG(8, "NormSession::ServerQueueFlush() node>%lu squelch queued (flush_count:%u)...\n",
|
||||||
LocalNodeId(), flush_count);
|
LocalNodeId(), flush_count);
|
||||||
|
|
@ -401,6 +408,7 @@ void NormSession::ServerQueueFlush()
|
||||||
flush->Init();
|
flush->Init();
|
||||||
flush->SetDestination(address);
|
flush->SetDestination(address);
|
||||||
flush->SetGrtt(grtt_quantized);
|
flush->SetGrtt(grtt_quantized);
|
||||||
|
flush->SetBackoffFactor((unsigned char)backoff_factor);
|
||||||
flush->SetGroupSize(gsize_quantized);
|
flush->SetGroupSize(gsize_quantized);
|
||||||
flush->SetObjectId(objectId);
|
flush->SetObjectId(objectId);
|
||||||
flush->SetFecBlockId(blockId);
|
flush->SetFecBlockId(blockId);
|
||||||
|
|
@ -408,7 +416,7 @@ void NormSession::ServerQueueFlush()
|
||||||
QueueMessage(flush);
|
QueueMessage(flush);
|
||||||
flush_count++;
|
flush_count++;
|
||||||
flush_timer.SetInterval(2*grtt_advertised);
|
flush_timer.SetInterval(2*grtt_advertised);
|
||||||
InstallTimer(&flush_timer);
|
ActivateTimer(flush_timer);
|
||||||
DMSG(8, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n",
|
DMSG(8, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n",
|
||||||
LocalNodeId(), flush_count);
|
LocalNodeId(), flush_count);
|
||||||
}
|
}
|
||||||
|
|
@ -419,7 +427,7 @@ void NormSession::ServerQueueFlush()
|
||||||
}
|
}
|
||||||
} // end NormSession::ServerQueueFlush()
|
} // end NormSession::ServerQueueFlush()
|
||||||
|
|
||||||
bool NormSession::OnFlushTimeout()
|
bool NormSession::OnFlushTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
flush_timer.Deactivate();
|
flush_timer.Deactivate();
|
||||||
Serve(); // (TBD) Change this to PromptServer() ??
|
Serve(); // (TBD) Change this to PromptServer() ??
|
||||||
|
|
@ -432,7 +440,7 @@ void NormSession::QueueMessage(NormMsg* msg)
|
||||||
/* A little test jig
|
/* A little test jig
|
||||||
static struct timeval lastTime = {0,0};
|
static struct timeval lastTime = {0,0};
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
GetSystemTime(¤tTime);
|
ProtoSystemTime(currentTime);
|
||||||
if (0 != lastTime.tv_sec)
|
if (0 != lastTime.tv_sec)
|
||||||
{
|
{
|
||||||
double delta = currentTime.tv_sec - lastTime.tv_sec;
|
double delta = currentTime.tv_sec - lastTime.tv_sec;
|
||||||
|
|
@ -445,7 +453,7 @@ void NormSession::QueueMessage(NormMsg* msg)
|
||||||
if (!tx_timer.IsActive())
|
if (!tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
tx_timer.SetInterval(0.0);
|
tx_timer.SetInterval(0.0);
|
||||||
InstallTimer(&tx_timer);
|
ActivateTimer(tx_timer);
|
||||||
}
|
}
|
||||||
message_queue.Append(msg);
|
message_queue.Append(msg);
|
||||||
} // end NormSesssion::QueueMessage(NormMsg& msg)
|
} // end NormSesssion::QueueMessage(NormMsg& msg)
|
||||||
|
|
@ -682,40 +690,34 @@ char* NormSession::ServerGetFreeSegment(NormObjectId objectId,
|
||||||
return segment_pool.Get();
|
return segment_pool.Get();
|
||||||
} // end NormSession::ServerGetFreeSegment()
|
} // end NormSession::ServerGetFreeSegment()
|
||||||
|
|
||||||
bool NormSession::TxSocketRecvHandler(UdpSocket* /*theSocket*/)
|
void NormSession::TxSocketRecvHandler(ProtoSocket& /*theSocket*/,
|
||||||
|
ProtoSocket::Event /*theEvent*/)
|
||||||
{
|
{
|
||||||
NormMsg msg;
|
NormMsg msg;
|
||||||
unsigned int msgLength = NormMsg::MAX_SIZE;
|
unsigned int msgLength = NormMsg::MAX_SIZE;
|
||||||
if (UDP_SOCKET_ERROR_NONE == tx_socket.RecvFrom(msg.AccessBuffer(),
|
while (tx_socket.RecvFrom(msg.AccessBuffer(),
|
||||||
&msgLength,
|
msgLength,
|
||||||
msg.AccessAddress()))
|
msg.AccessAddress()))
|
||||||
{
|
{
|
||||||
msg.InitFromBuffer(msgLength);
|
msg.InitFromBuffer(msgLength);
|
||||||
HandleReceiveMessage(msg, true);
|
HandleReceiveMessage(msg, true);
|
||||||
|
msgLength = NormMsg::MAX_SIZE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
DMSG(0, "NormSession::TxSocketRecvHandler() recvfrom error");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} // end NormSession::TxSocketRecvHandler()
|
} // end NormSession::TxSocketRecvHandler()
|
||||||
|
|
||||||
bool NormSession::RxSocketRecvHandler(UdpSocket* /*theSocket*/)
|
void NormSession::RxSocketRecvHandler(ProtoSocket& /*theSocket*/,
|
||||||
|
ProtoSocket::Event /*theEvent*/)
|
||||||
{
|
{
|
||||||
NormMsg msg;
|
NormMsg msg;
|
||||||
unsigned int msgLength = NormMsg::MAX_SIZE;
|
unsigned int msgLength = NormMsg::MAX_SIZE;
|
||||||
if (UDP_SOCKET_ERROR_NONE == rx_socket.RecvFrom(msg.AccessBuffer(),
|
while (rx_socket.RecvFrom(msg.AccessBuffer(),
|
||||||
&msgLength,
|
msgLength,
|
||||||
msg.AccessAddress()))
|
msg.AccessAddress()))
|
||||||
{
|
{
|
||||||
msg.InitFromBuffer(msgLength);
|
msg.InitFromBuffer(msgLength);
|
||||||
HandleReceiveMessage(msg, false);
|
HandleReceiveMessage(msg, false);
|
||||||
|
msgLength = NormMsg::MAX_SIZE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
DMSG(0, "NormSession::RxSocketRecvHandler() recvfrom error");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} // end NormSession::RxSocketRecvHandler()
|
} // end NormSession::RxSocketRecvHandler()
|
||||||
|
|
||||||
void NormTrace(const struct timeval& currentTime,
|
void NormTrace(const struct timeval& currentTime,
|
||||||
|
|
@ -759,12 +761,12 @@ void NormTrace(const struct timeval& currentTime,
|
||||||
NormMsg::Type msgType = msg.GetType();
|
NormMsg::Type msgType = msg.GetType();
|
||||||
UINT16 length = msg.GetLength();
|
UINT16 length = msg.GetLength();
|
||||||
const char* status = sent ? "dst" : "src";
|
const char* status = sent ? "dst" : "src";
|
||||||
const NetworkAddress& addr = sent ? msg.GetDestination() : msg.GetSource();
|
const ProtoAddress& addr = sent ? msg.GetDestination() : msg.GetSource();
|
||||||
|
|
||||||
struct tm* ct = gmtime((time_t*)¤tTime.tv_sec);
|
struct tm* ct = gmtime((time_t*)¤tTime.tv_sec);
|
||||||
DMSG(0, "trace>%02d:%02d:%02d.%06lu node>%lu %s>%s ",
|
DMSG(0, "trace>%02d:%02d:%02d.%06lu node>%lu %s>%s ",
|
||||||
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec,
|
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec,
|
||||||
(UINT32)localId, status, addr.HostAddressString());
|
(UINT32)localId, status, addr.GetHostString());
|
||||||
bool clrFlag = false;
|
bool clrFlag = false;
|
||||||
switch (msgType)
|
switch (msgType)
|
||||||
{
|
{
|
||||||
|
|
@ -881,9 +883,8 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
::GetSystemTime(¤tTime);
|
::ProtoSystemTime(currentTime);
|
||||||
|
|
||||||
if (trace) NormTrace(currentTime, LocalNodeId(), msg, false);
|
if (trace) NormTrace(currentTime, LocalNodeId(), msg, false);
|
||||||
|
|
||||||
|
|
@ -894,10 +895,10 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
||||||
{
|
{
|
||||||
// (TBD) combine these as needed for efficiency
|
// (TBD) combine these as needed for efficiency
|
||||||
// (i.e. fewer function calls per message)
|
// (i.e. fewer function calls per message)
|
||||||
|
if (theServer->IsOpen()) theServer->Activate();
|
||||||
theServer->UpdateRecvRate(currentTime, msg.GetLength());
|
theServer->UpdateRecvRate(currentTime, msg.GetLength());
|
||||||
theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
|
theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
|
||||||
theServer->SetAddress(msg.GetSource());
|
theServer->SetAddress(msg.GetSource());
|
||||||
|
|
||||||
// for statistics only (TBD) #ifdef NORM_DEBUG
|
// for statistics only (TBD) #ifdef NORM_DEBUG
|
||||||
theServer->IncrementRecvTotal(msg.GetLength());
|
theServer->IncrementRecvTotal(msg.GetLength());
|
||||||
}
|
}
|
||||||
|
|
@ -929,7 +930,7 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
||||||
if (!tx_timer.IsActive())
|
if (!tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
tx_timer.SetInterval(0.0);
|
tx_timer.SetInterval(0.0);
|
||||||
InstallTimer(&tx_timer);
|
ActivateTimer(tx_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1083,7 +1084,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
double ccRtt,
|
double ccRtt,
|
||||||
double ccLoss,
|
double ccLoss,
|
||||||
double ccRate,
|
double ccRate,
|
||||||
UINT8 ccSequence)
|
UINT16 ccSequence)
|
||||||
{
|
{
|
||||||
// Keep track of current suppressing feedback
|
// Keep track of current suppressing feedback
|
||||||
// (non-CLR, lowest rate, unconfirmed RTT)
|
// (non-CLR, lowest rate, unconfirmed RTT)
|
||||||
|
|
@ -1123,14 +1124,14 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
// 1) Does this response replace the active CLR?
|
// 1) Does this response replace the active CLR?
|
||||||
if (next && next->IsActive())
|
if (next && next->IsActive())
|
||||||
{
|
{
|
||||||
if (ccRate < next->GetRate() || (nodeId == next->Id()))
|
if (ccRate < next->GetRate() || (nodeId == next->GetId()))
|
||||||
{
|
{
|
||||||
NormNodeId savedId = next->Id();
|
NormNodeId savedId = next->GetId();
|
||||||
bool savedRttStatus = next->HasRtt();
|
bool savedRttStatus = next->HasRtt();
|
||||||
double savedRtt = next->GetRtt();
|
double savedRtt = next->GetRtt();
|
||||||
double savedLoss = next->GetLoss();
|
double savedLoss = next->GetLoss();
|
||||||
double savedRate = next->GetRate();
|
double savedRate = next->GetRate();
|
||||||
UINT8 savedSequence = next->GetCCSequence();
|
UINT16 savedSequence = next->GetCCSequence();
|
||||||
|
|
||||||
next->SetId(nodeId);
|
next->SetId(nodeId);
|
||||||
next->SetClrStatus(true);
|
next->SetClrStatus(true);
|
||||||
|
|
@ -1139,7 +1140,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
next->SetRate(ccRate);
|
next->SetRate(ccRate);
|
||||||
next->SetCCSequence(ccSequence);
|
next->SetCCSequence(ccSequence);
|
||||||
next->SetActive(true);
|
next->SetActive(true);
|
||||||
if (next->Id() == nodeId)
|
if (next->GetId() == nodeId)
|
||||||
{
|
{
|
||||||
// This was feedback from the current CLR
|
// This was feedback from the current CLR
|
||||||
AdjustRate(true);
|
AdjustRate(true);
|
||||||
|
|
@ -1206,7 +1207,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
{
|
{
|
||||||
while ((next = (NormCCNode*)iterator.GetNextNode()))
|
while ((next = (NormCCNode*)iterator.GetNextNode()))
|
||||||
{
|
{
|
||||||
if (next->Id() == nodeId)
|
if (next->GetId() == nodeId)
|
||||||
{
|
{
|
||||||
candidate = next;
|
candidate = next;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1238,7 +1239,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
||||||
{
|
{
|
||||||
bool haveRtt = (0 != (ccFlags && NormCC::RTT));
|
bool haveRtt = (0 != (ccFlags && NormCC::RTT));
|
||||||
bool replace;
|
bool replace;
|
||||||
if (candidate->Id() == nodeId)
|
if (candidate->GetId() == nodeId)
|
||||||
replace = true;
|
replace = true;
|
||||||
else if (!candidate->IsActive())
|
else if (!candidate->IsActive())
|
||||||
replace = true;
|
replace = true;
|
||||||
|
|
@ -1297,7 +1298,7 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
|
||||||
if (!tx_timer.IsActive())
|
if (!tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
tx_timer.SetInterval(0.0);
|
tx_timer.SetInterval(0.0);
|
||||||
InstallTimer(&tx_timer);
|
ActivateTimer(tx_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1346,10 +1347,10 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
||||||
NormRepairRequest req;
|
NormRepairRequest req;
|
||||||
NormObject* object = NULL;
|
NormObject* object = NULL;
|
||||||
bool freshObject = true;
|
bool freshObject = true;
|
||||||
NormObjectId prevObjectId;
|
NormObjectId prevObjectId = 0;
|
||||||
NormBlock* block = NULL;
|
NormBlock* block = NULL;
|
||||||
bool freshBlock = true;
|
bool freshBlock = true;
|
||||||
NormBlockId prevBlockId;
|
NormBlockId prevBlockId = 0;
|
||||||
|
|
||||||
bool startTimer = false;
|
bool startTimer = false;
|
||||||
UINT16 numErasures = extra_parity;
|
UINT16 numErasures = extra_parity;
|
||||||
|
|
@ -1360,7 +1361,7 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
||||||
NormBlockId txBlockIndex;
|
NormBlockId txBlockIndex;
|
||||||
if (tx_pending_mask.IsSet())
|
if (tx_pending_mask.IsSet())
|
||||||
{
|
{
|
||||||
txObjectIndex = tx_pending_mask.FirstSet();
|
txObjectIndex = NormObjectId((unsigned short)tx_pending_mask.FirstSet());
|
||||||
NormObject* obj = tx_table.Find(txObjectIndex);
|
NormObject* obj = tx_table.Find(txObjectIndex);
|
||||||
ASSERT(obj);
|
ASSERT(obj);
|
||||||
if (obj->IsPending())
|
if (obj->IsPending())
|
||||||
|
|
@ -1382,7 +1383,7 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
||||||
txBlockIndex = 0;
|
txBlockIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool holdoff = (repair_timer.IsActive() && !repair_timer.RepeatCount());
|
bool holdoff = (repair_timer.IsActive() && !repair_timer.GetRepeatCount());
|
||||||
enum NormRequestLevel {SEGMENT, BLOCK, INFO, OBJECT};
|
enum NormRequestLevel {SEGMENT, BLOCK, INFO, OBJECT};
|
||||||
while ((requestLength = nack.UnpackRepairRequest(req, requestOffset)))
|
while ((requestLength = nack.UnpackRepairRequest(req, requestOffset)))
|
||||||
{
|
{
|
||||||
|
|
@ -1728,14 +1729,14 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
||||||
|
|
||||||
if (tx_timer.IsActive())
|
if (tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
double txTimeout = tx_timer.TimeRemaining() - 1.0e-06;
|
double txTimeout = tx_timer.GetTimeRemaining() - 1.0e-06;
|
||||||
aggregateInterval = MAX(txTimeout, aggregateInterval);
|
aggregateInterval = MAX(txTimeout, aggregateInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
repair_timer.SetInterval(aggregateInterval);
|
repair_timer.SetInterval(aggregateInterval);
|
||||||
DMSG(4, "NormSession::ServerHandleNackMessage() node>%lu starting server "
|
DMSG(4, "NormSession::ServerHandleNackMessage() node>%lu starting server "
|
||||||
"NACK aggregation timer (%lf sec)...\n", LocalNodeId(), aggregateInterval);
|
"NACK aggregation timer (%lf sec)...\n", LocalNodeId(), aggregateInterval);
|
||||||
InstallTimer(&repair_timer);
|
ActivateTimer(repair_timer);
|
||||||
}
|
}
|
||||||
} // end NormSession::ServerHandleNackMessage()
|
} // end NormSession::ServerHandleNackMessage()
|
||||||
|
|
||||||
|
|
@ -1778,6 +1779,7 @@ bool NormSession::ServerQueueSquelch(NormObjectId objectId)
|
||||||
squelch->Init();
|
squelch->Init();
|
||||||
squelch->SetDestination(address);
|
squelch->SetDestination(address);
|
||||||
squelch->SetGrtt(grtt_quantized);
|
squelch->SetGrtt(grtt_quantized);
|
||||||
|
squelch->SetBackoffFactor((unsigned char)backoff_factor);
|
||||||
squelch->SetGroupSize(gsize_quantized);
|
squelch->SetGroupSize(gsize_quantized);
|
||||||
NormObject* obj = tx_table.Find(objectId);
|
NormObject* obj = tx_table.Find(objectId);
|
||||||
NormObjectTable::Iterator iterator(tx_table);
|
NormObjectTable::Iterator iterator(tx_table);
|
||||||
|
|
@ -1933,9 +1935,9 @@ bool NormSession::ServerBuildRepairAdv(NormCmdRepairAdvMsg& cmd)
|
||||||
return true;
|
return true;
|
||||||
} // end NormSession::ServerBuildRepairAdv()
|
} // end NormSession::ServerBuildRepairAdv()
|
||||||
|
|
||||||
bool NormSession::OnRepairTimeout()
|
bool NormSession::OnRepairTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
if (repair_timer.RepeatCount())
|
if (repair_timer.GetRepeatCount())
|
||||||
{
|
{
|
||||||
// NACK aggregation period has ended. (incorporate accumulated repair requests)
|
// NACK aggregation period has ended. (incorporate accumulated repair requests)
|
||||||
DMSG(4, "NormSession::OnRepairTimeout() node>%lu server NACK aggregation time ended.\n",
|
DMSG(4, "NormSession::OnRepairTimeout() node>%lu server NACK aggregation time ended.\n",
|
||||||
|
|
@ -1994,9 +1996,9 @@ bool NormSession::OnRepairTimeout()
|
||||||
} // end NormSession::OnRepairTimeout()
|
} // end NormSession::OnRepairTimeout()
|
||||||
|
|
||||||
|
|
||||||
// (TBD) Should pass current system time to ProtocolTimer timeout handlers
|
// (TBD) Should pass current system time to ProtoTimer timeout handlers
|
||||||
// for more efficiency ...
|
// for more efficiency ...
|
||||||
bool NormSession::OnTxTimeout()
|
bool NormSession::OnTxTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
NormMsg* msg;
|
NormMsg* msg;
|
||||||
|
|
||||||
|
|
@ -2004,12 +2006,13 @@ bool NormSession::OnTxTimeout()
|
||||||
NormCmdRepairAdvMsg adv;
|
NormCmdRepairAdvMsg adv;
|
||||||
|
|
||||||
if (advertise_repairs && (probe_proactive || (repair_timer.IsActive() &&
|
if (advertise_repairs && (probe_proactive || (repair_timer.IsActive() &&
|
||||||
repair_timer.RepeatCount())))
|
repair_timer.GetRepeatCount())))
|
||||||
{
|
{
|
||||||
// Build a NORM_CMD(NACK_ADV) in response to
|
// Build a NORM_CMD(NACK_ADV) in response to
|
||||||
// receipt of unicast NACK or CC update
|
// receipt of unicast NACK or CC update
|
||||||
adv.Init();
|
adv.Init();
|
||||||
adv.SetGrtt(grtt_quantized);
|
adv.SetGrtt(grtt_quantized);
|
||||||
|
adv.SetBackoffFactor((unsigned char)backoff_factor);
|
||||||
adv.SetGroupSize(gsize_quantized);
|
adv.SetGroupSize(gsize_quantized);
|
||||||
adv.SetDestination(address);
|
adv.SetDestination(address);
|
||||||
|
|
||||||
|
|
@ -2044,11 +2047,19 @@ bool NormSession::OnTxTimeout()
|
||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
SendMessage(*msg);
|
if (SendMessage(*msg))
|
||||||
if (advertise_repairs)
|
{
|
||||||
advertise_repairs = false;
|
if (advertise_repairs)
|
||||||
|
advertise_repairs = false;
|
||||||
|
else
|
||||||
|
ReturnMessageToPool(msg);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ReturnMessageToPool(msg);
|
{
|
||||||
|
// Requeue the message for another try
|
||||||
|
if (!advertise_repairs)
|
||||||
|
message_queue.Prepend(msg);
|
||||||
|
}
|
||||||
return true; // reinstall tx_timer
|
return true; // reinstall tx_timer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2068,16 +2079,15 @@ bool NormSession::OnTxTimeout()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We have a new message as a result of serving, so send it immediately
|
// We have a new message as a result of serving, so send it immediately
|
||||||
OnTxTimeout();
|
return OnTxTimeout(tx_timer);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end NormSession::OnTxTimeout()
|
} // end NormSession::OnTxTimeout()
|
||||||
|
|
||||||
void NormSession::SendMessage(NormMsg& msg)
|
bool NormSession::SendMessage(NormMsg& msg)
|
||||||
{
|
{
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
GetSystemTime(¤tTime);
|
ProtoSystemTime(currentTime);
|
||||||
|
|
||||||
bool clientMsg = false;
|
bool clientMsg = false;
|
||||||
|
|
||||||
|
|
@ -2134,61 +2144,65 @@ void NormSession::SendMessage(NormMsg& msg)
|
||||||
msg.SetSequence(tx_sequence++);
|
msg.SetSequence(tx_sequence++);
|
||||||
msg.SetSourceId(local_node_id);
|
msg.SetSourceId(local_node_id);
|
||||||
UINT16 msgSize = msg.GetLength();
|
UINT16 msgSize = msg.GetLength();
|
||||||
|
bool result = true;
|
||||||
// Drop some tx messages for testing purposes
|
// Drop some tx messages for testing purposes
|
||||||
bool drop = (UniformRand(100.0) < tx_loss_rate);
|
bool drop = (UniformRand(100.0) < tx_loss_rate);
|
||||||
|
|
||||||
if (drop || (clientMsg && client_silent))
|
if (drop || (clientMsg && client_silent))
|
||||||
{
|
{
|
||||||
//TRACE("TX MESSAGE DROPPED! (tx_loss_rate:%lf\n", tx_loss_rate);
|
//TRACE("TX MESSAGE DROPPED! (tx_loss_rate:%lf\n", tx_loss_rate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (UDP_SOCKET_ERROR_NONE != tx_socket.SendTo(&msg.GetDestination(),
|
if (tx_socket.SendTo(msg.GetBuffer(),
|
||||||
msg.GetBuffer(),
|
msgSize,
|
||||||
msgSize))
|
msg.GetDestination()))
|
||||||
{
|
|
||||||
DMSG(0, "NormSession::SendMessage() sendto() error\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Separate send/recv tracing
|
// Separate send/recv tracing
|
||||||
if (trace) NormTrace(currentTime, LocalNodeId(), msg, true);
|
if (trace) NormTrace(currentTime, LocalNodeId(), msg, true);
|
||||||
}
|
|
||||||
// Keep track of _actual_ sent rate
|
// Keep track of _actual_ sent rate
|
||||||
double interval;
|
double interval;
|
||||||
if (prev_update_time.tv_sec || prev_update_time.tv_usec)
|
if (prev_update_time.tv_sec || prev_update_time.tv_usec)
|
||||||
{
|
{
|
||||||
interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
|
interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
|
||||||
if (currentTime.tv_usec > prev_update_time.tv_sec)
|
if (currentTime.tv_usec > prev_update_time.tv_sec)
|
||||||
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
|
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
|
||||||
|
else
|
||||||
|
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
|
{
|
||||||
|
sent_rate = ((double)msgSize) / grtt_advertised;
|
||||||
|
interval = -1.0;
|
||||||
|
prev_update_time = currentTime;
|
||||||
|
}
|
||||||
|
if (interval < grtt_advertised)
|
||||||
|
{
|
||||||
|
sent_accumulator += msgSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sent_rate = ((double)(sent_accumulator+msgSize)) / interval;
|
||||||
|
prev_update_time = currentTime;
|
||||||
|
sent_accumulator = 0;
|
||||||
|
}
|
||||||
|
// Update nominal packet size
|
||||||
|
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sent_rate = ((double)msgSize) / grtt_advertised;
|
DMSG(8, "NormSession::SendMessage() sendto() error\n");
|
||||||
interval = -1.0;
|
result = false;
|
||||||
prev_update_time = currentTime;
|
|
||||||
}
|
|
||||||
if (interval < grtt_advertised)
|
|
||||||
{
|
|
||||||
sent_accumulator += msgSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sent_rate = ((double)(sent_accumulator+msgSize)) / interval;
|
|
||||||
prev_update_time = currentTime;
|
|
||||||
sent_accumulator = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
|
|
||||||
tx_timer.SetInterval(((double)msgSize) / tx_rate);
|
tx_timer.SetInterval(((double)msgSize) / tx_rate);
|
||||||
|
return result;
|
||||||
} // end NormSession::SendMessage()
|
} // end NormSession::SendMessage()
|
||||||
|
|
||||||
bool NormSession::OnProbeTimeout()
|
bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
// 1) Update grtt_estimate _if_ sufficient time elapsed.
|
// 1) Update grtt_estimate _if_ sufficient time elapsed.
|
||||||
grtt_age += probe_timer.Interval();
|
grtt_age += probe_timer.GetInterval();
|
||||||
if (grtt_age >= grtt_interval)
|
if (grtt_age >= grtt_interval)
|
||||||
{
|
{
|
||||||
if (grtt_response)
|
if (grtt_response)
|
||||||
|
|
@ -2247,6 +2261,7 @@ bool NormSession::OnProbeTimeout()
|
||||||
cmd->Init();
|
cmd->Init();
|
||||||
cmd->SetDestination(address);
|
cmd->SetDestination(address);
|
||||||
cmd->SetGrtt(grtt_quantized);
|
cmd->SetGrtt(grtt_quantized);
|
||||||
|
cmd->SetBackoffFactor((unsigned char)backoff_factor);
|
||||||
cmd->SetGroupSize(gsize_quantized);
|
cmd->SetGroupSize(gsize_quantized);
|
||||||
// SetSendTime() when message is being sent (in OnTxTimeout())
|
// SetSendTime() when message is being sent (in OnTxTimeout())
|
||||||
cmd->SetCCSequence(cc_sequence++);
|
cmd->SetCCSequence(cc_sequence++);
|
||||||
|
|
@ -2276,7 +2291,7 @@ bool NormSession::OnProbeTimeout()
|
||||||
UINT16 rateQuantized = NormQuantizeRate(next->GetRate());
|
UINT16 rateQuantized = NormQuantizeRate(next->GetRate());
|
||||||
// (TBD) check result
|
// (TBD) check result
|
||||||
cmd->AppendCCNode(segment_size,
|
cmd->AppendCCNode(segment_size,
|
||||||
next->Id(),
|
next->GetId(),
|
||||||
ccFlags,
|
ccFlags,
|
||||||
rttQuantized,
|
rttQuantized,
|
||||||
rateQuantized);
|
rateQuantized);
|
||||||
|
|
@ -2368,16 +2383,16 @@ void NormSession::AdjustRate(bool onResponse)
|
||||||
tx_rate = MAX(tx_rate, minRate);
|
tx_rate = MAX(tx_rate, minRate);
|
||||||
|
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
::GetSystemTime(¤tTime);
|
::ProtoSystemTime(currentTime);
|
||||||
double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec);
|
double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec);
|
||||||
DMSG(6, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n", theTime, tx_rate * (8.0/1000.0), ccRtt, ccLoss);
|
DMSG(6, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n", theTime, tx_rate * (8.0/1000.0), ccRtt, ccLoss);
|
||||||
} // end NormSession::AdjustRate()
|
} // end NormSession::AdjustRate()
|
||||||
|
|
||||||
bool NormSession::OnReportTimeout()
|
bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
|
||||||
{
|
{
|
||||||
// Client reporting (just print out for now)
|
// Client reporting (just print out for now)
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
GetSystemTime(¤tTime);
|
ProtoSystemTime(currentTime);
|
||||||
struct tm* ct = gmtime((time_t*)¤tTime.tv_sec);
|
struct tm* ct = gmtime((time_t*)¤tTime.tv_sec);
|
||||||
DMSG(2, "Report time>%02d:%02d:%02d.%06lu node>%lu ***************************************\n",
|
DMSG(2, "Report time>%02d:%02d:%02d.%06lu node>%lu ***************************************\n",
|
||||||
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, LocalNodeId());
|
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, LocalNodeId());
|
||||||
|
|
@ -2387,9 +2402,9 @@ bool NormSession::OnReportTimeout()
|
||||||
NormServerNode* next;
|
NormServerNode* next;
|
||||||
while ((next = (NormServerNode*)iterator.GetNextNode()))
|
while ((next = (NormServerNode*)iterator.GetNextNode()))
|
||||||
{
|
{
|
||||||
DMSG(2, "Remote server:%lu\n", next->Id());
|
DMSG(2, "Remote server:%lu\n", next->GetId());
|
||||||
double rxRate = 8.0e-03*((double)next->RecvTotal()) / report_timer.Interval(); // kbps
|
double rxRate = 8.0e-03*((double)next->RecvTotal()) / report_timer.GetInterval(); // kbps
|
||||||
double rxGoodput = 8.0e-03*((double)next->RecvGoodput()) / report_timer.Interval(); // kbps
|
double rxGoodput = 8.0e-03*((double)next->RecvGoodput()) / report_timer.GetInterval(); // kbps
|
||||||
next->ResetRecvStats();
|
next->ResetRecvStats();
|
||||||
DMSG(2, " rx_rate>%9.3lf kbps rx_goodput>%9.3lf kbps\n", rxRate, rxGoodput);
|
DMSG(2, " rx_rate>%9.3lf kbps rx_goodput>%9.3lf kbps\n", rxRate, rxGoodput);
|
||||||
DMSG(2, " objects completed>%lu pending>%lu failed:%lu\n",
|
DMSG(2, " objects completed>%lu pending>%lu failed:%lu\n",
|
||||||
|
|
@ -2406,8 +2421,9 @@ bool NormSession::OnReportTimeout()
|
||||||
return true;
|
return true;
|
||||||
} // end NormSession::OnReportTimeout()
|
} // end NormSession::OnReportTimeout()
|
||||||
|
|
||||||
NormSessionMgr::NormSessionMgr()
|
NormSessionMgr::NormSessionMgr(ProtoTimerMgr& timerMgr,
|
||||||
: socket_installer(NULL), socket_install_data(NULL),
|
ProtoSocket::Notifier& socketNotifier)
|
||||||
|
: timer_mgr(timerMgr), socket_notifier(socketNotifier),
|
||||||
controller(NULL), top_session(NULL)
|
controller(NULL), top_session(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -2434,8 +2450,8 @@ NormSession* NormSessionMgr::NewSession(const char* sessionAddress,
|
||||||
if (NORM_NODE_ANY == localNodeId)
|
if (NORM_NODE_ANY == localNodeId)
|
||||||
{
|
{
|
||||||
// Use local ip address to assign default localNodeId
|
// Use local ip address to assign default localNodeId
|
||||||
NetworkAddress localAddr;
|
ProtoAddress localAddr;
|
||||||
if (!localAddr.LookupLocalHostAddress())
|
if (!localAddr.ResolveLocalAddress())
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSessionMgr::NewSession() local address lookup error\n");
|
DMSG(0, "NormSessionMgr::NewSession() local address lookup error\n");
|
||||||
return ((NormSession*)NULL);
|
return ((NormSession*)NULL);
|
||||||
|
|
@ -2443,8 +2459,8 @@ NormSession* NormSessionMgr::NewSession(const char* sessionAddress,
|
||||||
// (TBD) test IPv6 "EndIdentifier" ???
|
// (TBD) test IPv6 "EndIdentifier" ???
|
||||||
localNodeId = localAddr.EndIdentifier();
|
localNodeId = localAddr.EndIdentifier();
|
||||||
}
|
}
|
||||||
NetworkAddress theAddress;
|
ProtoAddress theAddress;
|
||||||
if (!theAddress.LookupHostAddress(sessionAddress))
|
if (!theAddress.ResolveFromString(sessionAddress))
|
||||||
{
|
{
|
||||||
DMSG(0, "NormSessionMgr::NewSession() session address lookup error!\n");
|
DMSG(0, "NormSessionMgr::NewSession() session address lookup error!\n");
|
||||||
return ((NormSession*)NULL);
|
return ((NormSession*)NULL);
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@
|
||||||
#include "normNode.h"
|
#include "normNode.h"
|
||||||
#include "normEncoder.h"
|
#include "normEncoder.h"
|
||||||
|
|
||||||
#include "protocolTimer.h"
|
#include "protokit.h"
|
||||||
#include "udpSocket.h"
|
|
||||||
|
|
||||||
|
|
||||||
class NormController
|
class NormController
|
||||||
{
|
{
|
||||||
|
|
@ -34,19 +32,11 @@ class NormSessionMgr
|
||||||
{
|
{
|
||||||
friend class NormSession;
|
friend class NormSession;
|
||||||
public:
|
public:
|
||||||
NormSessionMgr();
|
NormSessionMgr(ProtoTimerMgr& timerMgr,
|
||||||
|
ProtoSocket::Notifier& socketNotifier);
|
||||||
~NormSessionMgr();
|
~NormSessionMgr();
|
||||||
void Init(ProtocolTimerInstallFunc* timerInstaller,
|
void SetController(NormController* theController)
|
||||||
const void* timerInstallData,
|
{controller = theController;}
|
||||||
UdpSocketInstallFunc* socketInstaller,
|
|
||||||
void* socketInstallData,
|
|
||||||
NormController* theController)
|
|
||||||
{
|
|
||||||
timer_mgr.SetInstaller(timerInstaller, timerInstallData);
|
|
||||||
socket_installer = socketInstaller;
|
|
||||||
socket_install_data = socketInstallData;
|
|
||||||
controller = theController;
|
|
||||||
}
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
class NormSession* NewSession(const char* sessionAddress,
|
class NormSession* NewSession(const char* sessionAddress,
|
||||||
|
|
@ -55,10 +45,6 @@ class NormSessionMgr
|
||||||
NORM_NODE_ANY);
|
NORM_NODE_ANY);
|
||||||
void DeleteSession(class NormSession* theSession);
|
void DeleteSession(class NormSession* theSession);
|
||||||
|
|
||||||
|
|
||||||
UdpSocketInstallFunc* SocketInstaller() {return socket_installer;}
|
|
||||||
const void* SocketInstallData() {return socket_install_data;}
|
|
||||||
|
|
||||||
void Notify(NormController::Event event,
|
void Notify(NormController::Event event,
|
||||||
class NormSession* session,
|
class NormSession* session,
|
||||||
class NormServerNode* server,
|
class NormServerNode* server,
|
||||||
|
|
@ -68,12 +54,13 @@ class NormSessionMgr
|
||||||
controller->Notify(event, this, session, server, object);
|
controller->Notify(event, this, session, server, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallTimer(ProtocolTimer* timer) {timer_mgr.InstallTimer(timer);}
|
void ActivateTimer(ProtoTimer& timer) {timer_mgr.ActivateTimer(timer);}
|
||||||
|
ProtoTimerMgr& GetTimerMgr() {return timer_mgr;}
|
||||||
|
ProtoSocket::Notifier& GetSocketNotifier() {return socket_notifier;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProtocolTimerMgr timer_mgr;
|
ProtoTimerMgr& timer_mgr;
|
||||||
UdpSocketInstallFunc* socket_installer;
|
ProtoSocket::Notifier& socket_notifier;
|
||||||
const void* socket_install_data;
|
|
||||||
NormController* controller;
|
NormController* controller;
|
||||||
|
|
||||||
class NormSession* top_session; // top of NormSession list
|
class NormSession* top_session; // top of NormSession list
|
||||||
|
|
@ -104,8 +91,8 @@ class NormSession
|
||||||
bool Open();
|
bool Open();
|
||||||
void Close();
|
void Close();
|
||||||
bool IsOpen() {return (rx_socket.IsOpen() || tx_socket.IsOpen());}
|
bool IsOpen() {return (rx_socket.IsOpen() || tx_socket.IsOpen());}
|
||||||
const NetworkAddress& Address() {return address;}
|
const ProtoAddress& Address() {return address;}
|
||||||
void SetAddress(const NetworkAddress& addr) {address = addr;}
|
void SetAddress(const ProtoAddress& addr) {address = addr;}
|
||||||
static double CalculateRate(double size, double rtt, double loss);
|
static double CalculateRate(double size, double rtt, double loss);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -135,9 +122,8 @@ class NormSession
|
||||||
NormMsg* GetMessageFromPool() {return message_pool.RemoveHead();}
|
NormMsg* GetMessageFromPool() {return message_pool.RemoveHead();}
|
||||||
void ReturnMessageToPool(NormMsg* msg) {message_pool.Append(msg);}
|
void ReturnMessageToPool(NormMsg* msg) {message_pool.Append(msg);}
|
||||||
void QueueMessage(NormMsg* msg);
|
void QueueMessage(NormMsg* msg);
|
||||||
void SendMessage(NormMsg& msg);
|
bool SendMessage(NormMsg& msg);
|
||||||
void InstallTimer(ProtocolTimer* timer)
|
void ActivateTimer(ProtoTimer& timer) {session_mgr.ActivateTimer(timer);}
|
||||||
{session_mgr.InstallTimer(timer);}
|
|
||||||
|
|
||||||
// Server methods
|
// Server methods
|
||||||
void ServerSetBaseObjectId(NormObjectId baseId)
|
void ServerSetBaseObjectId(NormObjectId baseId)
|
||||||
|
|
@ -195,7 +181,7 @@ class NormSession
|
||||||
if (!tx_timer.IsActive())
|
if (!tx_timer.IsActive())
|
||||||
{
|
{
|
||||||
tx_timer.SetInterval(0.0);
|
tx_timer.SetInterval(0.0);
|
||||||
InstallTimer(&tx_timer);
|
ActivateTimer(tx_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,7 +213,7 @@ class NormSession
|
||||||
// Simulation specific methods
|
// Simulation specific methods
|
||||||
NormSimObject* QueueTxSim(unsigned long objectSize);
|
NormSimObject* QueueTxSim(unsigned long objectSize);
|
||||||
bool SimSocketRecvHandler(char* buffer, unsigned short buflen,
|
bool SimSocketRecvHandler(char* buffer, unsigned short buflen,
|
||||||
const NetworkAddress& src, bool unicast);
|
const ProtoAddress& src, bool unicast);
|
||||||
#endif // SIMULATE
|
#endif // SIMULATE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -239,15 +225,15 @@ class NormSession
|
||||||
bool QueueTxObject(NormObject* obj, bool touchServer = true);
|
bool QueueTxObject(NormObject* obj, bool touchServer = true);
|
||||||
void DeleteTxObject(NormObject* obj);
|
void DeleteTxObject(NormObject* obj);
|
||||||
|
|
||||||
bool OnTxTimeout();
|
bool OnTxTimeout(ProtoTimer& theTimer);
|
||||||
bool OnRepairTimeout();
|
bool OnRepairTimeout(ProtoTimer& theTimer);
|
||||||
bool OnFlushTimeout();
|
bool OnFlushTimeout(ProtoTimer& theTimer);
|
||||||
bool OnWatermarkTimeout();
|
bool OnWatermarkTimeout(ProtoTimer& theTimer);
|
||||||
bool OnProbeTimeout();
|
bool OnProbeTimeout(ProtoTimer& theTimer);
|
||||||
bool OnReportTimeout();
|
bool OnReportTimeout(ProtoTimer& theTimer);
|
||||||
|
|
||||||
bool TxSocketRecvHandler(UdpSocket* theSocket);
|
void TxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
|
||||||
bool RxSocketRecvHandler(UdpSocket* theSocket);
|
void RxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEve);
|
||||||
void HandleReceiveMessage(NormMsg& msg, bool wasUnicast);
|
void HandleReceiveMessage(NormMsg& msg, bool wasUnicast);
|
||||||
|
|
||||||
// Server message handling routines
|
// Server message handling routines
|
||||||
|
|
@ -264,7 +250,7 @@ class NormSession
|
||||||
double ccRtt,
|
double ccRtt,
|
||||||
double ccLoss,
|
double ccLoss,
|
||||||
double ccRate,
|
double ccRate,
|
||||||
UINT8 ccSequence);
|
UINT16 ccSequence);
|
||||||
void AdjustRate(bool onResponse);
|
void AdjustRate(bool onResponse);
|
||||||
bool ServerQueueSquelch(NormObjectId objectId);
|
bool ServerQueueSquelch(NormObjectId objectId);
|
||||||
void ServerQueueFlush();
|
void ServerQueueFlush();
|
||||||
|
|
@ -283,17 +269,17 @@ class NormSession
|
||||||
|
|
||||||
NormSessionMgr& session_mgr;
|
NormSessionMgr& session_mgr;
|
||||||
bool notify_pending;
|
bool notify_pending;
|
||||||
ProtocolTimer tx_timer;
|
ProtoTimer tx_timer;
|
||||||
UdpSocket tx_socket;
|
ProtoSocket tx_socket;
|
||||||
UdpSocket rx_socket;
|
ProtoSocket rx_socket;
|
||||||
NormMessageQueue message_queue;
|
NormMessageQueue message_queue;
|
||||||
NormMessageQueue message_pool;
|
NormMessageQueue message_pool;
|
||||||
ProtocolTimer report_timer;
|
ProtoTimer report_timer;
|
||||||
UINT16 tx_sequence;
|
UINT16 tx_sequence;
|
||||||
|
|
||||||
// General session parameters
|
// General session parameters
|
||||||
NormNodeId local_node_id;
|
NormNodeId local_node_id;
|
||||||
NetworkAddress address; // session destination address
|
ProtoAddress address; // session destination address
|
||||||
UINT8 ttl; // session multicast ttl
|
UINT8 ttl; // session multicast ttl
|
||||||
double tx_rate; // bytes per second
|
double tx_rate; // bytes per second
|
||||||
double backoff_factor;
|
double backoff_factor;
|
||||||
|
|
@ -310,7 +296,7 @@ class NormSession
|
||||||
NormObjectTable tx_table;
|
NormObjectTable tx_table;
|
||||||
NormSlidingMask tx_pending_mask;
|
NormSlidingMask tx_pending_mask;
|
||||||
NormSlidingMask tx_repair_mask;
|
NormSlidingMask tx_repair_mask;
|
||||||
ProtocolTimer repair_timer;
|
ProtoTimer repair_timer;
|
||||||
NormBlockPool block_pool;
|
NormBlockPool block_pool;
|
||||||
NormSegmentPool segment_pool;
|
NormSegmentPool segment_pool;
|
||||||
NormEncoder encoder;
|
NormEncoder encoder;
|
||||||
|
|
@ -319,10 +305,10 @@ class NormSession
|
||||||
unsigned int tx_cache_count_min;
|
unsigned int tx_cache_count_min;
|
||||||
unsigned int tx_cache_count_max;
|
unsigned int tx_cache_count_max;
|
||||||
NormObjectSize tx_cache_size_max;
|
NormObjectSize tx_cache_size_max;
|
||||||
ProtocolTimer flush_timer;
|
ProtoTimer flush_timer;
|
||||||
int flush_count;
|
int flush_count;
|
||||||
bool posted_tx_queue_empty;
|
bool posted_tx_queue_empty;
|
||||||
ProtocolTimer watermark_timer;
|
ProtoTimer watermark_timer;
|
||||||
int watermark_count;
|
int watermark_count;
|
||||||
// (TBD) watermark_object_id, watermark_block_id, watermark_symbol_id
|
// (TBD) watermark_object_id, watermark_block_id, watermark_symbol_id
|
||||||
|
|
||||||
|
|
@ -332,7 +318,7 @@ class NormSession
|
||||||
double suppress_rate;
|
double suppress_rate;
|
||||||
double suppress_rtt;
|
double suppress_rtt;
|
||||||
|
|
||||||
ProtocolTimer probe_timer; // GRTT/congestion control probes
|
ProtoTimer probe_timer; // GRTT/congestion control probes
|
||||||
bool probe_proactive;
|
bool probe_proactive;
|
||||||
|
|
||||||
double grtt_interval; // current GRTT update interval
|
double grtt_interval; // current GRTT update interval
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,9 @@
|
||||||
// of a message stream from the MGEN simulation agent with restrictions. The
|
// of a message stream from the MGEN simulation agent with restrictions. The
|
||||||
// current restriction is the MGEN simulation agent
|
// current restriction is the MGEN simulation agent
|
||||||
|
|
||||||
NormSimAgent::NormSimAgent(ProtocolTimerInstallFunc* timerInstaller,
|
NormSimAgent::NormSimAgent(ProtoTimerMgr& timerMgr,
|
||||||
const void* timerInstallData,
|
ProtoSocket::Notifier& socketNotifier)
|
||||||
UdpSocketInstallFunc* socketInstaller,
|
: session_mgr(timerMgr, socketNotifier), session(NULL),
|
||||||
void* socketInstallData)
|
|
||||||
: session(NULL),
|
|
||||||
address(NULL), port(0), ttl(3),
|
address(NULL), port(0), ttl(3),
|
||||||
tx_rate(NormSession::DEFAULT_TRANSMIT_RATE),
|
tx_rate(NormSession::DEFAULT_TRANSMIT_RATE),
|
||||||
cc_enable(false), unicast_nacks(false), silent_client(false),
|
cc_enable(false), unicast_nacks(false), silent_client(false),
|
||||||
|
|
@ -25,12 +23,12 @@ NormSimAgent::NormSimAgent(ProtocolTimerInstallFunc* timerInstaller,
|
||||||
tracing(false), tx_loss(0.0), rx_loss(0.0)
|
tracing(false), tx_loss(0.0), rx_loss(0.0)
|
||||||
{
|
{
|
||||||
// Bind NormSessionMgr to this agent and simulation environment
|
// Bind NormSessionMgr to this agent and simulation environment
|
||||||
session_mgr.Init(timerInstaller, timerInstallData,
|
session_mgr.SetController(static_cast<NormController*>(this));
|
||||||
socketInstaller, socketInstallData,
|
|
||||||
static_cast<NormController*>(this));
|
interval_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSimAgent::OnIntervalTimeout);
|
||||||
|
interval_timer.SetInterval(0.0);
|
||||||
|
interval_timer.SetRepeat(0);
|
||||||
|
|
||||||
interval_timer.Init(0.0, 0, (ProtocolTimerOwner*)this,
|
|
||||||
(ProtocolTimeoutFunc)&NormSimAgent::OnIntervalTimeout);
|
|
||||||
memset(mgen_buffer, 0, 64);
|
memset(mgen_buffer, 0, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -589,9 +587,9 @@ void NormSimAgent::Notify(NormController::Event event,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Schedule or queue next "sim file" transmission
|
// Schedule or queue next "sim file" transmission
|
||||||
if (interval_timer.Interval() > 0.0)
|
if (interval_timer.GetInterval() > 0.0)
|
||||||
{
|
{
|
||||||
InstallTimer(interval_timer);
|
ActivateTimer(interval_timer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -735,7 +733,9 @@ void NormSimAgent::Notify(NormController::Event event,
|
||||||
}
|
}
|
||||||
if (msg_sync && (0 == mgen_pending_bytes))
|
if (msg_sync && (0 == mgen_pending_bytes))
|
||||||
{
|
{
|
||||||
const NetworkAddress& srcAddr = server->GetAddress();
|
ProtoAddress srcAddr;
|
||||||
|
srcAddr.ResolveFromString(server->GetAddress().GetHostString());
|
||||||
|
srcAddr.SetPort(server->GetAddress().GetPort());
|
||||||
mgen->HandleMgenMessage(mgen_buffer, mgen_bytes, srcAddr);
|
mgen->HandleMgenMessage(mgen_buffer, mgen_bytes, srcAddr);
|
||||||
mgen_bytes = 0;
|
mgen_bytes = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
|
|
||||||
// normSimAgent.h - Generic (base class) NORM simulation agent
|
// normSimAgent.h - Generic (base class) NORM simulation agent
|
||||||
|
|
||||||
#include "protoLib.h"
|
|
||||||
#include "protoSim.h"
|
|
||||||
#include "normSession.h"
|
#include "normSession.h"
|
||||||
|
#include "protokit.h"
|
||||||
|
|
||||||
#include "mgen.h" // for MGEN instance attachment
|
#include "mgen.h" // for MGEN instance attachment
|
||||||
|
|
||||||
|
|
@ -25,10 +24,8 @@ class NormSimAgent : public NormController
|
||||||
void AttachMgen(Mgen* mgenInstance) {mgen = mgenInstance;}
|
void AttachMgen(Mgen* mgenInstance) {mgen = mgenInstance;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NormSimAgent(ProtocolTimerInstallFunc* timerInstaller,
|
NormSimAgent(ProtoTimerMgr& timerMgr,
|
||||||
const void* timerInstallData,
|
ProtoSocket::Notifier& socketNotifier);
|
||||||
UdpSocketInstallFunc* socketInstaller,
|
|
||||||
void* socketInstallData);
|
|
||||||
enum CmdType {CMD_INVALID, CMD_NOARG, CMD_ARG};
|
enum CmdType {CMD_INVALID, CMD_NOARG, CMD_ARG};
|
||||||
CmdType CommandType(const char* cmd);
|
CmdType CommandType(const char* cmd);
|
||||||
virtual unsigned long GetAgentId() = 0;
|
virtual unsigned long GetAgentId() = 0;
|
||||||
|
|
@ -42,8 +39,8 @@ class NormSimAgent : public NormController
|
||||||
class NormServerNode* server,
|
class NormServerNode* server,
|
||||||
class NormObject* object);
|
class NormObject* object);
|
||||||
|
|
||||||
void InstallTimer(ProtocolTimer& theTimer)
|
void ActivateTimer(ProtoTimer& theTimer)
|
||||||
{session_mgr.InstallTimer(&theTimer);}
|
{session_mgr.ActivateTimer(theTimer);}
|
||||||
|
|
||||||
bool OnIntervalTimeout();
|
bool OnIntervalTimeout();
|
||||||
|
|
||||||
|
|
@ -88,7 +85,7 @@ class NormSimAgent : public NormController
|
||||||
unsigned int mgen_bytes;
|
unsigned int mgen_bytes;
|
||||||
unsigned int mgen_pending_bytes;
|
unsigned int mgen_pending_bytes;
|
||||||
|
|
||||||
ProtocolTimer interval_timer;
|
ProtoTimer interval_timer;
|
||||||
|
|
||||||
// protocol debug parameters
|
// protocol debug parameters
|
||||||
bool tracing;
|
bool tracing;
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -32,6 +32,6 @@
|
||||||
|
|
||||||
#ifndef _NORM_VERSION
|
#ifndef _NORM_VERSION
|
||||||
#define _NORM_VERSION
|
#define _NORM_VERSION
|
||||||
#define VERSION "1.0b2"
|
#define VERSION "1.1b1"
|
||||||
#endif // _NORM_VERSION
|
#endif // _NORM_VERSION
|
||||||
|
|
||||||
|
|
@ -0,0 +1,576 @@
|
||||||
|
# Copyright (c) 1994, 1995, 1996
|
||||||
|
# The Regents of the University of California. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that: (1) source code distributions
|
||||||
|
# retain the above copyright notice and this paragraph in its entirety, (2)
|
||||||
|
# distributions including binary code include the above copyright notice and
|
||||||
|
# this paragraph in its entirety in the documentation or other materials
|
||||||
|
# provided with the distribution, and (3) all advertising materials mentioning
|
||||||
|
# features or use of this software display the following acknowledgement:
|
||||||
|
# ``This product includes software developed by the University of California,
|
||||||
|
# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
||||||
|
# the University nor the names of its contributors may be used to endorse
|
||||||
|
# or promote products derived from this software without specific prior
|
||||||
|
# written permission.
|
||||||
|
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
#
|
||||||
|
# @(#) $Header: 2002/10/09 15:34:11
|
||||||
|
|
||||||
|
#
|
||||||
|
# Various configurable paths (remember to edit Makefile.in, not Makefile)
|
||||||
|
#
|
||||||
|
|
||||||
|
# Top level hierarchy
|
||||||
|
prefix = @prefix@
|
||||||
|
# Pathname of directory to install the binary
|
||||||
|
BINDEST = @prefix@/bin
|
||||||
|
# Pathname of directory to install the man page
|
||||||
|
MANDEST = @prefix@/man
|
||||||
|
|
||||||
|
BLANK = # make a blank space. DO NOT add anything to this line
|
||||||
|
|
||||||
|
# The following will be redefined under Windows (see WIN32 lable below)
|
||||||
|
CC = @CC@
|
||||||
|
CPP = @CXX@
|
||||||
|
LINK = $(CPP)
|
||||||
|
MKDEP = ./conf/mkdep
|
||||||
|
TCLSH = @V_TCLSH@
|
||||||
|
TCL2C = @V_TCL2CPP@
|
||||||
|
AR = ar rc $(BLANK)
|
||||||
|
|
||||||
|
RANLIB = @V_RANLIB@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
LN = ln
|
||||||
|
TEST = test
|
||||||
|
RM = rm -f
|
||||||
|
MV = mv
|
||||||
|
PERL = @PERL@
|
||||||
|
|
||||||
|
# for diffusion
|
||||||
|
#DIFF_INCLUDES = "./diffusion3/main ./diffusion3/lib ./diffusion3/nr ./diffusion3/ns"
|
||||||
|
|
||||||
|
CCOPT = @V_CCOPT@
|
||||||
|
STATIC = @V_STATIC@
|
||||||
|
LDFLAGS = $(STATIC)
|
||||||
|
LDOUT = -o $(BLANK)
|
||||||
|
|
||||||
|
DEFINE = -DTCP_DELAY_BIND_ALL -DNO_TK @V_DEFINE@ @V_DEFINES@ @DEFS@ -DNS_DIFFUSION -DSMAC_NO_SYNC -DSTL_NAMESPACE=@STL_NAMESPACE@ -DUSE_SINGLE_ADDRESS_SPACE
|
||||||
|
|
||||||
|
# NRL additions for Protolib, MDP, and NORM extensions
|
||||||
|
PROTOLIB_INCLUDES = -Iprotolib/common -Iprotolib/ns
|
||||||
|
MDP_INCLUDES = -Imdp/common -Imdp/ns -Imdp/unix
|
||||||
|
NORM_INCLUDES = -Inorm/common -Inorm/ns
|
||||||
|
MGEN_INCLUDES = -Imgen/common -Imgen/ns
|
||||||
|
NRL_INCLUDES = $(PROTOLIB_INCLUDES) $(MDP_INCLUDES) $(NORM_INCLUDES) $(MGEN_INCLUDES)
|
||||||
|
|
||||||
|
INCLUDES = \
|
||||||
|
-I. @V_INCLUDE_X11@ \
|
||||||
|
@V_INCLUDES@ \
|
||||||
|
-I./tcp -I./common -I./link -I./queue \
|
||||||
|
-I./adc -I./apps -I./mac -I./mobile -I./trace \
|
||||||
|
-I./routing -I./tools -I./classifier -I./mcast \
|
||||||
|
-I./diffusion3/lib/main -I./diffusion3/lib \
|
||||||
|
-I./diffusion3/lib/nr -I./diffusion3/ns \
|
||||||
|
-I./diffusion3/diffusion -I./asim/ -I./qs \
|
||||||
|
$(NRL_INCLUDES)
|
||||||
|
|
||||||
|
|
||||||
|
LIB = \
|
||||||
|
@V_LIBS@ \
|
||||||
|
@V_LIB_X11@ \
|
||||||
|
@V_LIB@ \
|
||||||
|
-lm @LIBS@
|
||||||
|
# -L@libdir@ \
|
||||||
|
|
||||||
|
# Additional flags for NRL Protolib/MDP/NORM extensions
|
||||||
|
# These flags have been tested on Linux
|
||||||
|
NRL_CFLAGS = -g -DNS2 -DSIMULATE -DUNIX -DPROTO_DEBUG -DHAVE_ASSERT -DHAVE_DIRFD
|
||||||
|
|
||||||
|
|
||||||
|
CFLAGS = $(CCOPT) $(DEFINE) $(NRL_CFLAGS)
|
||||||
|
|
||||||
|
# Explicitly define compilation rules since SunOS 4's make doesn't like gcc.
|
||||||
|
# Also, gcc does not remove the .o before forking 'as', which can be a
|
||||||
|
# problem if you don't own the file but can write to the directory.
|
||||||
|
# NRL Protolib/MDP/NORM code uses .cpp files so we added a suffix and rule
|
||||||
|
.SUFFIXES: .cc .cpp # $(.SUFFIXES)
|
||||||
|
|
||||||
|
.cc.o:
|
||||||
|
@rm -f $@
|
||||||
|
$(CPP) -c $(CFLAGS) $(INCLUDES) -o $@ $*.cc
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@rm -f $@
|
||||||
|
$(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $*.c
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
@rm -f $@
|
||||||
|
$(CPP) -c $(CFLAGS) $(INCLUDES) -o $@ $*.cpp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GEN_DIR = gen/
|
||||||
|
LIB_DIR = lib/
|
||||||
|
NS = ns
|
||||||
|
NSX = nsx
|
||||||
|
NSE = nse
|
||||||
|
|
||||||
|
# To allow conf/makefile.win overwrite this macro
|
||||||
|
# We will set these two macros to empty in conf/makefile.win since VC6.0
|
||||||
|
# does not seem to support the STL in gcc 2.8 and up.
|
||||||
|
OBJ_STL = diffusion3/lib/nr/nr.o diffusion3/lib/dr.o \
|
||||||
|
diffusion3/ns/diffagent.o diffusion3/ns/diffrtg.o \
|
||||||
|
diffusion3/ns/difftimer.o \
|
||||||
|
diffusion3/diffusion/diffusion.o \
|
||||||
|
diffusion3/lib/main/attrs.o \
|
||||||
|
diffusion3/lib/main/iodev.o \
|
||||||
|
diffusion3/lib/main/timers.o \
|
||||||
|
diffusion3/lib/main/events.o \
|
||||||
|
diffusion3/lib/main/message.o \
|
||||||
|
diffusion3/lib/main/stats.o \
|
||||||
|
diffusion3/lib/main/tools.o \
|
||||||
|
diffusion3/lib/drivers/rpc_stats.o \
|
||||||
|
diffusion3/apps/sysfilters/gradient.o \
|
||||||
|
diffusion3/apps/sysfilters/log.o \
|
||||||
|
diffusion3/apps/sysfilters/tag.o \
|
||||||
|
diffusion3/apps/sysfilters/srcrt.o \
|
||||||
|
diffusion3/lib/diffapp.o \
|
||||||
|
diffusion3/apps/pingapp/ping_sender.o \
|
||||||
|
diffusion3/apps/pingapp/ping_receiver.o \
|
||||||
|
diffusion3/apps/pingapp/ping_common.o \
|
||||||
|
diffusion3/apps/pingapp/push_receiver.o \
|
||||||
|
diffusion3/apps/pingapp/push_sender.o \
|
||||||
|
diffusion3/apps/gear/geo-attr.o \
|
||||||
|
diffusion3/apps/gear/geo-routing.o \
|
||||||
|
diffusion3/apps/gear/geo-tools.o \
|
||||||
|
nix/hdr_nv.o nix/classifier-nix.o \
|
||||||
|
nix/nixnode.o nix/nixvec.o \
|
||||||
|
nix/nixroute.o
|
||||||
|
|
||||||
|
NS_TCL_LIB_STL = tcl/lib/ns-diffusion.tcl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# WIN32: uncomment the following line to include specific make for VC++
|
||||||
|
# !include <conf/makefile.win>
|
||||||
|
|
||||||
|
OBJ_CC = \
|
||||||
|
tools/random.o tools/rng.o tools/ranvar.o common/misc.o common/timer-handler.o \
|
||||||
|
common/scheduler.o common/object.o common/packet.o \
|
||||||
|
common/ip.o routing/route.o common/connector.o common/ttl.o \
|
||||||
|
trace/trace.o trace/trace-ip.o \
|
||||||
|
classifier/classifier.o classifier/classifier-addr.o \
|
||||||
|
classifier/classifier-hash.o \
|
||||||
|
classifier/classifier-virtual.o \
|
||||||
|
classifier/classifier-mcast.o \
|
||||||
|
classifier/classifier-bst.o \
|
||||||
|
classifier/classifier-mpath.o mcast/replicator.o \
|
||||||
|
classifier/classifier-mac.o \
|
||||||
|
classifier/classifier-qs.o \
|
||||||
|
classifier/classifier-port.o src_rtg/classifier-sr.o \
|
||||||
|
src_rtg/sragent.o src_rtg/hdr_src.o adc/ump.o \
|
||||||
|
qs/qsagent.o qs/hdr_qs.o \
|
||||||
|
apps/app.o apps/telnet.o tcp/tcplib-telnet.o \
|
||||||
|
tools/trafgen.o trace/traffictrace.o tools/pareto.o \
|
||||||
|
tools/expoo.o tools/cbr_traffic.o \
|
||||||
|
adc/tbf.o adc/resv.o adc/sa.o tcp/saack.o \
|
||||||
|
tools/measuremod.o adc/estimator.o adc/adc.o adc/ms-adc.o \
|
||||||
|
adc/timewindow-est.o adc/acto-adc.o \
|
||||||
|
adc/pointsample-est.o adc/salink.o adc/actp-adc.o \
|
||||||
|
adc/hb-adc.o adc/expavg-est.o\
|
||||||
|
adc/param-adc.o adc/null-estimator.o \
|
||||||
|
adc/adaptive-receiver.o apps/vatrcvr.o adc/consrcvr.o \
|
||||||
|
common/agent.o common/message.o apps/udp.o \
|
||||||
|
common/session-rtp.o apps/rtp.o tcp/rtcp.o \
|
||||||
|
common/ivs.o \
|
||||||
|
tcp/tcp.o tcp/tcp-sink.o tcp/tcp-reno.o \
|
||||||
|
tcp/tcp-newreno.o \
|
||||||
|
tcp/tcp-vegas.o tcp/tcp-rbp.o tcp/tcp-full.o tcp/rq.o \
|
||||||
|
baytcp/tcp-full-bay.o baytcp/ftpc.o baytcp/ftps.o \
|
||||||
|
tcp/scoreboard.o tcp/scoreboard-rq.o tcp/tcp-sack1.o tcp/tcp-fack.o \
|
||||||
|
tcp/tcp-asym.o tcp/tcp-asym-sink.o tcp/tcp-fs.o \
|
||||||
|
tcp/tcp-asym-fs.o tcp/tcp-qs.o \
|
||||||
|
tcp/tcp-int.o tcp/chost.o tcp/tcp-session.o \
|
||||||
|
tcp/nilist.o \
|
||||||
|
tools/integrator.o tools/queue-monitor.o \
|
||||||
|
tools/flowmon.o tools/loss-monitor.o \
|
||||||
|
queue/queue.o queue/drop-tail.o \
|
||||||
|
adc/simple-intserv-sched.o queue/red.o \
|
||||||
|
queue/semantic-packetqueue.o queue/semantic-red.o \
|
||||||
|
tcp/ack-recons.o \
|
||||||
|
queue/sfq.o queue/fq.o queue/drr.o queue/srr.o queue/cbq.o \
|
||||||
|
queue/jobs.o queue/marker.o queue/demarker.o \
|
||||||
|
link/hackloss.o queue/errmodel.o queue/fec.o\
|
||||||
|
link/delay.o tcp/snoop.o \
|
||||||
|
gaf/gaf.o \
|
||||||
|
link/dynalink.o routing/rtProtoDV.o common/net-interface.o \
|
||||||
|
mcast/ctrMcast.o mcast/mcast_ctrl.o mcast/srm.o \
|
||||||
|
common/sessionhelper.o queue/delaymodel.o \
|
||||||
|
mcast/srm-ssm.o mcast/srm-topo.o \
|
||||||
|
apps/mftp.o apps/mftp_snd.o apps/mftp_rcv.o \
|
||||||
|
apps/codeword.o \
|
||||||
|
routing/alloc-address.o routing/address.o \
|
||||||
|
$(LIB_DIR)int.Vec.o $(LIB_DIR)int.RVec.o \
|
||||||
|
$(LIB_DIR)dmalloc_support.o \
|
||||||
|
webcache/http.o webcache/tcp-simple.o webcache/pagepool.o \
|
||||||
|
webcache/inval-agent.o webcache/tcpapp.o webcache/http-aux.o \
|
||||||
|
webcache/mcache.o webcache/webtraf.o \
|
||||||
|
webcache/webserver.o \
|
||||||
|
webcache/logweb.o \
|
||||||
|
empweb/empweb.o \
|
||||||
|
empweb/empftp.o \
|
||||||
|
realaudio/realaudio.o \
|
||||||
|
mac/lanRouter.o classifier/filter.o \
|
||||||
|
common/pkt-counter.o \
|
||||||
|
common/Decapsulator.o common/Encapsulator.o \
|
||||||
|
common/encap.o \
|
||||||
|
mac/channel.o mac/mac.o mac/ll.o mac/mac-802_11.o \
|
||||||
|
mac/mac-802_3.o mac/mac-tdma.o mac/smac.o \
|
||||||
|
mobile/mip.o mobile/mip-reg.o mobile/gridkeeper.o \
|
||||||
|
mobile/propagation.o mobile/tworayground.o \
|
||||||
|
mobile/antenna.o mobile/omni-antenna.o \
|
||||||
|
mobile/shadowing.o mobile/shadowing-vis.o mobile/dumb-agent.o \
|
||||||
|
common/bi-connector.o common/node.o \
|
||||||
|
common/mobilenode.o \
|
||||||
|
mac/arp.o mobile/god.o mobile/dem.o \
|
||||||
|
mobile/topography.o mobile/modulation.o \
|
||||||
|
queue/priqueue.o queue/dsr-priqueue.o \
|
||||||
|
mac/phy.o mac/wired-phy.o mac/wireless-phy.o \
|
||||||
|
mac/mac-timers.o trace/cmu-trace.o mac/varp.o \
|
||||||
|
dsdv/dsdv.o dsdv/rtable.o queue/rtqueue.o \
|
||||||
|
routing/rttable.o \
|
||||||
|
imep/imep.o imep/dest_queue.o imep/imep_api.o \
|
||||||
|
imep/imep_rt.o imep/rxmit_queue.o imep/imep_timers.o \
|
||||||
|
imep/imep_util.o imep/imep_io.o \
|
||||||
|
tora/tora.o tora/tora_api.o tora/tora_dest.o \
|
||||||
|
tora/tora_io.o tora/tora_logs.o tora/tora_neighbor.o \
|
||||||
|
dsr/dsragent.o dsr/hdr_sr.o dsr/mobicache.o dsr/path.o \
|
||||||
|
dsr/requesttable.o dsr/routecache.o dsr/add_sr.o \
|
||||||
|
dsr/dsr_proto.o dsr/flowstruct.o dsr/linkcache.o \
|
||||||
|
dsr/simplecache.o dsr/sr_forwarder.o \
|
||||||
|
aodv/aodv_logs.o aodv/aodv.o \
|
||||||
|
aodv/aodv_rtable.o aodv/aodv_rqueue.o \
|
||||||
|
common/ns-process.o \
|
||||||
|
satellite/satgeometry.o satellite/sathandoff.o \
|
||||||
|
satellite/satlink.o satellite/satnode.o \
|
||||||
|
satellite/satposition.o satellite/satroute.o \
|
||||||
|
satellite/sattrace.o \
|
||||||
|
rap/raplist.o rap/rap.o rap/media-app.o rap/utilities.o \
|
||||||
|
common/fsm.o tcp/tcp-abs.o \
|
||||||
|
diffusion/diffusion.o diffusion/diff_rate.o diffusion/diff_prob.o \
|
||||||
|
diffusion/diff_sink.o diffusion/flooding.o diffusion/omni_mcast.o \
|
||||||
|
diffusion/hash_table.o diffusion/routing_table.o diffusion/iflist.o \
|
||||||
|
tcp/tfrc.o tcp/tfrc-sink.o mobile/energy-model.o apps/ping.o tcp/tcp-rfc793edu.o \
|
||||||
|
queue/rio.o queue/semantic-rio.o tcp/tcp-sack-rh.o tcp/scoreboard-rh.o \
|
||||||
|
plm/loss-monitor-plm.o plm/cbr-traffic-PP.o \
|
||||||
|
linkstate/hdr-ls.o \
|
||||||
|
mpls/classifier-addr-mpls.o mpls/ldp.o mpls/mpls-module.o \
|
||||||
|
routing/rtmodule.o classifier/classifier-hier.o \
|
||||||
|
routing/addr-params.o \
|
||||||
|
routealgo/rnode.o \
|
||||||
|
routealgo/bfs.o \
|
||||||
|
routealgo/rbitmap.o \
|
||||||
|
routealgo/rlookup.o \
|
||||||
|
routealgo/routealgo.o \
|
||||||
|
diffserv/dsred.o diffserv/dsredq.o \
|
||||||
|
diffserv/dsEdge.o diffserv/dsCore.o \
|
||||||
|
diffserv/dsPolicy.o diffserv/ew.o\
|
||||||
|
queue/red-pd.o queue/pi.o queue/vq.o queue/rem.o \
|
||||||
|
queue/gk.o \
|
||||||
|
pushback/rate-limit.o pushback/rate-limit-strategy.o \
|
||||||
|
pushback/ident-tree.o pushback/agg-spec.o \
|
||||||
|
pushback/logging-data-struct.o \
|
||||||
|
pushback/rate-estimator.o \
|
||||||
|
pushback/pushback-queue.o pushback/pushback.o \
|
||||||
|
common/parentnode.o trace/basetrace.o \
|
||||||
|
common/simulator.o asim/asim.o \
|
||||||
|
common/scheduler-map.o common/splay-scheduler.o \
|
||||||
|
linkstate/ls.o linkstate/rtProtoLS.o \
|
||||||
|
pgm/classifier-pgm.o pgm/pgm-agent.o pgm/pgm-sender.o \
|
||||||
|
pgm/pgm-receiver.o mcast/rcvbuf.o \
|
||||||
|
mcast/classifier-lms.o mcast/lms-agent.o mcast/lms-receiver.o \
|
||||||
|
mcast/lms-sender.o \
|
||||||
|
@V_STLOBJ@
|
||||||
|
|
||||||
|
|
||||||
|
# don't allow comments to follow continuation lines
|
||||||
|
|
||||||
|
# mac-csma.o mac-multihop.o\
|
||||||
|
# sensor-nets/landmark.o mac-simple-wireless.o \
|
||||||
|
# sensor-nets/tags.o sensor-nets/sensor-query.o \
|
||||||
|
# sensor-nets/flood-agent.o \
|
||||||
|
|
||||||
|
# what was here before is now in emulate/
|
||||||
|
OBJ_C =
|
||||||
|
|
||||||
|
OBJ_COMPAT = $(OBJ_GETOPT) common/win32.o
|
||||||
|
#XXX compat/win32x.o compat/tkConsole.o
|
||||||
|
|
||||||
|
OBJ_EMULATE_CC = \
|
||||||
|
emulate/net-ip.o \
|
||||||
|
emulate/net.o \
|
||||||
|
emulate/tap.o \
|
||||||
|
emulate/ether.o \
|
||||||
|
emulate/internet.o \
|
||||||
|
emulate/ping_responder.o \
|
||||||
|
emulate/arp.o \
|
||||||
|
emulate/icmp.o \
|
||||||
|
emulate/net-pcap.o \
|
||||||
|
emulate/nat.o \
|
||||||
|
emulate/iptap.o \
|
||||||
|
emulate/tcptap.o
|
||||||
|
|
||||||
|
OBJ_EMULATE_C = \
|
||||||
|
emulate/inet.o
|
||||||
|
|
||||||
|
OBJ_GEN = $(GEN_DIR)version.o $(GEN_DIR)ns_tcl.o $(GEN_DIR)ptypes.o
|
||||||
|
|
||||||
|
#NRL additions
|
||||||
|
OBJ_PROTOLIB_CPP = \
|
||||||
|
protolib/ns/nsProtoSimAgent.o protolib/common/protoSimAgent.o \
|
||||||
|
protolib/common/protoSimSocket.o protolib/common/protoAddress.o \
|
||||||
|
protolib/common/protoTimer.o protolib/common/protoExample.o \
|
||||||
|
protolib/common/protoDebug.o
|
||||||
|
|
||||||
|
OBJ_MDP_CPP = \
|
||||||
|
mdp/ns/nsMdpAgent.o mdp/common/mdpSimAgent.o \
|
||||||
|
mdp/common/mdpBitMask.o mdp/common/mdpMessage.o \
|
||||||
|
mdp/common/mdpEncoder.o mdp/common/galois.o \
|
||||||
|
mdp/common/mdpSession.o mdp/common/mdpMsgHandler.o \
|
||||||
|
mdp/common/mdpNode.o mdp/common/mdpObject.o \
|
||||||
|
mdp/unix/mdpFile.o
|
||||||
|
|
||||||
|
OBJ_NORM_CPP = \
|
||||||
|
norm/ns/nsNormAgent.o norm/common/normSimAgent.o \
|
||||||
|
norm/common/normMessage.o norm/common/normSession.o \
|
||||||
|
norm/common/normNode.o norm/common/normObject.o \
|
||||||
|
norm/common/normSegment.o norm/common/normBitmask.o \
|
||||||
|
norm/common/normEncoder.o norm/common/galois.o \
|
||||||
|
norm/common/normFile.o
|
||||||
|
|
||||||
|
OBJ_MGEN_CPP = \
|
||||||
|
mgen/ns/nsMgenAgent.o \
|
||||||
|
mgen/common/mgen.o mgen/common/mgenEvent.o \
|
||||||
|
mgen/common/mgenFlow.o mgen/common/mgenMsg.o \
|
||||||
|
mgen/common/mgenSocketList.o mgen/common/mgenPattern.o
|
||||||
|
|
||||||
|
OBJ_CPP = $(OBJ_PROTOLIB_CPP) $(OBJ_MDP_CPP) $(OBJ_NORM_CPP) $(OBJ_MGEN_CPP)
|
||||||
|
|
||||||
|
SRC = $(OBJ_C:.o=.c) $(OBJ_CC:.o=.cc) \
|
||||||
|
$(OBJ_EMULATE_C:.o=.c) $(OBJ_EMULATE_CC:.o=.cc) \
|
||||||
|
common/tclAppInit.cc common/tkAppInit.cc
|
||||||
|
|
||||||
|
OBJ = $(OBJ_C) $(OBJ_CC) $(OBJ_GEN) $(OBJ_COMPAT) $(OBJ_CPP)
|
||||||
|
|
||||||
|
CLEANFILES = ns nse nsx ns.dyn $(OBJ) $(OBJ_EMULATE_CC) \
|
||||||
|
$(OBJ_EMULATE_C) common/tclAppInit.o \
|
||||||
|
$(GEN_DIR)* $(NS).core core core.$(NS) core.$(NSX) core.$(NSE) \
|
||||||
|
common/ptypes2tcl common/ptypes2tcl.o
|
||||||
|
|
||||||
|
SUBDIRS=\
|
||||||
|
indep-utils/cmu-scen-gen/setdest \
|
||||||
|
indep-utils/webtrace-conv/dec \
|
||||||
|
indep-utils/webtrace-conv/epa \
|
||||||
|
indep-utils/webtrace-conv/nlanr \
|
||||||
|
indep-utils/webtrace-conv/ucb
|
||||||
|
|
||||||
|
BUILD_NSE = @build_nse@
|
||||||
|
|
||||||
|
all: $(NS) $(BUILD_NSE) all-recursive
|
||||||
|
|
||||||
|
|
||||||
|
all-recursive:
|
||||||
|
for i in $(SUBDIRS); do ( cd $$i; $(MAKE) all; ) done
|
||||||
|
|
||||||
|
$(NS): $(OBJ) common/tclAppInit.o Makefile
|
||||||
|
$(LINK) $(LDFLAGS) $(LDOUT)$@ \
|
||||||
|
common/tclAppInit.o $(OBJ) $(LIB)
|
||||||
|
|
||||||
|
Makefile: Makefile.in
|
||||||
|
@echo "Makefile.in is newer than Makefile."
|
||||||
|
@echo "You need to re-run configure."
|
||||||
|
false
|
||||||
|
|
||||||
|
$(NSE): $(OBJ) common/tclAppInit.o $(OBJ_EMULATE_CC) $(OBJ_EMULATE_C)
|
||||||
|
$(LINK) $(LDFLAGS) $(LDOUT)$@ \
|
||||||
|
common/tclAppInit.o $(OBJ) \
|
||||||
|
$(OBJ_EMULATE_CC) $(OBJ_EMULATE_C) $(LIB)
|
||||||
|
|
||||||
|
ns.dyn: $(OBJ) common/tclAppInit.o
|
||||||
|
$(LINK) $(LDFLAGS) -o $@ \
|
||||||
|
common/tclAppInit.o $(OBJ) $(LIB)
|
||||||
|
|
||||||
|
PURIFY = purify -cache-dir=/tmp
|
||||||
|
ns-pure: $(OBJ) common/tclAppInit.o
|
||||||
|
$(PURIFY) $(LINK) $(LDFLAGS) -o $@ \
|
||||||
|
common/tclAppInit.o $(OBJ) $(LIB)
|
||||||
|
|
||||||
|
NS_TCL_LIB = \
|
||||||
|
tcl/lib/ns-compat.tcl \
|
||||||
|
tcl/lib/ns-default.tcl \
|
||||||
|
tcl/lib/ns-errmodel.tcl \
|
||||||
|
tcl/lib/ns-lib.tcl \
|
||||||
|
tcl/lib/ns-link.tcl \
|
||||||
|
tcl/lib/ns-mobilenode.tcl \
|
||||||
|
tcl/lib/ns-sat.tcl \
|
||||||
|
tcl/lib/ns-cmutrace.tcl \
|
||||||
|
tcl/lib/ns-node.tcl \
|
||||||
|
tcl/lib/ns-rtmodule.tcl \
|
||||||
|
tcl/lib/ns-hiernode.tcl \
|
||||||
|
tcl/lib/ns-packet.tcl \
|
||||||
|
tcl/lib/ns-queue.tcl \
|
||||||
|
tcl/lib/ns-source.tcl \
|
||||||
|
tcl/lib/ns-nam.tcl \
|
||||||
|
tcl/lib/ns-trace.tcl \
|
||||||
|
tcl/lib/ns-agent.tcl \
|
||||||
|
tcl/lib/ns-random.tcl \
|
||||||
|
tcl/lib/ns-namsupp.tcl \
|
||||||
|
tcl/lib/ns-address.tcl \
|
||||||
|
tcl/lib/ns-intserv.tcl \
|
||||||
|
tcl/lib/ns-autoconf.tcl \
|
||||||
|
tcl/rtp/session-rtp.tcl \
|
||||||
|
tcl/lib/ns-mip.tcl \
|
||||||
|
tcl/rtglib/dynamics.tcl \
|
||||||
|
tcl/rtglib/route-proto.tcl \
|
||||||
|
tcl/rtglib/algo-route-proto.tcl \
|
||||||
|
tcl/rtglib/ns-rtProtoLS.tcl \
|
||||||
|
tcl/interface/ns-iface.tcl \
|
||||||
|
tcl/mcast/BST.tcl \
|
||||||
|
tcl/mcast/ns-mcast.tcl \
|
||||||
|
tcl/mcast/McastProto.tcl \
|
||||||
|
tcl/mcast/DM.tcl \
|
||||||
|
tcl/mcast/srm.tcl \
|
||||||
|
tcl/mcast/srm-adaptive.tcl \
|
||||||
|
tcl/mcast/srm-ssm.tcl \
|
||||||
|
tcl/mcast/timer.tcl \
|
||||||
|
tcl/mcast/McastMonitor.tcl \
|
||||||
|
tcl/mcast/mftp_snd.tcl \
|
||||||
|
tcl/mcast/mftp_rcv.tcl \
|
||||||
|
tcl/mcast/mftp_rcv_stat.tcl \
|
||||||
|
tcl/mobility/dsdv.tcl \
|
||||||
|
tcl/mobility/dsr.tcl \
|
||||||
|
tcl/ctr-mcast/CtrMcast.tcl \
|
||||||
|
tcl/ctr-mcast/CtrMcastComp.tcl \
|
||||||
|
tcl/ctr-mcast/CtrRPComp.tcl \
|
||||||
|
tcl/rlm/rlm.tcl \
|
||||||
|
tcl/rlm/rlm-ns.tcl \
|
||||||
|
tcl/session/session.tcl \
|
||||||
|
tcl/lib/ns-route.tcl \
|
||||||
|
tcl/emulate/ns-emulate.tcl \
|
||||||
|
tcl/lan/vlan.tcl \
|
||||||
|
tcl/lan/abslan.tcl \
|
||||||
|
tcl/lan/ns-ll.tcl \
|
||||||
|
tcl/lan/ns-mac.tcl \
|
||||||
|
tcl/webcache/http-agent.tcl \
|
||||||
|
tcl/webcache/http-server.tcl \
|
||||||
|
tcl/webcache/http-cache.tcl \
|
||||||
|
tcl/webcache/http-mcache.tcl \
|
||||||
|
tcl/webcache/webtraf.tcl \
|
||||||
|
tcl/webcache/empweb.tcl \
|
||||||
|
tcl/webcache/empftp.tcl \
|
||||||
|
tcl/plm/plm.tcl \
|
||||||
|
tcl/plm/plm-ns.tcl \
|
||||||
|
tcl/plm/plm-topo.tcl \
|
||||||
|
tcl/mpls/ns-mpls-classifier.tcl \
|
||||||
|
tcl/mpls/ns-mpls-ldpagent.tcl \
|
||||||
|
tcl/mpls/ns-mpls-node.tcl \
|
||||||
|
tcl/mpls/ns-mpls-simulator.tcl \
|
||||||
|
tcl/lib/ns-pushback.tcl \
|
||||||
|
tcl/lib/ns-srcrt.tcl \
|
||||||
|
tcl/mcast/ns-lms.tcl \
|
||||||
|
tcl/lib/ns-qsnode.tcl \
|
||||||
|
@V_NS_TCL_LIB_STL@
|
||||||
|
|
||||||
|
$(GEN_DIR)ns_tcl.cc: $(NS_TCL_LIB)
|
||||||
|
$(TCLSH) bin/tcl-expand.tcl tcl/lib/ns-lib.tcl @V_NS_TCL_LIB_STL@ | $(TCL2C) et_ns_lib > $@
|
||||||
|
|
||||||
|
$(GEN_DIR)version.c: VERSION
|
||||||
|
$(RM) $@
|
||||||
|
$(TCLSH) bin/string2c.tcl version_string < VERSION > $@
|
||||||
|
|
||||||
|
$(GEN_DIR)ptypes.cc: common/ptypes2tcl common/packet.h
|
||||||
|
./common/ptypes2tcl > $@
|
||||||
|
|
||||||
|
common/ptypes2tcl: common/ptypes2tcl.o
|
||||||
|
$(LINK) $(LDFLAGS) $(LDOUT)$@ common/ptypes2tcl.o
|
||||||
|
|
||||||
|
common/ptypes2tcl.o: common/ptypes2tcl.cc common/packet.h
|
||||||
|
|
||||||
|
install: force install-ns install-man install-recursive
|
||||||
|
|
||||||
|
install-ns: force
|
||||||
|
$(INSTALL) -m 555 -o bin -g bin ns $(DESTDIR)$(BINDEST)
|
||||||
|
|
||||||
|
install-man: force
|
||||||
|
$(INSTALL) -m 444 -o bin -g bin ns.1 $(DESTDIR)$(MANDEST)/man1
|
||||||
|
|
||||||
|
install-recursive: force
|
||||||
|
for i in $(SUBDIRS); do ( cd $$i; $(MAKE) install; ) done
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(CLEANFILES)
|
||||||
|
|
||||||
|
nrlclean:
|
||||||
|
$(RM) $(OBJ_CPP)
|
||||||
|
|
||||||
|
|
||||||
|
AUTOCONF_GEN = tcl/lib/ns-autoconf.tcl
|
||||||
|
distclean: distclean-recursive
|
||||||
|
$(RM) $(CLEANFILES) Makefile config.cache config.log config.status \
|
||||||
|
autoconf.h gnuc.h os-proto.h $(AUTOCONF_GEN); \
|
||||||
|
$(MV) .configure .configure- ;\
|
||||||
|
echo "Moved .configure to .configure-"
|
||||||
|
|
||||||
|
distclean-recursive:
|
||||||
|
for i in $(SUBDIRS); do ( cd $$i; $(MAKE) clean; $(RM) Makefile; ) done
|
||||||
|
|
||||||
|
tags: force
|
||||||
|
ctags -wtd *.cc *.h webcache/*.cc webcache/*.h dsdv/*.cc dsdv/*.h \
|
||||||
|
dsr/*.cc dsr/*.h webcache/*.cc webcache/*.h lib/*.cc lib/*.h \
|
||||||
|
../Tcl/*.cc ../Tcl/*.h
|
||||||
|
|
||||||
|
TAGS: force
|
||||||
|
etags *.cc *.h webcache/*.cc webcache/*.h dsdv/*.cc dsdv/*.h \
|
||||||
|
dsr/*.cc dsr/*.h webcache/*.cc webcache/*.h lib/*.cc lib/*.h \
|
||||||
|
../Tcl/*.cc ../Tcl/*.h
|
||||||
|
|
||||||
|
tcl/lib/TAGS: force
|
||||||
|
( \
|
||||||
|
cd tcl/lib; \
|
||||||
|
$(TCLSH) ../../bin/tcl-expand.tcl ns-lib.tcl | grep '^### tcl-expand.tcl: begin' | awk '{print $$5}' >.tcl_files; \
|
||||||
|
etags --lang=none -r '/^[ \t]*proc[ \t]+\([^ \t]+\)/\1/' `cat .tcl_files`; \
|
||||||
|
etags --append --lang=none -r '/^\([A-Z][^ \t]+\)[ \t]+\(instproc\|proc\)[ \t]+\([^ \t]+\)[ \t]+/\1::\3/' `cat .tcl_files`; \
|
||||||
|
)
|
||||||
|
|
||||||
|
depend: $(SRC)
|
||||||
|
$(MKDEP) $(CFLAGS) $(INCLUDES) $(SRC)
|
||||||
|
|
||||||
|
srctar:
|
||||||
|
@cwd=`pwd` ; dir=`basename $$cwd` ; \
|
||||||
|
name=ns-`cat VERSION | tr A-Z a-z` ; \
|
||||||
|
tar=ns-src-`cat VERSION`.tar.gz ; \
|
||||||
|
list="" ; \
|
||||||
|
for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \
|
||||||
|
echo \
|
||||||
|
"(rm -f $$tar; cd .. ; ln -s $$dir $$name)" ; \
|
||||||
|
(rm -f $$tar; cd .. ; ln -s $$dir $$name) ; \
|
||||||
|
echo \
|
||||||
|
"(cd .. ; tar cfh $$tar [lots of files])" ; \
|
||||||
|
(cd .. ; tar cfh - $$list) | gzip -c > $$tar ; \
|
||||||
|
echo \
|
||||||
|
"rm ../$$name; chmod 444 $$tar" ; \
|
||||||
|
rm ../$$name; chmod 444 $$tar
|
||||||
|
|
||||||
|
force:
|
||||||
|
|
||||||
|
test: force
|
||||||
|
./validate
|
||||||
|
|
||||||
|
# Create makefile.vc for Win32 development by replacing:
|
||||||
|
# "# !include ..." -> "!include ..."
|
||||||
|
makefile.vc: Makefile.in
|
||||||
|
$(PERL) bin/gen-vcmake.pl < Makefile.in > makefile.vc
|
||||||
|
# $(PERL) -pe 's/^# (\!include)/\!include/o' < Makefile.in > makefile.vc
|
||||||
|
|
@ -45,10 +45,7 @@ static class NsNormAgentClass : public TclClass
|
||||||
|
|
||||||
|
|
||||||
NsNormAgent::NsNormAgent()
|
NsNormAgent::NsNormAgent()
|
||||||
: NormSimAgent(ProtoSimAgent::TimerInstaller,
|
: NormSimAgent(GetTimerMgr(), GetSocketNotifier())
|
||||||
static_cast<ProtoSimAgent*>(this),
|
|
||||||
ProtoSimAgent::SocketInstaller,
|
|
||||||
static_cast<ProtoSimAgent*>(this))
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +54,25 @@ NsNormAgent::~NsNormAgent()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int NsNormAgent::command(int argc, const char*const* argv)
|
bool NsNormAgent::OnStartup(int argc, const char*const* argv)
|
||||||
|
{
|
||||||
|
if (ProcessCommands(argc, argv))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "NsNormAgent::OnStartup() error processing commands\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // end NsNormAgent::OnStartup()
|
||||||
|
|
||||||
|
void NsNormAgent::OnShutdown()
|
||||||
|
{
|
||||||
|
NormSimAgent::Stop();
|
||||||
|
} // end NsNormAgent::OnShutdown()
|
||||||
|
|
||||||
|
bool NsNormAgent::ProcessCommands(int argc, const char*const* argv)
|
||||||
{
|
{
|
||||||
// Process commands, passing unknown commands to base Agent class
|
// Process commands, passing unknown commands to base Agent class
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
@ -70,8 +85,8 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
||||||
// Attach Agent/MGEN to this NormSimAgent
|
// Attach Agent/MGEN to this NormSimAgent
|
||||||
if (++i >= argc)
|
if (++i >= argc)
|
||||||
{
|
{
|
||||||
DMSG(0, "NsNormAgent::command() ProcessCommand(attach-mgen) error: insufficent arguments\n");
|
DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(attach-mgen) error: insufficent arguments\n");
|
||||||
return TCL_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
Tcl& tcl = Tcl::instance();
|
Tcl& tcl = Tcl::instance();
|
||||||
NsMgenAgent* mgenAgent = dynamic_cast<NsMgenAgent*> (tcl.lookup(argv[i]));
|
NsMgenAgent* mgenAgent = dynamic_cast<NsMgenAgent*> (tcl.lookup(argv[i]));
|
||||||
|
|
@ -83,8 +98,8 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMSG(0, "NsNormAgent::command() ProcessCommand(attach-mgen) error: invalid mgen agent\n");
|
DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(attach-mgen) error: invalid mgen agent\n");
|
||||||
return TCL_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[i], "active"))
|
else if (!strcmp(argv[i], "active"))
|
||||||
|
|
@ -105,9 +120,9 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
||||||
case NormSimAgent::CMD_NOARG:
|
case NormSimAgent::CMD_NOARG:
|
||||||
if (!ProcessCommand(argv[i], NULL))
|
if (!ProcessCommand(argv[i], NULL))
|
||||||
{
|
{
|
||||||
DMSG(0, "NsNormAgent::command() ProcessCommand(%s) error\n",
|
DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(%s) error\n",
|
||||||
argv[i]);
|
argv[i]);
|
||||||
return TCL_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
|
|
@ -115,23 +130,23 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
||||||
case NormSimAgent::CMD_ARG:
|
case NormSimAgent::CMD_ARG:
|
||||||
if (!ProcessCommand(argv[i], argv[i+1]))
|
if (!ProcessCommand(argv[i], argv[i+1]))
|
||||||
{
|
{
|
||||||
DMSG(0, "NsNormAgent::command() ProcessCommand(%s, %s) error\n",
|
DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(%s, %s) error\n",
|
||||||
argv[i], argv[i+1]);
|
argv[i], argv[i+1]);
|
||||||
return TCL_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NormSimAgent::CMD_INVALID:
|
case NormSimAgent::CMD_INVALID:
|
||||||
return NsProtoAgent::command(argc, argv);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TCL_OK;
|
return true;
|
||||||
} // end NsNormAgent::command()
|
} // end NsNormAgent::ProcessCommands()
|
||||||
|
|
||||||
bool NsNormAgent::SendMgenMessage(const NetworkAddress* dstAddr,
|
bool NsNormAgent::SendMgenMessage(const char* txBuffer,
|
||||||
const char* txBuffer,
|
unsigned int len,
|
||||||
unsigned int len)
|
const ProtoAddress& /*dstAddr*/)
|
||||||
{
|
{
|
||||||
return SendMessage(len, txBuffer);
|
return SendMessage(len, txBuffer);
|
||||||
} // end NsNormAgent::SendMgenMessage()
|
} // end NsNormAgent::SendMgenMessage()
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
#ifndef _NS_NORM_AGENT
|
#ifndef _NS_NORM_AGENT
|
||||||
#define _NS_NORM_AGENT
|
#define _NS_NORM_AGENT
|
||||||
|
|
||||||
#include "nsProtoAgent.h" // from ProtoLib
|
#include "nsProtoSimAgent.h" // from Protolib
|
||||||
#include "normSimAgent.h"
|
#include "normSimAgent.h"
|
||||||
|
|
||||||
#include "nsMgenAgent.h"
|
#include "nsMgenAgent.h"
|
||||||
|
|
@ -44,20 +44,23 @@
|
||||||
|
|
||||||
// IMPORTANT NOTE! NsProtoAgent must be listed _first_ here
|
// IMPORTANT NOTE! NsProtoAgent must be listed _first_ here
|
||||||
// (because we can't dynamic_cast install_data void* pointers)
|
// (because we can't dynamic_cast install_data void* pointers)
|
||||||
class NsNormAgent : public NsProtoAgent, public NormSimAgent, public MgenSink
|
class NsNormAgent : public NsProtoSimAgent, public NormSimAgent, public MgenSink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NsNormAgent();
|
NsNormAgent();
|
||||||
~NsNormAgent();
|
~NsNormAgent();
|
||||||
|
|
||||||
// NsProtoAgent base class override
|
// NsProtoSimAgent base class overrides
|
||||||
int command(int argc, const char*const* argv);
|
virtual bool OnStartup(int argc, const char*const* argv);
|
||||||
|
virtual bool ProcessCommands(int argc, const char*const* argv);
|
||||||
|
virtual void OnShutdown();
|
||||||
|
|
||||||
// NormSimAgent override
|
// NormSimAgent override
|
||||||
unsigned long GetAgentId() {return (unsigned long)addr();}
|
unsigned long GetAgentId() {return (unsigned long)addr();}
|
||||||
// MgenSink override
|
// MgenSink override
|
||||||
bool SendMgenMessage(const NetworkAddress* dstAddr,
|
bool SendMgenMessage(const char* txBuffer,
|
||||||
const char* txBuffer,
|
unsigned int len,
|
||||||
unsigned int len);
|
const ProtoAddress& dstAddr);
|
||||||
}; // end class NsNormAgent
|
}; // end class NsNormAgent
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ CFLAGS = -g -DPROTO_DEBUG -DUNIX -O -fPIC $(SYSTEM_HAVES) $(INCLUDES)
|
||||||
LDFLAGS = $(SYSTEM_LDFLAGS)
|
LDFLAGS = $(SYSTEM_LDFLAGS)
|
||||||
|
|
||||||
# Note: Even command line app needs X11 for Netscape post-processing
|
# Note: Even command line app needs X11 for Netscape post-processing
|
||||||
LIBS = $(SYSTEM_LIBS) -lm
|
LIBS = $(SYSTEM_LIBS) -lm -lpthread
|
||||||
XLIBS = -lXmu -lXt -lX11
|
XLIBS = -lXmu -lXt -lX11
|
||||||
|
|
||||||
#NOTE: TK_LIB must come before TCL_LIB for some reason
|
#NOTE: TK_LIB must come before TCL_LIB for some reason
|
||||||
|
|
@ -47,9 +47,9 @@ TARGETS = mdp tkMdp
|
||||||
$(CC) -c $(CFLAGS) -o $*.o $*.cpp
|
$(CC) -c $(CFLAGS) -o $*.o $*.cpp
|
||||||
|
|
||||||
# MDP depends upon the NRL Protean Group's development library
|
# MDP depends upon the NRL Protean Group's development library
|
||||||
LIBPROTO = $(PROTOLIB)/unix/libProto.a
|
LIBPROTO = $(PROTOLIB)/unix/libProtokit.a
|
||||||
$(PROTOLIB)/unix/libProto.a:
|
$(PROTOLIB)/unix/libProtokit.a:
|
||||||
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProto.a
|
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProtokit.a
|
||||||
|
|
||||||
NORM_SRC = $(COMMON)/normMessage.cpp $(COMMON)/normSession.cpp \
|
NORM_SRC = $(COMMON)/normMessage.cpp $(COMMON)/normSession.cpp \
|
||||||
$(COMMON)/normNode.cpp $(COMMON)/normObject.cpp \
|
$(COMMON)/normNode.cpp $(COMMON)/normObject.cpp \
|
||||||
|
|
@ -77,7 +77,8 @@ libnormSim.a: $(SIM_OBJ)
|
||||||
ranlib $@
|
ranlib $@
|
||||||
|
|
||||||
# (mdp) command-line file broadcaster/receiver
|
# (mdp) command-line file broadcaster/receiver
|
||||||
APP_SRC = $(COMMON)/normApp.cpp $(COMMON)/normPostProcess.cpp
|
APP_SRC = $(COMMON)/normApp.cpp $(COMMON)/normPostProcess.cpp \
|
||||||
|
$(UNIX)/unixPostProcess.cpp
|
||||||
APP_OBJ = $(APP_SRC:.cpp=.o)
|
APP_OBJ = $(APP_SRC:.cpp=.o)
|
||||||
|
|
||||||
norm: $(APP_OBJ) libnorm.a $(LIBPROTO)
|
norm: $(APP_OBJ) libnorm.a $(LIBPROTO)
|
||||||
|
|
|
||||||
|
|
@ -2,37 +2,14 @@
|
||||||
# FreeBSD Protean Makefile definitions
|
# FreeBSD Protean Makefile definitions
|
||||||
#
|
#
|
||||||
|
|
||||||
# TO BUILD THE TK GUI VERSION, EDIT THE FOLLOWING NUMBERED
|
# 1) System specific additional libraries, include paths, etc
|
||||||
# ITEMS AS NEEDED FOR YOUR SYSTEM
|
|
||||||
# (This has only been tested with TCL/TK 8.0 but it probably
|
|
||||||
# will work with Tcl7.x/Tk4.x with a little tweaking to
|
|
||||||
# the list of TCL_SCRIPTS (library scripts) given below)
|
|
||||||
|
|
||||||
# 1) Where to find the Tcl standard library scripts
|
|
||||||
# (e.g. init.tcl, ...)
|
|
||||||
TCL_SCRIPT_PATH = /usr/local/lib/tcl8.0
|
|
||||||
|
|
||||||
# 2) Where to find the Tk standard library scripts
|
|
||||||
# (e.g. button.tcl, entry.tcl, ...)
|
|
||||||
TK_SCRIPT_PATH = /usr/local/lib/tk8.0
|
|
||||||
|
|
||||||
# 3) Where to find Tcl/Tk header files
|
|
||||||
# (e.g. tcl.h, tk.h, ...)
|
|
||||||
TCL_INCL_PATH = -I/usr/local/include/tcl8.0 -I/usr/local/include/tk8.0
|
|
||||||
|
|
||||||
# 4) Point to specific libtcl.a and libtk.a to use
|
|
||||||
TCL_LIB = /usr/local/lib/libtcl80.a
|
|
||||||
TK_LIB = /usr/local/lib/libtk80.a
|
|
||||||
|
|
||||||
|
|
||||||
# 5) System specific additional libraries, include paths, etc
|
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
SYSTEM_INCLUDES = -I/usr/X11R6/include
|
SYSTEM_INCLUDES =
|
||||||
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
|
SYSTEM_LDFLAGS =
|
||||||
SYSTEM_LIBS =
|
SYSTEM_LIBS =
|
||||||
|
|
||||||
# 6) System specific capabilities
|
# 2) System specific capabilities
|
||||||
# Must choose appropriate for the following:
|
# Must choose appropriate for the following:
|
||||||
#
|
#
|
||||||
# A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin()
|
# A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin()
|
||||||
|
|
@ -48,7 +25,7 @@ SYSTEM_LIBS =
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The MDP code's use of offset pointers requires special treatment
|
# E) The PROTOLIB code's use of offset pointers requires special treatment
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
# for some different compilers. Set -DUSE_INHERITANCE for some
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
# to keep some compilers (gcc 2.7.2) happy.
|
||||||
#
|
#
|
||||||
|
|
@ -62,10 +39,13 @@ SYSTEM_LIBS =
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
export SYSTEM_HAVES = -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC)
|
SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC)
|
||||||
|
|
||||||
export CC = gcc
|
SYSTEM_SRC = bsdRouteMgr.cpp
|
||||||
export RANLIB = ranlib
|
|
||||||
export AR = ar
|
SYSTEM = freebsd
|
||||||
|
CC = gcc
|
||||||
|
RANLIB = ranlib
|
||||||
|
AR = ar
|
||||||
|
|
||||||
include Makefile.common
|
include Makefile.common
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ TK_LIB = -ltk #/usr/local/lib/libtk8.0.a
|
||||||
# 5) System specific additional libraries, include paths, etc
|
# 5) System specific additional libraries, include paths, etc
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
SYSTEM_INCLUDES = -I/usr/X11R6/include
|
SYSTEM_INCLUDES = -Wall -I/usr/X11R6/include
|
||||||
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
|
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
|
||||||
SYSTEM_LIBS = -ldl
|
SYSTEM_LIBS = -ldl
|
||||||
|
|
||||||
|
|
@ -62,10 +62,14 @@ SYSTEM_LIBS = -ldl
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
export SYSTEM_HAVES = -DLINUX -DHAVE_IPV6 -DHAVE_GETLOGIN -DHAVE_LOCKF \
|
SYSTEM_HAVES = -DLINUX -DHAVE_IPV6 -DHAVE_GETLOGIN -DHAVE_LOCKF \
|
||||||
-DHAVE_OLD_SIGNALHANDLER -DHAVE_DIRFD -DHAVE_ASSERT $(NETSEC)
|
-DHAVE_OLD_SIGNALHANDLER -DHAVE_DIRFD -DHAVE_ASSERT $(NETSEC)
|
||||||
|
|
||||||
export CC = gcc
|
SYSTEM_SRC =
|
||||||
|
|
||||||
|
SYSTEM = linux
|
||||||
|
|
||||||
|
export CC = g++
|
||||||
export RANLIB = ranlib
|
export RANLIB = ranlib
|
||||||
export AR = ar
|
export AR = ar
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
# 1) System specific additional libraries, include paths, etc
|
# 1) System specific additional libraries, include paths, etc
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
|
|
||||||
SYSTEM_INCLUDES = -I/usr/X11R6/include
|
SYSTEM_INCLUDES = -I/usr/X11R6/include
|
||||||
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
|
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
|
||||||
SYSTEM_LIBS =
|
SYSTEM_LIBS =
|
||||||
|
|
@ -35,7 +36,12 @@ SYSTEM_LIBS =
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
export SYSTEM_HAVES = -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC) -DSOCKLEN_T=int
|
export SYSTEM_HAVES = -DMACOSX -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC) -DSOCKLEN_T=int
|
||||||
|
|
||||||
|
SYSTEM_SRC = bsdRouteMgr.cpp
|
||||||
|
|
||||||
|
# The "SYSTEM" keyword can be used for dependent makes
|
||||||
|
SYSTEM = macosx
|
||||||
|
|
||||||
export CC = g++
|
export CC = g++
|
||||||
export RANLIB = ranlib
|
export RANLIB = ranlib
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,10 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 1) System specific additional libraries, include paths, etc
|
# 1) System specific additional libraries, include paths, etc
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333 -cfront
|
SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333
|
||||||
SYSTEM_LDFLAGS =
|
SYSTEM_LDFLAGS =
|
||||||
SYSTEM_LIBS =
|
SYSTEM_LIBS =
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,15 @@
|
||||||
#
|
#
|
||||||
# MDPv2 Solaris Makefile
|
# NORM Solaris Makefile
|
||||||
#
|
#
|
||||||
# TO BUILD THE TK GUI VERSION OF MDP EDIT THE FOLLOWING NUMBERED
|
|
||||||
# ITEMS AS NEEDED FOR YOUR SYSTEM
|
|
||||||
# (This has only been tested with TCL/TK 8.0 but it probably
|
|
||||||
# will work with Tcl7.x/Tk4.x with a little tweaking to
|
|
||||||
# the list of TCL_SCRIPTS (library scripts) given below)
|
|
||||||
|
|
||||||
# 1) Where to find the Tcl standard library scripts
|
# 1) System specific additional libraries, include paths, etc
|
||||||
# (e.g. init.tcl, ...)
|
|
||||||
TCL_SCRIPT_PATH = /usr/local/lib/tcl8.0
|
|
||||||
|
|
||||||
# 2) Where to find the Tk standard library scripts
|
|
||||||
# (e.g. button.tcl, entry.tcl, ...)
|
|
||||||
TK_SCRIPT_PATH = /usr/local/lib/tk8.0
|
|
||||||
|
|
||||||
# 3) Where to find Tcl/Tk header files
|
|
||||||
# (e.g. tcl.h, tk.h, ...)
|
|
||||||
TCL_INCL_PATH = -I/usr/local/include
|
|
||||||
|
|
||||||
# 4) Point to specific libtcl.a and libtk.a to use
|
|
||||||
TCL_LIB = /usr/local/lib/libtcl8.0.a
|
|
||||||
TK_LIB = /usr/local/lib/libtk8.0.a
|
|
||||||
|
|
||||||
# 5) System specific additional libraries, include paths, etc
|
|
||||||
# (Where to find X11 libraries, etc)
|
# (Where to find X11 libraries, etc)
|
||||||
#
|
#
|
||||||
SYSTEM_INCLUDES = -I/usr/openwin/include
|
SYSTEM_INCLUDES = -I/usr/openwin/include
|
||||||
SYSTEM_LDFLAGS = -L/usr/openwin/lib -R/usr/openwin/lib
|
SYSTEM_LDFLAGS = -L/usr/openwin/lib -R/usr/openwin/lib
|
||||||
SYSTEM_LIBS = -ldl -lnsl -lsocket
|
SYSTEM_LIBS = -ldl -lnsl -lsocket -lresolv
|
||||||
|
|
||||||
# 6) System specific capabilities
|
# 2) System specific capabilities
|
||||||
# Must choose appropriate for the following:
|
# Must choose appropriate for the following:
|
||||||
#
|
#
|
||||||
# A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin()
|
# A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin()
|
||||||
|
|
@ -46,24 +25,24 @@ SYSTEM_LIBS = -ldl -lnsl -lsocket
|
||||||
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
# routine.
|
# routine.
|
||||||
#
|
#
|
||||||
# E) The MDP code's use of offset pointers requires special treatment
|
# E) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
# for some different compilers. Set -DUSE_INHERITANCE for some
|
|
||||||
# to keep some compilers (gcc 2.7.2) happy.
|
|
||||||
#
|
|
||||||
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
|
||||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
#
|
#
|
||||||
# G) Uncomment this if you have the NRL IPv6+IPsec software
|
# F) Uncomment this if you have the NRL IPv6+IPsec software
|
||||||
#DNETSEC = -DNETSEC -I/usr/inet6/include
|
#DNETSEC = -DNETSEC -I/usr/inet6/include
|
||||||
#
|
#
|
||||||
# (We export these for other Makefiles as needed)
|
# (We export these for other Makefiles as needed)
|
||||||
#
|
#
|
||||||
|
|
||||||
export SYSTEM_HAVES = -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF $(NETSEC) -DSOLARIS
|
SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF $(NETSEC) -DSOLARIS
|
||||||
|
|
||||||
export CC = gcc
|
SYSTEM = solaris
|
||||||
export RANLIB = touch
|
|
||||||
export AR = ar
|
CC = g++
|
||||||
|
|
||||||
|
RANLIB = touch
|
||||||
|
|
||||||
|
AR = ar
|
||||||
|
|
||||||
include Makefile.common
|
include Makefile.common
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,411 @@
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* AUTHORIZATION TO USE AND DISTRIBUTE
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that:
|
||||||
|
*
|
||||||
|
* (1) source code distributions retain this paragraph in its entirety,
|
||||||
|
*
|
||||||
|
* (2) distributions including binary code include this paragraph in
|
||||||
|
* its entirety in the documentation or other materials provided
|
||||||
|
* with the distribution, and
|
||||||
|
*
|
||||||
|
* (3) all advertising materials mentioning features or use of this
|
||||||
|
* software display the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software written and developed
|
||||||
|
* by Brian Adamson and Joe Macker of the Naval Research
|
||||||
|
* Laboratory (NRL)."
|
||||||
|
*
|
||||||
|
* The name of NRL, the name(s) of NRL employee(s), or any entity
|
||||||
|
* of the United States Government may not be used to endorse or
|
||||||
|
* promote products derived from this software, nor does the
|
||||||
|
* inclusion of the NRL written and developed software directly or
|
||||||
|
* indirectly suggest NRL or United States Government endorsement
|
||||||
|
* of this product.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
// This file contains code for various UNIX MDP post processor options
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
* Netscape[tm] post processor routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Some portions of this code
|
||||||
|
// Copyright © 1996 Netscape Communications Corporation,
|
||||||
|
// all rights reserved.
|
||||||
|
|
||||||
|
#include "normPostProcess.h"
|
||||||
|
#include "protoDebug.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h> // for strerror()
|
||||||
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <stdlib.h> // for exit()
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef sighandler_t
|
||||||
|
#ifndef sig_t
|
||||||
|
typedef void (*sighandler_t)(int);
|
||||||
|
#else
|
||||||
|
typedef sig_t sighandler_t;
|
||||||
|
#endif // if/else !sig_t
|
||||||
|
#endif // !sighandler_t
|
||||||
|
|
||||||
|
#ifdef NETSCAPE_SUPPORT
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xmu/WinUtil.h> /* for XmuClientWindow() */
|
||||||
|
|
||||||
|
/* vroot.h is a header file which lets a client get along with `virtual root'
|
||||||
|
window managers like swm, tvtwm, olvwm, etc. If you don't have this header
|
||||||
|
file, you can find it at "http://home.netscape.com/newsref/std/vroot.h".
|
||||||
|
If you don't care about supporting virtual root window managers, you can
|
||||||
|
comment this line out.
|
||||||
|
*/
|
||||||
|
#include "vroot.h"
|
||||||
|
#define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
|
||||||
|
static Atom XA_MOZILLA_VERSION = 0;
|
||||||
|
bool CheckForNetscape(const char* cmd);
|
||||||
|
bool NetscapeIsRunning(Window *result);
|
||||||
|
bool NetscapeCheckWindow(Window window);
|
||||||
|
#endif // NETSCAPE_SUPPORT
|
||||||
|
|
||||||
|
class UnixPostProcessor : public NormPostProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~UnixPostProcessor();
|
||||||
|
bool IsActive() {return (0 != process_id);}
|
||||||
|
bool ProcessFile(const char* path);
|
||||||
|
void Kill();
|
||||||
|
|
||||||
|
void OnSIGCHLD();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class NormPostProcessor;
|
||||||
|
UnixPostProcessor();
|
||||||
|
|
||||||
|
int process_id;
|
||||||
|
#ifdef NETSCAPE_SUPPORT
|
||||||
|
Window window_id;
|
||||||
|
#endif // NETSCAPE_SUPPORT
|
||||||
|
}; // end class UnixPostProcessor
|
||||||
|
|
||||||
|
|
||||||
|
UnixPostProcessor::UnixPostProcessor()
|
||||||
|
: process_id(0)
|
||||||
|
#ifdef NETSCAPE_SUPPORT
|
||||||
|
,window_id(0)
|
||||||
|
#endif // NETSCAPE_SUPPORT
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NormPostProcessor* NormPostProcessor::Create()
|
||||||
|
{
|
||||||
|
return static_cast<NormPostProcessor*>(new UnixPostProcessor);
|
||||||
|
} // end NormPostProcessor::Create()
|
||||||
|
|
||||||
|
UnixPostProcessor::~UnixPostProcessor()
|
||||||
|
{
|
||||||
|
if (IsActive()) Kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixPostProcessor::ProcessFile(const char* path)
|
||||||
|
{
|
||||||
|
const char** argv = (const char**)process_argv;
|
||||||
|
int argc = process_argc;
|
||||||
|
#ifdef NETSCAPE_SUPPORT
|
||||||
|
// Special support for finding a Netscape window and
|
||||||
|
// use the openURL remote command to display received file
|
||||||
|
#define USE_ACTIVE_WINDOW 0xffffffff
|
||||||
|
const char* myArgs[32];
|
||||||
|
char wid_text[32], url_text[PATH_MAX+64];
|
||||||
|
if (CheckForNetscape(argv[0]))
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
myArgs[i++] = process_argv[0];
|
||||||
|
Window w = 0;
|
||||||
|
// (TBD) We could put in a hack to look for the old
|
||||||
|
// window if we made "w" static when "window_id" = 0xffffffff
|
||||||
|
// This would help us capture the proper window for file display
|
||||||
|
// It's still a hack but it might work a little better without
|
||||||
|
// too much trouble
|
||||||
|
if (NetscapeIsRunning(&w))
|
||||||
|
{
|
||||||
|
// Use -remote command to display file in current
|
||||||
|
// or new window
|
||||||
|
if (window_id)
|
||||||
|
{
|
||||||
|
if (NetscapeCheckWindow(window_id))
|
||||||
|
{
|
||||||
|
// Use the same window as last time
|
||||||
|
myArgs[i++] = "-id";
|
||||||
|
sprintf(wid_text, "0x%lx", window_id);
|
||||||
|
myArgs[i++] = wid_text;
|
||||||
|
myArgs[i++] = "-noraise";
|
||||||
|
myArgs[i++] = "-remote";
|
||||||
|
sprintf(url_text, "openURL(file://%s)", path);
|
||||||
|
myArgs[i++] = url_text;
|
||||||
|
}
|
||||||
|
else if (USE_ACTIVE_WINDOW == window_id)
|
||||||
|
{
|
||||||
|
// Capture the open window we found
|
||||||
|
myArgs[i++] = "-id";
|
||||||
|
sprintf(wid_text, "0x%lx", w);
|
||||||
|
myArgs[i++] = wid_text;
|
||||||
|
window_id = w;
|
||||||
|
myArgs[i++] = "-noraise";
|
||||||
|
myArgs[i++] = "-remote";
|
||||||
|
sprintf(url_text, "openURL(file://%s)", path);
|
||||||
|
myArgs[i++] = url_text;
|
||||||
|
}
|
||||||
|
else // user must have closed old window so open another
|
||||||
|
{
|
||||||
|
window_id = USE_ACTIVE_WINDOW;
|
||||||
|
//myArgs[i++] = "-raise";
|
||||||
|
myArgs[i++] = "-remote";
|
||||||
|
sprintf(url_text, "openURL(file://%s,new-window)", path);
|
||||||
|
myArgs[i++] = url_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We're starting fresh, open a new window
|
||||||
|
window_id = USE_ACTIVE_WINDOW;
|
||||||
|
//myArgs[i++] = "-raise";
|
||||||
|
myArgs[i++] = "-remote";
|
||||||
|
sprintf(url_text, "openURL(file://%s,new-window)", path);
|
||||||
|
myArgs[i++] = url_text;
|
||||||
|
}
|
||||||
|
argv = myArgs;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IsActive()) Kill();
|
||||||
|
window_id = USE_ACTIVE_WINDOW;
|
||||||
|
myArgs[i++] = path;
|
||||||
|
} // end if/else (NetscapeIsRunning())
|
||||||
|
myArgs[i] = NULL;
|
||||||
|
argc = i - 1;
|
||||||
|
argv = myArgs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // NETSCAPE_SUPPORT
|
||||||
|
{
|
||||||
|
if (IsActive()) Kill();
|
||||||
|
argv[argc] = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) temporarily disable signal handling
|
||||||
|
sighandler_t sigtermHandler = signal(SIGTERM, SIG_DFL);
|
||||||
|
sighandler_t sigintHandler = signal(SIGINT, SIG_DFL);
|
||||||
|
sighandler_t sigchldHandler = signal(SIGCHLD, SIG_DFL);
|
||||||
|
|
||||||
|
switch((process_id = fork()))
|
||||||
|
{
|
||||||
|
case -1: // error
|
||||||
|
DMSG(0, "UnixPostProcessor::ProcessFile fork() error: %s\n", strerror(errno));
|
||||||
|
process_id = 0;
|
||||||
|
process_argv[process_argc] = NULL;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case 0: // child
|
||||||
|
if (execvp((char*)argv[0], (char**)argv) < 0)
|
||||||
|
{
|
||||||
|
DMSG(0, "UnixPostProcessor::ProcessFile execvp() error: %s\n", strerror(errno));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // parent
|
||||||
|
process_argv[process_argc] = NULL;
|
||||||
|
// Restore signal handlers for parent
|
||||||
|
signal(SIGTERM, sigtermHandler);
|
||||||
|
signal(SIGINT, sigintHandler);
|
||||||
|
signal(SIGCHLD, sigchldHandler);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // end UnixPostProcessor::ProcessFile()
|
||||||
|
|
||||||
|
void UnixPostProcessor::Kill()
|
||||||
|
{
|
||||||
|
if (!IsActive()) return;
|
||||||
|
int count = 0;
|
||||||
|
while((kill(process_id, SIGTERM) != 0) && count < 10)
|
||||||
|
{
|
||||||
|
if (errno == ESRCH) break;
|
||||||
|
count++;
|
||||||
|
DMSG(0, "UnixPostProcessor::Kill kill() error: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
count = 0;
|
||||||
|
int status;
|
||||||
|
while((waitpid(process_id, &status, 0) != process_id) && count < 10)
|
||||||
|
{
|
||||||
|
if (errno == ECHILD) break;
|
||||||
|
count++;
|
||||||
|
DMSG(0, "UnixPostProcessor::Kill waitpid() error: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
process_id = 0;
|
||||||
|
} // end UnixPostProcessor::Kill()
|
||||||
|
|
||||||
|
void UnixPostProcessor::OnSIGCHLD()
|
||||||
|
{
|
||||||
|
// See if post processor exited itself
|
||||||
|
int status;
|
||||||
|
if (wait(&status) == process_id) process_id = 0;
|
||||||
|
} // end UnixPostProcessor::HandleSIGCHLD()
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef NETSCAPE_SUPPORT
|
||||||
|
bool CheckForNetscape(const char* cmd)
|
||||||
|
{
|
||||||
|
// See if it's Netscape post processing
|
||||||
|
// for which we provide special support
|
||||||
|
char txt[8];
|
||||||
|
const char *ptr = strrchr(cmd, PROTO_PATH_DELIMITER);
|
||||||
|
if (ptr)
|
||||||
|
ptr++;
|
||||||
|
else
|
||||||
|
ptr = cmd;
|
||||||
|
strncpy(txt, ptr, 8);
|
||||||
|
for (int i=0; i<8; i++) txt[i] = toupper(txt[i]);
|
||||||
|
if (!strncmp(txt, "NETSCAPE", 8))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
} // end CheckForNetscape()
|
||||||
|
|
||||||
|
bool NetscapeIsRunning(Window *result)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Window root2, parent, *kids;
|
||||||
|
unsigned int nkids;
|
||||||
|
*result = 0;
|
||||||
|
|
||||||
|
Display *dpy = XOpenDisplay(NULL);
|
||||||
|
if (!dpy)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "mdp: XOpenDisplay() error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!XA_MOZILLA_VERSION)
|
||||||
|
XA_MOZILLA_VERSION = XInternAtom(dpy, MOZILLA_VERSION_PROP, False);
|
||||||
|
|
||||||
|
Window root = RootWindowOfScreen(DefaultScreenOfDisplay(dpy));
|
||||||
|
|
||||||
|
if (!XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "mdp: XQueryTree failed on display %s\n", DisplayString (dpy));
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: root != root2 is possible with virtual root WMs.
|
||||||
|
if (!(kids && nkids))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "mdp: root window has no children on display %s\n",
|
||||||
|
DisplayString (dpy));
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = nkids-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Atom type;
|
||||||
|
int format;
|
||||||
|
unsigned long nitems, bytesafter;
|
||||||
|
unsigned char *version = 0;
|
||||||
|
Window w = XmuClientWindow (dpy, kids[i]);
|
||||||
|
int status = XGetWindowProperty (dpy, w, XA_MOZILLA_VERSION,
|
||||||
|
0, (65536 / sizeof (long)),
|
||||||
|
False, XA_STRING,
|
||||||
|
&type, &format, &nitems, &bytesafter,
|
||||||
|
&version);
|
||||||
|
if (! version) continue;
|
||||||
|
XFree (version);
|
||||||
|
if (status == Success && type != None)
|
||||||
|
{
|
||||||
|
*result = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
return (*result ? true : false);
|
||||||
|
|
||||||
|
} // end NetscapeIsRunning()
|
||||||
|
|
||||||
|
bool NetscapeCheckWindow(Window window)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Window root2, parent, *kids;
|
||||||
|
unsigned int nkids;
|
||||||
|
|
||||||
|
Display *dpy = XOpenDisplay(NULL);
|
||||||
|
if (!dpy)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "mdp: XOpenDisplay() error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!XA_MOZILLA_VERSION)
|
||||||
|
XA_MOZILLA_VERSION = XInternAtom(dpy, MOZILLA_VERSION_PROP, False);
|
||||||
|
|
||||||
|
Window root = RootWindowOfScreen(DefaultScreenOfDisplay (dpy));
|
||||||
|
|
||||||
|
if (!XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "mdp: XQueryTree failed on display %s\n", DisplayString (dpy));
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: root != root2 is possible with virtual root WMs.
|
||||||
|
if (!(kids && nkids)) return false;
|
||||||
|
|
||||||
|
for (i = nkids-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Atom type;
|
||||||
|
int format;
|
||||||
|
unsigned long nitems, bytesafter;
|
||||||
|
unsigned char *version = 0;
|
||||||
|
Window w = XmuClientWindow (dpy, kids[i]);
|
||||||
|
int status = XGetWindowProperty (dpy, w, XA_MOZILLA_VERSION,
|
||||||
|
0, (65536 / sizeof (long)),
|
||||||
|
False, XA_STRING,
|
||||||
|
&type, &format, &nitems, &bytesafter,
|
||||||
|
&version);
|
||||||
|
if (!version) continue;
|
||||||
|
XFree (version);
|
||||||
|
if (status == Success && type != None)
|
||||||
|
{
|
||||||
|
if (w == window)
|
||||||
|
{
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} // end NetscapeCheckWindow()
|
||||||
|
#endif // NETSCAPE_SUPPORT
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "NormLib"=.\NormLib.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "Protokit"=..\protolib\win32\Protokit.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "norm"=.\norm\norm.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
Begin Project Dependency
|
||||||
|
Project_Dep_Name NormLib
|
||||||
|
End Project Dependency
|
||||||
|
Begin Project Dependency
|
||||||
|
Project_Dep_Name Protokit
|
||||||
|
End Project Dependency
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,227 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="NormLib" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||||
|
|
||||||
|
CFG=NormLib - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "NormLib.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "NormLib.mak" CFG="NormLib - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "NormLib - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE "NormLib - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "NormLib - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "NDEBUG" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "NormLib - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# 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 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 BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "NormLib - Win32 Release"
|
||||||
|
# Name "NormLib - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\galois.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normBitmask.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normEncoder.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normFile.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normMessage.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normNode.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normObject.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normSegment.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\normSession.cpp
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!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"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="norm" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||||
|
|
||||||
|
CFG=norm - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "norm.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "norm.mak" CFG="norm - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "norm - Win32 Release" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE "norm - Win32 Debug" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "norm - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /vmg /GX /O2 /I "..\..\common" /I "..\..\protolib\common" /I "..\..\protolib\win32" /D "NDEBUG" /D "PROTO_DEBUG" /D "HAVE_IPV6" /D "HAVE_ASSERT" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# ADD LINK32 iphlpapi.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "norm - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# 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 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 BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 iphlpapi.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "norm - Win32 Release"
|
||||||
|
# Name "norm - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\common\normApp.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\common\normPostProcess.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\win32PostProcess.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
|
|
@ -0,0 +1,255 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include "normPostProcess.h"
|
||||||
|
#include "protoDebug.h"
|
||||||
|
|
||||||
|
#include <ddeml.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
class Win32PostProcessor : public NormPostProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~Win32PostProcessor();
|
||||||
|
|
||||||
|
bool ProcessFile(const char* path);
|
||||||
|
void Kill();
|
||||||
|
bool IsActive() {return (NULL != post_processor_handle);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static HDDEDATA CALLBACK DDEClientCallback(UINT uiType, UINT uiFmt, HCONV hConv,
|
||||||
|
HSZ sz1, HSZ sz2, HDDEDATA hData,
|
||||||
|
DWORD lData1, DWORD lData2);
|
||||||
|
friend class NormPostProcessor;
|
||||||
|
Win32PostProcessor();
|
||||||
|
bool Init();
|
||||||
|
|
||||||
|
// Post Processor DDE state
|
||||||
|
DWORD lIdInst; // DDE instance id
|
||||||
|
HCONV hConv; // dde converstation handle
|
||||||
|
DWORD transaction_id;
|
||||||
|
DWORD window_id; // dde browser window id
|
||||||
|
PFNCALLBACK lpDDECallback;
|
||||||
|
HANDLE post_processor_handle;
|
||||||
|
}; // end class Win32PostProcessor
|
||||||
|
|
||||||
|
|
||||||
|
HDDEDATA CALLBACK Win32PostProcessor::DDEClientCallback(UINT uiType, UINT uiFmt, HCONV hConv,
|
||||||
|
HSZ sz1, HSZ sz2, HDDEDATA hData,
|
||||||
|
DWORD lData1, DWORD lData2)
|
||||||
|
{
|
||||||
|
CONVINFO convInfo;
|
||||||
|
convInfo.cb = sizeof(convInfo);
|
||||||
|
bool gotInfo;
|
||||||
|
if (FALSE != DdeQueryConvInfo(hConv, lData1, &convInfo))
|
||||||
|
{
|
||||||
|
gotInfo = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(8, "Win32PostProcessor::DDEClientCallback() DdeQueryInfo error\n");
|
||||||
|
gotInfo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(uiType)
|
||||||
|
{
|
||||||
|
case XTYP_XACT_COMPLETE:
|
||||||
|
{
|
||||||
|
if (gotInfo)
|
||||||
|
{
|
||||||
|
Win32PostProcessor* processor = (Win32PostProcessor*)convInfo.hUser;
|
||||||
|
if (processor &&
|
||||||
|
(processor->hConv == hConv) &&
|
||||||
|
(processor->transaction_id == lData1))
|
||||||
|
{
|
||||||
|
DWORD result;
|
||||||
|
DdeGetData(hData, (unsigned char*)&result, sizeof(DWORD), 0);
|
||||||
|
// Hack to make IExplore fake working
|
||||||
|
if (-2 == result) // IExplore success
|
||||||
|
processor->window_id = -1;
|
||||||
|
else if (-3 == result) // IExplore failure
|
||||||
|
processor->window_id = 0x0;
|
||||||
|
else
|
||||||
|
processor->window_id = result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(0, "Win32PostProcessor::DDEClientCallback() Unknown DDE transaction ID! (proc:%p)\n",
|
||||||
|
processor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XTYP_REGISTER:
|
||||||
|
//TRACE("Win32PostProcessor::DDEClientCallback() XTYP_REGISTER \n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XTYP_UNREGISTER:
|
||||||
|
//TRACE("Win32PostProcessor::DDEClientCallback() XTYP_UNREGISTER (gotInfo:%d)\n", gotInfo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DMSG(4, "Win32PostProcessor::DDEClientCallback() Unknown DDE message type:%u\n", uiType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL; // callback does nothing for now
|
||||||
|
}
|
||||||
|
|
||||||
|
Win32PostProcessor::Win32PostProcessor()
|
||||||
|
: lIdInst(0), hConv(NULL), window_id(-1),
|
||||||
|
post_processor_handle(NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Win32PostProcessor::~Win32PostProcessor()
|
||||||
|
{
|
||||||
|
Kill();
|
||||||
|
if (lIdInst)
|
||||||
|
{
|
||||||
|
::DdeUninitialize(lIdInst);
|
||||||
|
lIdInst = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NormPostProcessor* NormPostProcessor::Create()
|
||||||
|
{
|
||||||
|
Win32PostProcessor* p = new Win32PostProcessor();
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
if (p->Init())
|
||||||
|
return static_cast<NormPostProcessor*>(p);
|
||||||
|
else
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
} // end NormPostProcessor::Create()
|
||||||
|
|
||||||
|
bool Win32PostProcessor::Init()
|
||||||
|
{
|
||||||
|
// Init DDE
|
||||||
|
if (0 != lIdInst)
|
||||||
|
{
|
||||||
|
// already exists
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (::DdeInitialize(&lIdInst,
|
||||||
|
(PFNCALLBACK)DDEClientCallback,
|
||||||
|
APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0ul))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end Win32PostProcessor::Init()
|
||||||
|
|
||||||
|
|
||||||
|
void Win32PostProcessor::Kill()
|
||||||
|
{
|
||||||
|
if (hConv)
|
||||||
|
{
|
||||||
|
DdeDisconnect(hConv);
|
||||||
|
hConv = NULL;
|
||||||
|
}
|
||||||
|
if (post_processor_handle)
|
||||||
|
{
|
||||||
|
TerminateProcess(post_processor_handle, 0);
|
||||||
|
CloseHandle(post_processor_handle);
|
||||||
|
post_processor_handle = NULL;
|
||||||
|
}
|
||||||
|
} // end Win32PostProcessor::Kill()
|
||||||
|
|
||||||
|
|
||||||
|
bool Win32PostProcessor::ProcessFile(const char *path)
|
||||||
|
{
|
||||||
|
|
||||||
|
// DDE seems to be broken for the moment
|
||||||
|
// (It does work if the serving applications is _already_ running
|
||||||
|
// so these two lines of code disable it for the moment)
|
||||||
|
bool useDDE = false;
|
||||||
|
if (useDDE)
|
||||||
|
{
|
||||||
|
if (NULL == hConv)
|
||||||
|
{
|
||||||
|
HSZ szServerName = ::DdeCreateStringHandle(lIdInst, process_argv[0], CP_WINANSI);
|
||||||
|
HSZ szTopicName = ::DdeCreateStringHandle(lIdInst, "WWW_OpenURL", CP_WINANSI);
|
||||||
|
DMSG(4, "Win32PostProcessor::ProcessFile() calling DdeConnect(WWW_OpenURL) ...\n");
|
||||||
|
if ((hConv = ::DdeConnect(lIdInst, szServerName, szTopicName, 0)))
|
||||||
|
DMSG(4, "Win32PostProcessor::ProcessFile() DdeConnect() completed successfully.\n");
|
||||||
|
else
|
||||||
|
DMSG(4, "Win32PostProcessor::ProcessFile() DdeConnect() failed\n");
|
||||||
|
DdeFreeStringHandle(lIdInst, szTopicName);
|
||||||
|
DdeFreeStringHandle(lIdInst, szServerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hConv)
|
||||||
|
{
|
||||||
|
char ddeText[PATH_MAX+128];
|
||||||
|
sprintf(ddeText, "\"file://%s\",,%d,0,,,NETREPORT", path, window_id);
|
||||||
|
HSZ szParams = ::DdeCreateStringHandle(lIdInst, ddeText, CP_WINANSI);
|
||||||
|
TRACE("Win32PostProcessor::ProcessFile() calling DdeClientTransaction() ...\n");
|
||||||
|
if(DdeClientTransaction(NULL, 0, hConv, szParams, CF_TEXT,
|
||||||
|
XTYP_REQUEST, TIMEOUT_ASYNC,
|
||||||
|
&transaction_id))
|
||||||
|
{
|
||||||
|
DdeSetUserHandle(hConv, transaction_id, (DWORD_PTR)this);
|
||||||
|
DdeFreeStringHandle(lIdInst, szParams);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMSG(0, "Win32PostProcessor::ProcessFile() DdeClientTransaction() failure ...\n");
|
||||||
|
DdeFreeStringHandle(lIdInst, szParams);
|
||||||
|
DdeDisconnect(hConv);
|
||||||
|
hConv = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end if (NULL != post_processor_handle)
|
||||||
|
|
||||||
|
// DDE post processor evidently not running
|
||||||
|
// Launch post processor with shell command
|
||||||
|
// For now we assume the DDE server name & command name are the
|
||||||
|
// same and that the post processor command executable is in
|
||||||
|
// the PATH
|
||||||
|
|
||||||
|
// Kill old PostProcessor first
|
||||||
|
Kill();
|
||||||
|
|
||||||
|
// Construct the command line
|
||||||
|
char args[PATH_MAX+512];
|
||||||
|
args[0] = '\0';
|
||||||
|
for (unsigned int i = 1; i < process_argc; i++)
|
||||||
|
{
|
||||||
|
strcat("%s ", process_argv[i]);
|
||||||
|
}
|
||||||
|
strcat(args, path);
|
||||||
|
|
||||||
|
DMSG(4, "Win32PostProcessor::ProcessFile() execing \"%s %s\"\n", process_argv[0], args);
|
||||||
|
|
||||||
|
SHELLEXECUTEINFO exeInfo;
|
||||||
|
exeInfo.cbSize = sizeof(SHELLEXECUTEINFO);
|
||||||
|
exeInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||||
|
exeInfo.hwnd = NULL;
|
||||||
|
exeInfo.lpVerb = NULL;
|
||||||
|
exeInfo.lpFile = process_argv[0];
|
||||||
|
exeInfo.lpParameters = args;
|
||||||
|
exeInfo.lpDirectory = NULL;
|
||||||
|
exeInfo.nShow = SW_SHOW;
|
||||||
|
if (!ShellExecuteEx(&exeInfo))
|
||||||
|
{
|
||||||
|
post_processor_handle = NULL;
|
||||||
|
DMSG(0, "Error launching post processor!\n\"%s %s %s\"", process_argv[0], args);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
post_processor_handle = exeInfo.hProcess;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // end Win32PostProcessor::ProcessFile()
|
||||||
Loading…
Reference in New Issue