summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/StackWalker.cpp8
-rw-r--r--indra/llcommon/always_return.h16
-rw-r--r--indra/llcommon/llexception.cpp44
-rw-r--r--indra/llcommon/llexception.h114
-rw-r--r--indra/llcommon/llfasttimer.h8
-rw-r--r--indra/llcommon/llpreprocessor.h4
-rw-r--r--indra/llcommon/llprocessor.cpp31
-rw-r--r--indra/llcommon/llsdjson.cpp4
-rw-r--r--indra/llcommon/llstring.cpp2
-rw-r--r--indra/llcommon/llstring.h4
-rw-r--r--indra/llcommon/llthread.cpp105
-rw-r--r--indra/llcommon/llthread.h7
-rw-r--r--indra/llcommon/llwin32headers.h1
14 files changed, 175 insertions, 175 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 6c1e1ef64a..e8c51c4c8e 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -297,6 +297,8 @@ if (CMAKE_OSX_ARCHITECTURES MATCHES arm64 OR CMAKE_SYSTEM_PROCESSOR MATCHES aarc
file(WRITE ${PREBUILD_TRACKING_DIR}/sse2neon_installed "0")
endif ()
target_include_directories(llcommon PUBLIC ${LIBS_PREBUILT_DIR}/include/sse2neon)
+elseif ($ENV{MSYSTEM_CARCH} MATCHES aarch64)
+ target_include_directories(llcommon PUBLIC ${prefix_result}/../include/sse2neon)
endif ()
if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu) OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed))
diff --git a/indra/llcommon/StackWalker.cpp b/indra/llcommon/StackWalker.cpp
index e9ae1723fb..027df80df5 100644
--- a/indra/llcommon/StackWalker.cpp
+++ b/indra/llcommon/StackWalker.cpp
@@ -1100,6 +1100,14 @@ bool StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *con
s.AddrBStore.Mode = AddrModeFlat;
s.AddrStack.Offset = c.IntSp;
s.AddrStack.Mode = AddrModeFlat;
+#elif _M_ARM64
+ imageType = IMAGE_FILE_MACHINE_ARM64;
+ s.AddrPC.Offset = c.Pc;
+ s.AddrPC.Mode = AddrModeFlat;
+ s.AddrFrame.Offset = c.Fp;
+ s.AddrFrame.Mode = AddrModeFlat;
+ s.AddrStack.Offset = c.Sp;
+ s.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif
diff --git a/indra/llcommon/always_return.h b/indra/llcommon/always_return.h
index b99eb49096..a206471da5 100644
--- a/indra/llcommon/always_return.h
+++ b/indra/llcommon/always_return.h
@@ -79,22 +79,6 @@ namespace LL
DESIRED mDefault;
};
- // specialize for AlwaysReturn<void>
- template <>
- struct AlwaysReturn<void>
- {
- public:
- AlwaysReturn() {}
-
- // callable returns a type not convertible to DESIRED, return default
- template <typename CALLABLE, typename... ARGS>
- void operator()(CALLABLE&& callable, ARGS&&... args)
- {
- // discard whatever callable(args) returns
- std::forward<CALLABLE>(callable)(std::forward<ARGS>(args)...);
- }
- };
-
/**
* always_return<T>(some_function, some_args...) calls
* some_function(some_args...). It is guaranteed to return a value of type
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index 107fdc2b2d..c0154a569f 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -15,12 +15,7 @@
#include "llexception.h"
// STL headers
// std headers
-#include <iomanip>
-#include <sstream>
#include <typeinfo>
-#if LL_WINDOWS
-#include <excpt.h>
-#endif // LL_WINDOWS
// external library headers
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception/error_info.hpp>
@@ -34,6 +29,7 @@
// On Windows, header-only implementation causes macro collisions -- use
// prebuilt library
#define BOOST_STACKTRACE_LINK
+#include <excpt.h>
#endif // LL_WINDOWS
#include <boost/stacktrace.hpp>
@@ -98,47 +94,25 @@ void annotate_exception_(boost::exception& exc)
// For windows SEH exception handling we sometimes need a filter that will
// separate C++ exceptions from C SEH exceptions
-static constexpr U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-static constexpr U32 STATUS_STACK_FULL = 0xC00000FD;
+static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-void LL::seh::fill_stacktrace(std::string& stacktrace, U32 code)
+U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
- // Sadly, despite its diagnostic importance, trying to capture a
- // stacktrace when the stack is already blown only terminates us faster.
- if (code == STATUS_STACK_FULL)
- {
- stacktrace = "(stack overflow, no traceback)";
- }
- else
- {
- stacktrace = to_string(boost::stacktrace::stacktrace());
- }
-}
+ const auto stack = to_string(boost::stacktrace::stacktrace());
+ LL_WARNS() << "SEH Exception handled (that probably shouldn't be): Code " << code
+ << "\n Stack trace: \n"
+ << stack << LL_ENDL;
-U32 LL::seh::common_filter(U32 code, struct _EXCEPTION_POINTERS*)
-{
if (code == STATUS_MSC_EXCEPTION)
{
- // C++ exception, don't stop at this handler
+ // C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
- // This is a non-C++ exception, e.g. hardware check.
- // Pass control into the handler block.
+ // handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
-void LL::seh::rethrow(U32 code, const std::string& stacktrace)
-{
- std::ostringstream out;
- out << "Windows exception 0x" << std::hex << code;
- if (! stacktrace.empty())
- {
- out << '\n' << stacktrace;
- }
- LLTHROW(Windows_SEH_exception(out.str()));
-}
-
#endif //LL_WINDOWS
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index f58a553eb3..68e609444e 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -12,7 +12,6 @@
#if ! defined(LL_LLEXCEPTION_H)
#define LL_LLEXCEPTION_H
-#include "always_return.h"
#include <stdexcept>
#include <boost/exception/exception.hpp>
#include <boost/throw_exception.hpp>
@@ -103,115 +102,14 @@ void crash_on_unhandled_exception_(const char*, int, const char*, const std::str
log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
void log_unhandled_exception_(const char*, int, const char*, const std::string&);
-/*****************************************************************************
-* Structured Exception Handling
-*****************************************************************************/
-// this is used in platform-generic code -- define outside #if LL_WINDOWS
-struct Windows_SEH_exception: public LLException
-{
- Windows_SEH_exception(const std::string& what): LLException(what) {}
-};
-
-namespace LL
-{
-namespace seh
-{
-
-#if LL_WINDOWS //-------------------------------------------------------------
-
-void fill_stacktrace(std::string& stacktrace, U32 code);
-
-// wrapper around caller's U32 filter(U32 code, struct _EXCEPTION_POINTERS*)
-// filter function: capture a stacktrace, if possible, before forwarding the
-// call to the caller's filter() function
-template <typename FILTER>
-U32 filter_(std::string& stacktrace, FILTER&& filter,
- U32 code, struct _EXCEPTION_POINTERS* exptrs)
-{
- // By the time the handler gets control, the stack has been unwound,
- // so report the stack trace now at filter() time.
- fill_stacktrace(stacktrace, code);
- return std::forward<FILTER>(filter)(code, exptrs);
-}
-
-template <typename TRYCODE, typename FILTER, typename HANDLER>
-auto catcher_inner(std::string& stacktrace,
- TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler)
-{
- __try
- {
- return std::forward<TRYCODE>(trycode)();
- }
- __except (filter_(stacktrace,
- std::forward<FILTER>(filter),
- GetExceptionCode(), GetExceptionInformation()))
- {
- return always_return<decltype(trycode())>(
- std::forward<HANDLER>(handler), GetExceptionCode(), stacktrace);
- }
-}
-
-// triadic variant specifies try(), filter(U32, struct _EXCEPTION_POINTERS*),
-// handler(U32, const std::string& stacktrace)
-// stacktrace may or may not be available
-template <typename TRYCODE, typename FILTER, typename HANDLER>
-auto catcher(TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler)
-{
- // Construct and destroy this stacktrace string in the outer function
- // because we can't do either in the function with __try/__except.
- std::string stacktrace;
- return catcher_inner(stacktrace,
- std::forward<TRYCODE>(trycode),
- std::forward<FILTER>(filter),
- std::forward<HANDLER>(handler));
-}
-// common_filter() handles the typical case in which we want our handler
-// clause to handle only Structured Exceptions rather than explicitly-thrown
-// C++ exceptions
-U32 common_filter(U32 code, struct _EXCEPTION_POINTERS*);
-
-// dyadic variant specifies try(), handler(U32, stacktrace), assumes common_filter()
-template <typename TRYCODE, typename HANDLER>
-auto catcher(TRYCODE&& trycode, HANDLER&& handler)
-{
- return catcher(std::forward<TRYCODE>(trycode),
- common_filter,
- std::forward<HANDLER>(handler));
-}
-
-// monadic variant specifies try(), assumes default filter and handler
-template <typename TRYCODE>
-auto catcher(TRYCODE&& trycode)
-{
- return catcher(std::forward<TRYCODE>(trycode), rethrow);
-}
-
-[[noreturn]] void rethrow(U32 code, const std::string& stacktrace);
-
-#else // not LL_WINDOWS -----------------------------------------------------
-
-template <typename TRYCODE, typename FILTER, typename HANDLER>
-auto catcher(TRYCODE&& trycode, FILTER&&, HANDLER&&)
-{
- return std::forward<TRYCODE>(trycode)();
-}
-
-template <typename TRYCODE, typename HANDLER>
-auto catcher(TRYCODE&& trycode, HANDLER&&)
-{
- return std::forward<TRYCODE>(trycode)();
-}
-
-template <typename TRYCODE>
-auto catcher(TRYCODE&& trycode)
-{
- return std::forward<TRYCODE>(trycode)();
-}
+#if LL_WINDOWS
-#endif // not LL_WINDOWS -----------------------------------------------------
+// SEH exception filtering for use in __try __except
+// Separates C++ exceptions from C SEH exceptions
+// Todo: might be good idea to do some kind of seh_to_msc_wrapper(function, ARGS&&);
+U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop);
-} // namespace LL::seh
-} // namespace LL
+#endif //LL_WINDOWS
#endif /* ! defined(LL_LLEXCEPTION_H) */
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index a69a03e419..8499655bfa 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -99,7 +99,11 @@ public:
#if LL_FASTTIMER_USE_RDTSC
static U32 getCPUClockCount32()
{
+#if _M_ARM64
+ unsigned __int64 val = _ReadStatusReg(ARM64_PMCCNTR_EL0);
+#else
unsigned __int64 val = __rdtsc();
+#endif
val = val >> 8;
return static_cast<U32>(val);
}
@@ -107,7 +111,11 @@ public:
// return full timer value, *not* shifted by 8 bits
static U64 getCPUClockCount64()
{
+#if _M_ARM64
+ return static_cast<U64>( _ReadStatusReg(ARM64_PMCCNTR_EL0) );
+#else
return static_cast<U64>( __rdtsc() );
+#endif
}
#else
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index e9f07f6fdf..268109e8b7 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -169,7 +169,11 @@
#define LL_TO_STRING_HELPER(x) #x
#define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
+#if _M_ARM64
+#define LL_TO_WSTRING_HELPER(x) L## #x
+#else
#define LL_TO_WSTRING_HELPER(x) L#x
+#endif
#define LL_TO_WSTRING(x) LL_TO_WSTRING_HELPER(x)
#define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
#define LL_GLUE_IMPL(x, y) x##y
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 9b3cdf4df5..c0b1a5c9e3 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -439,13 +439,21 @@ static F64 calculate_cpu_frequency(U32 measure_msecs)
//// completed now (serialization)
//__asm cpuid
int cpu_info[4] = {-1};
+#if _M_ARM64
+ std::fill(cpu_info, cpu_info + 4, 0);
+#else
__cpuid(cpu_info, 0);
+#endif
// We ask the high-res timer for the start time
QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
// Then we get the current cpu clock and store it
+#if _M_ARM64
+ start = _ReadStatusReg(ARM64_PMCCNTR_EL0);
+#else
start = __rdtsc();
+#endif
// Now we wart for some msecs
_Delay(measure_msecs);
@@ -455,7 +463,11 @@ static F64 calculate_cpu_frequency(U32 measure_msecs)
QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
// And also for the end cpu clock
+#if _M_ARM64
+ end = _ReadStatusReg(ARM64_PMCCNTR_EL0);
+#else
end = __rdtsc();
+#endif
// Now we can restore the default process and thread priorities
SetProcessAffinityMask(hProcess, dwProcessMask);
@@ -495,17 +507,21 @@ private:
// the other three array elements. The CPU identification string is
// not in linear order. The code below arranges the information
// in a human readable form.
+#if !_M_ARM64
int cpu_info[4] = {-1};
__cpuid(cpu_info, 0);
unsigned int ids = (unsigned int)cpu_info[0];
setConfig(eMaxID, (S32)ids);
+#endif
char cpu_vendor[0x20];
memset(cpu_vendor, 0, sizeof(cpu_vendor));
+#if !_M_ARM64
*((int*)cpu_vendor) = cpu_info[1];
*((int*)(cpu_vendor+4)) = cpu_info[3];
*((int*)(cpu_vendor+8)) = cpu_info[2];
setInfo(eVendor, cpu_vendor);
+#endif
std::string cmp_vendor(cpu_vendor);
bool is_amd = false;
if (cmp_vendor == "AuthenticAMD")
@@ -513,6 +529,20 @@ private:
is_amd = true;
}
+#if _M_ARM64
+ HKEY hKey;
+ DWORD gotType;
+ char inBuffer[48] = "";
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+ {
+ if (!RegQueryValueExA(hKey, "ProcessorNameString", nullptr, &gotType, (PBYTE)(inBuffer), nullptr))
+ {
+ if ((gotType == REG_SZ) && strlen(inBuffer))
+ setInfo(eModel, inBuffer);
+ }
+ RegCloseKey(hKey);
+ }
+#else
// Get the information associated with each valid Id
for(unsigned int i=0; i<=ids; ++i)
{
@@ -623,6 +653,7 @@ private:
setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff);
}
}
+#endif
}
};
diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp
index 655869a704..a4b45ed80d 100644
--- a/indra/llcommon/llsdjson.cpp
+++ b/indra/llcommon/llsdjson.cpp
@@ -35,7 +35,11 @@
#include "llerror.h"
#include "../llmath/llmath.h"
+#if LL_WINDOWS
+#include <boost/json.hpp>
+#else
#include <boost/json/src.hpp>
+#endif
//=========================================================================
LLSD LlsdFromJson(const boost::json::value& val)
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 07adf71d18..bb6d091a97 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -260,7 +260,7 @@ S32 utf16str_wstring_length(const llutf16string &utf16str, const S32 utf16_len)
{
S32 surrogate_pairs = 0;
// ... craziness to make gcc happy (llutf16string.c_str() is tweaked on linux):
- const U16 *const utf16_chars = &(*(utf16str.begin()));
+ const auto *const utf16_chars = &(*(utf16str.begin()));
S32 i = 0;
while (i < utf16_len)
{
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 7a8edc176d..2e579a4d2d 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -635,7 +635,11 @@ LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
//
// This typedef may or may not be identical to std::wstring, depending on
// LL_WCHAR_T_NATIVE.
+#if __FreeBSD__
+typedef std::basic_string<char16_t> llutf16string;
+#else
typedef std::basic_string<U16> llutf16string;
+#endif
// Considering wchar_t, llwchar and U16, there are three relevant cases:
#if LLWCHAR_IS_WCHAR_T // every which way but Windows
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index e5d25b52f0..692941a892 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -28,6 +28,7 @@
#include "apr_portable.h"
+#include "llapp.h"
#include "llthread.h"
#include "llmutex.h"
@@ -35,6 +36,7 @@
#include "lltrace.h"
#include "lltracethreadrecorder.h"
#include "llexception.h"
+#include "workqueue.h"
#if LL_LINUX
#include <sched.h>
@@ -106,6 +108,27 @@ namespace
return s_thread_id;
}
+#if LL_WINDOWS
+
+ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
+
+ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
+ {
+ if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
+ {
+ // Handled
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (code == STATUS_MSC_EXCEPTION)
+ {
+ // C++ exception, go on
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // handle it, convert to std::exception
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+#endif // LL_WINDOWS
} // anonymous namespace
LL_COMMON_API bool on_main_thread()
@@ -157,20 +180,11 @@ void LLThread::threadRun()
// Run the user supplied function
do
{
- try
- {
- run();
- }
- catch (const LLContinueError &e)
- {
- LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
- "' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
- //output possible call stacks to log file.
- LLError::LLCallStacks::print();
-
- LOG_UNHANDLED_EXCEPTION("LLThread");
- continue;
- }
+#ifdef LL_WINDOWS
+ sehHandle(); // Structured Exception Handling
+#else
+ tryRun();
+#endif
break;
} while (true);
@@ -188,6 +202,69 @@ void LLThread::threadRun()
mStatus = STOPPED;
}
+void LLThread::tryRun()
+{
+ try
+ {
+ run();
+ }
+ catch (const LLContinueError& e)
+ {
+ LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
+ "'. Error what is: '" << e.what() << "'" << LL_ENDL;
+ LLError::LLCallStacks::print();
+
+ LOG_UNHANDLED_EXCEPTION("LLThread");
+ }
+ catch (std::bad_alloc&)
+ {
+ // Todo: improve this, this is going to have a different callstack
+ // instead of showing where it crashed
+ LL_WARNS("THREAD") << "Out of memory in a thread: " << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ []() {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("THREAD") << "Out of memory in a thread" << LL_ENDL;
+ });
+ }
+#ifndef LL_WINDOWS
+ catch (...)
+ {
+ // Stash any other kind of uncaught exception to be rethrown by main thread.
+ LL_WARNS("THREAD") << "Capturing and rethrowing uncaught exception in LLThread "
+ << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ }
+#endif // else LL_WINDOWS
+}
+
+#ifdef LL_WINDOWS
+void LLThread::sehHandle()
+{
+ __try
+ {
+ // handle stop and continue exceptions first
+ tryRun();
+ }
+ __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ // convert to C++ styled exception
+ // Note: it might be better to use _se_set_translator
+ // if you want exception to inherit full callstack
+ char integer_string[512];
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ throw std::exception(integer_string);
+ }
+}
+#endif
+
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
mPaused(false),
mName(name),
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 4194e0014d..8794ac93aa 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -68,7 +68,7 @@ public:
// Called from MAIN THREAD.
void pause();
void unpause();
- bool isPaused() { return isStopped() || mPaused; }
+ bool isPaused() const { return isStopped() || mPaused; }
// Cause the thread to wake up and check its condition
void wake();
@@ -97,6 +97,11 @@ private:
// static function passed to APR thread creation routine
void threadRun();
+ void tryRun();
+
+#ifdef LL_WINDOWS
+ void sehHandle();
+#endif
protected:
std::string mName;
diff --git a/indra/llcommon/llwin32headers.h b/indra/llcommon/llwin32headers.h
index df433deb7a..32139821d5 100644
--- a/indra/llcommon/llwin32headers.h
+++ b/indra/llcommon/llwin32headers.h
@@ -29,6 +29,7 @@
#ifdef LL_WINDOWS
#include <windows.h> // Does not include winsock.h because WIN32_LEAN_AND_MEAN is defined
+#include <ws2tcpip.h>
#include <winsock2.h> // Requires windows.h
#endif