📄 main.cxx
字号:
* Fixed problem with recording zero length messages, and added autodelete of files
*
* Revision 1.2 1999/10/22 09:56:24 craigs
* Fixed various compile warnings
*
* Revision 1.1 1999/10/11 00:15:18 craigs
* Initial version
*
*/
#include <ptlib.h>
#include <ptlib/pipechan.h>
#include <signal.h>
#include "version.h"
#include "opalvxml.h"
#include "main.h"
PCREATE_PROCESS(OpenAm);
#define DEFAULT_MSG_LIMIT 30
#define DEFAULT_CALL_LOG "call_log.txt"
#define G7231_SAMPLES_PER_BLOCK 240
#define CHECK_PCM 1
#define CHECK_G7231 2
#define MENU_PREFIX "UserMenu-"
#define DISABLE_COUT 1
static PMutex logMutex;
static PTextFile logFile;
static PFilePath logFilename = DEFAULT_CALL_LOG;
PString G7231Ext(".g723");
PString WAVExt(".wav");
PString PCMExt(".sw");
#if OPENAM_VIDEO
#include <ptclib/pvfiledev.h>
PString VideoGrabberDriverName("YUVFile");
#define DEFAULT_VIDEO_FRAME_RATE 10
#define DEFAULT_VIDEO_SIZE "qcif"
#define DEFAULT_VIDEO_FORMAT "pal"
#define DEFAULT_VIDEO_MODE PVideoInputDevice_YUVFile::Channel_PlayAndClose
// these must be in the same order as the enum in PVideoInputDevice_YUVFile
static const char * VideoModes[PVideoInputDevice_YUVFile::ChannelCount] = {
"Close",
"Repeat",
"KeepLast",
"Black",
};
#endif // OPENAM_VIDEO
///////////////////////////////////////////////////////////////////////////////////////////
static void LogMessage(const PString & str)
{
PTime now;
PString msg = now.AsString("hh:mm:ss dd/MM/yyyy") & str;
logMutex.Wait();
if (!logFile.IsOpen()) {
logFile.Open(logFilename, PFile::ReadWrite);
logFile.SetPosition(0, PFile::End);
}
logFile.WriteLine(msg);
logFile.Close();
logMutex.Signal();
}
static void LogCall(const PFilePath & fn,
const PString & from,
const PString & user,
unsigned len,
const PString & codec,
const PString & product,
const PString & to)
{
PString addr = from;
LogMessage(addr & "\"" + user + "\"" & PString(PString::Unsigned, len) & codec & "\"" + product + "\"" & "\"" + fn + "\"" & "\"" + to + "\"");
}
#ifdef _WIN32
BOOL WINAPI WinCtrlHandlerProc(DWORD dwCtrlType)
{
PString eventName = "CTRL_UNKNOWN_EVENT";
if( dwCtrlType == CTRL_LOGOFF_EVENT ) {
eventName = "CTRL_LOGOFF_EVENT";
LogMessage("OpenAM received " + eventName);
// prevent shut down
return FALSE;
}
if( dwCtrlType == CTRL_C_EVENT )
eventName = "CTRL_C_EVENT";
else if( dwCtrlType == CTRL_BREAK_EVENT )
eventName = "CTRL_BREAK_EVENT";
else if( dwCtrlType == CTRL_CLOSE_EVENT )
eventName = "CTRL_CLOSE_EVENT";
else if( dwCtrlType == CTRL_SHUTDOWN_EVENT )
eventName = "CTRL_SHUTDOWN_EVENT";
LogMessage("OpenAM shutdown due to " + eventName);
OpenAm::Shutdown();
exit(1);
}
#else
void UnixShutdownHandler(int sig)
{
LogMessage(PString("OpenAM received signal ") + PString(sig));
OpenAm::Shutdown();
exit(1);
}
#endif
///////////////////////////////////////////////////////////////
MyH323EndPoint * OpenAm::endpoint = NULL;
OpenAm::OpenAm()
: PProcess("OpenH323 Project", "OpenAM",
MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
{
}
OpenAm::~OpenAm()
{
}
void OpenAm::Main()
{
cout << GetName()
<< " Version " << GetVersion(TRUE)
<< " by " << GetManufacturer()
<< " on " << GetOSClass() << ' ' << GetOSName()
<< " (" << GetOSVersion() << '-' << GetOSHardware() << ")\n\n";
#ifdef _WIN32
SetConsoleCtrlHandler(WinCtrlHandlerProc, TRUE);
#else
signal(SIGTERM, UnixShutdownHandler);
signal(SIGINT, UnixShutdownHandler);
signal(SIGQUIT, UnixShutdownHandler);
#endif
PConfigArgs args(GetArguments());
args.Parse(
"D-disable:"
"d-directory:"
"g-gatekeeper:" "n-no-gatekeeper."
"-g711-ulaw." "-no-g711-ulaw."
"-g711-alaw." "-no-g711-alaw."
"-g711message:" "-no-g711message."
"-g7231." "-no-g7231."
"-g7231message:" "-no-g7231message."
"-ilbc." "-no-ilbc."
"-ilbcmessage:" "-no-ilbcmessage."
"-gsm." "-no-gsm."
"-gsmmessage:" "-no-gsmmessage."
"h-help."
"H-hangup." "-no-hangup."
"i-interface:" "-no-interface."
"k-kill." "-no-kill."
"l-limit:" "-no-limit."
"-listenport:" "-no-listenport."
"-lpc10message:" "-no-lpc10message."
"-speexmessage:" "-no-speexmessage."
"m-message:" "-no-message."
"-no-recordg7231."
"-loop."
#if PTRACING
"o-output:"
#endif
"P-prefer:"
"-pcm." "-no-pcm."
"-pcmmessage:" "-no-pcmmessage."
"-port:"
"r-run:" "-no-run."
"-recordraw."
"-require-gatekeeper." "-no-require-gatekeeper."
"-save."
#if PMEMORY_CHECK
"-setallocationbreakpoint:"
#endif
#if PTRACING
"t-trace."
#endif
"u-username:" "-no-username."
"p-password:"
#if OPENAM_VIDEO
"-videomessage:"
"-videorate:"
"-videosize:"
"-videoformat:"
"-videomode:"
#endif
, FALSE);
#if PMEMORY_CHECK
if (args.HasOption("setallocationbreakpoint"))
PMemoryHeap::SetAllocationBreakpoint(args.GetOptionString("setallocationbreakpoint").AsInteger());
#endif
#if PTRACING
PTrace::Initialise(args.GetOptionCount('t'),
args.HasOption('o') ? (const char *)args.GetOptionString('o') : NULL);
#endif
if (args.HasOption('h')) {
cout << "Usage : " << GetName() << " [options]\n"
"Options:\n"
" -d --directory dir : Put recorded mesages into dir\n"
" -l --limit secs : Limit recorded messages to secs duration (default " << DEFAULT_MSG_LIMIT << ")\n"
" -m --pcmmessage fn : Set outgoing message for PCM derived codecs (G.711/GSM) to fn\n"
" --g7231message fn : Set outgoing message for G723.1 codec to fn\n"
" --g711message fn : Set outgoing message for G711 codec to fn\n"
" --gsmmessage fn : Set outgoing message for GSM codec to fn\n"
" --lpc10message fn : Set outgoing message for LPC10 codec to fn\n"
" --speexmessage fn : Set outgoing message for Speex codec to fn\n"
" --ilbcmessage fn : Set outgoing message for iLBC codec to fn\n"
#if OPENAM_VIDEO
" --videomessage fn : Set outgoing message for video to fn\n"
" --videorate num : Set video frame rate (default is " << DEFAULT_VIDEO_FRAME_RATE << ")\n"
" --videosize size : Set video frame size (default is " << DEFAULT_VIDEO_SIZE << ")\n"
" : Must be one of qcif or cif\n"
" --videoformat fmt : Set video frame format (default is " << DEFAULT_VIDEO_FORMAT << ")\n"
" : Must be one of pal or ntsc\n"
" --videomode mode: : Set video play mode. Default is " << VideoModes[DEFAULT_VIDEO_MODE] << "\n"
" : Must be one of Close, Repeat, KeepLast or Black\n"
#endif
" --loop : loop message, no recording\n"
" --recordraw : Record PCM audo in raw files (.sw) instead of .wav\n"
" -r --run cmd : Run this command after each recorded message\n"
" -k --kill : Kill recorded files after user command\n"
" -H --hangup : hangup after playing message\n"
" -u --username str : Set the local endpoint name to str\n"
" -p --password str : Set the gatekeeper password to str\n"
" -i --interface ip : Bind to a specific interface\n"
" --listenport port : Listen on a specific port\n"
" -g --gatekeeper host: Specify gatekeeper host.\n"
" -n --no-gatekeeper : Disable gatekeeper discovery.\n"
" --require-gatekeeper: Exit if gatekeeper discovery fails.\n"
" -D --disable codec : Disable the specified codec (may be used multiple times)\n"
" -P --prefer codec : Prefer the specified codec (may be used multiple times)\n"
#if PTRACING
" -t --trace : Enable trace, use multiple times for more detail\n"
" -o --output : File for trace output, default is stderr\n"
#endif
" --save : Save arguments in configuration file\n"
" -h --help : Display this help message\n";
return;
}
args.Save("save");
unsigned callLimit = DEFAULT_MSG_LIMIT;
if (args.HasOption('l')) {
callLimit = args.GetOptionString('l').AsInteger();
if (callLimit > 3600) {
cout << "warning: maximum call length " << callLimit << " is out of range. Using " << DEFAULT_MSG_LIMIT << " instead\n";
callLimit = DEFAULT_MSG_LIMIT;
} else if (callLimit == 0)
cout << "warning: recorded message call limit disabled\n";
}
if (!args.HasOption("no-recordg7231") && !args.HasOption("loop"))
cout << "Recorded messages limited to " << callLimit << " seconds\n";
else
cout << "Recording disabled\n";
PString runCmd;
if (args.HasOption('r')) {
runCmd = args.GetOptionString('r');
cout << "Executing \"" << runCmd << "\" after each message" << endl;
}
PDirectory dir;
if (args.HasOption('d'))
dir = args.GetOptionString('d');
int flags = 0;
if (args.HasOption("no-recordg7231")) {
cout << "Supressing recording of G723.1 messages" << endl;
flags |= MyH323EndPoint::NoRecordG7231;
}
if (args.HasOption('k')) {
cout << "Deleting recorded files after processing" << endl;
if (runCmd.IsEmpty())
cout << "WARNING: recorded files will be deleted even though no run command is present" << endl;
flags |= MyH323EndPoint::DeleteAfterRecord;
}
if (args.HasOption('H'))
flags |= MyH323EndPoint::HangupAfterPlay;
endpoint = new MyH323EndPoint(callLimit, runCmd, dir, flags);
PString userName = "OpenH323 Answering Machine v" + GetVersion();
if (args.HasOption('u'))
userName = args.GetOptionString('u');
endpoint->SetLocalUserName(userName);
if (args.HasOption('p')) {
const PString password = args.GetOptionString('p');
endpoint->SetGatekeeperPassword(password);
}
if (!endpoint->Initialise(args))
return;
// start the H.323 listener
H323ListenerTCP * listener;
PIPSocket::Address interfaceAddress(INADDR_ANY);
WORD listenPort = H323EndPoint::DefaultTcpPort;
if (args.HasOption("listenport"))
listenPort = (WORD)args.GetOptionString("listenport").AsInteger();
if (args.HasOption('i'))
interfaceAddress = PIPSocket::Address(args.GetOptionString('i'));
listener = new H323ListenerTCP(*endpoint, interfaceAddress, listenPort);
if (!endpoint->StartListener(listener)) {
cout << "Could not open H.323 listener port on "
<< listener->GetListenerPort() << endl;
delete listener;
return;
}
if (args.HasOption('g')) {
PString gkName = args.GetOptionString('g');
if (endpoint->SetGatekeeper(gkName, new H323TransportUDP(*endpoint)))
cout << "Gatekeeper set: " << *endpoint->GetGatekeeper() << endl;
else {
cout << "Error registering with gatekeeper at \"" << gkName << '"' << endl;
return;
}
}
else if (!args.HasOption('n')) {
cout << "Searching for gatekeeper..." << flush;
if (endpoint->DiscoverGatekeeper(new H323TransportUDP(*endpoint)))
cout << "\nGatekeeper found: " << *endpoint->GetGatekeeper() << endl;
else {
cout << "\nNo gatekeeper found." << endl;
if (args.HasOption("require-gatekeeper"))
return;
}
}
cout << "Waiting for incoming calls for \"" << endpoint->GetLocalUserName() << '"' << endl;
for (;;)
PThread::Current()->Sleep(5000);
}
void OpenAm::Shutdown()
{
if (endpoint) {
if (endpoint->IsRegisteredWithGatekeeper())
endpoint->RemoveGatekeeper();
delete endpoint;
}
exit(0);
}
///////////////////////////////////////////////////////////////
MyH323EndPoint::MyH323EndPoint(unsigned _callLimit,
const PString & _runCmd,
const PDirectory & _dir,
int _flags)
: callLimit(_callLimit), runCmd(_runCmd), dir(_dir), flags(_flags)
{
#if OPENAM_VIDEO
videoSize = 0;
videoIsPal = TRUE;
frameRate = DEFAULT_VIDEO_FRAME_RATE;
videoChannel = DEFAULT_VIDEO_MODE;
#endif
}
BOOL MyH323EndPoint::OnIncomingCall(H323Connection & _conn,
const H323SignalPDU & setupPDU,
H323SignalPDU &)
{
MyH323Connection & conn = (MyH323Connection &)_conn;
// see if incoming call is to a getway address
PString number;
if (setupPDU.GetDestinationE164(number))
conn.SetE164Number(number);
return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -