/* HawkNL cross platform network library Copyright (C) 2000-2002 Phil Frisbie, Jr. (phil@hawksoft.com) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Or go to http://www.gnu.org/copyleft/lgpl.html */ #ifndef NL_H #define NL_H #include /* for strcpy, strlen, and memcpy in macros */ #ifdef __cplusplus extern "C" { #endif #define NL_MAJOR_VERSION 1 #define NL_MINOR_VERSION 68 #define NL_VERSION_STRING "HawkNL 1.68" /* define NL_SAFE_COPY for Sparc and other processors that do not allow non-aligned memory access. Needed for read* and write* macros */ /*#define NL_SAFE_COPY */ /* undefine this to remove IPX code, Windows only */ #define NL_INCLUDE_IPX /* undefine this to remove loopback code */ #define NL_INCLUDE_LOOPBACK /* undefine this to remove serial code */ #define NL_INCLUDE_SERIAL /* undefine this to remove modem code */ #define NL_INCLUDE_MODEM /* undefine this to remove parallel code */ #define NL_INCLUDE_PARALLEL #if defined (WIN32) || defined (WIN64) || defined (_WIN32_WCE) #define WINDOWS_APP #endif /* use native Windows threads and remove IPX support for WinCE */ /* also, many CE devices will not allow non-aligned memory access */ #if defined (_WIN32_WCE) #define NL_WIN_THREADS #define NL_SAFE_COPY #undef NL_INCLUDE_IPX #endif #ifdef WINDOWS_APP /* define NL_WIN_THREADS to use native Windows threads instead of pthreads */ #define NL_WIN_THREADS #ifdef _MSC_VER #pragma warning (disable:4514) /* disable "unreferenced inline function has been removed" warning */ #endif /* _MSC_VER */ /* The default build for Windows is as a DLL. */ /* If you want a static library, define WIN_STATIC_LIB. */ #ifdef WIN_STATIC_LIB #define NL_EXP #else #if defined (__LCC__) #define NL_EXP extern #else #define NL_EXP __declspec(dllexport) #endif /* __LCC__ */ #endif /* WIN_STATIC_LIB */ #define NL_APIENTRY __stdcall #define NL_CALLBACK __cdecl #ifdef __GNUC__ #define NL_INLINE extern __inline__ #else #define NL_INLINE __inline #endif /* __GNUC__ */ #else /* !WINDOWS_APP */ #define NL_EXP extern #define NL_APIENTRY #define NL_CALLBACK #ifdef __GNUC__ #define NL_INLINE extern __inline__ #else #define NL_INLINE inline /* assuming C99 compliant compiler */ #endif /* __GNUC__ */ #endif /* !WINDOWS_APP */ /* Any more needed here? */ #if defined WIN32 || defined WIN64 || defined __i386__ || defined __alpha__ || defined __mips__ #define NL_LITTLE_ENDIAN #else #define NL_BIG_ENDIAN #endif /* How do we detect Solaris 64 and Linux 64 bit? */ #if defined WIN64 #define IS_64_BIT #endif /* 8 bit */ typedef char NLbyte; typedef unsigned char NLubyte; typedef unsigned char NLboolean; /* 16 bit */ typedef short NLshort; typedef unsigned short NLushort; /* 32 bit */ typedef float NLfloat; #ifdef IS_64_BIT typedef int NLlong; /* Longs are 64 bit on a 64 bit CPU, but integers are still 32 bit. */ typedef unsigned int NLulong; /* This is, of course, not true on Windows (yet another exception), */ /* but it does not hurt. */ #else typedef long NLlong; typedef unsigned long NLulong; #endif /* 64 bit */ typedef double NLdouble; /* multithread */ typedef void *(*NLThreadFunc)(void *data); typedef void *NLthreadID; typedef struct nl_mutex_t *NLmutex; typedef struct nl_cond_t *NLcond; /* misc. */ typedef int NLint; typedef unsigned int NLuint; typedef unsigned int NLenum; typedef void NLvoid; typedef NLlong NLsocket; /* NOTE: NLchar is only to be used for external strings that might be unicode */ #if defined _UNICODE typedef wchar_t NLchar; #else typedef char NLchar; #endif typedef struct _NLaddress { NLubyte addr[32]; /* large enough to hold IPv6 address */ NLenum driver; /* driver type, not used yet */ NLboolean valid; /* set to NL_TRUE when address is valid */ } NLaddress; /* for backwards compatability */ #if !defined(address_t) typedef struct _NLaddress address_t; #endif typedef struct _NLtime { NLlong seconds; /* seconds since 12:00AM, 1 January, 1970 */ NLlong mseconds; /* milliseconds added to the seconds */ NLlong useconds; /* microseconds added to the seconds */ } NLtime; /* max string size limited to 256 (255 plus NULL termination) for MacOS */ #define NL_MAX_STRING_LENGTH 256 /* max packet size for NL_UNRELIABLE and NL_RELIABLE_PACKETS */ #define NL_MAX_PACKET_LENGTH 16384 /* max number groups and sockets per group */ #define NL_MAX_GROUPS 128 #if defined (macintosh) /* WARNING: Macs only allow up to 32K of local data, don't exceed 4096 */ /* Does NOT apply to Mac OSX */ #define NL_MAX_GROUP_SOCKETS 4096 #else /* max number of sockets per group NL will handle */ #define NL_MAX_GROUP_SOCKETS 8192 #endif #define NL_INVALID (-1) /* Boolean values */ #define NL_FALSE ((NLboolean)(0)) #define NL_TRUE ((NLboolean)(1)) /* Network types */ /* Only one can be selected at a time */ #define NL_IP 0x0003 /* all platforms */ #define NL_IPV6 0x0004 /* not yet implemented, IPv6 address family */ #define NL_LOOP_BACK 0x0005 /* all platforms, for single player client/server emulation with no network */ #define NL_IPX 0x0006 /* Windows only */ #define NL_SERIAL 0x0007 /* not yet implemented, Windows and Linux only? */ #define NL_MODEM 0x0008 /* not yet implemented, Windows and Linux only? */ #define NL_PARALLEL 0x0009 /* not yet implemented, Windows and Linux only? */ /* Connection types */ #define NL_RELIABLE 0x0010 /* NL_IP (TCP), NL_IPX (SPX), NL_LOOP_BACK */ #define NL_UNRELIABLE 0x0011 /* NL_IP (UDP), NL_IPX, NL_LOOP_BACK */ #define NL_RELIABLE_PACKETS 0x0012 /* NL_IP (TCP), NL_IPX (SPX), NL_LOOP_BACK */ #define NL_BROADCAST 0x0013 /* NL_IP (UDP), NL_IPX, or NL_LOOP_BACK broadcast packets */ #define NL_UDP_MULTICAST 0x0014 /* NL_IP (UDP) multicast */ #define NL_RAW 0x0015 /* NL_SERIAL or NL_PARALLEL */ /* TCP/IP specific aliases for connection types */ #define NL_TCP NL_RELIABLE #define NL_TCP_PACKETS NL_RELIABLE_PACKETS #define NL_UDP NL_UNRELIABLE #define NL_UDP_BROADCAST NL_BROADCAST /* for backwards compatability */ #define NL_MULTICAST NL_UDP_MULTICAST /* nlGetString */ #define NL_VERSION 0x0020 /* the version string */ #define NL_NETWORK_TYPES 0x0021 /* space delimited list of available network types */ #define NL_CONNECTION_TYPES 0x0022 /* space delimited list of available connection types */ /* only valid AFTER nlSelectNetwork */ /* nlGetInteger, nlGetSocketStat, nlClear */ #define NL_PACKETS_SENT 0x0030 /* total packets sent since last nlClear */ #define NL_BYTES_SENT 0x0031 /* total bytes sent since last nlClear */ #define NL_AVE_BYTES_SENT 0x0032 /* average bytes sent per second for the last 8 seconds */ #define NL_HIGH_BYTES_SENT 0x0033 /* highest bytes per second ever sent */ #define NL_PACKETS_RECEIVED 0x0034 /* total packets received since last nlClear */ #define NL_BYTES_RECEIVED 0x0035 /* total bytes received since last nlClear */ #define NL_AVE_BYTES_RECEIVED 0x0036 /* average bytes received per second for the last 8 seconds */ #define NL_HIGH_BYTES_RECEIVED 0x0037 /* highest bytes per second ever received */ #define NL_ALL_STATS 0x0038 /* nlClear only, clears out all counters */ #define NL_OPEN_SOCKETS 0x0039 /* number of open sockets */ /* nlEnable, nlDisable */ #define NL_BLOCKING_IO 0x0040 /* set IO to blocking, default is NL_FALSE for non-blocking IO */ #define NL_SOCKET_STATS 0x0041 /* enable collection of socket read/write statistics, default disabled */ #define NL_BIG_ENDIAN_DATA 0x0042 /* enable big endian data for nlSwap* and read/write macros, default enabled */ #define NL_LITTLE_ENDIAN_DATA 0x0043 /* enable little endian data for nlSwap* and read/write macros, default disabled */ #define NL_MULTIPLE_DRIVERS 0x0044 /* enable multiple drivers to be selected */ /* nlPollGroup */ #define NL_READ_STATUS 0x0050 /* poll the read status for all sockets in the group */ #define NL_WRITE_STATUS 0x0051 /* poll the write status for all sockets in the group */ #define NL_ERROR_STATUS 0x0052 /* poll the error status for all sockets in the group */ /* nlHint, advanced network settings for experienced developers */ #define NL_LISTEN_BACKLOG 0x0060 /* TCP, SPX: the backlog of connections for listen */ #define NL_MULTICAST_TTL 0x0061 /* UDP : The multicast TTL value. Default : 1 */ #define NL_REUSE_ADDRESS 0x0062 /* TCP, UDP : Allow IP address to be reused. Default : NL_FALSE */ #define NL_TCP_NO_DELAY 0x0063 /* TCP : disable Nagle algorithm, arg != 0 to disable, 0 to enable */ /* errors */ #define NL_NO_ERROR 0x0000 /* no error is stored */ #define NL_NO_NETWORK 0x0100 /* no network was found on init */ #define NL_OUT_OF_MEMORY 0x0101 /* out of memory */ #define NL_INVALID_ENUM 0x0102 /* function called with an invalid NLenum */ #define NL_INVALID_SOCKET 0x0103 /* socket is not valid, or has been terminated */ #define NL_INVALID_PORT 0x0104 /* the port could not be opened */ #define NL_INVALID_TYPE 0x0105 /* the network type is not available */ #define NL_SYSTEM_ERROR 0x0106 /* a system error occurred, call nlGetSystemError */ #define NL_SOCK_DISCONNECT 0x0107 /* the socket should be closed because of a connection loss or error */ #define NL_NOT_LISTEN 0x0108 /* the socket has not been set to listen */ #define NL_CON_REFUSED 0x0109 /* connection refused, or socket already connected */ #define NL_NO_PENDING 0x010a /* there are no pending connections to accept */ #define NL_BAD_ADDR 0x010b /* the address or port are not valid */ #define NL_MESSAGE_END 0x010c /* the end of a reliable stream (TCP) message has been reached */ #define NL_NULL_POINTER 0x010d /* a NULL pointer was passed to a function */ #define NL_INVALID_GROUP 0x010e /* the group is not valid, or has been destroyed */ #define NL_OUT_OF_GROUPS 0x010f /* out of internal group objects */ #define NL_OUT_OF_GROUP_SOCKETS 0x0110 /* the group has no more room for sockets */ #define NL_BUFFER_SIZE 0x0111 /* the buffer was too small to store the data, retry with a larger buffer */ #define NL_PACKET_SIZE 0x0112 /* the size of the packet exceeds NL_MAX_PACKET_LENGTH or the protocol max */ #define NL_WRONG_TYPE 0x0113 /* the function does not support the socket type */ #define NL_CON_PENDING 0x0114 /* a non-blocking connection is still pending */ #define NL_SELECT_NET_ERROR 0x0115 /* a network is already selected, and NL_MULTIPLE_DRIVERS is not enabled, call nlShutDown and nlInit first */ #define NL_PACKET_SYNC 0x0116 /* the NL_RELIABLE_PACKET stream is out of sync */ #define NL_TLS_ERROR 0x0117 /* thread local storage could not be created */ #define NL_TIMED_OUT 0x0118 /* the function timed out */ #define NL_SOCKET_NOT_FOUND 0x0119 /* the socket was not found in the group */ #define NL_STRING_OVER_RUN 0x011a /* the string is not null terminated, or is longer than NL_MAX_STRING_LENGTH */ #define NL_MUTEX_RECURSION 0x011b /* the mutex was recursivly locked */ #define NL_MUTEX_OWNER 0x011c /* the mutex is not owned by thread */ /* for backwards compatability */ #define NL_SOCKET_ERROR NL_SYSTEM_ERROR #define NL_CON_TERM NL_SOCK_DISCONNECT /* standard multicast TTL settings as recommended by the */ /* white paper at http://www.ipmulticast.com/community/whitepapers/howipmcworks.html */ #define NL_TTL_LOCAL 1 /* local LAN only */ #define NL_TTL_SITE 15 /* this site */ #define NL_TTL_REGION 63 /* this region */ #define NL_TTL_WORLD 127 /* the world */ /* Low level API, a thin layer over Sockets or other network provider. */ NL_EXP NLboolean NL_APIENTRY nlListen(NLsocket socket); NL_EXP NLsocket NL_APIENTRY nlAcceptConnection(NLsocket socket); NL_EXP NLsocket NL_APIENTRY nlOpen(NLushort port, NLenum type); NL_EXP NLboolean NL_APIENTRY nlConnect(NLsocket socket, const NLaddress *address); NL_EXP NLboolean NL_APIENTRY nlClose(NLsocket socket); NL_EXP NLint NL_APIENTRY nlRead(NLsocket socket, /*@out@*/ NLvoid *buffer, NLint nbytes); NL_EXP NLint NL_APIENTRY nlWrite(NLsocket socket, const NLvoid *buffer, NLint nbytes); NL_EXP NLlong NL_APIENTRY nlGetSocketStat(NLsocket socket, NLenum name); NL_EXP NLboolean NL_APIENTRY nlClearSocketStat(NLsocket socket, NLenum name); NL_EXP NLint NL_APIENTRY nlPollGroup(NLint group, NLenum name, /*@out@*/ NLsocket *sockets, NLint number, NLint timeout); NL_EXP NLboolean NL_APIENTRY nlHint(NLenum name, NLint arg); /* Address management API */ NL_EXP /*@null@*/ NLchar* NL_APIENTRY nlAddrToString(const NLaddress *address, /*@returned@*/ /*@out@*/ NLchar *string); NL_EXP NLboolean NL_APIENTRY nlStringToAddr(const NLchar *string, /*@out@*/ NLaddress *address); NL_EXP NLboolean NL_APIENTRY nlGetRemoteAddr(NLsocket socket, /*@out@*/ NLaddress *address); NL_EXP NLboolean NL_APIENTRY nlSetRemoteAddr(NLsocket socket, const NLaddress *address); NL_EXP NLboolean NL_APIENTRY nlGetLocalAddr(NLsocket socket, /*@out@*/ NLaddress *address); NL_EXP NLaddress* NL_APIENTRY nlGetAllLocalAddr(/*@out@*/ NLint *count); NL_EXP NLboolean NL_APIENTRY nlSetLocalAddr(const NLaddress *address); NL_EXP /*@null@*/ NLchar* NL_APIENTRY nlGetNameFromAddr(const NLaddress *address, /*@returned@*/ /*@out@*/ NLchar *name); NL_EXP NLboolean NL_APIENTRY nlGetNameFromAddrAsync(const NLaddress *address, /*@out@*/ NLchar *name); NL_EXP NLboolean NL_APIENTRY nlGetAddrFromName(const NLchar *name, /*@out@*/ NLaddress *address); NL_EXP NLboolean NL_APIENTRY nlGetAddrFromNameAsync(const NLchar *name, /*@out@*/ NLaddress *address); NL_EXP NLboolean NL_APIENTRY nlAddrCompare(const NLaddress *address1, const NLaddress *address2); NL_EXP NLushort NL_APIENTRY nlGetPortFromAddr(const NLaddress *address); NL_EXP NLboolean NL_APIENTRY nlSetAddrPort(NLaddress *address, NLushort port); /* Group management API */ NL_EXP NLint NL_APIENTRY nlGroupCreate(void); NL_EXP NLboolean NL_APIENTRY nlGroupDestroy(NLint group); NL_EXP NLboolean NL_APIENTRY nlGroupAddSocket(NLint group, NLsocket socket); NL_EXP NLboolean NL_APIENTRY nlGroupGetSockets(NLint group, /*@out@*/ NLsocket *sockets, /*@in@*/ NLint *number); NL_EXP NLboolean NL_APIENTRY nlGroupDeleteSocket(NLint group, NLsocket socket); /* Multithreading API */ NL_EXP NLthreadID NL_APIENTRY nlThreadCreate(NLThreadFunc func, void *data, NLboolean joinable); NL_EXP void NL_APIENTRY nlThreadYield(void); NL_EXP NLboolean NL_APIENTRY nlThreadJoin(NLthreadID threadID, void **status); NL_EXP NLboolean NL_APIENTRY nlMutexInit(NLmutex *mutex); NL_EXP NLboolean NL_APIENTRY nlMutexLock(NLmutex *mutex); NL_EXP NLboolean NL_APIENTRY nlMutexUnlock(NLmutex *mutex); NL_EXP NLboolean NL_APIENTRY nlMutexDestroy(NLmutex *mutex); NL_EXP NLboolean NL_APIENTRY nlCondInit(NLcond *cond); NL_EXP NLboolean NL_APIENTRY nlCondWait(NLcond *cond, NLint timeout); NL_EXP NLboolean NL_APIENTRY nlCondSignal(NLcond *cond); NL_EXP NLboolean NL_APIENTRY nlCondBroadcast(NLcond *cond); NL_EXP NLboolean NL_APIENTRY nlCondDestroy(NLcond *cond); /* Time API */ NL_EXP NLboolean NL_APIENTRY nlTime(NLtime *ts); /* Misc. API */ NL_EXP NLboolean NL_APIENTRY nlInit(void); NL_EXP void NL_APIENTRY nlShutdown(void); NL_EXP NLboolean NL_APIENTRY nlSelectNetwork(NLenum network); NL_EXP const /*@observer@*//*@null@*/ NLchar* NL_APIENTRY nlGetString(NLenum name); NL_EXP NLlong NL_APIENTRY nlGetInteger(NLenum name); NL_EXP NLboolean NL_APIENTRY nlGetBoolean(NLenum name); NL_EXP NLboolean NL_APIENTRY nlClear(NLenum name); NL_EXP NLenum NL_APIENTRY nlGetError(void); NL_EXP const /*@observer@*/ NLchar* NL_APIENTRY nlGetErrorStr(NLenum err); NL_EXP NLint NL_APIENTRY nlGetSystemError(void); NL_EXP const /*@observer@*/ NLchar* NL_APIENTRY nlGetSystemErrorStr(NLint err); NL_EXP NLboolean NL_APIENTRY nlEnable(NLenum name); NL_EXP NLboolean NL_APIENTRY nlDisable(NLenum name); NL_EXP NLushort NL_APIENTRY nlGetCRC16(NLubyte *data, NLint len); NL_EXP NLulong NL_APIENTRY nlGetCRC32(NLubyte *data, NLint len); NL_EXP NLushort NL_APIENTRY nlSwaps(NLushort x); NL_EXP NLulong NL_APIENTRY nlSwapl(NLulong x); NL_EXP NLfloat NL_APIENTRY nlSwapf(NLfloat f); NL_EXP NLdouble NL_APIENTRY nlSwapd(NLdouble d); /* macros for writing/reading packet buffers */ /* NOTE: these also endian swap the data as needed */ /* write* or read* (buffer *, count, data [, length]) */ #ifdef NL_SAFE_COPY #define writeShort(x, y, z) {NLushort nl_temps = nlSwaps(z); memcpy((char *)&x[y], (char *)&nl_temps, 2); y += 2;} #define writeLong(x, y, z) {NLulong nl_templ = nlSwapl(z); memcpy((char *)&x[y], (char *)&nl_templ, 4); y += 4;} #define writeFloat(x, y, z) {NLfloat nl_tempf = nlSwapf(z); memcpy((char *)&x[y], (char *)&nl_tempf, 4); y += 4;} #define writeDouble(x, y, z) {NLdouble nl_tempd = nlSwapd(z); memcpy((char *)&x[y], (char *)&nl_tempd, 8); y += 8;} #define readShort(x, y, z) {memcpy((char *)&z, (char *)&x[y], 2); z = nlSwaps(z); y += 2;} #define readLong(x, y, z) {memcpy((char *)&z, (char *)&x[y], 4); z = nlSwapl(z); y += 4;} #define readFloat(x, y, z) {memcpy((char *)&z, (char *)&x[y], 4); z = nlSwapf(z); y += 4;} #define readDouble(x, y, z) {memcpy((char *)&z, (char *)&x[y], 8); z = nlSwapd(z); y += 8;} #else /* !NL_SAFE_COPY */ #define writeShort(x, y, z) {*((NLushort *)((NLbyte *)&x[y])) = nlSwaps(z); y += 2;} #define writeLong(x, y, z) {*((NLulong *)((NLbyte *)&x[y])) = nlSwapl(z); y += 4;} #define writeFloat(x, y, z) {*((NLfloat *)((NLbyte *)&x[y])) = nlSwapf(z); y += 4;} #define writeDouble(x, y, z) {*((NLdouble *)((NLbyte *)&x[y])) = nlSwapd(z); y += 8;} #define readShort(x, y, z) {z = nlSwaps(*(NLushort *)((NLbyte *)&x[y])); y += 2;} #define readLong(x, y, z) {z = nlSwapl(*(NLulong *)((NLbyte *)&x[y])); y += 4;} #define readFloat(x, y, z) {z = nlSwapf(*(NLfloat *)((NLbyte *)&x[y])); y += 4;} #define readDouble(x, y, z) {z = nlSwapd(*(NLdouble *)((NLbyte *)&x[y])); y += 8;} #endif /* !NL_SAFE_COPY */ #define writeByte(x, y, z) (*(NLbyte *)&x[y++] = (NLbyte)z) #define writeBlock(x, y, z, a) {memcpy((char *)&x[y], (char *)z, a);y += a;} #define readByte(x, y, z) (z = *(NLbyte *)&x[y++]) #define readBlock(x, y, z, a) {memcpy((char *)z, (char *)&x[y], a);y += a;} #ifdef _UNICODE #include #define writeString(x, y, z) writeStringWC(x, &y, z) #define readString(x, y, z) readStringWC(x, &y, z) NL_INLINE void writeStringWC(NLbyte *x, NLint *y, NLchar *z) { int len = (int)wcstombs(&x[*y], z, (size_t)NL_MAX_STRING_LENGTH); if(len == NL_MAX_STRING_LENGTH) { /* must null terminate string */ x[*y + NL_MAX_STRING_LENGTH] = '\0'; *y += NL_MAX_STRING_LENGTH; } else if(len > 0) { *y += (len + 1); } else { /* there was an error in wcstombs, so just add a 0 length string to the buffer */ x[*y] = '\0'; *y++; } } NL_INLINE void readStringWC(NLbyte *x, NLint *y, NLchar *z) { int len = (int)mbstowcs(z, &x[*y], (size_t)NL_MAX_STRING_LENGTH); if(len == NL_MAX_STRING_LENGTH) { /* must null terminate string */ z[NL_MAX_STRING_LENGTH] = L'\0'; } else if(len < 0) { /* must null terminate string */ z[0] = L'\0'; } *y += (strlen((char *)&x[*y]) + 1); } #else /* !_UNICODE */ #define writeString(x, y, z) {strcpy((char *)&x[y], (char *)z); y += (strlen((char *)z) + 1);} #define readString(x, y, z) {strcpy((char *)z, (char *)&x[y]); y += (strlen((char *)z) + 1);} #endif /* !_UNICODE */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* NL_H */