Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126440
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
236 KB
Referenced Files
None
Subscribers
None
View Options
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(¤tcount);
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
Details
Attached
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)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline