Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
236 KB
Referenced Files
None
Subscribers
None
diff --git a/util/network/hawknl/CMakeLists.txt b/util/network/hawknl/CMakeLists.txt
index d66c035a..f3c22683 100644
--- a/util/network/hawknl/CMakeLists.txt
+++ b/util/network/hawknl/CMakeLists.txt
@@ -1,44 +1,44 @@
# -------------------------------------------------------
# hawknl cmake build script for paintown.
# Written by: juvinious
# -------------------------------------------------------
# -------------------------------------------------------
# Set some specific stuff for hawknl
# -------------------------------------------------------
if(NOT MSVC)
set(CFLAGS "-W -O2 -Wwrite-strings -Wstrict-prototypes -Wall -funroll-loops -Wmissing-declarations -fomit-frame-pointer -Wno-missing-declarations")
else(NOT MSVC)
set(CFLAGS "-O2")
endif(NOT MSVC)
remove_definitions(${CXXFLAGS})
add_definitions(${CFLAGS})
# -------------------------------------------------------
# Source directories containing all the necessary .cpp files
# -------------------------------------------------------
set(SRC
src/crc.c
src/err.c
src/errorstr.c
src/group.c
src/htcondition.c
src/hthread.c
src/htmutex.c
src/ipx.c
src/loopback.c
src/nl.c
src/nltime.c
src/sock.c)
# -------------------------------------------------------
# Include directory
# -------------------------------------------------------
-include_directories(include hawknl)
+#include_directories(include hawknl)
# -------------------------------------------------------
# module
# -------------------------------------------------------
add_library (hawknl_module ${SRC})
diff --git a/util/network/hawknl/SConscript b/util/network/hawknl/SConscript
index bbea29e1..d1631a9d 100644
--- a/util/network/hawknl/SConscript
+++ b/util/network/hawknl/SConscript
@@ -1,24 +1,24 @@
import os
Import( 'env' )
# env = Environment( ENV = os.environ )
source = Split("""
src/crc.c
src/err.c
src/errorstr.c
src/group.c
src/hthread.c
src/htcondition.c
src/ipx.c
src/loopback.c
src/htmutex.c
src/nl.c
src/nltime.c
src/sock.c
""");
-env.Append(CPPPATH = 'hawknl')
+# env.Append(CPPPATH = 'hawknl')
x = env.StaticLibrary('hawknl', source)
-Return( 'x' )
+Return('x')
diff --git a/util/network/hawknl/src/crc.c b/util/network/hawknl/src/crc.c
index be9f886e..468e73cf 100644
--- a/util/network/hawknl/src/crc.c
+++ b/util/network/hawknl/src/crc.c
@@ -1,138 +1,138 @@
/*
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
*/
-#include "nl.h"
+#include "hawknl/nl.h"
static NLushort crc16tab[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
HL_EXP NLushort HL_APIENTRY nlGetCRC16(NLubyte *data, NLint len)
{
register NLushort crc = 0xffff;
register NLubyte *cp = data;
register NLint cnt = len;
while(0 != cnt--)
{
crc = (NLushort)((crc<<8) ^ crc16tab[(crc>>8) ^ *cp++]);
}
return crc;
}
static NLulong crc32tab[256] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
HL_EXP NLulong HL_APIENTRY nlGetCRC32(NLubyte *data, NLint len)
{
register NLulong crc = (NLulong)0xffffffff;
register NLubyte *cp = data;
register NLint cnt = len;
while(0 != cnt--)
{
crc = ((crc) >> 8) ^ crc32tab[(NLint)(*cp++) ^ ((crc) & 0x000000FF)];
}
return crc;
}
diff --git a/util/network/hawknl/src/err.c b/util/network/hawknl/src/err.c
index 89e222e3..2a74598d 100644
--- a/util/network/hawknl/src/err.c
+++ b/util/network/hawknl/src/err.c
@@ -1,119 +1,119 @@
/*
HawkNL cross platform network library
Copyright (C) 2000-2004 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
*/
-#include "nlinternal.h"
+#include "hawknl/nlinternal.h"
#ifdef HL_WINDOWS_APP
/* Windows systems */
#define NL_WIN_THREADS
#ifdef _MSC_VER
#pragma warning (disable:4201)
#pragma warning (disable:4214)
#endif /* _MSC_VER */
#define WIN32_LEAN_AND_MEAN
#include <winsock.h>
#ifdef _MSC_VER
#pragma warning (default:4201)
#pragma warning (default:4214)
#endif /* _MSC_VER */
#endif
#ifdef NL_WIN_THREADS
/* native Windows */
static DWORD key = (DWORD)0xFFFFFFFF;
#else
/* POSIX systems */
#include <pthread.h>
#define KEY_NULL ((pthread_key_t)-1)
static pthread_key_t key = KEY_NULL;
#endif
void nlSetError(NLenum err)
{
#ifdef NL_WIN_THREADS
/* check to see if we need to initialize */
if(key == (DWORD)0xFFFFFFFF)
{
key = TlsAlloc();
}
if(key != (DWORD)0xFFFFFFFF)
{
(void)TlsSetValue(key, (LPVOID)err);
}
#else
/* check to see if we need to initialize */
if(key == KEY_NULL)
{
(void)pthread_key_create(&key, NULL);
}
if(key != KEY_NULL)
{
(void)pthread_setspecific(key, (void *)(long)err);
}
#endif
}
HL_EXP NLenum HL_APIENTRY nlGetError(void)
{
NLenum result;
#ifdef NL_WIN_THREADS
/* check to see if we need to initialize */
if(key == (DWORD)0xFFFFFFFF)
{
key = TlsAlloc();
if(key == (DWORD)0xFFFFFFFF)
return NL_TLS_ERROR;
else
return NL_NO_ERROR;
}
else
{
int lasterror = WSAGetLastError();
result = (NLenum)TlsGetValue(key);
WSASetLastError(lasterror);
return result;
}
#else
/* check to see if we need to initialize */
if(key == KEY_NULL)
{
if(pthread_key_create(&key, NULL) != 0)
return NL_TLS_ERROR;
else
return NL_NO_ERROR;
}
else
{
result = (NLenum)(long)pthread_getspecific(key);
return result;
}
#endif
}
diff --git a/util/network/hawknl/src/errorstr.c b/util/network/hawknl/src/errorstr.c
index ca0b384a..ccd84463 100644
--- a/util/network/hawknl/src/errorstr.c
+++ b/util/network/hawknl/src/errorstr.c
@@ -1,364 +1,364 @@
/*
HawkNL cross platform network library
Copyright (C) 2000-2004 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
*/
/*
Based on code supplied by Ryan Haksi <cryogen@infoserve.net>
*/
#if defined WIN32 || defined WIN64 || defined (_WIN32_WCE)
#if !defined (_WIN32_WCE)
#include <errno.h>
#endif
#include "wsock.h"
#elif macintosh
/* POSIX compat Mac systems ie pre OSX with GUSI2 installed */
#include <unistd.h>
#include <types.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#else
/* POSIX systems */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netdb.h>
#include <string.h>
#endif
-#include "nlinternal.h"
+#include "hawknl/nlinternal.h"
HL_EXP const /*@observer@*/ NLchar* HL_APIENTRY nlGetSystemErrorStr(NLint err)
{
NLchar *lpszRetStr;
switch(err) {
#ifdef HL_WINDOWS_APP
case WSABASEERR:
lpszRetStr=(NLchar *)TEXT("No error.");
break;
case WSAVERNOTSUPPORTED:
lpszRetStr=(NLchar *)TEXT("Version of WinSock not supported.");
break;
case WSASYSNOTREADY:
lpszRetStr=(NLchar *)TEXT("WinSock not present or not responding.");
break;
case WSANOTINITIALISED:
lpszRetStr=(NLchar *)TEXT("WinSock not initialized.");
break;
#endif
/* ELOOK is used on some Macs */
#ifdef ELOOK
case ELOOK:
lpszRetStr=(NLchar *)TEXT("Internal mapping for kOTLookErr, don't return to client.");
break;
#endif
/* EPROCLIM not defined in some UNIXs */
#ifdef EPROCLIM
case EPROCLIM:
lpszRetStr=(NLchar *)TEXT("Too many processes.");
break;
#endif
/* On some UNIXs, EINTR and NO_DATA have the same value */
#if (EINTR != NO_DATA)
case EINTR:
lpszRetStr=(NLchar *)TEXT("Interrupted function call.");
break;
#if defined(NO_DATA)
case NO_DATA:
lpszRetStr=(NLchar *)TEXT("Valid name, no data record for type.");
break;
#endif
#else
case NO_DATA:
lpszRetStr=(NLchar *)TEXT("Interrupted function call or no data record for type.");
break;
#endif
case EBADF:
lpszRetStr=(NLchar *)TEXT("Bad file descriptor.");
break;
case EFAULT:
lpszRetStr=(NLchar *)TEXT("The namelen argument is incorrect.");
break;
case EMFILE:
lpszRetStr=(NLchar *)TEXT("Too many open files.");
break;
case EINVAL:
lpszRetStr=(NLchar *)TEXT("App version not supported by DLL.");
break;
#if defined(TRY_AGAIN)
case TRY_AGAIN:
lpszRetStr=(NLchar *)TEXT("Non-authoritive: host not found or server failure.");
break;
#endif
#if defined(NO_RECOVERY)
case NO_RECOVERY:
lpszRetStr=(NLchar *)TEXT("Non-recoverable: refused or not implemented.");
break;
#endif
#if defined(HOST_NOT_FOUND)
case HOST_NOT_FOUND:
lpszRetStr=(NLchar *)TEXT("Authoritive: Host not found.");
break;
#endif
case EACCES:
lpszRetStr=(NLchar *)TEXT("Permission to access socket denied.");
break;
case ENETDOWN:
lpszRetStr=(NLchar *)TEXT("Network subsystem failed.");
break;
case EAFNOSUPPORT:
lpszRetStr=(NLchar *)TEXT("Address family not supported.");
break;
case ENOBUFS:
lpszRetStr=(NLchar *)TEXT("No buffer space available.");
break;
case EPROTONOSUPPORT:
lpszRetStr=(NLchar *)TEXT("Specified protocol not supported.");
break;
case EPROTOTYPE:
lpszRetStr=(NLchar *)TEXT("Protocol wrong type for this socket.");
break;
case ESOCKTNOSUPPORT:
lpszRetStr=(NLchar *)TEXT("Socket type not supported for address family.");
break;
case ENOTSOCK:
lpszRetStr=(NLchar *)TEXT("Descriptor is not a socket.");
break;
case EWOULDBLOCK:
lpszRetStr=(NLchar *)TEXT("Non-blocking socket would block.");
break;
case EADDRINUSE:
lpszRetStr=(NLchar *)TEXT("Address already in use.");
break;
case ECONNABORTED:
lpszRetStr=(NLchar *)TEXT("Connection aborted.");
break;
case ECONNRESET:
lpszRetStr=(NLchar *)TEXT("Connection reset.");
break;
case ENOTCONN:
lpszRetStr=(NLchar *)TEXT("Not connected.");
break;
case ETIMEDOUT:
lpszRetStr=(NLchar *)TEXT("Connection timed out.");
break;
case ECONNREFUSED:
lpszRetStr=(NLchar *)TEXT("Connection was refused.");
break;
case EHOSTDOWN:
lpszRetStr=(NLchar *)TEXT("Host is down.");
break;
case ENETUNREACH:
lpszRetStr=(NLchar *)TEXT("Network unreachable.");
break;
case EHOSTUNREACH:
lpszRetStr=(NLchar *)TEXT("Host unreachable.");
break;
case EADDRNOTAVAIL:
lpszRetStr=(NLchar *)TEXT("Address not available.");
break;
case EINPROGRESS:
#ifdef HL_WINDOWS_APP
lpszRetStr=(NLchar *)TEXT("A blocking sockets call is in progress.");
#else
lpszRetStr=(NLchar *)TEXT("The socket is non-blocking and the connection could not be established immediately.");
#endif
break;
case EDESTADDRREQ:
lpszRetStr=(NLchar *)TEXT("Destination address is required.");
break;
case EISCONN:
lpszRetStr=(NLchar *)TEXT("Socket is already connected.");
break;
case ENETRESET:
lpszRetStr=(NLchar *)TEXT("Connection has been broken due to the remote host resetting.");
break;
case EOPNOTSUPP:
lpszRetStr=(NLchar *)TEXT("Operation not supported on socket");
break;
case ESHUTDOWN:
lpszRetStr=(NLchar *)TEXT("Socket has been shut down.");
break;
case EMSGSIZE:
lpszRetStr=(NLchar *)TEXT("The message was too large to fit into the specified buffer and was truncated.");
break;
case EALREADY:
lpszRetStr=(NLchar *)TEXT("A non-blocking connect call is in progress on the specified socket.");
break;
case ENOPROTOOPT:
lpszRetStr=(NLchar *)TEXT("Bad protocol option.");
break;
case EPFNOSUPPORT:
lpszRetStr=(NLchar *)TEXT("Protocol family not supported.");
break;
case ETOOMANYREFS:
lpszRetStr=(NLchar *)TEXT("Too many references; can't splice.");
break;
case ELOOP:
lpszRetStr=(NLchar *)TEXT("Too many levels of symbolic links.");
break;
case ENAMETOOLONG:
lpszRetStr=(NLchar *)TEXT("File name too long.");
break;
case ENOTEMPTY:
lpszRetStr=(NLchar *)TEXT("Directory not empty.");
break;
#if !defined(macintosh)
case EUSERS:
lpszRetStr=(NLchar *)TEXT("Too many users.");
break;
case EDQUOT:
lpszRetStr=(NLchar *)TEXT("Disc quota exceeded.");
break;
case ESTALE:
lpszRetStr=(NLchar *)TEXT("Stale NFS file handle.");
break;
case EREMOTE:
lpszRetStr=(NLchar *)TEXT("Too many levels of remote in path.");
break;
#endif
default:
#ifdef HL_WINDOWS_APP
{
static NLchar temp[256];
/* FormatMessage is unicode compliant */
(void)FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD)err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)temp, 256, NULL);
lpszRetStr = temp;
}
#else
lpszRetStr=strerror(err);
#endif
break;
}
return (const NLchar*)lpszRetStr;
}
HL_EXP const /*@observer@*/ NLchar* HL_APIENTRY nlGetErrorStr(NLenum err)
{
NLchar *retStr;
switch(err) {
case NL_NO_ERROR:
retStr = (NLchar *)TEXT("No HawkNL error.");
break;
case NL_NO_NETWORK:
retStr = (NLchar *)TEXT("No network was found on init.");
break;
case NL_OUT_OF_MEMORY:
retStr = (NLchar *)TEXT("Out of memory.");
break;
case NL_INVALID_ENUM:
retStr = (NLchar *)TEXT("Invalid NLenum.");
break;
case NL_INVALID_SOCKET:
retStr = (NLchar *)TEXT("Socket is not valid.");
break;
case NL_INVALID_PORT:
retStr = (NLchar *)TEXT("Port could not be opened.");
break;
case NL_INVALID_TYPE:
retStr = (NLchar *)TEXT("Network type is not available.");
break;
case NL_SYSTEM_ERROR:
retStr = (NLchar *)TEXT("A system error occurred, call nlGetSystemError.");
break;
case NL_SOCK_DISCONNECT:
retStr = (NLchar *)TEXT("Connection error: Close socket.");
break;
case NL_NOT_LISTEN:
retStr = (NLchar *)TEXT("Socket has not been set to listen.");
break;
case NL_CON_REFUSED:
retStr = (NLchar *)TEXT("Connection refused.");
break;
case NL_NO_PENDING:
retStr = (NLchar *)TEXT("No pending connections to accept.");
break;
case NL_BAD_ADDR:
retStr = (NLchar *)TEXT("The address or port are not valid.");
break;
case NL_MESSAGE_END:
retStr = (NLchar *)TEXT("TCP message end.");
break;
case NL_NULL_POINTER:
retStr = (NLchar *)TEXT("A NULL pointer was passed to a function.");
break;
case NL_INVALID_GROUP:
retStr = (NLchar *)TEXT("The group is not valid.");
break;
case NL_OUT_OF_GROUPS:
retStr = (NLchar *)TEXT("Out of groups.");
break;
case NL_OUT_OF_GROUP_SOCKETS:
retStr = (NLchar *)TEXT("The group is full.");
break;
case NL_BUFFER_SIZE:
retStr = (NLchar *)TEXT("The buffer is too small.");
break;
case NL_PACKET_SIZE:
retStr = (NLchar *)TEXT("The packet is too large.");
break;
case NL_WRONG_TYPE:
retStr = (NLchar *)TEXT("Wrong socket type.");
break;
case NL_CON_PENDING:
retStr = (NLchar *)TEXT("A non-blocking connection is still pending.");
break;
case NL_SELECT_NET_ERROR:
retStr = (NLchar *)TEXT("A network type is already selected.");
break;
case NL_PACKET_SYNC:
retStr = (NLchar *)TEXT("The NL_RELIABLE_PACKET stream is out of sync.");
break;
case NL_TLS_ERROR:
retStr = (NLchar *)TEXT("Thread local storage could not be created.");
break;
case NL_TIMED_OUT:
retStr = (NLchar *)TEXT("The function timed out.");
break;
case NL_SOCKET_NOT_FOUND:
retStr = (NLchar *)TEXT("The socket was not found in the group.");
break;
case NL_STRING_OVER_RUN:
retStr = (NLchar *)TEXT("The string could cause a buffer over-run or corrupt memory.");
break;
case NL_CONNECTED:
retStr = (NLchar *)TEXT("The socket is already connected.");
break;
default:
retStr = (NLchar *)TEXT("Undefined HawkNL error.");
break;
}
return (const NLchar*)retStr;
}
diff --git a/util/network/hawknl/src/group.c b/util/network/hawknl/src/group.c
index 5fe5b5b6..0e59c1dc 100644
--- a/util/network/hawknl/src/group.c
+++ b/util/network/hawknl/src/group.c
@@ -1,527 +1,527 @@
/*
HawkNL cross platform network library
Copyright (C) 2000-2004 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
*/
#include <string.h>
#define FD_SETSIZE 8192
#if defined WIN32 || defined WIN64 || defined (_WIN32_WCE)
/* Windows systems */
#include "wsock.h"
#else
/* Unix-style systems or macs with posix support */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET int
#endif
-#include "nlinternal.h"
+#include "hawknl/nlinternal.h"
static HTmutex grouplock;
typedef struct
{
NLsocket *sockets; /* the list of sockets in this group */
NLint maxsockets; /* the number of sockets allocated */
NLint numsockets; /* the number of sockets stored */
fd_set *fdset; /* for nlPollGroup */
SOCKET highest; /* for nlPollGroup */
} nl_group_t;
typedef /*@only@*/ nl_group_t *pnl_group_t;
static /*@only@*/ pnl_group_t *groups;
static NLint nlnextgroup = 0;
static NLint nlnumgroups = 0;
/* Internal functions */
void nlGroupLock(void)
{
(void)htMutexLock(&grouplock);
}
void nlGroupUnlock(void)
{
(void)htMutexUnlock(&grouplock);
}
NLboolean nlGroupInit(void)
{
if(groups == NULL)
{
groups = (nl_group_t **)malloc(NL_MAX_GROUPS * sizeof(nl_group_t *));
}
if(groups == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
return NL_FALSE;
}
memset(groups, 0, NL_MAX_GROUPS * sizeof(nl_group_t *));
if(htMutexInit(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return NL_TRUE;
}
void nlGroupShutdown(void)
{
if(groups != NULL)
{
NLint i;
for(i=0;i<NL_MAX_GROUPS;i++)
{
if(groups[i] != NULL)
{
(void)nlGroupDestroy(i + NL_FIRST_GROUP);
}
}
free(groups);
groups = NULL;
}
(void)htMutexDestroy(&grouplock);
}
SOCKET nlGroupGetFdset(NLint group, fd_set *fd)
{
NLint realgroup = group - NL_FIRST_GROUP;
nl_group_t *pgroup = NULL;
if(groups == NULL)
{
nlSetError(NL_NO_NETWORK);
return INVALID_SOCKET;
}
if(realgroup < 0)
{
nlSetError(NL_INVALID_GROUP);
return INVALID_SOCKET;
}
pgroup = groups[realgroup];
if(pgroup == NULL)
{
nlSetError(NL_INVALID_GROUP);
return INVALID_SOCKET;
}
/* if fdset is NULL, then create it */
if(pgroup->fdset == NULL)
{
int i;
SOCKET realsock;
/* create the fd_set */
pgroup->fdset = (fd_set *)malloc(sizeof(fd_set));
if(pgroup->fdset == NULL)
{
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_MEMORY);
return INVALID_SOCKET;
}
FD_ZERO(pgroup->fdset);
pgroup->highest = 0;
for(i=0;i<pgroup->numsockets;i++)
{
realsock = (SOCKET)nlSockets[pgroup->sockets[i]]->realsocket;
FD_SET(realsock, pgroup->fdset);
if(pgroup->highest < realsock + 1)
{
pgroup->highest = realsock + 1;
}
}
}
memcpy(fd, pgroup->fdset, sizeof(fd_set));
return pgroup->highest;
}
/* Group management API */
HL_EXP NLint HL_APIENTRY nlGroupCreate(void)
{
NLint newgroup = NL_INVALID;
nl_group_t *pgroup = NULL;
if(groups == NULL)
{
nlSetError(NL_NO_NETWORK);
return NL_INVALID;
}
if(htMutexLock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_INVALID;
}
if(nlnumgroups == NL_MAX_GROUPS)
{
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_GROUPS);
return NL_INVALID;
}
/* get a group number */
if(nlnumgroups == nlnextgroup)
{
/* do not increment nlnextgroup here, wait in case of malloc failure */
newgroup = nlnextgroup + 1;
}
else
/* there is an open group slot somewhere below nlnextgroup */
{
NLint i;
for(i=0;i<nlnextgroup;i++)
{
if(groups[i] == NULL)
{
/* found an open group slot */
newgroup = i;
}
}
/* let's check just to make sure we did find a group */
if(newgroup == NL_INVALID)
{
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_MEMORY);
return NL_INVALID;
}
}
/* allocate the memory */
pgroup = (nl_group_t *)malloc((size_t)(sizeof(nl_group_t)));
if(pgroup == NULL)
{
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_MEMORY);
return NL_INVALID;
}
else
{
NLint i;
pgroup->sockets = (NLsocket *)malloc(NL_MIN_SOCKETS * sizeof(NLsocket *));
if(pgroup->sockets == NULL)
{
free(pgroup);
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_MEMORY);
return NL_INVALID;
}
pgroup->maxsockets = NL_MIN_SOCKETS;
/* fill with -1, since 0 is a valid socket number */
for(i=0;i<pgroup->maxsockets;i++)
{
pgroup->sockets[i] = -1;
}
pgroup->numsockets = 0;
pgroup->fdset = NULL;
pgroup->highest = 0;
groups[newgroup] = pgroup;
}
nlnumgroups++;
if(nlnumgroups == newgroup)
{
nlnextgroup = nlnumgroups;
}
if(htMutexUnlock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_INVALID;
}
/* adjust the group number */
return (newgroup + NL_FIRST_GROUP);
}
HL_EXP NLboolean HL_APIENTRY nlGroupDestroy(NLint group)
{
NLint realgroup = group - NL_FIRST_GROUP;
if(groups == NULL)
{
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
if(realgroup < 0)
{
nlSetError(NL_INVALID_GROUP);
return NL_FALSE;
}
if(htMutexLock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
if(groups[realgroup] != NULL)
{
if(groups[realgroup]->fdset != NULL)
{
free(groups[realgroup]->fdset);
}
if(groups[realgroup]->sockets != NULL)
{
free(groups[realgroup]->sockets);
}
free(groups[realgroup]);
groups[realgroup] = NULL;
nlnumgroups--;
}
if(htMutexUnlock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return NL_TRUE;
}
HL_EXP NLboolean HL_APIENTRY nlGroupAddSocket(NLint group, NLsocket socket)
{
NLint realgroup = group - NL_FIRST_GROUP;
NLint i;
nl_group_t *pgroup = NULL;
if(groups == NULL)
{
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
if(realgroup < 0)
{
nlSetError(NL_INVALID_GROUP);
return NL_FALSE;
}
/* add the socket to the group */
if(htMutexLock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
pgroup = groups[realgroup];
/* allocate more sockets as needed */
if(pgroup->numsockets == pgroup->maxsockets)
{
NLint oldmax = pgroup->maxsockets;
NLint j;
NLsocket *newsockets;
if(oldmax == NL_MAX_GROUP_SOCKETS)
{
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_GROUP_SOCKETS);
return NL_FALSE;
}
pgroup->maxsockets *= 2;
if(pgroup->maxsockets > NL_MAX_GROUP_SOCKETS)
{
pgroup->maxsockets = NL_MAX_GROUP_SOCKETS;
}
if((newsockets = (NLsocket *)realloc(pgroup->sockets, pgroup->maxsockets * sizeof(NLsocket *))) == NULL)
{
pgroup->maxsockets = oldmax;
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_MEMORY);
return NL_FALSE;
}
/* set the new sockets to -1 */
for(j=oldmax;j<pgroup->maxsockets;j++)
{
newsockets[j] = -1;
}
pgroup->sockets = newsockets;
}
for(i=0;i<pgroup->maxsockets;i++)
{
if(pgroup->sockets[i] == -1)
{
pgroup->sockets[i] = socket;
if(pgroup->fdset != NULL)
{
SOCKET realsock;
/* make sure the socket is valid */
if(nlIsValidSocket(socket) == NL_FALSE)
{
(void)htMutexUnlock(&grouplock);
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
realsock = (SOCKET)nlSockets[socket]->realsocket;
FD_SET(realsock, pgroup->fdset);
if(pgroup->highest < realsock + 1)
{
pgroup->highest = realsock + 1;
}
}
break;
}
}
if(i == pgroup->maxsockets)
{
(void)htMutexUnlock(&grouplock);
nlSetError(NL_OUT_OF_GROUP_SOCKETS);
return NL_FALSE;
}
pgroup->numsockets++;
if(htMutexUnlock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean nlGroupGetSocketsINT(NLint group, NLsocket *socket, NLint *number)
{
NLint realgroup = group - NL_FIRST_GROUP;
NLint len, i;
nl_group_t *pgroup = NULL;
if(socket == NULL || number == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
if(groups == NULL)
{
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
if(realgroup < 0)
{
nlSetError(NL_INVALID_GROUP);
*number = 0;
return NL_FALSE;
}
pgroup = groups[realgroup];
len = *number;
if(len > pgroup->numsockets)
{
len = pgroup->numsockets;
}
for(i=0;i<len;i++)
{
socket[i] = pgroup->sockets[i];
}
*number = len;
return NL_TRUE;
}
HL_EXP NLboolean HL_APIENTRY nlGroupGetSockets(NLint group, NLsocket *socket, NLint *number)
{
NLboolean result;
if(htMutexLock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
result = nlGroupGetSocketsINT(group, socket, number);
if(htMutexUnlock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return result;
}
HL_EXP NLboolean HL_APIENTRY nlGroupDeleteSocket(NLint group, NLsocket socket)
{
NLint realgroup = group - NL_FIRST_GROUP;
NLint i;
nl_group_t *pgroup = NULL;
if(groups == NULL)
{
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
if(realgroup < 0)
{
nlSetError(NL_INVALID_GROUP);
return NL_FALSE;
}
/* delete the socket from the group */
if(htMutexLock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
pgroup = groups[realgroup];
for(i=0;i<pgroup->numsockets;i++)
{
/* check for match */
if(pgroup->sockets[i] == socket)
break;
}
if(i == pgroup->numsockets)
{
/* did not find the socket */
(void)htMutexUnlock(&grouplock);
nlSetError(NL_SOCKET_NOT_FOUND);
return NL_FALSE;
}
/* now pgroup[i] points to the socket to delete */
/* shift all other sockets down to close the gap */
i++;
for(;i<pgroup->maxsockets;i++)
{
pgroup->sockets[i - 1] = pgroup->sockets[i];
/* check for end of list */
if(pgroup->sockets[i] == -1)
break;
}
pgroup->numsockets--;
if(pgroup->fdset != NULL)
{
/* make sure the socket is valid */
if(nlIsValidSocket(socket) == NL_TRUE)
{
SOCKET realsock;
realsock = (SOCKET)nlSockets[socket]->realsocket;
FD_CLR(realsock, pgroup->fdset);
}
else
{
/* the socket was already closed */
/* free the fdset so that it can be rebuilt */
free(pgroup->fdset);
pgroup->fdset = NULL;
(void)htMutexUnlock(&grouplock);
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
}
if(htMutexUnlock(&grouplock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return NL_TRUE;
}
diff --git a/util/network/hawknl/src/htcondition.c b/util/network/hawknl/src/htcondition.c
index c2cc6b12..3ff2b0df 100644
--- a/util/network/hawknl/src/htcondition.c
+++ b/util/network/hawknl/src/htcondition.c
@@ -1,276 +1,276 @@
/*
HawkThreads condition module
Copyright (C) 2003-2004 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
*/
-#include "htinternal.h"
+#include "hawknl/htinternal.h"
#ifdef HT_WIN_THREADS
enum {
SIGNAL = 0,
BROADCAST = 1,
MAX_EVENTS = 2
};
struct ht_cond_t
{
HANDLE events_[MAX_EVENTS];
};
#else /* !HT_WIN_THREADS */
#ifdef __FreeBSD__
#include <sys/types.h>
#endif
#include <sys/timeb.h>
#ifdef HL_WINDOWS_APP
#define timeb _timeb
#define ftime _ftime
#else
#include <sys/time.h>
#endif /* HL_WINDOWS_APP */
#include <pthread.h>
struct ht_cond_t
{
pthread_cond_t cond;
pthread_mutex_t mutex;
};
#endif /* !HT_WIN_THREADS */
HL_EXP int HL_APIENTRY htCondInit(HTcond *cond)
{
if(cond == NULL)
{
return EINVAL;
}
else
{
#ifdef HT_WIN_THREADS
HTcond cv = NULL;
cv = (HTcond)malloc(sizeof(struct ht_cond_t));
if(cv == NULL)
{
return ENOMEM;
}
cv->events_[SIGNAL] = CreateEvent(NULL, FALSE, FALSE, NULL);
cv->events_[BROADCAST] = CreateEvent(NULL, TRUE, FALSE, NULL);
#else
int result;
HTcond cv = NULL;
cv = (HTcond)malloc(sizeof(struct ht_cond_t));
if(cv == NULL)
{
return ENOMEM;
}
result = pthread_cond_init((pthread_cond_t *)&cv->cond, NULL);
if(result != 0)
{
free(cv);
return result;
}
result = pthread_mutex_init((pthread_mutex_t *)&cv->mutex, NULL);
if(result != 0)
{
(void)pthread_cond_destroy((pthread_cond_t *)&cv->cond);
free(cv);
return result;
}
#endif
*cond = cv;
}
return 0;
}
HL_EXP int HL_APIENTRY htCondWait(HTcond *cond, int timeout)
{
if(cond == NULL)
{
return EINVAL;
}
if(*cond == NULL)
{
return EINVAL;
}
if(timeout <= 0)
{
HTcond cv = *cond;
#ifdef HT_WIN_THREADS
DWORD result;
result = WaitForMultipleObjects (2,cv->events_, FALSE, INFINITE);
if(result == WAIT_FAILED)
{
return EINVAL;
}
#else
int result = 0;
(void)pthread_mutex_lock((pthread_mutex_t *)&cv->mutex);
result = pthread_cond_wait((pthread_cond_t *)&cv->cond, (pthread_mutex_t *)&cv->mutex);
if(result != 0)
{
return result;
}
(void)pthread_mutex_unlock((pthread_mutex_t *)&cv->mutex);
#endif
}
else
{
HTcond cv = *cond;
#ifdef HT_WIN_THREADS
DWORD result;
result = WaitForMultipleObjects (2, cv->events_, FALSE, (DWORD)timeout);
if(result == WAIT_FAILED)
{
return EINVAL;
}
else if(result == (DWORD)WAIT_TIMEOUT)
{
return (int)ETIMEDOUT;
}
}
#else
int result = 0;
struct timespec tv;
struct timeb t;
long ms;
/* convert timeout to an absolute time */
ftime(&t);
ms = t.millitm + timeout;
tv.tv_sec = t.time + (ms / 1000);
tv.tv_nsec = (ms % 1000) * 1000000;
(void)pthread_mutex_lock((pthread_mutex_t *)&cv->mutex);
result = pthread_cond_timedwait((pthread_cond_t *)&cv->cond,
(pthread_mutex_t *)&cv->mutex, &tv);
if(result == ETIMEDOUT)
{
(void)pthread_mutex_unlock((pthread_mutex_t *)&cv->mutex);
return ETIMEDOUT;
}
else if(result != 0)
{
return result;
}
(void)pthread_mutex_unlock((pthread_mutex_t *)&cv->mutex);
}
#endif
return 0;
}
HL_EXP int HL_APIENTRY htCondSignal(HTcond *cond)
{
HTcond cv;
if(cond == NULL)
{
return EINVAL;
}
if(*cond == NULL)
{
return EINVAL;
}
else
{
#ifdef HT_WIN_THREADS
cv = *cond;
if(PulseEvent(cv->events_[SIGNAL]) == 0)
{
return EINVAL;
}
#else
int result;
cv = *cond;
result = pthread_cond_signal((pthread_cond_t *)&cv->cond);
if(result != 0)
{
return result;
}
#endif
}
return 0;
}
HL_EXP int HL_APIENTRY htCondBroadcast(HTcond *cond)
{
if(cond == NULL)
{
return EINVAL;
}
if(*cond == NULL)
{
return EINVAL;
}
else
{
HTcond cv = *cond;
#ifdef HT_WIN_THREADS
if(PulseEvent(cv->events_[BROADCAST]) == 0)
{
return EINVAL;
}
return 0;
#else
return pthread_cond_broadcast((pthread_cond_t *)&cv->cond);
#endif
}
}
HL_EXP int HL_APIENTRY htCondDestroy(HTcond *cond)
{
if(cond == NULL)
{
return EINVAL;
}
if(*cond == NULL)
{
return EINVAL;
}
else
{
HTcond cv = *cond;
int result = 0;
#ifdef HT_WIN_THREADS
(void)CloseHandle(cv->events_[SIGNAL]);
(void)CloseHandle(cv->events_[BROADCAST]);
#else
result = pthread_cond_destroy((pthread_cond_t *)&cv->cond);
#endif
free(*cond);
*cond = NULL;
return result;
}
}
diff --git a/util/network/hawknl/src/hthread.c b/util/network/hawknl/src/hthread.c
index 780823e9..e6fe0cba 100644
--- a/util/network/hawknl/src/hthread.c
+++ b/util/network/hawknl/src/hthread.c
@@ -1,180 +1,180 @@
/*
HawkThreads thread module
Copyright (C) 2003-2004 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
*/
-#include "htinternal.h"
+#include "hawknl/htinternal.h"
#ifdef HT_WIN_THREADS
typedef struct {
void *(*func) (void *);
void *arg;
} ThreadParms;
static unsigned __stdcall threadfunc(void *arg)
{
void *(*func) (void *);
void *args;
func = ((ThreadParms *)arg)->func;
args = ((ThreadParms *)arg)->arg;
free(arg);
return (unsigned)((*func)(args));
}
#if defined (_WIN32_WCE)
#define _beginthreadex(security, \
stack_size, \
start_proc, \
arg, \
flags, \
pid) \
CreateThread(security, \
stack_size, \
(LPTHREAD_START_ROUTINE) start_proc, \
arg, \
flags, \
pid)
#else /* !(_WIN32_WCE) */
#include <process.h>
#endif /* !(_WIN32_WCE) */
#else /* !HT_WIN_THREADS */
/* POSIX systems */
#include <pthread.h>
#include <sched.h>
#endif /* !HT_WIN_THREADS */
#ifndef HL_WINDOWS_APP
#include <unistd.h>
#endif /* HL_WINDOWS_APP */
HL_EXP HThreadID HL_APIENTRY htThreadCreate(HThreadFunc func, void *data, int joinable)
{
/* Windows threads */
#ifdef HT_WIN_THREADS
HANDLE h;
unsigned tid;
ThreadParms *p;
p = (ThreadParms *)malloc(sizeof(ThreadParms));
if(p == NULL)
{
SetLastError((DWORD)ENOMEM);
return (HThreadID)HT_INVALID;
}
p->func = func;
p->arg = data;
h = (HANDLE)_beginthreadex(NULL, 0, threadfunc, p, 0, &tid);
if(h == (HANDLE)(0))
{
return (HThreadID)HT_INVALID;
}
if(joinable == HT_FALSE)
{
(void)CloseHandle(h);
return NULL;
}
return (HThreadID)h;
/* POSIX systems */
#else
pthread_attr_t attr;
pthread_t tid;
int result;
(void)pthread_attr_init(&attr);
if(joinable == HT_FALSE)
{
(void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
}
else
{
(void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
}
result = pthread_create(&tid, &attr, func, data);
(void)pthread_attr_destroy(&attr);
if(result != 0)
{
#ifdef HL_WINDOWS_APP
SetLastError((DWORD)result);
#endif
return (HThreadID)HT_INVALID;
}
if(joinable == HT_FALSE)
{
return NULL;
}
return (HThreadID)tid;
#endif
}
HL_EXP void HL_APIENTRY htThreadYield(void)
{
/* Windows threads */
#ifdef HT_WIN_THREADS
Sleep((DWORD)0);
/* POSIX systems */
#else
(void)sched_yield();
#endif
}
HL_EXP int HL_APIENTRY htThreadJoin(HThreadID threadID, void **status)
{
#ifdef HT_WIN_THREADS
/* Windows threads */
if(WaitForSingleObject((HANDLE)threadID, INFINITE) == WAIT_FAILED)
{
return EINVAL;
}
if(status != NULL)
{
(void)GetExitCodeThread((HANDLE)threadID, (LPDWORD)status);
}
(void)CloseHandle((HANDLE)threadID);
return 0;
#else
/* POSIX systems */
return pthread_join((pthread_t)threadID, status);
#endif
}
HL_EXP void HL_APIENTRY htThreadSleep(int mseconds)
{
#ifdef HL_WINDOWS_APP
Sleep((DWORD)mseconds);
#else /* !HL_WINDOWS_APP */
struct timespec tv;
tv.tv_sec = mseconds / 1000;
tv.tv_nsec = (mseconds % 1000) * 1000;
(void)nanosleep(&tv, NULL);
#endif /* !HL_WINDOWS_APP */
/* can use usleep if nanosleep is not supported on your platform */
/* (void)usleep(mseconds*1000); */
}
diff --git a/util/network/hawknl/src/htmutex.c b/util/network/hawknl/src/htmutex.c
index a3fdb1c3..38a67f39 100644
--- a/util/network/hawknl/src/htmutex.c
+++ b/util/network/hawknl/src/htmutex.c
@@ -1,192 +1,192 @@
/*
HawkThreads mutex module
Copyright (C) 2003-2004 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
*/
-#include "htinternal.h"
+#include "hawknl/htinternal.h"
#ifdef HT_WIN_THREADS
struct ht_mutex_t
{
CRITICAL_SECTION mutex;
DWORD thread;
};
#else /* !HT_WIN_THREADS */
#include <pthread.h>
#ifndef HL_WINDOWS_APP
#include <sys/errno.h>
#endif /* HL_WINDOWS_APP */
struct ht_mutex_t
{
pthread_mutex_t mutex;
};
#endif /* HT_WIN_THREADS */
HL_EXP int HL_APIENTRY htMutexInit(HTmutex *mutex)
{
if(mutex == NULL)
{
return EINVAL;
}
else
{
HTmutex mx;
#ifdef HT_WIN_THREADS
/* native Windows */
mx = (HTmutex)malloc(sizeof(struct ht_mutex_t));
if(mx == NULL)
{
return ENOMEM;
}
InitializeCriticalSection(&mx->mutex);
mx->thread = 0;
#else
/* POSIX */
pthread_mutexattr_t attr;
int result;
mx = (HTmutex)malloc(sizeof(struct ht_mutex_t));
if(mx == NULL)
{
return ENOMEM;
}
(void)pthread_mutexattr_init(&attr);
#if defined MACOSX || defined __FreeBSD__
/* GUSI is not fully POSIX compliant, and does not
* define PTHREAD_MUTEX_ERRORCHECK
* http://lists.apple.com/archives/unix-porting/2005/May/msg00021.html
*/
(void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
#else
(void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
#endif
result = pthread_mutex_init((pthread_mutex_t *)&mx->mutex, &attr);
(void)pthread_mutexattr_destroy(&attr);
if(result != 0)
{
return result;
}
#endif
*mutex = mx;
}
return 0;
}
HL_EXP int HL_APIENTRY htMutexLock(HTmutex *mutex)
{
if(mutex == NULL)
{
return EINVAL;
}
if(*mutex == NULL)
{
return EINVAL;
}
else
{
HTmutex mx = *mutex;
#ifdef HT_WIN_THREADS
DWORD threadid = GetCurrentThreadId();
/* native Windows */
/* this call will not stop recursion on a single thread */
EnterCriticalSection(&mx->mutex);
/* check for recursion */
if(mx->thread == threadid)
{
/* must call LeaveCriticalSection for each EnterCriticalSection */
/* so this nullifies the above call to EnterCriticalSection*/
LeaveCriticalSection(&mx->mutex);
return EDEADLK;
}
else
{
mx->thread = threadid;
}
return 0;
#else
/* POSIX */
return pthread_mutex_lock((pthread_mutex_t *)&mx->mutex);
#endif
}
}
HL_EXP int HL_APIENTRY htMutexUnlock(HTmutex *mutex)
{
if(mutex == NULL)
{
return EINVAL;
}
if(*mutex == NULL)
{
return EINVAL;
}
else
{
HTmutex mx = *mutex;
#ifdef HT_WIN_THREADS
DWORD threadid = GetCurrentThreadId();
/* native Windows */
if((mx->thread == 0) ||(mx->thread != threadid))
{
return EPERM;
}
mx->thread = 0;
LeaveCriticalSection(&mx->mutex);
return 0;
#else
/* POSIX */
return pthread_mutex_unlock((pthread_mutex_t *)&mx->mutex);
#endif
}
}
HL_EXP int HL_APIENTRY htMutexDestroy(HTmutex *mutex)
{
if(mutex == NULL)
{
return EINVAL;
}
if(*mutex == NULL)
{
return EINVAL;
}
else
{
HTmutex mx = *mutex;
int result = 0;
#ifdef HT_WIN_THREADS
/* native Windows */
DeleteCriticalSection(&mx->mutex);
#else
/* POSIX */
result = pthread_mutex_destroy((pthread_mutex_t *)&mx->mutex);
#endif
free(*mutex);
*mutex = NULL;
return result;
}
}
diff --git a/util/network/hawknl/src/ipx.c b/util/network/hawknl/src/ipx.c
index 35c8a05f..298f9a80 100644
--- a/util/network/hawknl/src/ipx.c
+++ b/util/network/hawknl/src/ipx.c
@@ -1,563 +1,563 @@
/*
HawkNL cross platform network library
Copyright (C) 2000-2004 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
*/
#include <memory.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define FD_SETSIZE 8192
#if defined WIN32 || defined WIN64
-#include "wsock.h"
+#include "hawknl/wsock.h"
#ifdef _MSC_VER
#pragma warning (disable:4100) /* disable "unreferenced formal parameter" */
#endif
#else
/* Unix-style systems */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#define closesocket close
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKET int
/* define INADDR_NONE if not already */
#ifndef INADDR_NONE
#define INADDR_NONE ((unsigned long) -1)
#define sockerrno errno
#endif
#endif
-#include "nlinternal.h"
-#include "sock.h"
+#include "hawknl/nlinternal.h"
+#include "hawknl/sock.h"
#ifdef NL_INCLUDE_IPX
-#include "ipx.h"
+#include "hawknl/ipx.h"
typedef struct
{
NLaddress /*@temp@*/*address;
NLchar /*@temp@*/*name;
NLsocket socket;
} NLaddress_ex_t;
extern SOCKET nlGroupGetFdset(NLint group, /*@out@*/ fd_set *fd);
extern NLint sock_Error(void);
extern NLboolean sock_SetBlocking(SOCKET socket, NLboolean arg);
extern NLboolean sock_SetBroadcast(SOCKET socket);
extern NLboolean sock_SetReuseAddr(nl_socket_t *sock);
extern void sock_Close(NLsocket socket);
extern NLsocket sock_OpenINT(NLushort port, NLenum type, NLenum driver);
#define MAXHOSTNAMELEN 256
#define NL_CONNECT_STRING "HawkNL request connection."
#define NL_REPLY_STRING "HawkNL connection OK."
static NLaddress ipx_ouraddress;
static NLaddress ipx_ouraddress_copy;
static NLint ipxport = 0;
extern int backlog;
extern NLboolean reuseaddress;
/* is there a better way to get our address? */
static NLboolean ipx_GetHostAddress(NLaddress *address)
{
NLint addrlen = (NLint)sizeof(NLaddress);
SOCKET sock;
sock = socket(PF_IPX, SOCK_DGRAM, NSPROTO_IPX);
if(sock == INVALID_SOCKET)
{
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
((struct sockaddr_ipx *)address)->sa_family = AF_IPX;
memset(((struct sockaddr_ipx *)address)->sa_netnum, 0, 4);
memset(((struct sockaddr_ipx *)address)->sa_nodenum, 0, 6);
((struct sockaddr_ipx *)address)->sa_socket = 0;
if(bind(sock, (struct sockaddr *)address, (int)sizeof(struct sockaddr_ipx)) == SOCKET_ERROR)
{
nlSetError(NL_NO_NETWORK);
(void)closesocket(sock);
return NL_FALSE;
}
if(getsockname(sock, (struct sockaddr *)address, &addrlen) != 0)
{
nlSetError(NL_NO_NETWORK);
(void)closesocket(sock);
return NL_FALSE;
}
(void)closesocket(sock);
return NL_TRUE;
}
NLushort ipx_GetPort(SOCKET socket)
{
struct sockaddr_ipx addr;
int len;
len = (int)sizeof(struct sockaddr_ipx);
if(getsockname(socket, (struct sockaddr *)&addr, &len) != 0)
{
return 0;
}
return ntohs(addr.sa_socket);
}
NLboolean ipx_Init(void)
{
#ifdef HL_WINDOWS_APP
WSADATA libmibWSAdata;
if(WSAStartup(0x101,&libmibWSAdata) != 0)
{
return NL_FALSE;
}
#endif
if(ipx_GetHostAddress(&ipx_ouraddress) == NL_FALSE)
{
ipx_Shutdown();
return NL_FALSE;
}
return NL_TRUE;
}
void ipx_Shutdown(void)
{
#ifdef HL_WINDOWS_APP
(void)WSACleanup();
#endif
}
static SOCKET ipx_AcceptIPX(NLsocket nlsocket, struct sockaddr_ipx /*@out@*/ *newaddr)
{
nl_socket_t *sock = nlSockets[nlsocket];
struct sockaddr_ipx ouraddr;
SOCKET newsocket;
NLushort localport;
NLbyte buffer[NL_MAX_STRING_LENGTH];
socklen_t len = (socklen_t)sizeof(struct sockaddr_ipx);
NLint slen = (NLint)sizeof(NL_CONNECT_STRING);
NLbyte reply = (NLbyte)0x00;
NLint count = 0;
/* Get the packet and remote host address */
if(recvfrom((SOCKET)sock->realsocket, buffer, (int)sizeof(buffer), 0,
(struct sockaddr *)newaddr, &len) < (int)sizeof(NL_CONNECT_STRING))
{
nlSetError(NL_NO_PENDING);
return INVALID_SOCKET;
}
/* Let's check for the connection string */
buffer[slen - 1] = (NLbyte)0; /* null terminate for peace of mind */
if(strcmp(buffer, NL_CONNECT_STRING) != 0)
{
nlSetError(NL_NO_PENDING);
return INVALID_SOCKET;
}
/* open up a new socket on this end */
newsocket = socket(PF_IPX, SOCK_DGRAM, NSPROTO_IPX);
if(newsocket == INVALID_SOCKET)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
ouraddr.sa_family = AF_IPX;
memset(&ouraddr.sa_netnum, 0, 4);
memset(&ouraddr.sa_nodenum, 0, 6);
ouraddr.sa_socket = 0;
if(bind(newsocket, (struct sockaddr *)&ouraddr, len) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
/* get the new port */
localport = ipx_GetPort(newsocket);
/* create the return message */
writeShort(buffer, count, localport);
writeString(buffer, count, (NLchar *)TEXT(NL_REPLY_STRING));
/* send back the reply with our new port */
if(sendto((SOCKET)sock->realsocket, buffer, count, 0, (struct sockaddr *)newaddr,
(int)sizeof(struct sockaddr_ipx)) < count)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
/* send back a 0 length packet from our new port, needed for firewalls */
if(sendto(newsocket, &reply, 0, 0,
(struct sockaddr *)newaddr,
(int)sizeof(struct sockaddr_ipx)) < 0)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
/* connect the socket */
if(connect(newsocket, (struct sockaddr *)newaddr,
(int)sizeof(struct sockaddr_ipx)) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
return newsocket;
}
NLsocket ipx_AcceptConnection(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
nl_socket_t *newsock;
NLsocket newsocket;
SOCKET realsocket;
struct sockaddr_ipx newaddr;
if(sock->listen == NL_FALSE)
{
nlSetError(NL_NOT_LISTEN);
return NL_INVALID;
}
if(sock->type == NL_RELIABLE || sock->type == NL_RELIABLE_PACKETS)
{
NLint len = (NLint)sizeof(newaddr);
realsocket = accept((SOCKET)sock->realsocket,
(struct sockaddr *)&newaddr, &len);
if(realsocket == INVALID_SOCKET)
{
if(sockerrno == (int)EWOULDBLOCK || errno == EAGAIN)/* yes, we need to use errno here */
{
nlSetError(NL_NO_PENDING);
}
else
{
nlSetError(NL_SYSTEM_ERROR);
}
return NL_INVALID;
}
}
else if(sock->type == NL_UNRELIABLE)
{
realsocket = ipx_AcceptIPX(socket, &newaddr);
if(realsocket == INVALID_SOCKET)
{
/* error is already set in sock_AcceptUDP */
return NL_INVALID;
}
}
else
{
nlSetError(NL_WRONG_TYPE);
return NL_INVALID;
}
newsocket = nlGetNewSocket();
if(newsocket == NL_INVALID)
{
return NL_INVALID;
}
if(nlLockSocket(newsocket, NL_BOTH) == NL_FALSE)
{
return NL_INVALID;
}
newsock = nlSockets[newsocket];
/* update the remote address */
memcpy((char *)&newsock->addressin, (char *)&newaddr, sizeof(struct sockaddr_ipx));
newsock->realsocket = (NLint)realsocket;
newsock->localport = ipx_GetPort(realsocket);
newsock->remoteport = ipx_GetPortFromAddr((NLaddress *)&newsock->addressin);
if(newsock->blocking == NL_FALSE)
{
if(sock_SetBlocking((SOCKET)newsock->realsocket, NL_FALSE) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
sock_Close(newsocket);
return NL_INVALID;
}
}
newsock->reliable = sock->reliable;
return newsocket;
}
NLsocket ipx_Open(NLushort port, NLenum type)
{
return sock_OpenINT(port, type, NL_IPX);
}
NLchar *ipx_AddrToString(const NLaddress *address, NLchar *string)
{
_stprintf(string, TEXT("%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u"),
(unsigned int)((struct sockaddr_ipx *)address)->sa_netnum[0] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_netnum[1] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_netnum[2] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_netnum[3] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_nodenum[0] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_nodenum[1] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_nodenum[2] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_nodenum[3] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_nodenum[4] & 0xff,
(unsigned int)((struct sockaddr_ipx *)address)->sa_nodenum[5] & 0xff,
ntohs(((struct sockaddr_ipx *)address)->sa_socket));
return string;
}
NLboolean ipx_StringToAddr(const NLchar *string, NLaddress *address)
{
int val = 0;
NLchar buffer[3];
buffer[2] = (NLchar)0;
memset(address, 0, sizeof(NLaddress));
((struct sockaddr_ipx *)address)->sa_family = AF_IPX;
address->valid = NL_FALSE;
#define DO(src,dest) \
buffer[0] = string[(sizeof(NLchar) * src)]; \
buffer[1] = string[src + 1]; \
if(_stscanf (buffer, (const NLchar *)TEXT("%x"), &val) != 1) \
return NL_FALSE; \
((struct sockaddr_ipx *)address)->dest = (char)val
DO(0, sa_netnum[0]);
DO(2, sa_netnum[1]);
DO(4, sa_netnum[2]);
DO(6, sa_netnum[3]);
DO(9, sa_nodenum[0]);
DO(11, sa_nodenum[1]);
DO(13, sa_nodenum[2]);
DO(15, sa_nodenum[3]);
DO(17, sa_nodenum[4]);
DO(19, sa_nodenum[5]);
#undef DO
(void)_stscanf(&string[(sizeof(NLchar) * 22)], (const NLchar *)TEXT("%d"), &val);
((struct sockaddr_ipx *)address)->sa_socket = htons((unsigned short)val);
address->valid = NL_TRUE;
return NL_TRUE;
}
NLboolean ipx_GetLocalAddr(NLsocket socket, NLaddress *address)
{
nl_socket_t *sock = nlSockets[socket];
memcpy(address, &ipx_ouraddress, sizeof(NLaddress));
ipx_SetAddrPort(address, sock->localport);
address->valid = NL_TRUE;
return NL_TRUE;
}
NLaddress *ipx_GetAllLocalAddr(NLint *count)
{
*count = 1;
memcpy(&ipx_ouraddress_copy, &ipx_ouraddress, sizeof(NLaddress));
ipx_ouraddress_copy.valid = NL_TRUE;
return &ipx_ouraddress_copy;
}
NLboolean ipx_SetLocalAddr(const NLaddress *address)
{
memcpy(&ipx_ouraddress, address, sizeof(NLaddress));
return NL_TRUE;
}
NLchar *ipx_GetNameFromAddr(const NLaddress *address, NLchar *name)
{
return ipx_AddrToString(address, name);
}
NLboolean ipx_GetNameFromAddrAsync(const NLaddress *address, NLchar *name)
{
(void)ipx_AddrToString(address, name);
return NL_TRUE;
}
NLboolean ipx_GetAddrFromName(const NLchar *name, NLaddress *address)
{
NLint n;
NLchar buffer[(sizeof(NLchar) * 32)];
address->valid = NL_TRUE;
n = (NLint)_tcslen(name);
if(n == (NLint)(sizeof(NLchar) * 12))
{
_stprintf(buffer, TEXT("00000000:%s:%d"), name, ipxport);
return ipx_StringToAddr (buffer, address);
}
if(n == (NLint)(sizeof(NLchar) * 21))
{
_stprintf(buffer, TEXT("%s:%d"), name, ipxport);
return ipx_StringToAddr (buffer, address);
}
if((n > (NLint)(sizeof(NLchar) * 21)) && (n <= (NLint)(sizeof(NLchar) * 27)))
{
return ipx_StringToAddr (name, address);
}
memset(address, 0, sizeof(NLaddress));
address->valid = NL_FALSE;
return NL_FALSE;
}
NLboolean ipx_GetAddrFromNameAsync(const NLchar *name, NLaddress *address)
{
return ipx_GetAddrFromName(name, address);
}
NLboolean ipx_AddrCompare(const NLaddress *address1, const NLaddress *address2)
{
if(((struct sockaddr_ipx *)address1)->sa_family != ((struct sockaddr_ipx *)address2)->sa_family)
return NL_FALSE;
if(memcmp(((struct sockaddr_ipx *)address1)->sa_netnum, ((struct sockaddr_ipx *)address2)->sa_netnum, 4) != 0)
return NL_FALSE;
if(memcmp(((struct sockaddr_ipx *)address1)->sa_nodenum, ((struct sockaddr_ipx *)address2)->sa_nodenum, 6) != 0)
return NL_FALSE;
if(((struct sockaddr_ipx *)address1)->sa_socket != ((struct sockaddr_ipx *)address2)->sa_socket)
return NL_FALSE;
return NL_TRUE;
}
NLushort ipx_GetPortFromAddr(const NLaddress *address)
{
return ntohs(((struct sockaddr_ipx *)address)->sa_socket);
}
void ipx_SetAddrPort(NLaddress *address, NLushort port)
{
((struct sockaddr_ipx *)address)->sa_socket = htons((NLushort)port);
}
NLboolean ipx_Hint(NLenum name, NLint arg)
{
switch(name) {
case NL_LISTEN_BACKLOG:
backlog = arg;
break;
case NL_REUSE_ADDRESS:
reuseaddress = (NLboolean)(arg != 0 ? NL_TRUE : NL_FALSE);
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean ipx_SetSocketOpt(NLsocket socket, NLenum name, NLint arg)
{
nl_socket_t *sock = nlSockets[socket];
switch (name) {
case NL_BLOCKING_IO:
sock->blocking = (NLboolean)(arg != 0 ? NL_TRUE : NL_FALSE);
if(sock_SetBlocking((SOCKET)sock->realsocket, sock->blocking) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
break;
case NL_REUSE_ADDRESS:
if(sock_SetReuseAddr(sock) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
NLint ipx_GetSocketOpt(NLsocket socket, NLenum name)
{
nl_socket_t *sock = nlSockets[socket];
switch (name) {
case NL_BLOCKING_IO:
return (NLint)sock->blocking;
case NL_REUSE_ADDRESS:
return (NLint)sock->reuseaddr;
default:
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
}
#else /* NL_INCLUDE_IPX */
/* include dummy functions so that sock.c will compile */
NLushort ipx_GetPort(SOCKET socket)
{
return 0;
}
NLushort ipx_GetPortFromAddr(const NLaddress *address)
{
return 0;
}
#endif /* NL_INCLUDE_IPX */
diff --git a/util/network/hawknl/src/loopback.c b/util/network/hawknl/src/loopback.c
index f13aff8a..001a11c3 100644
--- a/util/network/hawknl/src/loopback.c
+++ b/util/network/hawknl/src/loopback.c
@@ -1,1045 +1,1045 @@
/*
HawkNL cross platform network library
Copyright (C) 2000-2004 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
*/
#include <string.h>
#include <stdio.h>
#if defined (_WIN32_WCE)
#define errno GetLastError()
#else
#include <errno.h>
#endif
-#include "nlinternal.h"
+#include "hawknl/nlinternal.h"
#ifdef HL_WINDOWS_APP
/* Windows systems */
-#include "wsock.h"
+#include "hawknl/wsock.h"
#else
/* Unix-style systems or macs with posix support */
#include <netinet/in.h> /* for ntohs and htons */
#endif
#ifdef NL_INCLUDE_LOOPBACK
-#include "loopback.h"
+#include "hawknl/loopback.h"
static NLaddress loopback_ouraddress;
static NLint loopgroup;
static volatile NLboolean reuseaddress = NL_FALSE;
static HTmutex portlock; /* In memory of my step-father, Don Portlock,
who passed away Jan 12, 2001 - Phil */
static volatile NLushort newport = 1024;
static NLushort loopback_getNextPort(void)
{
(void)htMutexLock(&portlock);
newport += 1;
if (newport < 1024){
newport = 1024;
}
(void)htMutexUnlock(&portlock);
return newport;
}
static NLboolean loopback_ScanPort(NLushort port, NLenum type)
{
NLint numsockets = NL_MAX_GROUP_SOCKETS;
NLsocket temp[NL_MAX_GROUP_SOCKETS];
if(reuseaddress == NL_TRUE)
{
return NL_TRUE;
}
if(nlGroupGetSockets(loopgroup, (NLsocket *)&temp, &numsockets) == NL_FALSE)
{
return NL_FALSE;
}
if(numsockets == 0)
{
return NL_TRUE;
}
while(numsockets-- > 0)
{
nl_socket_t *sock = nlSockets[temp[numsockets]];
if(sock->type == type && sock->localport == port)
{
return NL_FALSE;
}
}
return NL_TRUE;
}
static NLushort loopback_TryPort(NLushort port, NLenum type)
{
NLint ntries = 500; /* this is to prevent an infinite loop */
if(port > 0)
{
if(loopback_ScanPort(port, type) == NL_TRUE)
{
return port;
}
else
{
return 0;
}
}
/* let's find our own port number */
while(ntries-- > 0)
{
port = loopback_getNextPort();
if(loopback_ScanPort(port, type) == NL_TRUE)
{
return port;
}
}
return 0;
}
NLboolean loopback_Init(void)
{
loopgroup = nlGroupCreate();
if(loopgroup == NL_INVALID)
{
return NL_FALSE;
}
return NL_TRUE;
}
void loopback_Shutdown(void)
{
(void)nlGroupDestroy(loopgroup);
}
NLboolean loopback_Listen(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
NLint i = NL_MAX_ACCEPT;
if(sock->type == NL_BROADCAST)
{
nlSetError(NL_WRONG_TYPE);
return NL_FALSE;
}
sock->listen = NL_TRUE;
while(i-- > 0)
{
sock->ext->accept[i] = NL_INVALID;
}
return NL_TRUE;
}
NLsocket loopback_AcceptConnection(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
if(sock->listen == NL_FALSE)
{
nlSetError(NL_NOT_LISTEN);
return NL_INVALID;
}
if(sock->inuse == NL_FALSE)
{
/* socket was closed by nlShutdown */
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
if(sock->ext == NULL)
{
/* socket was closed on another thread */
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
if(sock->ext->accept[0] != NL_INVALID)
{
NLsocket newsocket;
NLsocket osock = sock->ext->accept[0];
nl_socket_t *othersock = nlSockets[osock];
/* make sure the other socket is valid */
if(nlIsValidSocket(osock) == NL_FALSE)
{
NLint i;
for(i=1;i<NL_MAX_ACCEPT;i++)
{
sock->ext->accept[i-1] = sock->ext->accept[i];
}
sock->ext->accept[NL_MAX_ACCEPT-1] = NL_INVALID;
return loopback_AcceptConnection(socket);
}
newsocket = loopback_Open(0, sock->type);
if(newsocket != NL_INVALID)
{
NLint i;
nl_socket_t *newsock = nlSockets[newsocket];
/* we must unlock the socket briefly or else nlConnect will deadlock */
nlUnlockSocket(socket, NL_BOTH);
if(nlLockSocket(osock, NL_READ) == NL_FALSE)
{
return NL_INVALID;
}
(void)nlLockSocket(socket, NL_BOTH);
/* do the connecting */
newsock->ext->consock = osock;
newsock->remoteport = othersock->localport;
othersock->ext->consock = newsocket;
othersock->remoteport = newsock->localport;
newsock->connected = NL_TRUE;
loopback_SetAddrPort(&othersock->addressin, othersock->remoteport);
loopback_SetAddrPort(&newsock->addressin, newsock->remoteport);
othersock->connected = NL_TRUE;
othersock->connecting = NL_FALSE;
/* move the accept que down one */
for(i=1;i<NL_MAX_ACCEPT;i++)
{
sock->ext->accept[i-1] = sock->ext->accept[i];
}
sock->ext->accept[NL_MAX_ACCEPT-1] = NL_INVALID;
nlUnlockSocket(socket, NL_BOTH);
nlUnlockSocket(osock, NL_READ);
(void)nlLockSocket(socket, NL_BOTH);
return newsocket;
}
}
nlSetError(NL_NO_PENDING);
return NL_INVALID;
}
NLsocket loopback_Open(NLushort port, NLenum type)
{
nl_socket_t *newsock;
NLsocket newsocket;
NLint i;
NLushort lport;
switch (type) {
case NL_RELIABLE:
case NL_UNRELIABLE:
case NL_RELIABLE_PACKETS:
case NL_BROADCAST:
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
lport = loopback_TryPort(port, type);
if(lport == 0)
{
nlSetError(NL_INVALID_PORT);
return NL_INVALID;
}
newsocket = nlGetNewSocket();
if(newsocket == NL_INVALID)
{
return NL_INVALID;
}
if(nlLockSocket(newsocket, NL_BOTH) == NL_FALSE)
{
return NL_INVALID;
}
newsock = nlSockets[newsocket];
newsock->type = type;
newsock->localport = lport;
if(type == NL_BROADCAST)
{
newsock->remoteport = lport;
}
if((newsock->ext = (nl_extra_t *)malloc(sizeof(nl_extra_t))) == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
nlUnlockSocket(newsocket, NL_BOTH);
loopback_Close(newsocket);
return NL_INVALID;
}
/* clear out the structure */
memset(newsock->ext, 0, sizeof(nl_extra_t));
for(i=0;i<NL_NUM_PACKETS;i++)
{
NLboolean err = NL_FALSE;
/* malloc the max packet length plus two bytes for the port number */
if((newsock->ext->inpacket[i] = (NLbyte *)malloc((size_t)(NL_MAX_PACKET_LENGTH + 2))) == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
err = NL_TRUE;
}
if(err == NL_TRUE)
{
while(i-- > 0)
{
free(newsock->ext->inpacket[i]);
}
nlUnlockSocket(newsocket, NL_BOTH);
loopback_Close(newsocket);
return NL_INVALID;
}
}
(void)nlGroupAddSocket(loopgroup, newsocket);
nlUnlockSocket(newsocket, NL_BOTH);
return newsocket;
}
NLboolean loopback_Connect(NLsocket socket, const NLaddress *address)
{
nl_socket_t *sock = nlSockets[socket];
NLushort port;
NLint numsockets = NL_MAX_GROUP_SOCKETS;
NLsocket temp[NL_MAX_GROUP_SOCKETS];
/* no need to connect a broadcast socket */
if(sock->type == NL_BROADCAST)
{
nlSetError(NL_WRONG_TYPE);
}
port = loopback_GetPortFromAddr(address);
/* make sure socket is not already connected */
if(sock->connected == NL_TRUE)
{
nlSetError(NL_CONNECTED);
return NL_FALSE;
}
if(sock->connecting == NL_TRUE)
{
nlSetError(NL_CON_PENDING);
return NL_FALSE;
}
if(nlGroupGetSockets(loopgroup, (NLsocket *)&temp, &numsockets) == NL_FALSE)
{
return NL_FALSE;
}
if(numsockets == 0)
{
return NL_FALSE;
}
while(numsockets-- > 0)
{
NLsocket s = temp[numsockets];
nl_socket_t *othersock = nlSockets[s];
if(sock->type == othersock->type && port == othersock->localport
&& othersock->listen == NL_TRUE && othersock->connected == NL_FALSE
&& othersock->connecting == NL_FALSE)
{
/* we found the right socket, so connect */
NLint i;
if(nlLockSocket(s, NL_BOTH) == NL_FALSE)
{
return NL_FALSE;
}
for(i=0;i<NL_MAX_ACCEPT;i++)
{
if(othersock->ext->accept[i] == NL_INVALID)
{
othersock->ext->accept[i] = socket;
sock->connecting = NL_TRUE;
sock->ext->consock = s;
nlUnlockSocket(s, NL_BOTH);
if(sock->blocking == NL_TRUE)
{
nlUnlockSocket(socket, NL_BOTH);
/* wait for nlAccept to be called */
while(sock->connecting == NL_TRUE)
{
if(sock->inuse == NL_FALSE)
{
/* nlShutdown has been called */
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
htThreadSleep(NL_CONNECT_SLEEP);
}
(void)nlLockSocket(socket, NL_BOTH);
}
return NL_TRUE;
}
}
nlUnlockSocket(s, NL_BOTH);
}
}
nlSetError(NL_CON_REFUSED);
return NL_FALSE;
}
void loopback_Close(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
int i;
if(sock->connected == NL_TRUE || sock->connecting == NL_TRUE)
{
/* break the connection */
nl_socket_t *othersock = nlSockets[sock->ext->consock];
if(othersock->ext != NULL)
{
othersock->ext->consock = NL_INVALID;
}
othersock->connected = NL_FALSE;
sock->connected = NL_FALSE;
sock->listen = NL_FALSE;
if(sock->type != NL_BROADCAST)
{
/* this allows nlPollGroup to report socket is readable */
/* so that the app can get the NL_SOCK_DISCONNECT message*/
if(othersock->ext != NULL)
{
othersock->ext->inlen[othersock->ext->nextinused] = -1;
}
}
}
for(i=0;i<NL_NUM_PACKETS;i++)
{
void /*@owned@*/*t = sock->ext->inpacket[i];
free(t);
sock->ext->inpacket[i] = NULL;
}
free(sock->ext);
sock->ext = NULL;
}
NLint loopback_Read(NLsocket socket, NLvoid *buffer, NLint nbytes)
{
nl_socket_t *sock = nlSockets[socket];
NLint len = sock->ext->inlen[sock->ext->nextinused];
NLint c = 0;
NLushort port;
if(sock->blocking == NL_TRUE)
{
while(len == 0)
{
nlUnlockSocket(socket, NL_READ);
htThreadSleep(NL_CONNECT_SLEEP);
(void)nlLockSocket(socket, NL_READ);
if(sock->inuse == NL_FALSE)
{
/* nlShutdown has been called */
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
len = sock->ext->inlen[sock->ext->nextinused];
}
}
if(len > 0)
{
if(len > nbytes)
{
nlSetError(NL_BUFFER_SIZE);
return NL_INVALID;
}
if(sock->connecting == NL_TRUE)
{
nlSetError(NL_CON_PENDING);
return NL_INVALID;
}
/* get the port number */
readShort(sock->ext->inpacket[sock->ext->nextinused], c, port);
loopback_SetAddrPort(&sock->addressin, port);
/* copy the packet */
memcpy(buffer, sock->ext->inpacket[sock->ext->nextinused] + 2, (size_t)len);
/* zero out length and set up for next packet */
sock->ext->inlen[sock->ext->nextinused] = 0;
sock->ext->nextinused++;
if(sock->ext->nextinused >= NL_NUM_PACKETS)
{
sock->ext->nextinused = 0;
}
}
/* check for broken connection */
else if((len == -1) || (sock->connected == NL_TRUE && sock->ext->consock == NL_INVALID)
|| (sock->connected == NL_FALSE && sock->type != NL_BROADCAST))
{
nlSetError(NL_SOCK_DISCONNECT);
return NL_INVALID;
}
return len;
}
static NLint loopback_WritePacket(NLsocket to, const NLvoid *buffer, NLint nbytes, NLushort fromport)
{
nl_socket_t *sock = nlSockets[to];
NLint i, j;
NLint c = 0;
/* check the packet size */
if(nbytes > NL_MAX_PACKET_LENGTH)
{
nlSetError(NL_PACKET_SIZE);
return NL_INVALID;
}
if(nlLockSocket(to, NL_READ) == NL_FALSE)
{
return NL_INVALID;
}
/* make sure we have an empty packet buffer */
if(sock->ext->nextinfree == NL_INVALID)
{
/* all buffers were filled by last write */
/* check to see if any were emptied by a read */
i = NL_NUM_PACKETS;
j = sock->ext->nextinused;
while(i-- > 0)
{
if(sock->ext->inlen[j] == 0)
{
/* found the first free */
sock->ext->nextinfree = j;
break;
}
j++;
if(j >= NL_NUM_PACKETS)
{
j = 0;
}
}
if(sock->ext->nextinfree == NL_INVALID)
{
nlUnlockSocket(to, NL_READ);
/* none are free */
if(sock->type == NL_RELIABLE || sock->type == NL_RELIABLE_PACKETS)
{
return 0;
}
else
{
/* silently fail */
return nbytes;
}
}
}
/* write the port number */
writeShort(sock->ext->inpacket[sock->ext->nextinfree], c, fromport);
/* copy the packet buffer */
memcpy(sock->ext->inpacket[sock->ext->nextinfree] + 2, buffer, (size_t)nbytes);
sock->ext->inlen[sock->ext->nextinfree] = nbytes;
sock->ext->nextinfree++;
if(sock->ext->nextinfree >= NL_NUM_PACKETS)
{
sock->ext->nextinfree = 0;
}
/* check for full packet buffers */
if(sock->ext->inlen[sock->ext->nextinfree] != 0)
{
sock->ext->nextinfree = NL_INVALID;
}
nlUnlockSocket(to, NL_READ);
return nbytes;
}
NLint loopback_Write(NLsocket socket, const NLvoid *buffer, NLint nbytes)
{
nl_socket_t *sock = nlSockets[socket];
nl_socket_t *othersock;
NLsocket s[NL_MAX_GROUP_SOCKETS];
NLint number = NL_MAX_GROUP_SOCKETS;
NLint i;
NLint count;
switch (sock->type) {
case NL_RELIABLE:
case NL_RELIABLE_PACKETS:
default:
{
if(sock->connected == NL_TRUE)
{
/* check for broken connection */
if(sock->ext->consock == NL_INVALID)
{
nlSetError(NL_SOCK_DISCONNECT);
return NL_INVALID;
}
count = loopback_WritePacket(sock->ext->consock, buffer, nbytes, sock->localport);
}
else if(sock->connecting == NL_TRUE)
{
nlSetError(NL_CON_PENDING);
return NL_INVALID;
}
else
{
nlSetError(NL_SOCK_DISCONNECT);
return NL_INVALID;
}
}
break;
case NL_UNRELIABLE:
{
if(sock->connected == NL_TRUE)
{
/* check for broken connection */
if(sock->ext->consock == NL_INVALID)
{
nlSetError(NL_SOCK_DISCONNECT);
return NL_INVALID;
}
count = loopback_WritePacket(sock->ext->consock, buffer, nbytes, sock->localport);
}
else if(sock->connecting == NL_TRUE)
{
nlSetError(NL_CON_PENDING);
return NL_INVALID;
}
/* unconnected UDP emulation */
count = nbytes;
(void)nlGroupGetSockets(loopgroup, (NLsocket *)s, &number);
for(i=0;i<number;i++)
{
if(nlIsValidSocket(s[i]) == NL_TRUE)
{
othersock = nlSockets[s[i]];
if(sock->remoteport == othersock->localport &&
othersock->connected == NL_FALSE &&
sock->type == othersock->type)
{
(void)loopback_WritePacket(s[i], buffer, nbytes, sock->localport);
}
}
}
}
break;
case NL_BROADCAST:
{
count = nbytes;
(void)nlGroupGetSockets(loopgroup, (NLsocket *)s, &number);
for(i=0;i<number;i++)
{
if(nlIsValidSocket(s[i]) == NL_TRUE)
{
othersock = nlSockets[s[i]];
if(sock->localport == othersock->localport &&
sock->type == othersock->type)
{
(void)loopback_WritePacket(s[i], buffer, nbytes, sock->localport);
}
}
}
}
}
return count;
}
NLchar *loopback_AddrToString(const NLaddress *address, NLchar *string)
{
_stprintf(string, TEXT("127.0.0.1:%u"), loopback_GetPortFromAddr(address));
return string;
}
NLboolean loopback_StringToAddr(const NLchar *string, NLaddress *address)
{
NLchar *st;
NLint port;
memset(address, 0, sizeof(NLaddress));
address->valid = NL_TRUE;
/* check for a port number */
st = _tcschr(string, TEXT(':'));
if(st != NULL)
{
st++;
port = _ttoi(st);
if(port < 0 || port > 65535)
{
nlSetError(NL_BAD_ADDR);
address->valid = NL_FALSE;
return NL_FALSE;
}
loopback_SetAddrPort(address, (NLushort)port);
}
return NL_TRUE;
}
NLboolean loopback_GetLocalAddr(NLsocket socket, NLaddress *address)
{
nl_socket_t *sock = nlSockets[socket];
memset(address, 0, sizeof(NLaddress));
loopback_SetAddrPort(address, sock->localport);
address->valid = NL_TRUE;
return NL_TRUE;
}
NLaddress *loopback_GetAllLocalAddr(NLint *count)
{
*count = 1;
memset(&loopback_ouraddress, 0, sizeof(NLaddress));
loopback_ouraddress.valid = NL_TRUE;
return &loopback_ouraddress;
}
NLboolean loopback_SetLocalAddr(const NLaddress *address)
{
/* this is just to keep compilers happy */
if(address == NULL)
{
return NL_FALSE;
}
return NL_TRUE;
}
NLchar *loopback_GetNameFromAddr(const NLaddress *address, NLchar *name)
{
_stprintf(name, TEXT("%s:%u"), TEXT("localhost"), loopback_GetPortFromAddr(address));
return name;
}
NLboolean loopback_GetNameFromAddrAsync(const NLaddress *address, NLchar *name)
{
(void)loopback_GetNameFromAddr(address, name);
return NL_TRUE;
}
NLboolean loopback_GetAddrFromName(const NLchar *name, NLaddress *address)
{
return loopback_StringToAddr(name, address);
}
NLboolean loopback_GetAddrFromNameAsync(const NLchar *name, NLaddress *address)
{
return loopback_GetAddrFromName(name, address);
}
NLboolean loopback_AddrCompare(const NLaddress *address1, const NLaddress *address2)
{
if(*(NLushort *)(&address1->addr[0]) == *(NLushort *)(&address2->addr[0]))
{
return NL_TRUE;
}
return NL_FALSE;
}
NLushort loopback_GetPortFromAddr(const NLaddress *address)
{
return *(NLushort *)(&address->addr[0]);
}
void loopback_SetAddrPort(NLaddress *address, NLushort port)
{
*(NLushort *)(&address->addr[0]) = port;
}
NLint loopback_GetSystemError(void)
{
return errno;
}
NLint loopback_PollGroup(NLint group, NLenum name, NLsocket *sockets, NLint number, NLint timeout)
{
NLint count = 0;
NLint numsockets = NL_MAX_GROUP_SOCKETS;
NLsocket temp[NL_MAX_GROUP_SOCKETS];
NLtime end, now;
nlGroupLock();
if(nlGroupGetSocketsINT(group, (NLsocket *)&temp, &numsockets) == NL_FALSE)
{
/* any error is set by nlGroupGetSockets */
nlGroupUnlock();
return NL_INVALID;
}
nlGroupUnlock();
if(numsockets == 0)
{
return 0;
}
(void)nlTime(&now);
end.seconds = now.seconds;
end.mseconds = now.mseconds;
if(timeout > 0)
{
end.mseconds += timeout;
while(end.mseconds > 999)
{
end.mseconds -= 1000;
end.seconds++;
}
}
while(count == 0)
{
switch(name) {
case NL_READ_STATUS:
{
NLint i = 0;
NLint j = numsockets;
while(j-- > 0)
{
/* check for a packet */
nl_socket_t *sock;
if(nlIsValidSocket(temp[i]) != NL_TRUE)
{
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
sock = nlSockets[temp[i]];
if(sock->ext->inlen[sock->ext->nextinused] != 0)
{
*sockets = temp[i];
sockets++;
count++;
if(count > number)
{
nlSetError(NL_BUFFER_SIZE);
return NL_INVALID;
}
}
i++;
}
}
break;
case NL_WRITE_STATUS:
{
NLint i = 0;
NLint j = numsockets;
while(j-- > 0)
{
nl_socket_t *sock;
if(nlIsValidSocket(temp[i]) != NL_TRUE)
{
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
sock = nlSockets[temp[i]];
/* check for a free packet if reliable and connected */
if((sock->type == NL_TCP || sock->type == NL_TCP_PACKETS)
&& (sock->connecting == NL_TRUE || sock->connected == NL_TRUE))
{
nl_socket_t *othersock = nlSockets[sock->ext->consock];
if(othersock->ext->nextinfree == NL_INVALID)
{
continue;
}
}
/* add the socket to the list */
*sockets = temp[i];
sockets++;
count++;
if(count > number)
{
nlSetError(NL_BUFFER_SIZE);
return NL_INVALID;
}
i++;
}
}
break;
case NL_ERROR_STATUS:
{
NLint i = 0;
NLint j = numsockets;
while(j-- > 0)
{
nl_socket_t *sock;
if(nlIsValidSocket(temp[i]) != NL_TRUE)
{
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
sock = nlSockets[temp[i]];
if(sock->connected == NL_FALSE && sock->type != NL_UDP_BROADCAST)
{
/* add the socket to the list */
*sockets = temp[i];
sockets++;
count++;
if(count > number)
{
nlSetError(NL_BUFFER_SIZE);
return NL_INVALID;
}
i++;
}
}
}
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
if(timeout != 0)
{
htThreadSleep(1);
(void)nlTime(&now);
if(timeout > 0 && (now.seconds > end.seconds || (now.seconds == end.seconds && now.mseconds > end.mseconds)))
break;
}
else
{
break;
}
}
return count;
}
NLboolean loopback_PollSocket(NLsocket socket, NLenum name, NLint timeout)
{
nl_socket_t *sock = nlSockets[socket];
NLtime end, now;
nlSetError(NL_NO_ERROR);
(void)nlTime(&now);
end.seconds = now.seconds;
end.mseconds = now.mseconds;
if(timeout > 0)
{
end.mseconds += timeout;
while(end.mseconds > 999)
{
end.mseconds -= 1000;
end.seconds++;
}
}
while(!(timeout > 0 && (now.seconds > end.seconds || (now.seconds == end.seconds && now.mseconds > end.mseconds))))
{
switch(name) {
case NL_READ_STATUS:
if(sock->ext->inlen[sock->ext->nextinused] > 0)
return NL_TRUE;
break;
case NL_WRITE_STATUS:
/* check for a free packet if reliable and connected */
if((sock->type == NL_TCP || sock->type == NL_TCP_PACKETS)
&& (sock->connecting == NL_TRUE || sock->connected == NL_TRUE))
{
nl_socket_t *othersock = nlSockets[sock->ext->consock];
if(othersock->ext->nextinfree != NL_INVALID)
{
return NL_TRUE;
}
}
else
{
return NL_TRUE;
}
break;
case NL_ERROR_STATUS:
if(sock->connected == NL_FALSE && sock->type != NL_UDP_BROADCAST)
return NL_TRUE;
break;
default:
nlSetError(NL_INVALID_ENUM);
}
if(timeout != 0)
{
htThreadSleep(1);
(void)nlTime(&now);
}
else
{
break;
}
}
return NL_FALSE;
}
NLboolean loopback_Hint(NLenum name, NLint arg)
{
switch (name) {
case NL_REUSE_ADDRESS:
reuseaddress = (NLboolean)(arg != 0 ? NL_TRUE : NL_FALSE);
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean loopback_SetSocketOpt(NLsocket socket, NLenum name, NLint arg)
{
nl_socket_t *sock = nlSockets[socket];
switch (name) {
case NL_BLOCKING_IO:
sock->blocking = (NLboolean)((NLboolean)arg != NL_FALSE ? NL_FALSE : NL_TRUE);
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
NLint loopback_GetSocketOpt(NLsocket socket, NLenum name)
{
nl_socket_t *sock = nlSockets[socket];
switch (name) {
case NL_BLOCKING_IO:
return (NLint)sock->blocking;
default:
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
}
#endif /* NL_INCLUDE_LOOPBACK */
diff --git a/util/network/hawknl/src/nl.c b/util/network/hawknl/src/nl.c
index b99143de..9e887c10 100644
--- a/util/network/hawknl/src/nl.c
+++ b/util/network/hawknl/src/nl.c
@@ -1,1928 +1,1928 @@
/*
HawkNL cross platform network library
Copyright (C) 2000-2004 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
*/
#include <string.h>
-#include "nlinternal.h"
-#include "sock.h"
-#include "serial.h"
-#include "parallel.h"
+#include "hawknl/nlinternal.h"
+#include "hawknl/sock.h"
+#include "hawknl/serial.h"
+#include "hawknl/parallel.h"
#ifdef NL_INCLUDE_LOOPBACK
-#include "loopback.h"
+#include "hawknl/loopback.h"
#endif
#if defined HL_WINDOWS_APP && defined NL_INCLUDE_IPX
- #include "ipx.h"
+ #include "hawknl/ipx.h"
#endif
#define MAX_NET_DRIVERS 6
volatile nl_state_t nlState = {NL_FALSE, NL_TRUE};
/* mutexes for global variables */
static HTmutex socklock, instatlock, outstatlock;
static volatile NLboolean nlBlocking = NL_FALSE;
static volatile nl_stats_t nlInstats;
static volatile nl_stats_t nlOutstats;
static volatile NLsocket nlNextsocket = 0;
static volatile NLint nlNumsockets = 0;
static volatile NLint nlMaxNumsockets = NL_MIN_SOCKETS; /* this is dynamic, and can grow as needed */
static volatile NLint nlInitCount = 0;
pnl_socket_t *nlSockets = NULL;
/* the current selected driver */
static nl_netdriver_t /*@null@*/*driver = NULL;
static nl_netdriver_t netdrivers[] =
{
{
(NLchar*)TEXT("NL_IP"),
(NLchar*)TEXT("NL_RELIABLE NL_UNRELIABLE NL_RELIABLE_PACKETS NL_BROADCAST NL_UDP_MULTICAST NL_MULTICAST"),
NL_IP,
NL_FALSE,
sock_Init,
sock_Shutdown,
sock_Listen,
sock_AcceptConnection,
sock_Open,
sock_Connect,
sock_Close,
sock_Read,
sock_Write,
sock_AddrToString,
sock_StringToAddr,
sock_GetLocalAddr,
sock_GetAllLocalAddr,
sock_SetLocalAddr,
sock_GetNameFromAddr,
sock_GetNameFromAddrAsync,
sock_GetAddrFromName,
sock_GetAddrFromNameAsync,
sock_AddrCompare,
sock_GetPortFromAddr,
sock_SetAddrPort,
sock_GetSystemError,
sock_PollGroup,
sock_PollSocket,
sock_Hint,
sock_SetSocketOpt,
sock_GetSocketOpt
}
#ifdef NL_INCLUDE_LOOPBACK
,
{
(NLchar*)TEXT("NL_LOOP_BACK"),
(NLchar*)TEXT("NL_RELIABLE NL_UNRELIABLE NL_RELIABLE_PACKETS NL_BROADCAST"),
NL_LOOP_BACK,
NL_FALSE,
loopback_Init,
loopback_Shutdown,
loopback_Listen,
loopback_AcceptConnection,
loopback_Open,
loopback_Connect,
loopback_Close,
loopback_Read,
loopback_Write,
loopback_AddrToString,
loopback_StringToAddr,
loopback_GetLocalAddr,
loopback_GetAllLocalAddr,
loopback_SetLocalAddr,
loopback_GetNameFromAddr,
loopback_GetNameFromAddrAsync,
loopback_GetAddrFromName,
loopback_GetAddrFromNameAsync,
loopback_AddrCompare,
loopback_GetPortFromAddr,
loopback_SetAddrPort,
loopback_GetSystemError,
loopback_PollGroup,
loopback_PollSocket,
loopback_Hint,
loopback_SetSocketOpt,
loopback_GetSocketOpt
}
#endif /* NL_INCLUDE_LOOPBACK */
#if defined HL_WINDOWS_APP && defined NL_INCLUDE_IPX
,
{
(NLchar*)TEXT("NL_IPX"),
(NLchar*)TEXT("NL_RELIABLE NL_UNRELIABLE NL_RELIABLE_PACKETS NL_BROADCAST"),
NL_IPX,
NL_FALSE,
ipx_Init,
ipx_Shutdown,
sock_Listen,
ipx_AcceptConnection,
ipx_Open,
sock_Connect,
sock_Close,
sock_Read,
sock_Write,
ipx_AddrToString,
ipx_StringToAddr,
ipx_GetLocalAddr,
ipx_GetAllLocalAddr,
ipx_SetLocalAddr,
ipx_GetNameFromAddr,
ipx_GetNameFromAddrAsync,
ipx_GetAddrFromName,
ipx_GetAddrFromNameAsync,
ipx_AddrCompare,
ipx_GetPortFromAddr,
ipx_SetAddrPort,
sock_GetSystemError,
sock_PollGroup,
sock_PollSocket,
ipx_Hint,
ipx_SetSocketOpt,
ipx_GetSocketOpt
}
#endif /* HL_WINDOWS_APP && NL_INCLUDE_IPX */
,
{
(NLchar*)NULL,
}
};
/*
Internal helper functions.
*/
static NLboolean isSafeString(const NLchar *string)
{
int i;
NLboolean nullfound = NL_FALSE;
/* make sure string is null terminated at less than NL_MAX_STRING_LENGTH */
for(i=0;i<NL_MAX_STRING_LENGTH;i++)
{
if(string[i] == (NLchar)'\0')
{
nullfound = NL_TRUE;
break;
}
}
if(nullfound == NL_FALSE)
{
return NL_FALSE;
}
/* check for formating characters */
if(_tcsrchr(string, '%') != NULL)
{
return NL_FALSE;
}
return NL_TRUE;
}
static void safecat(NLchar *dest, const NLchar *src)
{
int len;
if(isSafeString(dest) != NL_TRUE || isSafeString(src) != NL_TRUE)
{
/* don't do anything */
return;
}
len = (int)_tcslen(dest);
if( len < (NL_MAX_STRING_LENGTH - 1))
{
_tcsncat(dest, src, (size_t)(NL_MAX_STRING_LENGTH - len));
dest[NL_MAX_STRING_LENGTH - 1] = (NLchar)'\0';
}
}
NLsocket nlGetNewSocket(void)
{
NLsocket newsocket = NL_INVALID;
nl_socket_t *sock = NULL;
if(htMutexLock(&socklock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_INVALID;
}
if(nlNumsockets == nlMaxNumsockets)
{
nl_socket_t **temp;
NLint tempmaxnumsockets = nlMaxNumsockets;
/* expand the list of sockets pointers */
tempmaxnumsockets *= 2;
temp = (nl_socket_t **)realloc((void *)nlSockets, tempmaxnumsockets * sizeof(nl_socket_t *));
if(temp == NULL)
{
(void)htMutexUnlock(&socklock);
nlSetError(NL_OUT_OF_MEMORY);
return NL_INVALID;
}
nlSockets = temp;
nlMaxNumsockets = tempmaxnumsockets;
}
/* get a socket number */
if(nlNumsockets == (NLint)nlNextsocket)
{
newsocket = nlNextsocket++;
/* allocate the memory */
sock = (nl_socket_t *)malloc(sizeof(nl_socket_t));
if(sock == NULL)
{
(void)htMutexUnlock(&socklock);
nlSetError(NL_OUT_OF_MEMORY);
return NL_INVALID;
}
else
{
nlSockets[newsocket] = sock;
}
/* clear the structure */
memset(sock, 0, sizeof(nl_socket_t));
if(htMutexInit(&sock->readlock) != 0 || htMutexInit(&sock->writelock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
(void)htMutexUnlock(&socklock);
return NL_INVALID;
}
}
else
/* there is an open socket slot somewhere below nlNextsocket */
{
NLsocket i;
HTmutex readlock, writelock;
for(i=0;i<nlNextsocket;i++)
{
if(nlSockets[i]->inuse == NL_FALSE)
{
/* found an open socket slot */
newsocket = i;
sock = nlSockets[i];
break;
}
}
/* let's check just to make sure we did find a socket */
if(sock == NULL)
{
(void)htMutexUnlock(&socklock);
nlSetError(NL_OUT_OF_MEMORY);
return NL_INVALID;
}
readlock = sock->readlock;
writelock = sock->writelock;
/* clear the structure */
memset(sock, 0, sizeof(nl_socket_t));
sock->readlock = readlock;
sock->writelock = writelock;
}
/* sockets are blocking until set for non-blocking */
sock->blocking = nlBlocking;
sock->inuse = NL_TRUE;
nlNumsockets++;
(void)htMutexUnlock(&socklock);
return newsocket;
}
static void nlReturnSocket(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
if((sock != NULL) && (sock->inuse == NL_TRUE))
{
sock->inuse = NL_FALSE;
if(sock->inbuf != NULL)
{
free(sock->inbuf);
sock->inbuf = NULL;
}
if(sock->outbuf != NULL)
{
free(sock->outbuf);
sock->outbuf = NULL;
}
nlNumsockets--;
}
}
void nlFreeSocket(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
if(sock != NULL)
{
if(sock->inbuf != NULL)
{
free(sock->inbuf);
}
if(sock->outbuf != NULL)
{
free(sock->outbuf);
}
(void)htMutexDestroy(&sock->readlock);
(void)htMutexDestroy(&sock->writelock);
free(sock);
}
}
NLboolean nlIsValidSocket(NLsocket socket)
{
nl_socket_t *sock;
if(socket < 0 || socket > nlMaxNumsockets)
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
sock = nlSockets[socket];
if(sock == NULL)
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
if(sock->inuse == NL_FALSE)
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean nlLockSocket(NLsocket socket, NLint which)
{
nl_socket_t *sock = nlSockets[socket];
if((which&NL_READ) > 0)
{
if(htMutexLock(&sock->readlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
if((which&NL_WRITE) > 0)
{
if(htMutexLock(&sock->writelock) != 0)
{
if((which&NL_READ) > 0)
{
(void)htMutexUnlock(&sock->readlock);
}
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
return NL_TRUE;
}
void nlUnlockSocket(NLsocket socket, NLint which)
{
nl_socket_t *sock = nlSockets[socket];
if((which&NL_WRITE) > 0)
{
(void)htMutexUnlock(&sock->writelock);
}
if((which&NL_READ) > 0)
{
(void)htMutexUnlock(&sock->readlock);
}
}
static void nlUpdateStats(volatile nl_stats_t *stats, NLint nbytes, NLint npackets)
{
time_t t;
(void)time(&t);
if(stats->stime == 0)
{
/* must be the first time through */
stats->stime = t;
stats->lastbucket = -1;
stats->firstround = NL_TRUE;
}
/* do the basic update */
stats->packets += npackets;
stats->bytes += nbytes;
/* check to see if we need to do the full update */
if(stats->stime != t)
{
NLint i;
NLlong count = 0;
time_t diff = t - stats->stime;
stats->stime = t;
if(stats->curbytes > stats->highest)
{
stats->highest = stats->curbytes;
}
if(diff >= NL_NUM_BUCKETS)
{
diff = NL_NUM_BUCKETS;
}
while(diff > 1)
{
/* we need to zero out skipped over buckets */
stats->lastbucket++;
if(stats->lastbucket == NL_NUM_BUCKETS)
{
stats->lastbucket = 0;
}
stats->bucket[stats->lastbucket] = 0;
diff--;
}
stats->lastbucket++;
if(stats->lastbucket == NL_NUM_BUCKETS)
{
stats->lastbucket = 0;
stats->firstround = NL_FALSE;
}
stats->bucket[stats->lastbucket] = stats->curbytes;
if(stats->firstround == NL_TRUE)
{
/* this corrects the stats for the first second */
for(i=stats->lastbucket + 1;i<NL_NUM_BUCKETS;i++)
{
stats->bucket[i] = stats->curbytes;
}
}
stats->curbytes = 0;
for(i=0;i<NL_NUM_BUCKETS;i++)
{
count += stats->bucket[i];
}
stats->average = count / NL_NUM_BUCKETS;
}
stats->curbytes += nbytes;
}
static void nlUpdateInStats(NLint nbytes, NLint npackets)
{
if(nlState.socketStats == NL_FALSE)
{
return;
}
(void)htMutexLock(&instatlock);
nlUpdateStats(&nlInstats, nbytes, npackets);
(void)htMutexUnlock(&instatlock);
}
static void nlUpdateOutStats(NLint nbytes, NLint npackets)
{
if(nlState.socketStats == NL_FALSE)
{
return;
}
(void)htMutexLock(&outstatlock);
nlUpdateStats(&nlOutstats, nbytes, npackets);
(void)htMutexUnlock(&outstatlock);
}
static void nlUpdateSocketInStats(NLsocket socket, NLint nbytes, NLint npackets)
{
nl_socket_t *sock = nlSockets[socket];
if(nlState.socketStats == NL_FALSE)
{
return;
}
nlUpdateStats(&sock->instats, nbytes, npackets);
}
static void nlUpdateSocketOutStats(NLsocket socket, NLint nbytes, NLint npackets)
{
nl_socket_t *sock = nlSockets[socket];
if(nlState.socketStats == NL_FALSE)
{
return;
}
nlUpdateStats(&sock->outstats, nbytes, npackets);
}
/*
Low level functions, a thin layer over Sockets.
*/
/*
Trys to init all drivers, BUT DOES NOT SELECT A DRIVER
*/
HL_EXP NLboolean HL_APIENTRY nlInit(void)
{
int i, numdrivers = 0;
nlSetError(NL_NO_ERROR);
/* init socket memory, mutexes, and global variables */
if(nlInitCount == 0)
{
nlMaxNumsockets = NL_MIN_SOCKETS;
if(nlSockets == NULL)
{
nlSockets = (nl_socket_t **)malloc(nlMaxNumsockets * sizeof(nl_socket_t *));
}
if(nlSockets == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
nlShutdown();
return NL_FALSE;
}
if(nlGroupInit() == NL_FALSE)
{
nlShutdown();
return NL_FALSE;
}
if(htMutexInit(&socklock) != 0 || htMutexInit(&instatlock) != 0 ||
htMutexInit(&outstatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
nlShutdown();
return NL_FALSE;
}
nlNumsockets = 0;
nlNextsocket = 0;
nlBlocking = NL_FALSE;
nlState.socketStats = NL_FALSE;
nlState.nl_big_endian_data = NL_TRUE;
for(i=0;i<MAX_NET_DRIVERS;i++)
{
if(netdrivers[i].name == NULL)
{
break;
}
if(netdrivers[i].initialized == NL_TRUE)
{
numdrivers++;
}
else if(netdrivers[i].Init() == NL_TRUE)
{
netdrivers[i].initialized = NL_TRUE;
numdrivers++;
}
}
if(numdrivers == 0)
{
nlSetError(NL_NO_NETWORK);
nlShutdown();
return NL_FALSE;
}
}
nlInitCount++;
return NL_TRUE;
}
/*
Called at the end of your program, shuts down the active driver and frees memory
*/
HL_EXP void HL_APIENTRY nlShutdown(void)
{
--nlInitCount;
if(nlInitCount > 0)
{
return;
}
if(driver != NULL)
{
/* close any open sockets */
(void)htMutexLock(&socklock);
if(nlSockets != NULL)
{
NLsocket s;
for(s=0;s<nlNextsocket;s++)
{
if(nlSockets[s] != NULL)
{
if(nlIsValidSocket(s) == NL_TRUE)
{
driver->Close(s);
htThreadYield();
}
}
}
}
/* now we can shutdown the driver */
driver->Shutdown();
driver->initialized = NL_FALSE;
driver = NULL;
}
else
{
nlSetError(NL_NO_NETWORK);
}
htThreadSleep(1);
/* now free all the socket structures */
if(nlSockets != NULL)
{
NLsocket s;
for(s=0;s<nlNextsocket;s++)
{
if(nlSockets[s] != NULL)
{
if(nlIsValidSocket(s) == NL_TRUE)
{
(void)nlLockSocket(s, NL_BOTH);
nlReturnSocket(s);
nlUnlockSocket(s, NL_BOTH);
htThreadYield();
}
nlFreeSocket(s);
}
}
free(nlSockets);
nlSockets = NULL;
}
(void)htMutexUnlock(&socklock);
nlGroupShutdown();
/* destroy the mutexes */
(void)htMutexDestroy(&socklock);
(void)htMutexDestroy(&instatlock);
(void)htMutexDestroy(&outstatlock);
}
/*
Enables a socket to listen for incomming connections
*/
HL_EXP NLboolean HL_APIENTRY nlListen(NLsocket socket)
{
if(driver != NULL)
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
NLboolean result;
if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
{
return NL_FALSE;
}
result = driver->Listen(socket);
nlUnlockSocket(socket, NL_BOTH);
return result;
}
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Accepts a pending connection.
Creates a new socket object for this connection.
*/
HL_EXP NLsocket HL_APIENTRY nlAcceptConnection(NLsocket socket)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
NLsocket newsocket;
if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
{
return NL_INVALID;
}
newsocket = driver->AcceptConnection(socket);
nlUnlockSocket(socket, NL_BOTH);
if(newsocket != NL_INVALID)
{
/* the new socket was locked when it is created */
nlUnlockSocket(newsocket, NL_BOTH);
}
return newsocket;
}
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
nlSetError(NL_NO_NETWORK);
return NL_INVALID;
}
/*
Creates a new socket object.
Can be used for reading or broadcast as is.
For non-broadcast use, call nlConnectSocket to connect to a remote address.
*/
HL_EXP NLsocket HL_APIENTRY nlOpen(NLushort port, NLenum type)
{
if(driver)
{
return (driver->Open(port, type));
}
nlSetError(NL_NO_NETWORK);
return NL_INVALID;
}
/*
Connect a socket to a remote address.
*/
HL_EXP NLboolean HL_APIENTRY nlConnect(NLsocket socket, const NLaddress *address)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
if(address == NULL)
{
nlSetError(NL_NULL_POINTER);
}
else
{
NLboolean result;
if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
{
return NL_FALSE;
}
result = driver->Connect(socket, address);
nlUnlockSocket(socket, NL_BOTH);
return result;
}
}
else
{
nlSetError(NL_INVALID_SOCKET);
}
return NL_FALSE;
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Close the socket.
*/
HL_EXP NLboolean HL_APIENTRY nlClose(NLsocket socket)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
if(htMutexLock(&socklock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
/*
if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
{
return NL_FALSE;
}
*/
driver->Close(socket);
/* return the socket for reuse */
nlReturnSocket(socket);
// nlUnlockSocket(socket, NL_BOTH);
if(htMutexUnlock(&socklock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return NL_TRUE;
}
else
{
nlSetError(NL_INVALID_SOCKET);
return NL_TRUE;
}
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Reads from a socket.
*/
HL_EXP NLint HL_APIENTRY nlRead(NLsocket socket, NLvoid *buffer, NLint nbytes)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
if(buffer == NULL)
{
nlSetError(NL_NULL_POINTER);
}
else
{
NLint received;
if(nlLockSocket(socket, NL_READ) == NL_FALSE)
{
return NL_INVALID;
}
received = driver->Read(socket, buffer, nbytes);
if(received > 0)
{
nlUpdateSocketInStats(socket, received, 1);
nlUpdateInStats(received, 1);
}
nlUnlockSocket(socket, NL_READ);
return received;
}
}
else
{
nlSetError(NL_INVALID_SOCKET);
}
return NL_INVALID;
}
nlSetError(NL_NO_NETWORK);
return NL_INVALID;
}
/*
Writes to a socket.
*/
HL_EXP NLint HL_APIENTRY nlWrite(NLsocket socket, const NLvoid *buffer, NLint nbytes)
{
if(driver)
{
/* check for group */
if(socket >= NL_FIRST_GROUP)
{
NLint number = NL_MAX_GROUP_SOCKETS;
NLsocket s[NL_MAX_GROUP_SOCKETS];
NLint i;
NLint sent = nbytes;
if(nlGroupGetSockets((NLint)socket, (NLsocket *)s, &number) == NL_FALSE)
{
return NL_INVALID;
}
for(i=0;i<number;i++)
{
NLint result;
if(nlIsValidSocket(s[i]) == NL_TRUE)
{
result = nlWrite(s[i], buffer, nbytes);
if(result < sent)
{
sent = result;
}
}
}
return sent;
}
else
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
if(buffer == NULL)
{
nlSetError(NL_NULL_POINTER);
}
else
{
NLint sent;
if(nlLockSocket(socket, NL_WRITE) == NL_FALSE)
{
return NL_INVALID;
}
sent = driver->Write(socket, buffer, nbytes);
if(sent > 0)
{
nlUpdateSocketOutStats(socket, sent, 1);
nlUpdateOutStats(sent, 1);
}
nlUnlockSocket(socket, NL_WRITE);
return sent;
}
}
else
{
nlSetError(NL_INVALID_SOCKET);
}
return NL_INVALID;
}
}
nlSetError(NL_NO_NETWORK);
return NL_INVALID;
}
/*
Polls all sockets in the group to see which have data waiting to be read.
nlPollGroup uses select() on TCP or UDP sockets.
Returns number of sockets waiting, and a list of those sockets, or NL_INVALID
on an error.
*/
HL_EXP NLint HL_APIENTRY nlPollGroup(NLint group, NLenum name, /*@out@*/ NLsocket *sockets, NLint number, NLint timeout)
{
if(driver)
{
if(sockets == NULL )
{
nlSetError(NL_NULL_POINTER);
return 0;
}
return (driver->PollGroup(group, name, sockets, number, timeout));
}
nlSetError(NL_NO_NETWORK);
return 0;
}
HL_EXP NLboolean HL_APIENTRY nlPollSocket(NLsocket socket, NLenum name, NLint timeout)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE )
{
return (driver->PollSocket(socket, name, timeout));
}
else
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
HL_EXP NLboolean HL_APIENTRY nlHint(NLenum name, NLint arg)
{
if(driver)
{
return driver->Hint(name, arg);
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
HL_EXP NLboolean HL_APIENTRY nlSetSocketOpt(NLsocket socket, NLenum name, NLint arg)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE )
{
return driver->SetSocketOpt(socket, name, arg);
}
else
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
HL_EXP NLint HL_APIENTRY nlGetSocketOpt(NLsocket socket, NLenum name)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE )
{
return driver->GetSocketOpt(socket, name);
}
else
{
nlSetError(NL_INVALID_SOCKET);
return NL_INVALID;
}
}
nlSetError(NL_NO_NETWORK);
return NL_INVALID;
}
/*
Converts the numeric address in the NLaddress structure to a string.
*/
HL_EXP /*@null@*/ NLchar* HL_APIENTRY nlAddrToString(const NLaddress *address, NLchar *string)
{
if(driver)
{
if((string == NULL) || (address == NULL))
{
nlSetError(NL_NULL_POINTER);
return NULL;
}
return (driver->AddrToString(address, string));
}
nlSetError(NL_NO_NETWORK);
return NULL;
}
/*
Takes a string that contains a full network address (ie, for IP 192.168.0.1:27000),
and adds it to the NLaddress structure.
*/
HL_EXP NLboolean HL_APIENTRY nlStringToAddr(const NLchar *string, NLaddress *address)
{
if(driver)
{
if((string == NULL) || (address == NULL))
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
if(isSafeString(string) == NL_FALSE)
{
nlSetError(NL_STRING_OVER_RUN);
return NL_FALSE;
}
return driver->StringToAddr(string, address);
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Gets the remote address of the socket if connected to a remote host,
or the local address if not connected.
*/
/* Note: the drivers put a copy of address in nl_socket_t, so we just need to copy it */
HL_EXP NLboolean HL_APIENTRY nlGetRemoteAddr(NLsocket socket, NLaddress *address)
{
if(driver)
{
if(address == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
if(nlIsValidSocket(socket) == NL_TRUE)
{
nl_socket_t *sock = nlSockets[socket];
if(nlLockSocket(socket, NL_READ) == NL_FALSE)
{
return NL_FALSE;
}
memcpy(address, &sock->addressin, sizeof(NLaddress));
address->valid = NL_TRUE;
nlUnlockSocket(socket, NL_READ);
}
else
{
nlSetError(NL_INVALID_SOCKET);
memset(address, 0, sizeof(NLaddress));
return NL_FALSE;
}
return NL_TRUE;
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Sets the remote address of an unconnected UDP socket.
*/
HL_EXP NLboolean HL_APIENTRY nlSetRemoteAddr(NLsocket socket, const NLaddress *address)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
if(address == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
else
{
nl_socket_t *sock = nlSockets[socket];
if(nlLockSocket(socket, NL_WRITE) == NL_FALSE)
{
return NL_FALSE;
}
memcpy(&sock->addressout, address, sizeof(NLaddress));
nlUnlockSocket(socket, NL_WRITE);
}
}
else
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
return NL_TRUE;
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Gets the local address.
*/
HL_EXP NLboolean HL_APIENTRY nlGetLocalAddr(NLsocket socket, NLaddress *address)
{
if(driver)
{
if(nlIsValidSocket(socket) == NL_TRUE)
{
if(address == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
if(nlLockSocket(socket, NL_READ) == NL_FALSE)
{
return NL_FALSE;
}
if(driver->GetLocalAddr(socket, address) != NL_TRUE)
{
nlUnlockSocket(socket, NL_READ);
return NL_FALSE;
}
nlUnlockSocket(socket, NL_READ);
}
else
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
return NL_TRUE;
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
HL_EXP NLaddress * HL_APIENTRY nlGetAllLocalAddr(/*@out@*/ NLint *count)
{
if(driver)
{
if(count == NULL)
{
nlSetError(NL_NULL_POINTER);
return NULL;
}
return driver->GetAllLocalAddr(count);
}
nlSetError(NL_NO_NETWORK);
return NULL;
}
HL_EXP NLboolean HL_APIENTRY nlSetLocalAddr(const NLaddress *address)
{
if(driver)
{
if(address == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
return driver->SetLocalAddr(address);
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Resolves the name from the address.
*/
HL_EXP /*@null@*/ NLchar* HL_APIENTRY nlGetNameFromAddr(const NLaddress *address, NLchar *name)
{
if(driver)
{
if((name == NULL) || (address == NULL))
{
nlSetError(NL_NULL_POINTER);
return NULL;
}
return (driver->GetNameFromAddr(address, name));
}
nlSetError(NL_NO_NETWORK);
return NULL;
}
/*
Resolves the name from the address asynchronously.
*/
HL_EXP NLboolean HL_APIENTRY nlGetNameFromAddrAsync(const NLaddress *address, NLchar *name)
{
if(driver)
{
if((name == NULL) || (address == NULL))
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
return driver->GetNameFromAddrAsync(address, name);
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Get the address from a host name.
*/
HL_EXP NLboolean HL_APIENTRY nlGetAddrFromName(const NLchar *name, NLaddress *address)
{
if(driver)
{
if((name == NULL) || (address == NULL))
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
if(isSafeString(name) == NL_FALSE)
{
nlSetError(NL_STRING_OVER_RUN);
return NL_FALSE;
}
return driver->GetAddrFromName(name, address);
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Get the address from a host name asynchronously.
*/
HL_EXP NLboolean HL_APIENTRY nlGetAddrFromNameAsync(const NLchar *name, NLaddress *address)
{
if(driver)
{
if((name == NULL) || (address == NULL))
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
if(isSafeString(name) == NL_FALSE)
{
nlSetError(NL_STRING_OVER_RUN);
return NL_FALSE;
}
return driver->GetAddrFromNameAsync(name, address);
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Compare two addresses.
*/
HL_EXP NLboolean HL_APIENTRY nlAddrCompare(const NLaddress *address1, const NLaddress *address2)
{
if(driver)
{
if((address1 == NULL) || (address2 == NULL))
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
return driver->AddrCompare(address1, address2);
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Get the port number from an address.
*/
HL_EXP NLushort HL_APIENTRY nlGetPortFromAddr(const NLaddress *address)
{
if(driver)
{
if(address == NULL)
{
nlSetError(NL_NULL_POINTER);
return 0;
}
return driver->GetPortFromAddr(address);
}
nlSetError(NL_NO_NETWORK);
return 0;
}
/*
Set the port number in the address.
*/
HL_EXP NLboolean HL_APIENTRY nlSetAddrPort(NLaddress *address, NLushort port)
{
if(driver)
{
if(address == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
driver->SetAddrPort(address, port);
return NL_TRUE;
}
nlSetError(NL_NO_NETWORK);
return NL_FALSE;
}
/*
Non-socket functions
*/
/*
Select the network to use.
*/
HL_EXP NLboolean HL_APIENTRY nlSelectNetwork(NLenum network)
{
int i, found = 0;
if(driver != NULL)
{
/* we cannot select a new network without shutting down first */
nlSetError(NL_SELECT_NET_ERROR);
return NL_FALSE;
}
for(i=0;i<MAX_NET_DRIVERS;i++)
{
if(netdrivers[i].name == NULL)
{
break;
}
if(netdrivers[i].type == network)
{
found++;
if(netdrivers[i].initialized == NL_TRUE)
{
driver = &netdrivers[i];
return NL_TRUE;
}
}
}
if(found > 0)
{
nlSetError(NL_INVALID_TYPE);
}
else
{
nlSetError(NL_INVALID_ENUM);
}
return NL_FALSE;
}
/*
Returns a string corresponding to the NLenum.
*/
HL_EXP const /*@observer@*//*@null@*/ NLchar* HL_APIENTRY nlGetString(NLenum name)
{
/* use seperate strings for thread safety */
static NLchar vstring[NL_MAX_STRING_LENGTH];
static NLchar tstring[NL_MAX_STRING_LENGTH];
NLint i;
nlSetError(NL_NO_ERROR);
/* intitialize the version string */
_tcsncpy(vstring, (NLchar *)TEXT(NL_VERSION_STRING), (size_t)NL_MAX_STRING_LENGTH);
vstring[NL_MAX_STRING_LENGTH - 1] = (NLchar) '\0';
#ifdef _UNICODE
/* add the UNICODE string */
safecat(vstring, (NLchar *)TEXT(" UNICODE version"));
#endif
/* intitialize the network types string */
memset(tstring, 0, sizeof(NLchar) * NL_MAX_STRING_LENGTH);
for(i=0;i<MAX_NET_DRIVERS;i++)
{
if(netdrivers[i].name == NULL)
{
break;
}
if(netdrivers[i].initialized == NL_TRUE)
{
safecat((NLchar *)tstring, (const NLchar *)netdrivers[i].name);
safecat((NLchar *)tstring, (NLchar *)TEXT(" "));
}
}
switch (name) {
case NL_VERSION:
return (const NLchar*)vstring;
case NL_NETWORK_TYPES:
return (const NLchar*)tstring;
case NL_SOCKET_TYPES:
if(driver != NULL)
{
return (const NLchar*)(driver->socktypes);
}
else
{
nlSetError(NL_NO_NETWORK);
}
break;
default:
nlSetError(NL_INVALID_ENUM);
}
return NULL;
}
/*
Returns an integer corresponding to the NLenum.
*/
HL_EXP NLlong HL_APIENTRY nlGetInteger(NLenum name)
{
switch (name) {
case NL_PACKETS_SENT:
return nlOutstats.packets;
case NL_BYTES_SENT:
return nlOutstats.bytes;
case NL_AVE_BYTES_SENT:
nlUpdateOutStats(0, 0);
return nlOutstats.average;
case NL_HIGH_BYTES_SENT:
return nlOutstats.highest;
case NL_PACKETS_RECEIVED:
return nlInstats.packets;
case NL_BYTES_RECEIVED:
return nlInstats.bytes;
case NL_AVE_BYTES_RECEIVED:
nlUpdateInStats(0, 0);
return nlInstats.average;
case NL_HIGH_BYTES_RECEIVED:
return nlInstats.highest;
case NL_OPEN_SOCKETS:
return nlNumsockets;
default:
nlSetError(NL_INVALID_ENUM);
}
return 0;
}
/*
Clears the stat corresponding to the NLenum.
*/
HL_EXP NLboolean HL_APIENTRY nlClear(NLenum name)
{
switch (name) {
case NL_PACKETS_SENT:
if(htMutexLock(&outstatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlOutstats.packets = 0;
(void)htMutexUnlock(&outstatlock);
break;
case NL_BYTES_SENT:
if(htMutexLock(&outstatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlOutstats.bytes = 0;
(void)htMutexUnlock(&outstatlock);
break;
case NL_AVE_BYTES_SENT:
if(htMutexLock(&outstatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlOutstats.average = 0;
memset((NLbyte *)nlOutstats.bucket, 0, sizeof(NLlong) * NL_NUM_BUCKETS);
(void)htMutexUnlock(&outstatlock);
break;
case NL_HIGH_BYTES_SENT:
if(htMutexLock(&outstatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlOutstats.highest = 0;
(void)htMutexUnlock(&outstatlock);
break;
case NL_PACKETS_RECEIVED:
if(htMutexLock(&instatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlInstats.packets = 0;
(void)htMutexUnlock(&instatlock);
break;
case NL_BYTES_RECEIVED:
if(htMutexLock(&instatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlInstats.bytes = 0;
(void)htMutexUnlock(&instatlock);
break;
case NL_AVE_BYTES_RECEIVED:
if(htMutexLock(&instatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlInstats.average = 0;
memset((NLbyte *)nlInstats.bucket, 0, sizeof(NLlong) * NL_NUM_BUCKETS);
(void)htMutexUnlock(&instatlock);
break;
case NL_HIGH_BYTES_RECEIVED:
if(htMutexLock(&instatlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
nlInstats.highest = 0;
(void)htMutexUnlock(&instatlock);
break;
case NL_ALL_STATS:
(void)nlClear(NL_PACKETS_SENT);
(void)nlClear(NL_BYTES_SENT);
(void)nlClear(NL_AVE_BYTES_SENT);
(void)nlClear(NL_HIGH_BYTES_SENT);
(void)nlClear(NL_PACKETS_RECEIVED);
(void)nlClear(NL_BYTES_RECEIVED);
(void)nlClear(NL_AVE_BYTES_RECEIVED);
(void)nlClear(NL_HIGH_BYTES_RECEIVED);
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
/*
Get the socket or system error.
*/
HL_EXP NLint HL_APIENTRY nlGetSystemError(void)
{
if(driver)
{
return driver->GetSystemError();
}
return NL_NO_NETWORK;
}
HL_EXP NLboolean HL_APIENTRY nlEnable(NLenum name)
{
switch (name) {
case NL_BLOCKING_IO:
nlBlocking = NL_TRUE;
break;
case NL_TCP_NO_DELAY:
return nlHint(NL_TCP_NO_DELAY, (NLint)NL_TRUE);
case NL_SOCKET_STATS:
nlState.socketStats = NL_TRUE;
break;
case NL_BIG_ENDIAN_DATA:
nlState.nl_big_endian_data = NL_TRUE;
break;
case NL_LITTLE_ENDIAN_DATA:
nlState.nl_big_endian_data = NL_FALSE;
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
HL_EXP NLboolean HL_APIENTRY nlDisable(NLenum name)
{
switch (name) {
case NL_BLOCKING_IO:
nlBlocking = NL_FALSE;
break;
case NL_TCP_NO_DELAY:
return nlHint(NL_TCP_NO_DELAY, NL_FALSE);
case NL_SOCKET_STATS:
nlState.socketStats = NL_FALSE;
break;
case NL_BIG_ENDIAN_DATA:
nlState.nl_big_endian_data = NL_FALSE;
break;
case NL_LITTLE_ENDIAN_DATA:
nlState.nl_big_endian_data = NL_TRUE;
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
HL_EXP NLboolean HL_APIENTRY nlGetBoolean(NLenum name)
{
switch (name) {
case NL_BLOCKING_IO:
return nlBlocking;
case NL_SOCKET_STATS:
return nlState.socketStats;
case NL_BIG_ENDIAN_DATA:
return nlState.nl_big_endian_data;
case NL_LITTLE_ENDIAN_DATA:
return (NLboolean)(nlState.nl_big_endian_data == NL_TRUE ? NL_FALSE:NL_TRUE);
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
}
HL_EXP NLlong HL_APIENTRY nlGetSocketStat(NLsocket socket, NLenum name)
{
nl_socket_t *sock;
NLlong result = 0;
if(nlIsValidSocket(socket) == NL_FALSE)
{
nlSetError(NL_INVALID_SOCKET);
return 0;
}
if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
{
return 0;
}
sock = nlSockets[socket];
switch (name) {
case NL_PACKETS_SENT:
result = sock->outstats.packets;
break;
case NL_BYTES_SENT:
result = sock->outstats.bytes;
break;
case NL_AVE_BYTES_SENT:
nlUpdateSocketOutStats(socket, 0, 0);
result = sock->outstats.average;
if(result == 0)
{
/* this corrects the stats for the first second */
result = sock->outstats.curbytes;
}
break;
case NL_HIGH_BYTES_SENT:
result = sock->outstats.highest;
break;
case NL_PACKETS_RECEIVED:
result = sock->instats.packets;
break;
case NL_BYTES_RECEIVED:
result = sock->instats.bytes;
break;
case NL_AVE_BYTES_RECEIVED:
nlUpdateSocketInStats(socket, 0, 0);
result = sock->instats.average;
if(result == 0)
{
/* this corrects the stats for the first second */
result = sock->instats.curbytes;
}
break;
case NL_HIGH_BYTES_RECEIVED:
result = sock->instats.highest;
break;
default:
nlSetError(NL_INVALID_ENUM);
}
nlUnlockSocket(socket, NL_BOTH);
return result;
}
HL_EXP NLboolean HL_APIENTRY nlClearSocketStat(NLsocket socket, NLenum name)
{
nl_socket_t *sock;
if(nlIsValidSocket(socket) == NL_FALSE)
{
nlSetError(NL_INVALID_SOCKET);
return NL_FALSE;
}
if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
{
return NL_FALSE;
}
sock = nlSockets[socket];
switch (name) {
case NL_PACKETS_SENT:
sock->outstats.packets = 0;
break;
case NL_BYTES_SENT:
sock->outstats.bytes = 0;
break;
case NL_AVE_BYTES_SENT:
sock->outstats.average = 0;
memset((NLbyte *)sock->outstats.bucket, 0, sizeof(NLlong) * NL_NUM_BUCKETS);
break;
case NL_HIGH_BYTES_SENT:
sock->outstats.highest = 0;
break;
case NL_PACKETS_RECEIVED:
sock->instats.packets = 0;
break;
case NL_BYTES_RECEIVED:
sock->instats.bytes = 0;
break;
case NL_AVE_BYTES_RECEIVED:
sock->instats.average = 0;
memset((NLbyte *)sock->instats.bucket, 0, sizeof(NLlong) * NL_NUM_BUCKETS);
break;
case NL_HIGH_BYTES_RECEIVED:
sock->instats.highest = 0;
break;
case NL_ALL_STATS:
sock->outstats.packets = 0;
sock->outstats.bytes = 0;
sock->outstats.average = 0;
memset((NLbyte *)sock->outstats.bucket, 0, sizeof(NLlong) * NL_NUM_BUCKETS);
sock->outstats.highest = 0;
sock->instats.packets = 0;
sock->instats.bytes = 0;
sock->instats.average = 0;
memset((NLbyte *)sock->instats.bucket, 0, sizeof(NLlong) * NL_NUM_BUCKETS);
sock->instats.highest = 0;
break;
default:
nlSetError(NL_INVALID_ENUM);
nlUnlockSocket(socket, NL_BOTH);
return NL_FALSE;
}
nlUnlockSocket(socket, NL_BOTH);
return NL_TRUE;
}
HL_EXP NLushort HL_APIENTRY nlSwaps(NLushort x)
{
if(NL_SWAP_TRUE)
{
return (NLushort)(((((NLushort)x) & 0x00ff) << 8) | ((((NLushort)x) & 0xff00) >> 8));
}
else
{
return x;
}
}
HL_EXP NLulong HL_APIENTRY nlSwapl(NLulong x)
{
if(NL_SWAP_TRUE)
{
return (NLulong)(((((NLulong)x) & 0x000000ff) << 24) | ((((NLulong)x) & 0x0000ff00) << 8) | ((((NLulong)x) & 0x00ff0000) >> 8) | ((((NLulong)x) & 0xff000000) >> 24));
}
else
{
return x;
}
}
HL_EXP NLfloat HL_APIENTRY nlSwapf(NLfloat f)
{
if(NL_SWAP_TRUE)
{
NLulong temp = (NLulong)nlSwapl(*(NLulong *)&f);
return *((float *)&temp);
}
else
{
return f;
}
}
HL_EXP NLdouble HL_APIENTRY nlSwapd(NLdouble d)
{
if(NL_SWAP_TRUE)
{
union {NLulong l[2]; NLdouble d;} in, out;
in.d = d;
out.l[0] = nlSwapl(in.l[1]);
out.l[1] = nlSwapl(in.l[0]);
return out.d;
}
else
{
return d;
}
}
#if defined (__LCC__)
BOOL WINAPI __declspec(dllexport) LibMain(/*@unused@*/HINSTANCE hinstDLL, /*@unused@*/DWORD fdwReason, /*@unused@*/LPVOID lpvReserved)
{
return TRUE;
}
#endif /* WINDOWS APP */
diff --git a/util/network/hawknl/src/nltime.c b/util/network/hawknl/src/nltime.c
index 1fb8a4d3..6c2d9a42 100644
--- a/util/network/hawknl/src/nltime.c
+++ b/util/network/hawknl/src/nltime.c
@@ -1,185 +1,185 @@
/*
HawkNL time module
Copyright (C) 2000-2004 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
*/
-#include "nlinternal.h"
+#include "hawknl/nlinternal.h"
#ifdef HL_WINDOWS_APP
#ifdef _MSC_VER
#pragma warning (disable:4201)
#pragma warning (disable:4214)
#endif /* _MSC_VER */
#include <windows.h>
#include <winbase.h>
#include <limits.h>
#ifdef _MSC_VER
#pragma warning (default:4201)
#pragma warning (default:4214)
#endif /* _MSC_VER */
struct mytimeb {
time_t time;
unsigned short millitm;
};
static void myftime(/*@out@*/ struct mytimeb *tb)
{
static int needinit = 1;
static time_t currentseconds;
static DWORD currentmseconds;
static DWORD lastmseconds;
if(needinit == 1)
{
time_t t;
currentseconds = time(&t);
lastmseconds = GetTickCount();
currentmseconds = lastmseconds % 1000;
needinit = 0;
}
else
{
DWORD mseconds = GetTickCount();
/* check for roll over */
if(mseconds < lastmseconds)
{
currentmseconds += (UINT_MAX - lastmseconds) + mseconds + 1;
}
else
{
currentmseconds += mseconds - lastmseconds;
}
lastmseconds = mseconds;
while(currentmseconds > 1000)
{
currentseconds++;
currentmseconds -= 1000;
}
}
tb->time = currentseconds;
tb->millitm = (unsigned short)currentmseconds;
}
#else /* !HL_WINDOWS_APP */
#include <sys/time.h>
#endif /* !HL_WINDOWS_APP */
HL_EXP NLboolean HL_APIENTRY nlTime(NLtime *t)
{
#ifdef HL_WINDOWS_APP
static NLboolean needinit = NL_TRUE;
static NLboolean haspcounter = NL_FALSE;
static LARGE_INTEGER freq;
static LARGE_INTEGER lastcount;
static NLtime currenttime;
if(t == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
if(needinit == NL_TRUE)
{
if(QueryPerformanceFrequency(&freq) != 0)
{
if(QueryPerformanceCounter(&lastcount) != 0)
{
/* get the current time */
struct mytimeb tb;
myftime(&tb);
currenttime.seconds = (NLlong)(tb.time);
currenttime.useconds = (NLlong)(tb.millitm * 1000);
haspcounter = NL_TRUE;
}
}
needinit = NL_FALSE;
}
if(haspcounter == NL_TRUE)
{
LARGE_INTEGER currentcount;
LARGE_INTEGER diffcount;
(void)QueryPerformanceCounter(&currentcount);
diffcount.QuadPart = currentcount.QuadPart - lastcount.QuadPart;
lastcount.QuadPart = currentcount.QuadPart;
while(diffcount.QuadPart >= freq.QuadPart)
{
diffcount.QuadPart -= freq.QuadPart;
currenttime.seconds++;
}
currenttime.useconds += (NLlong)(diffcount.QuadPart * 1000000 / freq.QuadPart);
if(currenttime.useconds >= 1000000)
{
currenttime.useconds -= 1000000;
currenttime.seconds++;
}
t->seconds = currenttime.seconds;
t->mseconds = currenttime.useconds / 1000;
t->useconds = currenttime.useconds;
}
else
{
/* fall back to myftime */
struct mytimeb tb;
myftime(&tb);
t->seconds = (NLlong)(tb.time);
t->mseconds = (NLlong)(tb.millitm);
t->useconds = (NLlong)(tb.millitm * 1000);
}
#else /* !HL_WINDOWS_APP */
struct timeval tv;
if(t == NULL)
{
nlSetError(NL_NULL_POINTER);
return NL_FALSE;
}
gettimeofday(&tv, NULL);
t->seconds = (NLlong)(tv.tv_sec);
t->mseconds = (NLlong)(tv.tv_usec / 1000);
t->useconds = (NLlong)(tv.tv_usec);
#endif /* !HL_WINDOWS_APP */
return NL_TRUE;
}
/* Windows CE does not have time.h functions */
#if defined (_WIN32_WCE)
time_t time(time_t *timer)
{
NLtime t;
nlTime(&t);
*timer = t.seconds;
return *timer;
}
#endif
diff --git a/util/network/hawknl/src/sock.c b/util/network/hawknl/src/sock.c
index de53bdfb..824b8436 100644
--- a/util/network/hawknl/src/sock.c
+++ b/util/network/hawknl/src/sock.c
@@ -1,2698 +1,2698 @@
/*
HawkNL cross platform network library
Copyright (C) 2000-2004 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
*/
#define FD_SETSIZE 8192
#include <memory.h>
#include <stdio.h>
#include <string.h>
#if defined (_WIN32_WCE)
#define EAGAIN 11
#define errno GetLastError()
#else
#include <errno.h>
#endif
#if defined WIN32 || defined WIN64 || defined (_WIN32_WCE)
#include "wsock.h"
#elif defined Macintosh
#include <Types.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/time.h>
#include <LowMem.h>
#define closesocket close
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKET int
#define sockerrno errno
/* define INADDR_NONE if not already */
#ifndef INADDR_NONE
#define INADDR_NONE ((unsigned long) -1)
#endif
#else
/* Unix-style systems */
#ifdef SOLARIS
#include <sys/filio.h> /* for FIONBIO */
#endif
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#define closesocket close
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKET int
#define SD_RECEIVE 0
#define SD_SEND 1
#define SD_BOTH 2
#define sockerrno errno
/* define INADDR_NONE if not already */
#ifndef INADDR_NONE
#define INADDR_NONE ((unsigned long) -1)
#endif
/* SGI and MacOS X do not include socklen_t */
// #if defined __sgi || defined MACOSX
#if defined __sgi
typedef int socklen_t;
#endif
#endif /* HL_WINDOWS_APP*/
-#include "nlinternal.h"
-#include "sock.h"
+#include "hawknl/nlinternal.h"
+#include "hawknl/sock.h"
#ifndef IN_MULTICAST
#define IN_MULTICAST(i) (((unsigned long)(i) & 0xF0000000) == (unsigned long)0xE0000000)
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN NL_MAX_STRING_LENGTH
#endif
#define NL_CONNECT_STRING "HawkNL request connection."
#define NL_REPLY_STRING "HawkNL connection OK."
#define NL_HEADER_LEN 4
/*
* Portable NLMAX() function macro
*/
#define NLMAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
#define NLMIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
static volatile NLuint ouraddress, bindaddress;
int backlog = SOMAXCONN;
static volatile int multicastTTL = 1;
NLboolean reuseaddress = NL_FALSE;
static volatile NLboolean nlTCPNoDelay = NL_FALSE;
static NLaddress *alladdr = NULL;
typedef struct
{
NLaddress /*@temp@*/*address;
NLchar /*@temp@*/*name;
NLsocket socket;
} NLaddress_ex_t;
extern SOCKET nlGroupGetFdset(NLint group, /*@out@*/ fd_set *fd);
extern NLushort ipx_GetPort(SOCKET socket);
extern NLushort ipx_GetPortFromAddr(const NLaddress *address);
/*
This is a Winsock work around to be able to bind() to more than 3976 ports
*/
#ifdef HL_WINDOWS_APP
static HTmutex portlock; /* In memory of my step-father, Don Portlock,
who passed away Jan 12, 2001 - Phil */
static volatile NLushort nextport = 1024;
static NLushort sock_getNextPort(void)
{
NLlong temp;
(void)htMutexLock(&portlock);
temp = (NLlong)nextport;
if(++temp > 65535)
{
/* skip the well known ports */
temp = 1024;
}
nextport = (NLushort)temp;
(void)htMutexUnlock(&portlock);
return nextport;
}
static NLint sock_bind(SOCKET socket, const struct sockaddr *a, int len)
{
struct sockaddr_in *addr = (struct sockaddr_in *)a;
int ntries = 500; /* this is to prevent an infinite loop */
NLboolean found = NL_FALSE;
/* check to see if the port is already specified */
if(addr->sin_port != 0)
{
/* do the normal bind */
return bind(socket, a, len);
}
/* let's find our own port number */
while(ntries-- > 0)
{
addr->sin_port = htons(sock_getNextPort());
if(bind(socket, (struct sockaddr *)addr, len) != SOCKET_ERROR)
{
found = NL_TRUE;
break;
}
}
if(found == NL_TRUE)
{
return 0;
}
/* could not find a port, restore the port number back to 0 */
addr->sin_port = 0;
/* return error */
return SOCKET_ERROR;
}
static int sock_connect(SOCKET socket, const struct sockaddr* a, int len )
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
if(sock_bind(socket, (struct sockaddr *)&addr, (int)sizeof(addr)) == SOCKET_ERROR)
{
return SOCKET_ERROR;
}
return connect(socket, a, len);
}
void nlFD_CLR(SOCKET fd, fd_set *set)
{
u_int i;
for(i=0;i<set->fd_count;i++)
{
if(set->fd_array[i] == fd)
{
while(i < set->fd_count-1)
{
set->fd_array[i] = set->fd_array[i+1];
i++;
}
set->fd_count--;
break;
}
}
}
void nlFD_SET(SOCKET fd, /*@out@*/ fd_set *set)
{
if(set->fd_count < FD_SETSIZE)
set->fd_array[set->fd_count++]=fd;
}
/* This function is inlined for speed over the Winsock function */
int nlWSAFDIsSet(SOCKET fd, fd_set *set)
{
int i = (int)set->fd_count;
while(i-- != 0)
{
if (set->fd_array[i] == fd)
return 1;
}
return 0;
}
#else
#define sock_bind bind
#define sock_connect connect
#endif /* HL_WINDOWS_APP */
/*
helper functions for NL_RELIABLE_PACKETS
*/
static NLint rpGroup; /* the group to hold all the NL_RELIABLE_PACKETS sockets */
static HTmutex rpMutex; /* mutex to lock the functions */
static NLboolean needThread = NL_TRUE; /* do we need to spawn a thread? */
static NLint rpSocketCount = 0; /* total count of NL_RELIABLE_PACKETS sockets */
static volatile NLint rpBufferedCount = 0;/* count of sockets that are buffering data */
static void sock_WritePacketCheckPending(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
/* first check for data waiting to be sent */
if(sock->sendlen > 0)
{
NLint count, size = NL_MAX_PACKET_LENGTH + NL_HEADER_LEN;
if(size > sock->sendlen)
{
size = sock->sendlen;
}
count = send((SOCKET)sock->realsocket, (char *)sock->outbuf, size, 0);
if(count > 0)
{
sock->sendlen -= count;
if(sock->sendlen > 0)
{
/* move remaining data to beginning of outbuf */
memmove(sock->outbuf, (sock->outbuf + count), (size_t)sock->sendlen);
}
else
{
rpBufferedCount--;
}
}
}
}
static void *sock_rpThread(void *p)
{
static NLsocket *sockets = NULL;
static NLint maxsockets = 0;
/* allocate memory */
if(sockets == NULL)
{
sockets = (NLsocket *)malloc(sizeof(NLsocket *) * 16);
if(sockets == NULL)
{
needThread = NL_TRUE;
return NULL;
}
maxsockets = 16;
}
while(rpGroup != NL_INVALID)
{
NLint count = maxsockets;
/* make sure there is something to do */
if(rpSocketCount == 0 || rpBufferedCount == 0)
{
goto loopend;
}
/* see if we need to allocate more memory */
if(maxsockets < rpSocketCount)
{
NLsocket *temp;
while(maxsockets < rpSocketCount)
{
maxsockets *= 2;
}
temp = (NLsocket *)realloc((void *)sockets, sizeof(NLsocket *) * maxsockets);
if(temp == NULL)
{
goto cleanup;
}
sockets = temp;
}
/* we can now get the sockets */
if(nlGroupGetSockets(rpGroup, sockets, &count) == NL_FALSE)
{
goto cleanup;
}
while(count-- > 0 && rpBufferedCount > 0)
{
NLsocket socket = sockets[count];
(void)nlLockSocket(socket, NL_WRITE);
sock_WritePacketCheckPending(socket);
nlUnlockSocket(socket, NL_WRITE);
}
loopend:
htThreadSleep(50);
}
cleanup:
free(sockets);
sockets = NULL;
maxsockets = 0;
needThread = NL_TRUE;
return p;
}
static void sock_AddSocket(NLsocket socket)
{
(void)htMutexLock(&rpMutex);
(void)nlGroupAddSocket(rpGroup, socket);
rpSocketCount++;
if(needThread == NL_TRUE)
{
(void)htThreadCreate(sock_rpThread, NULL, NL_FALSE);
needThread = NL_FALSE;
}
(void)htMutexUnlock(&rpMutex);
}
static void sock_DeleteSocket(NLsocket socket)
{
(void)htMutexLock(&rpMutex);
(void)nlGroupDeleteSocket(rpGroup, socket);
rpSocketCount--;
(void)htMutexUnlock(&rpMutex);
}
/*
handle some common connection errors so the app knows when a connection has been dropped
*/
NLint sock_Error(void)
{
switch (sockerrno) {
#ifdef HL_WINDOWS_APP
case WSABASEERR:
return 0;
#endif
case EWOULDBLOCK:
return 0;
case ENETRESET:
case EHOSTUNREACH:
case ECONNABORTED:
case ECONNRESET:
case ENETUNREACH:
case ETIMEDOUT:
nlSetError(NL_SOCK_DISCONNECT);
break;
default:
nlSetError(NL_SYSTEM_ERROR);
break;
}
return NL_INVALID;
}
NLboolean sock_SetBlocking(SOCKET socket, NLboolean arg)
{
int rc;
unsigned long i = 1;
if(arg == NL_TRUE)
{
i = 0;
}
rc = ioctl(socket, FIONBIO, &i);
if(rc == SOCKET_ERROR)
{
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean sock_SetBroadcast(SOCKET socket)
{
int i = 1;
if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, (int)sizeof(i)) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean sock_SetReuseAddr(nl_socket_t *sock)
{
int i = 1;
if(setsockopt((SOCKET)sock->realsocket, SOL_SOCKET, SO_REUSEADDR, (char *)&i, (int)sizeof(i)) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
sock->reuseaddr = NL_TRUE;
return NL_TRUE;
}
static NLboolean sock_SetTCPNoDelay(nl_socket_t *sock, NLboolean arg)
{
NLenum type = sock->type;
SOCKET realsocket = (SOCKET)sock->realsocket;
int i;
if(type == NL_TCP || type == NL_TCP_PACKETS)
{
arg = (NLboolean)(arg != (NLboolean)0 ? NL_TRUE : NL_FALSE);
i = (int)arg;
if(setsockopt(realsocket, IPPROTO_TCP, TCP_NODELAY, (char *)&i, (int)sizeof(i)) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
sock->TCPNoDelay = arg;
return NL_TRUE;
}
static NLboolean sock_SetMulticastTTL(nl_socket_t *sock, NLint ttl)
{
SOCKET realsocket = (SOCKET)sock->realsocket;
unsigned char cttl;
/* make sure we have a valid TTL */
if(ttl > 255) ttl = 255;
if(ttl < 1) ttl = 1;
cttl = (unsigned char)ttl;
/* first try setsockopt by passing a 'char', the Unix standard */
if(setsockopt(realsocket, IPPROTO_IP, IP_MULTICAST_TTL,
(char *)&cttl, (int)sizeof(cttl)) == SOCKET_ERROR)
{
/* if that failed, we might be on a Windows system
that requires an 'int' */
if(setsockopt(realsocket, IPPROTO_IP, IP_MULTICAST_TTL,
(char *)&ttl, (int)sizeof(ttl)) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
sock->TTL = ttl;
return NL_TRUE;
}
static NLsocket sock_SetSocketOptions(NLsocket s)
{
nl_socket_t *sock = nlSockets[s];
NLenum type = sock->type;
SOCKET realsocket = (SOCKET)sock->realsocket;
if(type == NL_RELIABLE || type == NL_RELIABLE_PACKETS)
{
sock->reliable = NL_TRUE;
if(type == NL_RELIABLE_PACKETS)
{
sock->packetsync = NL_TRUE;
}
}
else
{
sock->reliable = NL_FALSE;
}
if(sock->driver == NL_IP)
{
if(sock_SetTCPNoDelay(sock, sock->TCPNoDelay) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_INVALID;
}
}
if(reuseaddress == NL_TRUE)
{
if(sock_SetReuseAddr(sock) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_INVALID;
}
}
if(sock_SetBlocking(realsocket, sock->blocking) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_INVALID;
}
return s;
}
static NLuint sock_GetHostAddress(void)
{
struct hostent *local;
char buff[MAXHOSTNAMELEN];
if(gethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR)
{
return INADDR_NONE;
}
buff[MAXHOSTNAMELEN - 1] = '\0';
local = gethostbyname(buff);
if(!local)
return (NLuint)htonl(0x7f000001);
return *(NLuint *)local->h_addr_list[0];
}
static NLushort sock_GetPort(SOCKET socket)
{
struct sockaddr_in addr;
socklen_t len;
len = (socklen_t)sizeof(struct sockaddr_in);
if(getsockname(socket, (struct sockaddr *) &addr, &len) == SOCKET_ERROR)
{
return 0;
}
return ntohs(addr.sin_port);
}
NLboolean sock_Init(void)
{
#ifdef HL_WINDOWS_APP
WSADATA libmibWSAdata;
/* We must have Winsock 2.0 */
if(WSAStartup(MAKEWORD(2, 0),&libmibWSAdata) != 0)
{
return NL_FALSE;
}
if(htMutexInit(&portlock) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
#endif
if(htMutexInit(&rpMutex) != 0)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
if((rpGroup = nlGroupCreate()) == NL_INVALID)
{
return NL_FALSE;
}
ouraddress = sock_GetHostAddress();
if(ouraddress == (NLuint)INADDR_NONE)
{
return NL_FALSE;
}
bindaddress = INADDR_ANY;
return NL_TRUE;
}
void sock_Shutdown(void)
{
#ifdef HL_WINDOWS_APP
(void)WSACleanup();
(void)htMutexDestroy(&portlock);
(void)htMutexDestroy(&rpMutex);
(void)nlGroupDestroy(rpGroup);
rpGroup = NL_INVALID;
#endif
if(alladdr != NULL)
{
free(alladdr);
alladdr = NULL;
}
}
NLboolean sock_Listen(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
if(sock->listen == NL_TRUE)
{
return NL_TRUE;
}
if(sock->reliable == NL_TRUE) /* TCP */
{
/* check for unbound socket */
if(sock->localport == 0)
{
NLint result;
/* bind socket */
#ifdef NL_INCLUDE_IPX
if(sock->driver == NL_IPX)
{
((struct sockaddr_ipx *)&sock->addressin)->sa_family = AF_IPX;
memset(((struct sockaddr_ipx *)&sock->addressin)->sa_netnum, 0, 4);
memset(((struct sockaddr_ipx *)&sock->addressin)->sa_nodenum, 0, 6);
((struct sockaddr_ipx *)&sock->addressin)->sa_socket = 0;
result = bind((SOCKET)sock->realsocket, (struct sockaddr *)&sock->addressin,
(int)sizeof(struct sockaddr_ipx));
}
else
#endif
{
((struct sockaddr_in *)&sock->addressin)->sin_family = AF_INET;
((struct sockaddr_in *)&sock->addressin)->sin_addr.s_addr = bindaddress;
((struct sockaddr_in *)&sock->addressin)->sin_port = 0;
result = sock_bind((SOCKET)sock->realsocket, (struct sockaddr *)&sock->addressin,
(int)sizeof(struct sockaddr_in));
}
if(result == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
if(listen((SOCKET)sock->realsocket, backlog) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
sock->listen = NL_TRUE;
return NL_TRUE;
}
static SOCKET sock_AcceptUDP(NLsocket nlsocket, /*@out@*/struct sockaddr_in *newaddr)
{
nl_socket_t *sock = nlSockets[nlsocket];
struct sockaddr_in ouraddr;
SOCKET newsocket;
NLushort localport;
NLbyte buffer[NL_MAX_STRING_LENGTH];
socklen_t len = (socklen_t)sizeof(struct sockaddr_in);
NLint slen = (NLint)sizeof(NL_CONNECT_STRING);
NLbyte reply = (NLbyte)0x00;
NLint count = 0;
/* Get the packet and remote host address */
if(recvfrom((SOCKET)sock->realsocket, buffer, (int)sizeof(buffer), 0,
(struct sockaddr *)newaddr, &len) < (int)sizeof(NL_CONNECT_STRING))
{
nlSetError(NL_NO_PENDING);
return INVALID_SOCKET;
}
/* Let's check for the connection string */
buffer[slen - 1] = (NLbyte)0; /* null terminate for peace of mind */
if(strcmp(buffer, NL_CONNECT_STRING) != 0)
{
nlSetError(NL_NO_PENDING);
return INVALID_SOCKET;
}
/* open up a new socket on this end */
newsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(newsocket == INVALID_SOCKET)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
ouraddr.sin_family = AF_INET;
ouraddr.sin_addr.s_addr = bindaddress;
/* system assigned port number */
ouraddr.sin_port = 0;
if(sock_bind(newsocket, (struct sockaddr *)&ouraddr, len) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
/* get the new port */
localport = sock_GetPort(newsocket);
/* create the return message */
writeShort(buffer, count, localport);
writeString(buffer, count, (NLchar *)TEXT(NL_REPLY_STRING));
/* send back the reply with our new port */
if(sendto((SOCKET)sock->realsocket, buffer, count, 0, (struct sockaddr *)newaddr,
(int)sizeof(struct sockaddr_in)) < count)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
/* send back a 0 length packet from our new port, needed for firewalls */
if(sendto(newsocket, &reply, 0, 0,
(struct sockaddr *)newaddr,
(int)sizeof(struct sockaddr_in)) < 0)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
/* connect the socket */
if(connect(newsocket, (struct sockaddr *)newaddr,
(int)sizeof(struct sockaddr_in)) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
(void)closesocket(newsocket);
return INVALID_SOCKET;
}
return newsocket;
}
NLsocket sock_AcceptConnection(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
nl_socket_t *newsock = NULL;
NLsocket newsocket = NL_INVALID;
SOCKET realsocket = INVALID_SOCKET;
struct sockaddr_in newaddr;
socklen_t len = (socklen_t)sizeof(newaddr);
memset(&newaddr, 0, sizeof(newaddr));
if(sock->listen != NL_TRUE)
{
nlSetError(NL_NOT_LISTEN);
return NL_INVALID;
}
if(sock->type == NL_RELIABLE || sock->type == NL_RELIABLE_PACKETS) /* TCP */
{
SOCKET s = 101;
/* !@#$% metrowerks compiler, try to get it to actually produce some code */
s = accept((SOCKET)(sock->realsocket), (struct sockaddr *)&newaddr, &len);
realsocket = s;
if(realsocket == INVALID_SOCKET)
{
if(sockerrno == (int)EWOULDBLOCK || errno == EAGAIN)/* yes, we need to use errno here */
{
nlSetError(NL_NO_PENDING);
}
else
{
nlSetError(NL_SYSTEM_ERROR);
}
return NL_INVALID;
}
}
else if(sock->type == NL_UNRELIABLE)/* UDP*/
{
realsocket = sock_AcceptUDP(socket, &newaddr);
if(realsocket == INVALID_SOCKET)
{
/* error is already set in sock_AcceptUDP */
return NL_INVALID;
}
}
else /* broadcast or multicast */
{
nlSetError(NL_WRONG_TYPE);
return NL_INVALID;
}
newsocket = nlGetNewSocket();
if(newsocket == NL_INVALID)
{
return NL_INVALID;
}
if(nlLockSocket(newsocket, NL_BOTH) == NL_FALSE)
{
return NL_INVALID;
}
newsock = nlSockets[newsocket];
/* update the remote address */
memcpy((char *)&newsock->addressin, (char *)&newaddr, sizeof(struct sockaddr_in));
newsock->realsocket = (NLint)realsocket;
newsock->localport = sock_GetPort(realsocket);
newsock->remoteport = sock_GetPortFromAddr((NLaddress *)&newsock->addressin);
newsock->type = sock->type;
newsock->TCPNoDelay = sock->TCPNoDelay;
newsock->connected = NL_TRUE;
newsock->blocking = sock->blocking;
if(newsock->type == NL_RELIABLE_PACKETS)
{
sock_AddSocket(newsocket);
}
return sock_SetSocketOptions(newsocket);
}
NLsocket sock_OpenINT(NLushort port, NLenum type, NLenum driver)
{
nl_socket_t *newsock;
NLsocket newsocket;
SOCKET realsocket;
switch (type) {
case NL_RELIABLE: /* TCP/SPX */
case NL_RELIABLE_PACKETS:
#ifdef NL_INCLUDE_IPX
if(driver == NL_IPX)
{
realsocket = socket(PF_IPX, SOCK_SEQPACKET, NSPROTO_SPXII);
type = NL_RELIABLE;
}
else
#endif
{
realsocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
}
break;
case NL_UNRELIABLE: /* UDP/IPX */
case NL_BROADCAST: /* UDP/IPX broadcast */
case NL_UDP_MULTICAST: /* UDP multicast */
#ifdef NL_INCLUDE_IPX
if(driver == NL_IPX)
{
if(type == NL_UDP_MULTICAST)
{
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
realsocket = socket(PF_IPX, SOCK_DGRAM, NSPROTO_IPX);
}
else
#endif
{
realsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
}
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
if(realsocket == INVALID_SOCKET)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_INVALID;
}
newsocket = nlGetNewSocket();
if(newsocket == NL_INVALID)
{
return NL_INVALID;
}
if(nlLockSocket(newsocket, NL_BOTH) == NL_FALSE)
{
return NL_INVALID;
}
newsock = nlSockets[newsocket];
newsock->realsocket = (NLint)realsocket;
newsock->type = type;
newsock->TCPNoDelay = nlTCPNoDelay;
if(sock_SetSocketOptions(newsocket) == NL_INVALID)
{
nlUnlockSocket(newsocket, NL_BOTH);
(void)sock_Close(newsocket);
return NL_INVALID;
}
/* do not bind a TCP/SPX socket here if the port is 0; let connect assign the port */
if((type == NL_RELIABLE || type == NL_RELIABLE_PACKETS) && port == 0)
{
newsock->localport = 0;
}
else
{
NLint result;
#ifdef NL_INCLUDE_IPX
if(driver == NL_IPX)
{
((struct sockaddr_ipx *)&newsock->addressin)->sa_family = AF_IPX;
memset(((struct sockaddr_ipx *)&newsock->addressin)->sa_netnum, 0, 4);
memset(((struct sockaddr_ipx *)&newsock->addressin)->sa_nodenum, 0, 6);
((struct sockaddr_ipx *)&newsock->addressin)->sa_socket = htons((unsigned short)port);
result = bind((SOCKET)realsocket, (struct sockaddr *)&newsock->addressin,
(int)sizeof(struct sockaddr_ipx));
}
else
#endif
{
((struct sockaddr_in *)&newsock->addressin)->sin_family = AF_INET;
((struct sockaddr_in *)&newsock->addressin)->sin_addr.s_addr = bindaddress;
((struct sockaddr_in *)&newsock->addressin)->sin_port = htons((unsigned short)port);
result = sock_bind(realsocket, (struct sockaddr *)&newsock->addressin,
(int)sizeof(struct sockaddr_in));
}
if(result == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
nlUnlockSocket(newsocket, NL_BOTH);
(void)sock_Close(newsocket);
return NL_INVALID;
}
if(type == NL_BROADCAST)
{
if(sock_SetBroadcast(realsocket) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
nlUnlockSocket(newsocket, NL_BOTH);
(void)sock_Close(newsocket);
return NL_INVALID;
}
#ifdef NL_INCLUDE_IPX
if(driver == NL_IPX)
{
((struct sockaddr_ipx *)&newsock->addressout)->sa_family = AF_IPX;
memset(((struct sockaddr_ipx *)&newsock->addressout)->sa_netnum, 0, 4);
memset(((struct sockaddr_ipx *)&newsock->addressout)->sa_nodenum, 0xff, 6);
((struct sockaddr_ipx *)&newsock->addressout)->sa_socket = htons((unsigned short)port);
}
else
#endif
{
((struct sockaddr_in *)&newsock->addressout)->sin_family = AF_INET;
((struct sockaddr_in *)&newsock->addressout)->sin_addr.s_addr = INADDR_BROADCAST;
((struct sockaddr_in *)&newsock->addressout)->sin_port = htons((unsigned short)port);
}
}
#ifdef NL_INCLUDE_IPX
if(driver == NL_IPX)
{
newsock->localport = ipx_GetPort(realsocket);
}
else
#endif
{
newsock->localport = sock_GetPort(realsocket);
}
}
if(type == NL_RELIABLE_PACKETS)
{
sock_AddSocket(newsocket);
}
newsock->driver = driver;
nlUnlockSocket(newsocket, NL_BOTH);
return newsocket;
}
NLsocket sock_Open(NLushort port, NLenum type)
{
return sock_OpenINT(port, type, NL_IP);
}
static NLboolean sock_ConnectUDP(NLsocket socket, const NLaddress *address)
{
nl_socket_t *sock = nlSockets[socket];
time_t begin, t;
socklen_t len = (socklen_t)sizeof(struct sockaddr_in);
sock->conerror = NL_FALSE;
#ifdef NL_INCLUDE_IPX
if(sock->driver == NL_IPX)
{
len = (socklen_t)sizeof(struct sockaddr_ipx);
}
#endif
if(sendto((SOCKET)sock->realsocket, (char *)NL_CONNECT_STRING, (NLint)sizeof(NL_CONNECT_STRING),
0, (struct sockaddr *)address, len)
== SOCKET_ERROR)
{
if(sock->blocking == NL_TRUE)
{
nlSetError(NL_SYSTEM_ERROR);
}
else
{
sock->conerror = NL_TRUE;
}
return NL_FALSE;
}
(void)time(&begin);
/* try for six seconds */
while((time(&t) - begin) < 6)
{
NLbyte buffer[NL_MAX_STRING_LENGTH];
NLbyte *pbuffer = buffer;
NLushort newport;
NLint slen = (NLint)(sizeof(NL_REPLY_STRING) + sizeof(newport));
NLint received;
NLbyte reply = (NLbyte)0;
received = recvfrom((SOCKET)sock->realsocket, (char *)buffer, (int)sizeof(buffer), 0,
(struct sockaddr *)&sock->addressin, &len);
if(received == SOCKET_ERROR)
{
if(sockerrno != (int)EWOULDBLOCK)
{
if(sock->blocking == NL_TRUE)
{
nlSetError(NL_CON_REFUSED);
}
else
{
sock->conerror = NL_TRUE;
}
return NL_FALSE;
}
}
if(received >= slen)
{
NLint count = 0;
/* retrieve the port number */
readShort(buffer, count, newport);
#ifdef NL_INCLUDE_IPX
if(sock->driver == NL_IPX)
{
((struct sockaddr_ipx *)&sock->addressin)->sa_socket = htons(newport);
}
else
#endif
{
((struct sockaddr_in *)&sock->addressin)->sin_port = htons(newport);
}
/* Lets check for the reply string */
pbuffer[slen - 1] = (NLbyte)0; /* null terminate for peace of mind */
pbuffer += sizeof(newport);
if(strcmp(pbuffer, NL_REPLY_STRING) == 0)
{
if(connect((SOCKET)sock->realsocket, (struct sockaddr *)&sock->addressin, len)
== SOCKET_ERROR)
{
if(sock->blocking == NL_TRUE)
{
nlSetError(NL_SYSTEM_ERROR);
}
else
{
sock->conerror = NL_TRUE;
}
return NL_FALSE;
}
/* send back a 0 length packet to the new port, needed for firewalls */
if(send((SOCKET)sock->realsocket, &reply, 0, 0) == SOCKET_ERROR)
{
if(sock->blocking == NL_TRUE)
{
nlSetError(NL_SYSTEM_ERROR);
}
else
{
sock->conerror = NL_TRUE;
}
return NL_FALSE;
}
/* success! */
#ifdef NL_INCLUDE_IPX
if(sock->driver == NL_IPX)
{
sock->localport = ipx_GetPort((SOCKET)sock->realsocket);
sock->remoteport = ipx_GetPortFromAddr((NLaddress *)&sock->addressin);
}
else
#endif
{
sock->localport = sock_GetPort((SOCKET)sock->realsocket);
sock->remoteport = sock_GetPortFromAddr((NLaddress *)&sock->addressin);
}
sock->connected = NL_TRUE;
sock->connecting = NL_FALSE;
return NL_TRUE;
}
}
htThreadSleep(NL_CONNECT_SLEEP);
}
if(sock->blocking == NL_TRUE)
{
nlSetError(NL_CON_REFUSED);
}
else
{
sock->conerror = NL_TRUE;
}
sock->connecting = NL_FALSE;
return NL_FALSE;
}
static void *sock_ConnectUDPAsynchInt(void /*@owned@*/*addr)
{
NLaddress_ex_t *address = (NLaddress_ex_t *)addr;
(void)sock_ConnectUDP(address->socket, address->address);
free(addr);
return NULL;
}
static NLboolean sock_ConnectUDPAsynch(NLsocket socket, const NLaddress *address)
{
NLaddress_ex_t /*@dependent@*/*addr;
nl_socket_t *sock = nlSockets[socket];
addr = (NLaddress_ex_t *)malloc(sizeof(NLaddress_ex_t));
if(addr == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
return NL_FALSE;
}
addr->address = (NLaddress *)address;
addr->socket = socket;
sock->connecting = NL_TRUE;
sock->conerror = NL_FALSE;
if(htThreadCreate(sock_ConnectUDPAsynchInt, (void *)addr, NL_FALSE) == (HThreadID)HT_INVALID)
{
return NL_FALSE;
}
return NL_TRUE;
}
static NLboolean sock_ConnectMulticast(NLsocket socket, const NLaddress *address)
{
struct ip_mreq mreq;
nl_socket_t *sock = nlSockets[socket];
if(sock->reliable == NL_TRUE)
{
nlSetError(NL_WRONG_TYPE);
return NL_FALSE;
}
if(!IN_MULTICAST(ntohl(((struct sockaddr_in *)address)->sin_addr.s_addr)))
{
nlSetError(NL_BAD_ADDR);
return NL_FALSE;
}
memcpy((char *)&sock->addressin, (char *)address, sizeof(NLaddress));
memcpy((char *)&sock->addressout, (char *)address, sizeof(NLaddress));
/* join the multicast group */
mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)address)->sin_addr.s_addr;
mreq.imr_interface.s_addr = bindaddress;
if(setsockopt((SOCKET)sock->realsocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char *)&mreq, (int)sizeof(mreq)) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
sock->localport = sock_GetPort((SOCKET)sock->realsocket);
sock->remoteport = sock_GetPortFromAddr((NLaddress *)&sock->addressout);
return sock_SetMulticastTTL(sock, multicastTTL);
}
NLboolean sock_Connect(NLsocket socket, const NLaddress *address)
{
nl_socket_t *sock = nlSockets[socket];
memcpy((char *)&sock->addressin, (char *)address, sizeof(NLaddress));
if(sock->connected == NL_TRUE)
{
nlSetError(NL_CONNECTED);
return NL_FALSE;
}
if(sock->connecting == NL_TRUE)
{
nlSetError(NL_CON_PENDING);
return NL_FALSE;
}
if(sock->type == NL_RELIABLE || sock->type == NL_RELIABLE_PACKETS)
{
socklen_t len = (socklen_t)sizeof(struct sockaddr_in);
#ifdef NL_INCLUDE_IPX
if(sock->driver == NL_IPX)
{
len = (socklen_t)sizeof(struct sockaddr_ipx);
if(connect((SOCKET)sock->realsocket, (struct sockaddr *)&sock->addressin, len)
== SOCKET_ERROR)
{
if(sock->blocking == NL_FALSE &&
(sockerrno == (int)EWOULDBLOCK || sockerrno == (int)EINPROGRESS))
{
sock->connecting = NL_TRUE;
}
else
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
sock->localport = ipx_GetPort((SOCKET)sock->realsocket);
sock->remoteport = ipx_GetPortFromAddr((NLaddress *)&sock->addressin);
}
else
#endif
{
if(sock_connect((SOCKET)sock->realsocket, (struct sockaddr *)&sock->addressin, len)
== SOCKET_ERROR)
{
if(sock->blocking == NL_FALSE &&
(sockerrno == (int)EWOULDBLOCK || sockerrno == (int)EINPROGRESS))
{
sock->connecting = NL_TRUE;
}
else
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
}
sock->localport = sock_GetPort((SOCKET)sock->realsocket);
sock->remoteport = sock_GetPortFromAddr((NLaddress *)&sock->addressin);
}
if(sock->connecting == NL_FALSE)
{
sock->connected = NL_TRUE;
}
return NL_TRUE;
}
else if(sock->type == NL_UDP_MULTICAST)
{
return sock_ConnectMulticast(socket, &sock->addressin);
}
else if(sock->type == NL_UNRELIABLE)
{
if(sock->blocking == NL_TRUE)
{
return sock_ConnectUDP(socket, &sock->addressin);
}
else
{
return sock_ConnectUDPAsynch(socket, &sock->addressin);
}
}
else
{
nlSetError(NL_WRONG_TYPE);
}
return NL_FALSE;
}
void sock_Close(NLsocket socket)
{
nl_socket_t *sock = nlSockets[socket];
struct ip_mreq mreq;
if(sock->type == NL_UDP_MULTICAST)
{
/* leave the multicast group */
mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)&sock->addressout)->sin_addr.s_addr;
mreq.imr_interface.s_addr = bindaddress;
(void)setsockopt((SOCKET)sock->realsocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(char *)&mreq, (int)sizeof(mreq));
}
if(sock->type == NL_RELIABLE_PACKETS)
{
/* check for unsent data */
if(sock->sendlen > 0)
{
int tries = 200;
/* 200 * 50 ms = up to a 10 second delay to allow data to be sent */
while(tries-- > 0 && sock->sendlen > 0)
{
htThreadSleep(50);
}
}
sock_DeleteSocket(socket);
}
if((sock->type == NL_RELIABLE_PACKETS || sock->type == NL_RELIABLE) && sock->listen == NL_FALSE)
{
struct linger l = {1, 1};
(void)setsockopt((SOCKET)sock->realsocket, SOL_SOCKET, SO_LINGER, (const char *)&l, (int)sizeof(l));
(void)shutdown((SOCKET)sock->realsocket, SD_RECEIVE);
}
else
{
(void)shutdown((SOCKET)sock->realsocket, SD_BOTH);
}
(void)closesocket((SOCKET)sock->realsocket);
}
/* internal function to read reliable packets from TCP stream */
static NLint sock_ReadPacket(NLsocket socket, NLvoid /*@out@*/ *buffer, NLint nbytes,
NLboolean checkonly)
{
nl_socket_t *sock = nlSockets[socket];
/* skip error reporting if checkonly is TRUE */
/* check for sync */
if(sock->packetsync == NL_FALSE)
{
if(checkonly == NL_FALSE)
{
nlSetError(NL_PACKET_SYNC);
}
else
{
sock->readable = NL_TRUE;
}
return NL_INVALID;
}
if(sock->message_end == NL_TRUE && checkonly == NL_FALSE && sock->reclen == 0)
{
sock->message_end = NL_FALSE;
nlSetError(NL_MESSAGE_END);
return NL_INVALID;
}
/* allocate some temp storage the first time through */
if(sock->inbuf == NULL)
{
sock->inbuflen = (nbytes + nbytes / 4 + NL_HEADER_LEN);
if(sock->inbuflen < 1024)
{
sock->inbuflen = 1024;
}
else if(sock->inbuflen > NL_MAX_PACKET_LENGTH + NL_MAX_PACKET_LENGTH/4)
{
sock->inbuflen = NL_MAX_PACKET_LENGTH + NL_MAX_PACKET_LENGTH/4;
}
sock->inbuf = (NLbyte *)malloc((size_t)sock->inbuflen);
if(sock->inbuf == NULL)
{
if(checkonly == NL_FALSE)
{
sock->inbuflen = 0;
nlSetError(NL_OUT_OF_MEMORY);
}
return NL_INVALID;
}
}
/* if inbuf is empty, get some data */
if(sock->reclen < NL_HEADER_LEN)
{
NLint count;
count = recv((SOCKET)sock->realsocket, (char *)(sock->inbuf + sock->reclen), (sock->inbuflen - sock->reclen), 0);
if(count == SOCKET_ERROR)
{
if(checkonly == NL_FALSE)
{
return sock_Error();
}
else
{
sock->readable = NL_TRUE;
return NL_INVALID;
}
}
if(count == 0)
{
if(checkonly == NL_FALSE)
{
nlSetError(NL_MESSAGE_END);
}
else
{
sock->message_end = NL_TRUE;
sock->readable = NL_TRUE;
}
return NL_INVALID;
}
sock->reclen += count;
}
/* start parsing the packet */
if(sock->reclen >= NL_HEADER_LEN)
{
NLboolean done = NL_FALSE;
NLushort len;
NLint c = 2;
/* check for valid packet */
if(sock->inbuf[0] != 'N' || sock->inbuf[1] != 'L')
{
/* packet is not valid, we are somehow out of sync,
or we are talking to a regular TCP stream */
if(checkonly == NL_FALSE)
{
nlSetError(NL_PACKET_SYNC);
}
else
{
sock->readable = NL_TRUE;
}
sock->packetsync = NL_FALSE;
return NL_INVALID;
}
/* read the length of the packet */
readShort(sock->inbuf, c, len);
if(len > NL_MAX_PACKET_LENGTH)
{
/* packet is not valid, or we are talking to a regular TCP stream */
if(checkonly == NL_FALSE)
{
nlSetError(NL_PACKET_SYNC);
}
else
{
sock->readable = NL_TRUE;
}
sock->packetsync = NL_FALSE;
return NL_INVALID;
}
/* check to see if we need to make the inbuf storage larger */
if((NLint)len > sock->inbuflen)
{
NLint newbuflen;
NLbyte *temp;
newbuflen = (len + len / 4 + NL_HEADER_LEN);
temp = (NLbyte *)realloc(sock->inbuf, (size_t)newbuflen);
if(temp == NULL)
{
if(checkonly == NL_FALSE)
{
nlSetError(NL_OUT_OF_MEMORY);
}
return NL_INVALID;
}
sock->inbuf = temp;
sock->inbuflen = newbuflen;
}
if(checkonly == NL_FALSE)
{
if(len > (NLushort)nbytes)
{
nlSetError(NL_BUFFER_SIZE);
return NL_INVALID;
}
}
/* see if we need to get more of the packet */
if(len > (NLushort)(sock->reclen - c))
{
done = NL_FALSE;
while(done == NL_FALSE)
{
NLint count;
if(checkonly == NL_FALSE)
{
count = recv((SOCKET)sock->realsocket,
(char *)(sock->inbuf + sock->reclen),
(sock->inbuflen - sock->reclen), 0);
}
else
{
/* we are calling this from PollGroup, so it cannot block */
fd_set fdset;
struct timeval t = {0,0};
FD_ZERO(&fdset);
FD_SET((SOCKET)sock->realsocket, &fdset);
if(select(sock->realsocket + 1, &fdset, NULL, NULL, &t) == 1)
{
count = recv((SOCKET)sock->realsocket,
(char *)(sock->inbuf + sock->reclen),
(sock->inbuflen - sock->reclen), 0);
}
else
{
/* socket would block, so break */
break;
}
}
if(count == SOCKET_ERROR)
{
if(checkonly == NL_FALSE)
{
/* check to see if we already have all the packet */
if(len <= (NLushort)(sock->reclen - c))
{
done = NL_TRUE;
}
else
{
/* report the error */
return sock_Error();
}
}
else
{
done = NL_TRUE;
}
}
else if(count == 0)
{
sock->message_end = NL_TRUE;
sock->readable = NL_TRUE;
done = NL_TRUE;
}
else
{
sock->reclen += count;
if(len <= (NLushort)(sock->reclen - c))
{
done = NL_TRUE;
}
}
}
}
/* see if we now have all of the packet */
if(len <= (NLushort)(sock->reclen - c))
{
sock->readable = NL_TRUE;
if(checkonly == NL_FALSE)
{
/* copy the packet */
memcpy(buffer, (sock->inbuf + c), (size_t)len);
/* check for another packet */
sock->reclen -= (len + c);
if(sock->reclen > 0)
{
/* move it down to the beginning of inbuf */
memmove(sock->inbuf, (sock->inbuf + c + len), (size_t)sock->reclen);
}
/* quick check to see if we have another complete packet buffered */
if(sock->reclen >= NL_HEADER_LEN)
{
NLushort templen;
/* read the length of the packet */
c = 2;
readShort(sock->inbuf, c, templen);
/* check the length */
if(templen <= (NLushort)(sock->reclen - c))
{
/* we have another complete packet, so mark as readable for PollGroup */
sock->readable = NL_TRUE;
}
else
{
sock->readable = NL_FALSE;
}
}
else
{
sock->readable = NL_FALSE;
}
return (NLint)len;
}
}
else
{
return 0;
}
}
return 0;
}
NLint sock_Read(NLsocket socket, NLvoid *buffer, NLint nbytes)
{
nl_socket_t *sock = nlSockets[socket];
NLint count;
if(nbytes < 0)
{
return 0;
}
if(sock->type == NL_RELIABLE || sock->type == NL_RELIABLE_PACKETS) /* TCP */
{
/* check for a non-blocking connection pending */
if(sock->connecting == NL_TRUE)
{
fd_set fdset;
struct timeval t = {0,0};
int serrval = -1;
socklen_t serrsize = (socklen_t)sizeof(serrval);
FD_ZERO(&fdset);
FD_SET((SOCKET)sock->realsocket, &fdset);
if(select(sock->realsocket + 1, NULL, &fdset, NULL, &t) == 1)
{
/* Check the socket status */
(void)getsockopt((SOCKET)sock->realsocket, SOL_SOCKET, SO_ERROR, (char *)&serrval, &serrsize );
if(serrval != 0)
{
if(serrval == (int)ECONNREFUSED)
{
nlSetError(NL_CON_REFUSED);
}
else if(serrval == (int)EINPROGRESS || serrval == (int)EWOULDBLOCK)
{
nlSetError(NL_CON_PENDING);
}
return NL_INVALID;
}
/* the connect has completed */
sock->connected = NL_TRUE;
sock->connecting = NL_FALSE;
}
else
{
/* check for a failed connect */
FD_ZERO(&fdset);
FD_SET((SOCKET)sock->realsocket, &fdset);
if(select(sock->realsocket + 1, NULL, NULL, &fdset, &t) == 1)
{
nlSetError(NL_CON_REFUSED);
}
else
{
nlSetError(NL_CON_PENDING);
}
return NL_INVALID;
}
}
/* check for reliable packets */
if(sock->type == NL_RELIABLE_PACKETS)
{
return sock_ReadPacket(socket, buffer, nbytes, NL_FALSE);
}
count = recv((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0);
if(count == 0)
{
/* end of message */
nlSetError(NL_MESSAGE_END);
return NL_INVALID;
}
}
else /* UDP */
{
/* check for a non-blocking connection pending */
if(sock->connecting == NL_TRUE)
{
nlSetError(NL_CON_PENDING);
return NL_INVALID;
}
/* check for a connection error */
if(sock->conerror == NL_TRUE)
{
nlSetError(NL_CON_REFUSED);
return NL_INVALID;
}
if(sock->connected == NL_TRUE)
{
count = recv((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0);
}
else
{
socklen_t len = (socklen_t)sizeof(struct sockaddr_in);
count = recvfrom((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0,
(struct sockaddr *)&sock->addressin, &len);
}
}
if(count == SOCKET_ERROR)
{
return sock_Error();
}
return count;
}
static NLboolean allocateBuffer(nl_socket_t *sock, NLint nbytes)
{
NLint size = NLMIN(NLMAX((nbytes + NL_HEADER_LEN) * 2, 1024), (NL_MAX_PACKET_LENGTH + NL_HEADER_LEN));
/* first call */
if(sock->outbuf == NULL)
{
sock->outbuf = (NLbyte *)malloc((size_t)size);
if(sock->outbuf == NULL)
{
sock->outbuflen = 0;
nlSetError(NL_OUT_OF_MEMORY);
return NL_FALSE;
}
sock->outbuflen = size;
}
else
{
if(size > sock->outbuflen)
{
NLbyte *temp;
temp = (NLbyte *)realloc(sock->outbuf, (size_t)size);
if(temp == NULL)
{
sock->outbuflen = 0;
nlSetError(NL_OUT_OF_MEMORY);
return NL_FALSE;
}
sock->outbuf = temp;
sock->outbuflen = size;
}
}
return NL_TRUE;
}
static NLint sock_WritePacket(NLsocket socket, const NLvoid *buffer, NLint nbytes)
{
nl_socket_t *sock = nlSockets[socket];
NLint count;
NLbyte temp[NL_HEADER_LEN];
NLint c = 0;
/* allocate memory for outbuf */
if(sock->outbuf == NULL)
{
if(allocateBuffer(sock, nbytes) == NL_FALSE)
{
return NL_INVALID;
}
}
else
{
/* send any unsent data from last packet */
sock_WritePacketCheckPending(socket);
}
/* check to see if we already have some pending data */
if(sock->sendlen > 0)
{
/* to comply with the way UDP packets act */
/* if the send buffer has unsent data return 0 */
return 0;
}
/* ID for packets is 'NL'*/
writeByte(temp, c, 'N');
writeByte(temp, c, 'L');
/* add the packet length */
writeShort(temp, c, (NLushort)nbytes);
count = send((SOCKET)sock->realsocket, (char *)temp, c, 0);
if(count == SOCKET_ERROR)
{
if(sockerrno == (int)EWOULDBLOCK)
{
count = 0;
}
else
{
return sock_Error();
}
}
if(count < c)
{
int dif = c - count;
/* check outbuf size */
if(allocateBuffer(sock, nbytes) == NL_FALSE)
{
return NL_INVALID;
}
/* store it */
memcpy((sock->outbuf + sock->sendlen), (temp + count), (size_t)(dif));
sock->sendlen += (dif);
memcpy((sock->outbuf + sock->sendlen), ((NLbyte *)buffer), (size_t)(nbytes));
sock->sendlen += (nbytes);
rpBufferedCount++;
}
else
{
count = send((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0);
if(count == SOCKET_ERROR)
{
if(sockerrno == (int)EWOULDBLOCK)
{
count = 0;
}
else
{
return sock_Error();
}
}
/* make sure all was sent */
if(count < nbytes)
{
int dif = nbytes - count;
/* check outbuf size */
if(allocateBuffer(sock, nbytes) == NL_FALSE)
{
return NL_INVALID;
}
/* store it */
memcpy((sock->outbuf + sock->sendlen), ((NLbyte *)buffer + count), (size_t)(dif));
sock->sendlen += dif;
rpBufferedCount++;
}
}
count = nbytes;
return count;
}
NLint sock_Write(NLsocket socket, const NLvoid *buffer, NLint nbytes)
{
nl_socket_t *sock = nlSockets[socket];
NLint count;
if(nbytes < 0)
{
return 0;
}
if((sock->type == NL_RELIABLE) || (sock->type == NL_RELIABLE_PACKETS)) /* TCP */
{
if(sock->connecting == NL_TRUE)
{
fd_set fdset;
struct timeval t = {0,0};
int serrval = -1;
socklen_t serrsize = (socklen_t)sizeof(serrval);
FD_ZERO(&fdset);
FD_SET((SOCKET)sock->realsocket, &fdset);
if(select(sock->realsocket + 1, NULL, &fdset, NULL, &t) == 1)
{
/* Check the socket status */
(void)getsockopt((SOCKET)sock->realsocket, SOL_SOCKET, SO_ERROR, (char *)&serrval, &serrsize );
if(serrval != 0)
{
if(serrval == (int)ECONNREFUSED)
{
nlSetError(NL_CON_REFUSED);
}
else if(serrval == (int)EINPROGRESS || serrval == (int)EWOULDBLOCK)
{
nlSetError(NL_CON_PENDING);
}
return NL_INVALID;
}
/* the connect has completed */
sock->connected = NL_TRUE;
sock->connecting = NL_FALSE;
}
else
{
/* check for a failed connect */
FD_ZERO(&fdset);
FD_SET((SOCKET)sock->realsocket, &fdset);
if(select(sock->realsocket + 1, NULL, NULL, &fdset, &t) == 1)
{
nlSetError(NL_CON_REFUSED);
}
else
{
nlSetError(NL_CON_PENDING);
}
return NL_INVALID;
}
}
/* check for reliable packets */
if(sock->type == NL_RELIABLE_PACKETS)
{
if(nbytes > NL_MAX_PACKET_LENGTH)
{
nlSetError(NL_PACKET_SIZE);
return NL_INVALID;
}
return sock_WritePacket(socket, buffer, nbytes);
}
count = send((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0);
}
else /* unconnected UDP */
{
int maxpacket = NL_MAX_PACKET_LENGTH;
int sizesockaddr = (int)sizeof(struct sockaddr_in);
/* check for a non-blocking connection pending */
if(sock->connecting == NL_TRUE)
{
nlSetError(NL_CON_PENDING);
return NL_INVALID;
}
/* check for a connection error */
if(sock->conerror == NL_TRUE)
{
nlSetError(NL_CON_REFUSED);
return NL_INVALID;
}
#ifdef NL_INCLUDE_IPX
if(sock->driver == NL_IPX)
{
maxpacket = 1466;
sizesockaddr = (int)sizeof(struct sockaddr_ipx);
}
#endif
if(nbytes > maxpacket)
{
nlSetError(NL_PACKET_SIZE);
return NL_INVALID;
}
if(sock->type == NL_UDP_MULTICAST)
{
count = sendto((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0,
(struct sockaddr *)&sock->addressout,
(int)sizeof(struct sockaddr_in));
}
else if(sock->connected == NL_TRUE)
{
count = send((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0);
}
else
{
count = sendto((SOCKET)sock->realsocket, (char *)buffer, nbytes, 0,
(struct sockaddr *)&sock->addressout, sizesockaddr);
}
}
if(count == SOCKET_ERROR)
{
return sock_Error();
}
return count;
}
NLchar *sock_AddrToString(const NLaddress *address, NLchar *string)
{
NLulong addr;
NLushort port;
addr = ntohl(((struct sockaddr_in *)address)->sin_addr.s_addr);
port = ntohs(((struct sockaddr_in *)address)->sin_port);
if(port == 0)
{
_stprintf(string, TEXT("%lu.%lu.%lu.%lu"), (addr >> 24) & 0xff, (addr >> 16)
& 0xff, (addr >> 8) & 0xff, addr & 0xff);
}
else
{
_stprintf(string, TEXT("%lu.%lu.%lu.%lu:%u"), (addr >> 24) & 0xff, (addr >> 16)
& 0xff, (addr >> 8) & 0xff, addr & 0xff, port);
}
return string;
}
NLboolean sock_StringToAddr(const NLchar *string, NLaddress *address)
{
NLulong a1, a2, a3, a4;
NLulong ipaddress, port = 0;
int ret;
ret = _stscanf((const NLchar *)string, (const NLchar *)TEXT("%lu.%lu.%lu.%lu:%lu"), &a1, &a2, &a3, &a4, &port);
if(a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255 || port > 65535 || ret < 4)
{
/* bad address */
((struct sockaddr_in *)address)->sin_family = AF_INET;
((struct sockaddr_in *)address)->sin_addr.s_addr = INADDR_NONE;
((struct sockaddr_in *)address)->sin_port = 0;
nlSetError(NL_BAD_ADDR);
address->valid = NL_FALSE;
return NL_FALSE;
}
else
{
ipaddress = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;
((struct sockaddr_in *)address)->sin_family = AF_INET;
((struct sockaddr_in *)address)->sin_addr.s_addr = htonl(ipaddress);
((struct sockaddr_in *)address)->sin_port = htons((NLushort)port);
address->valid = NL_TRUE;
return NL_TRUE;
}
}
NLboolean sock_GetLocalAddr(NLsocket socket, NLaddress *address)
{
nl_socket_t *sock = nlSockets[socket];
socklen_t len;
memset(address, 0, sizeof(NLaddress));
((struct sockaddr_in *)address)->sin_family = AF_INET;
address->valid = NL_TRUE;
len = (socklen_t)sizeof(struct sockaddr_in);
/* if the socket is connected, this will get us
the correct address on a multihomed system*/
if(getsockname((SOCKET)sock->realsocket, (struct sockaddr *)address, &len) == SOCKET_ERROR)
{
/* ignore error if socket has not been bound or connected yet */
if(sockerrno != (int)EINVAL)
{
nlSetError(NL_SYSTEM_ERROR);
address->valid = NL_FALSE;
return NL_FALSE;
}
}
/* if not connected, substitute the NIC address */
if(((struct sockaddr_in *)address)->sin_addr.s_addr == INADDR_ANY)
{
((struct sockaddr_in *)address)->sin_addr.s_addr = ouraddress;
}
sock_SetAddrPort(address, sock->localport);
return NL_TRUE;
}
NLaddress *sock_GetAllLocalAddr(NLint *count)
{
struct hostent *local;
char buff[MAXHOSTNAMELEN];
int i = 0;
if(gethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR)
{
nlSetError(NL_SYSTEM_ERROR);
return NULL;
}
buff[MAXHOSTNAMELEN - 1] = '\0';
local = gethostbyname(buff);
if(local == NULL)
{
if(sockerrno == (int)ENETDOWN)
{
nlSetError(NL_SYSTEM_ERROR);
return NULL;
}
}
/* count the number of returned IP addresses */
*count = 0;
if(local != NULL)
{
while(local->h_addr_list[i++] != NULL)
{
(*count)++;
}
}
/* allocate storage for address */
if(alladdr != NULL)
{
free(alladdr);
}
if(*count == 0)
{
*count = 1;
alladdr = (NLaddress *)malloc(sizeof(NLaddress));
memset(alladdr, 0, sizeof(NLaddress));
/* fill in the localhost address */
((struct sockaddr_in *)alladdr)->sin_family = AF_INET;
((struct sockaddr_in *)alladdr)->sin_addr.s_addr = (NLuint)htonl(0x7f000001);
alladdr->valid = NL_TRUE;
}
else
{
alladdr = (NLaddress *)malloc(sizeof(NLaddress) * *count);
memset(alladdr, 0, sizeof(NLaddress) * *count);
/* fill in the addresses */
i = 0;
while(local->h_addr_list[i] != NULL)
{
NLaddress *addr = &alladdr[i];
((struct sockaddr_in *)addr)->sin_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = *(NLuint *)local->h_addr_list[i];
addr->valid = NL_TRUE;
i++;
}
}
return alladdr;
}
NLboolean sock_SetLocalAddr(const NLaddress *address)
{
/* should we check against all the local addresses? */
bindaddress = ouraddress = (NLuint)((struct sockaddr_in *)address)->sin_addr.s_addr;
return NL_TRUE;
}
NLchar *sock_GetNameFromAddr(const NLaddress *address, NLchar *name)
{
struct hostent *hostentry;
NLchar tempname[MAXHOSTNAMELEN];
hostentry = gethostbyaddr((char *)&((struct sockaddr_in *)address)->sin_addr,
(int)sizeof(struct in_addr), AF_INET);
if(hostentry != NULL)
{
NLushort port = sock_GetPortFromAddr(address);
#ifdef _UNICODE
NLchar temp[MAXHOSTNAMELEN];
/* convert from multibyte char string to wide char string */
mbstowcs(temp, (const char *)hostentry->h_name, MAXHOSTNAMELEN);
temp[MAXHOSTNAMELEN - 1] = '\0';
#else
NLchar *temp = (NLchar *)hostentry->h_name;
#endif
if(port != 0)
{
_sntprintf(tempname, (size_t)(NL_MAX_STRING_LENGTH), (const NLchar *)TEXT("%s:%hu"), (const NLchar *)temp, port);
}
else
{
_tcsncpy(tempname, (const NLchar *)temp, (size_t)(NL_MAX_STRING_LENGTH));
}
tempname[NL_MAX_STRING_LENGTH - 1] = (NLchar)'\0';
}
else
{
if(((struct sockaddr_in *)address)->sin_addr.s_addr == (unsigned long)INADDR_NONE)
{
_tcsncpy(tempname, (const NLchar *)TEXT("Bad address"), (size_t)(NL_MAX_STRING_LENGTH));
}
else
{
(void)sock_AddrToString(address, tempname);
}
}
/* special copy in case this was called as sock_GetNameFromAddrAsync */
name[0] = (NLchar)'\0';
_tcsncpy(&name[1], (const NLchar *)&tempname[1], (size_t)(NL_MAX_STRING_LENGTH - 1));
name[0] = tempname[0];
return name;
}
static void *sock_GetNameFromAddrAsyncInt(void /*@owned@*/ * addr)
{
NLaddress_ex_t *address = (NLaddress_ex_t *)addr;
(void)sock_GetNameFromAddr(address->address, address->name);
free(address->address);
free(address);
return NULL;
}
NLboolean sock_GetNameFromAddrAsync(const NLaddress *address, NLchar *name)
{
NLaddress_ex_t *addr;
memset(name, 0, sizeof(NLchar) * NL_MAX_STRING_LENGTH);
addr = (NLaddress_ex_t *)malloc(sizeof(NLaddress_ex_t));
if(addr == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
return NL_FALSE;
}
addr->address = (NLaddress *)malloc(sizeof(NLaddress));
if(addr->address == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
free(addr);
return NL_FALSE;
}
memcpy(addr->address, address, sizeof(NLaddress));
addr->name = name;
if(htThreadCreate(sock_GetNameFromAddrAsyncInt, (void *)addr, NL_FALSE) == (HThreadID)HT_INVALID)
{
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean sock_GetAddrFromName(const NLchar *name, NLaddress *address)
{
struct hostent *hostentry;
NLushort port = 0;
int pos;
NLbyte temp[NL_MAX_STRING_LENGTH];
address->valid = NL_FALSE;
/* first check to see if we have a numeric address already */
(void)sock_StringToAddr(name, address);
/* clear out an NL_BAD_ADDR error */
if(nlGetError() == NL_BAD_ADDR)
{
nlSetError(NL_NO_ERROR);
}
if(((struct sockaddr_in *)address)->sin_addr.s_addr != (unsigned long)INADDR_NONE)
{
/* we are already done! */
address->valid = NL_TRUE;
return NL_TRUE;
}
#ifdef _UNICODE
/* convert from wide char string to multibyte char string */
(void)wcstombs(temp, (const NLchar *)name, NL_MAX_STRING_LENGTH);
#else
strncpy(temp, name, NL_MAX_STRING_LENGTH);
#endif
temp[NL_MAX_STRING_LENGTH - 1] = (NLbyte)'\0';
pos = (int)strcspn(temp, (const char *)":");
if(pos > 0)
{
NLbyte *p = &temp[pos+1];
temp[pos] = (NLbyte)'\0';
(void)sscanf(p, "%hu", &port);
}
hostentry = gethostbyname((const char *)temp);
if(hostentry != NULL)
{
((struct sockaddr_in *)address)->sin_family = AF_INET;
((struct sockaddr_in *)address)->sin_port = htons(port);
((struct sockaddr_in *)address)->sin_addr.s_addr = *(NLulong *)hostentry->h_addr_list[0];
address->valid = NL_TRUE;
}
else
{
((struct sockaddr_in *)address)->sin_family = AF_INET;
((struct sockaddr_in *)address)->sin_addr.s_addr = INADDR_NONE;
((struct sockaddr_in *)address)->sin_port = 0;
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
return NL_TRUE;
}
static void *sock_GetAddrFromNameAsyncInt(void /*@owned@*/ *addr)
{
NLaddress_ex_t *address = (NLaddress_ex_t *)addr;
(void)sock_GetAddrFromName(address->name, address->address);
address->address->valid = NL_TRUE;
free(address->name);
free(address);
return NULL;
}
NLboolean sock_GetAddrFromNameAsync(const NLchar *name, NLaddress *address)
{
NLaddress_ex_t *addr;
address->valid = NL_FALSE;
addr = (NLaddress_ex_t *)malloc(sizeof(NLaddress_ex_t));
if(addr == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
return NL_FALSE;
}
addr->name = (NLchar *)malloc(NL_MAX_STRING_LENGTH);
if(addr->name == NULL)
{
nlSetError(NL_OUT_OF_MEMORY);
free(addr);
return NL_FALSE;
}
_tcsncpy(addr->name, name, (size_t)NL_MAX_STRING_LENGTH);
addr->name[NL_MAX_STRING_LENGTH - 1] = '\0';
addr->address = address;
if(htThreadCreate(sock_GetAddrFromNameAsyncInt, (void *)addr, NL_FALSE) == (HThreadID)HT_INVALID)
{
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean sock_AddrCompare(const NLaddress *address1, const NLaddress *address2)
{
if(((struct sockaddr_in *)address1)->sin_family != ((struct sockaddr_in *)address2)->sin_family)
return NL_FALSE;
if(((struct sockaddr_in *)address1)->sin_addr.s_addr
!= ((struct sockaddr_in *)address2)->sin_addr.s_addr)
return NL_FALSE;
if(((struct sockaddr_in *)address1)->sin_port
!= ((struct sockaddr_in *)address2)->sin_port)
return NL_FALSE;
return NL_TRUE;
}
NLushort sock_GetPortFromAddr(const NLaddress *address)
{
return ntohs(((struct sockaddr_in *)address)->sin_port);
}
void sock_SetAddrPort(NLaddress *address, NLushort port)
{
((struct sockaddr_in *)address)->sin_port = htons((NLushort)port);
}
NLint sock_GetSystemError(void)
{
NLint err = sockerrno;
#ifdef HL_WINDOWS_APP
if(err < WSABASEERR)
{
if(errno > 0)
{
err = errno;
}
}
#endif
return err;
}
NLint sock_PollGroup(NLint group, NLenum name, NLsocket *sockets, NLint number, NLint timeout)
{
NLint numselect, count = 0;
NLint numsockets = NL_MAX_GROUP_SOCKETS;
NLsocket temp[NL_MAX_GROUP_SOCKETS];
NLboolean reliable[NL_MAX_GROUP_SOCKETS];
NLboolean result;
NLsocket *ptemp = temp;
int i, found = 0;
fd_set fdset;
SOCKET highest;
struct timeval t = {0,0}; /* {seconds, useconds}*/
struct timeval *tp = &t;
nlGroupLock();
highest = nlGroupGetFdset(group, &fdset);
if(highest == INVALID_SOCKET)
{
/* error is set by nlGroupGetFdset */
nlGroupUnlock();
return NL_INVALID;
}
result = nlGroupGetSocketsINT(group, ptemp, &numsockets);
nlGroupUnlock();
if(result == NL_FALSE)
{
/* any error is set by nlGroupGetSockets */
return NL_INVALID;
}
if(numsockets == 0)
{
return 0;
}
if(name == NL_READ_STATUS)
{
/* check for buffered reliable packets */
for(i=0;i<numsockets;i++)
{
nl_socket_t *s = nlSockets[ptemp[i]];
if(s->type == NL_RELIABLE_PACKETS && s->readable == NL_TRUE)
{
/* mark as readable */
reliable[i] = NL_TRUE;
found++;
/* change the timeout to 0, or non-blocking since we */
/* have at least one reliable packet to read */
timeout = 0;
}
else
{
reliable[i] = NL_FALSE;
}
}
}
/* check for full blocking call */
if(timeout < 0)
{
tp = NULL;
}
else /* set t values */
{
t.tv_sec = timeout/1000;
t.tv_usec = (timeout%1000) * 1000;
}
/* call select to check the status */
switch(name) {
case NL_READ_STATUS:
numselect = select((int)highest, &fdset, NULL, NULL, tp);
break;
case NL_WRITE_STATUS:
numselect = select((int)highest, NULL, &fdset, NULL, tp);
break;
case NL_ERROR_STATUS:
numselect = select((int)highest, NULL, NULL, &fdset, tp);
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
if(numselect == SOCKET_ERROR)
{
if(sockerrno == (int)ENOTSOCK)
{
/* one of the sockets has been closed */
nlSetError(NL_INVALID_SOCKET);
}
else if(sockerrno == (int)EINTR)
{
/* select was interrupted by the system, maybe because the app is exiting */
return 0;
}
else
{
nlSetError(NL_SYSTEM_ERROR);
}
return NL_INVALID;
}
if(numselect > number)
{
nlSetError(NL_BUFFER_SIZE);
return NL_INVALID;
}
/* fill *sockets with a list of the sockets ready to be read */
numselect += found;
i = 0;
while(numsockets-- > 0 && numselect > count)
{
nl_socket_t *s = nlSockets[*ptemp];
if((reliable[i] == NL_TRUE ) || (FD_ISSET(s->realsocket, &fdset) != 0))
{
/* if checking for read status, must check for a complete packet */
if(s->type == NL_RELIABLE_PACKETS && s->listen == NL_FALSE && name == NL_READ_STATUS)
{
(void)nlLockSocket(*ptemp, NL_READ);
if(s->readable != NL_TRUE)
{
if(s->inuse == NL_TRUE)
{
(void)sock_ReadPacket(*ptemp, NULL, 0, NL_TRUE);
}
else
{
s->readable = NL_FALSE;
}
}
if(s->readable == NL_TRUE)
{
/* we do have a complete packet */
*sockets = *ptemp;
sockets++;
count++;
}
nlUnlockSocket(*ptemp, NL_READ);
}
else
{
*sockets = *ptemp;
sockets++;
count ++;
}
}
i++;
ptemp++;
}
return count;
}
NLboolean sock_PollSocket(NLsocket socket, NLenum name, NLint timeout)
{
NLint numselect;
nl_socket_t *sock = nlSockets[socket];
fd_set fdset;
struct timeval t = {0,0}; /* {seconds, useconds}*/
struct timeval *tp = &t;
nlSetError(NL_NO_ERROR);
if(name == NL_READ_STATUS)
{
/* check for buffered reliable packets */
nl_socket_t *s = nlSockets[socket];
if(s->type == NL_TCP_PACKETS && s->readable == NL_TRUE)
{
return NL_TRUE;
}
}
/* check for full blocking call */
if(timeout < 0)
{
tp = NULL;
}
else /* set t values */
{
t.tv_sec = timeout/1000;
t.tv_usec = (timeout%1000) * 1000;
}
FD_ZERO(&fdset);
FD_SET((SOCKET)(sock->realsocket), &fdset);
/* call select to check the status */
switch(name) {
case NL_READ_STATUS:
numselect = select((int)(sock->realsocket + 1), &fdset, NULL, NULL, tp);
break;
case NL_WRITE_STATUS:
numselect = select((int)(sock->realsocket + 1), NULL, &fdset, NULL, tp);
break;
case NL_ERROR_STATUS:
numselect = select((int)(sock->realsocket + 1), NULL, NULL, &fdset, tp);
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
if(numselect == SOCKET_ERROR)
{
if(sockerrno == (int)ENOTSOCK)
{
/* the socket has been closed */
nlSetError(NL_INVALID_SOCKET);
}
else if(sockerrno == (int)EINTR)
{
/* select was interrupted by the system, maybe because the app is exiting */
return NL_FALSE;
}
else
{
nlSetError(NL_SYSTEM_ERROR);
}
}
else if(numselect == 1)
{
return NL_TRUE;
}
return NL_FALSE;
}
NLboolean sock_Hint(NLenum name, NLint arg)
{
switch(name) {
case NL_LISTEN_BACKLOG:
backlog = arg;
break;
case NL_MULTICAST_TTL:
if(arg < 1)
{
arg = 1;
}
else if(arg > 255)
{
arg = 255;
}
multicastTTL = arg;
break;
case NL_REUSE_ADDRESS:
reuseaddress = (NLboolean)(arg != 0 ? NL_TRUE : NL_FALSE);
break;
case NL_TCP_NO_DELAY:
nlTCPNoDelay = (NLboolean)(arg != 0 ? NL_TRUE : NL_FALSE);
break;
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
NLboolean sock_SetSocketOpt(NLsocket socket, NLenum name, NLint arg)
{
nl_socket_t *sock = nlSockets[socket];
switch (name) {
case NL_BLOCKING_IO:
sock->blocking = (NLboolean)(arg != 0 ? NL_TRUE : NL_FALSE);
if(sock_SetBlocking((SOCKET)sock->realsocket, sock->blocking) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
break;
case NL_MULTICAST_TTL:
if(sock->type == NL_UDP_MULTICAST)
{
return(sock_SetMulticastTTL(sock, multicastTTL));
}
else
{
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
case NL_REUSE_ADDRESS:
if(sock_SetReuseAddr(sock) == NL_FALSE)
{
nlSetError(NL_SYSTEM_ERROR);
return NL_FALSE;
}
break;
case NL_TCP_NO_DELAY:
return (sock_SetTCPNoDelay(sock, (NLboolean)(arg != 0 ? NL_TRUE : NL_FALSE)));
default:
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
return NL_TRUE;
}
NLint sock_GetSocketOpt(NLsocket socket, NLenum name)
{
nl_socket_t *sock = nlSockets[socket];
switch (name) {
case NL_BLOCKING_IO:
return (NLint)sock->blocking;
case NL_MULTICAST_TTL:
if(sock->type == NL_UDP_MULTICAST)
{
return sock->TTL;
}
else
{
nlSetError(NL_INVALID_ENUM);
return NL_FALSE;
}
case NL_REUSE_ADDRESS:
return (NLint)sock->reuseaddr;
case NL_TCP_NO_DELAY:
return (NLint)sock->TCPNoDelay;
default:
nlSetError(NL_INVALID_ENUM);
return NL_INVALID;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:37 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68809
Default Alt Text
(236 KB)

Event Timeline