// // FUNCTION: CServiceBase::Start(DWORD, PWSTR *) // // PURPOSE: The function starts the service. It calls the OnStart virtual // function in which you can specify the actions to take when the service // starts. If an error occurs during the startup, the error will be logged // in the Application event log, and the service will be stopped. // // PARAMETERS: // * dwArgc - number of command line arguments // * lpszArgv - array of command line arguments // void CServiceBase::Start(DWORD dwArgc, PWSTR *pszArgv) { WriteEventLogEntry(L"Service starting.", TRACE_LEVEL_ERROR); try { // Tell SCM that the service is starting. SetServiceStatus(SERVICE_START_PENDING); // Perform service-specific initialization. OnStart(dwArgc, pszArgv); // Tell SCM that the service is started. SetServiceStatus(SERVICE_RUNNING); } catch (DWORD dwError) { // Log the error. WriteErrorLogEntry(L"Service failed to start.", dwError); // Set the service status to be stopped. SetServiceStatus(SERVICE_STOPPED, dwError); } catch (...) { // Log the error. WriteEventLogEntry(L"Service failed to start.", TRACE_LEVEL_ERROR); // Set the service status to be stopped. SetServiceStatus(SERVICE_STOPPED); } }
void ZeroTierOneService::threadMain() throw() { ZT_SVCDBG("ZeroTierOneService::threadMain()\r\n"); restart_node: try { { ZeroTier::Mutex::Lock _l(_lock); delete _service; _service = (ZeroTier::OneService *)0; // in case newInstance() fails _service = ZeroTier::OneService::newInstance( ZeroTier::OneService::platformDefaultHomePath().c_str(), ZT_DEFAULT_PORT); } switch(_service->run()) { case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: { std::string err("ZeroTier One encountered an unrecoverable error: "); err.append(_service->fatalErrorMessage()); err.append(" (restarting in 5 seconds)"); WriteEventLogEntry(const_cast <PSTR>(err.c_str()),EVENTLOG_ERROR_TYPE); Sleep(5000); } goto restart_node; case ZeroTier::OneService::ONE_IDENTITY_COLLISION: { std::string homeDir(ZeroTier::OneService::platformDefaultHomePath()); delete _service; _service = (ZeroTier::OneService *)0; std::string oldid; ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); if (oldid.length()) { ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); } } goto restart_node; default: // normal termination break; } } catch ( ... ) { // sanity check, shouldn't happen since Node::run() should catch all its own errors // could also happen if we're out of memory though! WriteEventLogEntry("unexpected exception (out of memory?) (trying again in 5 seconds)",EVENTLOG_ERROR_TYPE); Sleep(5000); goto restart_node; } { ZeroTier::Mutex::Lock _l(_lock); delete _service; _service = (ZeroTier::OneService *)0; } }
void SessionServer::OnSessionEmpty(const XSessionConstPtr& session) { // Hold the lock during callbacks from the sessions, which run in their own threads ScopedLock lock(m_mutex); XT_UNREFERENCED_PARAM(session); // Log a service stop message to the Application log. WriteEventLogEntry(L"Sharing Service session empty", EVENTLOG_INFORMATION_TYPE); if (session->GetType() == SessionType::ADHOC) { // Find the session in the list for (size_t i = 0; i < m_sessions.size(); ++i) { if (m_sessions[i] == session) { uint32 sessionID = session->GetId(); // Queue the sessions the be deleted on the server's thread m_sessionsPendingDeletion.push_back(m_sessions[i]); // Erase the session from the list m_sessionChangeListener.erase(m_sessionChangeListener.find(m_sessions[i])); m_sessions.erase(m_sessions.begin() + i); // Notify the clients that the session has closed SessionClosedMsg closedMsg(sessionID); SendSessionMessageToAllClients(closedMsg.ToJSONString()); break; } } } }
// // FUNCTION: CSampleService::OnStop(void) // // PURPOSE: The function is executed when a Stop command is sent to the // service by SCM. It specifies actions to take when a service stops // running. In this code sample, OnStop logs a service-stop message to the // Application log, and waits for the finish of the main service function. // // COMMENTS: // Be sure to periodically call ReportServiceStatus() with // SERVICE_STOP_PENDING if the procedure is going to take long time. // void CSampleService::OnStop() { // Log a service stop message to the Application log. WriteEventLogEntry(L"CppWindowsService in OnStop", EVENTLOG_INFORMATION_TYPE); ProcessHelper::SendCtrlC(); }
// // FUNCTION: CSampleService::OnStart(DWORD, LPWSTR *) // // PURPOSE: The function is executed when a Start command is sent to the // service by the SCM or when the operating system starts (for a service // that starts automatically). It specifies actions to take when the // service starts. In this code sample, OnStart logs a service-start // message to the Application log, and queues the main service function for // execution in a thread pool worker thread. // // PARAMETERS: // * dwArgc - number of command line arguments // * lpszArgv - array of command line arguments // // NOTE: A service application is designed to be long running. Therefore, // it usually polls or monitors something in the system. The monitoring is // set up in the OnStart method. However, OnStart does not actually do the // monitoring. The OnStart method must return to the operating system after // the service's operation has begun. It must not loop forever or block. To // set up a simple monitoring mechanism, one general solution is to create // a timer in OnStart. The timer would then raise events in your code // periodically, at which time your service could do its monitoring. The // other solution is to spawn a new thread to perform the main service // functions, which is demonstrated in this code sample. // void CSampleService::OnStart(DWORD dwArgc, PWSTR *lpszArgv) { // Log a service start message to the Application log. WriteEventLogEntry(L"CppWindowsService in OnStart", EVENTLOG_INFORMATION_TYPE); // Launch external process ProcessHelper::CreateConsoleProcess(); }
// // FUNCTION: CServiceBase::Continue() // // PURPOSE: The function resumes normal functioning after being paused if // the service supports pause and continue. It calls the OnContinue virtual // function in which you can specify the actions to take when the service // continues. If an error occurs, the error will be logged in the // Application event log, and the service will still be paused. // void CServiceBase::Continue() { try { // Tell SCM that the service is resuming. SetServiceStatus(SERVICE_CONTINUE_PENDING); // Perform service-specific continue operations. OnContinue(); // Tell SCM that the service is running. SetServiceStatus(SERVICE_RUNNING); } catch (DWORD dwError) { // Log the error. WriteErrorLogEntry(L"Service failed to resume.", dwError); // Tell SCM that the service is still paused. SetServiceStatus(SERVICE_PAUSED); } catch (...) { // Log the error. WriteEventLogEntry(L"Service failed to resume.", TRACE_LEVEL_ERROR); // Tell SCM that the service is still paused. SetServiceStatus(SERVICE_PAUSED); } }
// // FUNCTION: CServiceBase::Pause() // // PURPOSE: The function pauses the service if the service supports pause // and continue. It calls the OnPause virtual function in which you can // specify the actions to take when the service pauses. If an error occurs, // the error will be logged in the Application event log, and the service // will become running. // void CServiceBase::Pause() { try { // Tell SCM that the service is pausing. SetServiceStatus(SERVICE_PAUSE_PENDING); // Perform service-specific pause operations. OnPause(); // Tell SCM that the service is paused. SetServiceStatus(SERVICE_PAUSED); } catch (DWORD dwError) { // Log the error. WriteErrorLogEntry(L"Service failed to pause.", dwError); // Tell SCM that the service is still running. SetServiceStatus(SERVICE_RUNNING); } catch (...) { // Log the error. WriteEventLogEntry(L"Service failed to pause.", TRACE_LEVEL_ERROR); // Tell SCM that the service is still running. SetServiceStatus(SERVICE_RUNNING); } }
// // FUNCTION: CServiceBase::Stop() // // PURPOSE: The function stops the service. It calls the OnStop virtual // function in which you can specify the actions to take when the service // stops. If an error occurs, the error will be logged in the Application // event log, and the service will be restored to the original state. // void CServiceBase::Stop() { DWORD dwOriginalState = m_status.dwCurrentState; try { // Tell SCM that the service is stopping. SetServiceStatus(SERVICE_STOP_PENDING); // Perform service-specific stop operations. OnStop(); // Tell SCM that the service is stopped. SetServiceStatus(SERVICE_STOPPED); } catch (DWORD dwError) { // Log the error. WriteErrorLogEntry(L"Service failed to stop.", dwError); // Set the orginal service status. SetServiceStatus(dwOriginalState); } catch (...) { // Log the error. WriteEventLogEntry(L"Service failed to stop.", TRACE_LEVEL_ERROR); // Set the orginal service status. SetServiceStatus(dwOriginalState); } }
// // FUNCTION: ServiceBase::WriteErrorLogEntry(PWSTR, DWORD) // // PURPOSE: Log an error message to the Application event log. // // PARAMETERS: // * pszFunction - the function that gives the error // * dwError - the error code // void ServiceBase::WriteErrorLogEntry(PWSTR pszFunction, DWORD dwError) { wchar_t szMessage[260]; StringCchPrintf(szMessage, ARRAYSIZE(szMessage), L"%s failed w/err 0x%08lx", pszFunction, dwError); WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE); }
// // FUNCTION: CServiceBase::WriteErrorLogEntry(PWSTR, DWORD) // // PURPOSE: Log an event. // // PARAMETERS: // * pszFunction - the function that gives the error // * dwError - the error code // void CServiceBase::WriteErrorLogEntry( _In_ PWSTR pszFunction, _In_ DWORD dwError) { wchar_t szMessage[260]; StringCchPrintf(szMessage, ARRAYSIZE(szMessage), L"%s failed w/err 0x%08lx", pszFunction, dwError); WriteEventLogEntry(szMessage, TRACE_LEVEL_ERROR); }
// // FUNCTION: CSampleService::OnStart(DWORD, LPWSTR *) // // PURPOSE: The function is executed when a Start command is sent to the // service by the SCM or when the operating system starts (for a service // that starts automatically). It specifies actions to take when the // service starts. In this code sample, OnStart logs a service-start // message to the Application log, and queues the main service function for // execution in a thread pool worker thread. // // PARAMETERS: // * dwArgc - number of command line arguments // * lpszArgv - array of command line arguments // // NOTE: A service application is designed to be long running. Therefore, // it usually polls or monitors something in the system. The monitoring is // set up in the OnStart method. However, OnStart does not actually do the // monitoring. The OnStart method must return to the operating system after // the service's operation has begun. It must not loop forever or block. To // set up a simple monitoring mechanism, one general solution is to create // a timer in OnStart. The timer would then raise events in your code // periodically, at which time your service could do its monitoring. The // other solution is to spawn a new thread to perform the main service // functions, which is demonstrated in this code sample. // void CSampleService::OnStart(DWORD dwArgc, LPWSTR *lpszArgv) { // Log a service start message to the Application log. WriteEventLogEntry(L"CppWindowsService in OnStart", EVENTLOG_INFORMATION_TYPE); // Queue the main service function for execution in a worker thread. CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this); }
// // FUNCTION: CSampleService::OnStop(void) // // PURPOSE: The function is executed when a Stop command is sent to the // service by SCM. It specifies actions to take when a service stops // running. In this code sample, OnStop logs a service-stop message to the // Application log, and waits for the finish of the main service function. // // COMMENTS: // Be sure to periodically call ReportServiceStatus() with // SERVICE_STOP_PENDING if the procedure is going to take long time. // void CSampleService::OnStop() { // Log a service stop message to the Application log. WriteEventLogEntry(L"CppWindowsService in OnStop", EVENTLOG_INFORMATION_TYPE); // Indicate that the service is stopping and wait for the finish of the // main service function (ServiceWorkerThread). m_fStopping = TRUE; if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0) { throw GetLastError(); } }
void SessionServer::OnStop() { LogInfo("**********************************"); LogInfo("****** Sharing Service OnStop ******"); LogInfo("**********************************"); // Log a service stop message to the Application log. WriteEventLogEntry(L"Sharing Server stopping", EVENTLOG_INFORMATION_TYPE); // Indicate that the service is stopping and wait for the finish of the // main service function (ServerThreadFunc). m_stopping = TRUE; m_serverThread->WaitForThreadExit(); TeardownFileLogger(); }
// // FUNCTION: CServiceBase::Shutdown() // // PURPOSE: The function executes when the system is shutting down. It // calls the OnShutdown virtual function in which you can specify what // should occur immediately prior to the system shutting down. If an error // occurs, the error will be logged in the Application event log. // void CServiceBase::Shutdown() { try { // Perform service-specific shutdown operations. OnShutdown(); // Tell SCM that the service is stopped. SetServiceStatus(SERVICE_STOPPED); } catch (DWORD dwError) { // Log the error. WriteErrorLogEntry(L"Service failed to shut down.", dwError); } catch (...) { // Log the error. WriteEventLogEntry(L"Service failed to shut down.", TRACE_LEVEL_ERROR); } }
void SessionServer::OnStart(DWORD dwArgc, PWSTR *pszArgv) { InitializeFileLogger(); // Log out an obvious piece of text to help distinguish between server sessions. LogInfo("***********************************"); LogInfo("****** Sharing Service OnStart ******"); LogInfo("***********************************"); // Log a service start message to the Application log. WriteEventLogEntry(L"Sharing Server starting", EVENTLOG_INFORMATION_TYPE); LogInfo("Server Info: \n\tBuild Version: %ls \n\tSchema Version: %i", XTOOLS_VERSION_STRING, kXToolsSchemaVersion); // TODO: use different machines, etc, based on command line parameters XT_UNREFERENCED_PARAM(dwArgc); XT_UNREFERENCED_PARAM(pszArgv); // Start listening for new connections m_listenerReceipt = m_socketMgr->AcceptConnections(kSessionServerPort, kSessionServerMaxConnections, this); LogInfo("Listening for session list connections on port %i of all network devices of the local machine.", kSessionServerPort); LogInfo("Local IP addresses are:"); IPAddressList addressList = m_socketMgr->GetLocalMachineAddresses(); for (size_t i = 0; i < addressList.size(); ++i) { LogInfo("\t%s", addressList[i].ToString().c_str()); } // Allocate a pool of ports to use for sessions m_portPool = new PortPool(kSessionServerPort-1, 256); // TODO: Read from a configuration file for persistent sessions. XTVERIFY(CreateNewSession("Default", SessionType::PERSISTENT) != NULL); // Start a thread to run the main service logic. m_serverThread = new MemberFuncThread(&SessionServer::ServerThreadFunc, this); }
void ZeroTierOneService::threadMain() throw() { ZT_SVCDBG("ZeroTierOneService::threadMain()\r\n"); restart_node: try { { // start or restart ZeroTier::Mutex::Lock _l(_lock); delete _node; _node = new ZeroTier::Node(ZeroTier::ZT_DEFAULTS.defaultHomePath.c_str(),ZT_DEFAULT_UDP_PORT,0,false); } switch(_node->run()) { case ZeroTier::Node::NODE_RESTART_FOR_UPGRADE: { // Shut down node ZeroTier::Node *n; { ZeroTier::Mutex::Lock _l(_lock); n = _node; _node = (ZeroTier::Node *)0; } std::string msiPath; if (n) { const char *msiPathTmp = n->reasonForTermination(); if (msiPathTmp) msiPath = msiPathTmp; } delete n; if ((!msiPath.length())||(!ZeroTier::Utils::fileExists(msiPath.c_str()))) { WriteEventLogEntry("auto-update failed: no msi path provided by Node",EVENTLOG_ERROR_TYPE); Sleep(5000); goto restart_node; } if (!doStartUpgrade(msiPath)) { WriteEventLogEntry("auto-update failed: unable to create InstallAndRestartService.bat",EVENTLOG_ERROR_TYPE); Sleep(5000); goto restart_node; } // Terminate service to allow updater to update Stop(); } return; case ZeroTier::Node::NODE_UNRECOVERABLE_ERROR: { std::string err("ZeroTier node encountered an unrecoverable error: "); const char *r = _node->reasonForTermination(); if (r) err.append(r); else err.append("(unknown error)"); err.append(" (restarting in 5 seconds)"); WriteEventLogEntry(const_cast <PSTR>(err.c_str()),EVENTLOG_ERROR_TYPE); Sleep(5000); goto restart_node; } break; default: // includes normal termination, which will terminate thread break; } } catch ( ... ) { // sanity check, shouldn't happen since Node::run() should catch all its own errors // could also happen if we're out of memory though! WriteEventLogEntry("unexpected exception (out of memory?) (trying again in 5 seconds)",EVENTLOG_ERROR_TYPE); Sleep(5000); goto restart_node; } _lock.lock(); delete _node; _node = (ZeroTier::Node *)0; _lock.unlock(); }