Changeset - 98982a60fba3
[Not reviewed]
0 6 4
Vitaly Takmazov - 13 years ago 2012-08-01 11:26:04
vitalyster@gmail.com
spectrum win32 service, in progress
10 files changed with 364 insertions and 8 deletions:
0 comments (0 inline, 0 general)
.gitignore
Show inline comments
 
*.pb.cc
 
*.pb.h
 
\ No newline at end of file
 
*.pb.h
 
plugin/python/protocol_pb2.py
 
\ No newline at end of file
CMakeLists.txt
Show inline comments
 
@@ -56,18 +56,14 @@ set(Boost_USE_STATIC_LIBS      ON)
 
set(Boost_USE_MULTITHREADED      ON)
 
set(Boost_USE_STATIC_RUNTIME    OFF)
 
endif()
 
find_package(Boost COMPONENTS program_options date_time system filesystem regex  signals REQUIRED)
 
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
 

	
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Protobuf REQUIRED)
 
else()
 
set(PROTOBUF_FOUND TRUE)
 
endif()
 

	
 
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Communi)
 

	
 
set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(log4cxx)
msvc-deps/CMakeLists.txt
Show inline comments
 
ADD_SUBDIRECTORY(sqlite3)
 
ADD_SUBDIRECTORY(protobuf)
 
\ No newline at end of file
spectrum/src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
 
if (WIN32)
 
FILE(GLOB WIN_SRC win32/*.cpp)
 
include_directories(win32)
 
ADD_EXECUTABLE(spectrum2 ${SRC} ${WIN_SRC})
 
else()
 
ADD_EXECUTABLE(spectrum2 ${SRC})
 
endif()
 
 
 
 
ADD_DEPENDENCIES(spectrum2 spectrum2_libpurple_backend)
 
ADD_DEPENDENCIES(spectrum2 spectrum2_libircclient-qt_backend)
 
 
target_link_libraries(spectrum2 transport ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
 
if (NOT CMAKE_COMPILER_IS_GNUCXX)
spectrum/src/main.cpp
Show inline comments
 
@@ -23,12 +23,13 @@
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
#else
 
#include <process.h>
 
#define getpid _getpid
 
#include "win32/SpectrumService.h"
 
#endif
 
#include <sys/stat.h>
 

	
 
using namespace Transport;
 

	
 
DEFINE_LOGGER(logger, "Spectrum");
 
@@ -140,12 +141,17 @@ int main(int argc, char **argv)
 
		("no-daemonize,n", "Do not run spectrum as daemon")
 
		("no-debug,d", "Create coredumps on crash")
 
		("jid,j", boost::program_options::value<std::string>(&jid)->default_value(""), "Specify JID of transport manually")
 
		("config", boost::program_options::value<std::string>(&config_file)->default_value(""), "Config file")
 
		("version,v", "Shows Spectrum version")
 
		;
 
#ifdef WIN32
 
	desc.add_options()
 
		("install-service,i", "Install spectrum as Windows service")
 
		("uninstall-service,u", "Uninstall Windows service");
 
#endif
 
	try
 
	{
 
		boost::program_options::positional_options_description p;
 
		p.add("config", -1);
 
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
 
          options(desc).positional(p).allow_unregistered().run(), vm);
 
@@ -167,12 +173,52 @@ int main(int argc, char **argv)
 
			return 1;
 
		}
 

	
 
		if(vm.count("no-daemonize")) {
 
			no_daemon = true;
 
		}
 
#ifdef WIN32
 
		if (vm.count("install-service")) {
 
			SpectrumService ntservice;
 
			if (!ntservice.IsInstalled()) {
 
					// determine the name of the currently executing file
 
				char szFilePath[MAX_PATH];
 
				GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
 
				std::string exe_file(szFilePath);
 
				std::string config_file = exe_file.replace(exe_file.end() - 4, exe_file.end(), ".cfg");
 
				std::string service_path = std::string(szFilePath) + std::string(" --config ") + config_file;
 

	
 
				if (ntservice.Install(service_path.c_str())) {
 
					std::cout << "Successfully installed" << std::endl;
 
					return 0;
 
				} else {
 
					std::cout << "Error installing service, are you an Administrator?" << std::endl;
 
					return 1;
 
				}                				
 
			} else {
 
				std::cout << "Already installed" << std::endl;
 
				return 1;
 
			}
 
		}
 
		if (vm.count("uninstall-service")) {
 
			SpectrumService ntservice;
 
			if (ntservice.IsInstalled()) {
 
				if (ntservice.Remove()) {
 
					std::cout << "Successfully removed" << std::endl;
 
					return 0;
 
				} else {
 
					std::cout << "Error removing service, are you an Administrator?" << std::endl;
 
					return 1;
 
				}                               				
 
			} else {
 
				std::cout << "Service not installed" << std::endl;
 
				return 1;
 
			}
 
		}
 

	
 
#endif
 
	}
 
	catch (std::runtime_error& e)
 
	{
 
		std::cout << desc << "\n";
 
		return 1;
 
	}
 
@@ -283,13 +329,13 @@ int main(int argc, char **argv)
 
	if (storageBackend == NULL) {
 
		if (!error.empty()) {
 
			std::cerr << error << "\n";
 
			return -2;
 
		}
 
	}
 
	else if (!storageBackend->connect()) {
 
	else if (!storageBackend->connect()) {        
 
		std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
		return -1;
 
	}
 

	
 
	UserManager userManager(&transport, &userRegistry, storageBackend);
 
	userManager_ = &userManager;
spectrum/src/win32/SpectrumService.cpp
Show inline comments
 
new file 100644
 
#include "SpectrumService.h"
 

	
 
SpectrumService::SpectrumService(void) {
 
	serviceName = "Spectrum2";
 
	displayName = "Spectrum2 XMPP Transport";
 
	username = NULL;
 
	password = NULL;
 
}
 

	
 
SpectrumService::~SpectrumService(void) {}
 

	
 
void SpectrumService::Stop() {
 
	ReportStatus((DWORD)SERVICE_STOP_PENDING);
 
}
 

	
 
void SpectrumService::Run(DWORD argc, LPTSTR *argv) {
 
	ReportStatus((DWORD)SERVICE_RUNNING);
 
	main(argc, argv);
 
}
 
\ No newline at end of file
spectrum/src/win32/SpectrumService.h
Show inline comments
 
new file 100644
 
#include <windows.h>
 
#include "WindowsService.h"
 

	
 
class SpectrumService : public WindowsService {
 

	
 
public:
 
	SpectrumService(void);
 
	~SpectrumService(void);
 
protected:
 
	void Stop();
 
	void Run(DWORD argc, LPTSTR *argv);
 
};
 

	
 
int main(int argc, char **argv);
 
\ No newline at end of file
spectrum/src/win32/WindowsService.cpp
Show inline comments
 
new file 100644
 
/* Copyright (C) 2005 MySQL AB
 

	
 
   This program is free software; you can redistribute it and/or modify
 
   it under the terms of the GNU General Public License as published by
 
   the Free Software Foundation; version 2 of the License.
 

	
 
   This program is distributed in the hope that it will be useful,
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   GNU General Public License for more details.
 

	
 
   You should have received a copy of the GNU General Public License
 
   along with this program; if not, write to the Free Software
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 

	
 
#include <windows.h>
 
#include <assert.h>
 
#include ".\windowsservice.h"
 

	
 
static WindowsService *gService;
 

	
 
WindowsService::WindowsService(void) :
 
  statusCheckpoint(0),
 
  serviceName(NULL),
 
  inited(false),
 
  dwAcceptedControls(SERVICE_ACCEPT_STOP),
 
  debugging(false)
 
{
 
  gService= this;
 
  status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
 
  status.dwServiceSpecificExitCode= 0;
 
}
 

	
 
WindowsService::~WindowsService(void)
 
{
 
}
 

	
 
BOOL WindowsService::Install(const char *szFilePath)
 
{
 
  bool ret_val= false;
 
  SC_HANDLE newService;
 
  SC_HANDLE scm;
 

	
 
  if (IsInstalled()) return true;
 

	
 
  // open a connection to the SCM
 
  if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
 
    return false;
 

	
 
  newService= CreateService(scm, serviceName, displayName,
 
                            SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
 
                            SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
 
                            szFilePath, NULL, NULL, NULL, username,
 
                            password);
 

	
 
  if (newService)
 
  {
 
    CloseServiceHandle(newService);
 
    ret_val= true;
 
  }
 

	
 
  CloseServiceHandle(scm);
 
  return ret_val;
 
}
 

	
 
BOOL WindowsService::Init()
 
{
 
  assert(serviceName != NULL);
 

	
 
  if (inited) return true;
 

	
 
  SERVICE_TABLE_ENTRY stb[] =
 
  {
 
    { (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
 
    { NULL, NULL }
 
  };
 
  inited= true;
 
  return StartServiceCtrlDispatcher(stb); //register with the Service Manager
 
}
 

	
 
BOOL WindowsService::Remove()
 
{
 
  bool  ret_val= false;
 

	
 
  if (! IsInstalled())
 
    return true;
 

	
 
  // open a connection to the SCM
 
  SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
 
  if (! scm)
 
    return false;
 

	
 
  SC_HANDLE service= OpenService(scm, serviceName, DELETE);
 
  if (service)
 
  {
 
    if (DeleteService(service))
 
      ret_val= true;
 
    DWORD dw= ::GetLastError();
 
    CloseServiceHandle(service);
 
  }
 

	
 
  CloseServiceHandle(scm);
 
  return ret_val;
 
}
 

	
 
BOOL WindowsService::IsInstalled()
 
{
 
  BOOL ret_val= FALSE;
 

	
 
  SC_HANDLE scm= ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
 
  SC_HANDLE serv_handle= ::OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
 

	
 
  ret_val= serv_handle != NULL;
 

	
 
  ::CloseServiceHandle(serv_handle);
 
  ::CloseServiceHandle(scm);
 

	
 
  return ret_val;
 
}
 

	
 
void WindowsService::SetAcceptedControls(DWORD acceptedControls)
 
{
 
  dwAcceptedControls= acceptedControls;
 
}
 

	
 

	
 
BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
 
                                  DWORD dwError)
 
{
 
  if(debugging) return TRUE;
 

	
 
  if(currentState == SERVICE_START_PENDING)
 
    status.dwControlsAccepted= 0;
 
  else
 
    status.dwControlsAccepted= dwAcceptedControls;
 

	
 
  status.dwCurrentState= currentState;
 
  status.dwWin32ExitCode= dwError != 0 ?
 
    ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
 
  status.dwWaitHint= waitHint;
 
  status.dwServiceSpecificExitCode= dwError;
 

	
 
  if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
 
  {
 
    status.dwCheckPoint= 0;
 
    statusCheckpoint= 0;
 
  }
 
  else
 
    status.dwCheckPoint= ++statusCheckpoint;
 

	
 
  // Report the status of the service to the service control manager.
 
  BOOL result= SetServiceStatus(statusHandle, &status);
 
  if (!result)
 
    Log("ReportStatus failed");
 

	
 
  return result;
 
}
 

	
 
void WindowsService::RegisterAndRun(DWORD argc, LPTSTR *argv)
 
{
 
  statusHandle= ::RegisterServiceCtrlHandler(serviceName, ControlHandler);
 
  if (statusHandle && ReportStatus(SERVICE_START_PENDING))
 
    Run(argc, argv);
 
  ReportStatus(SERVICE_STOPPED);
 
}
 

	
 
void WindowsService::HandleControlCode(DWORD opcode)
 
{
 
  // Handle the requested control code.
 
  switch(opcode) {
 
  case SERVICE_CONTROL_STOP:
 
    // Stop the service.
 
    status.dwCurrentState= SERVICE_STOP_PENDING;
 
    Stop();
 
    break;
 

	
 
  case SERVICE_CONTROL_PAUSE:
 
    status.dwCurrentState= SERVICE_PAUSE_PENDING;
 
    Pause();
 
    break;
 

	
 
  case SERVICE_CONTROL_CONTINUE:
 
    status.dwCurrentState= SERVICE_CONTINUE_PENDING;
 
    Continue();
 
    break;
 

	
 
  case SERVICE_CONTROL_SHUTDOWN:
 
    Shutdown();
 
    break;
 

	
 
  case SERVICE_CONTROL_INTERROGATE:
 
    ReportStatus(status.dwCurrentState);
 
    break;
 

	
 
  default:
 
    // invalid control code
 
    break;
 
  }
 
}
 

	
 
void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
 
{
 
  assert(gService != NULL);
 

	
 
  // register our service control handler:
 
  gService->RegisterAndRun(argc, argv);
 
}
 

	
 
void WINAPI WindowsService::ControlHandler(DWORD opcode)
 
{
 
  assert(gService != NULL);
 

	
 
  return gService->HandleControlCode(opcode);
 
}
spectrum/src/win32/WindowsService.h
Show inline comments
 
new file 100644
 
/* Copyright (C) 2005 MySQL AB
 

	
 
   This program is free software; you can redistribute it and/or modify
 
   it under the terms of the GNU General Public License as published by
 
   the Free Software Foundation; version 2 of the License.
 

	
 
   This program is distributed in the hope that it will be useful,
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   GNU General Public License for more details.
 

	
 
   You should have received a copy of the GNU General Public License
 
   along with this program; if not, write to the Free Software
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 

	
 
#pragma once
 

	
 
class WindowsService
 
{
 
protected:
 
  bool                  inited;
 
  const char            *serviceName;
 
  const char            *displayName;
 
  const char            *username;
 
  const char            *password;
 
  SERVICE_STATUS_HANDLE statusHandle;
 
  DWORD                 statusCheckpoint;
 
  SERVICE_STATUS        status;
 
  DWORD                 dwAcceptedControls;
 
  bool                  debugging;
 

	
 
public:
 
  WindowsService(void);
 
  ~WindowsService(void);
 

	
 
  BOOL  Install(const char *szFilePath);
 
  BOOL  Remove();
 
  BOOL  Init();
 
  BOOL  IsInstalled();
 
  void  SetAcceptedControls(DWORD acceptedControls);
 
  void  Debug(bool debugFlag) { debugging= debugFlag; }
 

	
 
public:
 
  static void WINAPI    ServiceMain(DWORD argc, LPTSTR *argv);
 
  static void WINAPI    ControlHandler(DWORD CtrlType);
 

	
 
protected:
 
  virtual void Run(DWORD argc, LPTSTR *argv)= 0;
 
  virtual void Stop()                 {}
 
  virtual void Shutdown()             {}
 
  virtual void Pause()                {}
 
  virtual void Continue()             {}
 
  virtual void Log(const char *msg)   {}
 

	
 
  BOOL ReportStatus(DWORD currentStatus, DWORD waitHint= 3000, DWORD dwError=0);
 
  void HandleControlCode(DWORD opcode);
 
  void RegisterAndRun(DWORD argc, LPTSTR *argv);
 
};
src/config.cpp
Show inline comments
 
@@ -52,18 +52,19 @@ bool Config::load(const std::string &configfile, boost::program_options::options
 
	if (!ifs.is_open())
 
		return false;
 

	
 
	m_file = configfile;
 
	bool ret = load(ifs, opts, jid);
 
	ifs.close();
 

	
 
#ifndef WIN32
 
	char path[PATH_MAX] = "";
 
	if (m_file.find_first_of("/") != 0) {
 
		getcwd(path, PATH_MAX);
 
		m_file = std::string(path) + "/" + m_file;
 
	}
 
#endif
 

	
 
	return ret;
 
}
 

	
 
bool Config::load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &_jid) {
 
	m_unregistered.clear();
0 comments (0 inline, 0 general)