pull/2/head
Jeff Weston 2019-09-11 11:28:35 -04:00
parent d0417b042a
commit 02fcae4cb0
37 changed files with 2533 additions and 874 deletions

View File

@ -1,31 +1,32 @@
// norm.cpp - Command-line NORM application // normApp.cpp - Command-line NORM application
#include "protoLib.h" #include "protokit.h"
#include "normSession.h" #include "normSession.h"
#include "normPostProcess.h" #include "normPostProcess.h"
#include <stdio.h> // for stdout/stderr printouts #include <stdio.h> // for stdout/stderr printouts
#include <signal.h> // for SIGTERM/SIGINT handling #include <signal.h> // for SIGTERM/SIGINT handling
#include <errno.h> #include <errno.h>
#include <stdlib.h>
// Command-line application using Protolib EventDispatcher // Command-line application using Protolib EventDispatcher
class NormApp : public NormController class NormApp : public NormController, public ProtoApp
{ {
public: public:
NormApp(); NormApp();
virtual ~NormApp(); virtual ~NormApp();
bool OnStartup();
int MainLoop() {return dispatcher.Run();} // Overrides from ProtoApp or NsProtoSimAgent base
void Stop(int exitCode) {dispatcher.Stop(exitCode);} bool OnStartup(int argc, const char*const* argv);
bool ProcessCommands(int argc, const char*const* argv);
void OnShutdown(); void OnShutdown();
bool ProcessCommand(const char* cmd, const char* val); bool ProcessCommand(const char* cmd, const char* val);
bool ParseCommandLine(int argc, char* argv[]);
static void DoInputReady(EventDispatcher::Descriptor descriptor, static void DoInputReady(ProtoDispatcher::Descriptor descriptor,
EventDispatcher::EventType theEvent, ProtoDispatcher::Event theEvent,
const void* userData); const void* userData);
private: private:
void OnInputReady(); void OnInputReady();
@ -39,17 +40,14 @@ class NormApp : public NormController
class NormServerNode* server, class NormServerNode* server,
class NormObject* object); class NormObject* object);
void InstallTimer(ProtocolTimer* timer) bool OnIntervalTimeout(ProtoTimer& theTimer);
{dispatcher.InstallTimer(timer);}
bool OnIntervalTimeout();
static const char* const cmd_list[]; static const char* const cmd_list[];
#ifdef UNIX
static void SignalHandler(int sigNum); static void SignalHandler(int sigNum);
bool IsPostProcessing() {return post_processor.IsActive();} #endif // UNIX
void HandleSIGCHLD() {post_processor.HandleSIGCHLD();}
EventDispatcher dispatcher;
NormSessionMgr session_mgr; NormSessionMgr session_mgr;
NormSession* session; NormSession* session;
NormStreamObject* tx_stream; NormStreamObject* tx_stream;
@ -91,13 +89,13 @@ class NormApp : public NormController
double tx_object_interval; double tx_object_interval;
int tx_repeat_count; int tx_repeat_count;
double tx_repeat_interval; double tx_repeat_interval;
ProtocolTimer interval_timer; ProtoTimer interval_timer;
// NormSession client-only parameters // NormSession client-only parameters
unsigned long rx_buffer_size; // bytes unsigned long rx_buffer_size; // bytes
NormFileList rx_file_cache; NormFileList rx_file_cache;
char* rx_cache_path; char* rx_cache_path;
NormPostProcessor post_processor; NormPostProcessor* post_processor;
bool unicast_nacks; bool unicast_nacks;
bool silent_client; bool silent_client;
@ -109,7 +107,8 @@ class NormApp : public NormController
}; // end class NormApp }; // end class NormApp
NormApp::NormApp() NormApp::NormApp()
: session(NULL), tx_stream(NULL), rx_stream(NULL), input(NULL), output(NULL), : session_mgr(GetTimerMgr(), GetSocketNotifier()),
session(NULL), tx_stream(NULL), rx_stream(NULL), input(NULL), output(NULL),
input_index(0), input_length(0), input_active(false), input_index(0), input_length(0), input_active(false),
push_stream(false), input_messaging(false), input_msg_length(0), input_msg_index(0), push_stream(false), input_messaging(false), input_msg_length(0), input_msg_index(0),
output_index(0), output_messaging(false), output_msg_length(0), output_msg_sync(false), output_index(0), output_messaging(false), output_msg_length(0), output_msg_sync(false),
@ -122,14 +121,14 @@ NormApp::NormApp()
tracing(false), tx_loss(0.0), rx_loss(0.0) tracing(false), tx_loss(0.0), rx_loss(0.0)
{ {
// Init tx_timer for 1.0 second interval, infinite repeats // Init tx_timer for 1.0 second interval, infinite repeats
session_mgr.Init(EventDispatcher::TimerInstaller, &dispatcher, session_mgr.SetController(this);
EventDispatcher::SocketInstaller, &dispatcher,
this); interval_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormApp::OnIntervalTimeout);
interval_timer.Init(0.0, 0, (ProtocolTimerOwner*)this, interval_timer.SetInterval(0.0);
(ProtocolTimeoutFunc)&NormApp::OnIntervalTimeout); interval_timer.SetRepeat(0);
struct timeval currentTime; struct timeval currentTime;
GetSystemTime(&currentTime); ProtoSystemTime(currentTime);
srand(currentTime.tv_usec); srand(currentTime.tv_usec);
} }
@ -137,6 +136,7 @@ NormApp::~NormApp()
{ {
if (address) delete address; if (address) delete address;
if (rx_cache_path) delete rx_cache_path; if (rx_cache_path) delete rx_cache_path;
if (post_processor) delete post_processor;
} }
@ -299,9 +299,9 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
else if (!strncmp("input", cmd, len)) else if (!strncmp("input", cmd, len))
{ {
if (!strcmp(val, "STDIN")) if (!strcmp(val, "STDIN"))
{ {
input = stdin; input = stdin;
} }
else if (!(input = fopen(val, "rb"))) else if (!(input = fopen(val, "rb")))
{ {
DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n", DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n",
@ -310,16 +310,18 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
} }
input_index = input_length = 0; input_index = input_length = 0;
input_messaging = false; input_messaging = false;
#ifdef UNIX
// Set input non-blocking // Set input non-blocking
if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK)) if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK))
perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error"); perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error");
#endif // UNIX
} }
else if (!strncmp("output", cmd, len)) else if (!strncmp("output", cmd, len))
{ {
if (!strcmp(val, "STDOUT")) if (!strcmp(val, "STDOUT"))
{ {
output = stdout; output = stdout;
} }
else if (!(output = fopen(val, "wb"))) else if (!(output = fopen(val, "wb")))
{ {
DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n", DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n",
@ -333,9 +335,9 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
else if (!strncmp("minput", cmd, len)) else if (!strncmp("minput", cmd, len))
{ {
if (!strcmp(val, "STDIN")) if (!strcmp(val, "STDIN"))
{ {
input = stdin; input = stdin;
} }
else if (!(input = fopen(val, "rb"))) else if (!(input = fopen(val, "rb")))
{ {
DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n", DMSG(0, "NormApp::ProcessCommand(input) fopen() error: %s\n",
@ -344,16 +346,18 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
} }
input_index = input_length = 0; input_index = input_length = 0;
input_messaging = true; input_messaging = true;
#ifdef UNIX
// Set input non-blocking // Set input non-blocking
if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK)) if(-1 == fcntl(fileno(input), F_SETFL, fcntl(fileno(input), F_GETFL, 0) | O_NONBLOCK))
perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error"); perror("NormApp::ProcessCommand(input) fcntl(F_SETFL(O_NONBLOCK)) error");
#endif // UNIX
} }
else if (!strncmp("moutput", cmd, len)) else if (!strncmp("moutput", cmd, len))
{ {
if (!strcmp(val, "STDOUT")) if (!strcmp(val, "STDOUT"))
{ {
output = stdout; output = stdout;
} }
else if (!(output = fopen(val, "wb"))) else if (!(output = fopen(val, "wb")))
{ {
DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n", DMSG(0, "NormApp::ProcessCommand(output) fopen() error: %s\n",
@ -404,8 +408,8 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
else if (!strncmp("rxcachedir", cmd, len)) else if (!strncmp("rxcachedir", cmd, len))
{ {
unsigned int length = strlen(val); unsigned int length = strlen(val);
// Make sure there is a trailing DIR_DELIMITER // Make sure there is a trailing PROTO_PATH_DELIMITER
if (DIR_DELIMITER != val[length-1]) if (PROTO_PATH_DELIMITER != val[length-1])
length += 2; length += 2;
else else
length += 1; length += 1;
@ -416,7 +420,7 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
return false; return false;
} }
strcpy(rx_cache_path, val); strcpy(rx_cache_path, val);
rx_cache_path[length-2] = DIR_DELIMITER; rx_cache_path[length-2] = PROTO_PATH_DELIMITER;
rx_cache_path[length-1] = '\0'; rx_cache_path[length-1] = '\0';
} }
else if (!strncmp("segment", cmd, len)) else if (!strncmp("segment", cmd, len))
@ -514,7 +518,7 @@ bool NormApp::ProcessCommand(const char* cmd, const char* val)
} }
else if (!strncmp("processor", cmd, len)) else if (!strncmp("processor", cmd, len))
{ {
if (!post_processor.SetCommand(val)) if (!post_processor->SetCommand(val))
{ {
DMSG(0, "NormApp::ProcessCommand(processor) error!\n"); DMSG(0, "NormApp::ProcessCommand(processor) error!\n");
return false; return false;
@ -555,7 +559,7 @@ NormApp::CmdType NormApp::CommandType(const char* cmd)
} // end NormApp::CommandType() } // end NormApp::CommandType()
bool NormApp::ParseCommandLine(int argc, char* argv[]) bool NormApp::ProcessCommands(int argc, const char*const* argv)
{ {
int i = 1; int i = 1;
while ( i < argc) while ( i < argc)
@ -564,13 +568,13 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
switch (cmdType) switch (cmdType)
{ {
case CMD_INVALID: case CMD_INVALID:
DMSG(0, "NormApp::ParseCommandLine() Invalid command:%s\n", DMSG(0, "NormApp::ProcessCommands() Invalid command:%s\n",
argv[i]); argv[i]);
return false; return false;
case CMD_NOARG: case CMD_NOARG:
if (!ProcessCommand(argv[i], NULL)) if (!ProcessCommand(argv[i], NULL))
{ {
DMSG(0, "NormApp::ParseCommandLine() ProcessCommand(%s) error\n", DMSG(0, "NormApp::ProcessCommands() ProcessCommand(%s) error\n",
argv[i]); argv[i]);
return false; return false;
} }
@ -579,7 +583,7 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
case CMD_ARG: case CMD_ARG:
if (!ProcessCommand(argv[i], argv[i+1])) if (!ProcessCommand(argv[i], argv[i+1]))
{ {
DMSG(0, "NormApp::ParseCommandLine() ProcessCommand(%s, %s) error\n", DMSG(0, "NormApp::ProcessCommands() ProcessCommand(%s, %s) error\n",
argv[i], argv[i+1]); argv[i], argv[i+1]);
return false; return false;
} }
@ -588,10 +592,10 @@ bool NormApp::ParseCommandLine(int argc, char* argv[])
} }
} }
return true; return true;
} // end NormApp::ParseCommandLine() } // end NormApp::ProcessCommands()
void NormApp::DoInputReady(EventDispatcher::Descriptor /*descriptor*/, void NormApp::DoInputReady(ProtoDispatcher::Descriptor /*descriptor*/,
EventDispatcher::EventType /*theEvent*/, ProtoDispatcher::Event /*theEvent*/,
const void* userData) const void* userData)
{ {
((NormApp*)userData)->OnInputReady(); ((NormApp*)userData)->OnInputReady();
@ -607,6 +611,8 @@ void NormApp::OnInputReady()
// the stream has buffer space for input // the stream has buffer space for input
while (input) while (input)
{ {
bool inputStarved = false;
if (0 == input_length) if (0 == input_length)
{ {
// We need input ... // We need input ...
@ -667,7 +673,11 @@ void NormApp::OnInputReady()
DMSG(0, "norm: input end-of-file.\n"); DMSG(0, "norm: input end-of-file.\n");
if (input_active) if (input_active)
{ {
#ifdef WIN32
ASSERT(0); // no Win32 support for stream i/o yet
#else
dispatcher.RemoveGenericInput(fileno(input)); dispatcher.RemoveGenericInput(fileno(input));
#endif // if/else WIN32/UNIX
input_active = false; input_active = false;
} }
if (stdin != input) fclose(input); if (stdin != input) fclose(input);
@ -679,8 +689,10 @@ void NormApp::OnInputReady()
switch (errno) switch (errno)
{ {
case EINTR: case EINTR:
continue;
case EAGAIN: case EAGAIN:
// Input not ready, will get notification when ready // Input not ready, will get notification when ready
inputStarved = true;
break; break;
default: default:
DMSG(0, "norm: input error:%s\n", strerror(errno)); DMSG(0, "norm: input error:%s\n", strerror(errno));
@ -716,30 +728,37 @@ void NormApp::OnInputReady()
{ {
// Stream buffer full, temporarily deactive "input" and // Stream buffer full, temporarily deactive "input" and
// wait for next TX_QUEUE_EMPTY notification // wait for next TX_QUEUE_EMPTY notification
//TRACE("stream buffer full ...\n");
if (input_active) if (input_active)
{ {
dispatcher.RemoveGenericInput(fileno(input)); #ifdef WIN32
ASSERT(0); // no Win32 support for stream i/o yet
#else
dispatcher.RemoveGenericInput(fileno(input));
#endif // if/else WIN32/UNIX
input_active = false; input_active = false;
} }
break; break;
} }
} }
else else if (inputStarved)
{ {
// Input not ready, wait for "input" to be ready // Input not ready, wait for "input" to be ready
// (Activate/reactivate "input" as necessary // (Activate/reactivate "input" as necessary
//TRACE("input starved ...\n");
if (!input_active) if (!input_active)
{ {
if (dispatcher.AddGenericInput(fileno(input), NormApp::DoInputReady, this)) #ifdef WIN32
ASSERT(0); // no Win32 support for stream i/o yet
if (false)
#else
if (dispatcher.InstallGenericInput(fileno(input), NormApp::DoInputReady, this))
#endif // if/else WIN32/UNIX
input_active = true; input_active = true;
else else
DMSG(0, "NormApp::Notify(TX_QUEUE_EMPTY) error adding input notification!\n"); DMSG(0, "NormApp::Notify(TX_QUEUE_EMPTY) error adding input notification!\n");
} }
break; break;
} }
} // end while (1) } // end while (input)
} // NormApp::OnInputReady() } // NormApp::OnInputReady()
@ -762,14 +781,10 @@ void NormApp::Notify(NormController::Event event,
{ {
// Can queue a new object for transmission // Can queue a new object for transmission
if (interval_timer.IsActive()) interval_timer.Deactivate(); if (interval_timer.IsActive()) interval_timer.Deactivate();
if (interval_timer.Interval() > 0.0) if (interval_timer.GetInterval() > 0.0)
{ ActivateTimer(interval_timer);
InstallTimer(&interval_timer);
}
else else
{ OnIntervalTimeout(interval_timer);
OnIntervalTimeout();
}
} }
break; break;
@ -789,7 +804,7 @@ void NormApp::Notify(NormController::Event event,
// object Size() has recommended buffering size // object Size() has recommended buffering size
NormObjectSize size; NormObjectSize size;
if (silent_client) if (silent_client)
size = NormObjectSize(rx_buffer_size); size = NormObjectSize((UINT32)rx_buffer_size);
else else
size = object->Size(); size = object->Size();
@ -863,7 +878,7 @@ void NormApp::Notify(NormController::Event event,
for (UINT16 i = pathLen; i < (pathLen+len); i++) for (UINT16 i = pathLen; i < (pathLen+len); i++)
{ {
if ('/' == fileName[i]) if ('/' == fileName[i])
fileName[i] = DIR_DELIMITER; fileName[i] = PROTO_PATH_DELIMITER;
} }
pathLen += len; pathLen += len;
if (pathLen < PATH_MAX) fileName[pathLen] = '\0'; if (pathLen < PATH_MAX) fileName[pathLen] = '\0';
@ -947,7 +962,8 @@ void NormApp::Notify(NormController::Event event,
} }
else else
{ {
output_msg_sync = true; if (readLength > 0)
output_msg_sync = true;
} }
if (readLength) if (readLength)
@ -1015,15 +1031,16 @@ void NormApp::Notify(NormController::Event event,
case RX_OBJECT_COMPLETE: case RX_OBJECT_COMPLETE:
{ {
//TRACE("NormApp::Notify(RX_OBJECT_COMPLETE) ...\n");
switch(object->GetType()) switch(object->GetType())
{ {
case NormObject::FILE: case NormObject::FILE:
{ {
const char* filePath = ((NormFileObject*)object)->Path(); const char* filePath = ((NormFileObject*)object)->Path();
//DMSG(0, "norm: Completed rx file: %s\n", filePath); //DMSG(0, "norm: Completed rx file: %s\n", filePath);
if (post_processor.IsEnabled()) if (post_processor->IsEnabled())
{ {
if (!post_processor.ProcessFile(filePath)) if (!post_processor->ProcessFile(filePath))
{ {
DMSG(0, "norm: post processing error\n"); DMSG(0, "norm: post processing error\n");
} }
@ -1044,7 +1061,7 @@ void NormApp::Notify(NormController::Event event,
} // end NormApp::Notify() } // end NormApp::Notify()
bool NormApp::OnIntervalTimeout() bool NormApp::OnIntervalTimeout(ProtoTimer& /*theTimer*/)
{ {
char fileName[PATH_MAX]; char fileName[PATH_MAX];
if (tx_file_list.GetNextFile(fileName)) if (tx_file_list.GetNextFile(fileName))
@ -1063,7 +1080,7 @@ bool NormApp::OnIntervalTimeout()
// Normalize directory delimiters in file name info // Normalize directory delimiters in file name info
for (unsigned int i = 0; i < len; i++) for (unsigned int i = 0; i < len; i++)
{ {
if (DIR_DELIMITER == fileNameInfo[i]) if (PROTO_PATH_DELIMITER == fileNameInfo[i])
fileNameInfo[i] = '/'; fileNameInfo[i] = '/';
} }
char temp[PATH_MAX]; char temp[PATH_MAX];
@ -1076,7 +1093,7 @@ bool NormApp::OnIntervalTimeout()
// Wait a second, then try the next file in the list // Wait a second, then try the next file in the list
if (interval_timer.IsActive()) interval_timer.Deactivate(); if (interval_timer.IsActive()) interval_timer.Deactivate();
interval_timer.SetInterval(1.0); interval_timer.SetInterval(1.0);
InstallTimer(&interval_timer); ActivateTimer(interval_timer);
return false; return false;
} }
//DMSG(0, "norm: File \"%s\" queued for transmission.\n", fileName); //DMSG(0, "norm: File \"%s\" queued for transmission.\n", fileName);
@ -1091,12 +1108,12 @@ bool NormApp::OnIntervalTimeout()
{ {
if (interval_timer.IsActive()) interval_timer.Deactivate(); if (interval_timer.IsActive()) interval_timer.Deactivate();
interval_timer.SetInterval(tx_repeat_interval = tx_object_interval); interval_timer.SetInterval(tx_repeat_interval = tx_object_interval);
InstallTimer(&interval_timer); ActivateTimer(interval_timer);
return false; return false;
} }
else else
{ {
return OnIntervalTimeout(); return OnIntervalTimeout(interval_timer);
} }
} }
else else
@ -1106,20 +1123,25 @@ bool NormApp::OnIntervalTimeout()
return true; return true;
} // end NormApp::OnIntervalTimeout() } // end NormApp::OnIntervalTimeout()
bool NormApp::OnStartup() bool NormApp::OnStartup(int argc, const char*const* argv)
{ {
#ifdef WIN32
if (!dispatcher.Win32Init())
{
fprintf(stderr, "norm:: Win32Init() error!\n");
return false;
}
#endif // WIN32
signal(SIGTERM, SignalHandler);
signal(SIGINT, SignalHandler);
signal(SIGCHLD, SignalHandler);
if (!(post_processor = NormPostProcessor::Create()))
{
DMSG(0, "NormApp::OnStartup() error creating post processor\n");
return false;
}
if (!ProcessCommands(argc, argv))
{
DMSG(0, "NormApp::OnStartup() error processing command-line commands\n");
return false;
}
#ifdef UNIX
signal(SIGCHLD, SignalHandler);
#endif // UNIX
// Validate our application settings // Validate our application settings
if (!address) if (!address)
{ {
@ -1200,7 +1222,11 @@ void NormApp::OnShutdown()
{ {
if (input_active) if (input_active)
{ {
#ifdef WIN32
ASSERT(0); // no Win32 support for stream i/o yet
#else
dispatcher.RemoveGenericInput(fileno(input)); dispatcher.RemoveGenericInput(fileno(input));
#endif // if/else WIN32/UNIX
input_active = false; input_active = false;
} }
if (stdin != input) fclose(input); if (stdin != input) fclose(input);
@ -1211,97 +1237,32 @@ void NormApp::OnShutdown()
if (stdout != output) fclose(output); if (stdout != output) fclose(output);
output = NULL; output = NULL;
} }
if (post_processor)
{
delete post_processor;
post_processor = NULL;
}
} // end NormApp::OnShutdown() } // end NormApp::OnShutdown()
// Out application instance
PROTO_INSTANTIATE_APP(NormApp);
// Out application instance (global for SignalHandler) #ifdef UNIX
NormApp theApp;
// Use "main()" for UNIX and WIN32 console apps,
// "WinMain()" for non-console WIN32
// (VC++ uses the "_CONSOLE_" macro to indicate build type)
#if defined(WIN32) && !defined(_CONSOLE_)
int PASCAL WinMain(HINSTANCE instance, HINSTANCE prevInst, LPSTR cmdline, int cmdshow)
{
// (TBD) transform WinMain "cmdLine" to (argc, argv[]) values
int argc = 0;
char* argv[] = NULL;
#else
int main(int argc, char* argv[])
{
#endif
#ifdef WIN32
// Hack to determine if Win32 console application was launched
// independently or from a pre-existing console window
bool pauseForUser = false;
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE != hConsoleOutput)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hConsoleOutput, &csbi);
pauseForUser = ((csbi.dwCursorPosition.X==0) && (csbi.dwCursorPosition.Y==0));
if ((csbi.dwSize.X<=0) || (csbi.dwSize.Y <= 0)) pauseForUser = false;
}
else
{
// We're not a "console" application, so create one
// This could be commented out or made a command-line option
OpenDebugWindow();
pauseForUser = true;
}
#endif // WIN32
int exitCode = 0;
if (theApp.ParseCommandLine(argc, argv))
{
if (theApp.OnStartup())
{
exitCode = theApp.MainLoop();
theApp.OnShutdown();
fprintf(stderr, "norm: Done.\n");
}
else
{
fprintf(stderr, "norm: Error initializing application!\n");
exitCode = -1;
}
}
else
{
fprintf(stderr, "norm: Error parsing command line!\n");
exitCode = -1;
}
#ifdef WIN32
// If Win32 console is going to disappear, pause for user before exiting
if (pauseForUser)
{
printf ("Program Finished - Hit <Enter> to exit");
getchar();
}
#endif // WIN32
return exitCode; // exitCode contains "signum" causing exit
} // end main();
void NormApp::SignalHandler(int sigNum) void NormApp::SignalHandler(int sigNum)
{ {
switch(sigNum) switch(sigNum)
{ {
case SIGTERM:
case SIGINT:
theApp.Stop(sigNum); // causes theApp's main loop to exit
break;
case SIGCHLD: case SIGCHLD:
if (theApp.IsPostProcessing()) theApp.HandleSIGCHLD(); {
NormApp* app = static_cast<NormApp*>(ProtoApp::GetApp());
if (app->post_processor) app->post_processor->OnDeath();
signal(SIGCHLD, SignalHandler); signal(SIGCHLD, SignalHandler);
break; break;
}
default: default:
fprintf(stderr, "norm: Unexpected signal: %d\n", sigNum); fprintf(stderr, "norm: Unexpected signal: %d\n", sigNum);
break; break;
} }
} // end NormApp::SignalHandler() } // end NormApp::SignalHandler()
#endif // UNIX

View File

@ -1,7 +1,8 @@
#ifndef _NORM_BITMASK_ #ifndef _NORM_BITMASK_
#define _NORM_BITMASK_ #define _NORM_BITMASK_
#include "debug.h" // for PROTO_DEBUG stuff #include "protokit.h" // for PROTO_DEBUG stuff
#include <string.h> // for memset() #include <string.h> // for memset()
#include <stdio.h> // for fprintf() #include <stdio.h> // for fprintf()
@ -183,7 +184,6 @@ class NormSlidingMask
long start; long start;
long end; long end;
unsigned long offset; unsigned long offset;
unsigned char* mask2;
}; // end class NormSlidingMask }; // end class NormSlidingMask
#endif // _NORM_BITMASK_ #endif // _NORM_BITMASK_

View File

@ -146,13 +146,14 @@ bool NormEncoder::CreateGeneratorPolynomial()
for (int i = 0; i < degree; i++) for (int i = 0; i < degree; i++)
{ {
memset(&tp2[degree], 0, degree*sizeof(unsigned char)); memset(&tp2[degree], 0, degree*sizeof(unsigned char));
int j;
// Scale tp2 by p1[i] // Scale tp2 by p1[i]
for(int j=0; j<degree; j++) tp2[j]=gmult(tp1[j], tp[i]); for(j=0; j<degree; j++) tp2[j]=gmult(tp1[j], tp[i]);
// Mult(shift) tp2 right by i // Mult(shift) tp2 right by i
for (int j = (degree*2)-1; j >= i; j--) tp2[j] = tp2[j-i]; for (j = (degree*2)-1; j >= i; j--) tp2[j] = tp2[j-i];
memset(tp2, 0, i*sizeof(unsigned char)); memset(tp2, 0, i*sizeof(unsigned char));
// Add into partial product // Add into partial product
for(int j=0; j < (npar+1); j++) genPoly[j] ^= tp2[j]; for(j=0; j < (npar+1); j++) genPoly[j] ^= tp2[j];
} }
memcpy(tp1, genPoly, (npar+1)*sizeof(unsigned char)); memcpy(tp1, genPoly, (npar+1)*sizeof(unsigned char));
memset(&tp1[npar+1], 0, (2*degree)-(npar+1)); memset(&tp1[npar+1], 0, (2*degree)-(npar+1));
@ -343,7 +344,8 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
int vecSize = vector_size; int vecSize = vector_size;
#endif // if/else SIMUATE #endif // if/else SIMUATE
for (int i = 0; i < npar; i++) int i;
for (i = 0; i < npar; i++)
{ {
int X = gexp(i+1); int X = gexp(i+1);
unsigned char* synVec = sVec[i]; unsigned char* synVec = sVec[i];
@ -365,7 +367,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
int nvecsMinusOne = nvecs - 1; int nvecsMinusOne = nvecs - 1;
memset(Lambda, 0, degree*sizeof(char)); memset(Lambda, 0, degree*sizeof(char));
Lambda[0] = 1; Lambda[0] = 1;
for (int i = 0; i < erasureCount; i++) for (i = 0; i < erasureCount; i++)
{ {
int X = gexp(nvecsMinusOne - erasureLocs[i]); int X = gexp(nvecsMinusOne - erasureLocs[i]);
for(int j = (degree-1); j > 0; j--) for(int j = (degree-1); j > 0; j--)
@ -373,7 +375,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
} }
// (C) Compute modified Omega using Lambda // (C) Compute modified Omega using Lambda
for(int i = 0; i < npar; i++) for(i = 0; i < npar; i++)
{ {
int k = i; int k = i;
memset(oVec[i], 0, vecSize*sizeof(char)); memset(oVec[i], 0, vecSize*sizeof(char));
@ -389,7 +391,7 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
} }
// (D) Finally, fill in the erasures // (D) Finally, fill in the erasures
for (int i = 0; i < erasureCount; i++) for (i = 0; i < erasureCount; i++)
{ {
// Only fill _data_ erasures // Only fill _data_ erasures
if (erasureLocs[i] >= ndata) break;//return erasureCount; if (erasureLocs[i] >= ndata) break;//return erasureCount;
@ -398,14 +400,15 @@ int NormDecoder::Decode(char** dVec, int ndata, UINT16 erasureCount, UINT16* era
// ( all odd powers disappear) // ( all odd powers disappear)
int k = nvecsMinusOne - erasureLocs[i]; int k = nvecsMinusOne - erasureLocs[i];
int denom = 0; int denom = 0;
for (int j = 1; j < degree; j += 2) int j;
for (j = 1; j < degree; j += 2)
denom ^= gmult(Lambda[j], gexp(((255-k)*(j-1)) % 255)); denom ^= gmult(Lambda[j], gexp(((255-k)*(j-1)) % 255));
// Invert for use computing errror value below // Invert for use computing errror value below
denom = ginv(denom); denom = ginv(denom);
// Now evaluate Omega at alpha^(-i) (numerator) // Now evaluate Omega at alpha^(-i) (numerator)
unsigned char* eVec = (unsigned char*)dVec[erasureLocs[i]]; unsigned char* eVec = (unsigned char*)dVec[erasureLocs[i]];
for (int j = 0; j < npar; j++) for (j = 0; j < npar; j++)
{ {
unsigned char* data = eVec; unsigned char* data = eVec;
unsigned char* Omega = oVec[j]; unsigned char* Omega = oVec[j];

View File

@ -33,7 +33,7 @@
#ifndef _NORM_ENCODER #ifndef _NORM_ENCODER
#define _NORM_ENCODER #define _NORM_ENCODER
#include "sysdefs.h" // protolib stuff #include "protokit.h" // protolib stuff
class NormEncoder class NormEncoder
{ {

View File

@ -3,7 +3,7 @@
#include <string.h> // for strerror() #include <string.h> // for strerror()
#include <errno.h> // for errno #include <errno.h> // for errno
#include <stdio.h> // for rename()
#ifdef WIN32 #ifdef WIN32
#include <direct.h> #include <direct.h>
#include <share.h> #include <share.h>
@ -34,14 +34,14 @@ bool NormFile::Open(const char* thePath, int theFlags)
// Create sub-directories as needed. // Create sub-directories as needed.
char tempPath[PATH_MAX]; char tempPath[PATH_MAX];
strncpy(tempPath, thePath, PATH_MAX); strncpy(tempPath, thePath, PATH_MAX);
char* ptr = strrchr(tempPath, DIR_DELIMITER); char* ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
if (ptr) *ptr = '\0'; if (ptr) *ptr = '\0';
ptr = NULL; ptr = NULL;
while (!NormFile::Exists(tempPath)) while (!NormFile::Exists(tempPath))
{ {
char* ptr2 = ptr; char* ptr2 = ptr;
ptr = strrchr(tempPath, DIR_DELIMITER); ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
if (ptr2) *ptr2 = DIR_DELIMITER; if (ptr2) *ptr2 = PROTO_PATH_DELIMITER;
if (ptr) if (ptr)
{ {
*ptr = '\0'; *ptr = '\0';
@ -52,18 +52,22 @@ bool NormFile::Open(const char* thePath, int theFlags)
break; break;
} }
} }
if (ptr && ('\0' == *ptr)) *ptr++ = DIR_DELIMITER; if (ptr && ('\0' == *ptr)) *ptr++ = PROTO_PATH_DELIMITER;
while (ptr) while (ptr)
{ {
ptr = strchr(ptr, DIR_DELIMITER); ptr = strchr(ptr, PROTO_PATH_DELIMITER);
if (ptr) *ptr = '\0'; if (ptr) *ptr = '\0';
#ifdef WIN32
if (mkdir(tempPath))
#else
if (mkdir(tempPath, 0755)) if (mkdir(tempPath, 0755))
#endif // if/else WIN32/UNIX
{ {
DMSG(0, "NormFile::Rename() mkdir(%s) error: %s\n", DMSG(0, "NormFile::Rename() mkdir(%s) error: %s\n",
tempPath, strerror(errno)); tempPath, strerror(errno));
return false; return false;
} }
if (ptr) *ptr++ = DIR_DELIMITER; if (ptr) *ptr++ = PROTO_PATH_DELIMITER;
} }
} }
#ifdef WIN32 #ifdef WIN32
@ -82,8 +86,7 @@ bool NormFile::Open(const char* thePath, int theFlags)
} }
else else
{ {
DMSG(0, "Error opening file \"%s\": %s\n", path, DMSG(0, "Error opening file \"%s\": %s\n", thePath, strerror(errno));
strerror(errno));
flags = 0; flags = 0;
return false; return false;
} }
@ -159,7 +162,7 @@ bool NormFile::Rename(const char* oldName, const char* newName)
if (NormFile::IsLocked(newName)) return false; if (NormFile::IsLocked(newName)) return false;
#ifdef WIN32 #ifdef WIN32
// In Win32, the new file can't already exist // In Win32, the new file can't already exist
if (NormFile::Exists(newName) _unlink(newName); if (NormFile::Exists(newName)) _unlink(newName);
// In Win32, the old file can't be open // In Win32, the old file can't be open
int oldFlags = 0; int oldFlags = 0;
if (IsOpen()) if (IsOpen())
@ -172,14 +175,14 @@ bool NormFile::Rename(const char* oldName, const char* newName)
// Create sub-directories as needed. // Create sub-directories as needed.
char tempPath[PATH_MAX]; char tempPath[PATH_MAX];
strncpy(tempPath, newName, PATH_MAX); strncpy(tempPath, newName, PATH_MAX);
char* ptr = strrchr(tempPath, DIR_DELIMITER); char* ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
if (ptr) *ptr = '\0'; if (ptr) *ptr = '\0';
ptr = NULL; ptr = NULL;
while (!NormFile::Exists(tempPath)) while (!NormFile::Exists(tempPath))
{ {
char* ptr2 = ptr; char* ptr2 = ptr;
ptr = strrchr(tempPath, DIR_DELIMITER); ptr = strrchr(tempPath, PROTO_PATH_DELIMITER);
if (ptr2) *ptr2 = DIR_DELIMITER; if (ptr2) *ptr2 = PROTO_PATH_DELIMITER;
if (ptr) if (ptr)
{ {
*ptr = '\0'; *ptr = '\0';
@ -190,10 +193,10 @@ bool NormFile::Rename(const char* oldName, const char* newName)
break; break;
} }
} }
if (ptr && ('\0' == *ptr)) *ptr++ = DIR_DELIMITER; if (ptr && ('\0' == *ptr)) *ptr++ = PROTO_PATH_DELIMITER;
while (ptr) while (ptr)
{ {
ptr = strchr(ptr, DIR_DELIMITER); ptr = strchr(ptr, PROTO_PATH_DELIMITER);
if (ptr) *ptr = '\0'; if (ptr) *ptr = '\0';
if (mkdir(tempPath, 0755)) if (mkdir(tempPath, 0755))
{ {
@ -201,7 +204,7 @@ bool NormFile::Rename(const char* oldName, const char* newName)
tempPath, strerror(errno)); tempPath, strerror(errno));
return false; return false;
} }
if (ptr) *ptr++ = DIR_DELIMITER; if (ptr) *ptr++ = PROTO_PATH_DELIMITER;
} }
#endif // if/else WIN32 #endif // if/else WIN32
if (rename(oldName, newName)) if (rename(oldName, newName))
@ -367,7 +370,7 @@ bool NormDirectoryIterator::GetNextFile(char* fileName)
bool success = true; bool success = true;
while(success) while(success)
{ {
WIN32_findData findData; WIN32_FIND_DATA findData;
if (current->hSearch == (HANDLE)-1) if (current->hSearch == (HANDLE)-1)
{ {
// Construct search string // Construct search string
@ -387,7 +390,7 @@ bool NormDirectoryIterator::GetNextFile(char* fileName)
// Do we have a candidate file? // Do we have a candidate file?
if (success) if (success)
{ {
char* ptr = strrchr(findData.cFileName, DIR_DELIMITER); char* ptr = strrchr(findData.cFileName, PROTO_PATH_DELIMITER);
if (ptr) if (ptr)
ptr += 1; ptr += 1;
else else
@ -535,9 +538,9 @@ NormDirectoryIterator::NormDirectory::NormDirectory(const char* thePath,
{ {
strncpy(path, thePath, PATH_MAX); strncpy(path, thePath, PATH_MAX);
int len = MIN(PATH_MAX, strlen(path)); int len = MIN(PATH_MAX, strlen(path));
if ((len < PATH_MAX) && (DIR_DELIMITER != path[len-1])) if ((len < PATH_MAX) && (PROTO_PATH_DELIMITER != path[len-1]))
{ {
path[len++] = DIR_DELIMITER; path[len++] = PROTO_PATH_DELIMITER;
if (len < PATH_MAX) path[len] = '\0'; if (len < PATH_MAX) path[len] = '\0';
} }
} }
@ -551,10 +554,10 @@ bool NormDirectoryIterator::NormDirectory::Open()
{ {
Close(); // in case it's already open Close(); // in case it's already open
char fullName[PATH_MAX]; char fullName[PATH_MAX];
GetFullName(fullName); GetFullName(fullName);
// Get rid of trailing DIR_DELIMITER // Get rid of trailing PROTO_PATH_DELIMITER
int len = MIN(PATH_MAX, strlen(fullName)); int len = MIN(PATH_MAX, strlen(fullName));
if (DIR_DELIMITER == fullName[len-1]) fullName[len-1] = '\0'; if (PROTO_PATH_DELIMITER == fullName[len-1]) fullName[len-1] = '\0';
#ifdef WIN32 #ifdef WIN32
DWORD attr = GetFileAttributes(fullName); DWORD attr = GetFileAttributes(fullName);
if (0xFFFFFFFF == attr) if (0xFFFFFFFF == attr)
@ -581,8 +584,11 @@ void NormDirectoryIterator::NormDirectory::Close()
hSearch = (HANDLE)-1; hSearch = (HANDLE)-1;
} }
#else #else
closedir(dptr); if (dptr)
dptr = NULL; {
closedir(dptr);
dptr = NULL;
}
#endif // if/else WIN32 #endif // if/else WIN32
} // end NormDirectoryIterator::NormDirectory::Close() } // end NormDirectoryIterator::NormDirectory::Close()
@ -856,15 +862,15 @@ void NormFileList::GetCurrentBasePath(char* pathBuffer)
strncpy(pathBuffer, next->Path(), PATH_MAX); strncpy(pathBuffer, next->Path(), PATH_MAX);
unsigned int len = strlen(pathBuffer); unsigned int len = strlen(pathBuffer);
len = MIN(len, PATH_MAX); len = MIN(len, PATH_MAX);
if (DIR_DELIMITER != pathBuffer[len-1]) if (PROTO_PATH_DELIMITER != pathBuffer[len-1])
{ {
if (len < PATH_MAX) pathBuffer[len++] = DIR_DELIMITER; if (len < PATH_MAX) pathBuffer[len++] = PROTO_PATH_DELIMITER;
if (len < PATH_MAX) pathBuffer[len] = '\0'; if (len < PATH_MAX) pathBuffer[len] = '\0';
} }
} }
else // NormFile::NORMAL else // NormFile::NORMAL
{ {
const char* ptr = strrchr(next->Path(), DIR_DELIMITER); const char* ptr = strrchr(next->Path(), PROTO_PATH_DELIMITER);
if (ptr++) if (ptr++)
{ {
unsigned int len = ptr - next->Path(); unsigned int len = ptr - next->Path();
@ -925,6 +931,7 @@ bool NormFileList::FileItem::GetNextFile(char* thePath,
NormFileList::DirectoryItem::DirectoryItem(const char* thePath) NormFileList::DirectoryItem::DirectoryItem(const char* thePath)
: NormFileList::FileItem(thePath) : NormFileList::FileItem(thePath)
{ {
} }
NormFileList::DirectoryItem::~DirectoryItem() NormFileList::DirectoryItem::~DirectoryItem()
@ -963,9 +970,9 @@ bool NormFileList::DirectoryItem::GetNextFile(char* thePath,
strncpy(thePath, path, PATH_MAX); strncpy(thePath, path, PATH_MAX);
unsigned int len = strlen(thePath); unsigned int len = strlen(thePath);
len = MIN(len, PATH_MAX); len = MIN(len, PATH_MAX);
if ((DIR_DELIMITER != thePath[len-1]) && (len < PATH_MAX)) if ((PROTO_PATH_DELIMITER != thePath[len-1]) && (len < PATH_MAX))
{ {
thePath[len++] = DIR_DELIMITER; thePath[len++] = PROTO_PATH_DELIMITER;
if (len < PATH_MAX) thePath[len] = '\0'; if (len < PATH_MAX) thePath[len] = '\0';
} }
char tempPath[PATH_MAX]; char tempPath[PATH_MAX];

View File

@ -18,8 +18,7 @@
#include <sys/stat.h> #include <sys/stat.h>
// From PROTOLIB // From PROTOLIB
#include "sysdefs.h" // for bool definition, DIR_DELIMITER, PATH_MAX, etc #include "protokit.h" // for Protolib stuff
#include "debug.h" // for DEBUG stuff
class NormFile class NormFile
{ {
@ -61,11 +60,11 @@ class NormFile
#ifdef WIN32 #ifdef WIN32
DWORD attr = GetFileAttributes(path); DWORD attr = GetFileAttributes(path);
return ((0xFFFFFFFF == attr) ? return ((0xFFFFFFFF == attr) ?
false : (0 == (attr & FILE_ATTRIBUTE_READONLY))); false : (0 == (attr & FILE_ATTRIBUTE_READONLY)));
#else #else
return (0 == access(path, W_OK)); return (0 == access(path, W_OK));
}
#endif // if/else WIN32 #endif // if/else WIN32
}
// Members // Members
@ -73,7 +72,9 @@ class NormFile
int fd; int fd;
int flags; int flags;
off_t offset; off_t offset;
}; }; // end class NormFile
/****************************************** /******************************************
* The NormDirectory and NormDirectoryIterator classes * The NormDirectory and NormDirectoryIterator classes
@ -98,11 +99,11 @@ class NormDirectoryIterator
private: private:
char path[PATH_MAX]; char path[PATH_MAX];
NormDirectory* parent; NormDirectory* parent;
#ifdef WIN32 #ifdef WIN32
HANDLE hSearch; HANDLE hSearch;
#else #else
DIR* dptr; DIR* dptr;
#endif // if/else WIN32 #endif // if/else WIN32
NormDirectory(const char *thePath, NormDirectory* theParent = NULL); NormDirectory(const char *thePath, NormDirectory* theParent = NULL);
~NormDirectory(); ~NormDirectory();
void GetFullName(char* namePtr); void GetFullName(char* namePtr);

View File

@ -150,7 +150,7 @@ bool NormRepairRequest::AppendRepairItem(const NormObjectId& objectId,
if (buffer_len >= (length+ITEM_LIST_OFFSET+RepairItemLength())) if (buffer_len >= (length+ITEM_LIST_OFFSET+RepairItemLength()))
{ {
char* ptr = buffer + length + ITEM_LIST_OFFSET; char* ptr = buffer + length + ITEM_LIST_OFFSET;
ptr[FEC_ID_OFFSET] = 129; ptr[FEC_ID_OFFSET] = (char)129;
ptr[RESERVED_OFFSET] = 0; ptr[RESERVED_OFFSET] = 0;
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId); *((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId); *((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId);
@ -181,7 +181,7 @@ bool NormRepairRequest::AppendRepairRange(const NormObjectId& startObjectId,
{ {
// range start // range start
char* ptr = buffer + length + ITEM_LIST_OFFSET; char* ptr = buffer + length + ITEM_LIST_OFFSET;
ptr[FEC_ID_OFFSET] = 129; ptr[FEC_ID_OFFSET] = (char)129;
ptr[RESERVED_OFFSET] = 0; ptr[RESERVED_OFFSET] = 0;
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)startObjectId); *((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)startObjectId);
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)startBlockId); *((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)startBlockId);
@ -189,7 +189,7 @@ bool NormRepairRequest::AppendRepairRange(const NormObjectId& startObjectId,
*((UINT16*)(ptr+SYMBOL_ID_OFFSET)) = htons((UINT16)startSymbolId); *((UINT16*)(ptr+SYMBOL_ID_OFFSET)) = htons((UINT16)startSymbolId);
ptr += RepairItemLength(); ptr += RepairItemLength();
// range end // range end
ptr[FEC_ID_OFFSET] = 129; ptr[FEC_ID_OFFSET] = (char)129;
ptr[RESERVED_OFFSET] = 0; ptr[RESERVED_OFFSET] = 0;
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)endObjectId); *((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)endObjectId);
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)endBlockId); *((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)endBlockId);
@ -212,7 +212,7 @@ bool NormRepairRequest::AppendErasureCount(const NormObjectId& objectId,
if (buffer_len >= (ITEM_LIST_OFFSET+length+ErasureItemLength())) if (buffer_len >= (ITEM_LIST_OFFSET+length+ErasureItemLength()))
{ {
char* ptr = buffer + length + ITEM_LIST_OFFSET; char* ptr = buffer + length + ITEM_LIST_OFFSET;
ptr[FEC_ID_OFFSET] = 129; ptr[FEC_ID_OFFSET] = (char)129;
ptr[RESERVED_OFFSET] = 0; ptr[RESERVED_OFFSET] = 0;
*((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId); *((UINT16*)(ptr+OBJ_ID_OFFSET)) = htons((UINT16)objectId);
*((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId); *((UINT32*)(ptr+BLOCK_ID_OFFSET)) = htonl((UINT32)blockId);
@ -425,8 +425,6 @@ unsigned char NormQuantizeRtt(double rtt)
return ((unsigned char)(ceil(255.0 - (13.0*log(NORM_RTT_MAX/rtt))))); return ((unsigned char)(ceil(255.0 - (13.0*log(NORM_RTT_MAX/rtt)))));
} // end NormQuantizeRtt() } // end NormQuantizeRtt()
bool NormObjectSize::operator<(const NormObjectSize& size) const bool NormObjectSize::operator<(const NormObjectSize& size) const
{ {
UINT16 diff = msb - size.msb; UINT16 diff = msb - size.msb;

View File

@ -2,14 +2,12 @@
#define _NORM_MESSAGE #define _NORM_MESSAGE
// PROTOLIB includes // PROTOLIB includes
#include "networkAddress.h" // for NetworkAddress class #include "protokit.h"
#include "sysdefs.h" // for UINT typedefs
#include "debug.h"
// standard includes // standard includes
#include <string.h> // for memcpy(), etc #include <string.h> // for memcpy(), etc
#include <math.h> #include <math.h>
#include <stdlib.h> // for rand(), etc
#ifdef SIMULATE #ifdef SIMULATE
#define SIM_PAYLOAD_MAX 36 // MGEN message size #define SIM_PAYLOAD_MAX 36 // MGEN message size
@ -22,6 +20,22 @@ const UINT8 NORM_PROTOCOL_VERSION = 1;
const int NORM_ROBUST_FACTOR = 20; // default robust factor const int NORM_ROBUST_FACTOR = 20; // default robust factor
// Pick a random number from 0..max
inline double UniformRand(double max)
{
return (max * ((double)rand() / (double)RAND_MAX));
}
// Pick a random number from 0..max
// (truncated exponential dist. lambda = log(groupSize) + 1)
inline double ExponentialRand(double max, double groupSize)
{
double lambda = log(groupSize) + 1;
double x = UniformRand(lambda/max)+lambda/(max*(exp(lambda)-1));
return ((max/lambda)*log(x*(exp(lambda)-1)*(max/lambda)));
}
// These are the GRTT estimation bounds set for the current // These are the GRTT estimation bounds set for the current
// NORM protocol. (Note that our Grtt quantization routines // NORM protocol. (Note that our Grtt quantization routines
// are good for the range of 1.0e-06 <= 1000.0) // are good for the range of 1.0e-06 <= 1000.0)
@ -39,13 +53,20 @@ unsigned char NormQuantizeRtt(double rtt);
inline double NormUnquantizeGroupSize(unsigned char gsize) inline double NormUnquantizeGroupSize(unsigned char gsize)
{ {
return ((double)(gsize >> 4) * pow(10.0, (double)(gsize & 0x0f))); double exponent = (double)((gsize & 0x07) + 1);
double mantissa = (0 != (gsize & 0x08)) ? 5.0 : 1.0;
return (mantissa * pow(10.0, exponent));
} }
inline unsigned char NormQuantizeGroupSize(double gsize) inline unsigned char NormQuantizeGroupSize(double gsize)
{ {
unsigned char exponent = (unsigned char)log10(gsize); unsigned char ebits = (unsigned char)log10(gsize);
exponent = MIN(exponent, 0x0f); int mantissa = (int)((gsize/pow(10.0, (double)ebits)) + 0.5);
return ((((unsigned char)(gsize / pow(10.0, (double)exponent) + 0.5)) << 4) | exponent); // round up quantized group size
unsigned char mbit = (mantissa > 1) ? ((mantissa > 5) ? 0x00 : 0x08) : 0x00;
ebits = (mantissa > 5) ? ebits : ebits+1;
mbit = (ebits > 0x07) ? 0x08 : mbit;
ebits = (ebits > 0x07) ? 0x07 : ebits;
return (mbit | ebits);
} }
inline unsigned short NormQuantizeLoss(double lossFraction) inline unsigned short NormQuantizeLoss(double lossFraction)
@ -62,8 +83,7 @@ inline double NormUnquantizeLoss(unsigned short lossQuantized)
inline unsigned short NormQuantizeRate(double rate) inline unsigned short NormQuantizeRate(double rate)
{ {
unsigned char exponent = (unsigned short)log10(rate); unsigned char exponent = (unsigned char)log10(rate);
exponent = MIN(exponent, 0xff);
unsigned short mantissa = (unsigned short)((256.0/10.0) * rate / pow(10.0, (double)exponent)); unsigned short mantissa = (unsigned short)((256.0/10.0) * rate / pow(10.0, (double)exponent));
return ((mantissa << 8) | exponent); return ((mantissa << 8) | exponent);
} }
@ -88,7 +108,11 @@ class NormObjectSize
UINT32 LSB() const {return lsb;} UINT32 LSB() const {return lsb;}
bool operator<(const NormObjectSize& size) const; bool operator<(const NormObjectSize& size) const;
bool operator<=(const NormObjectSize& size) const
{return ((*this == size) || (*this<size));}
bool operator>(const NormObjectSize& size) const; bool operator>(const NormObjectSize& size) const;
bool operator>=(const NormObjectSize& size) const
{return ((*this == size) || (*this>size));}
bool operator==(const NormObjectSize& size) const bool operator==(const NormObjectSize& size) const
{return ((msb == size.msb) && (lsb == size.lsb));} {return ((msb == size.msb) && (lsb == size.lsb));}
bool operator!=(const NormObjectSize& size) const bool operator!=(const NormObjectSize& size) const
@ -135,7 +159,11 @@ class NormObjectId
NormObjectId(const NormObjectId& id) {value = id.value;} NormObjectId(const NormObjectId& id) {value = id.value;}
operator UINT16() const {return value;} operator UINT16() const {return value;}
bool operator<(const NormObjectId& id) const; bool operator<(const NormObjectId& id) const;
bool operator<=(const NormObjectId& id) const
{return ((value == id.value) || (*this<id));}
bool operator>(const NormObjectId& id) const; bool operator>(const NormObjectId& id) const;
bool operator>=(const NormObjectId& id) const
{return ((value == id.value) || (*this>id));}
bool operator==(const NormObjectId& id) const bool operator==(const NormObjectId& id) const
{return (value == id.value);} {return (value == id.value);}
bool operator!=(const NormObjectId& id) const bool operator!=(const NormObjectId& id) const
@ -251,7 +279,7 @@ class NormMsg
{ {
*((UINT32*)(buffer+SOURCE_ID_OFFSET)) = htonl(sourceId); *((UINT32*)(buffer+SOURCE_ID_OFFSET)) = htonl(sourceId);
} }
void SetDestination(const NetworkAddress& dst) {addr = dst;} void SetDestination(const ProtoAddress& dst) {addr = dst;}
void AttachExtension(NormHeaderExtension& extension) void AttachExtension(NormHeaderExtension& extension)
{ {
@ -272,8 +300,8 @@ class NormMsg
{ {
return (ntohl(*((UINT32*)(buffer+SOURCE_ID_OFFSET)))); return (ntohl(*((UINT32*)(buffer+SOURCE_ID_OFFSET))));
} }
const NetworkAddress& GetDestination() const {return addr;} const ProtoAddress& GetDestination() const {return addr;}
const NetworkAddress& GetSource() const {return addr;} const ProtoAddress& GetSource() const {return addr;}
const char* GetBuffer() {return buffer;} const char* GetBuffer() {return buffer;}
UINT16 GetLength() const {return length;} UINT16 GetLength() const {return length;}
@ -286,12 +314,11 @@ class NormMsg
bool result = (nextOffset < header_length); bool result = (nextOffset < header_length);
ext.AttachBuffer(result ? (buffer+nextOffset) : NULL); ext.AttachBuffer(result ? (buffer+nextOffset) : NULL);
return result; return result;
} }
// For message reception and misc. // For message reception and misc.
char* AccessBuffer() {return buffer;} char* AccessBuffer() {return buffer;}
NetworkAddress* AccessAddress() {return &addr;} ProtoAddress& AccessAddress() {return addr;}
protected: protected:
// Common message header offsets // Common message header offsets
@ -321,7 +348,7 @@ class NormMsg
UINT16 length; UINT16 length;
UINT16 header_length; UINT16 header_length;
UINT16 header_length_base; UINT16 header_length_base;
NetworkAddress addr; // src or dst address ProtoAddress addr; // src or dst address
NormMsg* prev; NormMsg* prev;
NormMsg* next; NormMsg* next;
@ -349,7 +376,8 @@ class NormObjectMsg : public NormMsg
return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET)))); return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET))));
} }
UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];} UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];}
UINT8 GetGroupSize() const {return buffer[GSIZE_OFFSET];} UINT8 GetBackoffFactor() const {return ((buffer[GSIZE_OFFSET] >> 4) & 0x0f);}
UINT8 GetGroupSize() const {return (buffer[GSIZE_OFFSET] & 0x0f);}
bool FlagIsSet(NormObjectMsg::Flag flag) const bool FlagIsSet(NormObjectMsg::Flag flag) const
{return (0 != (flag & buffer[FLAGS_OFFSET]));} {return (0 != (flag & buffer[FLAGS_OFFSET]));}
UINT8 GetFecId() const {return buffer[FEC_ID_OFFSET];} UINT8 GetFecId() const {return buffer[FEC_ID_OFFSET];}
@ -364,7 +392,14 @@ class NormObjectMsg : public NormMsg
*((UINT16*)(buffer+SESSION_ID_OFFSET)) = htons(sessionId); *((UINT16*)(buffer+SESSION_ID_OFFSET)) = htons(sessionId);
} }
void SetGrtt(UINT8 grtt) {buffer[GRTT_OFFSET] = grtt;} void SetGrtt(UINT8 grtt) {buffer[GRTT_OFFSET] = grtt;}
void SetGroupSize(UINT8 gsize) {buffer[GSIZE_OFFSET] = gsize;} void SetBackoffFactor(UINT8 backoff)
{
buffer[BACKOFF_OFFSET] = (buffer[GSIZE_OFFSET] & 0x0f) | (backoff << 4);
}
void SetGroupSize(UINT8 gsize)
{
buffer[GSIZE_OFFSET] = (buffer[GSIZE_OFFSET] & 0xf0) | gsize;
}
void ResetFlags() {buffer[FLAGS_OFFSET] = 0;} void ResetFlags() {buffer[FLAGS_OFFSET] = 0;}
void SetFlag(NormObjectMsg::Flag flag) {buffer[FLAGS_OFFSET] |= flag;} void SetFlag(NormObjectMsg::Flag flag) {buffer[FLAGS_OFFSET] |= flag;}
void SetFecId(UINT8 fecId) {buffer[FEC_ID_OFFSET] = fecId;} void SetFecId(UINT8 fecId) {buffer[FEC_ID_OFFSET] = fecId;}
@ -378,7 +413,8 @@ class NormObjectMsg : public NormMsg
{ {
SESSION_ID_OFFSET = MSG_OFFSET, SESSION_ID_OFFSET = MSG_OFFSET,
GRTT_OFFSET = SESSION_ID_OFFSET + 2, GRTT_OFFSET = SESSION_ID_OFFSET + 2,
GSIZE_OFFSET = GRTT_OFFSET + 1, BACKOFF_OFFSET = GRTT_OFFSET + 1,
GSIZE_OFFSET = BACKOFF_OFFSET,
FLAGS_OFFSET = GSIZE_OFFSET + 1, FLAGS_OFFSET = GSIZE_OFFSET + 1,
FEC_ID_OFFSET = FLAGS_OFFSET + 1, FEC_ID_OFFSET = FLAGS_OFFSET + 1,
OBJ_ID_OFFSET = FEC_ID_OFFSET + 1, OBJ_ID_OFFSET = FEC_ID_OFFSET + 1,
@ -448,11 +484,11 @@ class NormFtiExtension : public NormHeaderExtension
private: private:
enum enum
{ {
FEC_INSTANCE_OFFSET = LENGTH_OFFSET + 1, OBJ_SIZE_OFFSET = LENGTH_OFFSET + 1,
FEC_NDATA_OFFSET = FEC_INSTANCE_OFFSET +2, FEC_INSTANCE_OFFSET = OBJ_SIZE_OFFSET + 6,
FEC_NPARITY_OFFSET = FEC_NDATA_OFFSET + 2, SEG_SIZE_OFFSET = FEC_INSTANCE_OFFSET +2,
SEG_SIZE_OFFSET = FEC_NPARITY_OFFSET+2, FEC_NDATA_OFFSET = SEG_SIZE_OFFSET + 2,
OBJ_SIZE_OFFSET = SEG_SIZE_OFFSET + 2 FEC_NPARITY_OFFSET = FEC_NDATA_OFFSET + 2
}; };
}; // end class NormFtiExtension }; // end class NormFtiExtension
@ -617,23 +653,32 @@ class NormCmdMsg : public NormMsg
} }
void SetGrtt(UINT8 quantizedGrtt) void SetGrtt(UINT8 quantizedGrtt)
{buffer[GRTT_OFFSET] = quantizedGrtt;} {buffer[GRTT_OFFSET] = quantizedGrtt;}
void SetGroupSize(UINT8 quantizedGroupSize) void SetBackoffFactor(UINT8 backoff)
{buffer[GSIZE_OFFSET] = quantizedGroupSize;} {
buffer[BACKOFF_OFFSET] = (buffer[GSIZE_OFFSET] & 0x0f) | (backoff << 4);
}
void SetGroupSize(UINT8 gsize)
{
buffer[GSIZE_OFFSET] = (buffer[GSIZE_OFFSET] & 0xf0) | gsize;
}
void SetFlavor(NormCmdMsg::Flavor flavor) void SetFlavor(NormCmdMsg::Flavor flavor)
{buffer[FLAVOR_OFFSET] = flavor;} {buffer[FLAVOR_OFFSET] = flavor;}
// Message processing // Message processing
UINT16 GetSessionId() const {return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET))));} UINT16 GetSessionId() const {return (ntohs(*((UINT16*)(buffer+SESSION_ID_OFFSET))));}
UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];} UINT8 GetGrtt() const {return buffer[GRTT_OFFSET];}
UINT8 GetGroupSize() const {return buffer[GSIZE_OFFSET];} UINT8 GetBackoffFactor() const {return ((buffer[GSIZE_OFFSET] >> 4) & 0x0f);}
UINT8 GetGroupSize() const {return (buffer[GSIZE_OFFSET] & 0x0f);}
NormCmdMsg::Flavor GetFlavor() const {return (Flavor)buffer[FLAVOR_OFFSET];} NormCmdMsg::Flavor GetFlavor() const {return (Flavor)buffer[FLAVOR_OFFSET];}
protected: protected:
friend class NormMsg;
enum enum
{ {
SESSION_ID_OFFSET = MSG_OFFSET, SESSION_ID_OFFSET = MSG_OFFSET,
GRTT_OFFSET = SESSION_ID_OFFSET + 2, GRTT_OFFSET = SESSION_ID_OFFSET + 2,
GSIZE_OFFSET = GRTT_OFFSET + 1, BACKOFF_OFFSET = GRTT_OFFSET + 1,
GSIZE_OFFSET = BACKOFF_OFFSET,
FLAVOR_OFFSET = GSIZE_OFFSET + 1 FLAVOR_OFFSET = GSIZE_OFFSET + 1
}; };
}; // end class NormCmdMsg }; // end class NormCmdMsg

View File

@ -37,12 +37,18 @@ NormServerNode::NormServerNode(class NormSession* theSession, NormNodeId nodeId)
recv_total(0), recv_goodput(0), resync_count(0), recv_total(0), recv_goodput(0), resync_count(0),
nack_count(0), suppress_count(0), completion_count(0), failure_count(0) nack_count(0), suppress_count(0), completion_count(0), failure_count(0)
{ {
repair_timer.Init(0.0, 1, (ProtocolTimerOwner*)this, repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnRepairTimeout);
(ProtocolTimeoutFunc)&NormServerNode::OnRepairTimeout); repair_timer.SetInterval(0.0);
activity_timer.Init(0.0, -1, (ProtocolTimerOwner*)this, repair_timer.SetRepeat(1);
(ProtocolTimeoutFunc)&NormServerNode::OnActivityTimeout);
cc_timer.Init(0.0, 1, (ProtocolTimerOwner*)this, activity_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnActivityTimeout);
(ProtocolTimeoutFunc)&NormServerNode::OnCCTimeout); activity_timer.SetInterval(NormSession::DEFAULT_GRTT_ESTIMATE*NORM_ROBUST_FACTOR);
activity_timer.SetRepeat(NORM_ROBUST_FACTOR);
cc_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormServerNode::OnCCTimeout);
cc_timer.SetInterval(0.0);
cc_timer.SetRepeat(1);
grtt_send_time.tv_sec = 0; grtt_send_time.tv_sec = 0;
grtt_send_time.tv_usec = 0; grtt_send_time.tv_usec = 0;
grtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE); grtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE);
@ -50,6 +56,8 @@ NormServerNode::NormServerNode(class NormSession* theSession, NormNodeId nodeId)
gsize_quantized = NormQuantizeGroupSize(NormSession::DEFAULT_GSIZE_ESTIMATE); gsize_quantized = NormQuantizeGroupSize(NormSession::DEFAULT_GSIZE_ESTIMATE);
gsize_estimate = NormUnquantizeGroupSize(gsize_quantized); gsize_estimate = NormUnquantizeGroupSize(gsize_quantized);
backoff_factor = NormSession::DEFAULT_BACKOFF_FACTOR;
rtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE); rtt_quantized = NormQuantizeRtt(NormSession::DEFAULT_GRTT_ESTIMATE);
rtt_estimate = NormUnquantizeRtt(rtt_quantized); rtt_estimate = NormUnquantizeRtt(rtt_quantized);
@ -142,6 +150,7 @@ bool NormServerNode::Open(UINT16 sessionId, UINT16 segmentSize, UINT16 numData,
void NormServerNode::Close() void NormServerNode::Close()
{ {
if (activity_timer.IsActive()) activity_timer.Deactivate();
decoder.Destroy(); decoder.Destroy();
if (erasure_loc) if (erasure_loc)
{ {
@ -169,9 +178,9 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
grtt_quantized = grttQuantized; grtt_quantized = grttQuantized;
grtt_estimate = NormUnquantizeRtt(grttQuantized); grtt_estimate = NormUnquantizeRtt(grttQuantized);
DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new grtt: %lf sec\n", DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new grtt: %lf sec\n",
LocalNodeId(), Id(), grtt_estimate); LocalNodeId(), GetId(), grtt_estimate);
activity_timer.SetInterval(grtt_estimate); activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
activity_timer.Reset(); if (activity_timer.IsActive()) activity_timer.Reschedule();
} }
UINT8 gsizeQuantized = cmd.GetGroupSize(); UINT8 gsizeQuantized = cmd.GetGroupSize();
if (gsizeQuantized != gsize_quantized) if (gsizeQuantized != gsize_quantized)
@ -179,8 +188,9 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
gsize_quantized = gsizeQuantized; gsize_quantized = gsizeQuantized;
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized); gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new group size:%lf\n", DMSG(4, "NormServerNode::HandleCommand() node>%lu server>%lu new group size:%lf\n",
LocalNodeId(), Id(), gsize_estimate); LocalNodeId(), GetId(), gsize_estimate);
} }
backoff_factor = (double)cmd.GetBackoffFactor();
NormCmdMsg::Flavor flavor = cmd.GetFlavor(); NormCmdMsg::Flavor flavor = cmd.GetFlavor();
switch (flavor) switch (flavor)
@ -255,8 +265,8 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
{ {
// Respond immediately // Respond immediately
if (cc_timer.IsActive()) cc_timer.Deactivate(); if (cc_timer.IsActive()) cc_timer.Deactivate();
cc_timer.ResetRepeats(); cc_timer.ResetRepeat();
OnCCTimeout(); OnCCTimeout(cc_timer);
} }
else if (!cc_timer.IsActive()) else if (!cc_timer.IsActive())
{ {
@ -292,7 +302,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
cc_timer.SetInterval(backoffTime); cc_timer.SetInterval(backoffTime);
DMSG(4, "NormServerNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n", DMSG(4, "NormServerNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
LocalNodeId(), backoffTime); LocalNodeId(), backoffTime);
session->InstallTimer(&cc_timer); session->ActivateTimer(cc_timer);
} }
} // end if (CC_RATE == ext.GetType()) } // end if (CC_RATE == ext.GetType())
} // end while (GetNextExtension()) } // end while (GetNextExtension())
@ -316,7 +326,8 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
{ {
const NormCmdRepairAdvMsg& repairAdv = (const NormCmdRepairAdvMsg&)cmd; const NormCmdRepairAdvMsg& repairAdv = (const NormCmdRepairAdvMsg&)cmd;
// Does the CC feedback of this ACK suppress our CC feedback // Does the CC feedback of this ACK suppress our CC feedback
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.RepeatCount()) if (!is_clr && !is_plr && cc_timer.IsActive() &&
cc_timer.GetRepeatCount())
{ {
NormCCFeedbackExtension ext; NormCCFeedbackExtension ext;
while (repairAdv.GetNextExtension(ext)) while (repairAdv.GetNextExtension(ext))
@ -328,7 +339,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
} }
} }
} }
if (repair_timer.IsActive() && repair_timer.RepeatCount()) if (repair_timer.IsActive() && repair_timer.GetRepeatCount())
{ {
HandleRepairContent(repairAdv.GetRepairContent(), HandleRepairContent(repairAdv.GetRepairContent(),
repairAdv.GetRepairContentLength()); repairAdv.GetRepairContentLength());
@ -345,7 +356,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate) void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
{ {
ASSERT(cc_timer.IsActive() && cc_timer.RepeatCount()); ASSERT(cc_timer.IsActive() && cc_timer.GetRepeatCount());
if (0 == (ccFlags & NormCC::CLR)) if (0 == (ccFlags & NormCC::CLR))
{ {
// We're suppressed by non-CLR receivers with no RTT confirmed // We're suppressed by non-CLR receivers with no RTT confirmed
@ -386,7 +397,7 @@ void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
{ {
if (cc_timer.IsActive()) cc_timer.Deactivate(); if (cc_timer.IsActive()) cc_timer.Deactivate();
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor()); cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
session->InstallTimer(&cc_timer); session->ActivateTimer(cc_timer);
cc_timer.DecrementRepeatCount(); cc_timer.DecrementRepeatCount();
} }
} }
@ -395,7 +406,7 @@ void NormServerNode::HandleCCFeedback(UINT8 ccFlags, double ccRate)
void NormServerNode::HandleAckMessage(const NormAckMsg& ack) void NormServerNode::HandleAckMessage(const NormAckMsg& ack)
{ {
// Does the CC feedback of this ACK suppress our CC feedback // Does the CC feedback of this ACK suppress our CC feedback
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.RepeatCount()) if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.GetRepeatCount())
{ {
NormCCFeedbackExtension ext; NormCCFeedbackExtension ext;
while (ack.GetNextExtension(ext)) while (ack.GetNextExtension(ext))
@ -412,7 +423,7 @@ void NormServerNode::HandleAckMessage(const NormAckMsg& ack)
void NormServerNode::HandleNackMessage(const NormNackMsg& nack) void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
{ {
// Does the CC feedback of this NACK suppress our CC feedback // Does the CC feedback of this NACK suppress our CC feedback
if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.RepeatCount()) if (!is_clr && !is_plr && cc_timer.IsActive() && cc_timer.GetRepeatCount())
{ {
NormCCFeedbackExtension ext; NormCCFeedbackExtension ext;
while (nack.GetNextExtension(ext)) while (nack.GetNextExtension(ext))
@ -425,7 +436,7 @@ void NormServerNode::HandleNackMessage(const NormNackMsg& nack)
} }
} }
// Clients also care about recvd NACKS for NACK suppression // Clients also care about recvd NACKS for NACK suppression
if (repair_timer.IsActive() && repair_timer.RepeatCount()) if (repair_timer.IsActive() && repair_timer.GetRepeatCount())
HandleRepairContent(nack.GetRepairContent(), nack.GetRepairContentLength()); HandleRepairContent(nack.GetRepairContent(), nack.GetRepairContentLength());
} // end NormServerNode::HandleNackMessage() } // end NormServerNode::HandleNackMessage()
@ -441,7 +452,7 @@ void NormServerNode::HandleRepairContent(const char* buffer, UINT16 bufferLen)
NormObjectId prevObjectId; NormObjectId prevObjectId;
NormObject* object = NULL; NormObject* object = NULL;
bool freshBlock = true; bool freshBlock = true;
NormBlockId prevBlockId; NormBlockId prevBlockId = 0;
NormBlock* block = NULL; NormBlock* block = NULL;
while ((requestLength = req.Unpack(buffer, bufferLen))) while ((requestLength = req.Unpack(buffer, bufferLen)))
{ {
@ -670,9 +681,9 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
grtt_quantized = grttQuantized; grtt_quantized = grttQuantized;
grtt_estimate = NormUnquantizeRtt(grttQuantized); grtt_estimate = NormUnquantizeRtt(grttQuantized);
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new grtt: %lf sec\n", DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new grtt: %lf sec\n",
LocalNodeId(), Id(), grtt_estimate); LocalNodeId(), GetId(), grtt_estimate);
activity_timer.SetInterval(grtt_estimate); activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
activity_timer.Reset(); if (activity_timer.IsActive()) activity_timer.Reschedule();
} }
UINT8 gsizeQuantized = msg.GetGroupSize(); UINT8 gsizeQuantized = msg.GetGroupSize();
if (gsizeQuantized != gsize_quantized) if (gsizeQuantized != gsize_quantized)
@ -680,8 +691,9 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
gsize_quantized = gsizeQuantized; gsize_quantized = gsizeQuantized;
gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized); gsize_estimate = NormUnquantizeGroupSize(gsizeQuantized);
DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new group size: %lf\n", DMSG(4, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new group size: %lf\n",
LocalNodeId(), Id(), gsize_estimate); LocalNodeId(), GetId(), gsize_estimate);
} }
backoff_factor = (double)msg.GetBackoffFactor();
if (IsOpen()) if (IsOpen())
@ -689,7 +701,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
if (msg.GetSessionId() != session_id) if (msg.GetSessionId() != session_id)
{ {
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu server>%lu sessionId change - resyncing.\n", DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu server>%lu sessionId change - resyncing.\n",
LocalNodeId(), Id()); LocalNodeId(), GetId());
Close(); Close();
resync_count++; resync_count++;
} }
@ -711,7 +723,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
fti.GetFecNumParity())) fti.GetFecNumParity()))
{ {
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu open error\n", DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu open error\n",
LocalNodeId(), Id()); LocalNodeId(), GetId());
// (TBD) notify app of error ?? // (TBD) notify app of error ??
return; return;
} }
@ -721,7 +733,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
if (!IsOpen()) if (!IsOpen())
{ {
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu - no FTI provided!\n", DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu - no FTI provided!\n",
LocalNodeId(), Id()); LocalNodeId(), GetId());
// (TBD) notify app of error ?? // (TBD) notify app of error ??
return; return;
} }
@ -770,7 +782,8 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
switch (status) switch (status)
{ {
case OBJ_PENDING: case OBJ_PENDING:
if ((obj = rx_table.Find(objectId))) break; if ((obj = rx_table.Find(objectId)))
break;
case OBJ_NEW: case OBJ_NEW:
{ {
if (msg.FlagIsSet(NormObjectMsg::FLAG_STREAM)) if (msg.FlagIsSet(NormObjectMsg::FLAG_STREAM))
@ -816,7 +829,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
((NormStreamObject*)obj)->StreamUpdateStatus(blockId); ((NormStreamObject*)obj)->StreamUpdateStatus(blockId);
rx_table.Insert(obj); rx_table.Insert(obj);
DMSG(8, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new obj>%hu\n", DMSG(8, "NormServerNode::HandleObjectMessage() node>%lu server>%lu new obj>%hu\n",
LocalNodeId(), Id(), (UINT16)objectId); LocalNodeId(), GetId(), (UINT16)objectId);
} }
else else
{ {
@ -835,7 +848,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
if (obj && !obj->IsOpen()) if (obj && !obj->IsOpen())
{ {
DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu " DMSG(0, "NormServerNode::HandleObjectMessage() node>%lu server>%lu "
"new obj>%hu - no FTI provided!\n", LocalNodeId(), Id(), (UINT16)objectId); "new obj>%hu - no FTI provided!\n", LocalNodeId(), GetId(), (UINT16)objectId);
DeleteObject(obj); DeleteObject(obj);
obj = NULL; obj = NULL;
} }
@ -855,7 +868,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
obj->HandleObjectMessage(msg, msgType, blockId, segmentId); obj->HandleObjectMessage(msg, msgType, blockId, segmentId);
if (!obj->IsPending()) if (!obj->IsPending())
{ {
// Reliable reception of this object has completed
if (NormObject::FILE == obj->GetType()) if (NormObject::FILE == obj->GetType())
#ifdef SIMULATE #ifdef SIMULATE
((NormSimObject*)obj)->Close(); ((NormSimObject*)obj)->Close();
@ -870,8 +883,7 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
completion_count++; completion_count++;
} }
} }
} }
RepairCheck(NormObject::TO_BLOCK, objectId, blockId, segmentId); RepairCheck(NormObject::TO_BLOCK, objectId, blockId, segmentId);
} // end NormServerNode::HandleObjectMessage() } // end NormServerNode::HandleObjectMessage()
@ -897,8 +909,8 @@ void NormServerNode::Sync(NormObjectId objectId)
{ {
if (rx_pending_mask.IsSet()) if (rx_pending_mask.IsSet())
{ {
NormObjectId firstSet = NormObjectId(rx_pending_mask.FirstSet()); NormObjectId firstSet = NormObjectId((UINT16)rx_pending_mask.FirstSet());
if ((objectId > NormObjectId(rx_pending_mask.LastSet())) || if ((objectId > NormObjectId((UINT16)rx_pending_mask.LastSet())) ||
((next_id - objectId) > 256)) ((next_id - objectId) > 256))
{ {
NormObject* obj; NormObject* obj;
@ -949,7 +961,7 @@ NormServerNode::ObjectStatus NormServerNode::UpdateSyncStatus(const NormObjectId
// or revert to fresh sync if sync is totally lost, // or revert to fresh sync if sync is totally lost,
// otherwise SQUELCH process will get things in order // otherwise SQUELCH process will get things in order
DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu re-syncing to server>%lu...\n", DMSG(2, "NormServerNode::HandleObjectMessage() node>%lu re-syncing to server>%lu...\n",
LocalNodeId(), Id()); LocalNodeId(), GetId());
Sync(objectId); Sync(objectId);
resync_count++; resync_count++;
status = OBJ_NEW; status = OBJ_NEW;
@ -975,7 +987,7 @@ void NormServerNode::SetPending(NormObjectId objectId)
rx_pending_mask.SetBits(next_id, objectId - next_id + 1); rx_pending_mask.SetBits(next_id, objectId - next_id + 1);
next_id = objectId + 1; next_id = objectId + 1;
// This prevents the "sync_id" from getting stale // This prevents the "sync_id" from getting stale
sync_id = rx_pending_mask.FirstSet(); sync_id = (UINT16)rx_pending_mask.FirstSet();
} }
} // end NormServerNode::SetPending() } // end NormServerNode::SetPending()
@ -1024,7 +1036,7 @@ NormServerNode::ObjectStatus NormServerNode::GetObjectStatus(const NormObjectId&
else else
{ {
NormObjectId delta = objectId - next_id + 1; NormObjectId delta = objectId - next_id + 1;
if (delta > NormObjectId(rx_pending_mask.Size())) if (delta > NormObjectId((UINT16)rx_pending_mask.Size()))
{ {
return OBJ_INVALID; return OBJ_INVALID;
} }
@ -1056,8 +1068,8 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
if (rx_pending_mask.IsSet()) if (rx_pending_mask.IsSet())
{ {
if (rx_repair_mask.IsSet()) rx_repair_mask.Clear(); if (rx_repair_mask.IsSet()) rx_repair_mask.Clear();
NormObjectId nextId = rx_pending_mask.FirstSet(); NormObjectId nextId = (UINT16)rx_pending_mask.FirstSet();
NormObjectId lastId = rx_pending_mask.LastSet(); NormObjectId lastId = (UINT16)rx_pending_mask.LastSet();
if (objectId < lastId) lastId = objectId; if (objectId < lastId) lastId = objectId;
while (nextId <= lastId) while (nextId <= lastId)
{ {
@ -1077,7 +1089,7 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
startTimer = true; startTimer = true;
} }
nextId++; nextId++;
nextId = rx_pending_mask.NextSet(nextId); nextId = (UINT16)rx_pending_mask.NextSet(nextId);
} }
current_object_id = objectId; current_object_id = objectId;
if (startTimer) if (startTimer)
@ -1090,11 +1102,11 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
repair_timer.SetInterval(backoffInterval); repair_timer.SetInterval(backoffInterval);
DMSG(3, "NormServerNode::RepairCheck() node>%lu begin NACK back-off: %lf sec)...\n", DMSG(3, "NormServerNode::RepairCheck() node>%lu begin NACK back-off: %lf sec)...\n",
LocalNodeId(), backoffInterval); LocalNodeId(), backoffInterval);
session->InstallTimer(&repair_timer); session->ActivateTimer(repair_timer);
} }
} }
} }
else if (repair_timer.RepeatCount()) else if (repair_timer.GetRepeatCount())
{ {
// Repair timer in backoff phase // Repair timer in backoff phase
// Trim server current transmit position reference // Trim server current transmit position reference
@ -1115,7 +1127,7 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
if (rewindDetected) if (rewindDetected)
{ {
repair_timer.Deactivate(); repair_timer.Deactivate();
DMSG(0, "NormServerNode::RepairCheck() node>%lu server rewind detected, ending NACK hold-off ...\n", DMSG(4, "NormServerNode::RepairCheck() node>%lu server rewind detected, ending NACK hold-off ...\n",
LocalNodeId()); LocalNodeId());
RepairCheck(checkLevel, objectId, blockId, segmentId); RepairCheck(checkLevel, objectId, blockId, segmentId);
@ -1125,10 +1137,10 @@ void NormServerNode::RepairCheck(NormObject::CheckLevel checkLevel,
// When repair timer fires, possibly build a NACK // When repair timer fires, possibly build a NACK
// and queue for transmission to this server node // and queue for transmission to this server node
bool NormServerNode::OnRepairTimeout() bool NormServerNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
{ {
switch(repair_timer.RepeatCount()) switch(repair_timer.GetRepeatCount())
{ {
case 0: // hold-off time complete case 0: // hold-off time complete
DMSG(4, "NormServerNode::OnRepairTimeout() node>%lu end NACK hold-off ...\n", DMSG(4, "NormServerNode::OnRepairTimeout() node>%lu end NACK hold-off ...\n",
@ -1143,8 +1155,8 @@ bool NormServerNode::OnRepairTimeout()
if (rx_pending_mask.IsSet()) if (rx_pending_mask.IsSet())
{ {
bool repairPending = false; bool repairPending = false;
NormObjectId nextId = rx_pending_mask.FirstSet(); NormObjectId nextId = (UINT16)rx_pending_mask.FirstSet();
NormObjectId lastId = rx_pending_mask.LastSet(); NormObjectId lastId = (UINT16)rx_pending_mask.LastSet();
if (current_object_id < lastId) lastId = current_object_id; if (current_object_id < lastId) lastId = current_object_id;
while (nextId <= lastId) while (nextId <= lastId)
{ {
@ -1158,7 +1170,7 @@ bool NormServerNode::OnRepairTimeout()
} }
} }
nextId++; nextId++;
nextId = rx_pending_mask.NextSet(nextId); nextId = (UINT16)rx_pending_mask.NextSet(nextId);
} // end while (nextId <= current_block_id) } // end while (nextId <= current_block_id)
if (repairPending) if (repairPending)
{ {
@ -1208,7 +1220,7 @@ bool NormServerNode::OnRepairTimeout()
{ {
cc_timer.Deactivate(); cc_timer.Deactivate();
cc_timer.SetInterval(grtt_estimate*session->BackoffFactor()); cc_timer.SetInterval(grtt_estimate*session->BackoffFactor());
session->InstallTimer(&cc_timer); session->ActivateTimer(cc_timer);
cc_timer.DecrementRepeatCount(); cc_timer.DecrementRepeatCount();
} }
} }
@ -1217,8 +1229,8 @@ bool NormServerNode::OnRepairTimeout()
NormObjectId prevId; NormObjectId prevId;
UINT16 reqCount = 0; UINT16 reqCount = 0;
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID; NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
nextId = rx_pending_mask.FirstSet(); nextId = (UINT16)rx_pending_mask.FirstSet();
lastId = rx_pending_mask.LastSet(); lastId = (UINT16)rx_pending_mask.LastSet();
if (max_pending_object < lastId) lastId = max_pending_object; if (max_pending_object < lastId) lastId = max_pending_object;
lastId++; // force loop to fully flush nack building. lastId++; // force loop to fully flush nack building.
while ((nextId <= lastId) || (reqCount > 0)) while ((nextId <= lastId) || (reqCount > 0))
@ -1298,12 +1310,12 @@ bool NormServerNode::OnRepairTimeout()
} }
nextId++; nextId++;
if (nextId <= lastId) if (nextId <= lastId)
nextId = rx_pending_mask.NextSet(nextId); nextId = (UINT16)rx_pending_mask.NextSet(nextId);
} // end while(nextId <= lastId) } // end while(nextId <= lastId)
if (NormRepairRequest::INVALID != prevForm) if (NormRepairRequest::INVALID != prevForm)
nack->PackRepairRequest(req); // (TBD) error check nack->PackRepairRequest(req); // (TBD) error check
// Queue NACK for transmission // Queue NACK for transmission
nack->SetServerId(Id()); nack->SetServerId(GetId());
nack->SetSessionId(session_id); nack->SetSessionId(session_id);
// GRTT response is deferred until transmit time // GRTT response is deferred until transmit time
@ -1382,29 +1394,30 @@ void NormServerNode::Activate()
{ {
if (activity_timer.IsActive()) if (activity_timer.IsActive())
{ {
activity_timer.ResetRepeats(); activity_timer.ResetRepeat();
} }
else else
{ {
activity_timer.SetInterval(grtt_estimate); activity_timer.SetInterval(grtt_estimate*NORM_ROBUST_FACTOR);
session->InstallTimer(&activity_timer); session->ActivateTimer(activity_timer);
} }
} // end NormServerNode::Activate() } // end NormServerNode::Activate()
bool NormServerNode::OnActivityTimeout() bool NormServerNode::OnActivityTimeout(ProtoTimer& /*theTimer*/)
{ {
if ((activity_timer.Repeats() - activity_timer.RepeatCount()) > 1) if ((activity_timer.GetRepeat() - activity_timer.GetRepeatCount()) > 1)
{ {
DMSG(4, "NormServerNode::OnActivityTimeout() node>%lu for server>%lu\n", DMSG(4, "NormServerNode::OnActivityTimeout() node>%lu for server>%lu\n",
LocalNodeId(), Id()); LocalNodeId(), GetId());
struct timeval currentTime; struct timeval currentTime;
::GetSystemTime(&currentTime); ::ProtoSystemTime(currentTime);
UpdateRecvRate(currentTime, 0); UpdateRecvRate(currentTime, 0);
} }
if (!activity_timer.RepeatCount()) if (0 == activity_timer.GetRepeatCount())
{ {
DMSG(0, "NormServerNode::OnActivityTimeout() node>%lu server>%lu gone inactive?\n", DMSG(0, "NormServerNode::OnActivityTimeout() node>%lu server>%lu gone inactive?\n",
LocalNodeId(), Id()); LocalNodeId(), GetId());
Close();
} }
return true; return true;
} // end NormServerNode::OnActivityTimeout() } // end NormServerNode::OnActivityTimeout()
@ -1427,10 +1440,10 @@ bool NormServerNode::UpdateLossEstimate(const struct timeval& currentTime,
return result; return result;
} }
bool NormServerNode::OnCCTimeout() bool NormServerNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
{ {
// Build and queue ACK() // Build and queue ACK()
switch (cc_timer.RepeatCount()) switch (cc_timer.GetRepeatCount())
{ {
case 0: case 0:
// "hold-off" time has ended // "hold-off" time has ended
@ -1448,7 +1461,7 @@ bool NormServerNode::OnCCTimeout()
return false; return false;
} }
ack->Init(); ack->Init();
ack->SetServerId(Id()); ack->SetServerId(GetId());
ack->SetSessionId(session_id); ack->SetSessionId(session_id);
ack->SetAckType(NormAck::CC); ack->SetAckType(NormAck::CC);
ack->SetAckId(0); ack->SetAckId(0);
@ -1522,7 +1535,7 @@ NormNodeTree::~NormNodeTree()
} }
NormNode *NormNodeTree::FindNodeById(unsigned long nodeId) const NormNode *NormNodeTree::FindNodeById(NormNodeId nodeId) const
{ {
NormNode* x = root; NormNode* x = root;
while(x && (x->id != nodeId)) while(x && (x->id != nodeId))
@ -1854,7 +1867,8 @@ double NormLossEstimator::LossFraction()
double s0 = 0.0; double s0 = 0.0;
const double* wptr = weight; const double* wptr = weight;
const unsigned int* h = history; const unsigned int* h = history;
for (unsigned int i = 0; i < DEPTH; i++) unsigned int i;
for (i = 0; i < DEPTH; i++)
{ {
if (0 == *h) break; if (0 == *h) break;
s0 += *wptr * *h++; s0 += *wptr * *h++;
@ -1866,7 +1880,7 @@ double NormLossEstimator::LossFraction()
double s1 = 0.0; double s1 = 0.0;
wptr = weight; wptr = weight;
h = history + 1; h = history + 1;
for (unsigned int i = 0; i < DEPTH; i++) for (i = 0; i < DEPTH; i++)
{ {
if (0 == *h) break; if (0 == *h) break;
s1 += *wptr * *h++; // ave loss interval w/out current interval s1 += *wptr * *h++; // ave loss interval w/out current interval

View File

@ -4,7 +4,8 @@
#include "normMessage.h" #include "normMessage.h"
#include "normObject.h" #include "normObject.h"
#include "normEncoder.h" #include "normEncoder.h"
#include "protocolTimer.h" #include "protokit.h"
class NormNode class NormNode
{ {
friend class NormNodeTree; friend class NormNodeTree;
@ -16,28 +17,22 @@ class NormNode
NormNode(class NormSession* theSession, NormNodeId nodeId); NormNode(class NormSession* theSession, NormNodeId nodeId);
virtual ~NormNode(); virtual ~NormNode();
void SetAddress(const NetworkAddress& address) {addr = address;} const ProtoAddress& GetAddress() const {return addr;}
const NetworkAddress& GetAddress() const {return addr;} void SetAddress(const ProtoAddress& address) {addr = address;}
const NormNodeId& GetId() const {return id;}
const NormNodeId& Id() const {return id;}
inline const NormNodeId& LocalNodeId() const;
void SetId(const NormNodeId& nodeId) {id = nodeId;} void SetId(const NormNodeId& nodeId) {id = nodeId;}
inline const NormNodeId& LocalNodeId() const;
protected: protected:
class NormSession* session; class NormSession* session;
private: private:
NormNodeId id; NormNodeId id;
NetworkAddress addr; ProtoAddress addr;
// We keep NormNodes in a binary tree
NormNode* parent; NormNode* parent;
NormNode* right; NormNode* right;
NormNode* left; NormNode* left;
//NormNode* prev;
//NormNode* next;
}; // end class NormNode }; // end class NormNode
// Weighted-history loss event estimator // Weighted-history loss event estimator
@ -156,7 +151,7 @@ class NormCCNode : public NormNode
double GetRtt() const {return rtt;} double GetRtt() const {return rtt;}
double GetLoss() const {return loss;} double GetLoss() const {return loss;}
double GetRate() const {return rate;} double GetRate() const {return rate;}
UINT8 GetCCSequence() const {return cc_sequence;} UINT16 GetCCSequence() const {return cc_sequence;}
void SetActive(bool state) {is_active = state;} void SetActive(bool state) {is_active = state;}
void SetClrStatus(bool state) {is_clr = state;} void SetClrStatus(bool state) {is_clr = state;}
@ -169,7 +164,7 @@ class NormCCNode : public NormNode
} }
void SetLoss(double value) {loss = value;} void SetLoss(double value) {loss = value;}
void SetRate(double value) {rate = value;} void SetRate(double value) {rate = value;}
void SetCCSequence(UINT8 value) {cc_sequence = value;} void SetCCSequence(UINT16 value) {cc_sequence = value;}
private: private:
bool is_clr; // true if worst path representative bool is_clr; // true if worst path representative
@ -179,7 +174,7 @@ class NormCCNode : public NormNode
double rtt; // in seconds double rtt; // in seconds
double loss; // loss fraction double loss; // loss fraction
double rate; // in bytes per second double rate; // in bytes per second
UINT8 cc_sequence; UINT16 cc_sequence;
}; // end class NormCCNode }; // end class NormCCNode
class NormServerNode : public NormNode class NormServerNode : public NormNode
@ -275,9 +270,9 @@ class NormServerNode : public NormNode
NormBlockId blockId, NormBlockId blockId,
NormSegmentId segmentId); NormSegmentId segmentId);
bool OnActivityTimeout(); bool OnActivityTimeout(ProtoTimer& theTimer);
bool OnRepairTimeout(); bool OnRepairTimeout(ProtoTimer& theTimer);
bool OnCCTimeout(); bool OnCCTimeout(ProtoTimer& theTimer);
void HandleRepairContent(const char* buffer, UINT16 bufferLen); void HandleRepairContent(const char* buffer, UINT16 bufferLen);
UINT16 session_id; UINT16 session_id;
@ -298,25 +293,26 @@ class NormServerNode : public NormNode
NormDecoder decoder; NormDecoder decoder;
UINT16* erasure_loc; UINT16* erasure_loc;
ProtocolTimer activity_timer; ProtoTimer activity_timer;
ProtocolTimer repair_timer; ProtoTimer repair_timer;
NormObjectId current_object_id; // index for suppression NormObjectId current_object_id; // index for suppression
NormObjectId max_pending_object; // index for NACK construction NormObjectId max_pending_object; // index for NACK construction
// Remote server grtt measurement state
double grtt_estimate; double grtt_estimate;
UINT8 grtt_quantized; UINT8 grtt_quantized;
struct timeval grtt_send_time; struct timeval grtt_send_time;
struct timeval grtt_recv_time; struct timeval grtt_recv_time;
double gsize_estimate; double gsize_estimate;
UINT8 gsize_quantized; UINT8 gsize_quantized;
double backoff_factor;
// Congestion control state // Remote server congestion control state
NormLossEstimator2 loss_estimator; NormLossEstimator2 loss_estimator;
//NormLossEstimator loss_estimator; UINT16 cc_sequence;
UINT8 cc_sequence;
bool cc_enable; bool cc_enable;
double cc_rate; // ccRate at start of cc_timer double cc_rate; // ccRate at start of cc_timer
ProtocolTimer cc_timer; ProtoTimer cc_timer;
double rtt_estimate; double rtt_estimate;
UINT8 rtt_quantized; UINT8 rtt_quantized;
bool rtt_confirmed; bool rtt_confirmed;
@ -330,13 +326,13 @@ class NormServerNode : public NormNode
double nominal_packet_size; double nominal_packet_size;
// For statistics tracking // For statistics tracking
unsigned long recv_total; // total recvd accumulator unsigned long recv_total; // total recvd accumulator
unsigned long recv_goodput; // goodput recvd accumulator unsigned long recv_goodput; // goodput recvd accumulator
unsigned long resync_count; unsigned long resync_count;
unsigned long nack_count; unsigned long nack_count;
unsigned long suppress_count; unsigned long suppress_count;
unsigned long completion_count; unsigned long completion_count;
unsigned long failure_count; // due to re-syncs unsigned long failure_count; // usually due to re-syncs
}; // end class NormServerNode }; // end class NormServerNode

View File

@ -49,8 +49,8 @@ bool NormObject::Open(const NormObjectSize& objectSize,
if (server) if (server)
{ {
segmentSize = server->SegmentSize(); segmentSize = server->SegmentSize();
numData = server->BlockSize(); numData = server->BlockSize(); // max source symbols per FEC block
numParity = server->NumParity(); numParity = server->NumParity(); // max parity symbols per FEC block
if (infoLen > 0) if (infoLen > 0)
{ {
pending_info = true; pending_info = true;
@ -65,8 +65,8 @@ bool NormObject::Open(const NormObjectSize& objectSize,
else else
{ {
segmentSize = session->ServerSegmentSize(); segmentSize = session->ServerSegmentSize();
numData = session->ServerBlockSize(); numData = session->ServerBlockSize(); // max source symbols per FEC block
numParity = session->ServerNumParity(); numParity = session->ServerNumParity(); // max parity symbols per FEC block
if (infoPtr) if (infoPtr)
{ {
if (info) delete []info; if (info) delete []info;
@ -88,11 +88,16 @@ bool NormObject::Open(const NormObjectSize& objectSize,
} }
} }
// Make sure object size and block/segment sizes are compatible // Compute number of segments and coding blocks for the object
NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData); // (Note NormObjectSize divide operator always rounds _up_)
NormObjectSize numBlocks = objectSize / blockSize; NormObjectSize numSegments = objectSize / NormObjectSize(segmentSize);
NormObjectSize numBlocks = numSegments / NormObjectSize(numData);
ASSERT(0 == numBlocks.MSB()); ASSERT(0 == numBlocks.MSB());
if (!block_buffer.Init(numBlocks.LSB())) if (!block_buffer.Init(numBlocks.LSB()))
{ {
DMSG(0, "NormObject::Open() init block_buffer error\n"); DMSG(0, "NormObject::Open() init block_buffer error\n");
@ -119,28 +124,44 @@ bool NormObject::Open(const NormObjectSize& objectSize,
} }
repair_mask.Clear(); repair_mask.Clear();
if (STREAM == type) if (STREAM == type)
{ {
last_block_id = 0; // not applicable for STREAM small_block_size = large_block_size = numData;
last_block_size = numData; // assumed for STREAM small_block_count = large_block_count = numBlocks.LSB();
final_segment_size = segmentSize;
NormStreamObject* stream = static_cast<NormStreamObject*>(this); NormStreamObject* stream = static_cast<NormStreamObject*>(this);
stream->StreamResync(numBlocks.LSB()); stream->StreamResync(numBlocks.LSB());
} }
else else
{ {
last_block_id = numBlocks.LSB() - 1; // Compute FEC block structure per NORM Protocol Spec Section 5.1.1
NormObjectSize lastBlockBytes = NormObjectSize(last_block_id) * blockSize; // (Note NormObjectSize divide operator always rounds _up_)
lastBlockBytes = objectSize - lastBlockBytes; NormObjectSize largeBlockSize = numSegments / numBlocks;
NormObjectSize lastBlockSize = lastBlockBytes / NormObjectSize(segmentSize); ASSERT(0 == largeBlockSize.MSB());
ASSERT(!lastBlockSize.MSB()); large_block_size = largeBlockSize.LSB();
ASSERT(lastBlockSize.LSB() <= numData); if (numSegments == (numBlocks*largeBlockSize))
last_block_size = lastBlockSize.LSB(); {
NormObjectSize lastSegmentSize = small_block_size = large_block_size;
NormObjectSize(0,last_block_size-1) * NormObjectSize(segmentSize); small_block_count = numBlocks.LSB();
lastSegmentSize = lastBlockBytes - lastSegmentSize; large_block_count = 0;
ASSERT(!lastSegmentSize.MSB()); }
ASSERT(lastSegmentSize.LSB() <= segmentSize); else
last_segment_size = lastSegmentSize.LSB(); {
small_block_size = large_block_size - 1;
NormObjectSize largeBlockCount = numSegments - numBlocks*small_block_size;
ASSERT(0 == largeBlockCount.MSB());
large_block_count = largeBlockCount.LSB();
NormObjectSize smallBlockCount = numBlocks - largeBlockCount;
ASSERT(0 == smallBlockCount.MSB());
small_block_count = smallBlockCount.LSB();
}
final_block_id = large_block_count + small_block_count - 1; // not used for STREAM objects
NormObjectSize finalSegmentSize =
objectSize - (numSegments - NormObjectSize((UINT32)1))*segmentSize;
ASSERT(0 == finalSegmentSize.MSB());
final_segment_size = finalSegmentSize.LSB();
} }
object_size = objectSize; object_size = objectSize;
@ -233,7 +254,7 @@ bool NormObject::TxReset(NormBlockId firstBlock)
NormBlockId blockId = block->Id(); NormBlockId blockId = block->Id();
if (blockId >= firstBlock) if (blockId >= firstBlock)
{ {
increasedRepair |= block->TxReset(BlockSize(blockId), increasedRepair |= block->TxReset(GetBlockSize(blockId),
nparity, nparity,
session->ServerAutoParity(), session->ServerAutoParity(),
segment_size); segment_size);
@ -255,7 +276,7 @@ bool NormObject::TxResetBlocks(NormBlockId nextId, NormBlockId lastId)
} }
NormBlock* block = block_buffer.Find(nextId); NormBlock* block = block_buffer.Find(nextId);
if (block) if (block)
increasedRepair |= block->TxReset(BlockSize(block->Id()), nparity, autoParity, segment_size); increasedRepair |= block->TxReset(GetBlockSize(block->Id()), nparity, autoParity, segment_size);
nextId++; nextId++;
} }
return increasedRepair; return increasedRepair;
@ -286,7 +307,7 @@ bool NormObject::ActivateRepairs()
while (nextId <= lastId) while (nextId <= lastId)
{ {
NormBlock* block = block_buffer.Find(nextId); NormBlock* block = block_buffer.Find(nextId);
if (block) block->TxReset(BlockSize(nextId), nparity, autoParity, segment_size); if (block) block->TxReset(GetBlockSize(nextId), nparity, autoParity, segment_size);
// (TBD) This check can be eventually eliminated if everything else is done right // (TBD) This check can be eventually eliminated if everything else is done right
if (!pending_mask.Set(nextId)) if (!pending_mask.Set(nextId))
DMSG(0, "NormObject::ActivateRepairs() pending_mask.Set(%lu) error!\n", DMSG(0, "NormObject::ActivateRepairs() pending_mask.Set(%lu) error!\n",
@ -526,12 +547,15 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
if (blockId > max_pending_block) if (blockId > max_pending_block)
{ {
max_pending_block = blockId; max_pending_block = blockId;
max_pending_segment = BlockSize(blockId); max_pending_segment = GetBlockSize(blockId);
} }
break; break;
case THRU_OBJECT: case THRU_OBJECT:
if (!IsStream()) max_pending_block = last_block_id; if (!IsStream())
max_pending_segment = BlockSize(max_pending_block); max_pending_block = final_block_id;
else if (blockId > max_pending_block)
max_pending_block = blockId;
max_pending_segment = GetBlockSize(max_pending_block);
default: default:
break; break;
} // end switch (level) } // end switch (level)
@ -568,7 +592,7 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
if (blockId < current_block_id) if (blockId < current_block_id)
{ {
current_block_id = blockId; current_block_id = blockId;
next_segment_id = BlockSize(blockId); next_segment_id = GetBlockSize(blockId);
} }
break; break;
default: default:
@ -633,14 +657,14 @@ bool NormObject::ClientRepairCheck(CheckLevel level,
break; break;
case THRU_BLOCK: case THRU_BLOCK:
current_block_id = blockId; current_block_id = blockId;
next_segment_id = BlockSize(blockId); next_segment_id = GetBlockSize(blockId);
break; break;
case THRU_OBJECT: case THRU_OBJECT:
if (IsStream()) if (IsStream())
current_block_id = max_pending_block; current_block_id = max_pending_block;
else else
current_block_id = last_block_id; current_block_id = final_block_id;
next_segment_id = BlockSize(current_block_id); next_segment_id = GetBlockSize(current_block_id);
default: default:
break; break;
} }
@ -665,7 +689,7 @@ bool NormObject::IsRepairPending(bool flush)
if (block) if (block)
{ {
bool isPending; bool isPending;
UINT16 numData = BlockSize(nextId); UINT16 numData = GetBlockSize(nextId);
if (flush || (nextId < lastId)) if (flush || (nextId < lastId))
{ {
isPending = block->IsRepairPending(numData, nparity); isPending = block->IsRepairPending(numData, nparity);
@ -788,7 +812,7 @@ bool NormObject::AppendRepairRequest(NormNackMsg& nack,
} // end if/else (!blockPending && reqCount && (reqCount == (nextId - prevId))) } // end if/else (!blockPending && reqCount && (reqCount == (nextId - prevId)))
if (blockPending) if (blockPending)
{ {
UINT16 numData = BlockSize(nextId); UINT16 numData = GetBlockSize(nextId);
if (NormRepairRequest::INVALID != prevForm) if (NormRepairRequest::INVALID != prevForm)
nack.PackRepairRequest(req); // (TBD) error check nack.PackRepairRequest(req); // (TBD) error check
reqCount = 0; reqCount = 0;
@ -846,7 +870,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
{ {
info_len = segment_size; info_len = segment_size;
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! info too long.\n", LocalNodeId(), server->Id(), (UINT16)id); "Warning! info too long.\n", LocalNodeId(), server->GetId(), (UINT16)id);
} }
memcpy(info, infoMsg.GetInfo(), info_len); memcpy(info, infoMsg.GetInfo(), info_len);
pending_info = false; pending_info = false;
@ -857,7 +881,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
// (TBD) Verify info hasn't changed? // (TBD) Verify info hasn't changed?
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"received duplicate info ...\n", LocalNodeId(), "received duplicate info ...\n", LocalNodeId(),
server->Id(), (UINT16)id); server->GetId(), (UINT16)id);
} }
} }
else // NORM_MSG_DATA else // NORM_MSG_DATA
@ -870,7 +894,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (!stream->StreamUpdateStatus(blockId)) if (!stream->StreamUpdateStatus(blockId))
{ {
DMSG(4, "NormObject::HandleObjectMessage() node:%lu server:%lu obj>%hu blk>%lu " DMSG(4, "NormObject::HandleObjectMessage() node:%lu server:%lu obj>%hu blk>%lu "
"broken stream ...\n", LocalNodeId(), server->Id(), (UINT16)id, (UINT32)blockId); "broken stream ...\n", LocalNodeId(), server->GetId(), (UINT16)id, (UINT32)blockId);
//ASSERT(0); //ASSERT(0);
// ??? Ignore this new packet and try to fix stream ??? // ??? Ignore this new packet and try to fix stream ???
@ -898,7 +922,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
} }
} }
} }
UINT16 numData = BlockSize(blockId); UINT16 numData = GetBlockSize(blockId);
if (pending_mask.Test(blockId)) if (pending_mask.Test(blockId))
{ {
NormBlock* block = block_buffer.Find(blockId); NormBlock* block = block_buffer.Find(blockId);
@ -907,7 +931,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (!(block = server->GetFreeBlock(id, blockId))) if (!(block = server->GetFreeBlock(id, blockId)))
{ {
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! no free blocks ...\n", LocalNodeId(), server->Id(), "Warning! no free blocks ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)id);
return; return;
} }
@ -921,7 +945,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (!segment) if (!segment)
{ {
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! no free segments ...\n", LocalNodeId(), server->Id(), "Warning! no free segments ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)id);
return; return;
} }
@ -929,7 +953,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (segmentLen > segment_size) if (segmentLen > segment_size)
{ {
DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(0, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Error! segment too large ...\n", LocalNodeId(), server->Id(), "Error! segment too large ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)id);
server->PutFreeSegment(segment); server->PutFreeSegment(segment);
return; return;
@ -975,7 +999,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
// Decode (if pending_mask.FirstSet() < numData) // Decode (if pending_mask.FirstSet() < numData)
// and write any decoded data segments to object // and write any decoded data segments to object
DMSG(8, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu blk>%lu " DMSG(8, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu blk>%lu "
"completed block ...\n", LocalNodeId(), server->Id(), "completed block ...\n", LocalNodeId(), server->GetId(),
(UINT16)id, (UINT32)block->Id()); (UINT16)id, (UINT32)block->Id());
UINT16 nextErasure = block->FirstPending(); UINT16 nextErasure = block->FirstPending();
UINT16 erasureCount = 0; UINT16 erasureCount = 0;
@ -990,7 +1014,7 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
if (!(segment = server->GetFreeSegment(id, blockId))) if (!(segment = server->GetFreeSegment(id, blockId)))
{ {
DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(2, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"Warning! no free segments ...\n", LocalNodeId(), server->Id(), "Warning! no free segments ...\n", LocalNodeId(), server->GetId(),
(UINT16)id); (UINT16)id);
// (TBD) Dump the block ...??? // (TBD) Dump the block ...???
return; return;
@ -1040,14 +1064,14 @@ void NormObject::HandleObjectMessage(const NormObjectMsg& msg,
{ {
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"received duplicate segment ...\n", LocalNodeId(), "received duplicate segment ...\n", LocalNodeId(),
server->Id(), (UINT16)id); server->GetId(), (UINT16)id);
} }
} }
else else
{ {
DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu " DMSG(6, "NormObject::HandleObjectMessage() node>%lu server>%lu obj>%hu "
"received duplicate block message ...\n", LocalNodeId(), "received duplicate block message ...\n", LocalNodeId(),
server->Id(), (UINT16)id); server->GetId(), (UINT16)id);
} // end if/else pending_mask.Test(blockId) } // end if/else pending_mask.Test(blockId)
} // end if/else (NORM_MSG_INFO) } // end if/else (NORM_MSG_INFO)
} // end NormObject::HandleObjectMessage() } // end NormObject::HandleObjectMessage()
@ -1183,7 +1207,7 @@ bool NormObject::NextServerMsg(NormObjectMsg* msg)
NormDataMsg* data = (NormDataMsg*)msg; NormDataMsg* data = (NormDataMsg*)msg;
NormBlockId blockId = pending_mask.FirstSet(); NormBlockId blockId = pending_mask.FirstSet();
UINT16 numData = BlockSize(blockId); UINT16 numData = GetBlockSize(blockId);
NormBlock* block = block_buffer.Find(blockId); NormBlock* block = block_buffer.Find(blockId);
if (!block) if (!block)
{ {
@ -1345,7 +1369,7 @@ void NormStreamObject::StreamAdvance()
bool NormObject::CalculateBlockParity(NormBlock* block) bool NormObject::CalculateBlockParity(NormBlock* block)
{ {
char buffer[NormMsg::MAX_SIZE]; char buffer[NormMsg::MAX_SIZE];
UINT16 numData = BlockSize(block->Id()); UINT16 numData = GetBlockSize(block->Id());
for (UINT16 i = 0; i < numData; i++) for (UINT16 i = 0; i < numData; i++)
{ {
if (ReadSegment(block->Id(), i, buffer)) if (ReadSegment(block->Id(), i, buffer))
@ -1369,7 +1393,7 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
NormBlock* block = session->ServerGetFreeBlock(id, blockId); NormBlock* block = session->ServerGetFreeBlock(id, blockId);
if (block) if (block)
{ {
UINT16 numData = BlockSize(blockId); UINT16 numData = GetBlockSize(blockId);
// Init block parameters // Init block parameters
block->TxRecover(blockId, numData, nparity); block->TxRecover(blockId, numData, nparity);
// Fill block with zero initialized parity segments // Fill block with zero initialized parity segments
@ -1427,7 +1451,8 @@ NormBlock* NormObject::ServerRecoverBlock(NormBlockId blockId)
NormFileObject::NormFileObject(class NormSession* theSession, NormFileObject::NormFileObject(class NormSession* theSession,
class NormServerNode* theServer, class NormServerNode* theServer,
const NormObjectId& objectId) const NormObjectId& objectId)
: NormObject(FILE, theSession, theServer, objectId), block_size(0,0) : NormObject(FILE, theSession, theServer, objectId),
large_block_length(0,0), small_block_length(0,0)
{ {
path[0] = '\0'; path[0] = '\0';
} }
@ -1462,15 +1487,15 @@ bool NormFileObject::Open(const char* thePath,
return false; return false;
} }
} }
block_size = NormObjectSize(server->BlockSize()) * //block_size = NormObjectSize(server->BlockSize()) *
NormObjectSize(server->SegmentSize()); // NormObjectSize(server->SegmentSize());
} }
else else
{ {
// We're sending this file // We're sending this file
if (file.Open(thePath, O_RDONLY)) if (file.Open(thePath, O_RDONLY))
{ {
unsigned long size = file.GetSize(); UINT32 size = file.GetSize();
if (size) if (size)
{ {
if (!NormObject::Open(size, infoPtr, infoLen)) if (!NormObject::Open(size, infoPtr, infoLen))
@ -1486,8 +1511,8 @@ bool NormFileObject::Open(const char* thePath,
file.Close(); file.Close();
return false; return false;
} }
block_size = NormObjectSize(session->ServerBlockSize()) * large_block_length = NormObjectSize(large_block_size) * segment_size;
NormObjectSize(session->ServerSegmentSize()); small_block_length = NormObjectSize(small_block_size) * segment_size;
} }
else else
{ {
@ -1526,13 +1551,20 @@ bool NormFileObject::WriteSegment(NormBlockId blockId,
const char* buffer) const char* buffer)
{ {
UINT16 len; UINT16 len;
if ((blockId == last_block_id) && if (blockId == final_block_id)
(segmentId == (last_block_size-1))) {
len = last_segment_size; if (segmentId == (GetBlockSize(blockId)-1))
len = final_segment_size;
else
len = segment_size;
}
else else
{
len = segment_size; len = segment_size;
}
NormObjectSize segmentOffset = NormDataMsg::ReadPayloadOffset(buffer); NormObjectSize segmentOffset = NormDataMsg::ReadPayloadOffset(buffer);
off_t offset = segmentOffset.LSB() + (segmentOffset.MSB() * 0x100000000LL); off_t offsetScaleMSB = 0xffffffff + 1;
off_t offset = (off_t)segmentOffset.LSB() + ((off_t)segmentOffset.MSB() * offsetScaleMSB);
if (offset != file.GetOffset()) if (offset != file.GetOffset())
{ {
if (!file.Seek(offset)) return false; if (!file.Seek(offset)) return false;
@ -1548,20 +1580,39 @@ bool NormFileObject::ReadSegment(NormBlockId blockId,
{ {
// Determine segment length // Determine segment length
UINT16 len; UINT16 len;
if ((blockId == last_block_id) && if (blockId == final_block_id)
(segmentId == (last_block_size - 1))) {
len = last_segment_size; if (segmentId == (GetBlockSize(blockId)-1))
len = final_segment_size;
else
len = segment_size;
}
else else
{
len = segment_size; len = segment_size;
}
// Determine segment offset from blockId::segmentId // Determine segment offset from blockId::segmentId
NormObjectSize segmentOffset = NormObjectSize(blockId) * block_size; NormObjectSize segmentOffset;
segmentOffset = segmentOffset + (NormObjectSize(segmentId) * NormObjectSize(segment_size)); NormObjectSize segmentSize = NormObjectSize(segment_size);
if ((UINT32)blockId < large_block_count)
{
segmentOffset = large_block_length*(UINT32)blockId + segmentSize*segmentId;
}
else
{
segmentOffset = large_block_length*large_block_count;
UINT32 smallBlockIndex = (UINT32)blockId - large_block_count;
segmentOffset = segmentOffset + small_block_length*smallBlockIndex +
segmentSize *segmentId;
}
NormDataMsg::WritePayloadLength(buffer, len); NormDataMsg::WritePayloadLength(buffer, len);
NormDataMsg::WritePayloadOffset(buffer, segmentOffset); NormDataMsg::WritePayloadOffset(buffer, segmentOffset);
off_t offset = segmentOffset.LSB() + (segmentOffset.MSB() * 0x100000000LL); off_t offsetScaleMSB = 0xffffffff + 1;
off_t offset = (off_t)segmentOffset.LSB() + ((off_t)segmentOffset.MSB() * offsetScaleMSB);
if (offset != file.GetOffset()) if (offset != file.GetOffset())
{ {
if (!file.Seek(offset)) return false; if (!file.Seek(offset))
return false;
} }
UINT16 nbytes = file.Read(buffer+NormDataMsg::PayloadHeaderLength(), len); UINT16 nbytes = file.Read(buffer+NormDataMsg::PayloadHeaderLength(), len);
return (len == nbytes); return (len == nbytes);
@ -1609,7 +1660,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
} }
NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData); NormObjectSize blockSize((UINT32)segmentSize * (UINT32)numData);
NormObjectSize numBlocks = NormObjectSize(bufferSize) / blockSize; NormObjectSize numBlocks = NormObjectSize((UINT32)bufferSize) / blockSize;
ASSERT(0 == numBlocks.MSB()); ASSERT(0 == numBlocks.MSB());
// Buffering requires at least 2 blocks // Buffering requires at least 2 blocks
numBlocks = MAX(2, numBlocks.LSB()); numBlocks = MAX(2, numBlocks.LSB());
@ -1642,7 +1693,7 @@ bool NormStreamObject::Open(unsigned long bufferSize,
write_offset = read_offset = NormObjectSize((UINT32)0); write_offset = read_offset = NormObjectSize((UINT32)0);
if (!server) if (!server)
{ {
if (!NormObject::Open(NormObjectSize(bufferSize), infoPtr, infoLen)) if (!NormObject::Open(NormObjectSize((UINT32)bufferSize), infoPtr, infoLen))
{ {
DMSG(0, "NormStreamObject::Open() object open error\n"); DMSG(0, "NormStreamObject::Open() object open error\n");
Close(); Close();
@ -1970,8 +2021,8 @@ void NormStreamObject::Prune(NormBlockId blockId)
// Sequential (in order) read/write routines (TBD) Add a "Seek()" method // Sequential (in order) read/write routines (TBD) Add a "Seek()" method
bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStart) bool NormStreamObject::Read(char* buffer, unsigned int* buflen, bool findMsgStart)
{ {
unsigned long bytesRead = 0; unsigned int bytesRead = 0;
unsigned long bytesToRead = *buflen; unsigned int bytesToRead = *buflen;
while (bytesToRead > 0) while (bytesToRead > 0)
{ {
NormBlock* block = stream_buffer.Find(read_index.block); NormBlock* block = stream_buffer.Find(read_index.block);
@ -2178,7 +2229,7 @@ unsigned long NormStreamObject::Write(const char* buffer, unsigned long len, boo
#endif // if/else SIMULATE #endif // if/else SIMULATE
} }
UINT16 count = len - nBytes; UINT16 count = (UINT16)(len - nBytes);
UINT16 space = segment_size - index; UINT16 space = segment_size - index;
count = MIN(count, space); count = MIN(count, space);
#ifdef SIMULATE #ifdef SIMULATE

View File

@ -28,9 +28,9 @@ class NormObject
THRU_OBJECT THRU_OBJECT
}; };
void Verify() const;
virtual ~NormObject(); virtual ~NormObject();
// Object information
NormObject::Type GetType() const {return type;} NormObject::Type GetType() const {return type;}
const NormObjectId& Id() const {return id;} const NormObjectId& Id() const {return id;}
const NormObjectSize& Size() const {return object_size;} const NormObjectSize& Size() const {return object_size;}
@ -60,10 +60,12 @@ class NormObject
char* buffer) = 0; char* buffer) = 0;
// These are only valid after object is open // These are only valid after object is open
NormBlockId LastBlockId() const {return last_block_id;} NormBlockId GetFinalBlockId() const {return final_block_id;}
NormSegmentId LastBlockSize() const {return last_block_size;} UINT32 GetBlockSize(NormBlockId blockId)
NormSegmentId BlockSize(NormBlockId blockId) {
{return ((blockId == last_block_id) ? last_block_size : ndata);} return (((UINT32)blockId < large_block_count) ? large_block_size :
small_block_size);
}
bool IsPending(bool flush = true) const; bool IsPending(bool flush = true) const;
bool IsRepairPending() const; bool IsRepairPending() const;
@ -84,12 +86,12 @@ class NormObject
{ {
NormBlockId blockId = theBlock->Id(); NormBlockId blockId = theBlock->Id();
bool result = theBlock->TxUpdate(firstSegmentId, lastSegmentId, bool result = theBlock->TxUpdate(firstSegmentId, lastSegmentId,
BlockSize(blockId), nparity, GetBlockSize(blockId), nparity,
numErasures); numErasures);
ASSERT(result ? pending_mask.Set(blockId) : true); ASSERT(result ? pending_mask.Set(blockId) : true);
result = result ? pending_mask.Set(blockId) : false; result = result ? pending_mask.Set(blockId) : false;
return result; return result;
} // end NormObject::TxUpdateBlock() }
bool HandleInfoRequest(); bool HandleInfoRequest();
bool HandleBlockRequest(NormBlockId nextId, NormBlockId lastId); bool HandleBlockRequest(NormBlockId nextId, NormBlockId lastId);
bool SetPending(NormBlockId blockId) {return pending_mask.Set(blockId);} bool SetPending(NormBlockId blockId) {return pending_mask.Set(blockId);}
@ -98,7 +100,7 @@ class NormObject
bool IsRepairSet(NormBlockId blockId) {return repair_mask.Test(blockId);} bool IsRepairSet(NormBlockId blockId) {return repair_mask.Test(blockId);}
bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd); bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd);
// Used by session server for resource management scheme // Used by sender for resource management scheme
NormBlock* StealNonPendingBlock(bool excludeBlock, NormBlockId excludeId = 0); NormBlock* StealNonPendingBlock(bool excludeBlock, NormBlockId excludeId = 0);
@ -110,7 +112,7 @@ class NormObject
NormSegmentId segmentId); NormSegmentId segmentId);
// Used by remote server node for resource management scheme // Used by receiver for resource management scheme
NormBlock* StealNewestBlock(bool excludeBlock, NormBlockId excludeId = 0); NormBlock* StealNewestBlock(bool excludeBlock, NormBlockId excludeId = 0);
NormBlock* StealOldestBlock(bool excludeBlock, NormBlockId excludeId = 0); NormBlock* StealOldestBlock(bool excludeBlock, NormBlockId excludeId = 0);
@ -129,7 +131,7 @@ class NormObject
} }
protected: protected:
NormObject(NormObject::Type theType, NormObject(Type theType,
class NormSession* theSession, class NormSession* theSession,
class NormServerNode* theServer, class NormServerNode* theServer,
const NormObjectId& objectId); const NormObjectId& objectId);
@ -154,17 +156,18 @@ class NormObject
NormSegmentId next_segment_id; // for suppression NormSegmentId next_segment_id; // for suppression
NormBlockId max_pending_block; // for NACK construction NormBlockId max_pending_block; // for NACK construction
NormSegmentId max_pending_segment; // for NACK construction NormSegmentId max_pending_segment; // for NACK construction
NormBlockId last_block_id; UINT32 large_block_count;
NormSegmentId last_block_size; UINT32 large_block_size;
UINT16 last_segment_size; UINT32 small_block_count;
UINT32 small_block_size;
NormBlockId final_block_id;
UINT16 final_segment_size;
char* info; char* info;
UINT16 info_len; UINT16 info_len;
bool accepted; bool accepted;
NormObject* next; NormObject* next;
}; // end class NormObject }; // end class NormObject
@ -201,7 +204,8 @@ class NormFileObject : public NormObject
private: private:
char path[PATH_MAX]; char path[PATH_MAX];
NormFile file; NormFile file;
NormObjectSize block_size; NormObjectSize large_block_length;
NormObjectSize small_block_length;
}; // end class NormFileObject }; // end class NormFileObject
@ -345,14 +349,14 @@ class NormObjectTable
private: private:
NormObject* Next(NormObject* o) const {return o->next;} NormObject* Next(NormObject* o) const {return o->next;}
NormObject** table; NormObject** table;
unsigned long hash_mask; UINT16 hash_mask;
unsigned long range_max; // max range of objects that can be kept UINT16 range_max; // max range of objects that can be kept
unsigned long range; // zero if "object table" is empty UINT16 range; // zero if "object table" is empty
NormObjectId range_lo; NormObjectId range_lo;
NormObjectId range_hi; NormObjectId range_hi;
unsigned long count; UINT16 count;
NormObjectSize size; NormObjectSize size;
}; // end class NormObjectTable }; // end class NormObjectTable
#endif // _NORM_OBJECT #endif // _NORM_OBJECT

View File

@ -1,39 +1,66 @@
#include "normPostProcess.h" #include "normPostProcess.h"
#include "protoLib.h" #include "protoDebug.h"
#include <errno.h>
#include <signal.h>
#include <ctype.h> #include <ctype.h>
#ifdef UNIX #include <string.h>
#include <unistd.h> #include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif // UNIX
typedef void (*sighandler_t)(int);
NormPostProcessor::NormPostProcessor() NormPostProcessor::NormPostProcessor()
: process_argv(NULL) : process_argv(NULL), process_argc(0)
#ifdef UNIX
,process_id(0)
#endif // UNIX
{ {
} }
NormPostProcessor::~NormPostProcessor() NormPostProcessor::~NormPostProcessor()
{ {
if (IsActive()) Kill();
SetCommand(NULL); SetCommand(NULL);
} }
void NormPostProcessor::GetCommand(char* buffer, unsigned int buflen)
{
if (process_argv && buffer)
{
unsigned int i = 0;
while (buflen && (i < process_argc))
{
strncpy(buffer, process_argv[i], buflen);
unsigned int len = strlen(process_argv[i]);
if (len < buflen)
{
buflen -= len;
buffer += len;
}
else
{
buflen = 0;
break;
}
i++;
if (i < process_argc)
{
*buffer++= ' ';
buflen--;
}
}
}
else if (buflen && buffer)
{
if (buflen < 4)
buffer[0] = '\0';
else
strncpy(buffer, "none", 4);
if (buflen > 4) buffer[4] = '\0';
}
} // end NormPostProcessor::GetCommand()
bool NormPostProcessor::SetCommand(const char* cmd) bool NormPostProcessor::SetCommand(const char* cmd)
{ {
// 1) Delete old command resources // 1) Delete old command resources
if (process_argv) if (process_argv)
{ {
const char** arg = process_argv; char** arg = process_argv;
while (*arg) while (*arg)
{ {
delete *arg; delete *arg;
@ -60,7 +87,7 @@ bool NormPostProcessor::SetCommand(const char* cmd)
// 3) Allocate new process_argv array (2 extra slots, one for "target", // 3) Allocate new process_argv array (2 extra slots, one for "target",
// and one for terminating NULL pointer. // and one for terminating NULL pointer.
if (!(process_argv = new const char*[argCount+2])) if (!(process_argv = new char*[argCount+2]))
{ {
DMSG(0, "NormPostProcessor::SetCommand new(process_argv) error: %s\n", DMSG(0, "NormPostProcessor::SetCommand new(process_argv) error: %s\n",
strerror(errno)); strerror(errno));
@ -92,74 +119,3 @@ bool NormPostProcessor::SetCommand(const char* cmd)
} }
return true; return true;
} // end NormPostProcessor::SetCommand() } // end NormPostProcessor::SetCommand()
bool NormPostProcessor::ProcessFile(const char* path)
{
if (IsActive()) Kill();
#ifdef UNIX
// 1) temporarily disable signal handling
sighandler_t sigtermHandler = signal(SIGTERM, SIG_DFL);
sighandler_t sigintHandler = signal(SIGINT, SIG_DFL);
sighandler_t sigchldHandler = signal(SIGCHLD, SIG_DFL);
process_argv[process_argc] = path;
switch((process_id = fork()))
{
case -1: // error
DMSG(0, "NormPostProcessor::ProcessFile fork() error: %s\n", strerror(errno));
process_id = 0;
process_argv[process_argc] = NULL;
return false;
case 0: // child
if (execvp((char*)process_argv[0], (char**)process_argv) < 0)
{
DMSG(0, "NormPostProcessor::ProcessFile execvp() error: %s\n", strerror(errno));
exit(-1);
}
break;
default: // parent
process_argv[process_argc] = NULL;
// Restore signal handlers for parent
signal(SIGTERM, sigtermHandler);
signal(SIGINT, sigintHandler);
signal(SIGCHLD, sigchldHandler);
break;
}
#endif // UNIX
return true;
} // end NormPostProcessor::ProcessFile()
void NormPostProcessor::Kill()
{
if (!IsActive()) return;
#ifdef UNIX
int count = 0;
while((kill(process_id, SIGTERM) != 0) && count < 10)
{
if (errno == ESRCH) break;
count++;
DMSG(0, "NormPostProcessor::Kill kill() error: %s\n", strerror(errno));
}
count = 0;
int status;
while((waitpid(process_id, &status, 0) != process_id) && count < 10)
{
if (errno == ECHILD) break;
count++;
DMSG(0, "NormPostProcessor::Kill waitpid() error: %s\n", strerror(errno));
}
process_id = 0;
#endif // UNIX
} // end NormPostProcessor::Kill()
void NormPostProcessor::HandleSIGCHLD()
{
// See if processor exited itself
int status;
if (wait(&status) == process_id) process_id = 0;
} // end NormPostProcessor::HandleSIGCHLD()

View File

@ -1,35 +1,29 @@
#ifndef _NORM_POST_PROCESS #ifndef _NORM_POST_PROCESS
#define _NORM_POST_PROCESS #define _NORM_POST_PROCESS
#include "protoDefs.h" // for NULL
class NormPostProcessor class NormPostProcessor
{ {
public: public:
NormPostProcessor(); NormPostProcessor();
~NormPostProcessor(); virtual ~NormPostProcessor();
// Implement this per derivation
static NormPostProcessor* Create();
bool IsEnabled() {return (0 != process_argv);} bool IsEnabled() {return (NULL != process_argv);}
bool SetCommand(const char* cmd); bool SetCommand(const char* cmd);
bool ProcessFile(const char* path); void GetCommand(char* buffer, unsigned int buflen);
void Kill();
bool IsActive()
{
#ifdef UNIX
return (0 != process_id);
#endif // UNIX
}
void HandleSIGCHLD(); virtual bool ProcessFile(const char* path) = 0;
virtual void Kill() = 0;
virtual bool IsActive() = 0;
virtual void OnDeath() {};
private: protected:
const char** process_argv; char** process_argv;
unsigned int process_argc; unsigned int process_argc;
#ifdef UNIX
int process_id;
#endif
#ifdef WIN32
HANDLE process_handle;
#endif
}; // end class NormPostProcessor }; // end class NormPostProcessor
#endif // _NORM_POST_PROCESS #endif // _NORM_POST_PROCESS

View File

@ -184,14 +184,14 @@ bool NormBlock::IsRepairPending(UINT16 ndata, UINT16 nparity)
if (nparity) if (nparity)
{ {
UINT16 i = nparity; UINT16 i = nparity;
NormSegmentId nextId = pending_mask.FirstSet(); NormSegmentId nextId = (UINT16)pending_mask.FirstSet();
while (i--) while (i--)
{ {
// (TBD) for more NACK suppression, we could skip ahead // (TBD) for more NACK suppression, we could skip ahead
// if this bit is already set in repair_mask? // if this bit is already set in repair_mask?
repair_mask.Set(nextId); // set bit a parity can fill repair_mask.Set(nextId); // set bit a parity can fill
nextId++; nextId++;
nextId = pending_mask.NextSet(nextId); nextId = (UINT16)pending_mask.NextSet(nextId);
} }
} }
else if (size > ndata) else if (size > ndata)
@ -390,7 +390,7 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
NormRepairRequest req; NormRepairRequest req;
req.SetFlag(NormRepairRequest::SEGMENT); req.SetFlag(NormRepairRequest::SEGMENT);
if (repairInfo) req.SetFlag(NormRepairRequest::INFO); if (repairInfo) req.SetFlag(NormRepairRequest::INFO);
UINT16 nextId = repair_mask.FirstSet(); UINT16 nextId = (UINT16)repair_mask.FirstSet();
UINT16 blockSize = size; UINT16 blockSize = size;
NormRepairRequest::Form prevForm = NormRepairRequest::INVALID; NormRepairRequest::Form prevForm = NormRepairRequest::INVALID;
UINT16 segmentCount = 0; UINT16 segmentCount = 0;
@ -398,7 +398,7 @@ bool NormBlock::AppendRepairAdv(NormCmdRepairAdvMsg& cmd,
while (nextId < blockSize) while (nextId < blockSize)
{ {
UINT16 currentId = nextId; UINT16 currentId = nextId;
nextId = repair_mask.NextSet(++nextId); nextId = (UINT16)repair_mask.NextSet(++nextId);
if (!segmentCount) firstId = currentId; if (!segmentCount) firstId = currentId;
segmentCount++; segmentCount++;
@ -467,19 +467,19 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
if (erasure_count > nparity) if (erasure_count > nparity)
{ {
// Request explicit repair // Request explicit repair
nextId = pending_mask.FirstSet(); nextId = (UINT16)pending_mask.FirstSet();
UINT16 i = nparity; UINT16 i = nparity;
// Skip nparity missing data segments // Skip nparity missing data segments
while (i--) while (i--)
{ {
nextId++; nextId++;
endId = pending_mask.NextSet(nextId); endId = (UINT16)pending_mask.NextSet(nextId);
} }
endId = ndata + nparity; endId = ndata + nparity;
} }
else else
{ {
nextId = pending_mask.NextSet(ndata); nextId = (UINT16)pending_mask.NextSet(ndata);
endId = ndata + erasure_count; endId = ndata + erasure_count;
} }
NormRepairRequest req; NormRepairRequest req;
@ -492,7 +492,7 @@ bool NormBlock::AppendRepairRequest(NormNackMsg& nack,
while (nextId < endId) while (nextId < endId)
{ {
UINT16 currentId = nextId; UINT16 currentId = nextId;
nextId = pending_mask.NextSet(++nextId); nextId = (UINT16)pending_mask.NextSet(++nextId);
if (0 == segmentCount) firstId = currentId; if (0 == segmentCount) firstId = currentId;
segmentCount++; segmentCount++;
// Check for break in consecutive series or end // Check for break in consecutive series or end

View File

@ -157,9 +157,9 @@ class NormBlock
UINT16 ParityCount() const {return parity_count;} UINT16 ParityCount() const {return parity_count;}
NormSymbolId FirstPending() const NormSymbolId FirstPending() const
{return pending_mask.FirstSet();} {return (NormSymbolId)pending_mask.FirstSet();}
NormSymbolId FirstRepair() const NormSymbolId FirstRepair() const
{return repair_mask.FirstSet();} {return (NormSymbolId)repair_mask.FirstSet();}
bool SetPending(NormSymbolId s) bool SetPending(NormSymbolId s)
{return pending_mask.Set(s);} {return pending_mask.Set(s);}
bool SetPending(NormSymbolId firstId, UINT16 count) bool SetPending(NormSymbolId firstId, UINT16 count)
@ -192,7 +192,7 @@ class NormBlock
NormSymbolId NextPending(NormSymbolId index) const NormSymbolId NextPending(NormSymbolId index) const
{return pending_mask.NextSet(index);} {return ((NormSymbolId)pending_mask.NextSet(index));}
bool AppendRepairRequest(NormNackMsg& nack, bool AppendRepairRequest(NormNackMsg& nack,

View File

@ -15,12 +15,14 @@ const UINT16 NormSession::DEFAULT_NDATA = 64;
const UINT16 NormSession::DEFAULT_NPARITY = 32; const UINT16 NormSession::DEFAULT_NPARITY = 32;
NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId) NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
: session_mgr(sessionMgr), notify_pending(false), local_node_id(localNodeId), : session_mgr(sessionMgr), notify_pending(false),
tx_socket(ProtoSocket::UDP), rx_socket(ProtoSocket::UDP),
local_node_id(localNodeId),
ttl(DEFAULT_TTL), tx_rate(DEFAULT_TRANSMIT_RATE/8.0), ttl(DEFAULT_TTL), tx_rate(DEFAULT_TRANSMIT_RATE/8.0),
backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0), backoff_factor(DEFAULT_BACKOFF_FACTOR), is_server(false), session_id(0),
ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0), ndata(DEFAULT_NDATA), nparity(DEFAULT_NPARITY), auto_parity(0), extra_parity(0),
next_tx_object_id(0), tx_cache_count_min(1), tx_cache_count_max(256), next_tx_object_id(0), tx_cache_count_min(1), tx_cache_count_max(256),
tx_cache_size_max((unsigned long)20*1024*1024), tx_cache_size_max((UINT32)20*1024*1024),
flush_count(NORM_ROBUST_FACTOR+1), flush_count(NORM_ROBUST_FACTOR+1),
posted_tx_queue_empty(false), advertise_repairs(false), posted_tx_queue_empty(false), advertise_repairs(false),
suppress_nonconfirmed(false), suppress_rate(-1.0), suppress_rtt(-1.0), suppress_nonconfirmed(false), suppress_rate(-1.0), suppress_rtt(-1.0),
@ -35,24 +37,27 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
trace(false), tx_loss_rate(0.0), rx_loss_rate(0.0), trace(false), tx_loss_rate(0.0), rx_loss_rate(0.0),
next(NULL) next(NULL)
{ {
tx_socket.Init((UdpSocketOwner*) this, tx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
(UdpSocketRecvHandler)&NormSession::TxSocketRecvHandler, tx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::TxSocketRecvHandler);
sessionMgr.SocketInstaller(),
sessionMgr.SocketInstallData());
rx_socket.Init((UdpSocketOwner*) this,
(UdpSocketRecvHandler)&NormSession::RxSocketRecvHandler,
sessionMgr.SocketInstaller(),
sessionMgr.SocketInstallData());
tx_timer.Init(0.0, -1, rx_socket.SetNotifier(&sessionMgr.GetSocketNotifier());
(ProtocolTimerOwner *)this, rx_socket.SetListener(this, (ProtoSocket::EventHandler)&NormSession::RxSocketRecvHandler);
(ProtocolTimeoutFunc)&NormSession::OnTxTimeout);
repair_timer.Init(0.0, 1, (ProtocolTimerOwner*)this, tx_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnTxTimeout);
(ProtocolTimeoutFunc)&NormSession::OnRepairTimeout); tx_timer.SetInterval(0.0);
flush_timer.Init(0.0, 0, (ProtocolTimerOwner*)this, tx_timer.SetRepeat(-1);
(ProtocolTimeoutFunc)&NormSession::OnFlushTimeout);
probe_timer.Init(0.0, -1, (ProtocolTimerOwner*)this, repair_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnRepairTimeout);
(ProtocolTimeoutFunc)&NormSession::OnProbeTimeout); repair_timer.SetInterval(0.0);
repair_timer.SetRepeat(1);
flush_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnFlushTimeout);
flush_timer.SetInterval(0.0);
flush_timer.SetRepeat(0);
probe_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnProbeTimeout);
probe_timer.SetInterval(0.0);
probe_timer.SetRepeat(-1);
grtt_quantized = NormQuantizeRtt(DEFAULT_GRTT_ESTIMATE); grtt_quantized = NormQuantizeRtt(DEFAULT_GRTT_ESTIMATE);
grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized); grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized);
@ -65,8 +70,9 @@ NormSession::NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId)
// This timer is for printing out occasional status reports // This timer is for printing out occasional status reports
// (It may be used to trigger transmission of report messages // (It may be used to trigger transmission of report messages
// in the future for debugging, etc // in the future for debugging, etc
report_timer.Init(30.0, -1, (ProtocolTimerOwner*)this, report_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSession::OnReportTimeout);
(ProtocolTimeoutFunc)&NormSession::OnReportTimeout); report_timer.SetInterval(10.0);
report_timer.SetRepeat(-1);
} }
NormSession::~NormSession() NormSession::~NormSession()
@ -75,13 +81,12 @@ NormSession::~NormSession()
} }
bool NormSession::Open() bool NormSession::Open()
{ {
ASSERT(address.IsValid()); ASSERT(address.IsValid());
if (!tx_socket.IsOpen()) if (!tx_socket.IsOpen())
{ {
if (UDP_SOCKET_ERROR_NONE != tx_socket.Open()) if (!tx_socket.Open())
{ {
DMSG(0, "NormSession::Open() tx_socket open error\n"); DMSG(0, "NormSession::Open() tx_socket open error\n");
return false; return false;
@ -89,7 +94,7 @@ bool NormSession::Open()
} }
if (!rx_socket.IsOpen()) if (!rx_socket.IsOpen())
{ {
if (UDP_SOCKET_ERROR_NONE != rx_socket.Open(address.Port())) if (!rx_socket.Open(address.GetPort()))
{ {
DMSG(0, "NormSession::Open() rx_socket open error\n"); DMSG(0, "NormSession::Open() rx_socket open error\n");
Close(); Close();
@ -99,13 +104,13 @@ bool NormSession::Open()
if (address.IsMulticast()) if (address.IsMulticast())
{ {
if (UDP_SOCKET_ERROR_NONE != rx_socket.JoinGroup(&address)) if (!rx_socket.JoinGroup(address))
{ {
DMSG(0, "NormSession::Open() rx_socket join group error\n"); DMSG(0, "NormSession::Open() rx_socket join group error\n");
Close(); Close();
return false; return false;
} }
if (UDP_SOCKET_ERROR_NONE != tx_socket.SetTTL(ttl)) if (!tx_socket.SetTTL(ttl))
{ {
DMSG(0, "NormSession::Open() tx_socket set ttl error\n"); DMSG(0, "NormSession::Open() tx_socket set ttl error\n");
Close(); Close();
@ -126,7 +131,7 @@ bool NormSession::Open()
return false; return false;
} }
} }
InstallTimer(&report_timer); ActivateTimer(report_timer);
return true; return true;
} // end NormSession::Open() } // end NormSession::Open()
@ -142,7 +147,7 @@ void NormSession::Close()
if (tx_socket.IsOpen()) tx_socket.Close(); if (tx_socket.IsOpen()) tx_socket.Close();
if (rx_socket.IsOpen()) if (rx_socket.IsOpen())
{ {
if (address.IsMulticast()) rx_socket.LeaveGroup(&address); if (address.IsMulticast()) rx_socket.LeaveGroup(address);
rx_socket.Close(); rx_socket.Close();
} }
} // end NormSession::Close() } // end NormSession::Close()
@ -226,8 +231,8 @@ bool NormSession::StartServer(unsigned long bufferSpace,
is_server = true; is_server = true;
flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor flush_count = NORM_ROBUST_FACTOR+1; // (TBD) parameterize robust_factor
//probe_timer.SetInterval(0.0); //probe_timer.SetInterval(0.0);
OnProbeTimeout(); OnProbeTimeout(probe_timer);
InstallTimer(&probe_timer); ActivateTimer(probe_timer);
return true; return true;
} // end NormSession::StartServer() } // end NormSession::StartServer()
@ -274,7 +279,7 @@ void NormSession::Serve()
// Queue next server message // Queue next server message
if (tx_pending_mask.IsSet()) if (tx_pending_mask.IsSet())
{ {
NormObjectId objectId(tx_pending_mask.FirstSet()); NormObjectId objectId((unsigned short)tx_pending_mask.FirstSet());
obj = tx_table.Find(objectId); obj = tx_table.Find(objectId);
ASSERT(obj); ASSERT(obj);
} }
@ -293,6 +298,7 @@ void NormSession::Serve()
if (obj) if (obj)
{ {
NormObjectMsg* msg = (NormObjectMsg*)GetMessageFromPool(); NormObjectMsg* msg = (NormObjectMsg*)GetMessageFromPool();
if (msg) if (msg)
{ {
@ -300,6 +306,7 @@ void NormSession::Serve()
{ {
msg->SetDestination(address); msg->SetDestination(address);
msg->SetGrtt(grtt_quantized); msg->SetGrtt(grtt_quantized);
msg->SetBackoffFactor((unsigned char)backoff_factor);
msg->SetGroupSize(gsize_quantized); msg->SetGroupSize(gsize_quantized);
QueueMessage(msg); QueueMessage(msg);
flush_count = 0; flush_count = 0;
@ -378,8 +385,8 @@ void NormSession::ServerQueueFlush()
else else
{ {
objectId = obj->Id(); objectId = obj->Id();
blockId = obj->LastBlockId(); blockId = obj->GetFinalBlockId();
segmentId = obj->LastBlockSize() - 1; segmentId = obj->GetBlockSize(blockId) - 1;
} }
} }
else else
@ -389,7 +396,7 @@ void NormSession::ServerQueueFlush()
{ {
flush_count++; flush_count++;
flush_timer.SetInterval(2*grtt_advertised); flush_timer.SetInterval(2*grtt_advertised);
InstallTimer(&flush_timer); ActivateTimer(flush_timer);
} }
DMSG(8, "NormSession::ServerQueueFlush() node>%lu squelch queued (flush_count:%u)...\n", DMSG(8, "NormSession::ServerQueueFlush() node>%lu squelch queued (flush_count:%u)...\n",
LocalNodeId(), flush_count); LocalNodeId(), flush_count);
@ -401,6 +408,7 @@ void NormSession::ServerQueueFlush()
flush->Init(); flush->Init();
flush->SetDestination(address); flush->SetDestination(address);
flush->SetGrtt(grtt_quantized); flush->SetGrtt(grtt_quantized);
flush->SetBackoffFactor((unsigned char)backoff_factor);
flush->SetGroupSize(gsize_quantized); flush->SetGroupSize(gsize_quantized);
flush->SetObjectId(objectId); flush->SetObjectId(objectId);
flush->SetFecBlockId(blockId); flush->SetFecBlockId(blockId);
@ -408,7 +416,7 @@ void NormSession::ServerQueueFlush()
QueueMessage(flush); QueueMessage(flush);
flush_count++; flush_count++;
flush_timer.SetInterval(2*grtt_advertised); flush_timer.SetInterval(2*grtt_advertised);
InstallTimer(&flush_timer); ActivateTimer(flush_timer);
DMSG(8, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n", DMSG(8, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n",
LocalNodeId(), flush_count); LocalNodeId(), flush_count);
} }
@ -419,7 +427,7 @@ void NormSession::ServerQueueFlush()
} }
} // end NormSession::ServerQueueFlush() } // end NormSession::ServerQueueFlush()
bool NormSession::OnFlushTimeout() bool NormSession::OnFlushTimeout(ProtoTimer& /*theTimer*/)
{ {
flush_timer.Deactivate(); flush_timer.Deactivate();
Serve(); // (TBD) Change this to PromptServer() ?? Serve(); // (TBD) Change this to PromptServer() ??
@ -432,7 +440,7 @@ void NormSession::QueueMessage(NormMsg* msg)
/* A little test jig /* A little test jig
static struct timeval lastTime = {0,0}; static struct timeval lastTime = {0,0};
struct timeval currentTime; struct timeval currentTime;
GetSystemTime(&currentTime); ProtoSystemTime(currentTime);
if (0 != lastTime.tv_sec) if (0 != lastTime.tv_sec)
{ {
double delta = currentTime.tv_sec - lastTime.tv_sec; double delta = currentTime.tv_sec - lastTime.tv_sec;
@ -445,7 +453,7 @@ void NormSession::QueueMessage(NormMsg* msg)
if (!tx_timer.IsActive()) if (!tx_timer.IsActive())
{ {
tx_timer.SetInterval(0.0); tx_timer.SetInterval(0.0);
InstallTimer(&tx_timer); ActivateTimer(tx_timer);
} }
message_queue.Append(msg); message_queue.Append(msg);
} // end NormSesssion::QueueMessage(NormMsg& msg) } // end NormSesssion::QueueMessage(NormMsg& msg)
@ -682,40 +690,34 @@ char* NormSession::ServerGetFreeSegment(NormObjectId objectId,
return segment_pool.Get(); return segment_pool.Get();
} // end NormSession::ServerGetFreeSegment() } // end NormSession::ServerGetFreeSegment()
bool NormSession::TxSocketRecvHandler(UdpSocket* /*theSocket*/) void NormSession::TxSocketRecvHandler(ProtoSocket& /*theSocket*/,
ProtoSocket::Event /*theEvent*/)
{ {
NormMsg msg; NormMsg msg;
unsigned int msgLength = NormMsg::MAX_SIZE; unsigned int msgLength = NormMsg::MAX_SIZE;
if (UDP_SOCKET_ERROR_NONE == tx_socket.RecvFrom(msg.AccessBuffer(), while (tx_socket.RecvFrom(msg.AccessBuffer(),
&msgLength, msgLength,
msg.AccessAddress())) msg.AccessAddress()))
{ {
msg.InitFromBuffer(msgLength); msg.InitFromBuffer(msgLength);
HandleReceiveMessage(msg, true); HandleReceiveMessage(msg, true);
msgLength = NormMsg::MAX_SIZE;
} }
else
{
DMSG(0, "NormSession::TxSocketRecvHandler() recvfrom error");
}
return true;
} // end NormSession::TxSocketRecvHandler() } // end NormSession::TxSocketRecvHandler()
bool NormSession::RxSocketRecvHandler(UdpSocket* /*theSocket*/) void NormSession::RxSocketRecvHandler(ProtoSocket& /*theSocket*/,
ProtoSocket::Event /*theEvent*/)
{ {
NormMsg msg; NormMsg msg;
unsigned int msgLength = NormMsg::MAX_SIZE; unsigned int msgLength = NormMsg::MAX_SIZE;
if (UDP_SOCKET_ERROR_NONE == rx_socket.RecvFrom(msg.AccessBuffer(), while (rx_socket.RecvFrom(msg.AccessBuffer(),
&msgLength, msgLength,
msg.AccessAddress())) msg.AccessAddress()))
{ {
msg.InitFromBuffer(msgLength); msg.InitFromBuffer(msgLength);
HandleReceiveMessage(msg, false); HandleReceiveMessage(msg, false);
msgLength = NormMsg::MAX_SIZE;
} }
else
{
DMSG(0, "NormSession::RxSocketRecvHandler() recvfrom error");
}
return true;
} // end NormSession::RxSocketRecvHandler() } // end NormSession::RxSocketRecvHandler()
void NormTrace(const struct timeval& currentTime, void NormTrace(const struct timeval& currentTime,
@ -759,12 +761,12 @@ void NormTrace(const struct timeval& currentTime,
NormMsg::Type msgType = msg.GetType(); NormMsg::Type msgType = msg.GetType();
UINT16 length = msg.GetLength(); UINT16 length = msg.GetLength();
const char* status = sent ? "dst" : "src"; const char* status = sent ? "dst" : "src";
const NetworkAddress& addr = sent ? msg.GetDestination() : msg.GetSource(); const ProtoAddress& addr = sent ? msg.GetDestination() : msg.GetSource();
struct tm* ct = gmtime((time_t*)&currentTime.tv_sec); struct tm* ct = gmtime((time_t*)&currentTime.tv_sec);
DMSG(0, "trace>%02d:%02d:%02d.%06lu node>%lu %s>%s ", DMSG(0, "trace>%02d:%02d:%02d.%06lu node>%lu %s>%s ",
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec,
(UINT32)localId, status, addr.HostAddressString()); (UINT32)localId, status, addr.GetHostString());
bool clrFlag = false; bool clrFlag = false;
switch (msgType) switch (msgType)
{ {
@ -881,9 +883,8 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
return; return;
} }
struct timeval currentTime; struct timeval currentTime;
::GetSystemTime(&currentTime); ::ProtoSystemTime(currentTime);
if (trace) NormTrace(currentTime, LocalNodeId(), msg, false); if (trace) NormTrace(currentTime, LocalNodeId(), msg, false);
@ -894,10 +895,10 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
{ {
// (TBD) combine these as needed for efficiency // (TBD) combine these as needed for efficiency
// (i.e. fewer function calls per message) // (i.e. fewer function calls per message)
if (theServer->IsOpen()) theServer->Activate();
theServer->UpdateRecvRate(currentTime, msg.GetLength()); theServer->UpdateRecvRate(currentTime, msg.GetLength());
theServer->UpdateLossEstimate(currentTime, msg.GetSequence()); theServer->UpdateLossEstimate(currentTime, msg.GetSequence());
theServer->SetAddress(msg.GetSource()); theServer->SetAddress(msg.GetSource());
// for statistics only (TBD) #ifdef NORM_DEBUG // for statistics only (TBD) #ifdef NORM_DEBUG
theServer->IncrementRecvTotal(msg.GetLength()); theServer->IncrementRecvTotal(msg.GetLength());
} }
@ -929,7 +930,7 @@ void NormSession::HandleReceiveMessage(NormMsg& msg, bool wasUnicast)
if (!tx_timer.IsActive()) if (!tx_timer.IsActive())
{ {
tx_timer.SetInterval(0.0); tx_timer.SetInterval(0.0);
InstallTimer(&tx_timer); ActivateTimer(tx_timer);
} }
} }
} }
@ -1083,7 +1084,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
double ccRtt, double ccRtt,
double ccLoss, double ccLoss,
double ccRate, double ccRate,
UINT8 ccSequence) UINT16 ccSequence)
{ {
// Keep track of current suppressing feedback // Keep track of current suppressing feedback
// (non-CLR, lowest rate, unconfirmed RTT) // (non-CLR, lowest rate, unconfirmed RTT)
@ -1123,14 +1124,14 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
// 1) Does this response replace the active CLR? // 1) Does this response replace the active CLR?
if (next && next->IsActive()) if (next && next->IsActive())
{ {
if (ccRate < next->GetRate() || (nodeId == next->Id())) if (ccRate < next->GetRate() || (nodeId == next->GetId()))
{ {
NormNodeId savedId = next->Id(); NormNodeId savedId = next->GetId();
bool savedRttStatus = next->HasRtt(); bool savedRttStatus = next->HasRtt();
double savedRtt = next->GetRtt(); double savedRtt = next->GetRtt();
double savedLoss = next->GetLoss(); double savedLoss = next->GetLoss();
double savedRate = next->GetRate(); double savedRate = next->GetRate();
UINT8 savedSequence = next->GetCCSequence(); UINT16 savedSequence = next->GetCCSequence();
next->SetId(nodeId); next->SetId(nodeId);
next->SetClrStatus(true); next->SetClrStatus(true);
@ -1139,7 +1140,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
next->SetRate(ccRate); next->SetRate(ccRate);
next->SetCCSequence(ccSequence); next->SetCCSequence(ccSequence);
next->SetActive(true); next->SetActive(true);
if (next->Id() == nodeId) if (next->GetId() == nodeId)
{ {
// This was feedback from the current CLR // This was feedback from the current CLR
AdjustRate(true); AdjustRate(true);
@ -1206,7 +1207,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
{ {
while ((next = (NormCCNode*)iterator.GetNextNode())) while ((next = (NormCCNode*)iterator.GetNextNode()))
{ {
if (next->Id() == nodeId) if (next->GetId() == nodeId)
{ {
candidate = next; candidate = next;
break; break;
@ -1238,7 +1239,7 @@ void NormSession::ServerHandleCCFeedback(NormNodeId nodeId,
{ {
bool haveRtt = (0 != (ccFlags && NormCC::RTT)); bool haveRtt = (0 != (ccFlags && NormCC::RTT));
bool replace; bool replace;
if (candidate->Id() == nodeId) if (candidate->GetId() == nodeId)
replace = true; replace = true;
else if (!candidate->IsActive()) else if (!candidate->IsActive())
replace = true; replace = true;
@ -1297,7 +1298,7 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
if (!tx_timer.IsActive()) if (!tx_timer.IsActive())
{ {
tx_timer.SetInterval(0.0); tx_timer.SetInterval(0.0);
InstallTimer(&tx_timer); ActivateTimer(tx_timer);
} }
} }
@ -1346,10 +1347,10 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
NormRepairRequest req; NormRepairRequest req;
NormObject* object = NULL; NormObject* object = NULL;
bool freshObject = true; bool freshObject = true;
NormObjectId prevObjectId; NormObjectId prevObjectId = 0;
NormBlock* block = NULL; NormBlock* block = NULL;
bool freshBlock = true; bool freshBlock = true;
NormBlockId prevBlockId; NormBlockId prevBlockId = 0;
bool startTimer = false; bool startTimer = false;
UINT16 numErasures = extra_parity; UINT16 numErasures = extra_parity;
@ -1360,7 +1361,7 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
NormBlockId txBlockIndex; NormBlockId txBlockIndex;
if (tx_pending_mask.IsSet()) if (tx_pending_mask.IsSet())
{ {
txObjectIndex = tx_pending_mask.FirstSet(); txObjectIndex = NormObjectId((unsigned short)tx_pending_mask.FirstSet());
NormObject* obj = tx_table.Find(txObjectIndex); NormObject* obj = tx_table.Find(txObjectIndex);
ASSERT(obj); ASSERT(obj);
if (obj->IsPending()) if (obj->IsPending())
@ -1382,7 +1383,7 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
txBlockIndex = 0; txBlockIndex = 0;
} }
bool holdoff = (repair_timer.IsActive() && !repair_timer.RepeatCount()); bool holdoff = (repair_timer.IsActive() && !repair_timer.GetRepeatCount());
enum NormRequestLevel {SEGMENT, BLOCK, INFO, OBJECT}; enum NormRequestLevel {SEGMENT, BLOCK, INFO, OBJECT};
while ((requestLength = nack.UnpackRepairRequest(req, requestOffset))) while ((requestLength = nack.UnpackRepairRequest(req, requestOffset)))
{ {
@ -1728,14 +1729,14 @@ void NormSession::ServerHandleNackMessage(const struct timeval& currentTime, Nor
if (tx_timer.IsActive()) if (tx_timer.IsActive())
{ {
double txTimeout = tx_timer.TimeRemaining() - 1.0e-06; double txTimeout = tx_timer.GetTimeRemaining() - 1.0e-06;
aggregateInterval = MAX(txTimeout, aggregateInterval); aggregateInterval = MAX(txTimeout, aggregateInterval);
} }
repair_timer.SetInterval(aggregateInterval); repair_timer.SetInterval(aggregateInterval);
DMSG(4, "NormSession::ServerHandleNackMessage() node>%lu starting server " DMSG(4, "NormSession::ServerHandleNackMessage() node>%lu starting server "
"NACK aggregation timer (%lf sec)...\n", LocalNodeId(), aggregateInterval); "NACK aggregation timer (%lf sec)...\n", LocalNodeId(), aggregateInterval);
InstallTimer(&repair_timer); ActivateTimer(repair_timer);
} }
} // end NormSession::ServerHandleNackMessage() } // end NormSession::ServerHandleNackMessage()
@ -1778,6 +1779,7 @@ bool NormSession::ServerQueueSquelch(NormObjectId objectId)
squelch->Init(); squelch->Init();
squelch->SetDestination(address); squelch->SetDestination(address);
squelch->SetGrtt(grtt_quantized); squelch->SetGrtt(grtt_quantized);
squelch->SetBackoffFactor((unsigned char)backoff_factor);
squelch->SetGroupSize(gsize_quantized); squelch->SetGroupSize(gsize_quantized);
NormObject* obj = tx_table.Find(objectId); NormObject* obj = tx_table.Find(objectId);
NormObjectTable::Iterator iterator(tx_table); NormObjectTable::Iterator iterator(tx_table);
@ -1933,9 +1935,9 @@ bool NormSession::ServerBuildRepairAdv(NormCmdRepairAdvMsg& cmd)
return true; return true;
} // end NormSession::ServerBuildRepairAdv() } // end NormSession::ServerBuildRepairAdv()
bool NormSession::OnRepairTimeout() bool NormSession::OnRepairTimeout(ProtoTimer& /*theTimer*/)
{ {
if (repair_timer.RepeatCount()) if (repair_timer.GetRepeatCount())
{ {
// NACK aggregation period has ended. (incorporate accumulated repair requests) // NACK aggregation period has ended. (incorporate accumulated repair requests)
DMSG(4, "NormSession::OnRepairTimeout() node>%lu server NACK aggregation time ended.\n", DMSG(4, "NormSession::OnRepairTimeout() node>%lu server NACK aggregation time ended.\n",
@ -1994,9 +1996,9 @@ bool NormSession::OnRepairTimeout()
} // end NormSession::OnRepairTimeout() } // end NormSession::OnRepairTimeout()
// (TBD) Should pass current system time to ProtocolTimer timeout handlers // (TBD) Should pass current system time to ProtoTimer timeout handlers
// for more efficiency ... // for more efficiency ...
bool NormSession::OnTxTimeout() bool NormSession::OnTxTimeout(ProtoTimer& /*theTimer*/)
{ {
NormMsg* msg; NormMsg* msg;
@ -2004,12 +2006,13 @@ bool NormSession::OnTxTimeout()
NormCmdRepairAdvMsg adv; NormCmdRepairAdvMsg adv;
if (advertise_repairs && (probe_proactive || (repair_timer.IsActive() && if (advertise_repairs && (probe_proactive || (repair_timer.IsActive() &&
repair_timer.RepeatCount()))) repair_timer.GetRepeatCount())))
{ {
// Build a NORM_CMD(NACK_ADV) in response to // Build a NORM_CMD(NACK_ADV) in response to
// receipt of unicast NACK or CC update // receipt of unicast NACK or CC update
adv.Init(); adv.Init();
adv.SetGrtt(grtt_quantized); adv.SetGrtt(grtt_quantized);
adv.SetBackoffFactor((unsigned char)backoff_factor);
adv.SetGroupSize(gsize_quantized); adv.SetGroupSize(gsize_quantized);
adv.SetDestination(address); adv.SetDestination(address);
@ -2044,11 +2047,19 @@ bool NormSession::OnTxTimeout()
if (msg) if (msg)
{ {
SendMessage(*msg); if (SendMessage(*msg))
if (advertise_repairs) {
advertise_repairs = false; if (advertise_repairs)
advertise_repairs = false;
else
ReturnMessageToPool(msg);
}
else else
ReturnMessageToPool(msg); {
// Requeue the message for another try
if (!advertise_repairs)
message_queue.Prepend(msg);
}
return true; // reinstall tx_timer return true; // reinstall tx_timer
} }
else else
@ -2068,16 +2079,15 @@ bool NormSession::OnTxTimeout()
else else
{ {
// We have a new message as a result of serving, so send it immediately // We have a new message as a result of serving, so send it immediately
OnTxTimeout(); return OnTxTimeout(tx_timer);
return true;
} }
} }
} // end NormSession::OnTxTimeout() } // end NormSession::OnTxTimeout()
void NormSession::SendMessage(NormMsg& msg) bool NormSession::SendMessage(NormMsg& msg)
{ {
struct timeval currentTime; struct timeval currentTime;
GetSystemTime(&currentTime); ProtoSystemTime(currentTime);
bool clientMsg = false; bool clientMsg = false;
@ -2134,61 +2144,65 @@ void NormSession::SendMessage(NormMsg& msg)
msg.SetSequence(tx_sequence++); msg.SetSequence(tx_sequence++);
msg.SetSourceId(local_node_id); msg.SetSourceId(local_node_id);
UINT16 msgSize = msg.GetLength(); UINT16 msgSize = msg.GetLength();
bool result = true;
// Drop some tx messages for testing purposes // Drop some tx messages for testing purposes
bool drop = (UniformRand(100.0) < tx_loss_rate); bool drop = (UniformRand(100.0) < tx_loss_rate);
if (drop || (clientMsg && client_silent)) if (drop || (clientMsg && client_silent))
{ {
//TRACE("TX MESSAGE DROPPED! (tx_loss_rate:%lf\n", tx_loss_rate); //TRACE("TX MESSAGE DROPPED! (tx_loss_rate:%lf\n", tx_loss_rate);
} }
else else
{ {
if (UDP_SOCKET_ERROR_NONE != tx_socket.SendTo(&msg.GetDestination(), if (tx_socket.SendTo(msg.GetBuffer(),
msg.GetBuffer(), msgSize,
msgSize)) msg.GetDestination()))
{
DMSG(0, "NormSession::SendMessage() sendto() error\n");
}
else
{ {
// Separate send/recv tracing // Separate send/recv tracing
if (trace) NormTrace(currentTime, LocalNodeId(), msg, true); if (trace) NormTrace(currentTime, LocalNodeId(), msg, true);
}
// Keep track of _actual_ sent rate // Keep track of _actual_ sent rate
double interval; double interval;
if (prev_update_time.tv_sec || prev_update_time.tv_usec) if (prev_update_time.tv_sec || prev_update_time.tv_usec)
{ {
interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec); interval = (double)(currentTime.tv_sec - prev_update_time.tv_sec);
if (currentTime.tv_usec > prev_update_time.tv_sec) if (currentTime.tv_usec > prev_update_time.tv_sec)
interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec); interval += 1.0e-06*(double)(currentTime.tv_usec - prev_update_time.tv_usec);
else
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec);
}
else else
interval -= 1.0e-06*(double)(prev_update_time.tv_usec - currentTime.tv_usec); {
sent_rate = ((double)msgSize) / grtt_advertised;
interval = -1.0;
prev_update_time = currentTime;
}
if (interval < grtt_advertised)
{
sent_accumulator += msgSize;
}
else
{
sent_rate = ((double)(sent_accumulator+msgSize)) / interval;
prev_update_time = currentTime;
sent_accumulator = 0;
}
// Update nominal packet size
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
} }
else else
{ {
sent_rate = ((double)msgSize) / grtt_advertised; DMSG(8, "NormSession::SendMessage() sendto() error\n");
interval = -1.0; result = false;
prev_update_time = currentTime;
}
if (interval < grtt_advertised)
{
sent_accumulator += msgSize;
}
else
{
sent_rate = ((double)(sent_accumulator+msgSize)) / interval;
prev_update_time = currentTime;
sent_accumulator = 0;
} }
} }
nominal_packet_size += 0.05 * (((double)msgSize) - nominal_packet_size);
tx_timer.SetInterval(((double)msgSize) / tx_rate); tx_timer.SetInterval(((double)msgSize) / tx_rate);
return result;
} // end NormSession::SendMessage() } // end NormSession::SendMessage()
bool NormSession::OnProbeTimeout() bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
{ {
// 1) Update grtt_estimate _if_ sufficient time elapsed. // 1) Update grtt_estimate _if_ sufficient time elapsed.
grtt_age += probe_timer.Interval(); grtt_age += probe_timer.GetInterval();
if (grtt_age >= grtt_interval) if (grtt_age >= grtt_interval)
{ {
if (grtt_response) if (grtt_response)
@ -2247,6 +2261,7 @@ bool NormSession::OnProbeTimeout()
cmd->Init(); cmd->Init();
cmd->SetDestination(address); cmd->SetDestination(address);
cmd->SetGrtt(grtt_quantized); cmd->SetGrtt(grtt_quantized);
cmd->SetBackoffFactor((unsigned char)backoff_factor);
cmd->SetGroupSize(gsize_quantized); cmd->SetGroupSize(gsize_quantized);
// SetSendTime() when message is being sent (in OnTxTimeout()) // SetSendTime() when message is being sent (in OnTxTimeout())
cmd->SetCCSequence(cc_sequence++); cmd->SetCCSequence(cc_sequence++);
@ -2276,7 +2291,7 @@ bool NormSession::OnProbeTimeout()
UINT16 rateQuantized = NormQuantizeRate(next->GetRate()); UINT16 rateQuantized = NormQuantizeRate(next->GetRate());
// (TBD) check result // (TBD) check result
cmd->AppendCCNode(segment_size, cmd->AppendCCNode(segment_size,
next->Id(), next->GetId(),
ccFlags, ccFlags,
rttQuantized, rttQuantized,
rateQuantized); rateQuantized);
@ -2368,16 +2383,16 @@ void NormSession::AdjustRate(bool onResponse)
tx_rate = MAX(tx_rate, minRate); tx_rate = MAX(tx_rate, minRate);
struct timeval currentTime; struct timeval currentTime;
::GetSystemTime(&currentTime); ::ProtoSystemTime(currentTime);
double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec); double theTime = (double)currentTime.tv_sec + 1.0e-06 * ((double)currentTime.tv_usec);
DMSG(6, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n", theTime, tx_rate * (8.0/1000.0), ccRtt, ccLoss); DMSG(6, "ServerRateTracking time>%lf rate>%lf rtt>%lf loss>%lf\n", theTime, tx_rate * (8.0/1000.0), ccRtt, ccLoss);
} // end NormSession::AdjustRate() } // end NormSession::AdjustRate()
bool NormSession::OnReportTimeout() bool NormSession::OnReportTimeout(ProtoTimer& /*theTimer*/)
{ {
// Client reporting (just print out for now) // Client reporting (just print out for now)
struct timeval currentTime; struct timeval currentTime;
GetSystemTime(&currentTime); ProtoSystemTime(currentTime);
struct tm* ct = gmtime((time_t*)&currentTime.tv_sec); struct tm* ct = gmtime((time_t*)&currentTime.tv_sec);
DMSG(2, "Report time>%02d:%02d:%02d.%06lu node>%lu ***************************************\n", DMSG(2, "Report time>%02d:%02d:%02d.%06lu node>%lu ***************************************\n",
ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, LocalNodeId()); ct->tm_hour, ct->tm_min, ct->tm_sec, currentTime.tv_usec, LocalNodeId());
@ -2387,9 +2402,9 @@ bool NormSession::OnReportTimeout()
NormServerNode* next; NormServerNode* next;
while ((next = (NormServerNode*)iterator.GetNextNode())) while ((next = (NormServerNode*)iterator.GetNextNode()))
{ {
DMSG(2, "Remote server:%lu\n", next->Id()); DMSG(2, "Remote server:%lu\n", next->GetId());
double rxRate = 8.0e-03*((double)next->RecvTotal()) / report_timer.Interval(); // kbps double rxRate = 8.0e-03*((double)next->RecvTotal()) / report_timer.GetInterval(); // kbps
double rxGoodput = 8.0e-03*((double)next->RecvGoodput()) / report_timer.Interval(); // kbps double rxGoodput = 8.0e-03*((double)next->RecvGoodput()) / report_timer.GetInterval(); // kbps
next->ResetRecvStats(); next->ResetRecvStats();
DMSG(2, " rx_rate>%9.3lf kbps rx_goodput>%9.3lf kbps\n", rxRate, rxGoodput); DMSG(2, " rx_rate>%9.3lf kbps rx_goodput>%9.3lf kbps\n", rxRate, rxGoodput);
DMSG(2, " objects completed>%lu pending>%lu failed:%lu\n", DMSG(2, " objects completed>%lu pending>%lu failed:%lu\n",
@ -2406,8 +2421,9 @@ bool NormSession::OnReportTimeout()
return true; return true;
} // end NormSession::OnReportTimeout() } // end NormSession::OnReportTimeout()
NormSessionMgr::NormSessionMgr() NormSessionMgr::NormSessionMgr(ProtoTimerMgr& timerMgr,
: socket_installer(NULL), socket_install_data(NULL), ProtoSocket::Notifier& socketNotifier)
: timer_mgr(timerMgr), socket_notifier(socketNotifier),
controller(NULL), top_session(NULL) controller(NULL), top_session(NULL)
{ {
} }
@ -2434,8 +2450,8 @@ NormSession* NormSessionMgr::NewSession(const char* sessionAddress,
if (NORM_NODE_ANY == localNodeId) if (NORM_NODE_ANY == localNodeId)
{ {
// Use local ip address to assign default localNodeId // Use local ip address to assign default localNodeId
NetworkAddress localAddr; ProtoAddress localAddr;
if (!localAddr.LookupLocalHostAddress()) if (!localAddr.ResolveLocalAddress())
{ {
DMSG(0, "NormSessionMgr::NewSession() local address lookup error\n"); DMSG(0, "NormSessionMgr::NewSession() local address lookup error\n");
return ((NormSession*)NULL); return ((NormSession*)NULL);
@ -2443,8 +2459,8 @@ NormSession* NormSessionMgr::NewSession(const char* sessionAddress,
// (TBD) test IPv6 "EndIdentifier" ??? // (TBD) test IPv6 "EndIdentifier" ???
localNodeId = localAddr.EndIdentifier(); localNodeId = localAddr.EndIdentifier();
} }
NetworkAddress theAddress; ProtoAddress theAddress;
if (!theAddress.LookupHostAddress(sessionAddress)) if (!theAddress.ResolveFromString(sessionAddress))
{ {
DMSG(0, "NormSessionMgr::NewSession() session address lookup error!\n"); DMSG(0, "NormSessionMgr::NewSession() session address lookup error!\n");
return ((NormSession*)NULL); return ((NormSession*)NULL);

View File

@ -6,9 +6,7 @@
#include "normNode.h" #include "normNode.h"
#include "normEncoder.h" #include "normEncoder.h"
#include "protocolTimer.h" #include "protokit.h"
#include "udpSocket.h"
class NormController class NormController
{ {
@ -34,19 +32,11 @@ class NormSessionMgr
{ {
friend class NormSession; friend class NormSession;
public: public:
NormSessionMgr(); NormSessionMgr(ProtoTimerMgr& timerMgr,
ProtoSocket::Notifier& socketNotifier);
~NormSessionMgr(); ~NormSessionMgr();
void Init(ProtocolTimerInstallFunc* timerInstaller, void SetController(NormController* theController)
const void* timerInstallData, {controller = theController;}
UdpSocketInstallFunc* socketInstaller,
void* socketInstallData,
NormController* theController)
{
timer_mgr.SetInstaller(timerInstaller, timerInstallData);
socket_installer = socketInstaller;
socket_install_data = socketInstallData;
controller = theController;
}
void Destroy(); void Destroy();
class NormSession* NewSession(const char* sessionAddress, class NormSession* NewSession(const char* sessionAddress,
@ -55,10 +45,6 @@ class NormSessionMgr
NORM_NODE_ANY); NORM_NODE_ANY);
void DeleteSession(class NormSession* theSession); void DeleteSession(class NormSession* theSession);
UdpSocketInstallFunc* SocketInstaller() {return socket_installer;}
const void* SocketInstallData() {return socket_install_data;}
void Notify(NormController::Event event, void Notify(NormController::Event event,
class NormSession* session, class NormSession* session,
class NormServerNode* server, class NormServerNode* server,
@ -68,12 +54,13 @@ class NormSessionMgr
controller->Notify(event, this, session, server, object); controller->Notify(event, this, session, server, object);
} }
void InstallTimer(ProtocolTimer* timer) {timer_mgr.InstallTimer(timer);} void ActivateTimer(ProtoTimer& timer) {timer_mgr.ActivateTimer(timer);}
ProtoTimerMgr& GetTimerMgr() {return timer_mgr;}
ProtoSocket::Notifier& GetSocketNotifier() {return socket_notifier;}
private: private:
ProtocolTimerMgr timer_mgr; ProtoTimerMgr& timer_mgr;
UdpSocketInstallFunc* socket_installer; ProtoSocket::Notifier& socket_notifier;
const void* socket_install_data;
NormController* controller; NormController* controller;
class NormSession* top_session; // top of NormSession list class NormSession* top_session; // top of NormSession list
@ -104,8 +91,8 @@ class NormSession
bool Open(); bool Open();
void Close(); void Close();
bool IsOpen() {return (rx_socket.IsOpen() || tx_socket.IsOpen());} bool IsOpen() {return (rx_socket.IsOpen() || tx_socket.IsOpen());}
const NetworkAddress& Address() {return address;} const ProtoAddress& Address() {return address;}
void SetAddress(const NetworkAddress& addr) {address = addr;} void SetAddress(const ProtoAddress& addr) {address = addr;}
static double CalculateRate(double size, double rtt, double loss); static double CalculateRate(double size, double rtt, double loss);
@ -135,9 +122,8 @@ class NormSession
NormMsg* GetMessageFromPool() {return message_pool.RemoveHead();} NormMsg* GetMessageFromPool() {return message_pool.RemoveHead();}
void ReturnMessageToPool(NormMsg* msg) {message_pool.Append(msg);} void ReturnMessageToPool(NormMsg* msg) {message_pool.Append(msg);}
void QueueMessage(NormMsg* msg); void QueueMessage(NormMsg* msg);
void SendMessage(NormMsg& msg); bool SendMessage(NormMsg& msg);
void InstallTimer(ProtocolTimer* timer) void ActivateTimer(ProtoTimer& timer) {session_mgr.ActivateTimer(timer);}
{session_mgr.InstallTimer(timer);}
// Server methods // Server methods
void ServerSetBaseObjectId(NormObjectId baseId) void ServerSetBaseObjectId(NormObjectId baseId)
@ -195,7 +181,7 @@ class NormSession
if (!tx_timer.IsActive()) if (!tx_timer.IsActive())
{ {
tx_timer.SetInterval(0.0); tx_timer.SetInterval(0.0);
InstallTimer(&tx_timer); ActivateTimer(tx_timer);
} }
} }
@ -227,7 +213,7 @@ class NormSession
// Simulation specific methods // Simulation specific methods
NormSimObject* QueueTxSim(unsigned long objectSize); NormSimObject* QueueTxSim(unsigned long objectSize);
bool SimSocketRecvHandler(char* buffer, unsigned short buflen, bool SimSocketRecvHandler(char* buffer, unsigned short buflen,
const NetworkAddress& src, bool unicast); const ProtoAddress& src, bool unicast);
#endif // SIMULATE #endif // SIMULATE
private: private:
@ -239,15 +225,15 @@ class NormSession
bool QueueTxObject(NormObject* obj, bool touchServer = true); bool QueueTxObject(NormObject* obj, bool touchServer = true);
void DeleteTxObject(NormObject* obj); void DeleteTxObject(NormObject* obj);
bool OnTxTimeout(); bool OnTxTimeout(ProtoTimer& theTimer);
bool OnRepairTimeout(); bool OnRepairTimeout(ProtoTimer& theTimer);
bool OnFlushTimeout(); bool OnFlushTimeout(ProtoTimer& theTimer);
bool OnWatermarkTimeout(); bool OnWatermarkTimeout(ProtoTimer& theTimer);
bool OnProbeTimeout(); bool OnProbeTimeout(ProtoTimer& theTimer);
bool OnReportTimeout(); bool OnReportTimeout(ProtoTimer& theTimer);
bool TxSocketRecvHandler(UdpSocket* theSocket); void TxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
bool RxSocketRecvHandler(UdpSocket* theSocket); void RxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEve);
void HandleReceiveMessage(NormMsg& msg, bool wasUnicast); void HandleReceiveMessage(NormMsg& msg, bool wasUnicast);
// Server message handling routines // Server message handling routines
@ -264,7 +250,7 @@ class NormSession
double ccRtt, double ccRtt,
double ccLoss, double ccLoss,
double ccRate, double ccRate,
UINT8 ccSequence); UINT16 ccSequence);
void AdjustRate(bool onResponse); void AdjustRate(bool onResponse);
bool ServerQueueSquelch(NormObjectId objectId); bool ServerQueueSquelch(NormObjectId objectId);
void ServerQueueFlush(); void ServerQueueFlush();
@ -283,17 +269,17 @@ class NormSession
NormSessionMgr& session_mgr; NormSessionMgr& session_mgr;
bool notify_pending; bool notify_pending;
ProtocolTimer tx_timer; ProtoTimer tx_timer;
UdpSocket tx_socket; ProtoSocket tx_socket;
UdpSocket rx_socket; ProtoSocket rx_socket;
NormMessageQueue message_queue; NormMessageQueue message_queue;
NormMessageQueue message_pool; NormMessageQueue message_pool;
ProtocolTimer report_timer; ProtoTimer report_timer;
UINT16 tx_sequence; UINT16 tx_sequence;
// General session parameters // General session parameters
NormNodeId local_node_id; NormNodeId local_node_id;
NetworkAddress address; // session destination address ProtoAddress address; // session destination address
UINT8 ttl; // session multicast ttl UINT8 ttl; // session multicast ttl
double tx_rate; // bytes per second double tx_rate; // bytes per second
double backoff_factor; double backoff_factor;
@ -310,7 +296,7 @@ class NormSession
NormObjectTable tx_table; NormObjectTable tx_table;
NormSlidingMask tx_pending_mask; NormSlidingMask tx_pending_mask;
NormSlidingMask tx_repair_mask; NormSlidingMask tx_repair_mask;
ProtocolTimer repair_timer; ProtoTimer repair_timer;
NormBlockPool block_pool; NormBlockPool block_pool;
NormSegmentPool segment_pool; NormSegmentPool segment_pool;
NormEncoder encoder; NormEncoder encoder;
@ -319,10 +305,10 @@ class NormSession
unsigned int tx_cache_count_min; unsigned int tx_cache_count_min;
unsigned int tx_cache_count_max; unsigned int tx_cache_count_max;
NormObjectSize tx_cache_size_max; NormObjectSize tx_cache_size_max;
ProtocolTimer flush_timer; ProtoTimer flush_timer;
int flush_count; int flush_count;
bool posted_tx_queue_empty; bool posted_tx_queue_empty;
ProtocolTimer watermark_timer; ProtoTimer watermark_timer;
int watermark_count; int watermark_count;
// (TBD) watermark_object_id, watermark_block_id, watermark_symbol_id // (TBD) watermark_object_id, watermark_block_id, watermark_symbol_id
@ -332,7 +318,7 @@ class NormSession
double suppress_rate; double suppress_rate;
double suppress_rtt; double suppress_rtt;
ProtocolTimer probe_timer; // GRTT/congestion control probes ProtoTimer probe_timer; // GRTT/congestion control probes
bool probe_proactive; bool probe_proactive;
double grtt_interval; // current GRTT update interval double grtt_interval; // current GRTT update interval

View File

@ -6,11 +6,9 @@
// of a message stream from the MGEN simulation agent with restrictions. The // of a message stream from the MGEN simulation agent with restrictions. The
// current restriction is the MGEN simulation agent // current restriction is the MGEN simulation agent
NormSimAgent::NormSimAgent(ProtocolTimerInstallFunc* timerInstaller, NormSimAgent::NormSimAgent(ProtoTimerMgr& timerMgr,
const void* timerInstallData, ProtoSocket::Notifier& socketNotifier)
UdpSocketInstallFunc* socketInstaller, : session_mgr(timerMgr, socketNotifier), session(NULL),
void* socketInstallData)
: session(NULL),
address(NULL), port(0), ttl(3), address(NULL), port(0), ttl(3),
tx_rate(NormSession::DEFAULT_TRANSMIT_RATE), tx_rate(NormSession::DEFAULT_TRANSMIT_RATE),
cc_enable(false), unicast_nacks(false), silent_client(false), cc_enable(false), unicast_nacks(false), silent_client(false),
@ -25,12 +23,12 @@ NormSimAgent::NormSimAgent(ProtocolTimerInstallFunc* timerInstaller,
tracing(false), tx_loss(0.0), rx_loss(0.0) tracing(false), tx_loss(0.0), rx_loss(0.0)
{ {
// Bind NormSessionMgr to this agent and simulation environment // Bind NormSessionMgr to this agent and simulation environment
session_mgr.Init(timerInstaller, timerInstallData, session_mgr.SetController(static_cast<NormController*>(this));
socketInstaller, socketInstallData,
static_cast<NormController*>(this)); interval_timer.SetListener(this, (ProtoTimer::TimeoutHandler)&NormSimAgent::OnIntervalTimeout);
interval_timer.SetInterval(0.0);
interval_timer.SetRepeat(0);
interval_timer.Init(0.0, 0, (ProtocolTimerOwner*)this,
(ProtocolTimeoutFunc)&NormSimAgent::OnIntervalTimeout);
memset(mgen_buffer, 0, 64); memset(mgen_buffer, 0, 64);
} }
@ -589,9 +587,9 @@ void NormSimAgent::Notify(NormController::Event event,
else else
{ {
// Schedule or queue next "sim file" transmission // Schedule or queue next "sim file" transmission
if (interval_timer.Interval() > 0.0) if (interval_timer.GetInterval() > 0.0)
{ {
InstallTimer(interval_timer); ActivateTimer(interval_timer);
} }
else else
{ {
@ -735,7 +733,9 @@ void NormSimAgent::Notify(NormController::Event event,
} }
if (msg_sync && (0 == mgen_pending_bytes)) if (msg_sync && (0 == mgen_pending_bytes))
{ {
const NetworkAddress& srcAddr = server->GetAddress(); ProtoAddress srcAddr;
srcAddr.ResolveFromString(server->GetAddress().GetHostString());
srcAddr.SetPort(server->GetAddress().GetPort());
mgen->HandleMgenMessage(mgen_buffer, mgen_bytes, srcAddr); mgen->HandleMgenMessage(mgen_buffer, mgen_bytes, srcAddr);
mgen_bytes = 0; mgen_bytes = 0;
} }

View File

@ -1,9 +1,8 @@
// normSimAgent.h - Generic (base class) NORM simulation agent // normSimAgent.h - Generic (base class) NORM simulation agent
#include "protoLib.h"
#include "protoSim.h"
#include "normSession.h" #include "normSession.h"
#include "protokit.h"
#include "mgen.h" // for MGEN instance attachment #include "mgen.h" // for MGEN instance attachment
@ -25,10 +24,8 @@ class NormSimAgent : public NormController
void AttachMgen(Mgen* mgenInstance) {mgen = mgenInstance;} void AttachMgen(Mgen* mgenInstance) {mgen = mgenInstance;}
protected: protected:
NormSimAgent(ProtocolTimerInstallFunc* timerInstaller, NormSimAgent(ProtoTimerMgr& timerMgr,
const void* timerInstallData, ProtoSocket::Notifier& socketNotifier);
UdpSocketInstallFunc* socketInstaller,
void* socketInstallData);
enum CmdType {CMD_INVALID, CMD_NOARG, CMD_ARG}; enum CmdType {CMD_INVALID, CMD_NOARG, CMD_ARG};
CmdType CommandType(const char* cmd); CmdType CommandType(const char* cmd);
virtual unsigned long GetAgentId() = 0; virtual unsigned long GetAgentId() = 0;
@ -42,8 +39,8 @@ class NormSimAgent : public NormController
class NormServerNode* server, class NormServerNode* server,
class NormObject* object); class NormObject* object);
void InstallTimer(ProtocolTimer& theTimer) void ActivateTimer(ProtoTimer& theTimer)
{session_mgr.InstallTimer(&theTimer);} {session_mgr.ActivateTimer(theTimer);}
bool OnIntervalTimeout(); bool OnIntervalTimeout();
@ -88,7 +85,7 @@ class NormSimAgent : public NormController
unsigned int mgen_bytes; unsigned int mgen_bytes;
unsigned int mgen_pending_bytes; unsigned int mgen_pending_bytes;
ProtocolTimer interval_timer; ProtoTimer interval_timer;
// protocol debug parameters // protocol debug parameters
bool tracing; bool tracing;

Binary file not shown.

View File

@ -32,6 +32,6 @@
#ifndef _NORM_VERSION #ifndef _NORM_VERSION
#define _NORM_VERSION #define _NORM_VERSION
#define VERSION "1.0b2" #define VERSION "1.1b1"
#endif // _NORM_VERSION #endif // _NORM_VERSION

576
ns/ns226-Makefile.in Normal file
View File

@ -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

View File

@ -45,10 +45,7 @@ static class NsNormAgentClass : public TclClass
NsNormAgent::NsNormAgent() NsNormAgent::NsNormAgent()
: NormSimAgent(ProtoSimAgent::TimerInstaller, : NormSimAgent(GetTimerMgr(), GetSocketNotifier())
static_cast<ProtoSimAgent*>(this),
ProtoSimAgent::SocketInstaller,
static_cast<ProtoSimAgent*>(this))
{ {
} }
@ -57,7 +54,25 @@ NsNormAgent::~NsNormAgent()
{ {
} }
int NsNormAgent::command(int argc, const char*const* argv) bool NsNormAgent::OnStartup(int argc, const char*const* argv)
{
if (ProcessCommands(argc, argv))
{
return true;
}
else
{
fprintf(stderr, "NsNormAgent::OnStartup() error processing commands\n");
return false;
}
} // end NsNormAgent::OnStartup()
void NsNormAgent::OnShutdown()
{
NormSimAgent::Stop();
} // end NsNormAgent::OnShutdown()
bool NsNormAgent::ProcessCommands(int argc, const char*const* argv)
{ {
// Process commands, passing unknown commands to base Agent class // Process commands, passing unknown commands to base Agent class
int i = 1; int i = 1;
@ -70,8 +85,8 @@ int NsNormAgent::command(int argc, const char*const* argv)
// Attach Agent/MGEN to this NormSimAgent // Attach Agent/MGEN to this NormSimAgent
if (++i >= argc) if (++i >= argc)
{ {
DMSG(0, "NsNormAgent::command() ProcessCommand(attach-mgen) error: insufficent arguments\n"); DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(attach-mgen) error: insufficent arguments\n");
return TCL_ERROR; return false;
} }
Tcl& tcl = Tcl::instance(); Tcl& tcl = Tcl::instance();
NsMgenAgent* mgenAgent = dynamic_cast<NsMgenAgent*> (tcl.lookup(argv[i])); NsMgenAgent* mgenAgent = dynamic_cast<NsMgenAgent*> (tcl.lookup(argv[i]));
@ -83,8 +98,8 @@ int NsNormAgent::command(int argc, const char*const* argv)
} }
else else
{ {
DMSG(0, "NsNormAgent::command() ProcessCommand(attach-mgen) error: invalid mgen agent\n"); DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(attach-mgen) error: invalid mgen agent\n");
return TCL_ERROR; return false;
} }
} }
else if (!strcmp(argv[i], "active")) else if (!strcmp(argv[i], "active"))
@ -105,9 +120,9 @@ int NsNormAgent::command(int argc, const char*const* argv)
case NormSimAgent::CMD_NOARG: case NormSimAgent::CMD_NOARG:
if (!ProcessCommand(argv[i], NULL)) if (!ProcessCommand(argv[i], NULL))
{ {
DMSG(0, "NsNormAgent::command() ProcessCommand(%s) error\n", DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(%s) error\n",
argv[i]); argv[i]);
return TCL_ERROR; return false;
} }
i++; i++;
break; break;
@ -115,23 +130,23 @@ int NsNormAgent::command(int argc, const char*const* argv)
case NormSimAgent::CMD_ARG: case NormSimAgent::CMD_ARG:
if (!ProcessCommand(argv[i], argv[i+1])) if (!ProcessCommand(argv[i], argv[i+1]))
{ {
DMSG(0, "NsNormAgent::command() ProcessCommand(%s, %s) error\n", DMSG(0, "NsNormAgent::ProcessCommands() ProcessCommand(%s, %s) error\n",
argv[i], argv[i+1]); argv[i], argv[i+1]);
return TCL_ERROR; return false;
} }
i += 2; i += 2;
break; break;
case NormSimAgent::CMD_INVALID: case NormSimAgent::CMD_INVALID:
return NsProtoAgent::command(argc, argv); return false;
} }
} }
return TCL_OK; return true;
} // end NsNormAgent::command() } // end NsNormAgent::ProcessCommands()
bool NsNormAgent::SendMgenMessage(const NetworkAddress* dstAddr, bool NsNormAgent::SendMgenMessage(const char* txBuffer,
const char* txBuffer, unsigned int len,
unsigned int len) const ProtoAddress& /*dstAddr*/)
{ {
return SendMessage(len, txBuffer); return SendMessage(len, txBuffer);
} // end NsNormAgent::SendMgenMessage() } // end NsNormAgent::SendMgenMessage()

View File

@ -33,7 +33,7 @@
#ifndef _NS_NORM_AGENT #ifndef _NS_NORM_AGENT
#define _NS_NORM_AGENT #define _NS_NORM_AGENT
#include "nsProtoAgent.h" // from ProtoLib #include "nsProtoSimAgent.h" // from Protolib
#include "normSimAgent.h" #include "normSimAgent.h"
#include "nsMgenAgent.h" #include "nsMgenAgent.h"
@ -44,20 +44,23 @@
// IMPORTANT NOTE! NsProtoAgent must be listed _first_ here // IMPORTANT NOTE! NsProtoAgent must be listed _first_ here
// (because we can't dynamic_cast install_data void* pointers) // (because we can't dynamic_cast install_data void* pointers)
class NsNormAgent : public NsProtoAgent, public NormSimAgent, public MgenSink class NsNormAgent : public NsProtoSimAgent, public NormSimAgent, public MgenSink
{ {
public: public:
NsNormAgent(); NsNormAgent();
~NsNormAgent(); ~NsNormAgent();
// NsProtoAgent base class override // NsProtoSimAgent base class overrides
int command(int argc, const char*const* argv); virtual bool OnStartup(int argc, const char*const* argv);
virtual bool ProcessCommands(int argc, const char*const* argv);
virtual void OnShutdown();
// NormSimAgent override // NormSimAgent override
unsigned long GetAgentId() {return (unsigned long)addr();} unsigned long GetAgentId() {return (unsigned long)addr();}
// MgenSink override // MgenSink override
bool SendMgenMessage(const NetworkAddress* dstAddr, bool SendMgenMessage(const char* txBuffer,
const char* txBuffer, unsigned int len,
unsigned int len); const ProtoAddress& dstAddr);
}; // end class NsNormAgent }; // end class NsNormAgent

View File

@ -18,7 +18,7 @@ CFLAGS = -g -DPROTO_DEBUG -DUNIX -O -fPIC $(SYSTEM_HAVES) $(INCLUDES)
LDFLAGS = $(SYSTEM_LDFLAGS) LDFLAGS = $(SYSTEM_LDFLAGS)
# Note: Even command line app needs X11 for Netscape post-processing # Note: Even command line app needs X11 for Netscape post-processing
LIBS = $(SYSTEM_LIBS) -lm LIBS = $(SYSTEM_LIBS) -lm -lpthread
XLIBS = -lXmu -lXt -lX11 XLIBS = -lXmu -lXt -lX11
#NOTE: TK_LIB must come before TCL_LIB for some reason #NOTE: TK_LIB must come before TCL_LIB for some reason
@ -47,9 +47,9 @@ TARGETS = mdp tkMdp
$(CC) -c $(CFLAGS) -o $*.o $*.cpp $(CC) -c $(CFLAGS) -o $*.o $*.cpp
# MDP depends upon the NRL Protean Group's development library # MDP depends upon the NRL Protean Group's development library
LIBPROTO = $(PROTOLIB)/unix/libProto.a LIBPROTO = $(PROTOLIB)/unix/libProtokit.a
$(PROTOLIB)/unix/libProto.a: $(PROTOLIB)/unix/libProtokit.a:
cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProto.a cd $(PROTOLIB)/unix; $(MAKE) -f Makefile.$(SYSTEM) libProtokit.a
NORM_SRC = $(COMMON)/normMessage.cpp $(COMMON)/normSession.cpp \ NORM_SRC = $(COMMON)/normMessage.cpp $(COMMON)/normSession.cpp \
$(COMMON)/normNode.cpp $(COMMON)/normObject.cpp \ $(COMMON)/normNode.cpp $(COMMON)/normObject.cpp \
@ -77,7 +77,8 @@ libnormSim.a: $(SIM_OBJ)
ranlib $@ ranlib $@
# (mdp) command-line file broadcaster/receiver # (mdp) command-line file broadcaster/receiver
APP_SRC = $(COMMON)/normApp.cpp $(COMMON)/normPostProcess.cpp APP_SRC = $(COMMON)/normApp.cpp $(COMMON)/normPostProcess.cpp \
$(UNIX)/unixPostProcess.cpp
APP_OBJ = $(APP_SRC:.cpp=.o) APP_OBJ = $(APP_SRC:.cpp=.o)
norm: $(APP_OBJ) libnorm.a $(LIBPROTO) norm: $(APP_OBJ) libnorm.a $(LIBPROTO)

View File

@ -2,37 +2,14 @@
# FreeBSD Protean Makefile definitions # FreeBSD Protean Makefile definitions
# #
# TO BUILD THE TK GUI VERSION, EDIT THE FOLLOWING NUMBERED # 1) System specific additional libraries, include paths, etc
# ITEMS AS NEEDED FOR YOUR SYSTEM
# (This has only been tested with TCL/TK 8.0 but it probably
# will work with Tcl7.x/Tk4.x with a little tweaking to
# the list of TCL_SCRIPTS (library scripts) given below)
# 1) Where to find the Tcl standard library scripts
# (e.g. init.tcl, ...)
TCL_SCRIPT_PATH = /usr/local/lib/tcl8.0
# 2) Where to find the Tk standard library scripts
# (e.g. button.tcl, entry.tcl, ...)
TK_SCRIPT_PATH = /usr/local/lib/tk8.0
# 3) Where to find Tcl/Tk header files
# (e.g. tcl.h, tk.h, ...)
TCL_INCL_PATH = -I/usr/local/include/tcl8.0 -I/usr/local/include/tk8.0
# 4) Point to specific libtcl.a and libtk.a to use
TCL_LIB = /usr/local/lib/libtcl80.a
TK_LIB = /usr/local/lib/libtk80.a
# 5) System specific additional libraries, include paths, etc
# (Where to find X11 libraries, etc) # (Where to find X11 libraries, etc)
# #
SYSTEM_INCLUDES = -I/usr/X11R6/include SYSTEM_INCLUDES =
SYSTEM_LDFLAGS = -L/usr/X11R6/lib SYSTEM_LDFLAGS =
SYSTEM_LIBS = SYSTEM_LIBS =
# 6) System specific capabilities # 2) System specific capabilities
# Must choose appropriate for the following: # Must choose appropriate for the following:
# #
# A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin()
@ -48,7 +25,7 @@ SYSTEM_LIBS =
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
# routine. # routine.
# #
# E) The MDP code's use of offset pointers requires special treatment # E) The PROTOLIB code's use of offset pointers requires special treatment
# for some different compilers. Set -DUSE_INHERITANCE for some # for some different compilers. Set -DUSE_INHERITANCE for some
# to keep some compilers (gcc 2.7.2) happy. # to keep some compilers (gcc 2.7.2) happy.
# #
@ -62,10 +39,13 @@ SYSTEM_LIBS =
# (We export these for other Makefiles as needed) # (We export these for other Makefiles as needed)
# #
export SYSTEM_HAVES = -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC) SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC)
export CC = gcc SYSTEM_SRC = bsdRouteMgr.cpp
export RANLIB = ranlib
export AR = ar SYSTEM = freebsd
CC = gcc
RANLIB = ranlib
AR = ar
include Makefile.common include Makefile.common

View File

@ -28,7 +28,7 @@ TK_LIB = -ltk #/usr/local/lib/libtk8.0.a
# 5) System specific additional libraries, include paths, etc # 5) System specific additional libraries, include paths, etc
# (Where to find X11 libraries, etc) # (Where to find X11 libraries, etc)
# #
SYSTEM_INCLUDES = -I/usr/X11R6/include SYSTEM_INCLUDES = -Wall -I/usr/X11R6/include
SYSTEM_LDFLAGS = -L/usr/X11R6/lib SYSTEM_LDFLAGS = -L/usr/X11R6/lib
SYSTEM_LIBS = -ldl SYSTEM_LIBS = -ldl
@ -62,10 +62,14 @@ SYSTEM_LIBS = -ldl
# (We export these for other Makefiles as needed) # (We export these for other Makefiles as needed)
# #
export SYSTEM_HAVES = -DLINUX -DHAVE_IPV6 -DHAVE_GETLOGIN -DHAVE_LOCKF \ SYSTEM_HAVES = -DLINUX -DHAVE_IPV6 -DHAVE_GETLOGIN -DHAVE_LOCKF \
-DHAVE_OLD_SIGNALHANDLER -DHAVE_DIRFD -DHAVE_ASSERT $(NETSEC) -DHAVE_OLD_SIGNALHANDLER -DHAVE_DIRFD -DHAVE_ASSERT $(NETSEC)
export CC = gcc SYSTEM_SRC =
SYSTEM = linux
export CC = g++
export RANLIB = ranlib export RANLIB = ranlib
export AR = ar export AR = ar

View File

@ -5,6 +5,7 @@
# 1) System specific additional libraries, include paths, etc # 1) System specific additional libraries, include paths, etc
# (Where to find X11 libraries, etc) # (Where to find X11 libraries, etc)
# #
SYSTEM_INCLUDES = -I/usr/X11R6/include SYSTEM_INCLUDES = -I/usr/X11R6/include
SYSTEM_LDFLAGS = -L/usr/X11R6/lib SYSTEM_LDFLAGS = -L/usr/X11R6/lib
SYSTEM_LIBS = SYSTEM_LIBS =
@ -35,7 +36,12 @@ SYSTEM_LIBS =
# (We export these for other Makefiles as needed) # (We export these for other Makefiles as needed)
# #
export SYSTEM_HAVES = -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC) -DSOCKLEN_T=int export SYSTEM_HAVES = -DMACOSX -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC) -DSOCKLEN_T=int
SYSTEM_SRC = bsdRouteMgr.cpp
# The "SYSTEM" keyword can be used for dependent makes
SYSTEM = macosx
export CC = g++ export CC = g++
export RANLIB = ranlib export RANLIB = ranlib

View File

@ -3,11 +3,10 @@
# #
# 1) System specific additional libraries, include paths, etc # 1) System specific additional libraries, include paths, etc
# (Where to find X11 libraries, etc) # (Where to find X11 libraries, etc)
# #
SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333 -cfront SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333
SYSTEM_LDFLAGS = SYSTEM_LDFLAGS =
SYSTEM_LIBS = SYSTEM_LIBS =

View File

@ -1,36 +1,15 @@
# #
# MDPv2 Solaris Makefile # NORM Solaris Makefile
# #
# TO BUILD THE TK GUI VERSION OF MDP EDIT THE FOLLOWING NUMBERED
# ITEMS AS NEEDED FOR YOUR SYSTEM
# (This has only been tested with TCL/TK 8.0 but it probably
# will work with Tcl7.x/Tk4.x with a little tweaking to
# the list of TCL_SCRIPTS (library scripts) given below)
# 1) Where to find the Tcl standard library scripts # 1) System specific additional libraries, include paths, etc
# (e.g. init.tcl, ...)
TCL_SCRIPT_PATH = /usr/local/lib/tcl8.0
# 2) Where to find the Tk standard library scripts
# (e.g. button.tcl, entry.tcl, ...)
TK_SCRIPT_PATH = /usr/local/lib/tk8.0
# 3) Where to find Tcl/Tk header files
# (e.g. tcl.h, tk.h, ...)
TCL_INCL_PATH = -I/usr/local/include
# 4) Point to specific libtcl.a and libtk.a to use
TCL_LIB = /usr/local/lib/libtcl8.0.a
TK_LIB = /usr/local/lib/libtk8.0.a
# 5) System specific additional libraries, include paths, etc
# (Where to find X11 libraries, etc) # (Where to find X11 libraries, etc)
# #
SYSTEM_INCLUDES = -I/usr/openwin/include SYSTEM_INCLUDES = -I/usr/openwin/include
SYSTEM_LDFLAGS = -L/usr/openwin/lib -R/usr/openwin/lib SYSTEM_LDFLAGS = -L/usr/openwin/lib -R/usr/openwin/lib
SYSTEM_LIBS = -ldl -lnsl -lsocket SYSTEM_LIBS = -ldl -lnsl -lsocket -lresolv
# 6) System specific capabilities # 2) System specific capabilities
# Must choose appropriate for the following: # Must choose appropriate for the following:
# #
# A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin()
@ -46,24 +25,24 @@ SYSTEM_LIBS = -ldl -lnsl -lsocket
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
# routine. # routine.
# #
# E) The MDP code's use of offset pointers requires special treatment # E) Some systems (SOLARIS/SUNOS) have a few gotchas which require
# for some different compilers. Set -DUSE_INHERITANCE for some
# to keep some compilers (gcc 2.7.2) happy.
#
# F) Some systems (SOLARIS/SUNOS) have a few gotchas which require
# some #ifdefs to avoid compiler warnings ... so you might need # some #ifdefs to avoid compiler warnings ... so you might need
# to specify -DSOLARIS or -DSUNOS depending on your OS. # to specify -DSOLARIS or -DSUNOS depending on your OS.
# #
# G) Uncomment this if you have the NRL IPv6+IPsec software # F) Uncomment this if you have the NRL IPv6+IPsec software
#DNETSEC = -DNETSEC -I/usr/inet6/include #DNETSEC = -DNETSEC -I/usr/inet6/include
# #
# (We export these for other Makefiles as needed) # (We export these for other Makefiles as needed)
# #
export SYSTEM_HAVES = -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF $(NETSEC) -DSOLARIS SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF $(NETSEC) -DSOLARIS
export CC = gcc SYSTEM = solaris
export RANLIB = touch
export AR = ar CC = g++
RANLIB = touch
AR = ar
include Makefile.common include Makefile.common

411
unix/unixPostProcess.cpp Normal file
View File

@ -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

59
win32/Norm.dsw Normal file
View File

@ -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>
{{{
}}}
###############################################################################

BIN
win32/Norm.opt Normal file

Binary file not shown.

227
win32/NormLib.dsp Normal file
View File

@ -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

115
win32/norm/norm.dsp Normal file
View File

@ -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

255
win32/win32PostProcess.cpp Normal file
View File

@ -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()