og-odamex/odalpapi/net_error.cpp

171 lines
3.1 KiB
C++

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 2006-2026 by The Odamex Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Error handling
//
// AUTHORS:
// Russell Rice (russell at odamex dot net)
// Michael Wood (mwoodj at knology dot net)
//
//-----------------------------------------------------------------------------
#include "net_error.h"
#include <cstdio>
#include <cstdarg>
#ifdef _WIN32
#include <windows.h>
#else
#include <string.h>
#include <errno.h>
#endif
// todo: detect agar
#if 0
#include <agar/core.h>
#endif
namespace odalpapi
{
#if defined(_WIN32)
// Russell - bits from msdn:
static LPSTR _GetFormattedMessage(DWORD errnum)
{
LPSTR pBuffer = NULL;
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
errnum,
0,
(LPSTR)&pBuffer,
0,
NULL);
return pBuffer;
}
#endif
static char* _GetStrError(int errnum)
{
#if defined(_WIN32)
return _GetFormattedMessage(errnum);
#else
return strerror(errnum);
#endif
}
// Get error code
static int _GetErrno()
{
#ifdef _WIN32
return GetLastError();
#else
return errno;
#endif
}
// We must lock the stderr stream for multiple thread access
#ifdef _WIN32
CRITICAL_SECTION STDERR_CRITICAL_SECTION;
static bool Init = false;
void InitLockStderr()
{
if(!Init)
InitializeCriticalSection(&STDERR_CRITICAL_SECTION);
Init = true;
}
void LockStderr()
{
EnterCriticalSection(&STDERR_CRITICAL_SECTION);
}
void UnlockStderr()
{
LeaveCriticalSection(&STDERR_CRITICAL_SECTION);
}
#endif // _WIN32
// Formatted debug output
void _ReportError(const char* file, int line, const char* func,
const char* fmt, ...)
{
va_list ap;
if(!func || !fmt)
return;
#if _WIN32
InitLockStderr();
LockStderr();
#else
flockfile(stderr);
#endif
char* syserrmsg = NULL;
int syserr = _GetErrno();
if(syserr)
{
syserrmsg = _GetStrError(syserr);
}
va_start(ap, fmt);
fprintf(stderr, "[%s:%d] BufferedSocket::%s(): ", file, line, func);
vfprintf(stderr, fmt, ap);
if(NULL != syserrmsg)
{
fprintf(stderr, "\n syserrmsg - %s\n", syserrmsg);
}
fputs("\n", stderr);
va_end(ap);
#ifdef _WIN32
if(NULL != syserrmsg)
{
LocalFree(syserrmsg);
}
UnlockStderr();
#else
funlockfile(stderr);
#endif
}
#if defined(_MSC_VER) && _MSC_VER < 1400
void NET_ReportError(const char* fmt, ...)
{
va_list ap;
char errorstr[1024];
va_start(ap, fmt);
vsnprintf(errorstr, 1024, fmt, ap);
va_end(ap);
_ReportError("", 0, "", errorstr);
}
#endif
} // namespace