kcp/test.h

243 lines
5.0 KiB
C
Raw Normal View History

#ifndef __TEST_H__
#define __TEST_H__
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include "ikcp.h"
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
#include <windows.h>
#elif !defined(__unix)
#define __unix
#endif
#ifdef __unix
#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/types.h>
#endif
/* get system time */
static inline void itimeofday(long *sec, long *usec)
{
#if defined(__unix)
struct timeval time;
gettimeofday(&time, NULL);
if (sec) *sec = time.tv_sec;
if (usec) *usec = time.tv_usec;
#else
static long mode = 0, addsec = 0;
BOOL retval;
static IINT64 freq = 1;
IINT64 qpc;
if (mode == 0) {
retval = QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
freq = (freq == 0)? 1 : freq;
retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc);
addsec = (long)time(NULL);
addsec = addsec - (long)((qpc / freq) & 0x7fffffff);
mode = 1;
}
retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc);
retval = retval * 2;
if (sec) *sec = (long)(qpc / freq) + addsec;
if (usec) *usec = (long)((qpc % freq) * 1000000 / freq);
#endif
}
/* get clock in millisecond 64 */
static inline IINT64 iclock64(void)
{
long s, u;
IINT64 value;
itimeofday(&s, &u);
value = ((IINT64)s) * 1000 + (u / 1000);
return value;
}
static inline IUINT32 iclock()
{
return (IUINT32)(iclock64() & 0xfffffffful);
}
/* sleep in millisecond */
static inline void isleep(unsigned long millisecond)
{
#ifdef __unix /* usleep( time * 1000 ); */
struct timespec ts;
ts.tv_sec = (time_t)(millisecond / 1000);
ts.tv_nsec = (long)((millisecond % 1000) * 1000000);
/*nanosleep(&ts, NULL);*/
usleep((millisecond << 10) - (millisecond << 4) - (millisecond << 3));
#elif defined(_WIN32)
Sleep(millisecond);
#endif
}
#ifdef __cplusplus
#include <list>
#include <vector>
// <20><><EFBFBD>ӳٵ<D3B3><D9B5><EFBFBD><EFBFBD>ݰ<EFBFBD>
class DelayPacket
{
public:
virtual ~DelayPacket() {
if (_ptr) delete _ptr;
_ptr = NULL;
}
DelayPacket(int size, const void *src = NULL) {
_ptr = new unsigned char[size];
_size = size;
if (src) {
memcpy(_ptr, src, size);
}
}
unsigned char* ptr() { return _ptr; }
const unsigned char* ptr() const { return _ptr; }
int size() const { return _size; }
IUINT32 ts() const { return _ts; }
void setts(IUINT32 ts) { _ts = ts; }
protected:
unsigned char *_ptr;
int _size;
IUINT32 _ts;
};
// <20><><EFBFBD>ȷֲ<C8B7><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
class Random
{
public:
Random(int size) {
this->size = 0;
seeds.resize(size);
}
int random() {
int x, i;
if (seeds.size() == 0) return 0;
if (size == 0) {
for (i = 0; i < (int)seeds.size(); i++) {
seeds[i] = i;
}
size = (int)seeds.size();
}
i = rand() % size;
x = seeds[i];
seeds[i] = seeds[--size];
return x;
}
protected:
int size;
std::vector<int> seeds;
};
// <20><><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>
class LatencySimulator
{
public:
virtual ~LatencySimulator() {
clear();
}
// lostrate: <20><><EFBFBD><EFBFBD>һ<EFBFBD>ܶ<EFBFBD><DCB6><EFBFBD><EFBFBD>ʵİٷֱȣ<D6B1>Ĭ<EFBFBD><C4AC> 10%
// rttmin<69><6E>rtt<74><74>Сֵ<D0A1><D6B5>Ĭ<EFBFBD><C4AC> 60
// rttmax<61><78>rtt<74><74><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>Ĭ<EFBFBD><C4AC> 125
LatencySimulator(int lostrate = 10, int rttmin = 60, int rttmax = 125, int nmax = 1000):
r12(100), r21(100) {
current = iclock();
this->lostrate = lostrate / 2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD>̳<EFBFBD><CCB3><EFBFBD>2
this->rttmin = rttmin / 2;
this->rttmax = rttmax / 2;
this->nmax = nmax;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void clear() {
DelayTunnel::iterator it;
for (it = p12.begin(); it != p12.end(); it++) {
delete *it;
}
for (it = p21.begin(); it != p21.end(); it++) {
delete *it;
}
p12.clear();
p21.clear();
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// peer - <20>˵<EFBFBD>0/1<><31><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>1<EFBFBD><31><EFBFBD>գ<EFBFBD><D5A3><EFBFBD>1<EFBFBD><31><EFBFBD>ʹ<EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD>
void send(int peer, const void *data, int size) {
if (peer == 0) {
if (r12.random() < lostrate) return;
if ((int)p12.size() >= nmax) return;
} else {
if (r21.random() < lostrate) return;
if ((int)p21.size() >= nmax) return;
}
DelayPacket *pkt = new DelayPacket(size, data);
current = iclock();
IUINT32 delay = rttmin;
if (rttmax > rttmin) delay += rand() % (rttmax - rttmin);
pkt->setts(current + delay);
if (peer == 0) {
p12.push_back(pkt);
} else {
p21.push_back(pkt);
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int recv(int peer, void *data, int maxsize) {
DelayTunnel::iterator it;
if (peer == 0) {
it = p21.begin();
if (p21.size() == 0) return -1;
} else {
it = p12.begin();
if (p12.size() == 0) return -1;
}
DelayPacket *pkt = *it;
current = iclock();
if (current < pkt->ts()) return -2;
if (maxsize < pkt->size()) return -3;
if (peer == 0) {
p21.erase(it);
} else {
p12.erase(it);
}
maxsize = pkt->size();
memcpy(data, pkt->ptr(), maxsize);
2014-12-29 00:43:25 +08:00
delete pkt;
return maxsize;
}
protected:
IUINT32 current;
int lostrate;
int rttmin;
int rttmax;
int nmax;
typedef std::list<DelayPacket*> DelayTunnel;
DelayTunnel p12;
DelayTunnel p21;
Random r12;
Random r21;
};
#endif
#endif