utp_utils.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Copyright (c) 2010-2013 BitTorrent, Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. #include <stdlib.h>
  23. #include <assert.h>
  24. #include "utp.h"
  25. #include "utp_types.h"
  26. #ifdef WIN32
  27. #define WIN32_LEAN_AND_MEAN
  28. #include <windows.h>
  29. #include <winsock2.h>
  30. #include <ws2tcpip.h>
  31. #else //!WIN32
  32. #include <time.h>
  33. #include <sys/time.h> // Linux needs both time.h and sys/time.h
  34. #endif
  35. #if defined(__APPLE__)
  36. #include <mach/mach_time.h>
  37. #endif
  38. #include "utp_utils.h"
  39. #ifdef WIN32
  40. typedef ULONGLONG (WINAPI GetTickCount64Proc)(void);
  41. static GetTickCount64Proc *pt2GetTickCount64;
  42. static GetTickCount64Proc *pt2RealGetTickCount;
  43. static uint64 startPerformanceCounter;
  44. static uint64 startGetTickCount;
  45. // MSVC 6 standard doesn't like division with uint64s
  46. static double counterPerMicrosecond;
  47. static uint64 UTGetTickCount64()
  48. {
  49. if (pt2GetTickCount64) {
  50. return pt2GetTickCount64();
  51. }
  52. if (pt2RealGetTickCount) {
  53. uint64 v = pt2RealGetTickCount();
  54. // fix return value from GetTickCount
  55. return (DWORD)v | ((v >> 0x18) & 0xFFFFFFFF00000000);
  56. }
  57. return (uint64)GetTickCount();
  58. }
  59. static void Time_Initialize()
  60. {
  61. HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
  62. pt2GetTickCount64 = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount64");
  63. // not a typo. GetTickCount actually returns 64 bits
  64. pt2RealGetTickCount = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount");
  65. uint64 frequency;
  66. QueryPerformanceCounter((LARGE_INTEGER*)&startPerformanceCounter);
  67. QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
  68. counterPerMicrosecond = (double)frequency / 1000000.0f;
  69. startGetTickCount = UTGetTickCount64();
  70. }
  71. static int64 abs64(int64 x) { return x < 0 ? -x : x; }
  72. static uint64 __GetMicroseconds()
  73. {
  74. static bool time_init = false;
  75. if (!time_init) {
  76. time_init = true;
  77. Time_Initialize();
  78. }
  79. uint64 counter;
  80. uint64 tick;
  81. QueryPerformanceCounter((LARGE_INTEGER*) &counter);
  82. tick = UTGetTickCount64();
  83. // unfortunately, QueryPerformanceCounter is not guaranteed
  84. // to be monotonic. Make it so.
  85. int64 ret = (int64)(((int64)counter - (int64)startPerformanceCounter) / counterPerMicrosecond);
  86. // if the QPC clock leaps more than one second off GetTickCount64()
  87. // something is seriously fishy. Adjust QPC to stay monotonic
  88. int64 tick_diff = tick - startGetTickCount;
  89. if (abs64(ret / 100000 - tick_diff / 100) > 10) {
  90. startPerformanceCounter -= (uint64)((int64)(tick_diff * 1000 - ret) * counterPerMicrosecond);
  91. ret = (int64)((counter - startPerformanceCounter) / counterPerMicrosecond);
  92. }
  93. return ret;
  94. }
  95. static inline uint64 UTP_GetMilliseconds()
  96. {
  97. return GetTickCount();
  98. }
  99. #else //!WIN32
  100. static inline uint64 UTP_GetMicroseconds(void);
  101. static inline uint64 UTP_GetMilliseconds()
  102. {
  103. return UTP_GetMicroseconds() / 1000;
  104. }
  105. #if defined(__APPLE__)
  106. static uint64 __GetMicroseconds()
  107. {
  108. // http://developer.apple.com/mac/library/qa/qa2004/qa1398.html
  109. // http://www.macresearch.org/tutorial_performance_and_time
  110. static mach_timebase_info_data_t sTimebaseInfo;
  111. static uint64_t start_tick = 0;
  112. uint64_t tick;
  113. // Returns a counter in some fraction of a nanoseconds
  114. tick = mach_absolute_time();
  115. if (sTimebaseInfo.denom == 0) {
  116. // Get the timer ratio to convert mach_absolute_time to nanoseconds
  117. mach_timebase_info(&sTimebaseInfo);
  118. start_tick = tick;
  119. }
  120. // Calculate the elapsed time, convert it to microseconds and return it.
  121. return ((tick - start_tick) * sTimebaseInfo.numer) / (sTimebaseInfo.denom * 1000);
  122. }
  123. #else // !__APPLE__
  124. #if ! (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC))
  125. #warning "Using non-monotonic function gettimeofday() in UTP_GetMicroseconds()"
  126. #endif
  127. /* Unfortunately, #ifdef CLOCK_MONOTONIC is not enough to make sure that
  128. POSIX clocks work -- we could be running a recent libc with an ancient
  129. kernel (think OpenWRT). -- jch */
  130. static uint64_t __GetMicroseconds()
  131. {
  132. struct timeval tv;
  133. #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC)
  134. static int have_posix_clocks = -1;
  135. int rc;
  136. if (have_posix_clocks < 0) {
  137. struct timespec ts;
  138. rc = clock_gettime(CLOCK_MONOTONIC, &ts);
  139. if (rc < 0) {
  140. have_posix_clocks = 0;
  141. } else {
  142. have_posix_clocks = 1;
  143. }
  144. }
  145. if (have_posix_clocks) {
  146. struct timespec ts;
  147. rc = clock_gettime(CLOCK_MONOTONIC, &ts);
  148. return uint64(ts.tv_sec) * 1000000 + uint64(ts.tv_nsec) / 1000;
  149. }
  150. #endif
  151. gettimeofday(&tv, NULL);
  152. return uint64(tv.tv_sec) * 1000000 + tv.tv_usec;
  153. }
  154. #endif //!__APPLE__
  155. #endif //!WIN32
  156. /*
  157. * Whew. Okay. After that #ifdef maze above, we now know we have a working
  158. * __GetMicroseconds() implementation on all platforms.
  159. *
  160. * Because there are a number of assertions in libutp that will cause a crash
  161. * if monotonic time isn't monotonic, now apply some safety checks. While in
  162. * principle we're already protecting ourselves in cases where non-monotonic
  163. * time is likely to happen, this protects all versions.
  164. */
  165. static inline uint64 UTP_GetMicroseconds()
  166. {
  167. static uint64 offset = 0, previous = 0;
  168. uint64 now = __GetMicroseconds() + offset;
  169. if (previous > now) {
  170. /* Eek! */
  171. offset += previous - now;
  172. now = previous;
  173. }
  174. previous = now;
  175. return now;
  176. }
  177. #define ETHERNET_MTU 1500
  178. #define IPV4_HEADER_SIZE 20
  179. #define IPV6_HEADER_SIZE 40
  180. #define UDP_HEADER_SIZE 8
  181. #define GRE_HEADER_SIZE 24
  182. #define PPPOE_HEADER_SIZE 8
  183. #define MPPE_HEADER_SIZE 2
  184. // packets have been observed in the wild that were fragmented
  185. // with a payload of 1416 for the first fragment
  186. // There are reports of routers that have MTU sizes as small as 1392
  187. #define FUDGE_HEADER_SIZE 36
  188. #define TEREDO_MTU 1280
  189. #define UDP_IPV4_OVERHEAD (IPV4_HEADER_SIZE + UDP_HEADER_SIZE)
  190. #define UDP_IPV6_OVERHEAD (IPV6_HEADER_SIZE + UDP_HEADER_SIZE)
  191. #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)
  195. uint64 utp_default_get_udp_mtu(utp_callback_arguments *args) {
  196. // Since we don't know the local address of the interface,
  197. // be conservative and assume all IPv6 connections are Teredo.
  198. return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_MTU : UDP_IPV4_MTU;
  199. }
  200. uint64 utp_default_get_udp_overhead(utp_callback_arguments *args) {
  201. // Since we don't know the local address of the interface,
  202. // be conservative and assume all IPv6 connections are Teredo.
  203. return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_OVERHEAD : UDP_IPV4_OVERHEAD;
  204. }
  205. uint64 utp_default_get_random(utp_callback_arguments *args) {
  206. return rand();
  207. }
  208. uint64 utp_default_get_milliseconds(utp_callback_arguments *args) {
  209. return UTP_GetMilliseconds();
  210. }
  211. uint64 utp_default_get_microseconds(utp_callback_arguments *args) {
  212. return UTP_GetMicroseconds();
  213. }