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 "normPostProcess.h"
|
||||
|
||||
#include <stdio.h> // for stdout/stderr printouts
|
||||
#include <signal.h> // for SIGTERM/SIGINT handling
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Command-line application using Protolib EventDispatcher
|
||||
class NormApp : public NormController
|
||||
class NormApp : public NormController, public ProtoApp
|
||||
{
|
||||
public:
|
||||
NormApp();
|
||||
virtual ~NormApp();
|
||||
bool OnStartup();
|
||||
int MainLoop() {return dispatcher.Run();}
|
||||
void Stop(int exitCode) {dispatcher.Stop(exitCode);}
|
||||
|
||||
// Overrides from ProtoApp or NsProtoSimAgent base
|
||||
bool OnStartup(int argc, const char*const* argv);
|
||||
bool ProcessCommands(int argc, const char*const* argv);
|
||||
void OnShutdown();
|
||||
|
||||
bool ProcessCommand(const char* cmd, const char* val);
|
||||
bool ParseCommandLine(int argc, char* argv[]);
|
||||
|
||||
static void DoInputReady(EventDispatcher::Descriptor descriptor,
|
||||
EventDispatcher::EventType theEvent,
|
||||
const void* userData);
|
||||
static void DoInputReady(ProtoDispatcher::Descriptor descriptor,
|
||||
ProtoDispatcher::Event theEvent,
|
||||
const void* userData);
|
||||
|
||||
private:
|
||||
void OnInputReady();
|
||||
|
|
@ -39,17 +40,14 @@ class NormApp : public NormController
|
|||
class NormServerNode* server,
|
||||
class NormObject* object);
|
||||
|
||||
void InstallTimer(ProtocolTimer* timer)
|
||||
{dispatcher.InstallTimer(timer);}
|
||||
bool OnIntervalTimeout();
|
||||
bool OnIntervalTimeout(ProtoTimer& theTimer);
|
||||
|
||||
static const char* const cmd_list[];
|
||||
|
||||
#ifdef UNIX
|
||||
static void SignalHandler(int sigNum);
|
||||
bool IsPostProcessing() {return post_processor.IsActive();}
|
||||
void HandleSIGCHLD() {post_processor.HandleSIGCHLD();}
|
||||
#endif // UNIX
|
||||
|
||||
EventDispatcher dispatcher;
|
||||
NormSessionMgr session_mgr;
|
||||
NormSession* session;
|
||||
NormStreamObject* tx_stream;
|
||||
|
|
@ -91,13 +89,13 @@ class NormApp : public NormController
|
|||
double tx_object_interval;
|
||||
int tx_repeat_count;
|
||||
double tx_repeat_interval;
|
||||
ProtocolTimer interval_timer;
|
||||
ProtoTimer interval_timer;
|
||||
|
||||
// NormSession client-only parameters
|
||||
unsigned long rx_buffer_size; // bytes
|
||||
NormFileList rx_file_cache;
|
||||
char* rx_cache_path;
|
||||
NormPostProcessor post_processor;
|
||||
NormPostProcessor* post_processor;
|
||||
bool unicast_nacks;
|
||||
bool silent_client;
|
||||
|
||||
|
|
@ -109,7 +107,8 @@ class NormApp : public NormController
|
|||
}; // end class 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),
|
||||
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),
|
||||
|
|
@ -122,14 +121,14 @@ NormApp::NormApp()
|
|||
tracing(false), tx_loss(0.0), rx_loss(0.0)
|
||||
{
|
||||
// Init tx_timer for 1.0 second interval, infinite repeats
|
||||
session_mgr.Init(EventDispatcher::TimerInstaller, &dispatcher,
|
||||
EventDispatcher::SocketInstaller, &dispatcher,
|
||||
this);
|
||||
interval_timer.Init(0.0, 0, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormApp::OnIntervalTimeout);
|
||||
session_mgr.SetController(this);
|
||||
|
||||
interval_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormApp::OnIntervalTimeout);
|
||||
interval_timer.SetInterval(0.0);
|
||||
interval_timer.SetRepeat(0);
|
||||
|
||||
struct timeval currentTime;
|
||||
GetSystemTime(¤tTime);
|
||||
ProtoSystemTime(currentTime);
|
||||
srand(currentTime.tv_usec);
|
||||
}
|
||||
|
||||
|
|
@ -137,6 +136,7 @@ NormApp::~NormApp()
|
|||
{
|
||||
if (address) delete address;
|
||||
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))
|
||||
{
|
||||
if (!strcmp(val, "STDIN"))
|
||||
{
|
||||
{
|
||||
input = stdin;
|
||||
}
|
||||
}
|
||||
else if (!(input = fopen(val, "rb")))
|
||||
{
|
||||
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_messaging = false;
|
||||
#ifdef UNIX
|
||||
// Set input non-blocking
|
||||
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");
|
||||
#endif // UNIX
|
||||
}
|
||||
else if (!strncmp("output", cmd, len))
|
||||
{
|
||||
if (!strcmp(val, "STDOUT"))
|
||||
{
|
||||
{
|
||||
output = stdout;
|
||||
}
|
||||
}
|
||||
else if (!(output = fopen(val, "wb")))
|
||||
{
|
||||
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))
|
||||
{
|
||||
if (!strcmp(val, "STDIN"))
|
||||
{
|
||||
{
|
||||
input = stdin;
|
||||
}
|
||||
}
|
||||
else if (!(input = fopen(val, "rb")))
|
||||
{
|
||||
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_messaging = true;
|
||||
#ifdef UNIX
|
||||
// Set input non-blocking
|
||||
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");
|
||||
#endif // UNIX
|
||||
}
|
||||
else if (!strncmp("moutput", cmd, len))
|
||||
{
|
||||
if (!strcmp(val, "STDOUT"))
|
||||
{
|
||||
{
|
||||
output = stdout;
|
||||
}
|
||||
}
|
||||
else if (!(output = fopen(val, "wb")))
|
||||
{
|
||||
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))
|
||||
{
|
||||
unsigned int length = strlen(val);
|
||||
// Make sure there is a trailing DIR_DELIMITER
|
||||
if (DIR_DELIMITER != val[length-1])
|
||||
// Make sure there is a trailing PROTO_PATH_DELIMITER
|
||||
if (PROTO_PATH_DELIMITER != val[length-1])
|
||||
length += 2;
|
||||
else
|
||||
length += 1;
|
||||
|
|
@ -416,7 +420,7 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
|
|||
return false;
|
||||
}
|
||||
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';
|
||||
}
|
||||
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))
|
||||
{
|
||||
if (!post_processor.SetCommand(val))
|
||||
if (!post_processor->SetCommand(val))
|
||||
{
|
||||
DMSG(0, "NormApp::ProcessCommand(processor) error!\n");
|
||||
return false;
|
||||
|
|
@ -555,7 +559,7 @@ NormApp::CmdType NormApp::CommandType(const char* cmd)
|
|||
} // end NormApp::CommandType()
|
||||
|
||||
|
||||
bool NormApp::ParseCommandLine(int argc, char* argv[])
|
||||
bool NormApp::ProcessCommands(int argc, const char*const* argv)
|
||||
{
|
||||
int i = 1;
|
||||
while ( i < argc)
|
||||
|
|
@ -564,13 +568,13 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
|
|||
switch (cmdType)
|
||||
{
|
||||
case CMD_INVALID:
|
||||
DMSG(0, "NormApp::ParseCommandLine() Invalid command:%s\n",
|
||||
DMSG(0, "NormApp::ProcessCommands() Invalid command:%s\n",
|
||||
argv[i]);
|
||||
return false;
|
||||
case CMD_NOARG:
|
||||
if (!ProcessCommand(argv[i], NULL))
|
||||
{
|
||||
DMSG(0, "NormApp::ParseCommandLine() ProcessCommand(%s) error\n",
|
||||
DMSG(0, "NormApp::ProcessCommands() ProcessCommand(%s) error\n",
|
||||
argv[i]);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -579,7 +583,7 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
|
|||
case CMD_ARG:
|
||||
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]);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -588,10 +592,10 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
return true;
|
||||
} // end NormApp::ParseCommandLine()
|
||||
} // end NormApp::ProcessCommands()
|
||||
|
||||
void NormApp::DoInputReady(EventDispatcher::Descriptor /*descriptor*/,
|
||||
EventDispatcher::EventType /*theEvent*/,
|
||||
void NormApp::DoInputReady(ProtoDispatcher::Descriptor /*descriptor*/,
|
||||
ProtoDispatcher::Event /*theEvent*/,
|
||||
const void* userData)
|
||||
{
|
||||
((NormApp*)userData)->OnInputReady();
|
||||
|
|
@ -607,6 +611,8 @@ void NormApp::OnInputReady()
|
|||
// the stream has buffer space for input
|
||||
while (input)
|
||||
{
|
||||
bool inputStarved = false;
|
||||
|
||||
if (0 == input_length)
|
||||
{
|
||||
// We need input ...
|
||||
|
|
@ -667,7 +673,11 @@ void NormApp::OnInputReady()
|
|||
DMSG(0, "norm: input end-of-file.\n");
|
||||
if (input_active)
|
||||
{
|
||||
#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;
|
||||
}
|
||||
if (stdin != input) fclose(input);
|
||||
|
|
@ -679,8 +689,10 @@ void NormApp::OnInputReady()
|
|||
switch (errno)
|
||||
{
|
||||
case EINTR:
|
||||
continue;
|
||||
case EAGAIN:
|
||||
// Input not ready, will get notification when ready
|
||||
inputStarved = true;
|
||||
break;
|
||||
default:
|
||||
DMSG(0, "norm: input error:%s\n", strerror(errno));
|
||||
|
|
@ -716,30 +728,37 @@ void NormApp::OnInputReady()
|
|||
{
|
||||
// Stream buffer full, temporarily deactive "input" and
|
||||
// wait for next TX_QUEUE_EMPTY notification
|
||||
//TRACE("stream buffer full ...\n");
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (inputStarved)
|
||||
{
|
||||
// Input not ready, wait for "input" to be ready
|
||||
// (Activate/reactivate "input" as necessary
|
||||
//TRACE("input starved ...\n");
|
||||
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;
|
||||
else
|
||||
DMSG(0, "NormApp::Notify(TX_QUEUE_EMPTY) error adding input notification!\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
} // end while (1)
|
||||
} // end while (input)
|
||||
} // NormApp::OnInputReady()
|
||||
|
||||
|
||||
|
|
@ -762,14 +781,10 @@ void NormApp::Notify(NormController::Event event,
|
|||
{
|
||||
// Can queue a new object for transmission
|
||||
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
||||
if (interval_timer.Interval() > 0.0)
|
||||
{
|
||||
InstallTimer(&interval_timer);
|
||||
}
|
||||
if (interval_timer.GetInterval() > 0.0)
|
||||
ActivateTimer(interval_timer);
|
||||
else
|
||||
{
|
||||
OnIntervalTimeout();
|
||||
}
|
||||
OnIntervalTimeout(interval_timer);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -789,7 +804,7 @@ void NormApp::Notify(NormController::Event event,
|
|||
// object Size() has recommended buffering size
|
||||
NormObjectSize size;
|
||||
if (silent_client)
|
||||
size = NormObjectSize(rx_buffer_size);
|
||||
size = NormObjectSize((UINT32)rx_buffer_size);
|
||||
else
|
||||
size = object->Size();
|
||||
|
||||
|
|
@ -863,7 +878,7 @@ void NormApp::Notify(NormController::Event event,
|
|||
for (UINT16 i = pathLen; i < (pathLen+len); i++)
|
||||
{
|
||||
if ('/' == fileName[i])
|
||||
fileName[i] = DIR_DELIMITER;
|
||||
fileName[i] = PROTO_PATH_DELIMITER;
|
||||
}
|
||||
pathLen += len;
|
||||
if (pathLen < PATH_MAX) fileName[pathLen] = '\0';
|
||||
|
|
@ -947,7 +962,8 @@ void NormApp::Notify(NormController::Event event,
|
|||
}
|
||||
else
|
||||
{
|
||||
output_msg_sync = true;
|
||||
if (readLength > 0)
|
||||
output_msg_sync = true;
|
||||
}
|
||||
|
||||
if (readLength)
|
||||
|
|
@ -1015,15 +1031,16 @@ void NormApp::Notify(NormController::Event event,
|
|||
|
||||
case RX_OBJECT_COMPLETE:
|
||||
{
|
||||
//TRACE("NormApp::Notify(RX_OBJECT_COMPLETE) ...\n");
|
||||
switch(object->GetType())
|
||||
{
|
||||
case NormObject::FILE:
|
||||
{
|
||||
const char* filePath = ((NormFileObject*)object)->Path();
|
||||
//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");
|
||||
}
|
||||
|
|
@ -1044,7 +1061,7 @@ void NormApp::Notify(NormController::Event event,
|
|||
} // end NormApp::Notify()
|
||||
|
||||
|
||||
bool NormApp::OnIntervalTimeout()
|
||||
bool NormApp::OnIntervalTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
char fileName[PATH_MAX];
|
||||
if (tx_file_list.GetNextFile(fileName))
|
||||
|
|
@ -1063,7 +1080,7 @@ bool NormApp::OnIntervalTimeout()
|
|||
// Normalize directory delimiters in file name info
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
{
|
||||
if (DIR_DELIMITER == fileNameInfo[i])
|
||||
if (PROTO_PATH_DELIMITER == fileNameInfo[i])
|
||||
fileNameInfo[i] = '/';
|
||||
}
|
||||
char temp[PATH_MAX];
|
||||
|
|
@ -1076,7 +1093,7 @@ bool NormApp::OnIntervalTimeout()
|
|||
// Wait a second, then try the next file in the list
|
||||
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
||||
interval_timer.SetInterval(1.0);
|
||||
InstallTimer(&interval_timer);
|
||||
ActivateTimer(interval_timer);
|
||||
return false;
|
||||
}
|
||||
//DMSG(0, "norm: File \"%s\" queued for transmission.\n", fileName);
|
||||
|
|
@ -1091,12 +1108,12 @@ bool NormApp::OnIntervalTimeout()
|
|||
{
|
||||
if (interval_timer.IsActive()) interval_timer.Deactivate();
|
||||
interval_timer.SetInterval(tx_repeat_interval = tx_object_interval);
|
||||
InstallTimer(&interval_timer);
|
||||
ActivateTimer(interval_timer);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OnIntervalTimeout();
|
||||
return OnIntervalTimeout(interval_timer);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1106,19 +1123,24 @@ bool NormApp::OnIntervalTimeout()
|
|||
return true;
|
||||
} // 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);
|
||||
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
|
||||
if (!address)
|
||||
|
|
@ -1200,7 +1222,11 @@ void NormApp::OnShutdown()
|
|||
{
|
||||
if (input_active)
|
||||
{
|
||||
#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;
|
||||
}
|
||||
if (stdin != input) fclose(input);
|
||||
|
|
@ -1211,97 +1237,32 @@ void NormApp::OnShutdown()
|
|||
if (stdout != output) fclose(output);
|
||||
output = NULL;
|
||||
}
|
||||
if (post_processor)
|
||||
{
|
||||
delete post_processor;
|
||||
post_processor = NULL;
|
||||
}
|
||||
} // end NormApp::OnShutdown()
|
||||
|
||||
// Out application instance
|
||||
PROTO_INSTANTIATE_APP(NormApp);
|
||||
|
||||
// Out application instance (global for SignalHandler)
|
||||
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();
|
||||
|
||||
|
||||
|
||||
#ifdef UNIX
|
||||
void NormApp::SignalHandler(int sigNum)
|
||||
{
|
||||
switch(sigNum)
|
||||
{
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
theApp.Stop(sigNum); // causes theApp's main loop to exit
|
||||
break;
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "norm: Unexpected signal: %d\n", sigNum);
|
||||
break;
|
||||
}
|
||||
} // end NormApp::SignalHandler()
|
||||
#endif // UNIX
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#ifndef _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 <stdio.h> // for fprintf()
|
||||
|
||||
|
|
@ -183,7 +184,6 @@ class NormSlidingMask
|
|||
long start;
|
||||
long end;
|
||||
unsigned long offset;
|
||||
unsigned char* mask2;
|
||||
}; // end class NormSlidingMask
|
||||
|
||||
#endif // _NORM_BITMASK_
|
||||
|
|
|
|||
|
|
@ -146,13 +146,14 @@ bool NormEncoder::CreateGeneratorPolynomial()
|
|||
for (int i = 0; i < degree; i++)
|
||||
{
|
||||
memset(&tp2[degree], 0, degree*sizeof(unsigned char));
|
||||
int j;
|
||||
// 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
|
||||
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));
|
||||
// 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));
|
||||
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;
|
||||
#endif // if/else SIMUATE
|
||||
|
||||
for (int i = 0; i < npar; i++)
|
||||
int i;
|
||||
for (i = 0; i < npar; i++)
|
||||
{
|
||||
int X = gexp(i+1);
|
||||
unsigned char* synVec = sVec[i];
|
||||
|
|
@ -365,7 +367,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
|
|||
int nvecsMinusOne = nvecs - 1;
|
||||
memset(Lambda, 0, degree*sizeof(char));
|
||||
Lambda[0] = 1;
|
||||
for (int i = 0; i < erasureCount; i++)
|
||||
for (i = 0; i < erasureCount; i++)
|
||||
{
|
||||
int X = gexp(nvecsMinusOne - erasureLocs[i]);
|
||||
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
|
||||
for(int i = 0; i < npar; i++)
|
||||
for(i = 0; i < npar; i++)
|
||||
{
|
||||
int k = i;
|
||||
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
|
||||
for (int i = 0; i < erasureCount; i++)
|
||||
for (i = 0; i < erasureCount; i++)
|
||||
{
|
||||
// Only fill _data_ erasures
|
||||
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)
|
||||
int k = nvecsMinusOne - erasureLocs[i];
|
||||
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));
|
||||
// Invert for use computing errror value below
|
||||
denom = ginv(denom);
|
||||
|
||||
// Now evaluate Omega at alpha^(-i) (numerator)
|
||||
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* Omega = oVec[j];
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#ifndef _NORM_ENCODER
|
||||
#define _NORM_ENCODER
|
||||
|
||||
#include "sysdefs.h" // protolib stuff
|
||||
#include "protokit.h" // protolib stuff
|
||||
|
||||
class NormEncoder
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <string.h> // for strerror()
|
||||
#include <errno.h> // for errno
|
||||
|
||||
#include <stdio.h> // for rename()
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#include <share.h>
|
||||
|
|
@ -34,14 +34,14 @@ bool NormFile::Open(const char* thePath, int theFlags)
|
|||
// Create sub-directories as needed.
|
||||
char tempPath[PATH_MAX];
|
||||
strncpy(tempPath, thePath, PATH_MAX);
|
||||
char* ptr = strrchr(tempPath, DIR_DELIMITER);
|
||||
char* ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||
if (ptr) *ptr = '\0';
|
||||
ptr = NULL;
|
||||
while (!NormFile::Exists(tempPath))
|
||||
{
|
||||
char* ptr2 = ptr;
|
||||
ptr = strrchr(tempPath, DIR_DELIMITER);
|
||||
if (ptr2) *ptr2 = DIR_DELIMITER;
|
||||
ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||
if (ptr2) *ptr2 = PROTO_PATH_DELIMITER;
|
||||
if (ptr)
|
||||
{
|
||||
*ptr = '\0';
|
||||
|
|
@ -52,18 +52,22 @@ bool NormFile::Open(const char* thePath, int theFlags)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (ptr && ('\0' == *ptr)) *ptr++ = DIR_DELIMITER;
|
||||
if (ptr && ('\0' == *ptr)) *ptr++ = PROTO_PATH_DELIMITER;
|
||||
while (ptr)
|
||||
{
|
||||
ptr = strchr(ptr, DIR_DELIMITER);
|
||||
ptr = strchr(ptr, PROTO_PATH_DELIMITER);
|
||||
if (ptr) *ptr = '\0';
|
||||
#ifdef WIN32
|
||||
if (mkdir(tempPath))
|
||||
#else
|
||||
if (mkdir(tempPath, 0755))
|
||||
#endif // if/else WIN32/UNIX
|
||||
{
|
||||
DMSG(0, "NormFile::Rename() mkdir(%s) error: %s\n",
|
||||
tempPath, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (ptr) *ptr++ = DIR_DELIMITER;
|
||||
if (ptr) *ptr++ = PROTO_PATH_DELIMITER;
|
||||
}
|
||||
}
|
||||
#ifdef WIN32
|
||||
|
|
@ -82,8 +86,7 @@ bool NormFile::Open(const char* thePath, int theFlags)
|
|||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "Error opening file \"%s\": %s\n", path,
|
||||
strerror(errno));
|
||||
DMSG(0, "Error opening file \"%s\": %s\n", thePath, strerror(errno));
|
||||
flags = 0;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -159,7 +162,7 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
|||
if (NormFile::IsLocked(newName)) return false;
|
||||
#ifdef WIN32
|
||||
// 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
|
||||
int oldFlags = 0;
|
||||
if (IsOpen())
|
||||
|
|
@ -172,14 +175,14 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
|||
// Create sub-directories as needed.
|
||||
char tempPath[PATH_MAX];
|
||||
strncpy(tempPath, newName, PATH_MAX);
|
||||
char* ptr = strrchr(tempPath, DIR_DELIMITER);
|
||||
char* ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||
if (ptr) *ptr = '\0';
|
||||
ptr = NULL;
|
||||
while (!NormFile::Exists(tempPath))
|
||||
{
|
||||
char* ptr2 = ptr;
|
||||
ptr = strrchr(tempPath, DIR_DELIMITER);
|
||||
if (ptr2) *ptr2 = DIR_DELIMITER;
|
||||
ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
|
||||
if (ptr2) *ptr2 = PROTO_PATH_DELIMITER;
|
||||
if (ptr)
|
||||
{
|
||||
*ptr = '\0';
|
||||
|
|
@ -190,10 +193,10 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (ptr && ('\0' == *ptr)) *ptr++ = DIR_DELIMITER;
|
||||
if (ptr && ('\0' == *ptr)) *ptr++ = PROTO_PATH_DELIMITER;
|
||||
while (ptr)
|
||||
{
|
||||
ptr = strchr(ptr, DIR_DELIMITER);
|
||||
ptr = strchr(ptr, PROTO_PATH_DELIMITER);
|
||||
if (ptr) *ptr = '\0';
|
||||
if (mkdir(tempPath, 0755))
|
||||
{
|
||||
|
|
@ -201,7 +204,7 @@ bool NormFile::Rename(const char* oldName, const char* newName)
|
|||
tempPath, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (ptr) *ptr++ = DIR_DELIMITER;
|
||||
if (ptr) *ptr++ = PROTO_PATH_DELIMITER;
|
||||
}
|
||||
#endif // if/else WIN32
|
||||
if (rename(oldName, newName))
|
||||
|
|
@ -367,7 +370,7 @@ bool NormDirectoryIterator::GetNextFile(char* fileName)
|
|||
bool success = true;
|
||||
while(success)
|
||||
{
|
||||
WIN32_findData findData;
|
||||
WIN32_FIND_DATA findData;
|
||||
if (current->hSearch == (HANDLE)-1)
|
||||
{
|
||||
// Construct search string
|
||||
|
|
@ -387,7 +390,7 @@ bool NormDirectoryIterator::GetNextFile(char* fileName)
|
|||
// Do we have a candidate file?
|
||||
if (success)
|
||||
{
|
||||
char* ptr = strrchr(findData.cFileName, DIR_DELIMITER);
|
||||
char* ptr = strrchr(findData.cFileName, PROTO_PATH_DELIMITER);
|
||||
if (ptr)
|
||||
ptr += 1;
|
||||
else
|
||||
|
|
@ -535,9 +538,9 @@ NormDirectoryIterator::NormDirectory::NormDirectory(const char* thePath,
|
|||
{
|
||||
strncpy(path, thePath, PATH_MAX);
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
|
@ -552,9 +555,9 @@ bool NormDirectoryIterator::NormDirectory::Open()
|
|||
Close(); // in case it's already open
|
||||
char fullName[PATH_MAX];
|
||||
GetFullName(fullName);
|
||||
// Get rid of trailing DIR_DELIMITER
|
||||
// Get rid of trailing PROTO_PATH_DELIMITER
|
||||
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
|
||||
DWORD attr = GetFileAttributes(fullName);
|
||||
if (0xFFFFFFFF == attr)
|
||||
|
|
@ -581,8 +584,11 @@ void NormDirectoryIterator::NormDirectory::Close()
|
|||
hSearch = (HANDLE)-1;
|
||||
}
|
||||
#else
|
||||
closedir(dptr);
|
||||
dptr = NULL;
|
||||
if (dptr)
|
||||
{
|
||||
closedir(dptr);
|
||||
dptr = NULL;
|
||||
}
|
||||
#endif // if/else WIN32
|
||||
} // end NormDirectoryIterator::NormDirectory::Close()
|
||||
|
||||
|
|
@ -856,15 +862,15 @@ void NormFileList::GetCurrentBasePath(char* pathBuffer)
|
|||
strncpy(pathBuffer, next->Path(), PATH_MAX);
|
||||
unsigned int len = strlen(pathBuffer);
|
||||
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';
|
||||
}
|
||||
}
|
||||
else // NormFile::NORMAL
|
||||
{
|
||||
const char* ptr = strrchr(next->Path(), DIR_DELIMITER);
|
||||
const char* ptr = strrchr(next->Path(), PROTO_PATH_DELIMITER);
|
||||
if (ptr++)
|
||||
{
|
||||
unsigned int len = ptr - next->Path();
|
||||
|
|
@ -925,6 +931,7 @@ bool NormFileList::FileItem::GetNextFile(char* thePath,
|
|||
NormFileList::DirectoryItem::DirectoryItem(const char* thePath)
|
||||
: NormFileList::FileItem(thePath)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NormFileList::DirectoryItem::~DirectoryItem()
|
||||
|
|
@ -963,9 +970,9 @@ bool NormFileList::DirectoryItem::GetNextFile(char* thePath,
|
|||
strncpy(thePath, path, PATH_MAX);
|
||||
unsigned int len = strlen(thePath);
|
||||
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';
|
||||
}
|
||||
char tempPath[PATH_MAX];
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
// From PROTOLIB
|
||||
#include "sysdefs.h" // for bool definition, DIR_DELIMITER, PATH_MAX, etc
|
||||
#include "debug.h" // for DEBUG stuff
|
||||
#include "protokit.h" // for Protolib stuff
|
||||
|
||||
class NormFile
|
||||
{
|
||||
|
|
@ -61,11 +60,11 @@ class NormFile
|
|||
#ifdef WIN32
|
||||
DWORD attr = GetFileAttributes(path);
|
||||
return ((0xFFFFFFFF == attr) ?
|
||||
false : (0 == (attr & FILE_ATTRIBUTE_READONLY)));
|
||||
false : (0 == (attr & FILE_ATTRIBUTE_READONLY)));
|
||||
#else
|
||||
return (0 == access(path, W_OK));
|
||||
}
|
||||
#endif // if/else WIN32
|
||||
}
|
||||
|
||||
|
||||
// Members
|
||||
|
|
@ -73,7 +72,9 @@ class NormFile
|
|||
int fd;
|
||||
int flags;
|
||||
off_t offset;
|
||||
};
|
||||
}; // end class NormFile
|
||||
|
||||
|
||||
|
||||
/******************************************
|
||||
* The NormDirectory and NormDirectoryIterator classes
|
||||
|
|
@ -98,11 +99,11 @@ class NormDirectoryIterator
|
|||
private:
|
||||
char path[PATH_MAX];
|
||||
NormDirectory* parent;
|
||||
#ifdef WIN32
|
||||
#ifdef WIN32
|
||||
HANDLE hSearch;
|
||||
#else
|
||||
#else
|
||||
DIR* dptr;
|
||||
#endif // if/else WIN32
|
||||
#endif // if/else WIN32
|
||||
NormDirectory(const char *thePath, NormDirectory* theParent = NULL);
|
||||
~NormDirectory();
|
||||
void GetFullName(char* namePtr);
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ bool NormRepairRequest::AppendRepairItem(const NormObjectId& objectId,
|
|||
if (buffer_len >= (length+ITEM_LIST_OFFSET+RepairItemLength()))
|
||||
{
|
||||
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
||||
ptr[FEC_ID_OFFSET] = 129;
|
||||
ptr[FEC_ID_OFFSET] = (char)129;
|
||||
ptr[RESERVED_OFFSET] = 0;
|
||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
|
||||
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId);
|
||||
|
|
@ -181,7 +181,7 @@ bool NormRepairRequest::AppendRepairRange(const NormObjectId& startObjectId,
|
|||
{
|
||||
// range start
|
||||
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
||||
ptr[FEC_ID_OFFSET] = 129;
|
||||
ptr[FEC_ID_OFFSET] = (char)129;
|
||||
ptr[RESERVED_OFFSET] = 0;
|
||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)startObjectId);
|
||||
*((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);
|
||||
ptr += RepairItemLength();
|
||||
// range end
|
||||
ptr[FEC_ID_OFFSET] = 129;
|
||||
ptr[FEC_ID_OFFSET] = (char)129;
|
||||
ptr[RESERVED_OFFSET] = 0;
|
||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)endObjectId);
|
||||
*((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()))
|
||||
{
|
||||
char* ptr = buffer + length + ITEM_LIST_OFFSET;
|
||||
ptr[FEC_ID_OFFSET] = 129;
|
||||
ptr[FEC_ID_OFFSET] = (char)129;
|
||||
ptr[RESERVED_OFFSET] = 0;
|
||||
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
|
||||
*((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)))));
|
||||
} // end NormQuantizeRtt()
|
||||
|
||||
|
||||
|
||||
bool NormObjectSize::operator<(const NormObjectSize& size) const
|
||||
{
|
||||
UINT16 diff = msb - size.msb;
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@
|
|||
#define _NORM_MESSAGE
|
||||
|
||||
// PROTOLIB includes
|
||||
#include "networkAddress.h" // for NetworkAddress class
|
||||
#include "sysdefs.h" // for UINT typedefs
|
||||
#include "debug.h"
|
||||
#include "protokit.h"
|
||||
|
||||
// standard includes
|
||||
#include <string.h> // for memcpy(), etc
|
||||
#include <math.h>
|
||||
|
||||
#include <stdlib.h> // for rand(), etc
|
||||
|
||||
#ifdef SIMULATE
|
||||
#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
|
||||
|
||||
|
||||
// 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
|
||||
// NORM protocol. (Note that our Grtt quantization routines
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
unsigned char exponent = (unsigned char)log10(gsize);
|
||||
exponent = MIN(exponent, 0x0f);
|
||||
return ((((unsigned char)(gsize / pow(10.0, (double)exponent) + 0.5)) << 4) | exponent);
|
||||
unsigned char ebits = (unsigned char)log10(gsize);
|
||||
int mantissa = (int)((gsize/pow(10.0, (double)ebits)) + 0.5);
|
||||
// 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)
|
||||
|
|
@ -62,8 +83,7 @@ inline double NormUnquantizeLoss(unsigned short lossQuantized)
|
|||
|
||||
inline unsigned short NormQuantizeRate(double rate)
|
||||
{
|
||||
unsigned char exponent = (unsigned short)log10(rate);
|
||||
exponent = MIN(exponent, 0xff);
|
||||
unsigned char exponent = (unsigned char)log10(rate);
|
||||
unsigned short mantissa = (unsigned short)((256.0/10.0) * rate / pow(10.0, (double)exponent));
|
||||
return ((mantissa << 8) | exponent);
|
||||
}
|
||||
|
|
@ -88,7 +108,11 @@ class NormObjectSize
|
|||
UINT32 LSB() const {return lsb;}
|
||||
|
||||
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 ((*this == size) || (*this>size));}
|
||||
bool operator==(const NormObjectSize& size) const
|
||||
{return ((msb == size.msb) && (lsb == size.lsb));}
|
||||
bool operator!=(const NormObjectSize& size) const
|
||||
|
|
@ -135,7 +159,11 @@ class NormObjectId
|
|||
NormObjectId(const NormObjectId& id) {value = id.value;}
|
||||
operator UINT16() const {return value;}
|
||||
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) || (*this>id));}
|
||||
bool operator==(const NormObjectId& id) const
|
||||
{return (value == id.value);}
|
||||
bool operator!=(const NormObjectId& id) const
|
||||
|
|
@ -251,7 +279,7 @@ class NormMsg
|
|||
{
|
||||
*((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)
|
||||
{
|
||||
|
|
@ -272,8 +300,8 @@ class NormMsg
|
|||
{
|
||||
return (ntohl(*((UINT32*)(buffer+SOURCE_ID_OFFSET))));
|
||||
}
|
||||
const NetworkAddress& GetDestination() const {return addr;}
|
||||
const NetworkAddress& GetSource() const {return addr;}
|
||||
const ProtoAddress& GetDestination() const {return addr;}
|
||||
const ProtoAddress& GetSource() const {return addr;}
|
||||
const char* GetBuffer() {return buffer;}
|
||||
UINT16 GetLength() const {return length;}
|
||||
|
||||
|
|
@ -288,10 +316,9 @@ class NormMsg
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
// For message reception and misc.
|
||||
char* AccessBuffer() {return buffer;}
|
||||
NetworkAddress* AccessAddress() {return &addr;}
|
||||
ProtoAddress& AccessAddress() {return addr;}
|
||||
|
||||
protected:
|
||||
// Common message header offsets
|
||||
|
|
@ -321,7 +348,7 @@ class NormMsg
|
|||
UINT16 length;
|
||||
UINT16 header_length;
|
||||
UINT16 header_length_base;
|
||||
NetworkAddress addr; // src or dst address
|
||||
ProtoAddress addr; // src or dst address
|
||||
|
||||
NormMsg* prev;
|
||||
NormMsg* next;
|
||||
|
|
@ -349,7 +376,8 @@ class NormObjectMsg : public NormMsg
|
|||
return (ntohs(*((UINT16*)(buffer+SESSION_ID_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
|
||||
{return (0 != (flag & buffer[FLAGS_OFFSET]));}
|
||||
UINT8 GetFecId() const {return buffer[FEC_ID_OFFSET];}
|
||||
|
|
@ -364,7 +392,14 @@ class NormObjectMsg : public NormMsg
|
|||
*((UINT16*)(buffer+SESSION_ID_OFFSET)) = htons(sessionId);
|
||||
}
|
||||
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 SetFlag(NormObjectMsg::Flag flag) {buffer[FLAGS_OFFSET] |= flag;}
|
||||
void SetFecId(UINT8 fecId) {buffer[FEC_ID_OFFSET] = fecId;}
|
||||
|
|
@ -378,7 +413,8 @@ class NormObjectMsg : public NormMsg
|
|||
{
|
||||
SESSION_ID_OFFSET = MSG_OFFSET,
|
||||
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,
|
||||
FEC_ID_OFFSET = FLAGS_OFFSET + 1,
|
||||
OBJ_ID_OFFSET = FEC_ID_OFFSET + 1,
|
||||
|
|
@ -448,11 +484,11 @@ class NormFtiExtension : public NormHeaderExtension
|
|||
private:
|
||||
enum
|
||||
{
|
||||
FEC_INSTANCE_OFFSET = LENGTH_OFFSET + 1,
|
||||
FEC_NDATA_OFFSET = FEC_INSTANCE_OFFSET +2,
|
||||
FEC_NPARITY_OFFSET = FEC_NDATA_OFFSET + 2,
|
||||
SEG_SIZE_OFFSET = FEC_NPARITY_OFFSET+2,
|
||||
OBJ_SIZE_OFFSET = SEG_SIZE_OFFSET + 2
|
||||
OBJ_SIZE_OFFSET = LENGTH_OFFSET + 1,
|
||||
FEC_INSTANCE_OFFSET = OBJ_SIZE_OFFSET + 6,
|
||||
SEG_SIZE_OFFSET = FEC_INSTANCE_OFFSET +2,
|
||||
FEC_NDATA_OFFSET = SEG_SIZE_OFFSET + 2,
|
||||
FEC_NPARITY_OFFSET = FEC_NDATA_OFFSET + 2
|
||||
};
|
||||
}; // end class NormFtiExtension
|
||||
|
||||
|
|
@ -617,23 +653,32 @@ class NormCmdMsg : public NormMsg
|
|||
}
|
||||
void SetGrtt(UINT8 quantizedGrtt)
|
||||
{buffer[GRTT_OFFSET] = quantizedGrtt;}
|
||||
void SetGroupSize(UINT8 quantizedGroupSize)
|
||||
{buffer[GSIZE_OFFSET] = quantizedGroupSize;}
|
||||
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 SetFlavor(NormCmdMsg::Flavor flavor)
|
||||
{buffer[FLAVOR_OFFSET] = flavor;}
|
||||
|
||||
// Message processing
|
||||
UINT16 GetSessionId() const {return (ntohs(*((UINT16*)(buffer+SESSION_ID_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];}
|
||||
|
||||
protected:
|
||||
friend class NormMsg;
|
||||
enum
|
||||
{
|
||||
SESSION_ID_OFFSET = MSG_OFFSET,
|
||||
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
|
||||
};
|
||||
}; // end class NormCmdMsg
|
||||
|
|
|
|||
|
|
@ -37,12 +37,18 @@ NormServerNode::NormServerNode(class NormSession* theSession, NormNodeId nodeId)
|
|||
recv_total(0), recv_goodput(0), resync_count(0),
|
||||
nack_count(0), suppress_count(0), completion_count(0), failure_count(0)
|
||||
{
|
||||
repair_timer.Init(0.0, 1, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormServerNode::OnRepairTimeout);
|
||||
activity_timer.Init(0.0, -1, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormServerNode::OnActivityTimeout);
|
||||
cc_timer.Init(0.0, 1, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormServerNode::OnCCTimeout);
|
||||
repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnRepairTimeout);
|
||||
repair_timer.SetInterval(0.0);
|
||||
repair_timer.SetRepeat(1);
|
||||
|
||||
activity_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnActivityTimeout);
|
||||
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_usec = 0;
|
||||
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_estimate = NormUnquantizeGroupSize(gsize_quantized);
|
||||
|
||||
backoff_factor = NormSession::DEFAULT_BACKOFF_FACTOR;
|
||||
|
||||
rtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE);
|
||||
rtt_estimate = NormUnquantizeRtt(rtt_quantized);
|
||||
|
||||
|
|
@ -142,6 +150,7 @@ bool NormServerNode::Open(UINT16 sessionId, UINT16 segmentSize, UINT16 numData,
|
|||
|
||||
void NormServerNode::Close()
|
||||
{
|
||||
if (activity_timer.IsActive()) activity_timer.Deactivate();
|
||||
decoder.Destroy();
|
||||
if (erasure_loc)
|
||||
{
|
||||
|
|
@ -169,9 +178,9 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
grtt_quantized = grttQuantized;
|
||||
grtt_estimate = NormUnquantizeRtt(grttQuantized);
|
||||
DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new grtt: %lf sec\n",
|
||||
LocalNodeId(), Id(), grtt_estimate);
|
||||
activity_timer.SetInterval(grtt_estimate);
|
||||
activity_timer.Reset();
|
||||
LocalNodeId(), GetId(), grtt_estimate);
|
||||
activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
|
||||
if (activity_timer.IsActive()) activity_timer.Reschedule();
|
||||
}
|
||||
UINT8 gsizeQuantized = cmd.GetGroupSize();
|
||||
if (gsizeQuantized != gsize_quantized)
|
||||
|
|
@ -179,8 +188,9 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
gsize_quantized = gsizeQuantized;
|
||||
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
|
||||
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();
|
||||
switch (flavor)
|
||||
|
|
@ -255,8 +265,8 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
{
|
||||
// Respond immediately
|
||||
if (cc_timer.IsActive()) cc_timer.Deactivate();
|
||||
cc_timer.ResetRepeats();
|
||||
OnCCTimeout();
|
||||
cc_timer.ResetRepeat();
|
||||
OnCCTimeout(cc_timer);
|
||||
}
|
||||
else if (!cc_timer.IsActive())
|
||||
{
|
||||
|
|
@ -292,7 +302,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
cc_timer.SetInterval(backoffTime);
|
||||
DMSG(4, "NormServerNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
|
||||
LocalNodeId(), backoffTime);
|
||||
session->InstallTimer(&cc_timer);
|
||||
session->ActivateTimer(cc_timer);
|
||||
}
|
||||
} // end if (CC_RATE == ext.GetType())
|
||||
} // end while (GetNextExtension())
|
||||
|
|
@ -316,7 +326,8 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
{
|
||||
const NormCmdRepairAdvMsg& repairAdv = (const NormCmdRepairAdvMsg&)cmd;
|
||||
// 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;
|
||||
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(),
|
||||
repairAdv.GetRepairContentLength());
|
||||
|
|
@ -345,7 +356,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
|
||||
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))
|
||||
{
|
||||
// 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();
|
||||
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
|
||||
session->InstallTimer(&cc_timer);
|
||||
session->ActivateTimer(cc_timer);
|
||||
cc_timer.DecrementRepeatCount();
|
||||
}
|
||||
}
|
||||
|
|
@ -395,7 +406,7 @@ void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
|
|||
void NormServerNode::HandleAckMessage(const NormAckMsg& ack)
|
||||
{
|
||||
// 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;
|
||||
while (ack.GetNextExtension(ext))
|
||||
|
|
@ -412,7 +423,7 @@ void NormServerNode::HandleAckMessage(const NormAckMsg& ack)
|
|||
void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
|
||||
{
|
||||
// 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;
|
||||
while (nack.GetNextExtension(ext))
|
||||
|
|
@ -425,7 +436,7 @@ void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
|
|||
}
|
||||
}
|
||||
// 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());
|
||||
} // end NormServerNode::HandleNackMessage()
|
||||
|
||||
|
|
@ -441,7 +452,7 @@ void NormServerNode::HandleRepairContent(const char* buffer, UINT16 bufferLen)
|
|||
NormObjectId prevObjectId;
|
||||
NormObject* object = NULL;
|
||||
bool freshBlock = true;
|
||||
NormBlockId prevBlockId;
|
||||
NormBlockId prevBlockId = 0;
|
||||
NormBlock* block = NULL;
|
||||
while ((requestLength = req.Unpack(buffer, bufferLen)))
|
||||
{
|
||||
|
|
@ -670,9 +681,9 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
grtt_quantized = grttQuantized;
|
||||
grtt_estimate = NormUnquantizeRtt(grttQuantized);
|
||||
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new grtt: %lf sec\n",
|
||||
LocalNodeId(), Id(), grtt_estimate);
|
||||
activity_timer.SetInterval(grtt_estimate);
|
||||
activity_timer.Reset();
|
||||
LocalNodeId(), GetId(), grtt_estimate);
|
||||
activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
|
||||
if (activity_timer.IsActive()) activity_timer.Reschedule();
|
||||
}
|
||||
UINT8 gsizeQuantized = msg.GetGroupSize();
|
||||
if (gsizeQuantized != gsize_quantized)
|
||||
|
|
@ -680,8 +691,9 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
gsize_quantized = gsizeQuantized;
|
||||
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
|
||||
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())
|
||||
|
|
@ -689,7 +701,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
if (msg.GetSessionId() != session_id)
|
||||
{
|
||||
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu server>%lu sessionId change - resyncing.\n",
|
||||
LocalNodeId(), Id());
|
||||
LocalNodeId(), GetId());
|
||||
Close();
|
||||
resync_count++;
|
||||
}
|
||||
|
|
@ -711,7 +723,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
fti.GetFecNumParity()))
|
||||
{
|
||||
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu open error\n",
|
||||
LocalNodeId(), Id());
|
||||
LocalNodeId(), GetId());
|
||||
// (TBD) notify app of error ??
|
||||
return;
|
||||
}
|
||||
|
|
@ -721,7 +733,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
if (!IsOpen())
|
||||
{
|
||||
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu - no FTI provided!\n",
|
||||
LocalNodeId(), Id());
|
||||
LocalNodeId(), GetId());
|
||||
// (TBD) notify app of error ??
|
||||
return;
|
||||
}
|
||||
|
|
@ -770,7 +782,8 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
switch (status)
|
||||
{
|
||||
case OBJ_PENDING:
|
||||
if ((obj = rx_table.Find(objectId))) break;
|
||||
if ((obj = rx_table.Find(objectId)))
|
||||
break;
|
||||
case OBJ_NEW:
|
||||
{
|
||||
if (msg.FlagIsSet(NormObjectMsg::FLAG_STREAM))
|
||||
|
|
@ -816,7 +829,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
((NormStreamObject*)obj)->StreamUpdateStatus(blockId);
|
||||
rx_table.Insert(obj);
|
||||
DMSG(8, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new obj>%hu\n",
|
||||
LocalNodeId(), Id(), (UINT16)objectId);
|
||||
LocalNodeId(), GetId(), (UINT16)objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -835,7 +848,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
if (obj && !obj->IsOpen())
|
||||
{
|
||||
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);
|
||||
obj = NULL;
|
||||
}
|
||||
|
|
@ -855,7 +868,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
obj->HandleObjectMessage(msg, msgType, blockId, segmentId);
|
||||
if (!obj->IsPending())
|
||||
{
|
||||
|
||||
// Reliable reception of this object has completed
|
||||
if (NormObject::FILE == obj->GetType())
|
||||
#ifdef SIMULATE
|
||||
((NormSimObject*)obj)->Close();
|
||||
|
|
@ -871,7 +884,6 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
RepairCheck(NormObject::TO_BLOCK, objectId, blockId, segmentId);
|
||||
} // end NormServerNode::HandleObjectMessage()
|
||||
|
||||
|
|
@ -897,8 +909,8 @@ void NormServerNode::Sync(NormObjectId objectId)
|
|||
{
|
||||
if (rx_pending_mask.IsSet())
|
||||
{
|
||||
NormObjectId firstSet = NormObjectId(rx_pending_mask.FirstSet());
|
||||
if ((objectId > NormObjectId(rx_pending_mask.LastSet())) ||
|
||||
NormObjectId firstSet = NormObjectId((UINT16)rx_pending_mask.FirstSet());
|
||||
if ((objectId > NormObjectId((UINT16)rx_pending_mask.LastSet())) ||
|
||||
((next_id - objectId) > 256))
|
||||
{
|
||||
NormObject* obj;
|
||||
|
|
@ -949,7 +961,7 @@ NormServerNode::ObjectStatus NormServerNode::UpdateSyncStatus(const NormObjectId
|
|||
// or revert to fresh sync if sync is totally lost,
|
||||
// otherwise SQUELCH process will get things in order
|
||||
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu re-syncing to server>%lu...\n",
|
||||
LocalNodeId(), Id());
|
||||
LocalNodeId(), GetId());
|
||||
Sync(objectId);
|
||||
resync_count++;
|
||||
status = OBJ_NEW;
|
||||
|
|
@ -975,7 +987,7 @@ void NormServerNode::SetPending(NormObjectId objectId)
|
|||
rx_pending_mask.SetBits(next_id, objectId - next_id + 1);
|
||||
next_id = objectId + 1;
|
||||
// This prevents the "sync_id" from getting stale
|
||||
sync_id = rx_pending_mask.FirstSet();
|
||||
sync_id = (UINT16)rx_pending_mask.FirstSet();
|
||||
}
|
||||
} // end NormServerNode::SetPending()
|
||||
|
||||
|
|
@ -1024,7 +1036,7 @@ NormServerNode::ObjectStatus NormServerNode::GetObjectStatus(const NormObjectId&
|
|||
else
|
||||
{
|
||||
NormObjectId delta = objectId - next_id + 1;
|
||||
if (delta > NormObjectId(rx_pending_mask.Size()))
|
||||
if (delta > NormObjectId((UINT16)rx_pending_mask.Size()))
|
||||
{
|
||||
return OBJ_INVALID;
|
||||
}
|
||||
|
|
@ -1056,8 +1068,8 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
|||
if (rx_pending_mask.IsSet())
|
||||
{
|
||||
if (rx_repair_mask.IsSet()) rx_repair_mask.Clear();
|
||||
NormObjectId nextId = rx_pending_mask.FirstSet();
|
||||
NormObjectId lastId = rx_pending_mask.LastSet();
|
||||
NormObjectId nextId = (UINT16)rx_pending_mask.FirstSet();
|
||||
NormObjectId lastId = (UINT16)rx_pending_mask.LastSet();
|
||||
if (objectId < lastId) lastId = objectId;
|
||||
while (nextId <= lastId)
|
||||
{
|
||||
|
|
@ -1077,7 +1089,7 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
|||
startTimer = true;
|
||||
}
|
||||
nextId++;
|
||||
nextId = rx_pending_mask.NextSet(nextId);
|
||||
nextId = (UINT16)rx_pending_mask.NextSet(nextId);
|
||||
}
|
||||
current_object_id = objectId;
|
||||
if (startTimer)
|
||||
|
|
@ -1090,11 +1102,11 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
|||
repair_timer.SetInterval(backoffInterval);
|
||||
DMSG(3, "NormServerNode::RepairCheck() node>%lu begin NACK back-off: %lf sec)...\n",
|
||||
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
|
||||
// Trim server current transmit position reference
|
||||
|
|
@ -1115,7 +1127,7 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
|||
if (rewindDetected)
|
||||
{
|
||||
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());
|
||||
|
||||
RepairCheck(checkLevel, objectId, blockId, segmentId);
|
||||
|
|
@ -1125,10 +1137,10 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
|
|||
|
||||
// When repair timer fires, possibly build a NACK
|
||||
// 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
|
||||
DMSG(4, "NormServerNode::OnRepairTimeout() node>%lu end NACK hold-off ...\n",
|
||||
|
|
@ -1143,8 +1155,8 @@ bool NormServerNode::OnRepairTimeout()
|
|||
if (rx_pending_mask.IsSet())
|
||||
{
|
||||
bool repairPending = false;
|
||||
NormObjectId nextId = rx_pending_mask.FirstSet();
|
||||
NormObjectId lastId = rx_pending_mask.LastSet();
|
||||
NormObjectId nextId = (UINT16)rx_pending_mask.FirstSet();
|
||||
NormObjectId lastId = (UINT16)rx_pending_mask.LastSet();
|
||||
if (current_object_id < lastId) lastId = current_object_id;
|
||||
while (nextId <= lastId)
|
||||
{
|
||||
|
|
@ -1158,7 +1170,7 @@ bool NormServerNode::OnRepairTimeout()
|
|||
}
|
||||
}
|
||||
nextId++;
|
||||
nextId = rx_pending_mask.NextSet(nextId);
|
||||
nextId = (UINT16)rx_pending_mask.NextSet(nextId);
|
||||
} // end while (nextId <= current_block_id)
|
||||
if (repairPending)
|
||||
{
|
||||
|
|
@ -1208,7 +1220,7 @@ bool NormServerNode::OnRepairTimeout()
|
|||
{
|
||||
cc_timer.Deactivate();
|
||||
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
|
||||
session->InstallTimer(&cc_timer);
|
||||
session->ActivateTimer(cc_timer);
|
||||
cc_timer.DecrementRepeatCount();
|
||||
}
|
||||
}
|
||||
|
|
@ -1217,8 +1229,8 @@ bool NormServerNode::OnRepairTimeout()
|
|||
NormObjectId prevId;
|
||||
UINT16 reqCount = 0;
|
||||
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
|
||||
nextId = rx_pending_mask.FirstSet();
|
||||
lastId = rx_pending_mask.LastSet();
|
||||
nextId = (UINT16)rx_pending_mask.FirstSet();
|
||||
lastId = (UINT16)rx_pending_mask.LastSet();
|
||||
if (max_pending_object < lastId) lastId = max_pending_object;
|
||||
lastId++; // force loop to fully flush nack building.
|
||||
while ((nextId <= lastId) || (reqCount > 0))
|
||||
|
|
@ -1298,12 +1310,12 @@ bool NormServerNode::OnRepairTimeout()
|
|||
}
|
||||
nextId++;
|
||||
if (nextId <= lastId)
|
||||
nextId = rx_pending_mask.NextSet(nextId);
|
||||
nextId = (UINT16)rx_pending_mask.NextSet(nextId);
|
||||
} // end while(nextId <= lastId)
|
||||
if (NormRepairRequest::INVALID != prevForm)
|
||||
nack->PackRepairRequest(req); // (TBD) error check
|
||||
// Queue NACK for transmission
|
||||
nack->SetServerId(Id());
|
||||
nack->SetServerId(GetId());
|
||||
nack->SetSessionId(session_id);
|
||||
// GRTT response is deferred until transmit time
|
||||
|
||||
|
|
@ -1382,29 +1394,30 @@ void NormServerNode::Activate()
|
|||
{
|
||||
if (activity_timer.IsActive())
|
||||
{
|
||||
activity_timer.ResetRepeats();
|
||||
activity_timer.ResetRepeat();
|
||||
}
|
||||
else
|
||||
{
|
||||
activity_timer.SetInterval(grtt_estimate);
|
||||
session->InstallTimer(&activity_timer);
|
||||
activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
|
||||
session->ActivateTimer(activity_timer);
|
||||
}
|
||||
} // 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",
|
||||
LocalNodeId(), Id());
|
||||
LocalNodeId(), GetId());
|
||||
struct timeval currentTime;
|
||||
::GetSystemTime(¤tTime);
|
||||
::ProtoSystemTime(currentTime);
|
||||
UpdateRecvRate(currentTime, 0);
|
||||
}
|
||||
if (!activity_timer.RepeatCount())
|
||||
if (0 == activity_timer.GetRepeatCount())
|
||||
{
|
||||
DMSG(0, "NormServerNode::OnActivityTimeout() node>%lu server>%lu gone inactive?\n",
|
||||
LocalNodeId(), Id());
|
||||
LocalNodeId(), GetId());
|
||||
Close();
|
||||
}
|
||||
return true;
|
||||
} // end NormServerNode::OnActivityTimeout()
|
||||
|
|
@ -1427,10 +1440,10 @@ bool NormServerNode::UpdateLossEstimate(const struct timeval& currentTime,
|
|||
return result;
|
||||
}
|
||||
|
||||
bool NormServerNode::OnCCTimeout()
|
||||
bool NormServerNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
// Build and queue ACK()
|
||||
switch (cc_timer.RepeatCount())
|
||||
switch (cc_timer.GetRepeatCount())
|
||||
{
|
||||
case 0:
|
||||
// "hold-off" time has ended
|
||||
|
|
@ -1448,7 +1461,7 @@ bool NormServerNode::OnCCTimeout()
|
|||
return false;
|
||||
}
|
||||
ack->Init();
|
||||
ack->SetServerId(Id());
|
||||
ack->SetServerId(GetId());
|
||||
ack->SetSessionId(session_id);
|
||||
ack->SetAckType(NormAck::CC);
|
||||
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;
|
||||
while(x && (x->id != nodeId))
|
||||
|
|
@ -1854,7 +1867,8 @@ double NormLossEstimator::LossFraction()
|
|||
double s0 = 0.0;
|
||||
const double* wptr = weight;
|
||||
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;
|
||||
s0 += *wptr * *h++;
|
||||
|
|
@ -1866,7 +1880,7 @@ double NormLossEstimator::LossFraction()
|
|||
double s1 = 0.0;
|
||||
wptr = weight;
|
||||
h = history + 1;
|
||||
for (unsigned int i = 0; i < DEPTH; i++)
|
||||
for (i = 0; i < DEPTH; i++)
|
||||
{
|
||||
if (0 == *h) break;
|
||||
s1 += *wptr * *h++; // ave loss interval w/out current interval
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
#include "normMessage.h"
|
||||
#include "normObject.h"
|
||||
#include "normEncoder.h"
|
||||
#include "protocolTimer.h"
|
||||
#include "protokit.h"
|
||||
|
||||
class NormNode
|
||||
{
|
||||
friend class NormNodeTree;
|
||||
|
|
@ -16,28 +17,22 @@ class NormNode
|
|||
NormNode(class NormSession* theSession, NormNodeId nodeId);
|
||||
virtual ~NormNode();
|
||||
|
||||
void SetAddress(const NetworkAddress& address) {addr = address;}
|
||||
const NetworkAddress& GetAddress() const {return addr;}
|
||||
|
||||
const NormNodeId& Id() const {return id;}
|
||||
const ProtoAddress& GetAddress() const {return addr;}
|
||||
void SetAddress(const ProtoAddress& address) {addr = address;}
|
||||
const NormNodeId& GetId() const {return id;}
|
||||
void SetId(const NormNodeId& nodeId) {id = nodeId;}
|
||||
inline const NormNodeId& LocalNodeId() const;
|
||||
|
||||
void SetId(const NormNodeId& nodeId) {id = nodeId;}
|
||||
|
||||
protected:
|
||||
class NormSession* session;
|
||||
class NormSession* session;
|
||||
|
||||
private:
|
||||
NormNodeId id;
|
||||
NetworkAddress addr;
|
||||
|
||||
NormNode* parent;
|
||||
NormNode* right;
|
||||
NormNode* left;
|
||||
|
||||
//NormNode* prev;
|
||||
//NormNode* next;
|
||||
|
||||
NormNodeId id;
|
||||
ProtoAddress addr;
|
||||
// We keep NormNodes in a binary tree
|
||||
NormNode* parent;
|
||||
NormNode* right;
|
||||
NormNode* left;
|
||||
}; // end class NormNode
|
||||
|
||||
// Weighted-history loss event estimator
|
||||
|
|
@ -156,7 +151,7 @@ class NormCCNode : public NormNode
|
|||
double GetRtt() const {return rtt;}
|
||||
double GetLoss() const {return loss;}
|
||||
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 SetClrStatus(bool state) {is_clr = state;}
|
||||
|
|
@ -169,7 +164,7 @@ class NormCCNode : public NormNode
|
|||
}
|
||||
void SetLoss(double value) {loss = value;}
|
||||
void SetRate(double value) {rate = value;}
|
||||
void SetCCSequence(UINT8 value) {cc_sequence = value;}
|
||||
void SetCCSequence(UINT16 value) {cc_sequence = value;}
|
||||
|
||||
private:
|
||||
bool is_clr; // true if worst path representative
|
||||
|
|
@ -179,7 +174,7 @@ class NormCCNode : public NormNode
|
|||
double rtt; // in seconds
|
||||
double loss; // loss fraction
|
||||
double rate; // in bytes per second
|
||||
UINT8 cc_sequence;
|
||||
UINT16 cc_sequence;
|
||||
}; // end class NormCCNode
|
||||
|
||||
class NormServerNode : public NormNode
|
||||
|
|
@ -275,9 +270,9 @@ class NormServerNode : public NormNode
|
|||
NormBlockId blockId,
|
||||
NormSegmentId segmentId);
|
||||
|
||||
bool OnActivityTimeout();
|
||||
bool OnRepairTimeout();
|
||||
bool OnCCTimeout();
|
||||
bool OnActivityTimeout(ProtoTimer& theTimer);
|
||||
bool OnRepairTimeout(ProtoTimer& theTimer);
|
||||
bool OnCCTimeout(ProtoTimer& theTimer);
|
||||
void HandleRepairContent(const char* buffer, UINT16 bufferLen);
|
||||
|
||||
UINT16 session_id;
|
||||
|
|
@ -298,25 +293,26 @@ class NormServerNode : public NormNode
|
|||
NormDecoder decoder;
|
||||
UINT16* erasure_loc;
|
||||
|
||||
ProtocolTimer activity_timer;
|
||||
ProtocolTimer repair_timer;
|
||||
ProtoTimer activity_timer;
|
||||
ProtoTimer repair_timer;
|
||||
NormObjectId current_object_id; // index for suppression
|
||||
NormObjectId max_pending_object; // index for NACK construction
|
||||
|
||||
// Remote server grtt measurement state
|
||||
double grtt_estimate;
|
||||
UINT8 grtt_quantized;
|
||||
struct timeval grtt_send_time;
|
||||
struct timeval grtt_recv_time;
|
||||
double gsize_estimate;
|
||||
UINT8 gsize_quantized;
|
||||
double backoff_factor;
|
||||
|
||||
// Congestion control state
|
||||
// Remote server congestion control state
|
||||
NormLossEstimator2 loss_estimator;
|
||||
//NormLossEstimator loss_estimator;
|
||||
UINT8 cc_sequence;
|
||||
UINT16 cc_sequence;
|
||||
bool cc_enable;
|
||||
double cc_rate; // ccRate at start of cc_timer
|
||||
ProtocolTimer cc_timer;
|
||||
double cc_rate; // ccRate at start of cc_timer
|
||||
ProtoTimer cc_timer;
|
||||
double rtt_estimate;
|
||||
UINT8 rtt_quantized;
|
||||
bool rtt_confirmed;
|
||||
|
|
@ -330,13 +326,13 @@ class NormServerNode : public NormNode
|
|||
double nominal_packet_size;
|
||||
|
||||
// For statistics tracking
|
||||
unsigned long recv_total; // total recvd accumulator
|
||||
unsigned long recv_goodput; // goodput recvd accumulator
|
||||
unsigned long recv_total; // total recvd accumulator
|
||||
unsigned long recv_goodput; // goodput recvd accumulator
|
||||
unsigned long resync_count;
|
||||
unsigned long nack_count;
|
||||
unsigned long suppress_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
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
|||
if (server)
|
||||
{
|
||||
segmentSize = server->SegmentSize();
|
||||
numData = server->BlockSize();
|
||||
numParity = server->NumParity();
|
||||
numData = server->BlockSize(); // max source symbols per FEC block
|
||||
numParity = server->NumParity(); // max parity symbols per FEC block
|
||||
if (infoLen > 0)
|
||||
{
|
||||
pending_info = true;
|
||||
|
|
@ -65,8 +65,8 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
|||
else
|
||||
{
|
||||
segmentSize = session->ServerSegmentSize();
|
||||
numData = session->ServerBlockSize();
|
||||
numParity = session->ServerNumParity();
|
||||
numData = session->ServerBlockSize(); // max source symbols per FEC block
|
||||
numParity = session->ServerNumParity(); // max parity symbols per FEC block
|
||||
if (infoPtr)
|
||||
{
|
||||
if (info) delete []info;
|
||||
|
|
@ -88,11 +88,16 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure object size and block/segment sizes are compatible
|
||||
NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData);
|
||||
NormObjectSize numBlocks = objectSize / blockSize;
|
||||
// Compute number of segments and coding blocks for the object
|
||||
// (Note NormObjectSize divide operator always rounds _up_)
|
||||
NormObjectSize numSegments = objectSize / NormObjectSize(segmentSize);
|
||||
NormObjectSize numBlocks = numSegments / NormObjectSize(numData);
|
||||
ASSERT(0 == numBlocks.MSB());
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (!block_buffer.Init(numBlocks.LSB()))
|
||||
{
|
||||
DMSG(0, "NormObject::Open() init block_buffer error\n");
|
||||
|
|
@ -119,28 +124,44 @@ bool NormObject::Open(const NormObjectSize& objectSize,
|
|||
}
|
||||
repair_mask.Clear();
|
||||
|
||||
|
||||
if (STREAM == type)
|
||||
{
|
||||
last_block_id = 0; // not applicable for STREAM
|
||||
last_block_size = numData; // assumed for STREAM
|
||||
small_block_size = large_block_size = numData;
|
||||
small_block_count = large_block_count = numBlocks.LSB();
|
||||
final_segment_size = segmentSize;
|
||||
NormStreamObject* stream = static_cast<NormStreamObject*>(this);
|
||||
stream->StreamResync(numBlocks.LSB());
|
||||
}
|
||||
else
|
||||
{
|
||||
last_block_id = numBlocks.LSB() - 1;
|
||||
NormObjectSize lastBlockBytes = NormObjectSize(last_block_id) * blockSize;
|
||||
lastBlockBytes = objectSize - lastBlockBytes;
|
||||
NormObjectSize lastBlockSize = lastBlockBytes / NormObjectSize(segmentSize);
|
||||
ASSERT(!lastBlockSize.MSB());
|
||||
ASSERT(lastBlockSize.LSB() <= numData);
|
||||
last_block_size = lastBlockSize.LSB();
|
||||
NormObjectSize lastSegmentSize =
|
||||
NormObjectSize(0,last_block_size-1) * NormObjectSize(segmentSize);
|
||||
lastSegmentSize = lastBlockBytes - lastSegmentSize;
|
||||
ASSERT(!lastSegmentSize.MSB());
|
||||
ASSERT(lastSegmentSize.LSB() <= segmentSize);
|
||||
last_segment_size = lastSegmentSize.LSB();
|
||||
// Compute FEC block structure per NORM Protocol Spec Section 5.1.1
|
||||
// (Note NormObjectSize divide operator always rounds _up_)
|
||||
NormObjectSize largeBlockSize = numSegments / numBlocks;
|
||||
ASSERT(0 == largeBlockSize.MSB());
|
||||
large_block_size = largeBlockSize.LSB();
|
||||
if (numSegments == (numBlocks*largeBlockSize))
|
||||
{
|
||||
small_block_size = large_block_size;
|
||||
small_block_count = numBlocks.LSB();
|
||||
large_block_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
|
@ -233,7 +254,7 @@ bool NormObject::TxReset(NormBlockId firstBlock)
|
|||
NormBlockId blockId = block->Id();
|
||||
if (blockId >= firstBlock)
|
||||
{
|
||||
increasedRepair |= block->TxReset(BlockSize(blockId),
|
||||
increasedRepair |= block->TxReset(GetBlockSize(blockId),
|
||||
nparity,
|
||||
session->ServerAutoParity(),
|
||||
segment_size);
|
||||
|
|
@ -255,7 +276,7 @@ bool NormObject::TxResetBlocks(NormBlockId nextId, NormBlockId lastId)
|
|||
}
|
||||
NormBlock* block = block_buffer.Find(nextId);
|
||||
if (block)
|
||||
increasedRepair |= block->TxReset(BlockSize(block->Id()), nparity, autoParity, segment_size);
|
||||
increasedRepair |= block->TxReset(GetBlockSize(block->Id()), nparity, autoParity, segment_size);
|
||||
nextId++;
|
||||
}
|
||||
return increasedRepair;
|
||||
|
|
@ -286,7 +307,7 @@ bool NormObject::ActivateRepairs()
|
|||
while (nextId <= lastId)
|
||||
{
|
||||
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
|
||||
if (!pending_mask.Set(nextId))
|
||||
DMSG(0, "NormObject::ActivateRepairs() pending_mask.Set(%lu) error!\n",
|
||||
|
|
@ -526,12 +547,15 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
|
|||
if (blockId > max_pending_block)
|
||||
{
|
||||
max_pending_block = blockId;
|
||||
max_pending_segment = BlockSize(blockId);
|
||||
max_pending_segment = GetBlockSize(blockId);
|
||||
}
|
||||
break;
|
||||
case THRU_OBJECT:
|
||||
if (!IsStream()) max_pending_block = last_block_id;
|
||||
max_pending_segment = BlockSize(max_pending_block);
|
||||
if (!IsStream())
|
||||
max_pending_block = final_block_id;
|
||||
else if (blockId > max_pending_block)
|
||||
max_pending_block = blockId;
|
||||
max_pending_segment = GetBlockSize(max_pending_block);
|
||||
default:
|
||||
break;
|
||||
} // end switch (level)
|
||||
|
|
@ -568,7 +592,7 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
|
|||
if (blockId < current_block_id)
|
||||
{
|
||||
current_block_id = blockId;
|
||||
next_segment_id = BlockSize(blockId);
|
||||
next_segment_id = GetBlockSize(blockId);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -633,14 +657,14 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
|
|||
break;
|
||||
case THRU_BLOCK:
|
||||
current_block_id = blockId;
|
||||
next_segment_id = BlockSize(blockId);
|
||||
next_segment_id = GetBlockSize(blockId);
|
||||
break;
|
||||
case THRU_OBJECT:
|
||||
if (IsStream())
|
||||
current_block_id = max_pending_block;
|
||||
else
|
||||
current_block_id = last_block_id;
|
||||
next_segment_id = BlockSize(current_block_id);
|
||||
current_block_id = final_block_id;
|
||||
next_segment_id = GetBlockSize(current_block_id);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -665,7 +689,7 @@ bool NormObject::IsRepairPending(bool flush)
|
|||
if (block)
|
||||
{
|
||||
bool isPending;
|
||||
UINT16 numData = BlockSize(nextId);
|
||||
UINT16 numData = GetBlockSize(nextId);
|
||||
if (flush || (nextId < lastId))
|
||||
{
|
||||
isPending = block->IsRepairPending(numData, nparity);
|
||||
|
|
@ -788,7 +812,7 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
|
|||
} // end if/else (!blockPending && reqCount && (reqCount == (nextId - prevId)))
|
||||
if (blockPending)
|
||||
{
|
||||
UINT16 numData = BlockSize(nextId);
|
||||
UINT16 numData = GetBlockSize(nextId);
|
||||
if (NormRepairRequest::INVALID != prevForm)
|
||||
nack.PackRepairRequest(req); // (TBD) error check
|
||||
reqCount = 0;
|
||||
|
|
@ -846,7 +870,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
{
|
||||
info_len = segment_size;
|
||||
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);
|
||||
pending_info = false;
|
||||
|
|
@ -857,7 +881,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
// (TBD) Verify info hasn't changed?
|
||||
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||
"received duplicate info ...\n", LocalNodeId(),
|
||||
server->Id(), (UINT16)id);
|
||||
server->GetId(), (UINT16)id);
|
||||
}
|
||||
}
|
||||
else // NORM_MSG_DATA
|
||||
|
|
@ -870,7 +894,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
if (!stream->StreamUpdateStatus(blockId))
|
||||
{
|
||||
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);
|
||||
// ??? 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))
|
||||
{
|
||||
NormBlock* block = block_buffer.Find(blockId);
|
||||
|
|
@ -907,7 +931,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
if (!(block = server->GetFreeBlock(id, blockId)))
|
||||
{
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
|
@ -921,7 +945,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
if (!segment)
|
||||
{
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
|
@ -929,7 +953,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
if (segmentLen > segment_size)
|
||||
{
|
||||
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);
|
||||
server->PutFreeSegment(segment);
|
||||
return;
|
||||
|
|
@ -975,7 +999,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
// Decode (if pending_mask.FirstSet() < numData)
|
||||
// and write any decoded data segments to object
|
||||
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 nextErasure = block->FirstPending();
|
||||
UINT16 erasureCount = 0;
|
||||
|
|
@ -990,7 +1014,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
if (!(segment = server->GetFreeSegment(id, blockId)))
|
||||
{
|
||||
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);
|
||||
// (TBD) Dump the block ...???
|
||||
return;
|
||||
|
|
@ -1040,14 +1064,14 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
|
|||
{
|
||||
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||
"received duplicate segment ...\n", LocalNodeId(),
|
||||
server->Id(), (UINT16)id);
|
||||
server->GetId(), (UINT16)id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
|
||||
"received duplicate block message ...\n", LocalNodeId(),
|
||||
server->Id(), (UINT16)id);
|
||||
server->GetId(), (UINT16)id);
|
||||
} // end if/else pending_mask.Test(blockId)
|
||||
} // end if/else (NORM_MSG_INFO)
|
||||
} // end NormObject::HandleObjectMessage()
|
||||
|
|
@ -1183,7 +1207,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
|
|||
NormDataMsg* data = (NormDataMsg*)msg;
|
||||
|
||||
NormBlockId blockId = pending_mask.FirstSet();
|
||||
UINT16 numData = BlockSize(blockId);
|
||||
UINT16 numData = GetBlockSize(blockId);
|
||||
NormBlock* block = block_buffer.Find(blockId);
|
||||
if (!block)
|
||||
{
|
||||
|
|
@ -1345,7 +1369,7 @@ void NormStreamObject::StreamAdvance()
|
|||
bool NormObject::CalculateBlockParity(NormBlock* block)
|
||||
{
|
||||
char buffer[NormMsg::MAX_SIZE];
|
||||
UINT16 numData = BlockSize(block->Id());
|
||||
UINT16 numData = GetBlockSize(block->Id());
|
||||
for (UINT16 i = 0; i < numData; i++)
|
||||
{
|
||||
if (ReadSegment(block->Id(), i, buffer))
|
||||
|
|
@ -1369,7 +1393,7 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
|
|||
NormBlock* block = session->ServerGetFreeBlock(id, blockId);
|
||||
if (block)
|
||||
{
|
||||
UINT16 numData = BlockSize(blockId);
|
||||
UINT16 numData = GetBlockSize(blockId);
|
||||
// Init block parameters
|
||||
block->TxRecover(blockId, numData, nparity);
|
||||
// Fill block with zero initialized parity segments
|
||||
|
|
@ -1427,7 +1451,8 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
|
|||
NormFileObject::NormFileObject(class NormSession* theSession,
|
||||
class NormServerNode* theServer,
|
||||
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';
|
||||
}
|
||||
|
|
@ -1462,15 +1487,15 @@ bool NormFileObject::Open(const char* thePath,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
block_size = NormObjectSize(server->BlockSize()) *
|
||||
NormObjectSize(server->SegmentSize());
|
||||
//block_size = NormObjectSize(server->BlockSize()) *
|
||||
// NormObjectSize(server->SegmentSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're sending this file
|
||||
if (file.Open(thePath, O_RDONLY))
|
||||
{
|
||||
unsigned long size = file.GetSize();
|
||||
UINT32 size = file.GetSize();
|
||||
if (size)
|
||||
{
|
||||
if (!NormObject::Open(size, infoPtr, infoLen))
|
||||
|
|
@ -1486,8 +1511,8 @@ bool NormFileObject::Open(const char* thePath,
|
|||
file.Close();
|
||||
return false;
|
||||
}
|
||||
block_size = NormObjectSize(session->ServerBlockSize()) *
|
||||
NormObjectSize(session->ServerSegmentSize());
|
||||
large_block_length = NormObjectSize(large_block_size) * segment_size;
|
||||
small_block_length = NormObjectSize(small_block_size) * segment_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1526,13 +1551,20 @@ bool NormFileObject::WriteSegment(NormBlockId blockId,
|
|||
const char* buffer)
|
||||
{
|
||||
UINT16 len;
|
||||
if ((blockId == last_block_id) &&
|
||||
(segmentId == (last_block_size-1)))
|
||||
len = last_segment_size;
|
||||
if (blockId == final_block_id)
|
||||
{
|
||||
if (segmentId == (GetBlockSize(blockId)-1))
|
||||
len = final_segment_size;
|
||||
else
|
||||
len = segment_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = segment_size;
|
||||
}
|
||||
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 (!file.Seek(offset)) return false;
|
||||
|
|
@ -1548,20 +1580,39 @@ bool NormFileObject::ReadSegment(NormBlockId blockId,
|
|||
{
|
||||
// Determine segment length
|
||||
UINT16 len;
|
||||
if ((blockId == last_block_id) &&
|
||||
(segmentId == (last_block_size - 1)))
|
||||
len = last_segment_size;
|
||||
if (blockId == final_block_id)
|
||||
{
|
||||
if (segmentId == (GetBlockSize(blockId)-1))
|
||||
len = final_segment_size;
|
||||
else
|
||||
len = segment_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = segment_size;
|
||||
}
|
||||
// Determine segment offset from blockId::segmentId
|
||||
NormObjectSize segmentOffset = NormObjectSize(blockId) * block_size;
|
||||
segmentOffset = segmentOffset + (NormObjectSize(segmentId) * NormObjectSize(segment_size));
|
||||
NormObjectSize segmentOffset;
|
||||
NormObjectSize segmentSize = NormObjectSize(segment_size);
|
||||
if ((UINT32)blockId < large_block_count)
|
||||
{
|
||||
segmentOffset = large_block_length*(UINT32)blockId + segmentSize*segmentId;
|
||||
}
|
||||
else
|
||||
{
|
||||
segmentOffset = large_block_length*large_block_count;
|
||||
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
|
||||
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
|
||||
segmentSize *segmentId;
|
||||
}
|
||||
NormDataMsg::WritePayloadLength(buffer, len);
|
||||
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 (!file.Seek(offset)) return false;
|
||||
if (!file.Seek(offset))
|
||||
return false;
|
||||
}
|
||||
UINT16 nbytes = file.Read(buffer+NormDataMsg::PayloadHeaderLength(), len);
|
||||
return (len == nbytes);
|
||||
|
|
@ -1609,7 +1660,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
|
|||
}
|
||||
|
||||
NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData);
|
||||
NormObjectSize numBlocks = NormObjectSize(bufferSize) / blockSize;
|
||||
NormObjectSize numBlocks = NormObjectSize((UINT32)bufferSize) / blockSize;
|
||||
ASSERT(0 == numBlocks.MSB());
|
||||
// Buffering requires at least 2 blocks
|
||||
numBlocks = MAX(2, numBlocks.LSB());
|
||||
|
|
@ -1642,7 +1693,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
|
|||
write_offset = read_offset = NormObjectSize((UINT32)0);
|
||||
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");
|
||||
Close();
|
||||
|
|
@ -1970,8 +2021,8 @@ void NormStreamObject::Prune(NormBlockId blockId)
|
|||
// Sequential (in order) read/write routines (TBD) Add a "Seek()" method
|
||||
bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStart)
|
||||
{
|
||||
unsigned long bytesRead = 0;
|
||||
unsigned long bytesToRead = *buflen;
|
||||
unsigned int bytesRead = 0;
|
||||
unsigned int bytesToRead = *buflen;
|
||||
while (bytesToRead > 0)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
UINT16 count = len - nBytes;
|
||||
UINT16 count = (UINT16)(len - nBytes);
|
||||
UINT16 space = segment_size - index;
|
||||
count = MIN(count, space);
|
||||
#ifdef SIMULATE
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ class NormObject
|
|||
THRU_OBJECT
|
||||
};
|
||||
|
||||
void Verify() const;
|
||||
|
||||
virtual ~NormObject();
|
||||
|
||||
// Object information
|
||||
NormObject::Type GetType() const {return type;}
|
||||
const NormObjectId& Id() const {return id;}
|
||||
const NormObjectSize& Size() const {return object_size;}
|
||||
|
|
@ -60,10 +60,12 @@ class NormObject
|
|||
char* buffer) = 0;
|
||||
|
||||
// These are only valid after object is open
|
||||
NormBlockId LastBlockId() const {return last_block_id;}
|
||||
NormSegmentId LastBlockSize() const {return last_block_size;}
|
||||
NormSegmentId BlockSize(NormBlockId blockId)
|
||||
{return ((blockId == last_block_id) ? last_block_size : ndata);}
|
||||
NormBlockId GetFinalBlockId() const {return final_block_id;}
|
||||
UINT32 GetBlockSize(NormBlockId blockId)
|
||||
{
|
||||
return (((UINT32)blockId < large_block_count) ? large_block_size :
|
||||
small_block_size);
|
||||
}
|
||||
|
||||
bool IsPending(bool flush = true) const;
|
||||
bool IsRepairPending() const;
|
||||
|
|
@ -84,12 +86,12 @@ class NormObject
|
|||
{
|
||||
NormBlockId blockId = theBlock->Id();
|
||||
bool result = theBlock->TxUpdate(firstSegmentId, lastSegmentId,
|
||||
BlockSize(blockId), nparity,
|
||||
GetBlockSize(blockId), nparity,
|
||||
numErasures);
|
||||
ASSERT(result ? pending_mask.Set(blockId) : true);
|
||||
result = result ? pending_mask.Set(blockId) : false;
|
||||
return result;
|
||||
} // end NormObject::TxUpdateBlock()
|
||||
}
|
||||
bool HandleInfoRequest();
|
||||
bool HandleBlockRequest(NormBlockId nextId, NormBlockId lastId);
|
||||
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 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);
|
||||
|
||||
|
||||
|
|
@ -110,7 +112,7 @@ class NormObject
|
|||
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* StealOldestBlock(bool excludeBlock, NormBlockId excludeId = 0);
|
||||
|
||||
|
|
@ -129,7 +131,7 @@ class NormObject
|
|||
}
|
||||
|
||||
protected:
|
||||
NormObject(NormObject::Type theType,
|
||||
NormObject(Type theType,
|
||||
class NormSession* theSession,
|
||||
class NormServerNode* theServer,
|
||||
const NormObjectId& objectId);
|
||||
|
|
@ -154,17 +156,18 @@ class NormObject
|
|||
NormSegmentId next_segment_id; // for suppression
|
||||
NormBlockId max_pending_block; // for NACK construction
|
||||
NormSegmentId max_pending_segment; // for NACK construction
|
||||
NormBlockId last_block_id;
|
||||
NormSegmentId last_block_size;
|
||||
UINT16 last_segment_size;
|
||||
UINT32 large_block_count;
|
||||
UINT32 large_block_size;
|
||||
UINT32 small_block_count;
|
||||
UINT32 small_block_size;
|
||||
NormBlockId final_block_id;
|
||||
UINT16 final_segment_size;
|
||||
|
||||
char* info;
|
||||
UINT16 info_len;
|
||||
|
||||
bool accepted;
|
||||
|
||||
|
||||
|
||||
NormObject* next;
|
||||
}; // end class NormObject
|
||||
|
||||
|
|
@ -201,7 +204,8 @@ class NormFileObject : public NormObject
|
|||
private:
|
||||
char path[PATH_MAX];
|
||||
NormFile file;
|
||||
NormObjectSize block_size;
|
||||
NormObjectSize large_block_length;
|
||||
NormObjectSize small_block_length;
|
||||
}; // end class NormFileObject
|
||||
|
||||
|
||||
|
|
@ -345,14 +349,14 @@ class NormObjectTable
|
|||
private:
|
||||
NormObject* Next(NormObject* o) const {return o->next;}
|
||||
|
||||
NormObject** table;
|
||||
unsigned long hash_mask;
|
||||
unsigned long range_max; // max range of objects that can be kept
|
||||
unsigned long range; // zero if "object table" is empty
|
||||
NormObjectId range_lo;
|
||||
NormObjectId range_hi;
|
||||
unsigned long count;
|
||||
NormObjectSize size;
|
||||
NormObject** table;
|
||||
UINT16 hash_mask;
|
||||
UINT16 range_max; // max range of objects that can be kept
|
||||
UINT16 range; // zero if "object table" is empty
|
||||
NormObjectId range_lo;
|
||||
NormObjectId range_hi;
|
||||
UINT16 count;
|
||||
NormObjectSize size;
|
||||
}; // end class NormObjectTable
|
||||
|
||||
#endif // _NORM_OBJECT
|
||||
|
|
|
|||
|
|
@ -1,39 +1,66 @@
|
|||
#include "normPostProcess.h"
|
||||
#include "protoLib.h"
|
||||
#include "protoDebug.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#ifdef UNIX
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#endif // UNIX
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
NormPostProcessor::NormPostProcessor()
|
||||
: process_argv(NULL)
|
||||
#ifdef UNIX
|
||||
,process_id(0)
|
||||
#endif // UNIX
|
||||
: process_argv(NULL), process_argc(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NormPostProcessor::~NormPostProcessor()
|
||||
{
|
||||
if (IsActive()) Kill();
|
||||
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)
|
||||
{
|
||||
|
||||
// 1) Delete old command resources
|
||||
if (process_argv)
|
||||
{
|
||||
const char** arg = process_argv;
|
||||
char** arg = process_argv;
|
||||
while (*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",
|
||||
// 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",
|
||||
strerror(errno));
|
||||
|
|
@ -92,74 +119,3 @@ bool NormPostProcessor::SetCommand(const char* cmd)
|
|||
}
|
||||
return true;
|
||||
} // 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
|
||||
#define _NORM_POST_PROCESS
|
||||
|
||||
#include "protoDefs.h" // for NULL
|
||||
|
||||
class NormPostProcessor
|
||||
{
|
||||
public:
|
||||
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 ProcessFile(const char* path);
|
||||
void Kill();
|
||||
bool IsActive()
|
||||
{
|
||||
#ifdef UNIX
|
||||
return (0 != process_id);
|
||||
#endif // UNIX
|
||||
}
|
||||
void GetCommand(char* buffer, unsigned int buflen);
|
||||
|
||||
void HandleSIGCHLD();
|
||||
virtual bool ProcessFile(const char* path) = 0;
|
||||
virtual void Kill() = 0;
|
||||
virtual bool IsActive() = 0;
|
||||
virtual void OnDeath() {};
|
||||
|
||||
private:
|
||||
const char** process_argv;
|
||||
protected:
|
||||
char** process_argv;
|
||||
unsigned int process_argc;
|
||||
#ifdef UNIX
|
||||
int process_id;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
HANDLE process_handle;
|
||||
#endif
|
||||
}; // end class NormPostProcessor
|
||||
|
||||
#endif // _NORM_POST_PROCESS
|
||||
|
|
|
|||
|
|
@ -184,14 +184,14 @@ bool NormBlock::IsRepairPending(UINT16 ndata, UINT16 nparity)
|
|||
if (nparity)
|
||||
{
|
||||
UINT16 i = nparity;
|
||||
NormSegmentId nextId = pending_mask.FirstSet();
|
||||
NormSegmentId nextId = (UINT16)pending_mask.FirstSet();
|
||||
while (i--)
|
||||
{
|
||||
// (TBD) for more NACK suppression, we could skip ahead
|
||||
// if this bit is already set in repair_mask?
|
||||
repair_mask.Set(nextId); // set bit a parity can fill
|
||||
nextId++;
|
||||
nextId = pending_mask.NextSet(nextId);
|
||||
nextId = (UINT16)pending_mask.NextSet(nextId);
|
||||
}
|
||||
}
|
||||
else if (size > ndata)
|
||||
|
|
@ -390,7 +390,7 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
|
|||
NormRepairRequest req;
|
||||
req.SetFlag(NormRepairRequest::SEGMENT);
|
||||
if (repairInfo) req.SetFlag(NormRepairRequest::INFO);
|
||||
UINT16 nextId = repair_mask.FirstSet();
|
||||
UINT16 nextId = (UINT16)repair_mask.FirstSet();
|
||||
UINT16 blockSize = size;
|
||||
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
|
||||
UINT16 segmentCount = 0;
|
||||
|
|
@ -398,7 +398,7 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
|
|||
while (nextId < blockSize)
|
||||
{
|
||||
UINT16 currentId = nextId;
|
||||
nextId = repair_mask.NextSet(++nextId);
|
||||
nextId = (UINT16)repair_mask.NextSet(++nextId);
|
||||
if (!segmentCount) firstId = currentId;
|
||||
|
||||
segmentCount++;
|
||||
|
|
@ -467,19 +467,19 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
|
|||
if (erasure_count > nparity)
|
||||
{
|
||||
// Request explicit repair
|
||||
nextId = pending_mask.FirstSet();
|
||||
nextId = (UINT16)pending_mask.FirstSet();
|
||||
UINT16 i = nparity;
|
||||
// Skip nparity missing data segments
|
||||
while (i--)
|
||||
{
|
||||
nextId++;
|
||||
endId = pending_mask.NextSet(nextId);
|
||||
endId = (UINT16)pending_mask.NextSet(nextId);
|
||||
}
|
||||
endId = ndata + nparity;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextId = pending_mask.NextSet(ndata);
|
||||
nextId = (UINT16)pending_mask.NextSet(ndata);
|
||||
endId = ndata + erasure_count;
|
||||
}
|
||||
NormRepairRequest req;
|
||||
|
|
@ -492,7 +492,7 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
|
|||
while (nextId < endId)
|
||||
{
|
||||
UINT16 currentId = nextId;
|
||||
nextId = pending_mask.NextSet(++nextId);
|
||||
nextId = (UINT16)pending_mask.NextSet(++nextId);
|
||||
if (0 == segmentCount) firstId = currentId;
|
||||
segmentCount++;
|
||||
// Check for break in consecutive series or end
|
||||
|
|
|
|||
|
|
@ -157,9 +157,9 @@ class NormBlock
|
|||
UINT16 ParityCount() const {return parity_count;}
|
||||
|
||||
NormSymbolId FirstPending() const
|
||||
{return pending_mask.FirstSet();}
|
||||
{return (NormSymbolId)pending_mask.FirstSet();}
|
||||
NormSymbolId FirstRepair() const
|
||||
{return repair_mask.FirstSet();}
|
||||
{return (NormSymbolId)repair_mask.FirstSet();}
|
||||
bool SetPending(NormSymbolId s)
|
||||
{return pending_mask.Set(s);}
|
||||
bool SetPending(NormSymbolId firstId, UINT16 count)
|
||||
|
|
@ -192,7 +192,7 @@ class NormBlock
|
|||
|
||||
|
||||
NormSymbolId NextPending(NormSymbolId index) const
|
||||
{return pending_mask.NextSet(index);}
|
||||
{return ((NormSymbolId)pending_mask.NextSet(index));}
|
||||
|
||||
|
||||
bool AppendRepairRequest(NormNackMsg& nack,
|
||||
|
|
|
|||
|
|
@ -15,12 +15,14 @@ const UINT16 NormSession::DEFAULT_NDATA = 64;
|
|||
const UINT16 NormSession::DEFAULT_NPARITY = 32;
|
||||
|
||||
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),
|
||||
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(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),
|
||||
tx_cache_size_max((unsigned long)20*1024*1024),
|
||||
tx_cache_size_max((UINT32)20*1024*1024),
|
||||
flush_count(NORM_ROBUST_FACTOR+1),
|
||||
posted_tx_queue_empty(false), advertise_repairs(false),
|
||||
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),
|
||||
next(NULL)
|
||||
{
|
||||
tx_socket.Init((UdpSocketOwner*) this,
|
||||
(UdpSocketRecvHandler)&NormSession::TxSocketRecvHandler,
|
||||
sessionMgr.SocketInstaller(),
|
||||
sessionMgr.SocketInstallData());
|
||||
rx_socket.Init((UdpSocketOwner*) this,
|
||||
(UdpSocketRecvHandler)&NormSession::RxSocketRecvHandler,
|
||||
sessionMgr.SocketInstaller(),
|
||||
sessionMgr.SocketInstallData());
|
||||
tx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
||||
tx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::TxSocketRecvHandler);
|
||||
|
||||
tx_timer.Init(0.0, -1,
|
||||
(ProtocolTimerOwner *)this,
|
||||
(ProtocolTimeoutFunc)&NormSession::OnTxTimeout);
|
||||
repair_timer.Init(0.0, 1, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormSession::OnRepairTimeout);
|
||||
flush_timer.Init(0.0, 0, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormSession::OnFlushTimeout);
|
||||
probe_timer.Init(0.0, -1, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormSession::OnProbeTimeout);
|
||||
rx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
|
||||
rx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::RxSocketRecvHandler);
|
||||
|
||||
tx_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnTxTimeout);
|
||||
tx_timer.SetInterval(0.0);
|
||||
tx_timer.SetRepeat(-1);
|
||||
|
||||
repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnRepairTimeout);
|
||||
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_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
|
||||
// (It may be used to trigger transmission of report messages
|
||||
// in the future for debugging, etc
|
||||
report_timer.Init(30.0, -1, (ProtocolTimerOwner*)this,
|
||||
(ProtocolTimeoutFunc)&NormSession::OnReportTimeout);
|
||||
report_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnReportTimeout);
|
||||
report_timer.SetInterval(10.0);
|
||||
report_timer.SetRepeat(-1);
|
||||
}
|
||||
|
||||
NormSession::~NormSession()
|
||||
|
|
@ -75,13 +81,12 @@ NormSession::~NormSession()
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool NormSession::Open()
|
||||
{
|
||||
ASSERT(address.IsValid());
|
||||
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");
|
||||
return false;
|
||||
|
|
@ -89,7 +94,7 @@ bool NormSession::Open()
|
|||
}
|
||||
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");
|
||||
Close();
|
||||
|
|
@ -99,13 +104,13 @@ bool NormSession::Open()
|
|||
|
||||
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");
|
||||
Close();
|
||||
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");
|
||||
Close();
|
||||
|
|
@ -126,7 +131,7 @@ bool NormSession::Open()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
InstallTimer(&report_timer);
|
||||
ActivateTimer(report_timer);
|
||||
|
||||
return true;
|
||||
} // end NormSession::Open()
|
||||
|
|
@ -142,7 +147,7 @@ void NormSession::Close()
|
|||
if (tx_socket.IsOpen()) tx_socket.Close();
|
||||
if (rx_socket.IsOpen())
|
||||
{
|
||||
if (address.IsMulticast()) rx_socket.LeaveGroup(&address);
|
||||
if (address.IsMulticast()) rx_socket.LeaveGroup(address);
|
||||
rx_socket.Close();
|
||||
}
|
||||
} // end NormSession::Close()
|
||||
|
|
@ -226,8 +231,8 @@ bool NormSession::StartServer(unsigned long bufferSpace,
|
|||
is_server = true;
|
||||
flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor
|
||||
//probe_timer.SetInterval(0.0);
|
||||
OnProbeTimeout();
|
||||
InstallTimer(&probe_timer);
|
||||
OnProbeTimeout(probe_timer);
|
||||
ActivateTimer(probe_timer);
|
||||
return true;
|
||||
} // end NormSession::StartServer()
|
||||
|
||||
|
|
@ -274,7 +279,7 @@ void NormSession::Serve()
|
|||
// Queue next server message
|
||||
if (tx_pending_mask.IsSet())
|
||||
{
|
||||
NormObjectId objectId(tx_pending_mask.FirstSet());
|
||||
NormObjectId objectId((unsigned short)tx_pending_mask.FirstSet());
|
||||
obj = tx_table.Find(objectId);
|
||||
ASSERT(obj);
|
||||
}
|
||||
|
|
@ -293,6 +298,7 @@ void NormSession::Serve()
|
|||
|
||||
if (obj)
|
||||
{
|
||||
|
||||
NormObjectMsg* msg = (NormObjectMsg*)GetMessageFromPool();
|
||||
if (msg)
|
||||
{
|
||||
|
|
@ -300,6 +306,7 @@ void NormSession::Serve()
|
|||
{
|
||||
msg->SetDestination(address);
|
||||
msg->SetGrtt(grtt_quantized);
|
||||
msg->SetBackoffFactor((unsigned char)backoff_factor);
|
||||
msg->SetGroupSize(gsize_quantized);
|
||||
QueueMessage(msg);
|
||||
flush_count = 0;
|
||||
|
|
@ -378,8 +385,8 @@ void NormSession::ServerQueueFlush()
|
|||
else
|
||||
{
|
||||
objectId = obj->Id();
|
||||
blockId = obj->LastBlockId();
|
||||
segmentId = obj->LastBlockSize() - 1;
|
||||
blockId = obj->GetFinalBlockId();
|
||||
segmentId = obj->GetBlockSize(blockId) - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -389,7 +396,7 @@ void NormSession::ServerQueueFlush()
|
|||
{
|
||||
flush_count++;
|
||||
flush_timer.SetInterval(2*grtt_advertised);
|
||||
InstallTimer(&flush_timer);
|
||||
ActivateTimer(flush_timer);
|
||||
}
|
||||
DMSG(8, "NormSession::ServerQueueFlush() node>%lu squelch queued (flush_count:%u)...\n",
|
||||
LocalNodeId(), flush_count);
|
||||
|
|
@ -401,6 +408,7 @@ void NormSession::ServerQueueFlush()
|
|||
flush->Init();
|
||||
flush->SetDestination(address);
|
||||
flush->SetGrtt(grtt_quantized);
|
||||
flush->SetBackoffFactor((unsigned char)backoff_factor);
|
||||
flush->SetGroupSize(gsize_quantized);
|
||||
flush->SetObjectId(objectId);
|
||||
flush->SetFecBlockId(blockId);
|
||||
|
|
@ -408,7 +416,7 @@ void NormSession::ServerQueueFlush()
|
|||
QueueMessage(flush);
|
||||
flush_count++;
|
||||
flush_timer.SetInterval(2*grtt_advertised);
|
||||
InstallTimer(&flush_timer);
|
||||
ActivateTimer(flush_timer);
|
||||
DMSG(8, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n",
|
||||
LocalNodeId(), flush_count);
|
||||
}
|
||||
|
|
@ -419,7 +427,7 @@ void NormSession::ServerQueueFlush()
|
|||
}
|
||||
} // end NormSession::ServerQueueFlush()
|
||||
|
||||
bool NormSession::OnFlushTimeout()
|
||||
bool NormSession::OnFlushTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
flush_timer.Deactivate();
|
||||
Serve(); // (TBD) Change this to PromptServer() ??
|
||||
|
|
@ -432,7 +440,7 @@ void NormSession::QueueMessage(NormMsg* msg)
|
|||
/* A little test jig
|
||||
static struct timeval lastTime = {0,0};
|
||||
struct timeval currentTime;
|
||||
GetSystemTime(¤tTime);
|
||||
ProtoSystemTime(currentTime);
|
||||
if (0 != lastTime.tv_sec)
|
||||
{
|
||||
double delta = currentTime.tv_sec - lastTime.tv_sec;
|
||||
|
|
@ -445,7 +453,7 @@ void NormSession::QueueMessage(NormMsg* msg)
|
|||
if (!tx_timer.IsActive())
|
||||
{
|
||||
tx_timer.SetInterval(0.0);
|
||||
InstallTimer(&tx_timer);
|
||||
ActivateTimer(tx_timer);
|
||||
}
|
||||
message_queue.Append(msg);
|
||||
} // end NormSesssion::QueueMessage(NormMsg& msg)
|
||||
|
|
@ -682,40 +690,34 @@ char* NormSession::ServerGetFreeSegment(NormObjectId objectId,
|
|||
return segment_pool.Get();
|
||||
} // end NormSession::ServerGetFreeSegment()
|
||||
|
||||
bool NormSession::TxSocketRecvHandler(UdpSocket* /*theSocket*/)
|
||||
void NormSession::TxSocketRecvHandler(ProtoSocket& /*theSocket*/,
|
||||
ProtoSocket::Event /*theEvent*/)
|
||||
{
|
||||
NormMsg msg;
|
||||
unsigned int msgLength = NormMsg::MAX_SIZE;
|
||||
if (UDP_SOCKET_ERROR_NONE == tx_socket.RecvFrom(msg.AccessBuffer(),
|
||||
&msgLength,
|
||||
msg.AccessAddress()))
|
||||
while (tx_socket.RecvFrom(msg.AccessBuffer(),
|
||||
msgLength,
|
||||
msg.AccessAddress()))
|
||||
{
|
||||
msg.InitFromBuffer(msgLength);
|
||||
HandleReceiveMessage(msg, true);
|
||||
msgLength = NormMsg::MAX_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "NormSession::TxSocketRecvHandler() recvfrom error");
|
||||
}
|
||||
return true;
|
||||
} // end NormSession::TxSocketRecvHandler()
|
||||
|
||||
bool NormSession::RxSocketRecvHandler(UdpSocket* /*theSocket*/)
|
||||
void NormSession::RxSocketRecvHandler(ProtoSocket& /*theSocket*/,
|
||||
ProtoSocket::Event /*theEvent*/)
|
||||
{
|
||||
NormMsg msg;
|
||||
unsigned int msgLength = NormMsg::MAX_SIZE;
|
||||
if (UDP_SOCKET_ERROR_NONE == rx_socket.RecvFrom(msg.AccessBuffer(),
|
||||
&msgLength,
|
||||
msg.AccessAddress()))
|
||||
while (rx_socket.RecvFrom(msg.AccessBuffer(),
|
||||
msgLength,
|
||||
msg.AccessAddress()))
|
||||
{
|
||||
msg.InitFromBuffer(msgLength);
|
||||
HandleReceiveMessage(msg, false);
|
||||
msgLength = NormMsg::MAX_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "NormSession::RxSocketRecvHandler() recvfrom error");
|
||||
}
|
||||
return true;
|
||||
} // end NormSession::RxSocketRecvHandler()
|
||||
|
||||
void NormTrace(const struct timeval& currentTime,
|
||||
|
|
@ -759,12 +761,12 @@ void NormTrace(const struct timeval& currentTime,
|
|||
NormMsg::Type msgType = msg.GetType();
|
||||
UINT16 length = msg.GetLength();
|
||||
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);
|
||||
DMSG(0, "trace>%02d:%02d:%02d.%06lu node>%lu %s>%s ",
|
||||
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;
|
||||
switch (msgType)
|
||||
{
|
||||
|
|
@ -881,9 +883,8 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
struct timeval currentTime;
|
||||
::GetSystemTime(¤tTime);
|
||||
::ProtoSystemTime(currentTime);
|
||||
|
||||
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
|
||||
// (i.e. fewer function calls per message)
|
||||
if (theServer->IsOpen()) theServer->Activate();
|
||||
theServer->UpdateRecvRate(currentTime, msg.GetLength());
|
||||
theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
|
||||
theServer->SetAddress(msg.GetSource());
|
||||
|
||||
// for statistics only (TBD) #ifdef NORM_DEBUG
|
||||
theServer->IncrementRecvTotal(msg.GetLength());
|
||||
}
|
||||
|
|
@ -929,7 +930,7 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
|
|||
if (!tx_timer.IsActive())
|
||||
{
|
||||
tx_timer.SetInterval(0.0);
|
||||
InstallTimer(&tx_timer);
|
||||
ActivateTimer(tx_timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1083,7 +1084,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
|||
double ccRtt,
|
||||
double ccLoss,
|
||||
double ccRate,
|
||||
UINT8 ccSequence)
|
||||
UINT16 ccSequence)
|
||||
{
|
||||
// Keep track of current suppressing feedback
|
||||
// (non-CLR, lowest rate, unconfirmed RTT)
|
||||
|
|
@ -1123,14 +1124,14 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
|||
// 1) Does this response replace the active CLR?
|
||||
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();
|
||||
double savedRtt = next->GetRtt();
|
||||
double savedLoss = next->GetLoss();
|
||||
double savedRate = next->GetRate();
|
||||
UINT8 savedSequence = next->GetCCSequence();
|
||||
UINT16 savedSequence = next->GetCCSequence();
|
||||
|
||||
next->SetId(nodeId);
|
||||
next->SetClrStatus(true);
|
||||
|
|
@ -1139,7 +1140,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
|||
next->SetRate(ccRate);
|
||||
next->SetCCSequence(ccSequence);
|
||||
next->SetActive(true);
|
||||
if (next->Id() == nodeId)
|
||||
if (next->GetId() == nodeId)
|
||||
{
|
||||
// This was feedback from the current CLR
|
||||
AdjustRate(true);
|
||||
|
|
@ -1206,7 +1207,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
|||
{
|
||||
while ((next = (NormCCNode*)iterator.GetNextNode()))
|
||||
{
|
||||
if (next->Id() == nodeId)
|
||||
if (next->GetId() == nodeId)
|
||||
{
|
||||
candidate = next;
|
||||
break;
|
||||
|
|
@ -1238,7 +1239,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
|
|||
{
|
||||
bool haveRtt = (0 != (ccFlags && NormCC::RTT));
|
||||
bool replace;
|
||||
if (candidate->Id() == nodeId)
|
||||
if (candidate->GetId() == nodeId)
|
||||
replace = true;
|
||||
else if (!candidate->IsActive())
|
||||
replace = true;
|
||||
|
|
@ -1297,7 +1298,7 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
|
|||
if (!tx_timer.IsActive())
|
||||
{
|
||||
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;
|
||||
NormObject* object = NULL;
|
||||
bool freshObject = true;
|
||||
NormObjectId prevObjectId;
|
||||
NormObjectId prevObjectId = 0;
|
||||
NormBlock* block = NULL;
|
||||
bool freshBlock = true;
|
||||
NormBlockId prevBlockId;
|
||||
NormBlockId prevBlockId = 0;
|
||||
|
||||
bool startTimer = false;
|
||||
UINT16 numErasures = extra_parity;
|
||||
|
|
@ -1360,7 +1361,7 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
|||
NormBlockId txBlockIndex;
|
||||
if (tx_pending_mask.IsSet())
|
||||
{
|
||||
txObjectIndex = tx_pending_mask.FirstSet();
|
||||
txObjectIndex = NormObjectId((unsigned short)tx_pending_mask.FirstSet());
|
||||
NormObject* obj = tx_table.Find(txObjectIndex);
|
||||
ASSERT(obj);
|
||||
if (obj->IsPending())
|
||||
|
|
@ -1382,7 +1383,7 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
|||
txBlockIndex = 0;
|
||||
}
|
||||
|
||||
bool holdoff = (repair_timer.IsActive() && !repair_timer.RepeatCount());
|
||||
bool holdoff = (repair_timer.IsActive() && !repair_timer.GetRepeatCount());
|
||||
enum NormRequestLevel {SEGMENT, BLOCK, INFO, OBJECT};
|
||||
while ((requestLength = nack.UnpackRepairRequest(req, requestOffset)))
|
||||
{
|
||||
|
|
@ -1728,14 +1729,14 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
|
|||
|
||||
if (tx_timer.IsActive())
|
||||
{
|
||||
double txTimeout = tx_timer.TimeRemaining() - 1.0e-06;
|
||||
double txTimeout = tx_timer.GetTimeRemaining() - 1.0e-06;
|
||||
aggregateInterval = MAX(txTimeout, aggregateInterval);
|
||||
}
|
||||
|
||||
repair_timer.SetInterval(aggregateInterval);
|
||||
DMSG(4, "NormSession::ServerHandleNackMessage() node>%lu starting server "
|
||||
"NACK aggregation timer (%lf sec)...\n", LocalNodeId(), aggregateInterval);
|
||||
InstallTimer(&repair_timer);
|
||||
ActivateTimer(repair_timer);
|
||||
}
|
||||
} // end NormSession::ServerHandleNackMessage()
|
||||
|
||||
|
|
@ -1778,6 +1779,7 @@ bool NormSession::ServerQueueSquelch(NormObjectId objectId)
|
|||
squelch->Init();
|
||||
squelch->SetDestination(address);
|
||||
squelch->SetGrtt(grtt_quantized);
|
||||
squelch->SetBackoffFactor((unsigned char)backoff_factor);
|
||||
squelch->SetGroupSize(gsize_quantized);
|
||||
NormObject* obj = tx_table.Find(objectId);
|
||||
NormObjectTable::Iterator iterator(tx_table);
|
||||
|
|
@ -1933,9 +1935,9 @@ bool NormSession::ServerBuildRepairAdv(NormCmdRepairAdvMsg& cmd)
|
|||
return true;
|
||||
} // 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)
|
||||
DMSG(4, "NormSession::OnRepairTimeout() node>%lu server NACK aggregation time ended.\n",
|
||||
|
|
@ -1994,9 +1996,9 @@ bool 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 ...
|
||||
bool NormSession::OnTxTimeout()
|
||||
bool NormSession::OnTxTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
NormMsg* msg;
|
||||
|
||||
|
|
@ -2004,12 +2006,13 @@ bool NormSession::OnTxTimeout()
|
|||
NormCmdRepairAdvMsg adv;
|
||||
|
||||
if (advertise_repairs && (probe_proactive || (repair_timer.IsActive() &&
|
||||
repair_timer.RepeatCount())))
|
||||
repair_timer.GetRepeatCount())))
|
||||
{
|
||||
// Build a NORM_CMD(NACK_ADV) in response to
|
||||
// receipt of unicast NACK or CC update
|
||||
adv.Init();
|
||||
adv.SetGrtt(grtt_quantized);
|
||||
adv.SetBackoffFactor((unsigned char)backoff_factor);
|
||||
adv.SetGroupSize(gsize_quantized);
|
||||
adv.SetDestination(address);
|
||||
|
||||
|
|
@ -2044,11 +2047,19 @@ bool NormSession::OnTxTimeout()
|
|||
|
||||
if (msg)
|
||||
{
|
||||
SendMessage(*msg);
|
||||
if (advertise_repairs)
|
||||
advertise_repairs = false;
|
||||
if (SendMessage(*msg))
|
||||
{
|
||||
if (advertise_repairs)
|
||||
advertise_repairs = false;
|
||||
else
|
||||
ReturnMessageToPool(msg);
|
||||
}
|
||||
else
|
||||
ReturnMessageToPool(msg);
|
||||
{
|
||||
// Requeue the message for another try
|
||||
if (!advertise_repairs)
|
||||
message_queue.Prepend(msg);
|
||||
}
|
||||
return true; // reinstall tx_timer
|
||||
}
|
||||
else
|
||||
|
|
@ -2068,16 +2079,15 @@ bool NormSession::OnTxTimeout()
|
|||
else
|
||||
{
|
||||
// We have a new message as a result of serving, so send it immediately
|
||||
OnTxTimeout();
|
||||
return true;
|
||||
return OnTxTimeout(tx_timer);
|
||||
}
|
||||
}
|
||||
} // end NormSession::OnTxTimeout()
|
||||
|
||||
void NormSession::SendMessage(NormMsg& msg)
|
||||
bool NormSession::SendMessage(NormMsg& msg)
|
||||
{
|
||||
struct timeval currentTime;
|
||||
GetSystemTime(¤tTime);
|
||||
ProtoSystemTime(currentTime);
|
||||
|
||||
bool clientMsg = false;
|
||||
|
||||
|
|
@ -2134,61 +2144,65 @@ void NormSession::SendMessage(NormMsg& msg)
|
|||
msg.SetSequence(tx_sequence++);
|
||||
msg.SetSourceId(local_node_id);
|
||||
UINT16 msgSize = msg.GetLength();
|
||||
bool result = true;
|
||||
// Drop some tx messages for testing purposes
|
||||
bool drop = (UniformRand(100.0) < tx_loss_rate);
|
||||
|
||||
if (drop || (clientMsg && client_silent))
|
||||
{
|
||||
//TRACE("TX MESSAGE DROPPED! (tx_loss_rate:%lf\n", tx_loss_rate);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UDP_SOCKET_ERROR_NONE != tx_socket.SendTo(&msg.GetDestination(),
|
||||
msg.GetBuffer(),
|
||||
msgSize))
|
||||
{
|
||||
DMSG(0, "NormSession::SendMessage() sendto() error\n");
|
||||
}
|
||||
else
|
||||
if (tx_socket.SendTo(msg.GetBuffer(),
|
||||
msgSize,
|
||||
msg.GetDestination()))
|
||||
{
|
||||
// Separate send/recv tracing
|
||||
if (trace) NormTrace(currentTime, LocalNodeId(), msg, true);
|
||||
}
|
||||
// Keep track of _actual_ sent rate
|
||||
double interval;
|
||||
if (prev_update_time.tv_sec || prev_update_time.tv_usec)
|
||||
{
|
||||
interval = (double)(currentTime.tv_sec - 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);
|
||||
|
||||
// Keep track of _actual_ sent rate
|
||||
double interval;
|
||||
if (prev_update_time.tv_sec || prev_update_time.tv_usec)
|
||||
{
|
||||
interval = (double)(currentTime.tv_sec - 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);
|
||||
else
|
||||
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
|
||||
}
|
||||
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
|
||||
{
|
||||
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;
|
||||
DMSG(8, "NormSession::SendMessage() sendto() error\n");
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
|
||||
tx_timer.SetInterval(((double)msgSize) / tx_rate);
|
||||
return result;
|
||||
} // end NormSession::SendMessage()
|
||||
|
||||
bool NormSession::OnProbeTimeout()
|
||||
bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
// 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_response)
|
||||
|
|
@ -2247,6 +2261,7 @@ bool NormSession::OnProbeTimeout()
|
|||
cmd->Init();
|
||||
cmd->SetDestination(address);
|
||||
cmd->SetGrtt(grtt_quantized);
|
||||
cmd->SetBackoffFactor((unsigned char)backoff_factor);
|
||||
cmd->SetGroupSize(gsize_quantized);
|
||||
// SetSendTime() when message is being sent (in OnTxTimeout())
|
||||
cmd->SetCCSequence(cc_sequence++);
|
||||
|
|
@ -2276,7 +2291,7 @@ bool NormSession::OnProbeTimeout()
|
|||
UINT16 rateQuantized = NormQuantizeRate(next->GetRate());
|
||||
// (TBD) check result
|
||||
cmd->AppendCCNode(segment_size,
|
||||
next->Id(),
|
||||
next->GetId(),
|
||||
ccFlags,
|
||||
rttQuantized,
|
||||
rateQuantized);
|
||||
|
|
@ -2368,16 +2383,16 @@ void NormSession::AdjustRate(bool onResponse)
|
|||
tx_rate = MAX(tx_rate, minRate);
|
||||
|
||||
struct timeval currentTime;
|
||||
::GetSystemTime(¤tTime);
|
||||
::ProtoSystemTime(currentTime);
|
||||
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);
|
||||
} // end NormSession::AdjustRate()
|
||||
|
||||
bool NormSession::OnReportTimeout()
|
||||
bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
|
||||
{
|
||||
// Client reporting (just print out for now)
|
||||
struct timeval currentTime;
|
||||
GetSystemTime(¤tTime);
|
||||
ProtoSystemTime(currentTime);
|
||||
struct tm* ct = gmtime((time_t*)¤tTime.tv_sec);
|
||||
DMSG(2, "Report time>%02d:%02d:%02d.%06lu node>%lu ***************************************\n",
|
||||
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, LocalNodeId());
|
||||
|
|
@ -2387,9 +2402,9 @@ bool NormSession::OnReportTimeout()
|
|||
NormServerNode* next;
|
||||
while ((next = (NormServerNode*)iterator.GetNextNode()))
|
||||
{
|
||||
DMSG(2, "Remote server:%lu\n", next->Id());
|
||||
double rxRate = 8.0e-03*((double)next->RecvTotal()) / report_timer.Interval(); // kbps
|
||||
double rxGoodput = 8.0e-03*((double)next->RecvGoodput()) / report_timer.Interval(); // kbps
|
||||
DMSG(2, "Remote server:%lu\n", next->GetId());
|
||||
double rxRate = 8.0e-03*((double)next->RecvTotal()) / report_timer.GetInterval(); // kbps
|
||||
double rxGoodput = 8.0e-03*((double)next->RecvGoodput()) / report_timer.GetInterval(); // kbps
|
||||
next->ResetRecvStats();
|
||||
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",
|
||||
|
|
@ -2406,8 +2421,9 @@ bool NormSession::OnReportTimeout()
|
|||
return true;
|
||||
} // end NormSession::OnReportTimeout()
|
||||
|
||||
NormSessionMgr::NormSessionMgr()
|
||||
: socket_installer(NULL), socket_install_data(NULL),
|
||||
NormSessionMgr::NormSessionMgr(ProtoTimerMgr& timerMgr,
|
||||
ProtoSocket::Notifier& socketNotifier)
|
||||
: timer_mgr(timerMgr), socket_notifier(socketNotifier),
|
||||
controller(NULL), top_session(NULL)
|
||||
{
|
||||
}
|
||||
|
|
@ -2434,8 +2450,8 @@ NormSession* NormSessionMgr::NewSession(const char* sessionAddress,
|
|||
if (NORM_NODE_ANY == localNodeId)
|
||||
{
|
||||
// Use local ip address to assign default localNodeId
|
||||
NetworkAddress localAddr;
|
||||
if (!localAddr.LookupLocalHostAddress())
|
||||
ProtoAddress localAddr;
|
||||
if (!localAddr.ResolveLocalAddress())
|
||||
{
|
||||
DMSG(0, "NormSessionMgr::NewSession() local address lookup error\n");
|
||||
return ((NormSession*)NULL);
|
||||
|
|
@ -2443,8 +2459,8 @@ NormSession* NormSessionMgr::NewSession(const char* sessionAddress,
|
|||
// (TBD) test IPv6 "EndIdentifier" ???
|
||||
localNodeId = localAddr.EndIdentifier();
|
||||
}
|
||||
NetworkAddress theAddress;
|
||||
if (!theAddress.LookupHostAddress(sessionAddress))
|
||||
ProtoAddress theAddress;
|
||||
if (!theAddress.ResolveFromString(sessionAddress))
|
||||
{
|
||||
DMSG(0, "NormSessionMgr::NewSession() session address lookup error!\n");
|
||||
return ((NormSession*)NULL);
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@
|
|||
#include "normNode.h"
|
||||
#include "normEncoder.h"
|
||||
|
||||
#include "protocolTimer.h"
|
||||
#include "udpSocket.h"
|
||||
|
||||
#include "protokit.h"
|
||||
|
||||
class NormController
|
||||
{
|
||||
|
|
@ -34,19 +32,11 @@ class NormSessionMgr
|
|||
{
|
||||
friend class NormSession;
|
||||
public:
|
||||
NormSessionMgr();
|
||||
NormSessionMgr(ProtoTimerMgr& timerMgr,
|
||||
ProtoSocket::Notifier& socketNotifier);
|
||||
~NormSessionMgr();
|
||||
void Init(ProtocolTimerInstallFunc* timerInstaller,
|
||||
const void* timerInstallData,
|
||||
UdpSocketInstallFunc* socketInstaller,
|
||||
void* socketInstallData,
|
||||
NormController* theController)
|
||||
{
|
||||
timer_mgr.SetInstaller(timerInstaller, timerInstallData);
|
||||
socket_installer = socketInstaller;
|
||||
socket_install_data = socketInstallData;
|
||||
controller = theController;
|
||||
}
|
||||
void SetController(NormController* theController)
|
||||
{controller = theController;}
|
||||
void Destroy();
|
||||
|
||||
class NormSession* NewSession(const char* sessionAddress,
|
||||
|
|
@ -55,10 +45,6 @@ class NormSessionMgr
|
|||
NORM_NODE_ANY);
|
||||
void DeleteSession(class NormSession* theSession);
|
||||
|
||||
|
||||
UdpSocketInstallFunc* SocketInstaller() {return socket_installer;}
|
||||
const void* SocketInstallData() {return socket_install_data;}
|
||||
|
||||
void Notify(NormController::Event event,
|
||||
class NormSession* session,
|
||||
class NormServerNode* server,
|
||||
|
|
@ -68,12 +54,13 @@ class NormSessionMgr
|
|||
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:
|
||||
ProtocolTimerMgr timer_mgr;
|
||||
UdpSocketInstallFunc* socket_installer;
|
||||
const void* socket_install_data;
|
||||
ProtoTimerMgr& timer_mgr;
|
||||
ProtoSocket::Notifier& socket_notifier;
|
||||
NormController* controller;
|
||||
|
||||
class NormSession* top_session; // top of NormSession list
|
||||
|
|
@ -104,8 +91,8 @@ class NormSession
|
|||
bool Open();
|
||||
void Close();
|
||||
bool IsOpen() {return (rx_socket.IsOpen() || tx_socket.IsOpen());}
|
||||
const NetworkAddress& Address() {return address;}
|
||||
void SetAddress(const NetworkAddress& addr) {address = addr;}
|
||||
const ProtoAddress& Address() {return address;}
|
||||
void SetAddress(const ProtoAddress& addr) {address = addr;}
|
||||
static double CalculateRate(double size, double rtt, double loss);
|
||||
|
||||
|
||||
|
|
@ -135,9 +122,8 @@ class NormSession
|
|||
NormMsg* GetMessageFromPool() {return message_pool.RemoveHead();}
|
||||
void ReturnMessageToPool(NormMsg* msg) {message_pool.Append(msg);}
|
||||
void QueueMessage(NormMsg* msg);
|
||||
void SendMessage(NormMsg& msg);
|
||||
void InstallTimer(ProtocolTimer* timer)
|
||||
{session_mgr.InstallTimer(timer);}
|
||||
bool SendMessage(NormMsg& msg);
|
||||
void ActivateTimer(ProtoTimer& timer) {session_mgr.ActivateTimer(timer);}
|
||||
|
||||
// Server methods
|
||||
void ServerSetBaseObjectId(NormObjectId baseId)
|
||||
|
|
@ -195,7 +181,7 @@ class NormSession
|
|||
if (!tx_timer.IsActive())
|
||||
{
|
||||
tx_timer.SetInterval(0.0);
|
||||
InstallTimer(&tx_timer);
|
||||
ActivateTimer(tx_timer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +213,7 @@ class NormSession
|
|||
// Simulation specific methods
|
||||
NormSimObject* QueueTxSim(unsigned long objectSize);
|
||||
bool SimSocketRecvHandler(char* buffer, unsigned short buflen,
|
||||
const NetworkAddress& src, bool unicast);
|
||||
const ProtoAddress& src, bool unicast);
|
||||
#endif // SIMULATE
|
||||
|
||||
private:
|
||||
|
|
@ -239,15 +225,15 @@ class NormSession
|
|||
bool QueueTxObject(NormObject* obj, bool touchServer = true);
|
||||
void DeleteTxObject(NormObject* obj);
|
||||
|
||||
bool OnTxTimeout();
|
||||
bool OnRepairTimeout();
|
||||
bool OnFlushTimeout();
|
||||
bool OnWatermarkTimeout();
|
||||
bool OnProbeTimeout();
|
||||
bool OnReportTimeout();
|
||||
bool OnTxTimeout(ProtoTimer& theTimer);
|
||||
bool OnRepairTimeout(ProtoTimer& theTimer);
|
||||
bool OnFlushTimeout(ProtoTimer& theTimer);
|
||||
bool OnWatermarkTimeout(ProtoTimer& theTimer);
|
||||
bool OnProbeTimeout(ProtoTimer& theTimer);
|
||||
bool OnReportTimeout(ProtoTimer& theTimer);
|
||||
|
||||
bool TxSocketRecvHandler(UdpSocket* theSocket);
|
||||
bool RxSocketRecvHandler(UdpSocket* theSocket);
|
||||
void TxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
|
||||
void RxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEve);
|
||||
void HandleReceiveMessage(NormMsg& msg, bool wasUnicast);
|
||||
|
||||
// Server message handling routines
|
||||
|
|
@ -264,7 +250,7 @@ class NormSession
|
|||
double ccRtt,
|
||||
double ccLoss,
|
||||
double ccRate,
|
||||
UINT8 ccSequence);
|
||||
UINT16 ccSequence);
|
||||
void AdjustRate(bool onResponse);
|
||||
bool ServerQueueSquelch(NormObjectId objectId);
|
||||
void ServerQueueFlush();
|
||||
|
|
@ -283,17 +269,17 @@ class NormSession
|
|||
|
||||
NormSessionMgr& session_mgr;
|
||||
bool notify_pending;
|
||||
ProtocolTimer tx_timer;
|
||||
UdpSocket tx_socket;
|
||||
UdpSocket rx_socket;
|
||||
ProtoTimer tx_timer;
|
||||
ProtoSocket tx_socket;
|
||||
ProtoSocket rx_socket;
|
||||
NormMessageQueue message_queue;
|
||||
NormMessageQueue message_pool;
|
||||
ProtocolTimer report_timer;
|
||||
ProtoTimer report_timer;
|
||||
UINT16 tx_sequence;
|
||||
|
||||
// General session parameters
|
||||
NormNodeId local_node_id;
|
||||
NetworkAddress address; // session destination address
|
||||
ProtoAddress address; // session destination address
|
||||
UINT8 ttl; // session multicast ttl
|
||||
double tx_rate; // bytes per second
|
||||
double backoff_factor;
|
||||
|
|
@ -310,7 +296,7 @@ class NormSession
|
|||
NormObjectTable tx_table;
|
||||
NormSlidingMask tx_pending_mask;
|
||||
NormSlidingMask tx_repair_mask;
|
||||
ProtocolTimer repair_timer;
|
||||
ProtoTimer repair_timer;
|
||||
NormBlockPool block_pool;
|
||||
NormSegmentPool segment_pool;
|
||||
NormEncoder encoder;
|
||||
|
|
@ -319,10 +305,10 @@ class NormSession
|
|||
unsigned int tx_cache_count_min;
|
||||
unsigned int tx_cache_count_max;
|
||||
NormObjectSize tx_cache_size_max;
|
||||
ProtocolTimer flush_timer;
|
||||
ProtoTimer flush_timer;
|
||||
int flush_count;
|
||||
bool posted_tx_queue_empty;
|
||||
ProtocolTimer watermark_timer;
|
||||
ProtoTimer watermark_timer;
|
||||
int watermark_count;
|
||||
// (TBD) watermark_object_id, watermark_block_id, watermark_symbol_id
|
||||
|
||||
|
|
@ -332,7 +318,7 @@ class NormSession
|
|||
double suppress_rate;
|
||||
double suppress_rtt;
|
||||
|
||||
ProtocolTimer probe_timer; // GRTT/congestion control probes
|
||||
ProtoTimer probe_timer; // GRTT/congestion control probes
|
||||
bool probe_proactive;
|
||||
|
||||
double grtt_interval; // current GRTT update interval
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@
|
|||
// of a message stream from the MGEN simulation agent with restrictions. The
|
||||
// current restriction is the MGEN simulation agent
|
||||
|
||||
NormSimAgent::NormSimAgent(ProtocolTimerInstallFunc* timerInstaller,
|
||||
const void* timerInstallData,
|
||||
UdpSocketInstallFunc* socketInstaller,
|
||||
void* socketInstallData)
|
||||
: session(NULL),
|
||||
NormSimAgent::NormSimAgent(ProtoTimerMgr& timerMgr,
|
||||
ProtoSocket::Notifier& socketNotifier)
|
||||
: session_mgr(timerMgr, socketNotifier), session(NULL),
|
||||
address(NULL), port(0), ttl(3),
|
||||
tx_rate(NormSession::DEFAULT_TRANSMIT_RATE),
|
||||
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)
|
||||
{
|
||||
// Bind NormSessionMgr to this agent and simulation environment
|
||||
session_mgr.Init(timerInstaller, timerInstallData,
|
||||
socketInstaller, socketInstallData,
|
||||
static_cast<NormController*>(this));
|
||||
session_mgr.SetController(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);
|
||||
}
|
||||
|
||||
|
|
@ -589,9 +587,9 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
else
|
||||
{
|
||||
// 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
|
||||
{
|
||||
|
|
@ -735,7 +733,9 @@ void NormSimAgent::Notify(NormController::Event event,
|
|||
}
|
||||
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_bytes = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
|
||||
// normSimAgent.h - Generic (base class) NORM simulation agent
|
||||
|
||||
#include "protoLib.h"
|
||||
#include "protoSim.h"
|
||||
#include "normSession.h"
|
||||
#include "protokit.h"
|
||||
|
||||
#include "mgen.h" // for MGEN instance attachment
|
||||
|
||||
|
|
@ -25,10 +24,8 @@ class NormSimAgent : public NormController
|
|||
void AttachMgen(Mgen* mgenInstance) {mgen = mgenInstance;}
|
||||
|
||||
protected:
|
||||
NormSimAgent(ProtocolTimerInstallFunc* timerInstaller,
|
||||
const void* timerInstallData,
|
||||
UdpSocketInstallFunc* socketInstaller,
|
||||
void* socketInstallData);
|
||||
NormSimAgent(ProtoTimerMgr& timerMgr,
|
||||
ProtoSocket::Notifier& socketNotifier);
|
||||
enum CmdType {CMD_INVALID, CMD_NOARG, CMD_ARG};
|
||||
CmdType CommandType(const char* cmd);
|
||||
virtual unsigned long GetAgentId() = 0;
|
||||
|
|
@ -42,8 +39,8 @@ class NormSimAgent : public NormController
|
|||
class NormServerNode* server,
|
||||
class NormObject* object);
|
||||
|
||||
void InstallTimer(ProtocolTimer& theTimer)
|
||||
{session_mgr.InstallTimer(&theTimer);}
|
||||
void ActivateTimer(ProtoTimer& theTimer)
|
||||
{session_mgr.ActivateTimer(theTimer);}
|
||||
|
||||
bool OnIntervalTimeout();
|
||||
|
||||
|
|
@ -88,7 +85,7 @@ class NormSimAgent : public NormController
|
|||
unsigned int mgen_bytes;
|
||||
unsigned int mgen_pending_bytes;
|
||||
|
||||
ProtocolTimer interval_timer;
|
||||
ProtoTimer interval_timer;
|
||||
|
||||
// protocol debug parameters
|
||||
bool tracing;
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -32,6 +32,6 @@
|
|||
|
||||
#ifndef _NORM_VERSION
|
||||
#define _NORM_VERSION
|
||||
#define VERSION "1.0b2"
|
||||
#define VERSION "1.1b1"
|
||||
#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()
|
||||
: NormSimAgent(ProtoSimAgent::TimerInstaller,
|
||||
static_cast<ProtoSimAgent*>(this),
|
||||
ProtoSimAgent::SocketInstaller,
|
||||
static_cast<ProtoSimAgent*>(this))
|
||||
: NormSimAgent(GetTimerMgr(), GetSocketNotifier())
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
int i = 1;
|
||||
|
|
@ -70,8 +85,8 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
|||
// Attach Agent/MGEN to this NormSimAgent
|
||||
if (++i >= argc)
|
||||
{
|
||||
DMSG(0, "NsNormAgent::command() ProcessCommand(attach-mgen) error: insufficent arguments\n");
|
||||
return TCL_ERROR;
|
||||
DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(attach-mgen) error: insufficent arguments\n");
|
||||
return false;
|
||||
}
|
||||
Tcl& tcl = Tcl::instance();
|
||||
NsMgenAgent* mgenAgent = dynamic_cast<NsMgenAgent*> (tcl.lookup(argv[i]));
|
||||
|
|
@ -83,8 +98,8 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "NsNormAgent::command() ProcessCommand(attach-mgen) error: invalid mgen agent\n");
|
||||
return TCL_ERROR;
|
||||
DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(attach-mgen) error: invalid mgen agent\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "active"))
|
||||
|
|
@ -105,9 +120,9 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
|||
case NormSimAgent::CMD_NOARG:
|
||||
if (!ProcessCommand(argv[i], NULL))
|
||||
{
|
||||
DMSG(0, "NsNormAgent::command() ProcessCommand(%s) error\n",
|
||||
DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(%s) error\n",
|
||||
argv[i]);
|
||||
return TCL_ERROR;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
|
|
@ -115,23 +130,23 @@ int NsNormAgent::command(int argc, const char*const* argv)
|
|||
case NormSimAgent::CMD_ARG:
|
||||
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]);
|
||||
return TCL_ERROR;
|
||||
return false;
|
||||
}
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case NormSimAgent::CMD_INVALID:
|
||||
return NsProtoAgent::command(argc, argv);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
} // end NsNormAgent::command()
|
||||
return true;
|
||||
} // end NsNormAgent::ProcessCommands()
|
||||
|
||||
bool NsNormAgent::SendMgenMessage(const NetworkAddress* dstAddr,
|
||||
const char* txBuffer,
|
||||
unsigned int len)
|
||||
bool NsNormAgent::SendMgenMessage(const char* txBuffer,
|
||||
unsigned int len,
|
||||
const ProtoAddress& /*dstAddr*/)
|
||||
{
|
||||
return SendMessage(len, txBuffer);
|
||||
} // end NsNormAgent::SendMgenMessage()
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#ifndef _NS_NORM_AGENT
|
||||
#define _NS_NORM_AGENT
|
||||
|
||||
#include "nsProtoAgent.h" // from ProtoLib
|
||||
#include "nsProtoSimAgent.h" // from Protolib
|
||||
#include "normSimAgent.h"
|
||||
|
||||
#include "nsMgenAgent.h"
|
||||
|
|
@ -44,20 +44,23 @@
|
|||
|
||||
// IMPORTANT NOTE! NsProtoAgent must be listed _first_ here
|
||||
// (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:
|
||||
NsNormAgent();
|
||||
~NsNormAgent();
|
||||
|
||||
// NsProtoAgent base class override
|
||||
int command(int argc, const char*const* argv);
|
||||
// NsProtoSimAgent base class overrides
|
||||
virtual bool OnStartup(int argc, const char*const* argv);
|
||||
virtual bool ProcessCommands(int argc, const char*const* argv);
|
||||
virtual void OnShutdown();
|
||||
|
||||
// NormSimAgent override
|
||||
unsigned long GetAgentId() {return (unsigned long)addr();}
|
||||
// MgenSink override
|
||||
bool SendMgenMessage(const NetworkAddress* dstAddr,
|
||||
const char* txBuffer,
|
||||
unsigned int len);
|
||||
bool SendMgenMessage(const char* txBuffer,
|
||||
unsigned int len,
|
||||
const ProtoAddress& dstAddr);
|
||||
}; // end class NsNormAgent
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ CFLAGS = -g -DPROTO_DEBUG -DUNIX -O -fPIC $(SYSTEM_HAVES) $(INCLUDES)
|
|||
LDFLAGS = $(SYSTEM_LDFLAGS)
|
||||
|
||||
# Note: Even command line app needs X11 for Netscape post-processing
|
||||
LIBS = $(SYSTEM_LIBS) -lm
|
||||
LIBS = $(SYSTEM_LIBS) -lm -lpthread
|
||||
XLIBS = -lXmu -lXt -lX11
|
||||
|
||||
#NOTE: TK_LIB must come before TCL_LIB for some reason
|
||||
|
|
@ -47,9 +47,9 @@ TARGETS = mdp tkMdp
|
|||
$(CC) -c $(CFLAGS) -o $*.o $*.cpp
|
||||
|
||||
# MDP depends upon the NRL Protean Group's development library
|
||||
LIBPROTO = $(PROTOLIB)/unix/libProto.a
|
||||
$(PROTOLIB)/unix/libProto.a:
|
||||
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProto.a
|
||||
LIBPROTO = $(PROTOLIB)/unix/libProtokit.a
|
||||
$(PROTOLIB)/unix/libProtokit.a:
|
||||
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProtokit.a
|
||||
|
||||
NORM_SRC = $(COMMON)/normMessage.cpp $(COMMON)/normSession.cpp \
|
||||
$(COMMON)/normNode.cpp $(COMMON)/normObject.cpp \
|
||||
|
|
@ -77,7 +77,8 @@ libnormSim.a: $(SIM_OBJ)
|
|||
ranlib $@
|
||||
|
||||
# (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)
|
||||
|
||||
norm: $(APP_OBJ) libnorm.a $(LIBPROTO)
|
||||
|
|
|
|||
|
|
@ -2,37 +2,14 @@
|
|||
# FreeBSD Protean Makefile definitions
|
||||
#
|
||||
|
||||
# TO BUILD THE TK GUI VERSION, 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
|
||||
# (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
|
||||
# 1) System specific additional libraries, include paths, etc
|
||||
# (Where to find X11 libraries, etc)
|
||||
#
|
||||
SYSTEM_INCLUDES = -I/usr/X11R6/include
|
||||
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
|
||||
SYSTEM_INCLUDES =
|
||||
SYSTEM_LDFLAGS =
|
||||
SYSTEM_LIBS =
|
||||
|
||||
# 6) System specific capabilities
|
||||
# 2) System specific capabilities
|
||||
# Must choose appropriate for the following:
|
||||
#
|
||||
# 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()
|
||||
# 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
|
||||
# to keep some compilers (gcc 2.7.2) happy.
|
||||
#
|
||||
|
|
@ -62,10 +39,13 @@ SYSTEM_LIBS =
|
|||
# (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
|
||||
export RANLIB = ranlib
|
||||
export AR = ar
|
||||
SYSTEM_SRC = bsdRouteMgr.cpp
|
||||
|
||||
SYSTEM = freebsd
|
||||
CC = gcc
|
||||
RANLIB = ranlib
|
||||
AR = ar
|
||||
|
||||
include Makefile.common
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ TK_LIB = -ltk #/usr/local/lib/libtk8.0.a
|
|||
# 5) System specific additional libraries, include paths, 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_LIBS = -ldl
|
||||
|
||||
|
|
@ -62,10 +62,14 @@ SYSTEM_LIBS = -ldl
|
|||
# (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)
|
||||
|
||||
export CC = gcc
|
||||
SYSTEM_SRC =
|
||||
|
||||
SYSTEM = linux
|
||||
|
||||
export CC = g++
|
||||
export RANLIB = ranlib
|
||||
export AR = ar
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
# 1) System specific additional libraries, include paths, etc
|
||||
# (Where to find X11 libraries, etc)
|
||||
#
|
||||
|
||||
SYSTEM_INCLUDES = -I/usr/X11R6/include
|
||||
SYSTEM_LDFLAGS = -L/usr/X11R6/lib
|
||||
SYSTEM_LIBS =
|
||||
|
|
@ -35,7 +36,12 @@ SYSTEM_LIBS =
|
|||
# (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 RANLIB = ranlib
|
||||
|
|
|
|||
|
|
@ -3,11 +3,10 @@
|
|||
#
|
||||
|
||||
|
||||
|
||||
# 1) System specific additional libraries, include paths, etc
|
||||
# (Where to find X11 libraries, etc)
|
||||
#
|
||||
SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333 -cfront
|
||||
SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333
|
||||
SYSTEM_LDFLAGS =
|
||||
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
|
||||
# (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
|
||||
# 1) System specific additional libraries, include paths, etc
|
||||
# (Where to find X11 libraries, etc)
|
||||
#
|
||||
SYSTEM_INCLUDES = -I/usr/openwin/include
|
||||
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:
|
||||
#
|
||||
# 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()
|
||||
# routine.
|
||||
#
|
||||
# E) The MDP code's use of offset pointers requires special treatment
|
||||
# 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
|
||||
# E) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||
# 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
|
||||
#
|
||||
# (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
|
||||
export RANLIB = touch
|
||||
export AR = ar
|
||||
SYSTEM = solaris
|
||||
|
||||
CC = g++
|
||||
|
||||
RANLIB = touch
|
||||
|
||||
AR = ar
|
||||
|
||||
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