2006-04-12 01:59:08 +02:00
|
|
|
/**
|
|
|
|
* =========================================================================
|
|
|
|
* File : wsock.cpp
|
|
|
|
* Project : 0 A.D.
|
|
|
|
* Description : emulate Berkeley sockets on Windows.
|
|
|
|
* =========================================================================
|
|
|
|
*/
|
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
// license: GPL; see lib/license.txt
|
2004-06-03 20:36:48 +02:00
|
|
|
|
2004-05-27 19:30:06 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
#include "wsock.h"
|
|
|
|
|
2007-01-01 22:25:47 +01:00
|
|
|
#include "../delay_load.h"
|
|
|
|
#include "wposix_internal.h"
|
2007-01-07 17:50:36 +01:00
|
|
|
#include "wsock_internal.h"
|
2004-06-04 14:41:53 +02:00
|
|
|
|
2005-08-09 18:23:19 +02:00
|
|
|
#if MSC_VERSION
|
2004-05-27 19:30:06 +02:00
|
|
|
#pragma comment(lib, "ws2_32.lib")
|
2004-06-04 14:41:53 +02:00
|
|
|
#endif
|
2004-05-27 19:30:06 +02:00
|
|
|
|
2004-06-13 18:06:23 +02:00
|
|
|
|
2007-01-07 17:50:36 +01:00
|
|
|
#pragma SECTION_PRE_MAIN(K)
|
2006-06-22 20:49:23 +02:00
|
|
|
WIN_REGISTER_FUNC(wsock_init);
|
2007-01-07 17:50:36 +01:00
|
|
|
#pragma FORCE_INCLUDE(wsock_init)
|
|
|
|
#pragma SECTION_POST_ATEXIT(D)
|
2004-06-13 18:06:23 +02:00
|
|
|
WIN_REGISTER_FUNC(wsock_shutdown);
|
2007-01-07 17:50:36 +01:00
|
|
|
#pragma FORCE_INCLUDE(wsock_shutdown)
|
|
|
|
#pragma SECTION_RESTORE
|
2004-06-13 18:06:23 +02:00
|
|
|
|
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
// IPv6 globals
|
|
|
|
// These are included in the linux C libraries and in newer platform SDKs,
|
|
|
|
// so should only be needed in VC++6 or earlier.
|
|
|
|
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; // ::
|
2006-09-22 15:19:40 +02:00
|
|
|
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; // ::_1
|
2004-06-11 04:14:18 +02:00
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
static HMODULE hWs2_32Dll;
|
|
|
|
static int dll_refs;
|
2004-05-27 19:30:06 +02:00
|
|
|
|
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
// called from delay loader the first time a wsock function is called
|
2005-01-28 19:16:51 +01:00
|
|
|
// (shortly before the actual wsock function is called).
|
2006-06-22 20:49:23 +02:00
|
|
|
static LibError wsock_actual_init()
|
2004-07-12 16:24:26 +02:00
|
|
|
{
|
|
|
|
hWs2_32Dll = LoadLibrary("ws2_32.dll");
|
2004-05-27 19:30:06 +02:00
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
// first time: call WSAStartup
|
|
|
|
if(!dll_refs++)
|
|
|
|
{
|
|
|
|
char d[1024];
|
|
|
|
if(WSAStartup(0x0002, d) != 0) // want 2.0
|
|
|
|
debug_warn("WSAStartup failed");
|
|
|
|
}
|
2004-05-27 19:30:06 +02:00
|
|
|
|
2006-09-22 15:19:40 +02:00
|
|
|
return INFO::OK;
|
2004-07-12 16:24:26 +02:00
|
|
|
}
|
2004-05-27 19:30:06 +02:00
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
|
2006-06-22 20:49:23 +02:00
|
|
|
// called via module init mechanism. triggers wsock_actual_init when
|
|
|
|
// someone first calls a wsock function.
|
|
|
|
static LibError wsock_init()
|
|
|
|
{
|
|
|
|
WDLL_LOAD_NOTIFY("ws2_32", wsock_actual_init);
|
2006-09-22 15:19:40 +02:00
|
|
|
return INFO::OK;
|
2006-06-22 20:49:23 +02:00
|
|
|
}
|
2004-07-12 16:24:26 +02:00
|
|
|
|
2005-12-11 23:23:55 +01:00
|
|
|
static LibError wsock_shutdown()
|
2004-05-27 19:30:06 +02:00
|
|
|
{
|
2004-07-12 16:24:26 +02:00
|
|
|
// call WSACleanup if DLL was used
|
|
|
|
// (this way is easier to understand than ONCE in loop below)
|
|
|
|
if(dll_refs > 0)
|
|
|
|
if(WSACleanup() < 0)
|
|
|
|
debug_warn("WSACleanup failed");
|
2004-06-13 18:06:23 +02:00
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
// remove all references
|
|
|
|
while(dll_refs-- > 0)
|
|
|
|
FreeLibrary(hWs2_32Dll);
|
2004-06-13 18:06:23 +02:00
|
|
|
|
2006-09-22 15:19:40 +02:00
|
|
|
return INFO::OK;
|
2004-05-27 19:30:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
// manual import instead of delay-load because we don't want to require
|
|
|
|
// these functions to be present. the user must be able to check if they
|
|
|
|
// are available (currently, on Win2k with IPv6 update or WinXP).
|
|
|
|
// can't use compile-time HAVE_* to make that decision because
|
|
|
|
// we don't want to distribute a separate binary for this.
|
|
|
|
//
|
|
|
|
// note: can't import at startup because we don't want to load wsock unless necessary
|
|
|
|
// don't use delay load because we don't want to confuse error handling for other users
|
|
|
|
//
|
|
|
|
// don't bother caching - these functions themselves take a while and aren't time-critical
|
|
|
|
|
|
|
|
static void* import(const char* name)
|
2004-05-27 19:30:06 +02:00
|
|
|
{
|
2004-07-12 16:24:26 +02:00
|
|
|
return GetProcAddress(hWs2_32Dll, name);
|
2004-05-27 19:30:06 +02:00
|
|
|
}
|
|
|
|
|
2004-07-12 16:24:26 +02:00
|
|
|
fp_getnameinfo_t import_getnameinfo() { return (fp_getnameinfo_t )import("getnameinfo" ); }
|
|
|
|
fp_getaddrinfo_t import_getaddrinfo() { return (fp_getaddrinfo_t )import("getaddrinfo" ); }
|
|
|
|
fp_freeaddrinfo_t import_freeaddrinfo() { return (fp_freeaddrinfo_t)import("freeaddrinfo"); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-05-27 19:30:06 +02:00
|
|
|
|
2004-06-01 19:34:12 +02:00
|
|
|
uint16_t htons(uint16_t s)
|
2004-05-27 19:30:06 +02:00
|
|
|
{
|
|
|
|
return (s >> 8) | ((s & 0xff) << 8);
|
|
|
|
}
|