251 lines
7.1 KiB
C++
251 lines
7.1 KiB
C++
|
|
// norm.cpp - Command-line NORM application
|
|
|
|
#include "protoLib.h"
|
|
#include "normSession.h"
|
|
|
|
#include <stdio.h> // for stdout/stderr printouts
|
|
#include <signal.h> // for SIGTERM/SIGINT handling
|
|
|
|
class NormApp : public NormController
|
|
{
|
|
public:
|
|
NormApp();
|
|
virtual ~NormApp();
|
|
bool OnStartup();
|
|
int MainLoop() {return dispatcher.Run();}
|
|
void Stop(int exitCode) {dispatcher.Stop(exitCode);}
|
|
void OnShutdown();
|
|
|
|
private:
|
|
|
|
virtual void Notify(NormController::Event event,
|
|
class NormSessionMgr* sessionMgr,
|
|
class NormSession* session,
|
|
class NormServerNode* server,
|
|
class NormObject* object);
|
|
|
|
static void SignalHandler(int sigNum);
|
|
|
|
EventDispatcher dispatcher;
|
|
NormSessionMgr session_mgr;
|
|
NormSession* session;
|
|
NormStreamObject* stream;
|
|
|
|
}; // end class NormApp
|
|
|
|
|
|
void NormApp::Notify(NormController::Event event,
|
|
class NormSessionMgr* sessionMgr,
|
|
class NormSession* session,
|
|
class NormServerNode* server,
|
|
class NormObject* object)
|
|
{
|
|
switch (event)
|
|
{
|
|
case TX_QUEUE_EMPTY:
|
|
//TRACE("NormApp::Notify(TX_QUEUE_EMPTY) ...\n");
|
|
if (object == stream)
|
|
{
|
|
char text[256];
|
|
memset(text, 'a', 256);
|
|
stream->Write(text, 256);
|
|
}
|
|
break;
|
|
|
|
case RX_OBJECT_NEW:
|
|
//TRACE("NormApp::Notify(RX_OBJECT_NEW) ...\n");
|
|
{
|
|
switch (object->GetType())
|
|
{
|
|
case NormObject::STREAM:
|
|
{
|
|
const NormObjectSize& size = object->Size();
|
|
if (!((NormStreamObject*)object)->Accept(size.LSB()))
|
|
{
|
|
TRACE("stream object accept error!\n");
|
|
}
|
|
}
|
|
break;
|
|
case NormObject::FILE:
|
|
case NormObject::DATA:
|
|
TRACE("NormApp::Notify() FILE/DATA objects not supported...\n");
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RX_OBJECT_UPDATE:
|
|
//TRACE("NormApp::Notify(RX_OBJECT_UPDATE) ...\n");
|
|
switch (object->GetType())
|
|
{
|
|
case NormObject::STREAM:
|
|
{
|
|
// Read the stream
|
|
char buffer[2048];
|
|
unsigned int nBytes;
|
|
while ((nBytes = ((NormStreamObject*)object)->Read(buffer, 2048)))
|
|
{
|
|
for (unsigned int i =0; i < nBytes; i++)
|
|
{
|
|
if ('a' != buffer[i])
|
|
{
|
|
TRACE("NormApp::Notify() bad data received!\n");
|
|
break;
|
|
}
|
|
}
|
|
buffer[32] = '\0';
|
|
DMSG(0, "NormApp::Notify() stream read %u bytes: \"%s\"\n", nBytes, buffer);
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case NormObject::FILE:
|
|
case NormObject::DATA:
|
|
TRACE("NormApp::Notify() FILE/DATA objects not supported...\n");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
NormApp::NormApp()
|
|
: session(NULL), stream(NULL)
|
|
{
|
|
// Init tx_timer for 1.0 second interval, infinite repeats
|
|
session_mgr.Init(EventDispatcher::TimerInstaller, &dispatcher,
|
|
EventDispatcher::SocketInstaller, &dispatcher,
|
|
this);
|
|
}
|
|
|
|
NormApp::~NormApp()
|
|
{
|
|
|
|
}
|
|
|
|
bool NormApp::OnStartup()
|
|
{
|
|
#ifdef WIN32
|
|
if (!dispatcher.Win32Init())
|
|
{
|
|
fprintf(stderr, "norm:: Win32Init() error!\n");
|
|
return false;
|
|
}
|
|
#endif // WIN32
|
|
|
|
signal(SIGTERM, SignalHandler);
|
|
signal(SIGINT, SignalHandler);
|
|
|
|
|
|
session = session_mgr.NewSession("224.225.1.5", 5005);
|
|
if (session)
|
|
{
|
|
if (!session->StartServer(1024*1024, 256, 20, 8))
|
|
{
|
|
DMSG(0, "NormApp::OnStartup() start server error!\n");
|
|
session_mgr.Destroy();
|
|
return false;
|
|
}
|
|
session->ServerSetAutoParity(4);
|
|
//session->SetLoopback(true);
|
|
|
|
// Open a stream object to write to
|
|
stream = session->QueueTxStream(10*1024);
|
|
if (!stream)
|
|
{
|
|
DMSG(0, "NormApp::OnStartup() queue tx stream error!\n");
|
|
session_mgr.Destroy();
|
|
return false;
|
|
}
|
|
char text[256];
|
|
memset(text, 'a', 256);
|
|
stream->Write(text, 256);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} // end NormApp::OnStartup()
|
|
|
|
void NormApp::OnShutdown()
|
|
{
|
|
session_mgr.Destroy();
|
|
} // end NormApp::OnShutdown()
|
|
|
|
|
|
// Out application instance (global for SignalHandler)
|
|
NormApp theApp;
|
|
|
|
// Use "main()" for UNIX and WIN32 console apps,
|
|
// "WinMain()" for non-console WIN32
|
|
// (VC++ uses the "_CONSOLE_ macro to indicate build type)
|
|
|
|
#if defined(WIN32) && !defined(_CONSOLE)
|
|
int PASCAL WinMain(HINSTANCE instance, HINSTANCE prevInst, LPSTR cmdline, int cmdshow)
|
|
#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.OnStartup())
|
|
{
|
|
exitCode = theApp.MainLoop();
|
|
theApp.OnShutdown();
|
|
fprintf(stderr, "norm: Done.\n");
|
|
#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
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "norm: Error initializing application!\n");
|
|
return -1;
|
|
}
|
|
return exitCode; // exitCode contains "signum" causing exit
|
|
} // end main();
|
|
|
|
void NormApp::SignalHandler(int sigNum)
|
|
{
|
|
switch(sigNum)
|
|
{
|
|
case SIGTERM:
|
|
case SIGINT:
|
|
theApp.Stop(sigNum); // causes theApp's main loop to exit
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "norm: Unexpected signal: %d\n", sigNum);
|
|
break;
|
|
}
|
|
} // end NormApp::SignalHandler()
|