283 lines
8.4 KiB
C++

//----------------------------------------------------------------------------
//
// Copyright (C) Intel Corporation, 2006 - 2007.
//
// File: mps.cpp
//
// Contents: The program's entry point, starting acceptors and connectors,
// timers, and the reactor to start accepting connections.
//
// Notes:
//----------------------------------------------------------------------------
//===================================================
// INCLUDES
//===================================================
#include <fstream>
#include <ace/Signal.h>
#include <ace/Logging_Strategy.h>
#include <ace/Get_Opt.h>
#include <ace/OS_NS_sys_stat.h>
//#include "ace/Reactor.h"
#include <ace/OS_NS_signal.h>
#include <ace/OS_NS_string.h>
#include <ace/OS_NS_unistd.h>
#include <ace/Synch_Traits.h>
#include <ace/Thread_Semaphore.h>
#include <ace/String_Base.h>
#include <ace/Auto_Ptr.h>
#include <ace/TP_Reactor.h>
//mps includes:
#include "DynamicConfiguration.h"
#include "acceptor.h"
#include "DevicePresence.h"
#include "MPSReactorTask.h"
#include "SocksSvcHandler.h"
#include "TunnelHandler.h"
#include "global.h"
#include "OptionsUtils.h"
#include "Logger.h"
#include "MPS_Class.h"
#include "GuardedCounter.h"
#include "Options.h"
//#define ACE_NTRACE 0
#define SLEEP_TIME 500
#define HEADING "Intel(R) Management Presence Server"
GuardedCounter TUNNEL_COUNTER;
GuardedCounter TCP_COUNTER;
STATUS validateLogFilePath(const ACE_TString& filePath, bool& absPath);
//===================================================
// Globals
//===================================================
ACE_Event stop_event;
//===================================================
// Initialize acceptors, logger, and reactor
//===================================================
/*int mps_init (int argc, ACE_TCHAR *argv[])
{
int status = 0;
dynamic_config.attach(&logger);
return status;
}*/
//===================================================
// Main
//===================================================
int run_main (int argc, ACE_TCHAR *argv[])
{
TUNNEL_COUNTER.SetMaxValue(MAX_TUNNEL_COUNTER);
TCP_COUNTER.SetMaxValue(MAX_TCP_COUNTER);
stop_event.reset();
int status = 0;
// Prepare the logging mechanism
logFileNameFull = "";
const ACE_TString* filePathPtr = getLogFilePath();
if (filePathPtr == NULL) {
ACE_ERROR_RETURN((MY_ERROR
ACE_TEXT("Failed getting log file name.\n")), -1);
}
ACE_TString filePath = *filePathPtr;
bool absPath;
if (validateLogFilePath(filePath, absPath) != STATUS_SUCCESS)
{
ACE_ERROR_RETURN((MY_ERROR ACE_TEXT ("Log file path is incorrect %s.\n"),
filePath.c_str()), -1);
}
if (!absPath)
{
logFileNameFull += absolutePath;
}
logFileNameFull += filePath;
// Create the appropriate directory
// Note: (not checking for return value, on failure, will find out later).
ACE_OS::mkdir(logFileNameFull.c_str());
// We must open the output file first.
const ACE_TString* logFileNamePtr = getLogFileName();
if (logFileNamePtr == NULL) {
ACE_ERROR_RETURN((MY_ERROR
ACE_TEXT("Failed getting output file name.\n")), -1);
}
const ACE_TString& logFileName = *logFileNamePtr;
logFileNameFull += logFileName;
ofstream log_file;
log_file.open(logFileNameFull.c_str(), ios::app | ios::out);
if (log_file.fail())
{
ACE_ERROR_RETURN((MY_ERROR
ACE_TEXT ("Failed opening log file for read/write.\n")), -1);
}
ACE_LOG_MSG->msg_ostream(&log_file);
ACE_LOG_MSG->open("MPS", ACE_Log_Msg::OSTREAM);
DynamicConfiguration dynamic_config;
MPS_Reactor_Task reactor_task;
Logger logger;
dynamic_config.attach(&logger);
ACE_Time_Value delay(DYNAMIC_CONFIGURATION_DELAY);
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
m_pLogger.LogInfoEvent(MPS_INFO, MPS_START);
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
const unsigned int* nthreadsPtr = getThreadNumber();
if (nthreadsPtr == NULL) {
ACE_ERROR_RETURN((MY_ERROR
ACE_TEXT("Failed to get thread number.\n")), -1);
}
const unsigned int& nthreads = *nthreadsPtr;
if (reactor_task.start(nthreads) == 0)
{
if (logger.init(logFileNameFull.c_str()) == STATUS_FAILURE)
{
ACE_ERROR ((MY_ERROR ACE_TEXT ("Failed to initialize logger\n")));
}
ACE_DEBUG((MY_INFO ACE_TEXT("%s %s\n"), HEADING, "has started"));
// Start dynamic configuration first
if (dynamic_config.start(ACE_Time_Value(0), delay) == STATUS_FAILURE)
{
ACE_ERROR ((MY_ERROR ACE_TEXT ("Failed to start dynamic configuration\n")));
}
DevicePresence::instance().start();
// ---- Start AMT acceptors ---
ACE_INET_Addr amt_acceptor_address;
if (getAMTListenINET(amt_acceptor_address) != STATUS_SUCCESS)
{
ACE_ERROR ((MY_ERROR ACE_TEXT ("Failed to listen on AMT listen address, exiting MPS\n")));
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
m_pLogger.LogErrorEvent(MPS_ERROR, MPS_AMT_ACCEPTOR_FAIL_MESSAGE);
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
return -1;
}
ACE_TCHAR buffer1[MAXHOSTNAMELEN];
amt_acceptor_address.addr_to_string(buffer1, MAXHOSTNAMELEN);
ACE_DEBUG((MY_TRACE ACE_TEXT("amt binding addr: %s"), buffer1));
if (MPS_Class::instance()->_amt_acceptor.start(amt_acceptor_address) == -1)
{
ACE_TCHAR buffer[MAXHOSTNAMELEN];
if (amt_acceptor_address.addr_to_string(buffer, MAXHOSTNAMELEN) != -1)
{
ACE_ERROR ((MY_ERROR ACE_TEXT ("Failed to listen on %p, exiting MPS\n"),buffer));
}
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
m_pLogger.LogErrorEvent(MPS_ERROR, MPS_AMT_ACCEPTOR_FAIL_MESSAGE);
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
return -1;
}
// ------- Start SOCKS acceptor --------
ACE_INET_Addr socks_acceptor_address;
if (getListenINET(NETWORK_SECTION, MC_SOCKS_LISTEN_IP_ELEMENT, MC_SOCKS_LISTEN_PORT_ELEMENT, socks_acceptor_address) != STATUS_SUCCESS)
{
ACE_ERROR ((MY_ERROR ACE_TEXT ("Failed to listen on Socks listen address, exiting MPS\n")));
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
m_pLogger.LogErrorEvent(MPS_ERROR, MPS_SOCKS_ACCEPTOR_FAIL_MESSAGE);
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
return -1;
}
if (MPS_Class::instance()->_socks_acceptor.start(socks_acceptor_address) == -1)
{
ACE_TCHAR buffer[MAXHOSTNAMELEN];
if (socks_acceptor_address.addr_to_string(buffer, MAXHOSTNAMELEN) != -1)
{
ACE_ERROR ((MY_ERROR ACE_TEXT ("Failed to listen on %p, exiting MPS\n"),buffer));
}
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
m_pLogger.LogErrorEvent(MPS_ERROR, MPS_SOCKS_ACCEPTOR_FAIL_MESSAGE);
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
return -1;
}
}
stop_event.wait();
delete(ConfigFormats::instance());
delete(Options::instance());
ACE_LOG_MSG->msg_ostream(&std::cerr, true);
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
Sleep(SLEEP_TIME);
ExitProcess(status);
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
log_file.close();
return status;
}
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
int closeMPS()
{
ACE_DEBUG((MY_INFO ACE_TEXT("---------< MPS Stopping >----------\n")));
// Close the acceptors (release the sockets)
MPS_Class::instance()->_socks_acceptor.close();
MPS_Class::instance()->_amt_acceptor.close();
ACE_Thread_Manager::instance ()->cancel_all();
Sleep(1000);
ACE_Thread_Manager::instance ()->suspend_all();
stop_event.signal();
return 0;
}
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
// Used to validate the log file path given.
// Enters into absPath if the path is absolute or not
// Returns STATUS_SUCCESS if it is correct,
// returns STATUS_FAILURE otherwise.
STATUS validateLogFilePath(const ACE_TString& filePath, bool& absPath)
{
absPath = false;
// first check if it is an absolute or relative path
if (!filePath.empty() &&
((filePath[1] == ':') ||
((filePath[0] == '\\') && (filePath[1] == '\\'))))
{
absPath = true;
}
if (!absPath && filePath.empty())
{
return STATUS_SUCCESS;
}
if (filePath[0] == '\\')
{
return STATUS_FAILURE;
}
#ifdef ACE_WIN32
if ((filePath[filePath.length()-1] != '/') &&
(filePath[filePath.length()-1] != '\\'))
#else
if (filePath[filePath.length()-1] != '/')
#endif
{
return STATUS_FAILURE;
}
return STATUS_SUCCESS;
}