7 /* XXX: need a sacrificial lamb for win-diarrhea testing */
10 #define WIN32_LEAN_AND_MEAN
15 typedef ULONGLONG (WINAPI GetTickCount64Proc
)(void);
16 static GetTickCount64Proc
*pt2GetTickCount64
;
17 static GetTickCount64Proc
*pt2RealGetTickCount
;
19 static uint64 startPerformanceCounter
;
20 static uint64 startGetTickCount
;
21 /* MSVC 6 standard doesn't like division with uint64s */
22 static double counterPerMicrosecond
;
24 uint64
UTGetTickCount64()
26 if (pt2GetTickCount64
) {
27 return pt2GetTickCount64();
29 if (pt2RealGetTickCount
) {
30 uint64 v
= pt2RealGetTickCount();
31 /* fix return value from GetTickCount */
32 return (DWORD
)v
| ((v
>> 0x18) & 0xFFFFFFFF00000000);
34 return (uint64
)GetTickCount();
37 void Time_Initialize()
39 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
40 pt2GetTickCount64
= (GetTickCount64Proc
*)GetProcAddress(kernel32
, "GetTickCount64");
41 /* not a typo. GetTickCount actually returns 64 bits */
42 pt2RealGetTickCount
= (GetTickCount64Proc
*)GetProcAddress(kernel32
, "GetTickCount");
45 QueryPerformanceCounter((LARGE_INTEGER
*)&startPerformanceCounter
);
46 QueryPerformanceFrequency((LARGE_INTEGER
*)&frequency
);
47 counterPerMicrosecond
= (double)frequency
/ 1000000.0f
;
48 startGetTickCount
= UTGetTickCount64();
51 int64
abs64(int64 x
) { return x
< 0 ? -x
: x
; }
53 static uint64
GetMicroseconds(void)
55 static bool time_init
= false;
64 QueryPerformanceCounter((LARGE_INTEGER
*) &counter
);
65 tick
= UTGetTickCount64();
67 /* unfortunately, QueryPerformanceCounter is not guaranteed
68 to be monotonic. Make it so. */
69 int64 ret
= (int64
)(((int64
)counter
- (int64
)startPerformanceCounter
) / counterPerMicrosecond
);
70 /* if the QPC clock leaps more than one second off GetTickCount64()
71 something is seriously fishy. Adjust QPC to stay monotonic */
72 int64 tick_diff
= tick
- startGetTickCount
;
73 if (abs64(ret
/ 100000 - tick_diff
/ 100) > 10) {
74 startPerformanceCounter
-= (uint64
)((int64
)(tick_diff
* 1000 - ret
) * counterPerMicrosecond
);
75 ret
= (int64
)((counter
- startPerformanceCounter
) / counterPerMicrosecond
);
83 #include <sys/time.h> /* Linux needs both time.h and sys/time.h */
87 #include <sys/socket.h>
88 #include <arpa/inet.h>
90 /* XXX: need a sacrificial lamb to test this on mac-vomit */
91 #if defined(__APPLE__)
92 #include <mach/mach_time.h>
94 static uint64
GetMicroseconds(void)
96 /* http://developer.apple.com/mac/library/qa/qa2004/qa1398.html
97 http://www.macresearch.org/tutorial_performance_and_time */
98 static mach_timebase_info_data_t sTimebaseInfo
;
99 static uint64_t start_tick
= 0;
101 /* Returns a counter in some fraction of a nanoseconds */
102 tick
= mach_absolute_time();
103 if (sTimebaseInfo
.denom
== 0) {
104 /* Get the timer ratio to convert mach_absolute_time to nanoseconds */
105 mach_timebase_info(&sTimebaseInfo
);
108 /* Calculate the elapsed time, convert it to microseconds and return it. */
109 return ((tick
- start_tick
) * sTimebaseInfo
.numer
) / (sTimebaseInfo
.denom
* 1000);
112 #else /* !__APPLE__ */
114 /* Unfortunately, #ifdef CLOCK_MONOTONIC is not enough to make sure that
115 POSIX clocks work -- we could be running a recent libc with an ancient
116 kernel (think OpenWRT). -- jch */
118 static uint64_t GetMicroseconds(void)
120 #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC)
121 static int have_posix_clocks
= -1;
125 #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC)
126 if (have_posix_clocks
< 0) {
128 rc
= clock_gettime(CLOCK_MONOTONIC
, &ts
);
130 have_posix_clocks
= 0;
132 have_posix_clocks
= 1;
136 if (have_posix_clocks
) {
138 rc
= clock_gettime(CLOCK_MONOTONIC
, &ts
);
140 return (uint64
)(ts
.tv_sec
) * 1000000 + ts
.tv_nsec
/ 1000;
145 rc
= gettimeofday(&tv
, NULL
);
147 return (uint64
)(tv
.tv_sec
) * 1000000 + tv
.tv_usec
;
150 #endif /* !__APPLE__ */
154 uint64
UTP_GetMicroseconds(void)
156 static uint64 offset
= 0;
157 static uint64 previous
= 0;
160 now
= GetMicroseconds() + offset
;
161 if (previous
> now
) {
163 offset
+= previous
- now
;
170 uint32
UTP_GetMilliseconds(void)
172 return UTP_GetMicroseconds() / 1000;
175 #define ETHERNET_MTU 1500
176 #define IPV4_HEADER_SIZE 20
177 #define IPV6_HEADER_SIZE 40
178 #define UDP_HEADER_SIZE 8
179 #define GRE_HEADER_SIZE 24
180 #define PPPOE_HEADER_SIZE 8
181 #define MPPE_HEADER_SIZE 2
182 /* packets have been observed in the wild that were fragmented
183 with a payload of 1416 for the first fragment
184 There are reports of routers that have MTU sizes as small as 1392 */
185 #define FUDGE_HEADER_SIZE 36
186 #define TEREDO_MTU 1280
188 #define UDP_IPV4_OVERHEAD (IPV4_HEADER_SIZE + UDP_HEADER_SIZE)
189 #define UDP_IPV6_OVERHEAD (IPV6_HEADER_SIZE + UDP_HEADER_SIZE)
190 #define UDP_TEREDO_OVERHEAD (UDP_IPV4_OVERHEAD + UDP_IPV6_OVERHEAD)
192 #define UDP_IPV4_MTU (ETHERNET_MTU - IPV4_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
193 #define UDP_IPV6_MTU (ETHERNET_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
194 #define UDP_TEREDO_MTU (TEREDO_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE)
196 uint16
UTP_GetUDPMTU(struct sockaddr
*remote
, socklen_t remotelen
)
199 /* Since we don't know the local address of the interface,
200 be conservative and assume all IPv6 connections are Teredo. */
201 return remote
->sa_family
== AF_INET6
? UDP_TEREDO_MTU
: UDP_IPV4_MTU
;
204 uint16
UTP_GetUDPOverhead(struct sockaddr
*remote
, socklen_t remotelen
)
207 /* Since we don't know the local address of the interface,
208 be conservative and assume all IPv6 connections are Teredo. */
209 return remote
->sa_family
== AF_INET6
? UDP_TEREDO_OVERHEAD
: UDP_IPV4_OVERHEAD
;
212 uint32
UTP_Random(void)
217 void UTP_DelaySample(struct sockaddr
*remote
, int sample_ms
)
223 size_t UTP_sockaddr_GetPacketSize(struct sockaddr
*remote
)