12 changed files with 464 additions and 74 deletions
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere |
||||
* Copyright (C) 2011-2015 ZeroTier, Inc. |
||||
* |
||||
* 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, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#ifndef ZT_BINARYSEMAPHORE_HPP |
||||
#define ZT_BINARYSEMAPHORE_HPP |
||||
|
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "Constants.hpp" |
||||
#include "NonCopyable.hpp" |
||||
|
||||
#ifdef __WINDOWS__ |
||||
|
||||
#include <Windows.h> |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
class BinarySemaphore : NonCopyable |
||||
{ |
||||
public: |
||||
BinarySemaphore() throw() { _sem = CreateSemaphore(NULL,0,1,NULL); } |
||||
~BinarySemaphore() { CloseHandle(_sem); } |
||||
inline void wait() { WaitForSingleObject(_sem,INFINITE); } |
||||
inline void post() { ReleaseSemaphore(_sem,1,NULL); } |
||||
private: |
||||
HANDLE _sem; |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#else // !__WINDOWS__
|
||||
|
||||
#include <pthread.h> |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
class BinarySemaphore : NonCopyable |
||||
{ |
||||
public: |
||||
BinarySemaphore() |
||||
{ |
||||
pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0); |
||||
pthread_cond_init(&_cond,(const pthread_condattr_t *)0); |
||||
_f = false; |
||||
} |
||||
|
||||
~BinarySemaphore() |
||||
{ |
||||
pthread_cond_destroy(&_cond); |
||||
pthread_mutex_destroy(&_mh); |
||||
} |
||||
|
||||
inline void wait() |
||||
{ |
||||
pthread_mutex_lock(const_cast <pthread_mutex_t *>(&_mh)); |
||||
while (!_f) |
||||
pthread_cond_wait(const_cast <pthread_cond_t *>(&_cond),const_cast <pthread_mutex_t *>(&_mh)); |
||||
_f = false; |
||||
pthread_mutex_unlock(const_cast <pthread_mutex_t *>(&_mh)); |
||||
} |
||||
|
||||
inline void post() |
||||
{ |
||||
pthread_mutex_lock(const_cast <pthread_mutex_t *>(&_mh)); |
||||
_f = true; |
||||
pthread_mutex_unlock(const_cast <pthread_mutex_t *>(&_mh)); |
||||
pthread_cond_signal(const_cast <pthread_cond_t *>(&_cond)); |
||||
} |
||||
|
||||
private: |
||||
pthread_cond_t _cond; |
||||
pthread_mutex_t _mh; |
||||
volatile bool _f; |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // !__WINDOWS__
|
||||
|
||||
#endif |
||||
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere |
||||
* Copyright (C) 2011-2015 ZeroTier, Inc. |
||||
* |
||||
* 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, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#include "Constants.hpp" |
||||
#include "DeferredPackets.hpp" |
||||
#include "IncomingPacket.hpp" |
||||
#include "RuntimeEnvironment.hpp" |
||||
#include "Node.hpp" |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
DeferredPackets::DeferredPackets(const RuntimeEnvironment *renv) : |
||||
RR(renv), |
||||
_readPtr(0), |
||||
_writePtr(0), |
||||
_die(false) |
||||
{ |
||||
} |
||||
|
||||
DeferredPackets::~DeferredPackets() |
||||
{ |
||||
_q_m.lock(); |
||||
_die = true; |
||||
_q_m.unlock(); |
||||
_q_s.post(); |
||||
} |
||||
|
||||
bool DeferredPackets::enqueue(IncomingPacket *pkt) |
||||
{ |
||||
_q_m.lock(); |
||||
const unsigned long p = _writePtr % ZT_DEFFEREDPACKETS_MAX; |
||||
if (_q[p]) { |
||||
_q_m.unlock(); |
||||
return false; |
||||
} else { |
||||
_q[p].setToUnsafe(pkt); |
||||
++_writePtr; |
||||
_q_m.unlock(); |
||||
_q_s.post(); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
int DeferredPackets::process() |
||||
{ |
||||
SharedPtr<IncomingPacket> pkt; |
||||
|
||||
_q_m.lock(); |
||||
if (_die) { |
||||
_q_m.unlock(); |
||||
_q_s.post(); |
||||
return -1; |
||||
} |
||||
while (_readPtr == _writePtr) { |
||||
_q_m.unlock(); |
||||
_q_s.wait(); |
||||
_q_m.lock(); |
||||
if (_die) { |
||||
_q_m.unlock(); |
||||
_q_s.post(); |
||||
return -1; |
||||
} |
||||
} |
||||
pkt.swap(_q[_readPtr++ % ZT_DEFFEREDPACKETS_MAX]); |
||||
_q_m.unlock(); |
||||
|
||||
pkt->tryDecode(RR,true); |
||||
return 1; |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere |
||||
* Copyright (C) 2011-2015 ZeroTier, Inc. |
||||
* |
||||
* 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, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#ifndef ZT_DEFERREDPACKETS_HPP |
||||
#define ZT_DEFERREDPACKETS_HPP |
||||
|
||||
#include "Constants.hpp" |
||||
#include "SharedPtr.hpp" |
||||
#include "Mutex.hpp" |
||||
#include "DeferredPackets.hpp" |
||||
#include "BinarySemaphore.hpp" |
||||
|
||||
/**
|
||||
* Maximum number of deferred packets |
||||
*/ |
||||
#define ZT_DEFFEREDPACKETS_MAX 1024 |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
class IncomingPacket; |
||||
class RuntimeEnvironment; |
||||
|
||||
/**
|
||||
* Deferred packets |
||||
* |
||||
* IncomingPacket can defer its decoding this way by enqueueing itself here. |
||||
* When this is done, deferredDecode() is called later. This is done for |
||||
* operations that may be expensive to allow them to potentially be handled |
||||
* in the background or rate limited to maintain quality of service for more |
||||
* routine operations. |
||||
*/ |
||||
class DeferredPackets |
||||
{ |
||||
public: |
||||
DeferredPackets(const RuntimeEnvironment *renv); |
||||
~DeferredPackets(); |
||||
|
||||
/**
|
||||
* Enqueue a packet |
||||
* |
||||
* Since packets enqueue themselves, they call it with 'this' and we wrap |
||||
* them in a SharedPtr<>. This is safe as SharedPtr<> is introspective and |
||||
* supports this. This should not be called from any other code outside |
||||
* IncomingPacket. |
||||
* |
||||
* @param pkt Packet to process later (possibly in the background) |
||||
* @return False if queue is full |
||||
*/ |
||||
bool enqueue(IncomingPacket *pkt); |
||||
|
||||
/**
|
||||
* Wait for and then process a deferred packet |
||||
* |
||||
* If we are shutting down (in destructor), this returns -1 and should |
||||
* not be called again. Otherwise it returns the number of packets |
||||
* processed. |
||||
* |
||||
* @return Number processed or -1 if shutting down |
||||
*/ |
||||
int process(); |
||||
|
||||
private: |
||||
SharedPtr<IncomingPacket> _q[ZT_DEFFEREDPACKETS_MAX]; |
||||
const RuntimeEnvironment *const RR; |
||||
unsigned long _readPtr; |
||||
unsigned long _writePtr; |
||||
bool _die; |
||||
Mutex _q_m; |
||||
BinarySemaphore _q_s; |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif |
||||
Loading…
Reference in new issue