diff --git a/libfreerdp/primitives/test/measure.h b/libfreerdp/primitives/test/measure.h index ee04abda9..2d4f36e97 100644 --- a/libfreerdp/primitives/test/measure.h +++ b/libfreerdp/primitives/test/measure.h @@ -29,6 +29,7 @@ #include #include +#include #ifndef _WIN32 #include @@ -69,28 +70,24 @@ #define PROFILER_STOP #endif // GOOGLE_PROFILER -extern float _delta_time(const struct timespec* t0, const struct timespec* t1); -extern void _floatprint(float t, char* output); +extern float measure_delta_time(UINT64 t0, UINT64 t1); +extern void measure_floatprint(float t, char* output); -#ifndef CLOCK_MONOTONIC_RAW -#define CLOCK_MONOTONIC_RAW 4 -#endif // !CLOCK_MONOTONIC_RAW - -#define MEASURE_LOOP_START(_prefix_, _count_) \ - { \ - struct timespec _start, _stop; \ - char* _prefix; \ - int _count = (_count_); \ - int _loop; \ - float _delta; \ - char _str1[32], _str2[32]; \ - _prefix = _strdup(_prefix_); \ - _str1[0] = '\0'; \ - _str2[0] = '\0'; \ - clock_gettime(CLOCK_MONOTONIC_RAW, &_start); \ - PROFILER_START(_prefix); \ - _loop = (_count); \ - do \ +#define MEASURE_LOOP_START(_prefix_, _count_) \ + { \ + UINT64 _start, _stop; \ + char* _prefix; \ + int _count = (_count_); \ + int _loop; \ + float _delta; \ + char _str1[32], _str2[32]; \ + _prefix = _strdup(_prefix_); \ + _str1[0] = '\0'; \ + _str2[0] = '\0'; \ + _start = winpr_GetTickCount64NS(); \ + PROFILER_START(_prefix); \ + _loop = (_count); \ + do \ { #define MEASURE_LOOP_STOP \ @@ -100,28 +97,28 @@ extern void _floatprint(float t, char* output); #define MEASURE_GET_RESULTS(_result_) \ PROFILER_STOP; \ - clock_gettime(CLOCK_MONOTONIC_RAW, &_stop); \ - _delta = _delta_time(&_start, &_stop); \ + _stop = winpr_GetTickCount64NS(); \ + _delta = measure_delta_time(_start, _stop); \ (_result_) = (float)_count / _delta; \ free(_prefix); \ } #define MEASURE_SHOW_RESULTS(_result_) \ PROFILER_STOP; \ - clock_gettime(CLOCK_MONOTONIC_RAW, &_stop); \ - _delta = _delta_time(&_start, &_stop); \ + _stop = winpr_GetTickCount64NS(); \ + _delta = measure_delta_time(_start, _stop); \ (_result_) = (float)_count / _delta; \ - _floatprint((float)_count / _delta, _str1); \ + measure_floatprint((float)_count / _delta, _str1); \ printf("%s: %9d iterations in %5.1f seconds = %s/s \n", _prefix, _count, _delta, _str1); \ free(_prefix); \ } #define MEASURE_SHOW_RESULTS_SCALED(_scale_, _label_) \ PROFILER_STOP; \ - clock_gettime(CLOCK_MONOTONIC_RAW, &_stop); \ - _delta = _delta_time(&_start, &_stop); \ - _floatprint((float)_count / _delta, _str1); \ - _floatprint((float)_count / _delta * (_scale_), _str2); \ + _stop = winpr_GetTickCount64NS(); \ + _delta = measure_delta_time(_start, _stop); \ + measure_floatprint((float)_count / _delta, _str1); \ + measure_floatprint((float)_count / _delta * (_scale_), _str2); \ printf("%s: %9d iterations in %5.1f seconds = %s/s = %s%s \n", _prefix, _count, _delta, _str1, \ _str2, _label_); \ free(_prefix); \ diff --git a/libfreerdp/primitives/test/prim_test.c b/libfreerdp/primitives/test/prim_test.c index ede831625..5ec85f85e 100644 --- a/libfreerdp/primitives/test/prim_test.c +++ b/libfreerdp/primitives/test/prim_test.c @@ -36,31 +36,15 @@ int test_sizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; /* ------------------------------------------------------------------------- */ -#ifdef _WIN32 -float _delta_time(const struct timespec* t0, const struct timespec* t1) +float measure_delta_time(UINT64 t0, UINT64 t1) { - return 0.0f; + INT64 diff = (INT64)(t1 - t0); + double retval = diff / 1000000000.0; + return (retval < 0.0) ? 0.0f : (float)retval; } -#else -float _delta_time(const struct timespec* t0, const struct timespec* t1) -{ - INT64 secs = (INT64)(t1->tv_sec) - (INT64)(t0->tv_sec); - long nsecs = t1->tv_nsec - t0->tv_nsec; - double retval = NAN; - - if (nsecs < 0) - { - --secs; - nsecs += 1000000000; - } - - retval = (double)secs + (double)nsecs / (double)1000000000.0; - return (retval < 0.0) ? 0.0 : (float)retval; -} -#endif /* ------------------------------------------------------------------------- */ -void _floatprint(float t, char* output) +void measure_floatprint(float t, char* output) { /* I don't want to link against -lm, so avoid log,exp,... */ float f = 10.0; diff --git a/libfreerdp/utils/pcap.c b/libfreerdp/utils/pcap.c index db5090901..c18caf296 100644 --- a/libfreerdp/utils/pcap.c +++ b/libfreerdp/utils/pcap.c @@ -27,27 +27,11 @@ #include #include #include +#include #include #define TAG FREERDP_TAG("utils") -#ifndef _WIN32 -#include -#else -#include -#include -#include - -int gettimeofday(struct timeval* tp, void* tz) -{ - struct _timeb timebuffer; - _ftime(&timebuffer); - tp->tv_sec = (long)timebuffer.time; - tp->tv_usec = timebuffer.millitm * 1000; - return 0; -} -#endif - #include #include @@ -131,14 +115,11 @@ static BOOL pcap_write_record(rdpPcap* pcap, const pcap_record* record) BOOL pcap_add_record(rdpPcap* pcap, const void* data, size_t length) { - pcap_record* record = NULL; - struct timeval tp; - WINPR_ASSERT(pcap); WINPR_ASSERT(data || (length == 0)); WINPR_ASSERT(length <= UINT32_MAX); - record = (pcap_record*)calloc(1, sizeof(pcap_record)); + pcap_record* record = (pcap_record*)calloc(1, sizeof(pcap_record)); if (!record) return FALSE; @@ -147,9 +128,10 @@ BOOL pcap_add_record(rdpPcap* pcap, const void* data, size_t length) record->header.incl_len = (UINT32)length; record->header.orig_len = (UINT32)length; - gettimeofday(&tp, 0); - record->header.ts_sec = (UINT32)tp.tv_sec; - record->header.ts_usec = (UINT32)tp.tv_usec; + const UINT64 ns = winpr_GetUnixTimeNS(); + + record->header.ts_sec = WINPR_TIME_NS_TO_S(ns); + record->header.ts_usec = WINPR_TIME_NS_REM_US(ns); if (pcap->tail == NULL) { diff --git a/libfreerdp/utils/stopwatch.c b/libfreerdp/utils/stopwatch.c index 39896385d..70b60b3b4 100644 --- a/libfreerdp/utils/stopwatch.c +++ b/libfreerdp/utils/stopwatch.c @@ -22,38 +22,18 @@ #include #include +#include #include -#ifdef _WIN32 -LARGE_INTEGER stopwatch_freq = { 0 }; -#else -#include -#endif - static void stopwatch_set_time(UINT64* usecs) { -#ifdef _WIN32 - LARGE_INTEGER perfcount; - QueryPerformanceCounter(&perfcount); - *usecs = (perfcount.QuadPart * 1000000) / stopwatch_freq.QuadPart; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - *usecs = tv.tv_sec * 1000000 + tv.tv_usec; -#endif + const UINT64 ns = winpr_GetTickCount64NS(); + *usecs = WINPR_TIME_NS_TO_US(ns); } STOPWATCH* stopwatch_create(void) { - STOPWATCH* sw = NULL; -#ifdef _WIN32 - if (stopwatch_freq.QuadPart == 0) - { - QueryPerformanceFrequency(&stopwatch_freq); - } -#endif - - sw = (STOPWATCH*)malloc(sizeof(STOPWATCH)); + STOPWATCH* sw = (STOPWATCH*)calloc(1, sizeof(STOPWATCH)); if (!sw) return NULL; stopwatch_reset(sw); diff --git a/winpr/include/winpr/sysinfo.h b/winpr/include/winpr/sysinfo.h index d7d6dd8fc..61fadc317 100644 --- a/winpr/include/winpr/sysinfo.h +++ b/winpr/include/winpr/sysinfo.h @@ -322,6 +322,17 @@ extern "C" #endif +#define WINPR_TIME_NS_TO_S(ns) ((ns) / 1000000000ull) +#define WINPR_TIME_NS_TO_MS(ns) ((ns) / 1000000ull) +#define WINPR_TIME_NS_TO_US(ns) ((ns) / 1000ull) + +#define WINPR_TIME_NS_REM_NS(ns) ((ns) % 1000000000ull) +#define WINPR_TIME_NS_REM_US(ns) (WINPR_TIME_NS_REM_NS(ns) / 1000ull) +#define WINPR_TIME_NS_REM_MS(ns) (WINPR_TIME_NS_REM_US(ns) / 1000ull) + + WINPR_API UINT64 winpr_GetTickCount64NS(void); + WINPR_API UINT64 winpr_GetUnixTimeNS(void); + WINPR_API DWORD GetTickCountPrecise(void); WINPR_API BOOL IsProcessorFeaturePresentEx(DWORD ProcessorFeature); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index 9c6e81890..69970c85c 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -248,15 +248,12 @@ BOOL ntlm_write_ntlm_v2_response(wStream* s, const NTLMv2_RESPONSE* response) void ntlm_current_time(BYTE* timestamp) { - FILETIME filetime = { 0 }; - ULARGE_INTEGER time64 = { 0 }; + FILETIME ft = { 0 }; WINPR_ASSERT(timestamp); - GetSystemTimeAsFileTime(&filetime); - time64.u.LowPart = filetime.dwLowDateTime; - time64.u.HighPart = filetime.dwHighDateTime; - CopyMemory(timestamp, &(time64.QuadPart), 8); + GetSystemTimeAsFileTime(&ft); + CopyMemory(timestamp, &(ft), sizeof(ft)); } /** diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index 8238a88e7..6296c6b62 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -707,11 +707,11 @@ static void timespec_add_ms(struct timespec* tspec, UINT32 ms) static void timespec_gettimeofday(struct timespec* tspec) { - struct timeval tval; WINPR_ASSERT(tspec); - gettimeofday(&tval, NULL); - tspec->tv_sec = tval.tv_sec; - tspec->tv_nsec = tval.tv_usec * 1000; + + const UINT64 ns = winpr_GetUnixTimeNS(); + tspec->tv_sec = WINPR_TIME_NS_TO_S(ns); + tspec->tv_nsec = WINPR_TIME_NS_REM_NS(ns); } static INT64 timespec_compare(const struct timespec* tspec1, const struct timespec* tspec2) diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index 3bef657a2..865f58338 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -59,60 +59,16 @@ #include "../pipe/pipe.h" -/* clock_gettime is not implemented on OSX prior to 10.12 */ -#if defined(__MACH__) && defined(__APPLE__) - -#include - -#ifndef CLOCK_REALTIME -#define CLOCK_REALTIME 0 -#endif - -#ifndef CLOCK_MONOTONIC -#define CLOCK_MONOTONIC 0 -#endif - -/* clock_gettime is not implemented on OSX prior to 10.12 */ -int _mach_clock_gettime(int clk_id, struct timespec* t); - -int _mach_clock_gettime(int clk_id, struct timespec* t) +static struct timespec ts_from_ns(void) { - UINT64 time = 0; - double seconds = 0.0; - double nseconds = 0.0; - mach_timebase_info_data_t timebase = { 0 }; - mach_timebase_info(&timebase); - time = mach_absolute_time(); - nseconds = ((double)time * (double)timebase.numer) / ((double)timebase.denom); - seconds = ((double)time * (double)timebase.numer) / ((double)timebase.denom * 1e9); - t->tv_sec = seconds; - t->tv_nsec = nseconds; - return 0; + const UINT64 ns = winpr_GetUnixTimeNS(); + struct timespec timeout = { 0 }; + timeout.tv_sec = WINPR_TIME_NS_TO_S(ns); + timeout.tv_nsec = WINPR_TIME_NS_REM_NS(ns); + ; + return timeout; } -/* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */ -#ifdef __CLOCK_AVAILABILITY -/* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be declared - * * but it may be NULL at runtime. So we need to check before using it. */ -int _mach_safe_clock_gettime(int clk_id, struct timespec* t); - -int _mach_safe_clock_gettime(int clk_id, struct timespec* t) -{ - if (clock_gettime) - { - return clock_gettime(clk_id, t); - } - - return _mach_clock_gettime(clk_id, t); -} - -#define clock_gettime _mach_safe_clock_gettime -#else -#define clock_gettime _mach_clock_gettime -#endif - -#endif - /** * Drop in replacement for pthread_mutex_timedlock * http://code.google.com/p/android/issues/detail?id=7807 @@ -148,14 +104,14 @@ STATIC_NEEDED int pthread_mutex_timedlock(pthread_mutex_t* mutex, unsigned long long diff = 0; int retcode = -1; /* This is just to avoid a completely busy wait */ - clock_gettime(CLOCK_MONOTONIC, &timenow); + timenow = ts_from_ns(); diff = ts_difftime(&timenow, timeout); sleepytime.tv_sec = diff / 1000000000LL; sleepytime.tv_nsec = diff % 1000000000LL; while ((retcode = pthread_mutex_trylock(mutex)) == EBUSY) { - clock_gettime(CLOCK_MONOTONIC, &timenow); + timenow = ts_from_ns(); if (ts_difftime(timeout, &timenow) >= 0) { @@ -237,8 +193,8 @@ DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertabl if (dwMilliseconds != INFINITE) { int status = 0; - struct timespec timeout = { 0 }; - clock_gettime(CLOCK_MONOTONIC, &timeout); + struct timespec timeout = ts_from_ns(); + ts_add_ms(&timeout, dwMilliseconds); status = pthread_mutex_timedlock(&mutex->mutex, &timeout); diff --git a/winpr/libwinpr/sysinfo/sysinfo.c b/winpr/libwinpr/sysinfo/sysinfo.c index f12f4eb9b..d8e4d7c1c 100644 --- a/winpr/libwinpr/sysinfo/sysinfo.c +++ b/winpr/libwinpr/sysinfo/sysinfo.c @@ -33,9 +33,43 @@ #include #endif +#if !defined(_WIN32) +#if defined(_POSIX_SOURCE) && (_POSIX_C_SOURCE >= 200112L) +#include +#elif !defined(__APPLE__) +#include +#include +#endif +#endif + #include "../log.h" #define TAG WINPR_TAG("sysinfo") +#define FILETIME_TO_UNIX_OFFSET_S 11644473600UL + +#if defined(__MACH__) && defined(__APPLE__) + +#include + +static UINT64 scaleHighPrecision(UINT64 i, UINT32 numer, UINT32 denom) +{ + UINT64 high = (i >> 32) * numer; + UINT64 low = (i & 0xffffffffull) * numer / denom; + UINT64 highRem = ((high % denom) << 32) / denom; + high /= denom; + return (high << 32) + highRem + low; +} + +static UINT64 mac_get_time_ns(void) +{ + mach_timebase_info_data_t timebase = { 0 }; + mach_timebase_info(&timebase); + UINT64 t = mach_absolute_time(); + return scaleHighPrecision(t, timebase.numer, timebase.denom); +} + +#endif + /** * api-ms-win-core-sysinfo-l1-1-1.dll: * @@ -272,13 +306,14 @@ BOOL SetLocalTime(CONST SYSTEMTIME* lpSystemTime) VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { - ULARGE_INTEGER time64; - time64.u.HighPart = 0; - /* time represented in tenths of microseconds since midnight of January 1, 1601 */ - time64.QuadPart = time(NULL) + 11644473600LL; /* Seconds since January 1, 1601 */ - time64.QuadPart *= 10000000; /* Convert timestamp to tenths of a microsecond */ - lpSystemTimeAsFileTime->dwLowDateTime = time64.u.LowPart; - lpSystemTimeAsFileTime->dwHighDateTime = time64.u.HighPart; + union + { + UINT64 u64; + FILETIME ft; + } t; + + t.u64 = (winpr_GetUnixTimeNS() / 100ull) + FILETIME_TO_UNIX_OFFSET_S * 10000000ull; + *lpSystemTimeAsFileTime = t.ft; } BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, @@ -294,25 +329,7 @@ BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, DWORD GetTickCount(void) { - DWORD ticks = 0; -#ifdef __linux__ - struct timespec ts; - - if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) - ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); - -#else - /** - * FIXME: this is relative to the Epoch time, and we - * need to return a value relative to the system uptime. - */ - struct timeval tv; - - if (!gettimeofday(&tv, NULL)) - ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - -#endif - return ticks; + return GetTickCount64(); } #endif // _WIN32 @@ -553,35 +570,80 @@ DWORD GetTickCount(void) ULONGLONG winpr_GetTickCount64(void) { - ULONGLONG ticks = 0; -#if defined(__linux__) - struct timespec ts; + const UINT64 ns = winpr_GetTickCount64NS(); + return WINPR_TIME_NS_TO_MS(ns); +} - if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) - ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); +#endif +UINT64 winpr_GetTickCount64NS(void) +{ + UINT64 ticks = 0; +#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) + struct timespec ts = { 0 }; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0) + ticks = (ts.tv_sec * 1000000000ull) + ts.tv_nsec; +#elif defined(__MACH__) && defined(__APPLE__) + ticks = mac_get_time_ns(); #elif defined(_WIN32) - FILETIME ft; - ULARGE_INTEGER ul; - GetSystemTimeAsFileTime(&ft); - ul.LowPart = ft.dwLowDateTime; - ul.HighPart = ft.dwHighDateTime; - ticks = ul.QuadPart; + LARGE_INTEGER li = { 0 }; + LARGE_INTEGER freq = { 0 }; + if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&li)) + ticks = li.QuadPart * 1000000000ull / freq.QuadPart; #else - /** - * FIXME: this is relative to the Epoch time, and we - * need to return a value relative to the system uptime. + struct timeval tv = { 0 }; + + if (gettimeofday(&tv, NULL) == 0) + ticks = (tv.tv_sec * 1000000000ull) + (tv.tv_usec * 1000ull); + + /* We need to trick here: + * this function should return the system uptime, but we need higher resolution. + * so on first call get the actual timestamp along with the system uptime. + * + * return the uptime measured from now on (e.g. current measure - first measure + uptime at + * first measure) */ - struct timeval tv; - - if (!gettimeofday(&tv, NULL)) - ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + static UINT64 first = 0; + static UINT64 uptime = 0; + if (first == 0) + { + struct sysinfo info = { 0 }; + if (sysinfo(&info) == 0) + { + first = ticks; + uptime = 1000000000ull * info.uptime; + } + } + ticks = ticks - first + uptime; #endif return ticks; } +UINT64 winpr_GetUnixTimeNS(void) +{ +#if defined(_WIN32) + + union + { + UINT64 u64; + FILETIME ft; + } t = { 0 }; + GetSystemTimeAsFileTime(&t.ft); + return (t.u64 - FILETIME_TO_UNIX_OFFSET_S * 10000000ull) * 100ull; +#elif _POSIX_C_SOURCE >= 200112L + struct timespec ts = { 0 }; + if (clock_gettime(CLOCK_REALTIME, &ts) != 0) + return 0; + return ts.tv_sec * 1000000000ull + ts.tv_nsec; +#else + struct timeval tv = { 0 }; + if (gettimeofday(&tv, NULL) != 0) + return 0; + return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ull; #endif +} /* If x86 */ #ifdef _M_IX86_AMD64 diff --git a/winpr/libwinpr/utils/wlog/PacketMessage.c b/winpr/libwinpr/utils/wlog/PacketMessage.c index cc1c812a8..17df1ece6 100644 --- a/winpr/libwinpr/utils/wlog/PacketMessage.c +++ b/winpr/libwinpr/utils/wlog/PacketMessage.c @@ -29,27 +29,11 @@ #include #include #include +#include #include "../../log.h" #define TAG WINPR_TAG("utils.wlog") -#ifndef _WIN32 -#include -#else -#include -#include -#include - -static int gettimeofday(struct timeval* tp, void* tz) -{ - struct _timeb timebuffer; - _ftime(&timebuffer); - tp->tv_sec = (long)timebuffer.time; - tp->tv_usec = timebuffer.millitm * 1000; - return 0; -} -#endif - static BOOL Pcap_Read_Header(wPcap* pcap, wPcapHeader* header) { if (pcap && pcap->fp && fread((void*)header, sizeof(wPcapHeader), 1, pcap->fp) == 1) @@ -89,8 +73,7 @@ static BOOL Pcap_Read_Record(wPcap* pcap, wPcapRecord* record) static BOOL Pcap_Add_Record(wPcap* pcap, void* data, UINT32 length) { - wPcapRecord* record; - struct timeval tp; + wPcapRecord* record = NULL; if (!pcap->tail) { @@ -117,9 +100,10 @@ static BOOL Pcap_Add_Record(wPcap* pcap, void* data, UINT32 length) record->length = length; record->header.incl_len = length; record->header.orig_len = length; - gettimeofday(&tp, 0); - record->header.ts_sec = tp.tv_sec; - record->header.ts_usec = tp.tv_usec; + + UINT64 ns = winpr_GetUnixTimeNS(); + record->header.ts_sec = WINPR_TIME_NS_TO_S(ns); + record->header.ts_usec = WINPR_TIME_NS_REM_US(ns); return TRUE; } @@ -380,7 +364,6 @@ BOOL WLog_PacketMessage_Write(wPcap* pcap, void* data, size_t length, DWORD flag { wTcpHeader tcp; wIPv4Header ipv4; - struct timeval tp; wPcapRecord record; wEthernetHeader ethernet; ethernet.Type = 0x0800; @@ -474,9 +457,11 @@ BOOL WLog_PacketMessage_Write(wPcap* pcap, void* data, size_t length, DWORD flag record.header.incl_len = (UINT32)record.length + offset; record.header.orig_len = (UINT32)record.length + offset; record.next = NULL; - gettimeofday(&tp, 0); - record.header.ts_sec = tp.tv_sec; - record.header.ts_usec = tp.tv_usec; + + UINT64 ns = winpr_GetUnixTimeNS(); + record.header.ts_sec = WINPR_TIME_NS_TO_S(ns); + record.header.ts_usec = WINPR_TIME_NS_REM_US(ns); + if (!Pcap_Write_RecordHeader(pcap, &record.header) || !WLog_PacketMessage_Write_EthernetHeader(pcap, ðernet) || !WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||