version 3.0
This commit is contained in:
commit
d837490606
209 changed files with 19662 additions and 0 deletions
5
common/Makefile
Normal file
5
common/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
SUBDIR+=thread
|
||||
SUBDIR+=timer
|
||||
SUBDIR+=uuid
|
||||
|
||||
include ../common/subdir.mk
|
167
common/buffer.cc
Normal file
167
common/buffer.cc
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/uio.h>
|
||||
#include <limits.h>
|
||||
#include <iostream>
|
||||
#include <common/limits.h>
|
||||
#include <common/buffer.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: buffer.cc //
|
||||
// Description: generic buffer composed by reference counted segments //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if USING_SEGMENT_CACHE
|
||||
std::deque<BufferSegment *> BufferSegment::segment_cache;
|
||||
pthread_mutex_t BufferSegment::segment_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
size_t
|
||||
Buffer::fill_iovec(struct iovec *iov, size_t niov) const
|
||||
{
|
||||
if (niov == 0)
|
||||
return (0);
|
||||
|
||||
if (niov > IOV_MAX)
|
||||
niov = IOV_MAX;
|
||||
|
||||
segment_list_t::const_iterator iter = data_.begin();
|
||||
size_t iovcnt = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < niov; i++) {
|
||||
if (iter == data_.end())
|
||||
break;
|
||||
const BufferSegment *seg = *iter;
|
||||
iov[i].iov_base = (void *)(uintptr_t)seg->data();
|
||||
iov[i].iov_len = seg->length();
|
||||
iovcnt++;
|
||||
iter++;
|
||||
}
|
||||
return (iovcnt);
|
||||
}
|
||||
|
||||
std::string
|
||||
Buffer::hexdump(unsigned start) const
|
||||
{
|
||||
static const char hexchars[] = "0123456789abcdef";
|
||||
|
||||
std::string hex;
|
||||
std::string vis;
|
||||
|
||||
segment_list_t::const_iterator iter = data_.begin();
|
||||
while (iter != data_.end()) {
|
||||
const BufferSegment *seg = *iter++;
|
||||
const uint8_t *p;
|
||||
|
||||
for (p = seg->data(); p < seg->end(); p++) {
|
||||
hex += hexchars[(*p & 0xf0) >> 4];
|
||||
hex += hexchars[*p & 0xf];
|
||||
|
||||
if (isprint(*p))
|
||||
vis += (char)*p;
|
||||
else
|
||||
vis += '.';
|
||||
}
|
||||
}
|
||||
|
||||
std::string dump;
|
||||
unsigned cur = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned offset = start + cur;
|
||||
std::string str;
|
||||
unsigned n;
|
||||
|
||||
while (offset != 0) {
|
||||
str = hexchars[offset & 0xf] + str;
|
||||
offset >>= 4;
|
||||
}
|
||||
|
||||
while (str.length() < 8)
|
||||
str = '0' + str;
|
||||
|
||||
dump += str;
|
||||
|
||||
if (cur == length_) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print hex.
|
||||
*/
|
||||
for (n = 0; n < 16; n++) {
|
||||
if (n % 8 == 0)
|
||||
dump += " ";
|
||||
dump += " ";
|
||||
if (cur + n < length_) {
|
||||
dump += hex[n * 2];
|
||||
dump += hex[n * 2 + 1];
|
||||
} else {
|
||||
hex = "";
|
||||
dump += " ";
|
||||
}
|
||||
}
|
||||
if (hex != "")
|
||||
hex = hex.substr(32);
|
||||
|
||||
dump += " |";
|
||||
for (n = 0; cur < length_ && n < 16; n++) {
|
||||
dump += vis[n];
|
||||
cur++;
|
||||
}
|
||||
if (cur < length_)
|
||||
vis = vis.substr(16);
|
||||
dump += "|";
|
||||
|
||||
if (cur == length_ && cur % 16 == 0)
|
||||
break;
|
||||
|
||||
dump += "\n";
|
||||
}
|
||||
|
||||
|
||||
return (dump);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<< (std::ostream& os, const Buffer *buf)
|
||||
{
|
||||
std::string str;
|
||||
buf->extract(str);
|
||||
return (os << str);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<< (std::ostream& os, const Buffer& buf)
|
||||
{
|
||||
return (os << &buf);
|
||||
}
|
1755
common/buffer.h
Normal file
1755
common/buffer.h
Normal file
File diff suppressed because it is too large
Load diff
42
common/common.h
Normal file
42
common/common.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_COMMON_H
|
||||
#define COMMON_COMMON_H
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/log.h>
|
||||
#include <common/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <string> /* Already here for log.h, but be explicit. */
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||
#endif
|
||||
|
||||
#endif /* !COMMON_COMMON_H */
|
69
common/debug.h
Normal file
69
common/debug.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_DEBUG_H
|
||||
#define COMMON_DEBUG_H
|
||||
|
||||
#if defined(NDEBUG)
|
||||
#define ASSERT(log, p) \
|
||||
do { \
|
||||
if (false) \
|
||||
(void)(p); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ASSERT(log, p) \
|
||||
do { \
|
||||
if (!(p)) { \
|
||||
HALT((log)) << "Assertion (" << #p << \
|
||||
") failed at " \
|
||||
<< __FILE__ << ':' << __LINE__ \
|
||||
<< " in function " \
|
||||
<< __PRETTY_FUNCTION__ \
|
||||
<< '.'; \
|
||||
for (;;) \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Newer GCCs are horribly broken and seem to have become unable to detect
|
||||
* that HALT(x) << bar will prevent a function ever returning. We add the
|
||||
* infinite loop here to help.
|
||||
*/
|
||||
#if defined(NDEBUG)
|
||||
#define NOTREACHED(log) \
|
||||
abort()
|
||||
#else
|
||||
#define NOTREACHED(log) \
|
||||
do { \
|
||||
ASSERT(log, "Should not be reached." == NULL); \
|
||||
for (;;) \
|
||||
abort(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* !COMMON_DEBUG_H */
|
141
common/endian.h
Normal file
141
common/endian.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_ENDIAN_H
|
||||
#define COMMON_ENDIAN_H
|
||||
|
||||
#if !defined(BYTE_ORDER) && !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BIG_ENDIAN 4321
|
||||
#if defined(_LITTLE_ENDIAN)
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#elif defined(_BIG_ENDIAN)
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#else
|
||||
#error "Can't determine host byte order."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#error "BYTE_ORDER must be defined."
|
||||
#else
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#else
|
||||
#error "Unexpected BYTE_ORDER value."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Endian {
|
||||
static uint16_t swap(const uint16_t& in)
|
||||
{
|
||||
return (((in & 0xff00u) >> 0x08) | ((in & 0x00ffu) << 0x08));
|
||||
}
|
||||
|
||||
static uint32_t swap(const uint32_t& in)
|
||||
{
|
||||
return (((in & 0xff000000u) >> 0x18) |
|
||||
((in & 0x00ff0000u) >> 0x08) |
|
||||
((in & 0x0000ff00u) << 0x08) |
|
||||
((in & 0x000000ffu) << 0x18));
|
||||
}
|
||||
|
||||
static uint64_t swap(const uint64_t& in)
|
||||
{
|
||||
return (((in & 0xff00000000000000ull) >> 0x38) |
|
||||
((in & 0x00ff000000000000ull) >> 0x28) |
|
||||
((in & 0x0000ff0000000000ull) >> 0x18) |
|
||||
((in & 0x000000ff00000000ull) >> 0x08) |
|
||||
((in & 0x00000000ff000000ull) << 0x08) |
|
||||
((in & 0x0000000000ff0000ull) << 0x18) |
|
||||
((in & 0x000000000000ff00ull) << 0x28) |
|
||||
((in & 0x00000000000000ffull) << 0x38));
|
||||
}
|
||||
};
|
||||
|
||||
struct SwapEndian {
|
||||
template<typename T>
|
||||
static T encode(const T& in)
|
||||
{
|
||||
return (Endian::swap(in));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T decode(const T& in)
|
||||
{
|
||||
return (Endian::swap(in));
|
||||
}
|
||||
|
||||
template<class C, typename T>
|
||||
static void append(C *out, const T& in)
|
||||
{
|
||||
T swapped = encode(in);
|
||||
out->append(&swapped);
|
||||
}
|
||||
|
||||
template<class C, typename T>
|
||||
static void extract(T *out, const C *in)
|
||||
{
|
||||
T wire;
|
||||
in->extract(&wire);
|
||||
*out = decode(wire);
|
||||
}
|
||||
};
|
||||
|
||||
struct HostEndian {
|
||||
template<typename T>
|
||||
static T encode(const T& in)
|
||||
{
|
||||
return (in);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T decode(const T& in)
|
||||
{
|
||||
return (in);
|
||||
}
|
||||
|
||||
template<class C, typename T>
|
||||
static void append(C *out, const T& in)
|
||||
{
|
||||
out->append(&in);
|
||||
}
|
||||
|
||||
template<class C, typename T>
|
||||
static void extract(T *out, const C *in)
|
||||
{
|
||||
in->extract(out);
|
||||
}
|
||||
};
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
typedef HostEndian LittleEndian;
|
||||
typedef SwapEndian BigEndian;
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
typedef SwapEndian LittleEndian;
|
||||
typedef HostEndian BigEndian;
|
||||
#endif
|
||||
|
||||
#endif /* !COMMON_ENDIAN_H */
|
171
common/factory.h
Normal file
171
common/factory.h
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_FACTORY_H
|
||||
#define COMMON_FACTORY_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
template<class C>
|
||||
class Factory {
|
||||
public:
|
||||
Factory(void)
|
||||
{ }
|
||||
|
||||
virtual ~Factory()
|
||||
{ }
|
||||
|
||||
virtual C *create(void) const = 0;
|
||||
};
|
||||
|
||||
template<class B, class C>
|
||||
class ConstructorFactory : public Factory<B> {
|
||||
public:
|
||||
ConstructorFactory(void)
|
||||
{ }
|
||||
|
||||
~ConstructorFactory()
|
||||
{ }
|
||||
|
||||
B *create(void) const
|
||||
{
|
||||
return (new C());
|
||||
}
|
||||
};
|
||||
|
||||
template<class B, class C, typename A>
|
||||
class ConstructorArgFactory : public Factory<B> {
|
||||
A a_;
|
||||
public:
|
||||
ConstructorArgFactory(A a)
|
||||
: a_(a)
|
||||
{ }
|
||||
|
||||
~ConstructorArgFactory()
|
||||
{ }
|
||||
|
||||
B *create(void) const
|
||||
{
|
||||
return (new C(a_));
|
||||
}
|
||||
};
|
||||
|
||||
template<class B, class C>
|
||||
class SubclassFactory : public Factory<B> {
|
||||
Factory<C> *factory_;
|
||||
public:
|
||||
SubclassFactory(Factory<C> *factory)
|
||||
: factory_(factory)
|
||||
{ }
|
||||
|
||||
~SubclassFactory()
|
||||
{
|
||||
delete factory_;
|
||||
factory_ = NULL;
|
||||
}
|
||||
|
||||
B *create(void) const
|
||||
{
|
||||
return (factory_->create());
|
||||
}
|
||||
};
|
||||
|
||||
template<class B, class C = B>
|
||||
struct factory {
|
||||
Factory<B> *operator() (void) const
|
||||
{
|
||||
return (new ConstructorFactory<B, C>);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Factory<B> *operator() (T arg) const
|
||||
{
|
||||
return (new ConstructorArgFactory<B, C, T>(arg));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename K, typename C>
|
||||
class FactoryMap {
|
||||
typedef std::map<K, Factory<C> *> map_type;
|
||||
|
||||
map_type map_;
|
||||
public:
|
||||
FactoryMap(void)
|
||||
: map_()
|
||||
{ }
|
||||
|
||||
~FactoryMap()
|
||||
{
|
||||
typename map_type::iterator it;
|
||||
|
||||
while ((it = map_.begin()) != map_.end()) {
|
||||
delete it->second;
|
||||
map_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
C *create(const K& key) const
|
||||
{
|
||||
typename map_type::const_iterator it;
|
||||
|
||||
it = map_.find(key);
|
||||
if (it == map_.end())
|
||||
return (NULL);
|
||||
return (it->second->create());
|
||||
}
|
||||
|
||||
void enter(const K& key, Factory<C> *factory)
|
||||
{
|
||||
typename map_type::iterator it;
|
||||
|
||||
it = map_.find(key);
|
||||
if (it != map_.end()) {
|
||||
delete it->second;
|
||||
map_.erase(it);
|
||||
}
|
||||
|
||||
map_[key] = factory;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
void enter(const K& key, Factory<S> *factory)
|
||||
{
|
||||
enter(key, new SubclassFactory<C, S>(factory));
|
||||
}
|
||||
|
||||
std::set<K> keys(void) const
|
||||
{
|
||||
typename map_type::const_iterator it;
|
||||
std::set<K> key_set;
|
||||
|
||||
for (it = map_.begin(); it != map_.end(); ++it)
|
||||
key_set.insert(it->first);
|
||||
|
||||
return (key_set);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !COMMON_FACTORY_H */
|
82
common/filter.h
Normal file
82
common/filter.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: filter.h //
|
||||
// Description: base classes for chained data processors //
|
||||
// Project: WANProxy XTech //
|
||||
// Author: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef COMMON_FILTER_H
|
||||
#define COMMON_FILTER_H
|
||||
|
||||
#include <list>
|
||||
#include <common/log.h>
|
||||
#include <common/buffer.h>
|
||||
|
||||
class Filter
|
||||
{
|
||||
private:
|
||||
Filter* recipient_;
|
||||
|
||||
public:
|
||||
Filter () { recipient_ = 0; }
|
||||
virtual ~Filter () { }
|
||||
|
||||
void chain (Filter* nxt) { recipient_ = nxt; }
|
||||
virtual bool consume (Buffer& buf) { return produce (buf); }
|
||||
virtual bool produce (Buffer& buf) { return (recipient_ && recipient_->consume (buf)); }
|
||||
virtual void flush (int flg) { if (recipient_) recipient_->flush (flg); }
|
||||
};
|
||||
|
||||
class CountFilter : public Filter
|
||||
{
|
||||
private:
|
||||
intmax_t& counter_;
|
||||
|
||||
public:
|
||||
CountFilter (intmax_t& p) : counter_(p) { }
|
||||
virtual bool consume (Buffer& buf) { counter_ += buf.length (); return produce (buf); }
|
||||
};
|
||||
|
||||
class BufferedFilter : public Filter
|
||||
{
|
||||
protected:
|
||||
LogHandle log_;
|
||||
Buffer pending_;
|
||||
bool flushing_;
|
||||
int flush_flags_;
|
||||
|
||||
public:
|
||||
BufferedFilter (const LogHandle& log) : log_ (log) { flushing_ = 0; flush_flags_ = 0; }
|
||||
};
|
||||
|
||||
class LogisticFilter : public BufferedFilter
|
||||
{
|
||||
protected:
|
||||
Filter* upstream_;
|
||||
|
||||
public:
|
||||
LogisticFilter (const LogHandle& log) : BufferedFilter (log) { upstream_ = 0; }
|
||||
void set_upstream (Filter* f) { upstream_ = f; }
|
||||
};
|
||||
|
||||
class FilterChain : public Filter
|
||||
{
|
||||
private:
|
||||
std::list<Filter*> nodes_;
|
||||
Filter* holder_;
|
||||
|
||||
public:
|
||||
FilterChain (Filter* f) { holder_ = f; }
|
||||
virtual ~FilterChain () { while (! nodes_.empty ()) { delete nodes_.front (); nodes_.pop_front (); }}
|
||||
|
||||
void prepend (Filter* f) { Filter* act = (nodes_.empty () ? holder_ : nodes_.front ());
|
||||
if (f && act) nodes_.push_front (f), chain (f), f->chain (act); }
|
||||
void append (Filter* f) { Filter* act = (nodes_.empty () ? this : nodes_.front ());
|
||||
if (f && act) nodes_.push_front (f), act->chain (f), f->chain (holder_); }
|
||||
virtual void flush (int flg) { if (nodes_.empty ()) chain (holder_); Filter::flush (flg); }
|
||||
};
|
||||
|
||||
#endif /* !COMMON_FILTER_H */
|
6
common/lib.mk
Normal file
6
common/lib.mk
Normal file
|
@ -0,0 +1,6 @@
|
|||
VPATH+= ${TOPDIR}/common
|
||||
|
||||
SRCS+= buffer.cc
|
||||
SRCS+= log.cc
|
||||
|
||||
CXXFLAGS+=-include common/common.h
|
33
common/limits.h
Normal file
33
common/limits.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_LIMITS_H
|
||||
#define COMMON_LIMITS_H
|
||||
|
||||
#if defined(__OPENNT)
|
||||
#define IOV_MAX 1024
|
||||
#endif
|
||||
|
||||
#endif /* !COMMON_LIMITS_H */
|
188
common/log.cc
Normal file
188
common/log.cc
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef USE_SYSLOG
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
||||
struct LogMask {
|
||||
regex_t regex_;
|
||||
enum Log::Priority priority_;
|
||||
};
|
||||
|
||||
static std::list<LogMask> log_masks;
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
static int syslog_priority(const Log::Priority&);
|
||||
#endif
|
||||
static std::ostream& operator<< (std::ostream&, const Log::Priority&);
|
||||
static std::ostream& operator<< (std::ostream&, const struct timeval&);
|
||||
|
||||
void
|
||||
Log::log(const Priority& priority, const LogHandle& handle,
|
||||
const std::string& message)
|
||||
{
|
||||
std::list<LogMask>::const_iterator it;
|
||||
std::string handle_string = (std::string)handle;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Skip this all if we're in a HALT or NOTREACHED, since we can
|
||||
* generate those here. Critical logs cannot ever be masked, right?
|
||||
*/
|
||||
for (it = log_masks.begin(); it != log_masks.end(); ++it) {
|
||||
const LogMask& mask = *it;
|
||||
int rv;
|
||||
|
||||
rv = regexec(&mask.regex_, handle_string.c_str(), 0, NULL, 0);
|
||||
switch (rv) {
|
||||
case 0:
|
||||
if (priority <= mask.priority_)
|
||||
goto done;
|
||||
return;
|
||||
case REG_NOMATCH:
|
||||
continue;
|
||||
default:
|
||||
HALT("/log") << "Could not match regex: " << rv;
|
||||
return;
|
||||
}
|
||||
NOTREACHED("/log");
|
||||
}
|
||||
|
||||
done:
|
||||
#ifdef USE_SYSLOG
|
||||
std::string syslog_message;
|
||||
|
||||
syslog_message += "[";
|
||||
syslog_message += (std::string)handle;
|
||||
syslog_message += "] ";
|
||||
syslog_message += message;
|
||||
|
||||
syslog(syslog_priority(priority), "%s", syslog_message.c_str());
|
||||
#endif
|
||||
|
||||
struct timeval now;
|
||||
int rv;
|
||||
|
||||
rv = gettimeofday(&now, NULL);
|
||||
if (rv == -1)
|
||||
memset(&now, 0, sizeof now);
|
||||
|
||||
std::cerr << now << " [" << handle_string << "] " <<
|
||||
priority << ": " <<
|
||||
message <<
|
||||
std::endl;
|
||||
}
|
||||
|
||||
bool
|
||||
Log::mask(const std::string& handle_regex, const Log::Priority& priority)
|
||||
{
|
||||
LogMask mask;
|
||||
|
||||
if (::regcomp(&mask.regex_, handle_regex.c_str(),
|
||||
REG_NOSUB | REG_EXTENDED) != 0) {
|
||||
return (false);
|
||||
}
|
||||
mask.priority_ = priority;
|
||||
|
||||
log_masks.push_back(mask);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
static int
|
||||
syslog_priority(const Log::Priority& priority)
|
||||
{
|
||||
switch (priority) {
|
||||
case Log::Emergency:
|
||||
return (LOG_EMERG);
|
||||
case Log::Alert:
|
||||
return (LOG_ALERT);
|
||||
case Log::Critical:
|
||||
return (LOG_CRIT);
|
||||
case Log::Error:
|
||||
return (LOG_ERR);
|
||||
case Log::Warning:
|
||||
return (LOG_WARNING);
|
||||
case Log::Notice:
|
||||
return (LOG_NOTICE);
|
||||
case Log::Info:
|
||||
return (LOG_INFO);
|
||||
case Log::Debug:
|
||||
case Log::Trace:
|
||||
return (LOG_DEBUG);
|
||||
default:
|
||||
HALT("/log") << "Unhandled log priority!";
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::ostream&
|
||||
operator<< (std::ostream& os, const Log::Priority& priority)
|
||||
{
|
||||
switch (priority) {
|
||||
case Log::Emergency:
|
||||
return (os << "EMERG");
|
||||
case Log::Alert:
|
||||
return (os << "ALERT");
|
||||
case Log::Critical:
|
||||
return (os << "CRIT");
|
||||
case Log::Error:
|
||||
return (os << "ERR");
|
||||
case Log::Warning:
|
||||
return (os << "WARNING");
|
||||
case Log::Notice:
|
||||
return (os << "NOTICE");
|
||||
case Log::Info:
|
||||
return (os << "INFO");
|
||||
case Log::Debug:
|
||||
return (os << "DEBUG");
|
||||
case Log::Trace:
|
||||
return (os << "TRACE");
|
||||
default:
|
||||
HALT("/log") << "Unhandled log priority!";
|
||||
return (os);
|
||||
}
|
||||
}
|
||||
|
||||
static std::ostream&
|
||||
operator<< (std::ostream& os, const struct timeval& tv)
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
snprintf(buf, sizeof buf, "%u.%06u", (unsigned)tv.tv_sec,
|
||||
(unsigned)tv.tv_usec);
|
||||
return (os << buf);
|
||||
}
|
217
common/log.h
Normal file
217
common/log.h
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_LOG_H
|
||||
#define COMMON_LOG_H
|
||||
|
||||
#include <stdlib.h> /* For abort(3). */
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
class LogNull {
|
||||
public:
|
||||
LogNull(void)
|
||||
{ }
|
||||
|
||||
~LogNull()
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
const LogNull& operator<< (T) const
|
||||
{
|
||||
return (*this);
|
||||
}
|
||||
|
||||
const LogNull& operator<< (std::ostream& (*)(std::ostream&)) const
|
||||
{
|
||||
return (*this);
|
||||
}
|
||||
};
|
||||
|
||||
class LogHandle {
|
||||
std::string string_;
|
||||
public:
|
||||
LogHandle(const char *s)
|
||||
: string_(s)
|
||||
{ }
|
||||
|
||||
LogHandle(const std::string& s)
|
||||
: string_(s)
|
||||
{ }
|
||||
|
||||
~LogHandle()
|
||||
{ }
|
||||
|
||||
operator const std::string& (void) const
|
||||
{
|
||||
return (string_);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
LogHandle operator+ (T x) const
|
||||
{
|
||||
LogHandle appended = *this;
|
||||
appended.string_ += x;
|
||||
return (appended);
|
||||
}
|
||||
};
|
||||
|
||||
class Log {
|
||||
public:
|
||||
enum Priority {
|
||||
Emergency,
|
||||
Alert,
|
||||
Critical,
|
||||
Error,
|
||||
Warning,
|
||||
Notice,
|
||||
Info,
|
||||
Trace,
|
||||
Debug,
|
||||
};
|
||||
|
||||
class Halt {
|
||||
public:
|
||||
Halt(void)
|
||||
{ }
|
||||
|
||||
~Halt()
|
||||
{ }
|
||||
};
|
||||
|
||||
private:
|
||||
LogHandle handle_;
|
||||
Priority priority_;
|
||||
std::ostringstream str_;
|
||||
bool pending_;
|
||||
bool halted_;
|
||||
public:
|
||||
Log(const LogHandle& handle, const Priority& priority, const std::string function)
|
||||
: handle_(handle),
|
||||
priority_(priority),
|
||||
str_(),
|
||||
pending_(false),
|
||||
halted_(false)
|
||||
{
|
||||
/*
|
||||
* Print the function name for non-routine messages.
|
||||
*/
|
||||
switch (priority_) {
|
||||
case Emergency:
|
||||
case Alert:
|
||||
case Critical:
|
||||
case Error:
|
||||
#if !defined(NDEBUG)
|
||||
case Debug:
|
||||
#endif
|
||||
str_ << function << ": ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~Log()
|
||||
{
|
||||
flush();
|
||||
if (halted_) {
|
||||
abort(); /* XXX */
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream&
|
||||
operator << (T x)
|
||||
{
|
||||
pending_ = true;
|
||||
return (str_ << x);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator << (const Halt&)
|
||||
{
|
||||
pending_ = true;
|
||||
halted_ = true;
|
||||
return (str_ << "Halting: ");
|
||||
}
|
||||
|
||||
void
|
||||
flush(void)
|
||||
{
|
||||
if (!pending_)
|
||||
return;
|
||||
Log::log(priority_, handle_, str_.str());
|
||||
}
|
||||
|
||||
static void log(const Priority&, const LogHandle&, const std::string&);
|
||||
static bool mask(const std::string&, const Priority&);
|
||||
};
|
||||
|
||||
/* A panic condition. */
|
||||
#define EMERGENCY(log) Log(log, Log::Emergency, __PRETTY_FUNCTION__)
|
||||
/* A condition that should be corrected immediately. */
|
||||
#define ALERT(log) Log(log, Log::Alert, __PRETTY_FUNCTION__)
|
||||
/* Critical condition. */
|
||||
#define CRITICAL(log) Log(log, Log::Critical, __PRETTY_FUNCTION__)
|
||||
/* Errors. */
|
||||
#define ERROR(log) Log(log, Log::Error, __PRETTY_FUNCTION__)
|
||||
/* Warnings. */
|
||||
#define WARNING(log) Log(log, Log::Warning, __PRETTY_FUNCTION__)
|
||||
/* Conditions that are not error conditions, but may need handled. */
|
||||
#define NOTICE(log) Log(log, Log::Notice, __PRETTY_FUNCTION__)
|
||||
/* Informational. */
|
||||
#define INFO(log) Log(log, Log::Info, __PRETTY_FUNCTION__)
|
||||
/* Debugging information. */
|
||||
#if !defined(NDEBUG)
|
||||
#define DEBUG(log) Log(log, Log::Debug, __PRETTY_FUNCTION__)
|
||||
#else
|
||||
#define DEBUG(log) LogNull()
|
||||
#endif
|
||||
|
||||
/* A condition which cannot be continued from. */
|
||||
#define HALT(log) EMERGENCY(log) << Log::Halt()
|
||||
|
||||
class Trace {
|
||||
LogHandle log_;
|
||||
std::string function_;
|
||||
public:
|
||||
Trace(const LogHandle& log, const std::string& function)
|
||||
: log_(log),
|
||||
function_(function)
|
||||
{
|
||||
Log(log_, Log::Trace, __PRETTY_FUNCTION__) << "Entered " << function_;
|
||||
}
|
||||
|
||||
~Trace()
|
||||
{
|
||||
Log(log_, Log::Trace, __PRETTY_FUNCTION__) << "Exited " << function_;
|
||||
}
|
||||
};
|
||||
|
||||
/* Selective debug tracing. */
|
||||
#define TRACE(log) Trace trace_(log, __PRETTY_FUNCTION__)
|
||||
|
||||
#endif /* !COMMON_LOG_H */
|
110
common/program.mk
Normal file
110
common/program.mk
Normal file
|
@ -0,0 +1,110 @@
|
|||
ifndef TOPDIR
|
||||
$(error "TOPDIR must be defined")
|
||||
endif
|
||||
|
||||
ifdef NETWORK_TEST
|
||||
TEST=${NETWORK_TEST}
|
||||
endif
|
||||
|
||||
ifdef SKIP_NETWORK_TESTS
|
||||
SKIP_TESTS=${SKIP_NETWORK_TESTS}
|
||||
endif
|
||||
|
||||
ifdef TEST
|
||||
ifndef SKIP_TESTS
|
||||
PROGRAM=${TEST}
|
||||
SRCS+=${TEST}.cc
|
||||
|
||||
all: ${PROGRAM}
|
||||
|
||||
# Build and run regression tests.
|
||||
regress: ${PROGRAM}
|
||||
ifdef TEST_WRAPPER
|
||||
${TEST_WRAPPER} ${PWD}/${PROGRAM}
|
||||
else
|
||||
${PWD}/${PROGRAM}
|
||||
endif
|
||||
else
|
||||
# Build but don't run regression tests.
|
||||
regress: ${PROGRAM}
|
||||
endif
|
||||
else
|
||||
ifndef PROGRAM
|
||||
$(error "Must have a program to build.")
|
||||
endif
|
||||
|
||||
all: ${PROGRAM}
|
||||
|
||||
# Not a regression test, do nothing.
|
||||
regress:
|
||||
@true
|
||||
endif
|
||||
|
||||
.PHONY: regress
|
||||
|
||||
OSNAME:=$(shell uname -s)
|
||||
|
||||
CFLAGS+=-pipe
|
||||
CPPFLAGS+=-I${TOPDIR}
|
||||
ifdef NDEBUG
|
||||
CFLAGS+=-O2
|
||||
CPPFLAGS+=-DNDEBUG=1
|
||||
else
|
||||
CFLAGS+=-O0
|
||||
ifneq "${OSNAME}" "SunOS"
|
||||
CFLAGS+=-g
|
||||
endif
|
||||
endif
|
||||
|
||||
# OpenBSD needs no -Werror.
|
||||
ifeq "${OSNAME}" "OpenBSD"
|
||||
NO_WERROR=1
|
||||
endif
|
||||
|
||||
# Linux needs no -Werror because the epoll headers are terrible.
|
||||
# XXX Should just disable -Werror for the one file using epoll.
|
||||
ifeq "${OSNAME}" "Linux"
|
||||
NO_WERROR=1
|
||||
endif
|
||||
|
||||
#CFLAGS+=--std gnu++0x
|
||||
#CFLAGS+=-pedantic
|
||||
CFLAGS+=-W -Wall
|
||||
ifndef NO_WERROR
|
||||
CFLAGS+=-Werror
|
||||
endif
|
||||
CFLAGS+=-Wno-system-headers
|
||||
CFLAGS+=-Wno-unused-parameter
|
||||
CFLAGS+=-Wno-switch
|
||||
CFLAGS+=-Wno-uninitialized
|
||||
CFLAGS+=-Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wshadow -Wcast-align -Wchar-subscripts -Wreorder
|
||||
#CFLAGS+=-Winline
|
||||
CXXFLAGS+=-Wno-deprecated
|
||||
CXXFLAGS+=-Wnon-virtual-dtor
|
||||
|
||||
$(foreach _lib,${USE_LIBS},$(eval include ${TOPDIR}/$(strip ${_lib})/lib.mk))
|
||||
|
||||
define __library_conditionals
|
||||
ifdef CFLAGS_${1}
|
||||
CFLAGS+=${CFLAGS_${1}}
|
||||
endif
|
||||
ifdef SRCS_${1}
|
||||
SRCS+= ${SRCS_${1}}
|
||||
endif
|
||||
endef
|
||||
|
||||
$(foreach _lib,${USE_LIBS},$(eval $(call __library_conditionals,$(subst /,_,${_lib}))))
|
||||
|
||||
OBJS+= $(patsubst %.cc,bin/%.o,$(patsubst %.c,bin/%.o,${SRCS}))
|
||||
|
||||
${PROGRAM}: ${OBJS}
|
||||
${CXX} ${CXXFLAGS} ${CFLAGS} ${LDFLAGS} -o bin/$@ ${OBJS} ${LDADD}
|
||||
|
||||
bin/%.o: %.cc
|
||||
${CXX} ${CPPFLAGS} ${CXXFLAGS} ${CFLAGS} -c -o $@ $<
|
||||
|
||||
bin/%.o: %.c
|
||||
${CC} ${CPPFLAGS} ${CFLAGS} -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f ${PROGRAM} ${OBJS}
|
154
common/ref.h
Normal file
154
common/ref.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_REF_H
|
||||
#define COMMON_REF_H
|
||||
|
||||
template<typename T>
|
||||
class Ref {
|
||||
class RefObj {
|
||||
T *ptr_;
|
||||
unsigned count_;
|
||||
public:
|
||||
RefObj(T *ptr)
|
||||
: ptr_(ptr),
|
||||
count_(1)
|
||||
{ }
|
||||
|
||||
private:
|
||||
~RefObj()
|
||||
{
|
||||
delete ptr_;
|
||||
ptr_ = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
void hold(void)
|
||||
{
|
||||
count_++;
|
||||
}
|
||||
|
||||
void drop(void)
|
||||
{
|
||||
if (count_-- == 1)
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool exclusive(void) const
|
||||
{
|
||||
return (count_ == 1);
|
||||
}
|
||||
|
||||
T *get(void) const
|
||||
{
|
||||
return (ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
RefObj *obj_;
|
||||
public:
|
||||
Ref(void)
|
||||
: obj_(NULL)
|
||||
{ }
|
||||
|
||||
Ref(T *ptr)
|
||||
: obj_(NULL)
|
||||
{
|
||||
if (ptr != NULL)
|
||||
obj_ = new RefObj(ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Template... See operator=.
|
||||
*/
|
||||
Ref(const Ref& ref)
|
||||
: obj_(ref.obj_)
|
||||
{
|
||||
if (obj_ != NULL)
|
||||
obj_->hold();
|
||||
}
|
||||
|
||||
~Ref()
|
||||
{
|
||||
if (obj_ != NULL) {
|
||||
obj_->drop();
|
||||
obj_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Template so we can take a pointer from a Ref<> with a compatible
|
||||
* base class?
|
||||
*/
|
||||
const Ref& operator= (const Ref& ref)
|
||||
{
|
||||
if (obj_ != NULL) {
|
||||
obj_->drop();
|
||||
obj_ = NULL;
|
||||
}
|
||||
|
||||
if (ref.obj_ != NULL) {
|
||||
obj_ = ref.obj_;
|
||||
obj_->hold();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
T *operator-> (void) const
|
||||
{
|
||||
return (obj_->get());
|
||||
}
|
||||
|
||||
const T& operator* (void) const
|
||||
{
|
||||
const T *ptr = obj_->get();
|
||||
return (*ptr);
|
||||
}
|
||||
|
||||
template<typename Tc>
|
||||
Tc cast(void) const
|
||||
{
|
||||
const T *ptr = obj_->get();
|
||||
return (dynamic_cast<Tc>(ptr));
|
||||
}
|
||||
|
||||
bool exclusive(void) const
|
||||
{
|
||||
return (obj_->exclusive());
|
||||
}
|
||||
|
||||
bool null(void) const
|
||||
{
|
||||
return (obj_ == NULL);
|
||||
}
|
||||
|
||||
bool operator< (const Ref& b) const
|
||||
{
|
||||
return (obj_ < b.obj_);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !COMMON_REF_H */
|
66
common/registrar.h
Normal file
66
common/registrar.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_REGISTRAR_H
|
||||
#define COMMON_REGISTRAR_H
|
||||
|
||||
#include <set>
|
||||
|
||||
/*
|
||||
* U is merely a type used as a unique key, so that multiple Registrars of
|
||||
* objects with the same type can coexist.
|
||||
*/
|
||||
template<typename U, typename T>
|
||||
class Registrar {
|
||||
std::set<T> registered_set_;
|
||||
|
||||
Registrar(void)
|
||||
: registered_set_()
|
||||
{ }
|
||||
|
||||
~Registrar()
|
||||
{ }
|
||||
public:
|
||||
void enter(T item)
|
||||
{
|
||||
registered_set_.insert(item);
|
||||
}
|
||||
|
||||
std::set<T> enumerate(void) const
|
||||
{
|
||||
return (registered_set_);
|
||||
}
|
||||
|
||||
static Registrar *instance(void)
|
||||
{
|
||||
static Registrar *instance;
|
||||
|
||||
if (instance == NULL)
|
||||
instance = new Registrar();
|
||||
return (instance);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !COMMON_REGISTRAR_H */
|
151
common/ring_buffer.h
Normal file
151
common/ring_buffer.h
Normal file
|
@ -0,0 +1,151 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: ring_buffer.h //
|
||||
// Description: circular buffer for unlocked exchange of data //
|
||||
// Project: WANProxy XTech //
|
||||
// Author: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef COMMON_RING_BUFFER_H
|
||||
#define COMMON_RING_BUFFER_H
|
||||
|
||||
#define STANDARD_RING_BUFFER_CAPACITY 32768
|
||||
#define ITEM_SIZE ((int) sizeof (T))
|
||||
|
||||
template<typename T, int N = STANDARD_RING_BUFFER_CAPACITY> class RingBuffer
|
||||
{
|
||||
private:
|
||||
unsigned char buffer[N * ITEM_SIZE];
|
||||
unsigned char* reader;
|
||||
unsigned char* writer;
|
||||
|
||||
public:
|
||||
RingBuffer ();
|
||||
|
||||
int read (T& trg);
|
||||
int write (const T& src);
|
||||
|
||||
bool is_empty () { return (reader == writer); }
|
||||
int data_size () { return (writer >= reader ? writer - reader : sizeof buffer - (reader - writer)); }
|
||||
};
|
||||
|
||||
template<typename T, int N> RingBuffer<T, N>::RingBuffer ()
|
||||
{
|
||||
reader = writer = buffer;
|
||||
}
|
||||
|
||||
template<typename T, int N> int RingBuffer<T, N>::read (T& trg)
|
||||
{
|
||||
unsigned char* r;
|
||||
unsigned char* w;
|
||||
int s, t, n1, n2;
|
||||
|
||||
r = reader;
|
||||
w = writer;
|
||||
s = (w >= r ? (w - r) : sizeof buffer - (r - w));
|
||||
if (s >= ITEM_SIZE)
|
||||
{
|
||||
t = buffer + sizeof buffer - r;
|
||||
if (ITEM_SIZE <= t)
|
||||
n1 = ITEM_SIZE, n2 = 0;
|
||||
else
|
||||
n1 = t, n2 = ITEM_SIZE - t;
|
||||
memcpy (&trg, r, n1);
|
||||
if (n2)
|
||||
memcpy (((char*) &trg) + n1, buffer, n2);
|
||||
reader = (ITEM_SIZE < t ? r + n1 : buffer + n2);
|
||||
return ITEM_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, int N> int RingBuffer<T, N>::write (const T& src)
|
||||
{
|
||||
unsigned char* r;
|
||||
unsigned char* w;
|
||||
int s, t, n1, n2;
|
||||
|
||||
r = reader;
|
||||
w = writer;
|
||||
s = (w >= r ? sizeof buffer - (w - r) : (r - w));
|
||||
if (s > ITEM_SIZE)
|
||||
{
|
||||
t = buffer + sizeof buffer - w;
|
||||
if (ITEM_SIZE <= t)
|
||||
n1 = ITEM_SIZE, n2 = 0;
|
||||
else
|
||||
n1 = t, n2 = ITEM_SIZE - t;
|
||||
memcpy (w, &src, n1);
|
||||
if (n2)
|
||||
memcpy (buffer, ((const char*) &src) + n1, n2);
|
||||
writer = (ITEM_SIZE < t ? w + n1 : buffer + n2);
|
||||
return ITEM_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
template<typename T> class WaitBuffer
|
||||
{
|
||||
private:
|
||||
RingBuffer<T> ring;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t ready;
|
||||
|
||||
public:
|
||||
WaitBuffer ();
|
||||
~WaitBuffer ();
|
||||
|
||||
int read (T& trg);
|
||||
int write (const T& src);
|
||||
|
||||
void wakeup () { if (ring.is_empty ()) pthread_cond_signal (&ready); }
|
||||
};
|
||||
|
||||
template<typename T> WaitBuffer<T>::WaitBuffer ()
|
||||
{
|
||||
pthread_mutex_init (&mutex, 0);
|
||||
pthread_cond_init (&ready, 0);
|
||||
}
|
||||
|
||||
template<typename T> WaitBuffer<T>::~WaitBuffer ()
|
||||
{
|
||||
pthread_mutex_destroy (&mutex);
|
||||
pthread_cond_destroy (&ready);
|
||||
}
|
||||
|
||||
template<typename T> int WaitBuffer<T>::read (T& trg)
|
||||
{
|
||||
if (ring.is_empty ())
|
||||
{
|
||||
pthread_mutex_lock (&mutex);
|
||||
if (ring.is_empty ())
|
||||
pthread_cond_wait (&ready, &mutex);
|
||||
pthread_mutex_unlock (&mutex);
|
||||
}
|
||||
|
||||
return ring.read (trg);
|
||||
}
|
||||
|
||||
template<typename T> int WaitBuffer<T>::write (const T& src)
|
||||
{
|
||||
int rsl = ring.write (src);
|
||||
|
||||
if (rsl && ring.data_size () == ITEM_SIZE)
|
||||
{
|
||||
pthread_mutex_lock (&mutex);
|
||||
pthread_cond_signal (&ready);
|
||||
pthread_mutex_unlock (&mutex);
|
||||
}
|
||||
|
||||
return rsl;
|
||||
}
|
||||
|
||||
#endif /* !COMMON_RING_BUFFER_H */
|
7
common/subdir.mk
Normal file
7
common/subdir.mk
Normal file
|
@ -0,0 +1,7 @@
|
|||
all install regress clean:
|
||||
@for _dir in ${SUBDIR}; do \
|
||||
echo "==> ${SUBMAKE_DIR}$$_dir ($@)" ; \
|
||||
(cd $$_dir && \
|
||||
SUBMAKE_DIR=${SUBMAKE_DIR}$$_dir/ ${MAKE} $@) || \
|
||||
exit $$? ; \
|
||||
done
|
107
common/test.h
Normal file
107
common/test.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_TEST_H
|
||||
#define COMMON_TEST_H
|
||||
|
||||
class TestGroup {
|
||||
friend class Test;
|
||||
|
||||
LogHandle log_;
|
||||
const std::string description_;
|
||||
unsigned tests_;
|
||||
unsigned passes_;
|
||||
public:
|
||||
TestGroup(const LogHandle& log, const std::string& description)
|
||||
: log_(log),
|
||||
description_(description),
|
||||
tests_(0),
|
||||
passes_(0)
|
||||
{
|
||||
INFO(log_) << "Running tests in group: " << description_;
|
||||
}
|
||||
|
||||
~TestGroup()
|
||||
{
|
||||
ASSERT(log_, tests_ != 0);
|
||||
|
||||
INFO(log_) << "Test results for group: " << description_;
|
||||
if (passes_ == tests_) {
|
||||
INFO(log_) << "All tests passed.";
|
||||
} else {
|
||||
if (passes_ == 0) {
|
||||
ERROR(log_) << "All tests failed.";
|
||||
} else {
|
||||
INFO(log_) << passes_ << "/" << tests_ << " tests passed.";
|
||||
ERROR(log_) << (tests_ - passes_) << " tests failed.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void test(bool passed, const std::string& description)
|
||||
{
|
||||
if (passed) {
|
||||
#if 0
|
||||
DEBUG(log_) << "PASS: " << description;
|
||||
#endif
|
||||
passes_++;
|
||||
} else {
|
||||
ERROR(log_) << "FAIL: " << description;
|
||||
}
|
||||
tests_++;
|
||||
}
|
||||
};
|
||||
|
||||
class Test {
|
||||
TestGroup& group_;
|
||||
const std::string description_;
|
||||
bool passed_;
|
||||
public:
|
||||
Test(TestGroup& group, const std::string& description)
|
||||
: group_(group),
|
||||
description_(description),
|
||||
passed_(false)
|
||||
{ }
|
||||
|
||||
Test(TestGroup& group, const std::string& description, bool passed)
|
||||
: group_(group),
|
||||
description_(description),
|
||||
passed_(passed)
|
||||
{ }
|
||||
|
||||
~Test()
|
||||
{
|
||||
group_.test(passed_, description_);
|
||||
}
|
||||
|
||||
void pass(void)
|
||||
{
|
||||
ASSERT("/test", !passed_);
|
||||
passed_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !COMMON_TEST_H */
|
0
common/thread/Makefile
Normal file
0
common/thread/Makefile
Normal file
15
common/thread/TODO
Normal file
15
common/thread/TODO
Normal file
|
@ -0,0 +1,15 @@
|
|||
Threads need to pick a blocking mechanism and somehow stick to it reliably, so there can be a neat and tidy Thread::kill function. A signal should knock a thread out of anything, but that can still have races. It would be nice if Thread::kill didn't have to be virtual, and if it could be worked into a generalized thread-to-thread messaging paradigm, but that's problematic when one of the major purposes of having threads in the first place is to be able to use other polling mechanisms in separate threads, i.e. blocking for libpcap or X11 or whatever.
|
||||
|
||||
Maybe it would be best to remove virtual void main() and instead have a worker-thread model, where threads can perform work, wait, or be signalled. The work, wait and signal functions would be virtual, which would hide a lot of the complexity about whether it's okay to block, or whether we've been signalled. And then threads could determine their own needs for block and signal; most threads might use EventPoll to do that work, but some might use something like pcap or X11 instead. No inter-thread messaging at a low-level, but maybe some higher-level interfaces that could be implemented on top of them.
|
||||
|
||||
If moving to a worker model, why not provide a work unit, too, and the possibility of some messaging primitives? That also has the benefit of mirroring some of the hardware models it'd be nice for the event system and threading to be compatible with, like that of Octeon. And it allows for lossless messaging between threads, whereas signal/wait can have problems with races and spurious wakeups, right? Especially if there's any chance of the signal being consumed by something like a system call, rather than an instance of wait. But with some slightly-heavyweight locking, there's no chance of those kinds of races, because e.g. the thread state lock would be held during work processing. That nearly serializes processing, though. *Unless* we have a lockless work-queueing model in addition to a wakeup mechanism. Right? Then we can guarantee that a thread will acquire a lock, check for work, and only then block. There's still races, though, such as with pcap, or X11, which won't let us specify a lock to relinquish at wait time. Argh!
|
||||
|
||||
Maybe too much generalization is a curse, and it would be better to find a limited and reliable model to support, and make sure all the applications we care about in the immediate future are plausible.
|
||||
|
||||
Why not just register threads that need to generate callbacks as an "EventSource" with the EventThread/EventSystem? This is non-ideal for a world in which we would have multiple EventThreads but it's a start for now. But with this, the EventSource could include a pipe to read/write on, which would be very neat and tidy.
|
||||
|
||||
I tried moving towards making EventThread the normative model for threads, and parameterizing anything using callbacks on EventThread (as a CallbackScheduler mostly, but also for timeouts, although there's no reason to not have timeouts in a different thread, and merely schedule them back to EventThread.) This is OK, but mostly devolves into single-threading anyway.
|
||||
|
||||
If polling code is simplified a little further and moved to common/poll/..., it makes sense indeed to move polling into *every* thread, and to use pipes to communicate between threads (or, where possible, we could use user events like with kqueue.) That can all mostly be done under the hood after the fact for real if we begin with the EventSource model, in which new sources are registered with the EventSystem. Then we have one-direction communication, which is probably most of what we need anyway. Right?
|
||||
|
||||
Actually, to avoid races, the method of inter-thread communication must be a condvar so that we can savely use mutexes. Otherwise we can go to sleep with work waiting, right? Unless we get really fussy about the data on the inter-thread pipe, but why not just use condvars instead? Then we just need to have a WorkerThread which has block/signal/work abstractions, and make EventPoll one of the few that uses something other than the default. And have a single poll thread, of course. Yes, this doesn't solve the pcap race problem, but nothing will; pcap is thread hell.
|
95
common/thread/atomic.h
Normal file
95
common/thread/atomic.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_THREAD_ATOMIC_H
|
||||
#define COMMON_THREAD_ATOMIC_H
|
||||
|
||||
template<typename T>
|
||||
class Atomic {
|
||||
T val_;
|
||||
public:
|
||||
Atomic(void)
|
||||
: val_()
|
||||
{ }
|
||||
|
||||
template<typename Ta>
|
||||
Atomic(Ta arg)
|
||||
: val_(arg)
|
||||
{ }
|
||||
|
||||
~Atomic()
|
||||
{ }
|
||||
|
||||
T val () const { return val_; }
|
||||
bool operator == (T v) const { return (v == val_); }
|
||||
bool operator != (T v) const { return (v != val_); }
|
||||
|
||||
/*
|
||||
* Note that these are deliberately not operator overloads, to force
|
||||
* deliberate use of this class.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
template<typename Ta>
|
||||
T add(Ta arg)
|
||||
{
|
||||
return (__sync_add_and_fetch (&val_, arg));
|
||||
}
|
||||
|
||||
template<typename Ta>
|
||||
T subtract(Ta arg)
|
||||
{
|
||||
return (__sync_sub_and_fetch (&val_, arg));
|
||||
}
|
||||
|
||||
template<typename Ta>
|
||||
T set(Ta arg)
|
||||
{
|
||||
return (__sync_or_and_fetch (&val_, arg));
|
||||
}
|
||||
|
||||
template<typename Ta>
|
||||
T mask(Ta arg)
|
||||
{
|
||||
return (__sync_and_and_fetch (&val_, arg));
|
||||
}
|
||||
|
||||
template<typename Ta>
|
||||
T clear(Ta arg)
|
||||
{
|
||||
return (__sync_and_and_fetch (&val_, ~arg));
|
||||
}
|
||||
|
||||
template<typename To, typename Tn>
|
||||
bool cmpset(To oldval, Tn newval)
|
||||
{
|
||||
return (__sync_bool_compare_and_swap (&val_, oldval, newval));
|
||||
}
|
||||
#else
|
||||
#error "No support for atomic operations for your compiler. Why not add some?"
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* !COMMON_THREAD_ATOMIC_H */
|
6
common/thread/lib.mk
Normal file
6
common/thread/lib.mk
Normal file
|
@ -0,0 +1,6 @@
|
|||
VPATH+= ${TOPDIR}/common/thread
|
||||
|
||||
SRCS+= thread.cc
|
||||
|
||||
LDADD+= -lpthread
|
||||
|
71
common/thread/thread.cc
Normal file
71
common/thread/thread.cc
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <common/thread/thread.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: thread.cc //
|
||||
// Description: basic structure for generic thread objects //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
static void* thread_posix_start (void* arg)
|
||||
{
|
||||
Thread* td = (Thread*) arg;
|
||||
td->main ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Thread::Thread (const std::string& name) : name_(name), thread_id_(0), stop_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool Thread::start ()
|
||||
{
|
||||
int rv = pthread_create (&thread_id_, NULL, thread_posix_start, this);
|
||||
if (rv != 0)
|
||||
{
|
||||
ERROR("/thread/posix") << "Unable to start thread.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Thread::stop ()
|
||||
{
|
||||
stop_ = true;
|
||||
void* val;
|
||||
int rv = pthread_join (thread_id_, &val);
|
||||
if (rv == -1)
|
||||
ERROR("/thread/posix") << "Thread join failed.";
|
||||
}
|
||||
|
59
common/thread/thread.h
Normal file
59
common/thread/thread.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_THREAD_THREAD_H
|
||||
#define COMMON_THREAD_THREAD_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: thread.h //
|
||||
// Description: basic structure for generic thread objects //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Thread
|
||||
{
|
||||
protected:
|
||||
std::string name_;
|
||||
pthread_t thread_id_;
|
||||
bool stop_;
|
||||
|
||||
protected:
|
||||
Thread (const std::string&);
|
||||
|
||||
public:
|
||||
virtual ~Thread () {}
|
||||
|
||||
bool start ();
|
||||
virtual void stop ();
|
||||
virtual void main () = 0;
|
||||
};
|
||||
|
||||
#endif /* !COMMON_THREAD_THREAD_H */
|
3
common/time/Makefile
Normal file
3
common/time/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
SUBDIR+=
|
||||
|
||||
include ../../common/subdir.mk
|
3
common/time/lib.mk
Normal file
3
common/time/lib.mk
Normal file
|
@ -0,0 +1,3 @@
|
|||
VPATH+= ${TOPDIR}/common/time
|
||||
|
||||
SRCS+= time.cc
|
68
common/time/time.cc
Normal file
68
common/time/time.cc
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <common/time/time.h>
|
||||
|
||||
NanoTime
|
||||
NanoTime::current_time(void)
|
||||
{
|
||||
NanoTime nt;
|
||||
int rv;
|
||||
|
||||
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
|
||||
struct timespec ts;
|
||||
|
||||
rv = ::clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
ASSERT("/nano/time/posix", rv != -1);
|
||||
|
||||
nt.seconds_ = ts.tv_sec;
|
||||
nt.nanoseconds_ = ts.tv_nsec;
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
||||
rv = ::gettimeofday(&tv, NULL);
|
||||
ASSERT("/nano/time/gtod", rv != -1);
|
||||
nt.seconds_ = tv.tv_sec;
|
||||
nt.nanoseconds_ = tv.tv_usec * 1000;
|
||||
#endif
|
||||
|
||||
return (nt);
|
||||
}
|
||||
|
||||
void
|
||||
NanoTime::sleep(int ms)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms - ts.tv_sec) * 1000000;
|
||||
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
105
common/time/time.h
Normal file
105
common/time/time.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_TIME_TIME_H
|
||||
#define COMMON_TIME_TIME_H
|
||||
|
||||
#include <map>
|
||||
|
||||
struct NanoTime {
|
||||
uintmax_t seconds_;
|
||||
uintmax_t nanoseconds_;
|
||||
|
||||
NanoTime(void)
|
||||
: seconds_(0),
|
||||
nanoseconds_(0)
|
||||
{ }
|
||||
|
||||
NanoTime(const NanoTime& src)
|
||||
: seconds_(src.seconds_),
|
||||
nanoseconds_(src.nanoseconds_)
|
||||
{ }
|
||||
|
||||
bool operator< (const NanoTime& b) const
|
||||
{
|
||||
if (seconds_ == b.seconds_)
|
||||
return (nanoseconds_ < b.nanoseconds_);
|
||||
return (seconds_ < b.seconds_);
|
||||
}
|
||||
|
||||
bool operator> (const NanoTime& b) const
|
||||
{
|
||||
if (seconds_ == b.seconds_)
|
||||
return (nanoseconds_ > b.nanoseconds_);
|
||||
return (seconds_ > b.seconds_);
|
||||
}
|
||||
|
||||
bool operator<= (const NanoTime& b) const
|
||||
{
|
||||
if (seconds_ == b.seconds_)
|
||||
return (nanoseconds_ <= b.nanoseconds_);
|
||||
return (seconds_ <= b.seconds_);
|
||||
}
|
||||
|
||||
bool operator>= (const NanoTime& b) const
|
||||
{
|
||||
if (seconds_ == b.seconds_)
|
||||
return (nanoseconds_ >= b.nanoseconds_);
|
||||
return (seconds_ >= b.seconds_);
|
||||
}
|
||||
|
||||
NanoTime& operator+= (const NanoTime& b)
|
||||
{
|
||||
seconds_ += b.seconds_;
|
||||
nanoseconds_ += b.nanoseconds_;
|
||||
|
||||
if (nanoseconds_ >= 1000000000) {
|
||||
seconds_++;
|
||||
nanoseconds_ -= 1000000000;
|
||||
}
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
NanoTime& operator-= (const NanoTime& b)
|
||||
{
|
||||
ASSERT("/nano/time", *this >= b);
|
||||
|
||||
if (nanoseconds_ < b.nanoseconds_) {
|
||||
nanoseconds_ += 1000000000;
|
||||
seconds_ -= 1;
|
||||
}
|
||||
|
||||
seconds_ -= b.seconds_;
|
||||
nanoseconds_ -= b.nanoseconds_;
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
static NanoTime current_time(void);
|
||||
static void sleep(int ms);
|
||||
};
|
||||
|
||||
#endif /* !COMMON_TIME_TIME_H */
|
3
common/timer/Makefile
Normal file
3
common/timer/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
SUBDIR+=
|
||||
|
||||
include ../../common/subdir.mk
|
3
common/timer/lib.mk
Normal file
3
common/timer/lib.mk
Normal file
|
@ -0,0 +1,3 @@
|
|||
VPATH+= ${TOPDIR}/common/timer
|
||||
|
||||
SRCS+= timer.cc
|
56
common/timer/timer.cc
Normal file
56
common/timer/timer.cc
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2010 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <common/timer/timer.h>
|
||||
|
||||
void
|
||||
Timer::start(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
int rv;
|
||||
|
||||
rv = gettimeofday(&tv, NULL);
|
||||
if (rv == -1)
|
||||
HALT("/timer") << "Could not gettimeofday.";
|
||||
start_ = (tv.tv_sec * 1000 * 1000) + tv.tv_usec;
|
||||
}
|
||||
|
||||
void
|
||||
Timer::stop(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
int rv;
|
||||
|
||||
rv = gettimeofday(&tv, NULL);
|
||||
if (rv == -1)
|
||||
HALT("/timer") << "Could not gettimeofday.";
|
||||
stop_ = (tv.tv_sec * 1000 * 1000) + tv.tv_usec;
|
||||
|
||||
samples_.push_back(stop_ - start_);
|
||||
}
|
65
common/timer/timer.h
Normal file
65
common/timer/timer.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_TIMER_TIMER_H
|
||||
#define COMMON_TIMER_TIMER_H
|
||||
|
||||
class Timer {
|
||||
uintmax_t start_;
|
||||
uintmax_t stop_;
|
||||
|
||||
std::vector<uintmax_t> samples_;
|
||||
public:
|
||||
Timer(void)
|
||||
: start_(),
|
||||
stop_(),
|
||||
samples_()
|
||||
{ }
|
||||
|
||||
~Timer()
|
||||
{ }
|
||||
|
||||
void reset(void)
|
||||
{
|
||||
samples_.clear();
|
||||
}
|
||||
|
||||
void start(void);
|
||||
void stop(void);
|
||||
|
||||
uintmax_t sample(void) const
|
||||
{
|
||||
if (samples_.size() != 1)
|
||||
HALT("/timer") << "Requested 1 sample but " << samples_.size() << " available.";
|
||||
return (samples_[0]);
|
||||
}
|
||||
|
||||
std::vector<uintmax_t> samples(void) const
|
||||
{
|
||||
return (samples_);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !COMMON_TIMER_TIMER_H */
|
41
common/types.h
Normal file
41
common/types.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_TYPES_H
|
||||
#define COMMON_TYPES_H
|
||||
|
||||
#if !defined(__OPENNT)
|
||||
#include <stdint.h> /* XXX cstdint? */
|
||||
#endif
|
||||
|
||||
#if defined(__OPENNT)
|
||||
typedef unsigned long long uintmax_t;
|
||||
typedef long long intmax_t;
|
||||
typedef unsigned int uintptr_t; /* XXX Appears to be in stddef.h! */
|
||||
typedef int socklen_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#endif
|
||||
|
||||
#endif /* !COMMON_TYPES_H */
|
3
common/uuid/Makefile
Normal file
3
common/uuid/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
SUBDIR+=
|
||||
|
||||
include ../../common/subdir.mk
|
7
common/uuid/lib.mk
Normal file
7
common/uuid/lib.mk
Normal file
|
@ -0,0 +1,7 @@
|
|||
VPATH+= ${TOPDIR}/common/uuid
|
||||
|
||||
SRCS+= uuid.cc
|
||||
|
||||
ifeq "${OSNAME}" "Linux"
|
||||
LDADD+= -luuid
|
||||
endif
|
131
common/uuid/uuid.cc
Normal file
131
common/uuid/uuid.cc
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include <common/uuid/uuid.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: uuid.cc //
|
||||
// Description: basic handling of standard UUID objects //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool UUID::from_string (const uint8_t* str)
|
||||
{
|
||||
#ifdef USE_LIBUUID
|
||||
int rv = uuid_parse ((const char*) str, uuid_);
|
||||
if (rv == -1)
|
||||
return (false);
|
||||
ASSERT("/uuid/libuuid", rv == 0);
|
||||
#else
|
||||
uint32_t status;
|
||||
uuid_from_string ((const char*) str, &uuid_, &status);
|
||||
if (status != uuid_s_ok)
|
||||
return (false);
|
||||
#endif
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool UUID::to_string (uint8_t* str) const
|
||||
{
|
||||
#ifdef USE_LIBUUID
|
||||
uuid_unparse (uuid_, (char*) str);
|
||||
#else
|
||||
char *p;
|
||||
uuid_to_string (&uuid_, &p, NULL);
|
||||
ASSERT("/uuid/libc", p != NULL);
|
||||
strcpy ((char*) str, p);
|
||||
free (p);
|
||||
#endif
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool UUID::from_file (std::string& path)
|
||||
{
|
||||
std::fstream file;
|
||||
std::string s;
|
||||
file.open (path.c_str(), std::ios::in);
|
||||
if (file.good())
|
||||
{
|
||||
file >> s;
|
||||
return from_string ((const uint8_t*) s.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UUID::to_file (std::string& path) const
|
||||
{
|
||||
std::fstream file;
|
||||
file.open (path.c_str(), std::ios::out);
|
||||
if (file.good())
|
||||
{
|
||||
uint8_t str[UUID_STRING_SIZE + 1];
|
||||
to_string (str);
|
||||
std::string s ((const char*) str);
|
||||
file << s;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UUID::decode (Buffer& buf)
|
||||
{
|
||||
if (buf.length() < UUID_STRING_SIZE)
|
||||
return (false);
|
||||
|
||||
uint8_t str[UUID_STRING_SIZE + 1];
|
||||
buf.moveout (str, UUID_STRING_SIZE);
|
||||
str[UUID_STRING_SIZE] = 0;
|
||||
return from_string (str);
|
||||
}
|
||||
|
||||
bool UUID::encode (Buffer& buf) const
|
||||
{
|
||||
uint8_t str[UUID_STRING_SIZE + 1];
|
||||
to_string (str);
|
||||
buf.append (str, UUID_STRING_SIZE);
|
||||
return (true);
|
||||
}
|
||||
|
||||
void UUID::generate(void)
|
||||
{
|
||||
#ifdef USE_LIBUUID
|
||||
uuid_generate (uuid_);
|
||||
#else
|
||||
uuid_create (&uuid_, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const UUID& uuid)
|
||||
{
|
||||
uint8_t str[UUID_STRING_SIZE + 1];
|
||||
uuid.to_string (str);
|
||||
return os << str;
|
||||
}
|
86
common/uuid/uuid.h
Normal file
86
common/uuid/uuid.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_UUID_UUID_H
|
||||
#define COMMON_UUID_UUID_H
|
||||
|
||||
#include <string.h>
|
||||
#include <ostream>
|
||||
#include <common/buffer.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: uuid.h //
|
||||
// Description: basic handling of standard UUID objects //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#else
|
||||
#define USE_LIBUUID
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBUUID
|
||||
#include <uuid/uuid.h>
|
||||
#else
|
||||
#include <uuid.h>
|
||||
#endif
|
||||
|
||||
#define UUID_STRING_SIZE (sizeof (uuid_t) * 2 + 4)
|
||||
|
||||
struct UUID
|
||||
{
|
||||
uuid_t uuid_;
|
||||
|
||||
bool from_string (const uint8_t* str);
|
||||
bool to_string (uint8_t* str) const;
|
||||
bool from_file (std::string& path);
|
||||
bool to_file (std::string& path) const;
|
||||
bool decode (Buffer&);
|
||||
bool encode (Buffer& buf) const;
|
||||
void generate (void);
|
||||
|
||||
UUID ()
|
||||
{
|
||||
memset (&uuid_, 0, sizeof uuid_);
|
||||
}
|
||||
|
||||
bool operator< (const UUID& b) const
|
||||
{
|
||||
return (memcmp (&uuid_, &b.uuid_, sizeof uuid_) < 0);
|
||||
}
|
||||
|
||||
bool is_valid () const
|
||||
{
|
||||
uuid_t u; return (memcmp (&uuid_, &u, sizeof uuid_) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const UUID& uuid);
|
||||
|
||||
#endif /* !COMMON_UUID_UUID_H */
|
Loading…
Add table
Add a link
Reference in a new issue