[Opalvoip-svn] SF.net SVN: opalvoip:[26365] opal/trunk
Brought to you by:
csoutheren,
rjongbloed
From: <rjo...@us...> - 2011-08-29 05:43:54
|
Revision: 26365 http://opalvoip.svn.sourceforge.net/opalvoip/?rev=26365&view=rev Author: rjongbloed Date: 2011-08-29 05:43:47 +0000 (Mon, 29 Aug 2011) Log Message: ----------- Major enhancement to OpalManagerConsole allowing more control from application. Added OpalManagerCLI which includes a command line interpreter and OpalConsoleProcess which is a template to create a standard PProcess that uses the user derived OpalManager. Reducing the amount of overrides required. Modified Paths: -------------- opal/trunk/include/opal/console_mgr.h opal/trunk/samples/opalmcu/main.cxx opal/trunk/samples/opalmcu/main.h opal/trunk/samples/sipim/main.cxx opal/trunk/samples/sipim/main.h opal/trunk/src/opal/console_mgr.cxx Modified: opal/trunk/include/opal/console_mgr.h =================================================================== --- opal/trunk/include/opal/console_mgr.h 2011-08-29 05:41:01 UTC (rev 26364) +++ opal/trunk/include/opal/console_mgr.h 2011-08-29 05:43:47 UTC (rev 26365) @@ -36,6 +36,7 @@ #endif #include <opal/manager.h> +#include <ptclib/cli.h> class SIPEndPoint; @@ -43,12 +44,11 @@ class OpalLineEndPoint; -/**Opal manager class for console applications. +/**OPAL manager class for console applications. An OpalManager derived class for use in a console application, providing a standard set of command line arguments for configuring many system parameters. Used by the sample applications such as faxopal, ovropal etc. */ - class OpalManagerConsole : public OpalManager { PCLASSINFO(OpalManagerConsole, OpalManager); @@ -56,10 +56,13 @@ public: OpalManagerConsole(); - PString GetArgumentSpec() const; - PString GetArgumentUsage() const; + virtual PString GetArgumentSpec() const; + virtual PString GetArgumentUsage() const; + virtual void Usage(ostream & strm, const PArgList & args); - bool Initialise(PArgList & args, bool verbose); + virtual bool Initialise(PArgList & args, bool verbose); + virtual void Run(); + virtual void EndRun(); protected: #if OPAL_SIP @@ -71,9 +74,99 @@ #if OPAL_LID OpalLineEndPoint * CreateLineEndPoint(); #endif + + PSyncPoint m_endRun; }; +/**OPAL manager class for applications with command line interpreter. + An OpalManager derived class for use in a console application, providing + a standard set of command line arguments for configuring many system + parameters, and a standard command line interpreter for control of many + functions. Used by the sample applications such as faxopal, ovropal etc. + */ +class OpalManagerCLI : public OpalManagerConsole +{ + PCLASSINFO(OpalManagerCLI, OpalManagerConsole); + + public: + OpalManagerCLI(); + ~OpalManagerCLI(); + + virtual PString GetArgumentSpec() const; + virtual bool Initialise(PArgList & args, bool verbose); + virtual void Run(); + virtual void EndRun(); + + protected: + PCLI * CreatePCLI( +#if P_TELNET + WORD port /// Port to listen for telnet sessions, zero disables. +#endif + ); + +#if OPAL_SIP + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdRegister); +#endif + +#if P_NAT + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdNat); +#endif + +#if PTRACING + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdTrace); +#endif + + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdListCodecs); + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdDelay); + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdVersion); + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdQuit); + PDECLARE_NOTIFIER(PCLI::Arguments, OpalManagerCLI, CmdShutDown); + + PCLI * m_cli; +}; + + +/**Create a process for OpalConsoleManager based applications. + */ +template <class Manager, ///< Class of OpalManagerConsole derived class + const char Manuf[], ///< Name of manufacturer + const char Name[], ///< Name of product + WORD MajorVersion = OPAL_MAJOR, ///< Major version number of the product + WORD MinorVersion = OPAL_MINOR, ///< Minor version number of the product + PProcess::CodeStatus Status = PProcess::ReleaseCode, ///< Development status of the product + WORD BuildNumber = OPAL_BUILD, ///< Build number of the product + bool Verbose = true> +class OpalConsoleProcess : public PProcess +{ + PCLASSINFO(OpalConsoleProcess, PProcess) + public: + OpalConsoleProcess() + : PProcess(Manuf, Name, MajorVersion, MinorVersion, Status, BuildNumber) + , m_manager(NULL) + { + } + + ~OpalConsoleProcess() + { + delete this->m_manager; + } + + virtual void Main() + { + this->SetTerminationValue(1); + this->m_manager = new MyManager; + if (this->m_manager->Initialise(this->GetArguments(), Verbose)) { + this->SetTerminationValue(0); + this->m_manager->Run(); + } + } + + private: + Manager * m_manager; +}; + + #endif // OPAL_OPAL_CONSOLE_MGR_H Modified: opal/trunk/samples/opalmcu/main.cxx =================================================================== --- opal/trunk/samples/opalmcu/main.cxx 2011-08-29 05:41:01 UTC (rev 26364) +++ opal/trunk/samples/opalmcu/main.cxx 2011-08-29 05:43:47 UTC (rev 26365) @@ -30,74 +30,58 @@ #include "main.h" -PCREATE_PROCESS(ConfOPAL); +extern const char Manufacturer[] = "Vox Gratia"; +extern const char Application[] = "ConfOPAL"; +typedef OpalConsoleProcess<MyManager, Manufacturer, Application> MyApp; +PCREATE_PROCESS(MyApp); - // Debug command: -m 123 -V -S udp$*:25060 -H tcp$*:21720 -ttttodebugstream -ConfOPAL::ConfOPAL() - : PProcess("Vox Gratia", "ConfOPAL", 1, 0, ReleaseCode, 0) - , m_manager(NULL) +MyManager::MyManager() + : m_mixer(NULL) { } -ConfOPAL::~ConfOPAL() +PString MyManager::GetArgumentSpec() const { - delete m_manager; -} + PString spec = OpalManagerCLI::GetArgumentSpec(); + spec.Replace("V-version", "-version"); // Want the 'V' option back - -void ConfOPAL::Main() -{ - m_manager = new MyManager(); - - PArgList & args = GetArguments(); - - args.Parse(m_manager->GetArgumentSpec() + - "a-attendant:" - "c-cli:" - "m-moderator:" - "n-name:" - "s-size:" - "V-no-video." - "-pass-thru.", false); - if (args.HasOption('h')) { - cerr << "usage: " << GetFile().GetTitle() << " [ options ] [ name ]\n" - "\n" - "Available options are:\n" - " -a or --attendant vxml : VXML script to run for incoming calls not directed.\n" - " : to a specific conference. If absent, then ad-hoc\n" - " : conferences are created.\n" - " -m or --moderator pin : PIN to allow to become a moderator and have talk\n" - " : rights if absent, all participants are moderators.\n" - " --pass-thru : Enable media pass through optimisation.\n" - " -n or --name alias : Default name for ad-hoc conference.\n" + return "[Application options:]" + "a-attendant: VXML script to run for incoming calls not directed\r" + "to a specific conference. If absent, then ad-hoc\r" + "conferences are created.\n" + "m-moderator: PIN to allow to become a moderator and have talk\r" + "rights if absent, all participants are moderators.\n" + "n-name: Default name for ad-hoc conference.\n" #if OPAL_VIDEO - " -V or --no-video : Disable video for ad-hoc conference.\n" - " -s or --size : Set default video size for ad-hoc conference.\n" + "s-size: Set default video size for ad-hoc conference.\n" + "V-no-video. Disable video for ad-hoc conference.\n" #endif - "\n" - << m_manager->GetArgumentUsage(); - return; - } + "-pass-thru. Enable media pass through optimisation.\n" + + spec; +} - if (!m_manager->Initialise(args, true)) - return; +bool MyManager::Initialise(PArgList & args, bool verbose) +{ + if (!OpalManagerCLI::Initialise(args, verbose)) + return false; + // Set up PCSS to do speaker playback - new MyPCSSEndPoint(*m_manager); + new MyPCSSEndPoint(*this); // Set up IVR to do recording or WAV file play - OpalIVREndPoint * ivr = new OpalIVREndPoint(*m_manager); + OpalIVREndPoint * ivr = new OpalIVREndPoint(*this); // Set up conference mixer MyMixerNodeInfo * info = NULL; if (args.HasOption('a')) { PFilePath path = args.GetOptionString('a'); ivr->SetDefaultVXML(path); - m_manager->AddRouteEntry(".*:.* = ivr:<da>"); + AddRouteEntry(".*:.* = ivr:<da>"); cout << "Using attendant IVR " << path << endl; } else { @@ -115,153 +99,59 @@ cout << "Using ad-hoc conference, default name: " << info->m_name << endl; } - MyMixerEndPoint * mixer = m_manager->m_mixer = new MyMixerEndPoint(*m_manager, info); + m_mixer = new MyMixerEndPoint(*this, info); - m_manager->AddRouteEntry("sip.*:.* = mcu:<du>"); - m_manager->AddRouteEntry("h323.*:.* = mcu:<du>"); + AddRouteEntry("sip.*:.* = mcu:<du>"); + AddRouteEntry("h323.*:.* = mcu:<du>"); - // Wait for call to come in and finish - PCLI * cli; - if (args.HasOption('c')) { - unsigned port = args.GetOptionString('c').AsUnsigned(); - if (port == 0 || port > 65535) { - cerr << "Illegal CLI port " << port << endl; - return; - } - cli = new PCLISocket((WORD)port); - cli->StartContext(new PConsoleChannel(PConsoleChannel::StandardInput), - new PConsoleChannel(PConsoleChannel::StandardOutput)); - } - else - cli = new PCLIStandard(); + m_cli->SetPrompt("MCU> "); - cli->SetPrompt("MCU> "); - - cli->SetCommand("conf add", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdConfAdd), - "Add a new conferance:", + m_cli->SetCommand("conf add", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdConfAdd), + "Add a new conferance:", #if OPAL_VIDEO - "[ -V ] [ -s size ] [ -m pin ] <name> [ <name> ... ]\n" - " -V or --no-video : Disable video\n" - " -s or --size : Set video size" + "[ -V ] [ -s size ] [ -m pin ] <name> [ <name> ... ]\n" + " -V or --no-video : Disable video\n" + " -s or --size : Set video size\n" #else - "[ -m pin ] <name>" + "[ -m pin ] <name>\n" #endif - "\n" - " -m or --moderator pin : PIN to allow to become a moderator and have talk rights\n" - " : if absent, all participants are moderators.\n" - " --no-pass-thru : Disable media pass through optimisation.\n" - ); - cli->SetCommand("conf list", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdConfList), - "List conferances"); - cli->SetCommand("conf remove", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdConfRemove), - "Remove conferance:", - "<name> | <guid>"); - cli->SetCommand("conf listen", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdConfListen), - "Toggle listening to conferance:", - "{ <conf-name> | <guid> }"); - cli->SetCommand("conf record", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdConfRecord), - "Record conferance:", - "{ <conf-name> | <guid> } { <filename> | stop }"); - cli->SetCommand("conf play", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdConfPlay), - "Play file to conferance:", - "{ <conf-name> | <guid> } <filename>"); + "\n" + " -m or --moderator pin : PIN to allow to become a moderator and have talk rights\n" + " : if absent, all participants are moderators.\n" + " --no-pass-thru : Disable media pass through optimisation.\n" + ); + m_cli->SetCommand("conf list", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdConfList), + "List conferances"); + m_cli->SetCommand("conf remove", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdConfRemove), + "Remove conferance:", + "<name> | <guid>"); + m_cli->SetCommand("conf listen", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdConfListen), + "Toggle listening to conferance:", + "{ <conf-name> | <guid> }"); + m_cli->SetCommand("conf record", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdConfRecord), + "Record conferance:", + "{ <conf-name> | <guid> } { <filename> | stop }"); + m_cli->SetCommand("conf play", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdConfPlay), + "Play file to conferance:", + "{ <conf-name> | <guid> } <filename>"); - cli->SetCommand("member add", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdMemberAdd), - "Add a member to conferance:", - "{ <name> | <guid> } <address>"); - cli->SetCommand("member list", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdMemberList), - "List members in conferance:", - "<name> | <guid>"); - cli->SetCommand("member remove", PCREATE_NOTIFIER_EXT(mixer, MyMixerEndPoint, CmdMemberRemove), - "Remove conferance member:", - "{ <conf-name> | <guid> } <member-name>\n" - "member remove <call-token>"); + m_cli->SetCommand("member add", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdMemberAdd), + "Add a member to conferance:", + "{ <name> | <guid> } <address>"); + m_cli->SetCommand("member list", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdMemberList), + "List members in conferance:", + "<name> | <guid>"); + m_cli->SetCommand("member remove", PCREATE_NOTIFIER_EXT(m_mixer, MyMixerEndPoint, CmdMemberRemove), + "Remove conferance member:", + "{ <conf-name> | <guid> } <member-name>\n" + "member remove <call-token>"); - cli->SetCommand("list codecs", PCREATE_NOTIFIER(CmdListCodecs), - "List available codecs"); -#if PTRACING - cli->SetCommand("trace", PCREATE_NOTIFIER(CmdTrace), - "Set trace level (1..6) and filename", - "<n> [ <filename> ]"); -#endif - cli->SetCommand("shutdown", PCREATE_NOTIFIER(CmdShutDown), - "Shut down the application"); - cli->SetCommand("quit\nq\nexit", PCREATE_NOTIFIER(CmdQuit), - "Quit command line interpreter, note quitting from console also shuts down application."); - - m_manager->m_cli = cli; - cli->Start(false); // Do not spawn thread, wait till end of input - - cout << "\nExiting ..." << endl; + return true; } -void ConfOPAL::CmdListCodecs(PCLI::Arguments & args, INT) -{ - OpalMediaFormatList formats; - OpalMediaFormat::GetAllRegisteredMediaFormats(formats); - - PCLI::Context & out = args.GetContext(); - OpalMediaFormatList::iterator format; - for (format = formats.begin(); format != formats.end(); ++format) { - if (format->GetMediaType() == OpalMediaType::Audio() && format->IsTransportable()) - out << *format << '\n'; - } -#if OPAL_VIDEO - for (format = formats.begin(); format != formats.end(); ++format) { - if (format->GetMediaType() == OpalMediaType::Video() && format->IsTransportable()) - out << *format << '\n'; - } -#endif - out.flush(); -} - - -#if PTRACING -void ConfOPAL::CmdTrace(PCLI::Arguments & args, INT) -{ - if (args.GetCount() == 0) - args.WriteUsage(); - else - PTrace::Initialise(args[0].AsUnsigned(), - args.GetCount() > 1 ? (const char *)args[1] : NULL, - PTrace::GetOptions()); -} -#endif // PTRACING - - -void ConfOPAL::CmdShutDown(PCLI::Arguments & args, INT) -{ - m_manager->m_cli->Stop(); -} - - -void ConfOPAL::CmdQuit(PCLI::Arguments & args, INT) -{ - if (PIsDescendant(args.GetContext().GetBaseReadChannel(), PConsoleChannel)) - m_manager->m_cli->Stop(); - else - args.GetContext().Stop(); -} - - -/////////////////////////////////////////////////////////////// - -MyManager::MyManager() - : m_mixer(NULL) - , m_cli(NULL) -{ -} - - -MyManager::~MyManager() -{ - delete m_cli; -} - - void MyManager::OnEstablishedCall(OpalCall & call) { PStringStream strm; @@ -302,7 +192,7 @@ { PStringStream strm; strm << "Created new conference \"" << info->m_name << '"'; - m_manager.m_cli->Broadcast(strm); + m_manager.Broadcast(strm); return OpalMixerEndPoint::CreateNode(info); } @@ -563,7 +453,7 @@ << GetRemotePartyName() << "\"" " promoted to moderator.\n"; - m_endpoint.m_manager.m_cli->Broadcast(strm); + m_endpoint.m_manager.Broadcast(strm); } return OpalMixerConnection::SendUserInputString(value); Modified: opal/trunk/samples/opalmcu/main.h =================================================================== --- opal/trunk/samples/opalmcu/main.h 2011-08-29 05:41:01 UTC (rev 26364) +++ opal/trunk/samples/opalmcu/main.h 2011-08-29 05:43:47 UTC (rev 26365) @@ -128,44 +128,25 @@ }; -class MyManager : public OpalManagerConsole +class MyManager : public OpalManagerCLI { - PCLASSINFO(MyManager, OpalManagerConsole) + PCLASSINFO(MyManager, OpalManagerCLI) public: MyManager(); - ~MyManager(); + PString GetArgumentSpec() const; + bool Initialise(PArgList & args, bool verbose); + virtual void OnEstablishedCall(OpalCall & call); virtual void OnClearedCall(OpalCall & call); + void Broadcast(const PString & str) { m_cli->Broadcast(str); } + MyMixerEndPoint * m_mixer; - PCLI * m_cli; }; -class ConfOPAL : public PProcess -{ - PCLASSINFO(ConfOPAL, PProcess) - - public: - ConfOPAL(); - ~ConfOPAL(); - - virtual void Main(); - - private: - PDECLARE_NOTIFIER(PCLI::Arguments, ConfOPAL, CmdListCodecs); -#if PTRACING - PDECLARE_NOTIFIER(PCLI::Arguments, ConfOPAL, CmdTrace); -#endif - PDECLARE_NOTIFIER(PCLI::Arguments, ConfOPAL, CmdShutDown); - PDECLARE_NOTIFIER(PCLI::Arguments, ConfOPAL, CmdQuit); - - MyManager * m_manager; -}; - - #endif // _OPAL_MCU_MAIN_H Modified: opal/trunk/samples/sipim/main.cxx =================================================================== --- opal/trunk/samples/sipim/main.cxx 2011-08-29 05:41:01 UTC (rev 26364) +++ opal/trunk/samples/sipim/main.cxx 2011-08-29 05:43:47 UTC (rev 26365) @@ -29,134 +29,68 @@ #include "main.h" #include <im/im_ep.h> +#include <ptclib/mime.h> -PCREATE_PROCESS(SipIM); +extern const char Manufacturer[] = "OPAL"; +extern const char Application[] = "IM Test"; +typedef OpalConsoleProcess<MyManager, Manufacturer, Application> MyApp; +PCREATE_PROCESS(MyApp); -SipIM::SipIM() - : PProcess("OPAL", "IM Test", OPAL_MAJOR, OPAL_MINOR, ReleaseCode, OPAL_BUILD) - , m_manager(NULL) + +PString MyManager::GetArgumentSpec() const { + return "[Application options:]" + "l-listen. Listen for incoming connections\n" + + OpalManagerCLI::GetArgumentSpec(); } -SipIM::~SipIM() +void MyManager::Usage(ostream & strm, const PArgList & args) { - delete m_manager; + PString name = PProcess::Current().GetFile().GetTitle(); + strm << "\n" + "usage: " << name << " [ options ... ] [ <url> ]\n" + "\n" + "If there is no URL to dial specified then --listen must be present.\n" + "\n" + "e.g. " << name << " -P T.140 sip:fr...@bl...\n" + " " << name << " --listen\n" + "\n" + "\n"; + args.Usage(strm); } -void SipIM::Main() +bool MyManager::Initialise(PArgList & args, bool verbose) { - m_manager = new MyManager; - - PArgList & args = GetArguments(); - args.Parse(m_manager->GetArgumentSpec() + - "l-listen." - "f-script-file:"); - - if (args.HasOption('h') || (args.GetCount() == 0 && !args.HasOption('l'))) { - PString name = GetFile().GetTitle(); - cerr << "usage: " << name << " [ options ] [ url ]\n" - "\n" - "Available options are:\n" - " -l or --listen : Listen for incoming connections\n" - " -f or --script-file fn : Execute script file\n" - "\n" - << m_manager->GetArgumentUsage() - << "\n" - "e.g. " << name << " sip-im sip:fr...@bl...\n" - "\n" - " " << name << " t.140\n\n"; - return; + if (args.Parse(GetArgumentSpec()) != PArgList::ParseWithArguments && !args.HasOption('l')) { + Usage(cerr, args); + return false; } - if (!m_manager->Initialise(args, true)) - return; + if (!OpalManagerCLI::Initialise(args, verbose)) + return false; - new OpalIMEndPoint(*m_manager); - m_manager->AddRouteEntry("sip:.*\t.*=im:*"); - m_manager->AddRouteEntry("h323:.*\t.*=im:*"); + new OpalIMEndPoint(*this); + AddRouteEntry("sip:.*\t.*=im:*"); + AddRouteEntry("h323:.*\t.*=im:*"); - PCLIStandard cli; - cli.SetPrompt("IM> "); -#if 0 - cli.SetCommand("create", PCREATE_NOTIFIER(CmdCreate), - "Create presentity.", - "[ -p ] <url>"); - cli.SetCommand("list", PCREATE_NOTIFIER(CmdList), - "List presentities."); - cli.SetCommand("subscribe", PCREATE_NOTIFIER(CmdSubscribeToPresence), - "Subscribe to presence state for presentity.", - "<url-watcher> <url-watched>"); - cli.SetCommand("unsubscribe", PCREATE_NOTIFIER(CmdUnsubscribeToPresence), - "Subscribe to presence state for presentity.", - "<url-watcher> <url-watched>"); - cli.SetCommand("authorise", PCREATE_NOTIFIER(CmdPresenceAuthorisation), - "Authorise a presentity to see local presence.", - "<url-watched> <url-watcher> [ deny | deny-politely | remove ]"); - cli.SetCommand("publish", PCREATE_NOTIFIER(CmdSetLocalPresence), - "Publish local presence state for presentity.", - "<url> { available | unavailable | busy } [ <note> ]"); - cli.SetCommand("buddy list\nshow buddies", PCREATE_NOTIFIER(CmdBuddyList), - "Show buddy list for presentity.", - "<presentity>"); - cli.SetCommand("buddy add\nadd buddy", PCREATE_NOTIFIER(CmdBuddyAdd), - "Add buddy to list for presentity.", - "<presentity> <url-buddy> <display-name>"); - cli.SetCommand("buddy remove\ndel buddy", PCREATE_NOTIFIER(CmdBuddyRemove), - "Delete buddy from list for presentity.", - "<presentity> <url-buddy>"); - cli.SetCommand("buddy subscribe", PCREATE_NOTIFIER(CmdBuddySusbcribe), - "Susbcribe to all URIs in the buddy list for presentity.", - "<presentity>"); -#endif - cli.SetCommand("stun", PCREATE_NOTIFIER(CmdStun), - "Set external STUN server", - "address"); - cli.SetCommand("translate", PCREATE_NOTIFIER(CmdTranslate), - "Set external NAT translate address", - "address"); - cli.SetCommand("register", PCREATE_NOTIFIER(CmdRegister), - "Register with SIP registrar", - "username password domain"); - cli.SetCommand("delay", PCREATE_NOTIFIER(CmdDelay), - "Delay for n seconds", - "secs"); - cli.SetCommand("send", PCREATE_NOTIFIER(CmdSend), - "Send IM", - "dest message..."); - cli.SetCommand("set", PCREATE_NOTIFIER(CmdSet), - "Set/unset attribute", - "name <value>"); - cli.SetCommand("quit\nq\nexit", PCREATE_NOTIFIER(CmdQuit), - "Quit command line interpreter, note quitting from console also shuts down application."); + m_cli->SetPrompt("IM> "); + m_cli->SetCommand("send", PCREATE_NOTIFIER(CmdSend), + "Send IM", + "dest message..."); + m_cli->SetCommand("set", PCREATE_NOTIFIER(CmdSet), + "Set/unset attribute", + "name <value>"); - if (args.HasOption('f')) { - // if there is a script file, process commands - PTextFile scriptFile; - if (scriptFile.Open(args.GetOptionString('f'))) { - cout << "Running script '" << scriptFile.GetFilePath() << "'" << endl; - cli.RunScript(scriptFile); - cout << "Script complete" << endl; - } - else - cerr << "error: cannot open script file \"" << args.GetOptionString('f') << '"' << endl; - } - - cli.Start(false); // Do not spawn thread, wait till end of input + return true; } -void SipIM::CmdQuit(PCLI::Arguments & args, INT) +void MyManager::CmdSet(PCLI::Arguments & args, INT) { - args.GetContext().Stop(); -} - - -void SipIM::CmdSet(PCLI::Arguments & args, INT) -{ if (args.GetCount() < 1) { if (m_variables.GetSize() == 0) args.GetContext() << "no variables set" << endl; @@ -179,7 +113,7 @@ } -bool SipIM::CheckForVar(PString & var) +bool MyManager::CheckForVar(PString & var) { if ((var.GetLength() < 2) || (var[0] != '$')) return true; @@ -193,7 +127,7 @@ } -void SipIM::CmdSend(PCLI::Arguments & args, INT) +void MyManager::CmdSend(PCLI::Arguments & args, INT) { if (args.GetCount() < 2) { args.WriteUsage(); @@ -219,117 +153,16 @@ while (i < args.GetCount()) message.m_bodies[PMIMEInfo::TextPlain()] = message.m_bodies[PMIMEInfo::TextPlain()] & args[i++]; - if (!m_manager->Message(message)) + if (!Message(message)) args.GetContext() << "IM failed" << endl; else args.GetContext() << "IM sent" << endl; } -void SipIM::CmdDelay(PCLI::Arguments & args, INT) -{ - if (args.GetCount() < 1) - args.WriteUsage(); - else { - int delay = args[0].AsInteger(); - PThread::Sleep(delay * 1000); - } -} - -void SipIM::CmdRegister(PCLI::Arguments & args, INT) -{ - if (args.GetCount() < 3) - args.WriteUsage(); - else { - SIPRegister::Params params; - - PString user = args[0]; - PString password = args[1]; - PString domain = args[2]; - - params.m_registrarAddress = domain; - params.m_addressOfRecord = user; - params.m_password = password; - params.m_realm = domain; - PString aor; - args.GetContext() << "Registering with " << params.m_registrarAddress << "..."; - if (m_manager->FindEndPointAs<SIPEndPoint>("sip")->Register(params, aor, false)) - args.GetContext() << "succeeded" << endl; - else - args.GetContext() << "failed" << endl; - } -} - -void SipIM::CmdTranslate(PCLI::Arguments & args, INT) -{ - if (args.GetCount() < 1) - args.WriteUsage(); - else { - m_manager->SetTranslationAddress(args[0]); - cout << "External address set to " << args[0] << '\n'; - } -} - -void SipIM::CmdStun(PCLI::Arguments & args, INT) -{ - if (args.GetCount() < 1) - args.WriteUsage(); - else { - m_manager->SetSTUNServer(args[0]); - if (m_manager->GetSTUNClient() != NULL) - args.GetContext() << args[0] << " replies " << m_manager->GetSTUNClient()->GetNatTypeName(); - else - args.GetContext() << "None"; - args.GetContext() << endl; - } -} - - -////////////////////////////////////////////////////////////////////////// - - void MyManager::OnMessageReceived(const OpalIM & message) { } -#if 0 - -void MyManager::Initialise(PArgs * args) -{ - if (args.HasOption("translate")) { - SetTranslationAddress(args.GetOptionString("translate")); - cout << "External address set to " << GetTranslationAddress() << '\n'; - } - - if (args.HasOption("portbase")) { - unsigned portbase = args.GetOptionString("portbase").AsUnsigned(); - unsigned portmax = args.GetOptionString("portmax").AsUnsigned(); - SetTCPPorts (portbase, portmax); - SetUDPPorts (portbase, portmax); - SetRtpIpPorts(portbase, portmax); - } else { - if (args.HasOption("tcp-base")) - SetTCPPorts(args.GetOptionString("tcp-base").AsUnsigned(), - args.GetOptionString("tcp-max").AsUnsigned()); - - if (args.HasOption("udp-base")) - SetUDPPorts(args.GetOptionString("udp-base").AsUnsigned(), - args.GetOptionString("udp-max").AsUnsigned()); - - if (args.HasOption("rtp-base")) - SetRtpIpPorts(args.GetOptionString("rtp-base").AsUnsigned(), - args.GetOptionString("rtp-max").AsUnsigned()); - } -} - -#endif - -void MyManager::OnClearedCall(OpalCall & /*call*/) -{ - m_connected.Signal(); - m_completed.Signal(); -} - - // End of File /////////////////////////////////////////////////////////////// Modified: opal/trunk/samples/sipim/main.h =================================================================== --- opal/trunk/samples/sipim/main.h 2011-08-29 05:41:01 UTC (rev 26364) +++ opal/trunk/samples/sipim/main.h 2011-08-29 05:43:47 UTC (rev 26365) @@ -30,67 +30,29 @@ #define _SipIM_MAIN_H #include <opal/console_mgr.h> -#include <sip/sipep.h> -#include <ptclib/cli.h> + #if !OPAL_HAS_IM #error Cannot compile IM sample program without IM! #endif -class OpalIMEndPoint; - - -class MyManager : public OpalManagerConsole +class MyManager : public OpalManagerCLI { - PCLASSINFO(MyManager, OpalManagerConsole) + PCLASSINFO(MyManager, OpalManagerCLI) - public: - virtual void OnClearedCall(OpalCall & call); // Callback override + virtual PString GetArgumentSpec() const; + virtual void Usage(ostream & strm, const PArgList & args); + virtual bool Initialise(PArgList & args, bool verbose); + protected: virtual void OnMessageReceived(const OpalIM & message); - PSyncPoint m_connected; - PSyncPoint m_completed; - PString m_callToken; -}; + PDECLARE_NOTIFIER(PCLI::Arguments, MyManager, CmdSend); - -class SipIM : public PProcess -{ - PCLASSINFO(SipIM, PProcess) - - public: - SipIM(); - ~SipIM(); - - virtual void Main(); - - protected: + PDECLARE_NOTIFIER(PCLI::Arguments, MyManager, CmdSet); bool CheckForVar(PString & var); PStringToString m_variables; - - private: - PDECLARE_NOTIFIER(PCLI::Arguments, SipIM, CmdSet); - PDECLARE_NOTIFIER(PCLI::Arguments, SipIM, CmdSend); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdList); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdSubscribeToPresence); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdUnsubscribeToPresence); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdPresenceAuthorisation); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdSetLocalPresence); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdBuddyList); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdBuddyAdd); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdBuddyRemove); - //PDECLARE_NOTIFIER(PCLI::Arguments, TestPresEnt, CmdBuddySusbcribe); - - PDECLARE_NOTIFIER(PCLI::Arguments, SipIM, CmdStun); - PDECLARE_NOTIFIER(PCLI::Arguments, SipIM, CmdTranslate); - PDECLARE_NOTIFIER(PCLI::Arguments, SipIM, CmdRegister); - PDECLARE_NOTIFIER(PCLI::Arguments, SipIM, CmdDelay); - PDECLARE_NOTIFIER(PCLI::Arguments, SipIM, CmdQuit); - - private: - MyManager * m_manager; }; Modified: opal/trunk/src/opal/console_mgr.cxx =================================================================== --- opal/trunk/src/opal/console_mgr.cxx 2011-08-29 05:41:01 UTC (rev 26364) +++ opal/trunk/src/opal/console_mgr.cxx 2011-08-29 05:43:47 UTC (rev 26365) @@ -41,158 +41,163 @@ #include <lids/lidep.h> -OpalManagerConsole::OpalManagerConsole() +static void PrintVersion(ostream & strm) { + const PProcess & process = PProcess::Current(); + strm << process.GetName() + << " version " << process.GetVersion(true) << "\n" + " by " << process.GetManufacturer() << "\n" + " on " << process.GetOSClass() << ' ' << process.GetOSName() + << " (" << process.GetOSVersion() << '-' << process.GetOSHardware() << ")\n" + " with PTLib v" << PProcess::GetLibVersion() << "\n" + " and OPAL v" << OpalGetVersion() + << endl; } -PString OpalManagerConsole::GetArgumentSpec() const +#if OPAL_SIP +static bool SetRegistrationParams(SIPRegister::Params & params, + PString & error, + const PArgList & args, + const char * mode, + const char * ttl) { - return "u-user:" - "p-password:" - "D-disable:" - "P-prefer:" - "O-option:" - "-inband-detect." - "-inband-send." - "-tel:" -#if OPAL_SIP - "S-sip:" - "r-register:" - "-register-auth-id:" - "-register-proxy:" - "-register-ttl:" - "-register-mode:" - "-proxy:" - "-sip-ui:" -#endif -#if OPAL_H323 - "g-gk-host:" - "G-gk-id:" - "H-h323:" - "-no-fast." - "-no-tunnel." - "-h323-ui:" -#endif -#if OPAL_LID - "L-lines:" - "-country:" -#endif - "-stun:" - "-translate:" - "-portbase:" - "-portmax:" - "-tcp-base:" - "-tcp-max:" - "-udp-base:" - "-udp-max:" - "-rtp-base:" - "-rtp-max:" - "-rtp-tos:" - "-rtp-size:" -#if PTRACING - "t-trace." - "o-output:" -#endif - "V-version." - "h-help."; + if (args.HasOption(mode)) { + PCaselessString str = args.GetOptionString("register-mode"); + if (str == "normal") + params.m_compatibility = SIPRegister::e_FullyCompliant; + else if (str == "single") + params.m_compatibility = SIPRegister::e_CannotRegisterMultipleContacts; + else if (str == "public") + params.m_compatibility = SIPRegister::e_CannotRegisterPrivateContacts; + else { + error = "Unknown SIP registration mode " + str; + return false; + } + } + + params.m_expire = args.GetOptionString(ttl).AsUnsigned(); + if (params.m_expire < 30) { + error = "SIP registrar Time To Live must be more than 30 seconds"; + return false; + } + + return true; } +#endif // OPAL_SIP + +///////////////////////////////////////////////////////////////////////////// -PString OpalManagerConsole::GetArgumentUsage() const +OpalManagerConsole::OpalManagerConsole() { - return "Global options:\n" - " -u or --user name : Set local username, defaults to OS username.\n" - " -p or --password pwd : Set password for authentication.\n" - " -D or --disable codec : Disable use of specified media formats (codecs).\n" - " -P or --prefer codec : Set preference order for media formats (codecs).\n" - " -O or --option fmt:opt=val : Set options for media format (codecs).\n" - " --inband-detect : Disable detection of in-band tones.\n" - " --inband-send : Disable transmission of in-band tones.\n" - " --tel proto : Protocol to use for tel: URI, e.g. sip\n" - "\n" +} + +PString OpalManagerConsole::GetArgumentSpec() const +{ + return "[Global options:]" + "u-user: Set local username, defaults to OS username.\n" + "p-password: Set password for authentication.\n" + "D-disable: Disable use of specified media formats (codecs).\n" + "P-prefer: Set preference order for media formats (codecs).\n" + "O-option: Set options for media formatm argument is of form fmt:opt=val.\n" + "-inband-detect. Disable detection of in-band tones.\n" + "-inband-send. Disable transmission of in-band tones.\n" + "-tel: Protocol to use for tel: URI, e.g. sip\n" + #if OPAL_SIP - "SIP options:\n" - " -S or --sip interface : SIP listens on interface, defaults to udp$*:5060, 'x' disables.\n" - " -r or --register server : SIP registration to server.\n" - " --register-auth-id n : SIP registration authorisation id, default is username.\n" - " --register-proxy n : SIP registration proxy, default is none.\n" - " --register-ttl n : SIP registration Time To Live, default 300 seconds.\n" - " --register-mode m : SIP registration mode (normal, single, public).\n" - " --proxy url : SIP outbound proxy.\n" - " --sip-ui mode : SIP User Indication mode (inband,rfc2833,info-tone,info-string)\n" + "[SIP options:]" + "S-sip: SIP listens on interface, defaults to udp$*:5060, 'x' disables.\n" + "r-register: SIP registration to server.\n" + "-register-auth-id: SIP registration authorisation id, default is username.\n" + "-register-proxy: SIP registration proxy, default is none.\n" + "-register-ttl: SIP registration Time To Live, default 300 seconds.\n" + "-register-mode: SIP registration mode (normal, single, public).\n" + "-proxy: SIP outbound proxy.\n" + "-sip-ui: SIP User Indication mode (inband,rfc2833,info-tone,info-string)\n" #endif - "\n" #if OPAL_H323 - "H.323 options:\n" - " -H or --h323 interface : H.323 listens on interface, defaults to tcp$*:1720, 'x' disables.\n" - " -g or --gk-host host : H.323 gatekeeper host.\n" - " -G or --gk-id id : H.323 gatekeeper identifier.\n" - " --no-fast : H.323 fast connect disabled.\n" - " --no-tunnel : H.323 tunnel for H.245 disabled.\n" - " --h323-ui mode : H.323 User Indication mode (inband,rfc2833,h245-signal,h245-string)\n" + "[H.323 options:]" + "H-h323: H.323 listens on interface, defaults to tcp$*:1720, 'x' disables.\n" + "g-gk-host: H.323 gatekeeper host.\n" + "G-gk-id: H.323 gatekeeper identifier.\n" + "-no-fast. H.323 fast connect disabled.\n" + "-no-tunnel. H.323 tunnel for H.245 disabled.\n" + "-h323-ui: H.323 User Indication mode (inband,rfc2833,h245-signal,h245-string)\n" #endif - "\n" #if OPAL_LID - "Line Interface options:\n" - " -L or --lines devices : Set Line Interface Devices, 'x' disables.\n" - " --country code : Select country to use for LID (eg \"US\", \"au\" or \"+61\").\n" + "[Line Interface options:]" + "L-lines: Set Line Interface Devices, 'x' disables.\n" + "-country: Select country to use for LID (eg \"US\", \"au\" or \"+61\").\n" #endif - "\n" - "IP options:\n" + "[IP options:]" #ifdef P_STUN - " --stun server : Set NAT traversal STUN server\n" + "-stun: Set NAT traversal STUN server\n" #endif - " --translate ip : Set external IP address if masqueraded\n" - " --portbase n : Set TCP/UDP/RTP port base\n" - " --portmax n : Set TCP/UDP/RTP port max\n" - " --tcp-base n : Set TCP port base (default 0)\n" - " --tcp-max n : Set TCP port max (default base+99)\n" - " --udp-base n : Set UDP port base (default 6000)\n" - " --udp-max n : Set UDP port max (default base+199)\n" - " --rtp-base n : Set RTP port base (default 5000)\n" - " --rtp-max n : Set RTP port max (default base+199)\n" - " --rtp-tos n : Set RTP packet IP TOS bits to n\n" - " --rtp-size size : Set RTP maximum payload size in bytes.\n" - "\n" - "Debug:\n" + "-translate: Set external IP address if masqueraded\n" + "-portbase: Set TCP/UDP/RTP port base\n" + "-portmax: Set TCP/UDP/RTP port max\n" + "-tcp-base: Set TCP port base (default 0)\n" + "-tcp-max: Set TCP port max (default base+99)\n" + "-udp-base: Set UDP port base (default 6000)\n" + "-udp-max: Set UDP port max (default base+199)\n" + "-rtp-base: Set RTP port base (default 5000)\n" + "-rtp-max: Set RTP port max (default base+199)\n" + "-rtp-tos: Set RTP packet IP TOS bits to n\n" + "-rtp-size: Set RTP maximum payload size in bytes.\n" + + "[Debug & General:]" #if PTRACING - " -t or --trace : verbosity in error log (more times for more detail)\n" - " -o or --output file : file name for output of log messages\n" + "t-trace. Verbosity in error log (more times for more detail)\n" + "o-output: File name for output of log messages\n" #endif - " -V or --version : Display application version.\n" - " -h or --help : This help message.\n" - ; + "V-version. Display application version.\n" + "h-help. This help message.\n" + ; } +PString OpalManagerConsole::GetArgumentUsage() const +{ + return "[ options ... ]"; +} + + +void OpalManagerConsole::Usage(ostream & strm, const PArgList & args) +{ + strm << "usage: " << PProcess::Current().GetFile().GetTitle() << ' ' << GetArgumentUsage() << "\n\n"; + args.Usage(strm); +} + + bool OpalManagerConsole::Initialise(PArgList & args, bool verbose) { - if (args.HasOption('V')) { - const PProcess & process = PProcess::Current(); - cerr << process.GetName() - << " version " << process.GetVersion(true) << "\n" - " by " << process.GetManufacturer() << "\n" - " on " << process.GetOSClass() << ' ' << process.GetOSName() - << " (" << process.GetOSVersion() << '-' << process.GetOSHardware() << ")\n" - " with PTLib v" << PProcess::GetLibVersion() << "\n" - " and OPAL v" << OpalGetVersion() - << endl; + if (!args.IsParsed()) { + PArgList::ParseResult result = args.Parse(GetArgumentSpec()); + if (result < 0 || args.HasOption("help")) { + if (PAssert(result != PArgList::ParseInvalidOptions, "Invalid options specification")) + Usage(cerr, args); + return false; + } + } + + if (args.HasOption("version")) { + PrintVersion(cerr); return false; } #if PTRACING - PTrace::Initialise(args.GetOptionCount('t'), - args.HasOption('o') ? (const char *)args.GetOptionString('o') : NULL, + PTrace::Initialise(args.GetOptionCount("trace"), + args.HasOption("output") ? (const char *)args.GetOptionString("output") : NULL, PTrace::Blocks | PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine); #endif - if (args.HasOption('O')) { - PStringArray options = args.GetOptionString('O').Lines(); + if (args.HasOption("option")) { + PStringArray options = args.GetOptionString("option").Lines(); for (PINDEX i = 0; i < options.GetSize(); ++i) { PRegularExpression parse("\\([A-Za-z].*\\):\\([A-Za-z].*\\)=\\(.*\\)"); PStringArray subexpressions(4); @@ -221,10 +226,10 @@ } } - if (args.HasOption('D')) - SetMediaFormatMask(args.GetOptionString('D').Lines()); - if (args.HasOption('P')) - SetMediaFormatOrder(args.GetOptionString('P').Lines()); + if (args.HasOption("disable")) + SetMediaFormatMask(args.GetOptionString("disable").Lines()); + if (args.HasOption("prefer")) + SetMediaFormatOrder(args.GetOptionString("prefer").Lines()); if (verbose) { OpalMediaFormatList formats = OpalMediaFormat::GetAllRegisteredMediaFormats(); formats.Remove(GetMediaFormatMask()); @@ -303,8 +308,8 @@ } #endif - if (args.HasOption('u')) - SetDefaultUserName(args.GetOptionString('u')); + if (args.HasOption("user")) + SetDefaultUserName(args.GetOptionString("user")); if (verbose) { PIPSocket::InterfaceTable interfaceTable; @@ -317,7 +322,7 @@ #if OPAL_SIP // Set up SIP - interfaces = args.GetOptionString('S'); + interfaces = args.GetOptionString("sip"); if (interfaces != "x") { SIPEndPoint * sip = CreateSIPEndPoint(); if (!sip->StartListeners(interfaces.Lines())) { @@ -348,35 +353,23 @@ << sip->GetSendUserInputMode() << '\n'; if (args.HasOption("proxy")) { - sip->SetProxy(args.GetOptionString("proxy"), args.GetOptionString('u'), args.GetOptionString('p')); + sip->SetProxy(args.GetOptionString("proxy"), args.GetOptionString("user"), args.GetOptionString("password")); if (verbose) cout << "SIP proxy: " << sip->GetProxy() << '\n'; } - if (args.HasOption('r')) { + if (args.HasOption("register")) { SIPRegister::Params params; - params.m_addressOfRecord = args.GetOptionString('r'); + params.m_addressOfRecord = args.GetOptionString("register"); params.m_authID = args.GetOptionString("register-auth-id"); params.m_registrarAddress = args.GetOptionString("register-proxy"); - params.m_password = args.GetOptionString('p'); - params.m_expire = args.GetOptionString("register-ttl", "300").AsUnsigned(); - if (params.m_expire < 30) { - cerr << "SIP registrar Time To Live must be more than 30 seconds" << endl; + params.m_password = args.GetOptionString("password"); + + PString error; + if (!SetRegistrationParams(params, error, args, "register-mode", "register-ttl")) { + cerr << error << endl; return false; } - if (args.HasOption("register-mode")) { - PCaselessString str = args.GetOptionString("register-mode"); - if (str == "normal") - params.m_compatibility = SIPRegister::e_FullyCompliant; - else if (str == "single") - params.m_compatibility = SIPRegister::e_CannotRegisterMultipleContacts; - else if (str == "public") - params.m_compatibility = SIPRegister::e_CannotRegisterPrivateContacts; - else { - cerr << "Unknown SIP registration mode \"" << str << '"' << endl; - return false; - } - } if (verbose) cout << "SIP registrar: " << flush; @@ -394,7 +387,7 @@ #if OPAL_H323 // Set up H.323 - interfaces = args.GetOptionString('H'); + interfaces = args.GetOptionString("h323"); if (interfaces != "x") { H323EndPoint * h323 = CreateH323EndPoint(); if (!h323->StartListeners(interfaces.Lines())) { @@ -429,10 +422,10 @@ << (h323->IsH245TunnelingDisabled() ? "Separate" : "Tunnelled") << " H.245, " << h323->GetSendUserInputMode() << '\n'; - if (args.HasOption('g') || args.HasOption('G')) { + if (args.HasOption("gk-host") || args.HasOption("gk-id")) { if (verbose) cout << "H.323 Gatekeeper: " << flush; - if (!h323->UseGatekeeper(args.GetOptionString('g'), args.GetOptionString('G'))) { + if (!h323->UseGatekeeper(args.GetOptionString("gk-host"), args.GetOptionString("gk-id"))) { cerr << "\nCould not complete gatekeeper registration" << endl; return false; } @@ -444,9 +437,9 @@ #if OPAL_LID // If we have LIDs speficied in command line, load them - if (args.HasOption('L')) { + if (args.HasOption("lines")) { OpalLineEndPoint * lines = CreateLineEndPoint(); - if (!lines->AddDeviceNames(args.GetOptionString('L').Lines())) { + if (!lines->AddDeviceNames(args.GetOptionString("lines").Lines())) { cerr << "Could not start Line Interface Device(s)" << endl; return false; } @@ -480,6 +473,18 @@ } +void OpalManagerConsole::Run() +{ + m_endRun.Wait(); +} + + +void OpalManagerConsole::EndRun() +{ + m_endRun.Signal(); +} + + #if OPAL_SIP SIPEndPoint * OpalManagerConsole::CreateSIPEndPoint() { @@ -505,3 +510,278 @@ ///////////////////////////////////////////////////////////////////////////// + +OpalManagerCLI::OpalManagerCLI() + : m_cli(NULL) +{ +} + + +OpalManagerCLI::~OpalManagerCLI() +{ + delete m_cli; +} + + +PString OpalManagerCLI::GetArgumentSpec() const +{ + PString spec = OpalManagerConsole::GetArgumentSpec(); + // Insert just before the version option + spec.Splice("F-script-file: Execute script file in CLI\n" + "-cli: Enable telnet command line sessions on port.\n", + spec.Find("V-version")); + return spec; +} + + +bool OpalManagerCLI::Initialise(PArgList & args, bool verbose) +{ + if (!OpalManagerConsole::Initialise(args, verbose)) + return false; + + if (m_cli == NULL) { + unsigned port = 0; + if (args.HasOption("cli")) { + port = args.GetOptionString("cli").AsUnsigned(); + if (port == 0 || port > 65535) { + cerr << "Illegal CLI port " << port << endl; + return false; + } + } + + m_cli = CreatePCLI((WORD)port); + if (m_cli == NULL) + return false; + } + + m_cli->SetPrompt(PProcess::Current().GetName()); + +#if OPAL_SIP + m_cli->SetCommand("register", PCREATE_NOTIFIER(CmdRegister), + "Register with SIP registrar", + "[ options ] <address> [ <password> ]\n" + " -a or --auth-id <name> : Override user for authorisation\n" + " -r or --realm <name> : Set realm for authorisation\n" + " -p or --proxy <address> : Set proxy for registration\n" + " -m or --mode <mode> : Set registration mode (normal, single, public)\n" + " -t or --ttl <seconds> : Set Time To Live for registration"); +#endif + +#if P_NAT + m_cli->SetCommand("nat address", PCREATE_NOTIFIER(CmdNat), + "Set NAT method and address", + "<method> <address>"); +#endif + +#if PTRACING + m_cli->SetCommand("trace", PCREATE_NOTIFIER(CmdTrace), + "Set trace level (1..6) and filename", + "<n> [ <filename> ]"); +#endif + + m_cli->SetCommand("list codecs", PCREATE_NOTIFIER(CmdListCodecs), + "List available codecs"); + m_cli->SetCommand("delay", PCREATE_NOTIFIER(CmdDelay), + "Delay for the specified numebr of seconds", + "seconds"); + m_cli->SetCommand("version", PCREATE_NOTIFIER(CmdVersion), + "Print application vesion number and library details."); + m_cli->SetCommand("quit\nq\nexit", PCREATE_NOTIFIER(CmdQuit), + "Quit command line interpreter, note quitting from console also shuts down application."); + m_cli->SetCommand("shutdown", PCREATE_NOTIFIER(CmdShutDown), + "Shut down the application"); + return true; +} + + +void OpalManagerCLI::Run() +{ + if (PAssertNULL(m_cli) == NULL) + return; + + if (PProcess::Current().GetArguments().HasOption("script-file")) { + // if there is a script file, process commands + PString filename = PProcess::Current().GetArguments().GetOptionString("script-file"); + PTextFile scriptFile; + if (scriptFile.Open(filename)) { + PCLIStandard * stdCLI = dynamic_cast<PCLIStandard *>(m_cli); + if (stdCLI != NULL) + stdCLI->RunScript(scriptFile); + else + m_cli->Run(&scriptFile, new PNullChannel, false, true); + } + else + cerr << "error: cannot open script file \"" << filename << '"' << endl; + } + + if (m_cli != NULL) + m_cli->Start(false); +} + + +void OpalManagerCLI::EndRun() +{ + if (m_cli != NULL) + m_cli->Stop(); + OpalManagerConsole::EndRun(); +} + + +#if P_TELNET +PCLI * OpalManagerCLI::CreatePCLI(WORD port) +{ + if (port == 0) + return new PCLIStandard; + + PCLI * cli = new PCLITelnet(port); + cli->StartContext(new PConsoleChannel(PConsoleChannel::StandardInput), + new PConsoleChannel(PConsoleChannel::StandardOutput)); + return cli; +} +#else +PCLI * OpalManagerCLI::CreatePCLI() +{ + return new PCLIStandard; +} +#endif + + +#if OPAL_SIP +void OpalManagerCLI::CmdRegister(PCLI::Arguments & args, INT) +{ + if (!args.Parse("a-auth-id:" + "r-realm:" + "p-proxy:" + "m-mode:" + "t-ttl:")) { + args.WriteUsage(); + return; + } + + SIPRegister::Params params; + + params.m_addressOfRecord = args[0]; + params.m_password = args[1]; + params.m_authID = args.GetOptionString('a'); + params.m_realm = args.GetOptionString('r'); + params.m_proxyAddress = args.GetOptionString('p'); + + PString error; + if (!SetRegistrationParams(params, error, args, "mode", "ttl")) { + args.WriteError(error); + return; + } + + args.GetContext() << "Registering with " << params.m_addressOfRecord << " ..." << flush; + + PString aor; + if (FindEndPointAs<SIPEndPoint>("sip")->Register(params, aor, false)) + args.GetContext() << "succeeded" << endl; + else + args.GetContext() << "failed" << endl; +} +#endif + + +#if P_NAT +void OpalManagerCLI::CmdNat(PCLI::Arguments & args, INT) +{ + if (args.GetCount() < 2) { + args.WriteUsage(); + return; + } + + if (!SetNATServer(args[0], args[1])) { + args.WriteError("STUN server offline or unsuitable NAT type"); + return; + } + + PCLI::Context & out = args.GetContext(); + out << m_natMethod->GetName() << " server \"" << m_natMethod->GetServer() << " replies " << m_natMethod->GetNatType(); + PIPSocket::Address externalAddress; + if (m_natMethod->GetExternalAddress(externalAddress)) + out << " with address " << externalAddress; + out.flush(); +} +#endif + + +#if PTRACING +void OpalManagerCLI::CmdTrace(PCLI::Arguments & args, INT) +{ + if (args.GetCount() == 0) + args.WriteUsage(); + else + PTrace::Initialise(args[0].AsUnsigned(), + args.GetCount() > 1 ? (const char *)args[1] : NULL, + PTrace::GetOptions()); +} +#endif // PTRACING + + +void OpalManagerCLI::CmdListCodecs(PCLI::Arguments & args, INT) +{ + OpalMediaFormatList formats; + OpalMediaFormat::GetAllRegisteredMediaFormats(formats); + + PCLI::Context & out = args.GetContext(); + OpalMediaFormatList::iterator format; + for (format = formats.begin(); format != formats.end(); ++format) { + if (format->GetMediaType() == OpalMediaType::Audio() && format->IsTransportable()) + out << *format << '\n'; + } + +#if OPAL_VIDEO + for (format = formats.begin(); format != formats.end(); ++format) { + if (format->GetMediaType() == OpalMediaType::Video() && format->IsTransportable()) + out << *format << '\n'; + } +#endif + + for (format = formats.begin(); format != formats.end(); ++format) { + if (format->GetMediaType() != OpalMediaType::Audio() && +#if OPAL_VIDEO + format->GetMediaType() != OpalMediaType::Video() && +#endif + format->IsTransportable()) + out << *format << '\n'; + } + + out.flush(); +} + + +void OpalManagerCLI::CmdDelay(PCLI::Arguments & args, INT) +{ + if (args.GetCount() < 1) + args.WriteUsage(); + else { + PTimeInterval delay(0, args[0].AsUnsigned()); + m_endRun.Wait(delay); + } +} + + +void OpalManagerCLI::CmdVersion(PCLI::Arguments & args, INT) +{ + PrintVersion(args.GetContext()); +} + + +void OpalManagerCLI::CmdQuit(PCLI::Arguments & args, INT) +{ + if (PIsDescendant(args.GetContext().GetBaseReadChannel(), PConsoleChannel)) + CmdShutDown(args, 0); + else + args.GetContext().Stop(); +} + + +void OpalManagerCLI::CmdShutDown(PCLI::Arguments & args, INT) +{ + args.GetContext().GetCLI().Stop(); +} + + + +///////////////////////////////////////////////////////////////////////////// This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |