lock.h:
#ifndef __LOCK_H__
#define __LOCK_H__
#include <pthread.h>
class MutexLocker
{
public:
MutexLocker();
~MutexLocker();
void lock();
void unlock();
private:
pthread_mutex_t m_locker;
};
class RWLocker
{
public:
RWLocker();
~RWLocker();
void rdlock();
void wrlock();
void unlock();
private:
pthread_rwlock_t m_locker;
};
#endif
lock.cpp:
#include <cstdio>
#include <cstdlib>
#include <error.h>
#include <cstring>
#include "lock.h"
MutexLocker::MutexLocker()
{
int error_no = 0;
if (0 != (error_no = pthread_mutex_init(&m_locker, NULL)))
{
printf("pthread_mutex_init error: %s\n", strerror(error_no));
exit(1);
}
}
MutexLocker::~MutexLocker()
{
int error_no = 0;
if (0 != (error_no = pthread_mutex_destroy(&m_locker)))
{
printf("pthread_mutex_destroy error: %s\n", strerror(error_no));
exit(1);
}
}
void MutexLocker::lock()
{
int error_no = 0;
if (0 != (error_no = pthread_mutex_lock(&m_locker)))
{
printf("pthread_mutex_lock error: %s\n", strerror(error_no));
exit(1);
}
}
void MutexLocker::unlock()
{
int error_no = 0;
if (0 != (error_no = pthread_mutex_unlock(&m_locker)))
{
printf("pthread_mutex_unlock error: %s\n", strerror(error_no));
exit(1);
}
}
RWLocker::RWLocker()
{
int error_no = 0;
if (0 != (error_no = pthread_rwlock_init(&m_locker, NULL)))
{
printf("pthread_rwlock_init error: %s\n", strerror(error_no));
exit(1);
}
}
RWLocker::~RWLocker()
{
int error_no = 0;
if (0 != (error_no = pthread_rwlock_destroy(&m_locker)))
{
printf("pthread_rwlock_destroy error: %s\n", strerror(error_no));
exit(1);
}
}
void RWLocker::rdlock()
{
int error_no = 0;
if (0 != (error_no = pthread_rwlock_rdlock(&m_locker)))
{
printf("pthread_rwlock_rdlock error: %s\n", strerror(error_no));
exit(1);
}
}
void RWLocker::wrlock()
{
int error_no = 0;
if (0 != (error_no = pthread_rwlock_wrlock(&m_locker)))
{
printf("pthread_rwlock_wrlock error: %s\n", strerror(error_no));
exit(1);
}
}
void RWLocker::unlock()
{
int error_no = 0;
if (0 != (error_no = pthread_rwlock_unlock(&m_locker)))
{
printf("pthread_rwlock_unlock error: %s\n", strerror(error_no));
exit(1);
}
}
types.h:
#ifndef __TYPES_H__
#define __TYPES_H__
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef uint32_t seq_type;
typedef uint32_t time_type;
#endif
common.h:
#ifndef __COMMON_H__
#define __COMMON_H__
#include "types.h"
time_type getcurtime();
void big2little(void * object, int size);
#endif
common.cpp:
#include <cstdio>
#include <sys/time.h>
#include "common.h"
time_type getcurtime()
{
static struct timeval base;
static bool first_time = true;
if (first_time)
{
gettimeofday(&base, NULL);
first_time = false;
}
struct timeval curtime;
gettimeofday(&curtime, NULL);
time_type delta = 0;
if (curtime.tv_usec < base.tv_usec)
{
delta = (1000000 + curtime.tv_usec - base.tv_usec) / 1000;
--curtime.tv_sec;
}
else
{
delta = (curtime.tv_usec - base.tv_usec) / 1000;
}
delta += (curtime.tv_sec - base.tv_sec) * 1000;
return(delta);
}
void big2little(void * object, int size)
{
static union
{
uint16_t us;
unsigned char uc[sizeof(uint16_t)];
} un;
un.us = 0x0001;
if (0x00 == un.uc[0])
{
char * ptr = (char *)object;
for (int i = 0; i < size / 2; ++i)
{
char temp = ptr[i];
ptr[i] = ptr[size - 1 - i];
ptr[size - 1 - i] = temp;
}
}
}
nodes.hpp:
#ifndef __NODES_H__
#define __NODES_H__
#include <cassert>
#include <iostream>
using std::min;
using std::max;
#include "types.h"
#include "lock.h"
template <typename NodeType>
class NodePool
{
public:
NodePool(NodePool<typename NodeType::InnerNode> * p) : first_node(NULL), inner_pool(p)
{
}
~NodePool()
{
locker.lock();
NodeType * ptr = first_node;
while (NULL != ptr)
{
first_node = first_node->next;
delete ptr;
ptr = first_node;
}
locker.unlock();
}
NodeType * get_node()
{
NodeType * ptr = NULL;
locker.lock();
if (NULL != first_node)
{
ptr = first_node;
first_node = first_node->next;
if (NULL != first_node)
{
first_node->prev = NULL;
}
ptr->prev = NULL;
ptr->next = NULL;
}
else
{
ptr = new NodeType(inner_pool);
}
locker.unlock();
return(ptr);
}
void put_node(NodeType * node)
{
put_node(node, node);
}
void put_node(NodeType * head, NodeType * tail)
{
assert(NULL != head && NULL != tail);
locker.lock();
tail->next = first_node;
if (NULL != first_node)
{
first_node->prev = tail;
}
first_node = head;
first_node->prev = NULL;
locker.unlock();
}
private:
NodeType * first_node;
NodePool<typename NodeType::InnerNode> * inner_pool;
MutexLocker locker;
};
template <typename NodeType>
struct NodeLink
{
typedef NodePool<NodeType> PoolType;
NodeType * head;
NodeType * tail;
PoolType * pool;
uint16_t size;
NodeLink(PoolType * p)
: head(NULL), tail(NULL), pool(p), size(0)
{
assert(NULL != pool);
}
~NodeLink()
{
clear();
}
bool push_after(NodeType * loc, NodeType * node)
{
if (NULL == loc)
{
assert(false);
return(false);
}
if (NULL == node)
{
assert(false);
return(false);
}
node->prev = loc;
node->next = loc->next;
if (NULL != loc->next)
{
loc->next->prev = node;
}
else
{
tail = node;
}
loc->next = node;
++size;
return(true);
}
bool push_front(NodeType * node)
{
if (NULL == node)
{
assert(false);
return(false);
}
node->prev = NULL;
node->next = head;
if (NULL != head)
{
head->prev = node;
}
else
{
tail = node;
}
head = node;
++size;
return(true);
}
bool push_back(NodeType * node)
{
if (NULL == node)
{
assert(false);
return(false);
}
node->prev = tail;
node->next = NULL;
if (NULL == tail)
{
head = node;
}
else
{
tail->next = node;
}
tail = node;
++size;
return(true);
}
bool push_back(NodeLink<NodeType> & node_list)
{
if (NULL == node_list.head)
{
assert(false);
return(false);
}
node_list.head->prev = tail;
if (NULL == tail)
{
head = node_list.head;
}
else
{
tail->next = node_list.head;
}
tail = node_list.tail;
size += node_list.size;
node_list.head = node_list.tail = NULL;
node_list.size = 0;
return(true);
}
bool erase(NodeType * node)
{
assert(NULL != pool);
if (NULL == node)
{
assert(false);
return(false);
}
if (NULL != node->prev)
{
node->prev->next = node->next;
}
else
{
head = node->next;
}
if (NULL != node->next)
{
node->next->prev = node->prev;
}
else
{
tail = node->prev;
}
node->clear();
pool->put_node(node);
--size;
return(true);
}
void clear()
{
assert(NULL != pool);
NodeType * node = head;
while (NULL != node)
{
node->clear();
node = node->next;
}
if (NULL != head)
{
pool->put_node(head, tail);
}
head = tail = NULL;
size = 0;
}
};
typedef struct TimeInfo
{
uint8_t index;
time_type time;
struct TimeInfo * prev;
struct TimeInfo * next;
typedef void InnerNode;
TimeInfo(NodePool<void> * p) : index(0), time(0), prev(NULL), next(NULL)
{
}
~TimeInfo()
{
clear();
}
void clear()
{
}
} TimeNode;
typedef struct SeqInfo
{
seq_type front_sequence;
seq_type behind_sequence;
NodeLink<TimeNode> time_list;
struct SeqInfo * prev;
struct SeqInfo * next;
typedef TimeNode InnerNode;
SeqInfo(NodePool<TimeNode> * p)
: front_sequence(0), behind_sequence(0),
time_list(p), prev(NULL), next(NULL)
{
}
~SeqInfo()
{
clear();
}
int compare(const struct SeqInfo * other) const
{
assert(NULL != other);
if (front_sequence < other->front_sequence)
{
assert(behind_sequence <= other->front_sequence);
return(-1);
}
else if (front_sequence > other->front_sequence)
{
assert(front_sequence >= other->behind_sequence);
return(1);
}
else /* if (front_sequence == other->front_sequence) */
{
assert(behind_sequence == other->behind_sequence);
return(0);
}
}
TimeNode * find_time_node(uint8_t index)
{
assert(0 != index);
TimeNode * node = time_list.head;
while (NULL != node)
{
if (index < node->index)
{
assert(false);
return(NULL);
}
else if (index > node->index)
{
node = node->next;
}
else
{
return(node);
}
}
return(NULL);
}
void clear()
{
time_list.clear();
}
} SeqNode;
typedef struct SendDataInfo
{
enum { send_node_block_size = 16384 };
seq_type first_sequence;
uint16_t using_size;
uint16_t blank_size;
NodeLink<SeqNode> seq_list;
struct SendDataInfo * prev;
struct SendDataInfo * next;
unsigned char data[send_node_block_size];
typedef SeqNode InnerNode;
SendDataInfo(NodePool<SeqNode> * p)
: first_sequence(0), using_size(0),
blank_size(send_node_block_size),
seq_list(p), prev(NULL), next(NULL)
{
}
~SendDataInfo()
{
clear();
}
int get_relation(seq_type front_sequence, uint16_t offset)
{
assert(0 != offset);
assert(front_sequence + offset > front_sequence);
if (first_sequence > front_sequence)
{
return(1);
}
else if (first_sequence + using_size <= front_sequence)
{
return(-1);
}
else
{
assert(front_sequence + offset <= first_sequence + using_size);
return(0);
}
}
SeqNode * find_seq_node(const SeqNode * node)
{
assert(NULL != node);
SeqNode * ret = seq_list.head;
while (NULL != ret)
{
int comp = node->compare(ret);
if (comp < 0)
{
return(NULL);
}
else if (comp > 0)
{
ret = ret->next;
}
else
{
return(ret);
}
}
return(NULL);
}
void clear()
{
seq_list.clear();
}
} SendDataNode;
typedef struct RttInfo
{
enum { g = 8, h = 4 };
enum { min_rto = 200, max_rto = 1000 };
time_type srtt;
time_type rttvar;
time_type rto;
RttInfo() : srtt(0), rttvar(250), rto(srtt + 4 * rttvar)
{
}
void update(time_type rtt)
{
int delta = rtt - srtt;
srtt += delta / g;
if (delta < 0)
{
delta = -delta;
}
rttvar += (delta - rttvar) / h;
rto = srtt + 4 * rttvar;
if (rto < min_rto)
{
rto = min_rto;
}
else if (rto > max_rto)
{
rto = max_rto;
}
}
} RttType;
typedef struct AckInfo
{
seq_type front_sequence;
uint16_t region_size;
uint8_t count;
AckInfo() : front_sequence(0), region_size(0), count(4)
{
}
AckInfo & operator = (const struct AckInfo & other)
{
if (this != &other)
{
front_sequence = other.front_sequence;
region_size = other.region_size;
count = other.count;
}
return(*this);
}
} AckRegion;
typedef struct RegionInfo
{
seq_type front_sequence;
seq_type behind_sequence;
struct RegionInfo * prev;
struct RegionInfo * next;
typedef void InnerNode;
RegionInfo(NodePool<void> * p)
: front_sequence(0), behind_sequence(0), prev(NULL), next(NULL)
{
}
~RegionInfo()
{
clear();
}
void clear()
{
}
} RegionNode;
typedef struct RecvDataInfo
{
enum { recv_node_block_size = 16384 };
seq_type min_sequence;
seq_type max_sequence;
struct RecvDataInfo * prev;
struct RecvDataInfo * next;
unsigned char data[recv_node_block_size];
typedef void InnerNode;
RecvDataInfo(NodePool<void> * p)
: min_sequence(0), max_sequence(0), prev(NULL), next(NULL)
{
}
~RecvDataInfo()
{
clear();
}
void clear()
{
}
} RecvDataNode;
#endif
rudp.h:
#ifndef __RUDP_H__
#define __RUDP_H__
#include "nodes.hpp"
#include "lock.h"
class RudpMgr;
class Rudp
{
public: /* both end */
Rudp(RudpMgr * mgr, int sockfd, uint32_t unique_id);
~Rudp();
public: /* send end, for user */
bool send_data(unsigned char * data, uint16_t len, bool reliable);
bool send_heart_beat_package();
public: /* both end, for RudpMgr */
bool recv_data(unsigned char * data, uint16_t len);
bool is_alive();
uint32_t get_unique_id();
void kill();
private: /* both end */
enum { unreliable_udp, reliable_udp, ack_message, heart_beat };
RudpMgr * m_rudp_mgr;
int m_sockfd;
uint32_t m_unique_id;
bool m_is_alive;
time_type m_last_recv_heart_beat_time;
public: /* send end, for RudpMgr */
bool has_data_to_send();
bool send_data();
private: /* send end */
bool store_send_data(unsigned char * data, uint16_t len);
bool recv_ack(unsigned char * data, uint16_t len);
void send_new_data(uint8_t & send_count);
void send_old_data(uint