torservice.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00019  *  Boston, MA  02110-1301, USA.
00020  ****************************************************************/
00021 
00022 /** 
00023  * \file torservice.cpp
00024  * \version $Id: torservice.cpp 1238 2006-09-25 17:50:57Z edmanm $
00025  * \brief Starts, stops, installs, and uninstalls a Tor service (Win32).
00026  */
00027 
00028 #include "torservice.h"
00029 
00030 
00031 /** Returns true if services are supported. */
00032 bool
00033 TorService::isSupported()
00034 {
00035   bool supported = false;
00036 #if defined(Q_OS_WIN32)
00037   supported = (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based);
00038 #endif
00039   return supported;
00040 }
00041 
00042 /** Default ctor. */
00043 TorService::TorService(const QString &torPath, const QString &torrc,
00044                        QObject* parent)
00045   : QObject(parent)
00046 {
00047   Q_UNUSED(torrc);
00048 
00049   // FIXME this is hardcoded for now
00050   _torrc = "\"C:\\Program Files\\Tor\\torrc\"";
00051   _torPath = "\"" + torPath + "\"";
00052   _manager = NULL;
00053   _service = NULL;
00054 
00055   initialize();
00056 }
00057 
00058 /** Default dtor. */
00059 TorService::~TorService()
00060 {
00061   close();
00062 }
00063 
00064 /** Closes the service and the service manager. */
00065 void
00066 TorService::close()
00067 {
00068 #if defined(Q_OS_WIN32)
00069   if (_service) {
00070     CloseServiceHandle(_service);
00071     _service = NULL;
00072   }
00073 
00074   if (_manager) {
00075     CloseServiceHandle(_manager);
00076     _manager = NULL;
00077   }
00078 #endif
00079 }
00080 
00081 /** Initializes the service and service manager. */
00082 void
00083 TorService::initialize()
00084 {
00085   /* If services are supported, initialize the manager and service */
00086 #if defined(Q_OS_WIN32)
00087   if (isSupported()) {
00088     /* Open service manager */
00089     if (_manager == NULL) {
00090     _manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
00091     }
00092     /* Open tor service */
00093     if (_service == NULL) {
00094     _service = OpenServiceA(_manager, TOR_SERVICE_NAME, TOR_SERVICE_ACCESS);
00095     }
00096   }
00097 #endif
00098 }
00099 
00100 /** Returns true if the Tor service is installed. */
00101 bool
00102 TorService::isInstalled()
00103 {
00104   return _service != NULL;
00105 }
00106 
00107 /** Returns true if the Tor service is running. */
00108 bool
00109 TorService::isRunning()
00110 {
00111 #if defined(Q_OS_WIN32)
00112   return (status() == SERVICE_RUNNING);
00113 #else
00114   return false;
00115 #endif
00116 }
00117 
00118 /** Starts Tor service. */
00119 void
00120 TorService::start()
00121 {
00122   if (!isSupported()) {
00123     emit startFailed(tr("Services not supported on this platform."));
00124     return;
00125   }
00126 
00127   if (!isInstalled()) {
00128     if (!install()) {
00129       emit startFailed(tr("Unable to install the Tor service."));
00130       return;
00131     }
00132   }
00133 #if defined(Q_OS_WIN32)
00134   /* Make sure we're initialized */
00135   initialize();
00136 
00137   /* Starting a service can take up to 30 seconds! */
00138   if (!isRunning()) StartService(_service, 0, NULL); 
00139   
00140   int tries = 0;
00141   while (true) {
00142     if (isRunning()) break;
00143     tries++;
00144     Sleep(1000);
00145     if (tries > 5) break;
00146   }
00147 
00148   if (isRunning()) {
00149     emit started();
00150 
00151   } else {
00152     emit startFailed(tr("Unable to start Tor service."));
00153   }
00154 #endif
00155 }
00156 
00157 /** Stops Tor service. */
00158 void
00159 TorService::stop()
00160 {
00161 #if defined(Q_OS_WIN32)
00162   if (isRunning()) {
00163     SERVICE_STATUS stat;
00164     stat.dwCurrentState = SERVICE_RUNNING;
00165     ControlService(_service, SERVICE_CONTROL_STOP, &stat);
00166 
00167     int tries = 0;
00168     while (true) {
00169       if (status() ==  SERVICE_STOPPED) break;
00170       tries++;
00171       Sleep(1000);
00172       if (tries > 5) break;
00173     }
00174   }
00175 
00176   if (!isRunning()) emit finished();
00177 #endif
00178 }
00179 
00180 /** Installs the Tor service. */
00181 bool
00182 TorService::install()
00183 {
00184 #if defined(Q_OS_WIN32)
00185   if (!isSupported()) return false;
00186 
00187   /* Make sure we're initialized */
00188   initialize();
00189 
00190   if (!isInstalled()) {
00191     QString command = _torPath + " --nt-service -f " + _torrc;
00192 
00193     _service = CreateServiceA(_manager, TOR_SERVICE_NAME, TOR_SERVICE_DISP,
00194                               TOR_SERVICE_ACCESS, SERVICE_WIN32_OWN_PROCESS,
00195                               SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
00196                               command.toAscii().data(), NULL, NULL, NULL, NULL, "");
00197 
00198     SERVICE_DESCRIPTION desc;
00199     desc.lpDescription = TOR_SERVICE_DESC;
00200     ChangeServiceConfig2(_service, SERVICE_CONFIG_DESCRIPTION, &desc);
00201   }
00202   return isInstalled();
00203 #else
00204   return false;
00205 #endif
00206 }
00207 
00208 /** Removes the Tor service. */
00209 bool
00210 TorService::remove()
00211 {
00212 #if defined(Q_OS_WIN32)
00213   if (!isSupported()) return false;
00214   if (isInstalled()) {
00215     /* Stop the service */
00216     stop();
00217 
00218     /* Delete the service */
00219     if (!DeleteService(_service)) return false;
00220     
00221     /* Release references to manager and service */
00222     close();
00223   }
00224 
00225   return !isInstalled();
00226 #else
00227   return false;
00228 #endif
00229 }
00230 
00231 
00232 /** Gets the status of the Tor service. */
00233 DWORD
00234 TorService::status()
00235 {
00236 #if defined(Q_OS_WIN32)
00237   if (!(isSupported() && _manager && _service)) return DWORD(-1);
00238 
00239   SERVICE_STATUS s;
00240   DWORD stat = SERVICE_ERROR;
00241 
00242   if (QueryServiceStatus(_service, &s)) {
00243     stat = s.dwCurrentState;
00244   } 
00245   return stat;
00246 #else
00247   return 0;
00248 #endif
00249 }
00250 

Generated on Mon Oct 23 20:08:16 2006 for Vidalia by  doxygen 1.5.0