0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 12:12:15 +02:00
openvpn3/openvpn/apple/macsleep.hpp
2014-07-20 21:22:06 -06:00

129 lines
3.5 KiB
C++

// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2013-2014 OpenVPN Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_APPLE_MACSLEEP_H
#define OPENVPN_APPLE_MACSLEEP_H
#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>
#include <boost/noncopyable.hpp>
#include <openvpn/common/types.hpp>
namespace openvpn {
class MacSleep : boost::noncopyable
{
public:
MacSleep()
: root_port(0),
notifyPortRef(NULL),
notifierObject(0)
{
}
virtual ~MacSleep()
{
mac_sleep_stop();
}
bool mac_sleep_start()
{
if (!root_port)
{
root_port = IORegisterForSystemPower(this, &notifyPortRef, callback_static, &notifierObject);
if (!root_port)
return false;
CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes);
}
return true;
}
void mac_sleep_stop()
{
if (root_port)
{
// remove the sleep notification port from the application runloop
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
IONotificationPortGetRunLoopSource(notifyPortRef),
kCFRunLoopCommonModes);
// deregister for system sleep notifications
IODeregisterForSystemPower(&notifierObject);
// IORegisterForSystemPower implicitly opens the Root Power Domain IOService
// so we close it here
IOServiceClose(root_port);
// destroy the notification port allocated by IORegisterForSystemPower
IONotificationPortDestroy(notifyPortRef);
// reset object members
root_port = 0;
notifyPortRef = NULL;
notifierObject = 0;
}
}
virtual void notify_sleep() = 0;
virtual void notify_wakeup() = 0;
private:
static void callback_static(void* arg, io_service_t service, natural_t messageType, void *messageArgument)
{
MacSleep* self = (MacSleep*)arg;
self->callback(service, messageType, messageArgument);
}
void callback(io_service_t service, natural_t messageType, void *messageArgument)
{
switch (messageType)
{
case kIOMessageCanSystemSleep:
IOAllowPowerChange(root_port, (long)messageArgument);
break;
case kIOMessageSystemWillSleep:
notify_sleep();
IOAllowPowerChange(root_port, (long)messageArgument);
break;
case kIOMessageSystemHasPoweredOn:
notify_wakeup();
break;
}
}
// a reference to the Root Power Domain IOService
io_connect_t root_port;
// notification port allocated by IORegisterForSystemPower
IONotificationPortRef notifyPortRef;
// notifier object, used to deregister later
io_object_t notifierObject;
};
}
#endif