Simplify locking semantics some more to address a deadlock.

This commit is contained in:
Adam Ierymenko 2014-10-21 10:42:04 -07:00
parent 7c0f5e97e1
commit 0e47f13f14
4 changed files with 161 additions and 204 deletions

View file

@ -37,14 +37,14 @@
#include "Constants.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "Buffer.hpp"
#define ZT_PATH_SERIALIZATION_VERSION 3
namespace ZeroTier {
/**
* WAN address and protocol for reaching a peer
*
* This structure is volatile and memcpy-able, and depends on
* InetAddress being similarly safe.
*/
class Path
{
@ -67,7 +67,6 @@ public:
Path(const Path &p)
{
// InetAddress is memcpy'able
memcpy(this,&p,sizeof(Path));
}
@ -79,6 +78,16 @@ public:
_type(t),
_fixed(fixed) {}
inline void init(const InetAddress &addr,Type t,bool fixed = false)
{
_lastSend = 0;
_lastReceived = 0;
_lastPing = 0;
_addr = addr;
_type = t;
_fixed = fixed;
}
inline Path &operator=(const Path &p)
{
if (this != &p)
@ -150,59 +159,6 @@ public:
inline bool operator<=(const Path &p) const throw() { return !(p < *this); }
inline bool operator>=(const Path &p) const throw() { return !(*this < p); }
template<unsigned int C>
inline void serialize(Buffer<C> &b) const
{
b.append((unsigned char)ZT_PATH_SERIALIZATION_VERSION);
b.append(_lastSend);
b.append(_lastReceived);
b.append(_lastPing);
b.append((unsigned char)_addr.type());
switch(_addr.type()) {
case InetAddress::TYPE_NULL:
break;
case InetAddress::TYPE_IPV4:
b.append(_addr.rawIpData(),4);
b.append((uint16_t)_addr.port());
break;
case InetAddress::TYPE_IPV6:
b.append(_addr.rawIpData(),16);
b.append((uint16_t)_addr.port());
break;
}
b.append((unsigned char)_type);
b.append(_fixed ? (unsigned char)1 : (unsigned char)0);
}
template<unsigned int C>
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{
unsigned int p = startAt;
if (b[p++] != ZT_PATH_SERIALIZATION_VERSION)
throw std::invalid_argument("Path: deserialize(): version mismatch");
_lastSend = b.template at<uint64_t>(p); p += sizeof(uint64_t);
_lastReceived = b.template at<uint64_t>(p); p += sizeof(uint64_t);
_lastPing = b.template at<uint64_t>(p); p += sizeof(uint64_t);
switch((InetAddress::AddressType)b[p++]) {
case InetAddress::TYPE_IPV4:
_addr.set(b.field(p,4),4,b.template at<uint16_t>(p + 4));
p += 4 + sizeof(uint16_t);
break;
case InetAddress::TYPE_IPV6:
_addr.set(b.field(p,16),16,b.template at<uint16_t>(p + 16));
p += 16 + sizeof(uint16_t);
break;
default:
_addr.zero();
break;
}
_type = (Type)b[p++];
_fixed = (b[p++] != 0);
return (p - startAt);
}
private:
volatile uint64_t _lastSend;
volatile uint64_t _lastReceived;