/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
static const char* const main_cpp_Version =
"$Id: vmserver.cxx,v 1.7.2.2 2003/02/26 01:37:28 sprajpat Exp $";
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream.h>
#include <list>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "Timer.h"
#include "Waiter.h"
#include "cpLog.h"
#include "LineVMCP.h"
#include "VmSession.h"
#include <signal.h>
#include <unistd.h>
/** This is the main class for voice mail server (vmserver)
* VM server uses sockets for communication with clients.
* It listens on port 8024 for requests.
*/
/** shutdown flag */
bool g_bShutdown = false;
string g_xCfgPath;
extern "C" {
void catch_child(int p);
void catch_term(int p);
};
void
catch_child (int p)
{
/** Child was terminated, get return code. */
#ifdef WNOHANG
while (waitpid (-1, NULL, WNOHANG) > 0);
#else
wait (NULL);
#endif
signal (SIGCHLD, catch_child);
}
void
catch_term (int p)
{
/** Termination signal received. Shutown server.
*/
g_bShutdown = true;
exit(1);
}
int
daemon()
{
pid_t pid;
char* envValString = getenv( "NO_DAEMON" );
if( envValString )
{
if( atoi( envValString ) != 0 )
{
cpLog(LOG_DEBUG,"NO_DAEMON environment variable set");
return 0 ;
}
}
if( ( pid = fork() ) < 0 )
{
cpLog(LOG_ERR,"Fork failed!");
return -1 ;
}
else if( pid != 0 )
{
exit ( 0 );
}
setsid();
umask(0);
close(0);
return 0;
}
int
main (int argc, char *argv[])
{
int logPrio=LOG_ERR;
bool daemonflag=false;
bool inetdflag=false;
bool interactive=false;
int vmcpHandle;
g_xCfgPath="./voicemail.config";
int c = 0;
while( ( c = getopt( argc, argv, "idf:v:h:m") ) != EOF )
{
switch(c)
{
/** To run VM Server as the basis for IVR style applications, interactive
* i.e. 'm' flag is used. This is going to be in future release
*/
case 'm':
{
interactive=true;
}
break;
/** With this option, provide a voicemail configuration file */
case 'f':
{
g_xCfgPath = optarg;
}
break;
case 'h':
{
if( optarg == 0 )
vmcpHandle=0;
else
{
vmcpHandle = atoi(optarg);
}
}
break;
/** With 'v' option : specify the Log Priority Level */
case 'v':
{
if( optarg == 0 )
logPrio = 7;
else
{
logPrio = cpLogStrToPriority(optarg);
}
}
break;
/** Run The VMServer as a daemon */
case 'd':
{
daemonflag=true;
}
break;
/** Run The VMServer as a Inet daemon */
case 'i':
{
inetdflag=true;
}
break;
}
}
/** Setup Logging priority */
cpLogSetLabel ("VM");
cpLogSetPriority (logPrio);
Configuration cfg;
/** Parse configuration */
cfg.parse (g_xCfgPath);
cpLogSetPriority (logPrio);
cpLogOpen(cfg.m_xLogFileName.c_str());
if( daemonflag ) daemon();
/** Create sockets */
Vmcp vmcp;
if( inetdflag )
{
vmcp.assign(vmcpHandle,vmcpHandle);
char logLabel[11];
sprintf (logLabel, "VM%08X", getpid ());
cpLogSetLabel (logLabel);
cpLog (LOG_INFO, "Starting session %08X", getpid ());
/** Close waiting socket. We don't need it in this process */
/** Start session */
VmSession session;
session.Start(&vmcp,interactive);
cpLog (LOG_INFO, "End of session");
return 3;
}
/** Catch SIGCHLD signal to get rid of zombies */
signal (SIGCHLD, catch_child);
/** Catch all termination signals to shutdown gracefully */
signal (SIGTERM, catch_term);
signal (SIGHUP, catch_term);
signal (SIGKILL, catch_term);
signal (SIGABRT, catch_term);
signal (SIGSTOP, catch_term);
signal (SIGTSTP, catch_term);
signal (SIGINT, catch_term);
signal (SIGQUIT, catch_term);
/** Open a socket
* Voice Mail server always listens for the requests on port 8024
*/
int sfd;
if( (sfd=vmcp.wait(8024))==-1 )
{
cpLog(LOG_ERR,"Error binding socket %d",sfd );
exit(3);
}
while (!g_bShutdown)
{
int fd;
cpLog(LOG_DEBUG,"Waiting for connection");
fd=vmcp.accept();
if( fd ==-1 )
{
cpLog(LOG_ERR,"Error accepting socket" );
exit(3);
}
if (g_bShutdown)
{
break;
}
cpLog (LOG_DEBUG, "Connected");
/** Ok, we have connected client. */
/** Let's start a new process for it. */
pid_t cPid;
cPid = fork();
switch (cPid)
{
case 0:
{
close(vmcp.getListenSocket());
/** set log label for a new process */
char logLabel[25];
sprintf (logLabel, "VM%08X", getpid ());
cpLogSetLabel (logLabel);
cpLog (LOG_INFO, "Starting session:%d", getpid ());
/** Start session */
VmSession session;
session.Start(&vmcp,interactive);
cpLog (LOG_INFO, "End of session:%d", getpid());
//return 3;
exit(0);
}
default:
/** Close connected socket. We don't need it in this process. */
/** Continue loop */
cpLog(LOG_DEBUG, "In parent: closing");
close(fd);
break;
}
}
cpLog (LOG_INFO, "Server shutdown.");
return EXIT_SUCCESS;
}
syntax highlighted by Code2HTML, v. 0.9.1