You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/12/01 07:04:00 UTC

svn commit: r350181 [189/198] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/ depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/ depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/ depends/oss/win....

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/win.IA32/port/hysock.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/win.IA32/port/hysock.c?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/win.IA32/port/hysock.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/win.IA32/port/hysock.c Wed Nov 30 21:29:27 2005
@@ -0,0 +1,5056 @@
+/* Copyright 1991, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CDEV_CURRENT_FUNCTION _comment_
+/**
+ * @file
+ * @ingroup Port
+ * @brief Sockets
+ */
+#undef CDEV_CURRENT_FUNCTION
+
+#include "hysock.h"
+#include "portpriv.h"
+#include "hyportptb.h"
+#include <Iphlpapi.h>
+
+typedef DWORD (WINAPI * GetAdaptersAddressesFunctionAddress) (ULONG, DWORD,
+							      PVOID,
+							      PIP_ADAPTER_ADDRESSES,
+							      PULONG);
+
+#include <limits.h>
+
+#define VALIDATE_ALLOCATIONS 1
+
+#define LOOP_BACK_NAME            "loopback"
+#define LOOP_BACK_DISPLAY_NAME    "loopback interface"
+#define LOOP_BACK_IPV4_ADDRESS    "127.0.0.1"
+#define LOOP_BACK_NUM_ADDRESSES   1
+
+typedef struct selectFDSet_struct
+{
+  int nfds;
+  OSSOCKET sock;
+  fd_set writeSet;
+  fd_set readSet;
+  fd_set exceptionSet;
+} selectFDSet_strut;
+
+#define CDEV_CURRENT_FUNCTION _prototypes_private
+
+I_32 platformSocketOption (I_32 portableSocketOption);
+
+static void VMCALL initializeSocketStructure (hysocket_t sockHandle,
+					      OSSOCKET sock,
+					      BOOL useIPv4Socket);
+
+void VMCALL updateSocketState (hysocket_t socket, BOOL useIPv4Socket);
+
+I_32 platformSocketLevel (I_32 portableSocketLevel);
+
+static I_32 ensureConnected (void);
+
+static I_32 findError (I_32 errorCode);
+
+I_32 map_protocol_family_Hy_to_OS (I_32 addr_family);
+
+BOOL VMCALL isAnyAddress (hysockaddr_t addr);
+
+I_32 map_addr_family_Hy_to_OS (I_32 addr_family);
+
+I_32 map_sockettype_Hy_to_OS (I_32 socket_type);
+
+int VMCALL internalCloseSocket (struct HyPortLibrary *portLibrary,
+				hysocket_t sockHandle, BOOL closeIPv4Socket);
+
+BOOL VMCALL useIPv4Socket (hysocket_t sockHandle);
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION ensureConnected
+static I_32
+ensureConnected (void)
+{
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION findError
+/**
+ * @internal
+ * Determines the proper portable error code to return given a native error code
+ *
+ * @param[in] errorCode The error code reported by the OS
+ *
+ * @return	the (negative) portable error code
+ */
+static I_32
+findError (I_32 errorCode)
+{
+  switch (errorCode)
+    {
+    case WSANOTINITIALISED:
+      return HYPORT_ERROR_SOCKET_NOTINITIALIZED;
+    case WSAENOPROTOOPT:
+      return HYPORT_ERROR_SOCKET_OPTUNSUPP;
+    case WSAEINTR:
+      return HYPORT_ERROR_SOCKET_INTERRUPTED;
+    case WSAENOTCONN:
+      return HYPORT_ERROR_SOCKET_NOTCONNECTED;
+    case WSAEWOULDBLOCK:
+      return HYPORT_ERROR_SOCKET_WOULDBLOCK;
+    case WSAECONNABORTED:
+      return HYPORT_ERROR_SOCKET_TIMEOUT;
+    case WSAECONNRESET:
+      return HYPORT_ERROR_SOCKET_CONNRESET;
+    case WSAENOBUFS:
+      return HYPORT_ERROR_SOCKET_NOBUFFERS;
+    case WSAEADDRINUSE:
+      return HYPORT_ERROR_SOCKET_ADDRINUSE;
+    case WSANO_DATA:
+      return HYPORT_ERROR_SOCKET_NODATA;
+    case WSAEOPNOTSUPP:
+      return HYPORT_ERROR_SOCKET_OPNOTSUPP;
+    case WSAEISCONN:
+      return HYPORT_ERROR_SOCKET_ISCONNECTED;
+    case WSAHOST_NOT_FOUND:
+      return HYPORT_ERROR_SOCKET_HOSTNOTFOUND;
+    case WSAEADDRNOTAVAIL:
+      return HYPORT_ERROR_SOCKET_ADDRNOTAVAIL;
+    case WSAEFAULT:
+      return HYPORT_ERROR_SOCKET_OPTARGSINVALID;
+    case WSAENOTSOCK:
+      return HYPORT_ERROR_SOCKET_NOTSOCK;
+    case WSAECONNREFUSED:
+      return HYPORT_ERROR_SOCKET_CONNECTION_REFUSED;
+    case WSAEACCES:
+      return HYPORT_ERROR_SOCKET_EACCES;
+    default:
+      return HYPORT_ERROR_SOCKET_OPFAILED;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION internalCloseSocket
+/**
+ * @internal updates the socketHandle by putting the socket in either the ipv4 or ipv6 slot
+ */
+int VMCALL
+internalCloseSocket (struct HyPortLibrary *portLibrary, hysocket_t sockHandle,
+		     BOOL closeIPv4Socket)
+{
+  U_8 mask1 = SOCKET_USE_IPV4_MASK;
+  int rc = 0;
+
+  if (closeIPv4Socket)
+    {
+      if (sockHandle->flags & SOCKET_IPV4_OPEN_MASK)
+	{
+	  /* Don't bother to check the error -- not like we can do anything about it. */
+	  shutdown (sockHandle->ipv4, 1);
+
+	  if (closesocket (sockHandle->ipv4) == SOCKET_ERROR)
+	    {
+	      rc = WSAGetLastError ();
+	      HYSOCKDEBUG ("<closesocket failed, err=%d>\n", rc);
+	      switch (rc)
+		{
+		case WSAEWOULDBLOCK:
+		  rc =
+		    portLibrary->error_set_last_error (portLibrary, rc,
+						       HYPORT_ERROR_SOCKET_NBWITHLINGER);
+		  break;
+		default:
+		  rc =
+		    portLibrary->error_set_last_error (portLibrary, rc,
+						       findError (rc));
+		}
+	    }
+	  sockHandle->ipv4 = INVALID_SOCKET;
+	}
+    }
+  else
+    {
+      if (sockHandle->flags & SOCKET_IPV6_OPEN_MASK)
+	{
+	  /* Don't bother to check the error -- not like we can do anything about it. */
+	  shutdown (sockHandle->ipv6, 1);
+
+	  if (closesocket (SOCKET_CAST (sockHandle->ipv6)) == SOCKET_ERROR)
+	    {
+	      rc = WSAGetLastError ();
+	      HYSOCKDEBUG ("<closesocket failed, err=%d>\n", rc);
+	      switch (rc)
+		{
+		case WSAEWOULDBLOCK:
+		  rc =
+		    portLibrary->error_set_last_error (portLibrary, rc,
+						       HYPORT_ERROR_SOCKET_NBWITHLINGER);
+		  break;
+		default:
+		  rc =
+		    portLibrary->error_set_last_error (portLibrary, rc,
+						       findError (rc));
+		}
+	    }
+	  sockHandle->ipv6 = INVALID_SOCKET;
+	}
+    }
+
+  updateSocketState (sockHandle, !closeIPv4Socket);
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION isAnyAddress
+/**
+ * @internal Returns TRUE if the address is 0.0.0.0 or ::0, FALSE otherwise
+ */
+BOOL VMCALL
+isAnyAddress (hysockaddr_t addr)
+{
+  U_32 length = 0;
+  U_8 address[16];
+  BOOL truth = TRUE;
+  U_32 i;
+  U_32 scope_id;
+
+  /* get the address */
+  hysock_sockaddr_address6 (NULL, addr, address, &length, &scope_id);
+
+  for (i = 0; i < length; i++)
+    {
+      if (address[i] != 0)
+	{
+	  truth = FALSE;
+	  break;
+	}
+    }
+
+  return truth;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION map_addr_family_Hy_to_OS
+/**
+ * @internal Map the portable address family to the platform address family. 
+ *
+ * @param[in] addr_family The portable address family to convert
+ *
+ * @return	the platform family, or OS_AF_UNSPEC if none exists
+ */
+I_32
+map_addr_family_Hy_to_OS (I_32 addr_family)
+{
+  switch (addr_family)
+    {
+    case HYADDR_FAMILY_AFINET4:
+      return OS_AF_INET4;
+    case HYADDR_FAMILY_AFINET6:
+      return OS_AF_INET6;
+    }
+  return OS_AF_UNSPEC;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION map_protocol_family_Hy_to_OS
+/**
+ * @internal Map the portable address protocol to the platform protocol
+ *
+ * @param[in] addr_protocol The portable address protocol to convert
+ *
+ * @return	the platform family, or OS_PF_UNSPEC if none exists
+ */
+I_32
+map_protocol_family_Hy_to_OS (I_32 addr_family)
+{
+  switch (addr_family)
+    {
+    case HYPROTOCOL_FAMILY_INET4:
+      return OS_PF_INET4;
+    case HYPROTOCOL_FAMILY_INET6:
+      return OS_PF_INET6;
+    }
+  return OS_PF_UNSPEC;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION map_sockettype_Hy_to_OS
+/**
+ * @internal Map the portable socket type to the platform type. 
+ *
+ * @param[in] addr_family The portable socket type to convert
+ *
+ * @return	the platform family, or OSSOCK_ANY if none exists
+ */
+I_32
+map_sockettype_Hy_to_OS (I_32 socket_type)
+{
+  switch (socket_type)
+    {
+    case HYSOCKET_STREAM:
+      return OSSOCK_STREAM;
+    case HYSOCKET_DGRAM:
+      return OSSOCK_DGRAM;
+    case HYSOCKET_RAW:
+      return OSSOCK_RAW;
+    case HYSOCKET_RDM:
+      return OSSOCK_RDM;
+    case HYSOCKET_SEQPACKET:
+      return OSSOCK_SEQPACKET;
+    }
+  return OSSOCK_ANY;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION platformSocketLevel
+/**
+ * @internal Map the portable to the platform socket level. 
+ * Used to resolve the arguments of socket option functions.
+ * Levels currently in use are:
+ * \arg SOL_SOCKET, for most options
+ * \arg IPPROTO_TCP, for the TCP noDelay option
+ * \arg IPPROTO_IP, for the option operations associated with multicast (join, drop, interface)
+ *
+ * @param[in] portableSocketLevel The portable socket level to convert.
+ *
+ * @return the platform socket level or a (negative) error code if no equivalent level exists.
+ */
+I_32
+platformSocketLevel (I_32 portableSocketLevel)
+{
+  switch (portableSocketLevel)
+    {
+    case HY_SOL_SOCKET:
+      return OS_SOL_SOCKET;
+    case HY_IPPROTO_TCP:
+      return OS_IPPROTO_TCP;
+    case HY_IPPROTO_IP:
+      return OS_IPPROTO_IP;
+    case HY_IPPROTO_IPV6:
+      return OS_IPPROTO_IPV6;
+    }
+  return HYPORT_ERROR_SOCKET_SOCKLEVELINVALID;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION platformSocketOption
+/**
+ * @internal
+ * Map the portable to the platform socket options.  Used to resolve the arguments of socket option functions.
+ * Options currently in supported are:
+ * \arg SOL_LINGER, the linger timeout
+ * \arg TCP_NODELAY, the buffering scheme implementing Nagle's algorithm
+ * \arg IP_MULTICAST_TTL, the packet Time-To-Live
+ * \arg IP_ADD_MEMBERSHIP, to join a multicast group
+ * \arg  IP_DROP_MEMBERSHIP, to leave a multicast group
+ * \arg IP_MULTICAST_IF, the multicast interface
+ *
+ * @param[in] portableSocketOption The portable socket option to convert.
+ *
+ * @return	the platform socket option or a (negative) error code if no equivalent option exists.
+ */
+I_32
+platformSocketOption (I_32 portableSocketOption)
+{
+  switch (portableSocketOption)
+    {
+    case HY_SO_LINGER:
+      return OS_SO_LINGER;
+    case HY_SO_KEEPALIVE:
+      return OS_SO_KEEPALIVE;
+    case HY_TCP_NODELAY:
+      return OS_TCP_NODELAY;
+    case HY_MCAST_TTL:
+      return OS_MCAST_TTL;
+    case HY_MCAST_ADD_MEMBERSHIP:
+      return OS_MCAST_ADD_MEMBERSHIP;
+    case HY_MCAST_DROP_MEMBERSHIP:
+      return OS_MCAST_DROP_MEMBERSHIP;
+    case HY_MCAST_INTERFACE:
+      return OS_MCAST_INTERFACE;
+    case HY_MCAST_INTERFACE_2:
+      return OS_MCAST_INTERFACE_2;
+    case HY_IPV6_ADD_MEMBERSHIP:
+      return OS_IPV6_ADD_MEMBERSHIP;
+    case HY_IPV6_DROP_MEMBERSHIP:
+      return OS_IPV6_DROP_MEMBERSHIP;
+    case HY_SO_REUSEADDR:
+      return OS_SO_REUSEADDR;
+    case HY_SO_SNDBUF:
+      return OS_SO_SNDBUF;
+    case HY_SO_RCVBUF:
+      return OS_SO_RCVBUF;
+    case HY_SO_BROADCAST:
+      return OS_SO_BROADCAST;
+    case HY_SO_OOBINLINE:
+      return OS_SO_OOBINLINE;
+    case HY_IP_MULTICAST_LOOP:
+      return OS_MCAST_LOOP;
+    case HY_IP_TOS:
+      return OS_IP_TOS;
+    }
+  return HYPORT_ERROR_SOCKET_OPTUNSUPP;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION updateSocketState
+
+/**
+ * @internal updates the socketHandle by putting the socket in either the ipv4 or ipv6 slot
+ */
+void VMCALL
+updateSocketState (hysocket_t socket, BOOL useIPv4Socket)
+{
+
+  U_8 mask1 = SOCKET_USE_IPV4_MASK;
+  U_8 mask2 = SOCKET_IPV4_OPEN_MASK;
+  U_8 mask3 = SOCKET_IPV6_OPEN_MASK;
+
+  if (useIPv4Socket)
+    {
+      /* Set the flags to "use IPv4" and "IPv6 not open"  */
+      socket->flags = (socket->flags | mask1) & ~mask3;
+    }
+  else
+    {
+      /* Set the flags to "use IPv6" and "IPv4 not open"  */
+      socket->flags = (socket->flags | mask3) & ~(mask1 | mask2);
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION initializeSocketStructure
+/**
+ * @internal initializes the socketHandle by putting the socket in either the ipv4 or ipv6 slot
+ */
+static void VMCALL
+initializeSocketStructure (hysocket_t sockHandle, OSSOCKET sock,
+			   BOOL useIPv4Socket)
+{
+  if (useIPv4Socket)
+    {
+      sockHandle->ipv4 = sock;
+      sockHandle->ipv6 = INVALID_SOCKET;
+      sockHandle->flags = SOCKET_IPV4_OPEN_MASK;
+    }
+  else
+    {
+      sockHandle->ipv4 = INVALID_SOCKET;
+      sockHandle->ipv6 = sock;
+      sockHandle->flags = SOCKET_IPV6_OPEN_MASK;
+    }
+
+  updateSocketState (sockHandle, useIPv4Socket);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION useIPv4Socket
+/**
+ * @internal updates the socketHandle by putting the socket in either the ipv4 or ipv6 slot
+ */
+BOOL VMCALL
+useIPv4Socket (hysocket_t sockHandle)
+{
+  return (sockHandle->flags & SOCKET_USE_IPV4_MASK) == SOCKET_USE_IPV4_MASK;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_accept
+/**
+ * The accept function extracts the first connection on the queue of pending connections 
+ * on socket sock. It then creates a new socket and returns a handle to the new socket. 
+ * The newly created socket is the socket that will handle the actual the connection and 
+ * has the same properties as socket sock.  
+ *
+ * The accept function can block the caller until a connection is present if no pending 
+ * connections are present on the queue.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] serverSock  A hysocket_t  from which data will be read.
+ * @param[in] addrHandle An optional pointer to a buffer that receives the address of the connecting 
+ * entity, as known to the communications layer. The exact format of the addr parameter 
+ * is determined by the address family established when the socket was created. 
+ * @param[in] sockHandle A pointer to a hysocket_t  which will point to the newly created 
+ * socket once accept returns succesfully
+ *
+ * @return 
+ * \arg 0 on success
+ * \arg HYPORT_ERROR_SOCKET_BADSOCKET, on generic error
+ * \arg HYPORT_ERROR_SOCKET_NOTINITIALIZED, if socket library uninitialized
+ * \arg HYPORT_ERROR_SOCKET_INTERRUPTED, the call was cancelled
+ * \arg HYPORT_ERROR_SOCKET_ADDRNOTAVAIL, the addr parameter is not valid
+ * \arg HYPORT_ERROR_SOCKET_SYSTEMBUSY, if system busy handling other requests
+ * \arg HYPORT_ERROR_SOCKET_SYSTEMFULL, is too many sockets are active
+ * \arg HYPORT_ERROR_SOCKET_WOULDBLOCK, the socket is marked as nonblocking and no connections are present to be accepted., 
+ */
+/* IPv6 - In the case of IPv6 if the address is the any address, a socket will be created on 
+ * both the IPv4 and IPv6 stack.  The Windows IPv6 stack does not implement the full
+ * specification and a socket must be created to listen on both stacks for incoming calls.
+ */
+I_32 VMCALL
+hysock_accept (struct HyPortLibrary * portLibrary, hysocket_t serverSock,
+	       hysockaddr_t addrHandle, hysocket_t * sockHandle)
+{
+  I_32 rc = 0;
+  hysocket_t sock = 0;
+  SOCKET _sc;
+  I_32 addrlen = sizeof (addrHandle->addr);
+
+  if (useIPv4Socket (serverSock))
+    {
+      ((OSSOCKADDR *) & addrHandle->addr)->sin_family = OS_AF_INET4;
+      _sc =
+	accept (serverSock->ipv4, (struct sockaddr *) &addrHandle->addr,
+		&addrlen);
+    }
+  else
+    {
+      ((OSSOCKADDR *) & addrHandle->addr)->sin_family = OS_AF_INET6;
+      _sc =
+	accept (serverSock->ipv6, (struct sockaddr *) &addrHandle->addr,
+		&addrlen);
+    }
+
+  if (_sc == INVALID_SOCKET)
+    {
+      *sockHandle = (hysocket_t)INVALID_SOCKET;
+      rc = WSAGetLastError ();
+      HYSOCKDEBUG ("<accept failed, err=%d>\n", rc);
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_NOTLISTENING);
+	case WSAEOPNOTSUPP:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_NOTSTREAMSOCK);
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+  else
+    {
+      *sockHandle =
+	portLibrary->mem_allocate_memory (portLibrary,
+					  sizeof (struct hysocket_struct));
+      initializeSocketStructure (*sockHandle, _sc,
+				 useIPv4Socket (serverSock));
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_bind
+/**
+ * The bind function is used on an unconnected socket before subsequent 
+ * calls to the connect or listen functions. When a socket is created with a 
+ * call to the socket function, it exists in a name space (address family), but 
+ * it has no name assigned to it. Use bind to establish the local association 
+ * of the socket by assigning a local name to an unnamed socket.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] sock hysocket_t which will be be associated with the specified name.
+ * @param[in] addr Address to bind to socket.
+ *
+ * @return
+ * \arg 0, on success
+ * \arg HYPORT_ERROR_SOCKET_BADSOCKET, on generic error
+ * \arg HYPORT_ERROR_SOCKET_NOTINITIALIZED, if socket library uninitialized
+ * \arg HYPORT_ERROR_SOCKET_ADDRINUSE  A process on the machine is already bound to the same fully-qualified address 
+ * and the socket has not been marked to allow address re-use with SO_REUSEADDR. 
+ * \arg HYPORT_ERROR_SOCKET_ADDRNOTAVAIL The specified address is not a valid address for this machine 
+ * \arg HYPORT_ERROR_SOCKET_SYSTEMBUSY, if system busy handling other requests
+ * \arg HYPORT_ERROR_SOCKET_SYSTEMFULL, is too many sockets are active
+ * \arg HYPORT_ERROR_SOCKET_BADADDR, the addr parameter is not a valid part of the user address space, 
+ */
+/* IPv6 - Since we may have 2 sockets open when we are in IPv6 mode we need to
+ * close down the second socket.  At the bind stage we now know the IP address' family
+ * so we can shut down the other socket.
+ */
+I_32 VMCALL
+hysock_bind (struct HyPortLibrary * portLibrary, hysocket_t sock,
+	     hysockaddr_t addr)
+{
+  I_32 rc = 0;
+  BOOL isIPv4 = ((OSSOCKADDR *) & addr->addr)->sin_family == OS_AF_INET4;
+  BOOL anyAddress = isAnyAddress (addr);
+  OSSOCKET socket;
+  struct sockaddr_in temp4Name;
+  struct sockaddr_in6 temp6Name;
+  I_32 addrlen;
+  OSSOCKADDR_STORAGE anyAddr;
+
+  /* use the IPv4 socket, if is an IPv4 address or where  IPv6 socket is null (when preferIPv4Stack=true),
+   * it will give a meaningful error msg.
+   */
+  if (isIPv4 || (sock->ipv6 == -1))
+    {
+      socket = sock->ipv4;
+    }
+  else
+    {
+      socket = sock->ipv6;
+    }
+
+  if (SOCKET_ERROR ==
+      bind (socket, (const struct sockaddr FAR *) &addr->addr,
+	    sizeof (addr->addr)))
+    {
+      rc = WSAGetLastError ();
+      HYSOCKDEBUG ("<bind failed, err=%d>\n", rc);
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_ALREADYBOUND);
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+
+  /* If we are the any address, then we want to bind on the other IP stack as well, if that socket is still open */
+  if (isAnyAddress
+      && ((isIPv4 && (sock->flags & SOCKET_IPV6_OPEN_MASK))
+	  || (!isIPv4 && (sock->flags & SOCKET_IPV4_OPEN_MASK))))
+    {
+      memset (&anyAddr, 0, sizeof (OSSOCKADDR_STORAGE));
+
+      if (isIPv4)
+	{
+	  socket = sock->ipv6;
+	  addrlen = sizeof (temp4Name);
+	  rc =
+	    getsockname (sock->ipv4, (struct sockaddr *) &temp4Name,
+			 &addrlen);
+	  ((OSSOCKADDR_IN6 *) & anyAddr)->sin6_port = temp4Name.sin_port;
+	  ((OSSOCKADDR *) & anyAddr)->sin_family = OS_AF_INET6;
+	}
+      else
+	{
+	  socket = sock->ipv4;
+	  addrlen = sizeof (temp6Name);
+	  rc =
+	    getsockname (sock->ipv6, (struct sockaddr *) &temp6Name,
+			 &addrlen);
+	  /*TODO: put error check here - determine what to do in the case where unable to get port */
+	  ((OSSOCKADDR *) & anyAddr)->sin_port = temp6Name.sin6_port;
+	  ((OSSOCKADDR *) & anyAddr)->sin_family = OS_AF_INET4;
+	}
+
+      if (SOCKET_ERROR ==
+	  bind (socket, (const struct sockaddr FAR *) &anyAddr,
+		sizeof (addr->addr)))
+	{
+	  rc = WSAGetLastError ();
+	  HYSOCKDEBUG ("<bind failed, err=%d>\n", rc);
+	  switch (rc)
+	    {
+	    case WSAEINVAL:
+	      return portLibrary->error_set_last_error (portLibrary, rc,
+							HYPORT_ERROR_SOCKET_ALREADYBOUND);
+	    default:
+	      return portLibrary->error_set_last_error (portLibrary, rc,
+							findError (rc));
+	    }
+	}
+    }
+
+  /* close the other half of the socket, if we are not the ANY address ::0 or 0.0.0.0 */
+  if (!anyAddress)
+    {
+      internalCloseSocket (portLibrary, sock, !isIPv4);
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_close
+/**
+ * The close function closes a socket. Use it to release the socket descriptor socket so 
+ * further references to socket will fail.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] sock hysocket_t  which will be closed.
+ *
+ * @return
+ * \arg 0, on success
+ * \arg HYPORT_ERROR_SOCKET_BADSOCKET, on generic error
+ * \arg HYPORT_ERROR_SOCKET_SYSTEMBUSY, if system busy handling other requests
+ * \arg HYPORT_ERROR_SOCKET_WOULDBLOCK,  the socket is marked as nonblocking and SO_LINGER
+ *                                       is set to a nonzero time-out value.
+ */
+I_32 VMCALL
+hysock_close (struct HyPortLibrary * portLibrary, hysocket_t * sock)
+{
+  I_32 rc1 = 0;
+  I_32 rc2 = 0;
+  hysocket_t theSocket = *sock;
+
+  rc1 = internalCloseSocket (portLibrary, theSocket, TRUE);
+  rc2 = internalCloseSocket (portLibrary, theSocket, FALSE);
+
+  portLibrary->mem_free_memory (portLibrary, theSocket);
+  *sock = (hysocket_t) INVALID_SOCKET;
+
+  if (rc1 == 0)
+    {
+      rc1 = rc2;
+    }
+
+  return rc1;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_connect
+/**
+ * Establish a connection to a peer.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] sock pointer to the unconnected local socket.
+ * @param[in] addr	pointer to the sockaddr, specifying remote host/port.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+/* IPv6 - we may have more than one open socket at this point, an IPv6 and an IPv4.  Now
+ * that we are connect to a specific address we can determine whether to use the IPv4
+ * or IPv6 address and close the other address.
+ *
+ */
+I_32 VMCALL
+hysock_connect (struct HyPortLibrary * portLibrary, hysocket_t sock,
+		hysockaddr_t addr)
+{
+  I_32 rc = 0;
+  DWORD socketType;
+  int socketTypeLen = sizeof (DWORD);
+  byte nAddrBytes[HYSOCK_INADDR6_LEN];
+
+  /* get the socket type, it should be the same for both sockets and one of the two should be open */
+  if (sock->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      if (getsockopt
+	  (sock->ipv4, SOL_SOCKET, SO_TYPE, (char *) &socketType,
+	   &socketTypeLen) == SOCKET_ERROR)
+	{
+	  rc = WSAGetLastError ();
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+  else
+    {
+      if (getsockopt
+	  (sock->ipv6, SOL_SOCKET, SO_TYPE, (char *) &socketType,
+	   &socketTypeLen) == SOCKET_ERROR)
+	{
+	  rc = WSAGetLastError ();
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+
+  /* here we need to do the connect based on the type of addressed passed in as well as the sockets which are open. If 
+     a socket with a type that matches the type of the address passed in is open then we use that one.  Otherwise we
+     use the socket that is open */
+  if (((((OSSOCKADDR *) & addr->addr)->sin_family != OS_AF_UNSPEC) &&
+       ((((OSSOCKADDR *) & addr->addr)->sin_family == OS_AF_INET4) ||
+	!(sock->flags & SOCKET_IPV6_OPEN_MASK)) &&
+       (sock->flags & SOCKET_IPV4_OPEN_MASK)))
+    {
+      rc =
+	connect (sock->ipv4, (const struct sockaddr FAR *) &addr->addr,
+		 sizeof (addr->addr));
+      if (socketType != SOCK_DGRAM)
+	{
+	  internalCloseSocket (portLibrary, sock, FALSE);
+	}
+      else
+	{
+	  /* we don't acutally want to close the sockets as connect can be called again on a datagram socket  but we 
+	     still need to set the flag that tells us which socket to use */
+	  sock->flags = sock->flags | SOCKET_USE_IPV4_MASK;
+	}
+    }
+  else if (((OSSOCKADDR *) & addr->addr)->sin_family == OS_AF_INET6)
+    {
+      rc =
+	connect (sock->ipv6, (const struct sockaddr FAR *) &addr->addr,
+		 sizeof (addr->addr));
+      if (socketType != SOCK_DGRAM)
+	{
+	  internalCloseSocket (portLibrary, sock, TRUE);
+	}
+      else
+	{
+	  /* we don't acutally want to close the sockets as connect can be called again on a datagram socket  but we 
+	     still need to set the flag that tells us which socket to use. */
+	  sock->flags = sock->flags & ~SOCKET_USE_IPV4_MASK;
+	}
+    }
+  else
+    {
+      if (socketType != SOCK_DGRAM)
+	{
+	  /* this should never occur */
+	  return HYPORT_ERROR_SOCKET_BADAF;
+	}
+
+      /* for windows it seems to want to have it connect with an IN_ADDR any instead of with an 
+         UNSPEC familty type so lets be accomodating */
+
+      /* we need to disconnect on both sockets and swallow any expected errors */
+      memset (nAddrBytes, 0, HYSOCK_INADDR6_LEN);
+      if (sock->flags & SOCKET_IPV4_OPEN_MASK)
+	{
+	  hysock_sockaddr_init6 (portLibrary, addr, (U_8 *) nAddrBytes,
+				 HYSOCK_INADDR_LEN, HYADDR_FAMILY_AFINET4, 0,
+				 0, 0, sock);
+	  rc =
+	    connect (sock->ipv4, (const struct sockaddr FAR *) &addr->addr,
+		     sizeof (addr->addr));
+	}
+
+      /* filter out acceptable errors */
+      if (rc == SOCKET_ERROR)
+	{
+	  rc = WSAGetLastError ();
+	  if (rc == WSAEAFNOSUPPORT || rc == WSAEADDRNOTAVAIL)
+	    {
+	      rc = 0;
+	    }
+	}
+
+      if (rc == 0 && sock->flags & SOCKET_IPV6_OPEN_MASK)
+	{
+	  hysock_sockaddr_init6 (portLibrary, addr, (U_8 *) nAddrBytes,
+				 HYSOCK_INADDR_LEN, HYADDR_FAMILY_AFINET6, 0,
+				 0, 0, sock);
+	  connect (sock->ipv6, (const struct sockaddr FAR *) &addr->addr,
+		   sizeof (addr->addr));
+	}
+    }
+
+  if (rc == SOCKET_ERROR)
+    {
+      rc = WSAGetLastError ();
+      HYSOCKDEBUG ("<connect failed, err=%d>\n", rc);
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_ALREADYBOUND);
+	case WSAEAFNOSUPPORT:
+	  /* if it is a SOCK_DGRAM this is ok as posix says this may be returned when disconnecting */
+	  if (socketType == SOCK_DGRAM)
+	    {
+	      return 0;
+	    }
+	  /* no break here as default is what we want if we do not return above */
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_error_message
+/**
+ * Return an error message describing the last OS error that occurred.  The last
+ * error returned is not thread safe, it may not be related to the operation that
+ * failed for this thread.
+ *
+ * @param[in] portLibrary The port library
+ *
+ * @return	error message describing the last OS error, may return NULL.
+ *
+ * @internal
+ * @note  This function gets the last error code from the OS and then returns
+ * the corresponding string.  It is here as a helper function for JCL.  Once hyerror
+ * is integrated into the port library this function should probably disappear.
+ */
+const char *VMCALL
+hysock_error_message (struct HyPortLibrary *portLibrary)
+{
+  return portLibrary->error_last_error_message (portLibrary);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_fdset_init
+/**
+ * Create a file descriptor (FD) set of one element.  The call may not be generally useful,
+ * as it currently only supports a single FD and is assumed to be used in conjunction with the 
+ * hysock_select function.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] socketP pointer to the socket to be added to the FD set.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_fdset_init (struct HyPortLibrary * portLibrary, hysocket_t socketP)
+{
+  PortlibPTBuffers_t ptBuffers;
+  hyfdset_t fdset;
+
+  ptBuffers = hyport_tls_get (portLibrary);
+  if (NULL == ptBuffers)
+    {
+      return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+    }
+
+  if (NULL == ptBuffers->fdset)
+    {
+      ptBuffers->fdset =
+	portLibrary->mem_allocate_memory (portLibrary,
+					  sizeof (struct hyfdset_struct));
+      if (NULL == ptBuffers->fdset)
+	{
+	  return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+	}
+    }
+  fdset = ptBuffers->fdset;
+  memset (fdset, 0, sizeof (struct hyfdset_struct));
+
+  FD_ZERO (&fdset->handle);
+  if (socketP->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      FD_SET (socketP->ipv4, &fdset->handle);
+    }
+  if (socketP->flags & SOCKET_IPV6_OPEN_MASK)
+    {
+      FD_SET (socketP->ipv6, &fdset->handle);
+    }
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_fdset_size
+/**
+ * Answer the maximum size of the fdset currently declared for the platform.
+ * This value is a parameter of the @ref hysock_select call.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle
+ *
+ * @return	the maximum size of the fdset, otherwise the (negative) error code.
+ *
+ * @note On Unix, the value was the maximum file descriptor plus one, although
+ * on many flavors, the value is ignored in the select function.
+ * It is essential on Neutrino 2.0.
+ * On Windows, the value is ignored by the select function.
+ * On OS/2, the value is the number of file descriptors to be checked.
+ */
+I_32 VMCALL
+hysock_fdset_size (struct HyPortLibrary * portLibrary, hysocket_t handle)
+{
+  I_32 rc;
+  if (handle->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      rc = handle->ipv4 + 1;
+    }
+  if (handle->flags & SOCKET_IPV6_OPEN_MASK)
+    {
+      rc = handle->ipv6 + 1;
+      if ((handle->ipv4 != -1) && (handle->ipv4 > handle->ipv6))
+	{
+	  rc = handle->ipv4 + 1;
+	}
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_freeaddrinfo
+/**
+ * Frees the memory created by the call to @ref hysock_getaddrinfo().
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Hints on what results are returned and how the response if formed .
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ *
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_freeaddrinfo (struct HyPortLibrary * portLibrary, hyaddrinfo_t handle)
+{
+  /* If we have the IPv6 functions we free the memory for an addr info, otherwise we just set the pointer to null.
+     The hostent structure returned by the IPv4 function is not supposed to be freed  */
+  if (PPG_sock_IPv6_FUNCTION_SUPPORT)
+    {
+      freeaddrinfo ((OSADDRINFO *) handle->addr_info);
+    }
+
+  handle->addr_info = NULL;
+  handle->length = 0;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getaddrinfo
+/**
+ * \section hysock_getaddrinfo()
+ * Answers a list of addresses as an opaque pointer in "result".
+ * 
+ * Use the following functions to extract the details:
+ * \arg \ref hysock_getaddrinfo_length
+ * \arg \ref hysock_getaddrinfo_name
+ * \arg \ref hysock_getaddrinfo_address
+ * \arg \ref hysock_getaddrinfo_family
+ *
+ * If the machine type supports IPv6 you can specify how you want the results returned with the following function:
+ * \arg \ref hysock_create_getaddrinfo_hints.
+ * Passing the structure into a machine with only IPv4 support will have no effect.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] name The name of the host in either host name format or in IPv4 or IPv6 accepted notations.
+ * @param[in] hints Hints on what results are returned and how the response if formed (can be NULL for default action).
+ * @param[out] result An opaque pointer to a list of results (hyaddrinfo_struct must be preallocated).
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ *
+ * @note you must free the "result" structure with @ref hysock_freeaddrinfo to free up memory.  This must be done
+ * before you make a subsequent call in the same thread to this function. 
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_getaddrinfo (struct HyPortLibrary * portLibrary, char *name,
+		    hyaddrinfo_t hints, hyaddrinfo_t result)
+{
+  struct hyhostent_struct hyhostent;
+  U_32 addr = 0;
+  I_32 rc = 0;
+  OSADDRINFO *ipv6_result;
+  OSADDRINFO *addr_info_hints = NULL;
+
+  int count = 0;
+
+  /* If we have the IPv6 functions available we will call them, otherwise we'll call the IPv4 function */
+  if (PPG_sock_IPv6_FUNCTION_SUPPORT)
+    {
+      if (hints != NULL)
+	{
+	  addr_info_hints = (OSADDRINFO *) hints->addr_info;
+	}
+      if (0 != getaddrinfo (name, NULL, addr_info_hints, &ipv6_result))
+	{
+	  I_32 errorCode = WSAGetLastError ();
+	  HYSOCKDEBUG ("<getaddrinfo failed, err=%d>\n", errorCode);
+	  return portLibrary->error_set_last_error (portLibrary, errorCode,
+						    findError (errorCode));
+	}
+      else
+	{
+	  memset (result, 0, sizeof (struct hyaddrinfo_struct));
+	  result->addr_info = (void *) ipv6_result;
+	  while (ipv6_result->ai_next != NULL)
+	    {
+	      count++;
+	      ipv6_result = ipv6_result->ai_next;
+	    }
+	  result->length = ++count;	/* Have to add an extra, because we didn't count the first entry */
+	}
+    }
+  else
+    {
+      if (0 != portLibrary->sock_inetaddr (portLibrary, name, &addr))
+	{
+	  if (0 !=
+	      (rc =
+	       portLibrary->sock_gethostbyname (portLibrary, name,
+						&hyhostent)))
+	    {
+	      return rc;
+	    }
+	}
+      else
+	{
+	  if ((0 !=
+	       (rc =
+		portLibrary->sock_gethostbyaddr (portLibrary, (char *) &addr,
+						 sizeof (addr), HYSOCK_AFINET,
+						 &hyhostent)))
+	      && (0 !=
+		  portLibrary->sock_gethostbyname (portLibrary, name,
+						   &hyhostent)))
+	    {
+	      return rc;
+	    }
+	}
+
+      memset (result, 0, sizeof (struct hyaddrinfo_struct));
+      result->addr_info = (void *) hyhostent.entity;
+
+      /* count the host names and the addresses */
+      while (hyhostent.entity->h_addr_list[count] != 0)
+	{
+	  count++;
+	}
+      result->length = count;
+    }
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getaddrinfo_address
+/**
+ * Answers a U_8 array representing the address at "index" in the structure returned from @ref hysock_getaddrinfo,
+ * indexed starting at 0. The address is in network byte order. 
+ *
+ * The address will either be 4 or 16 bytes depending on whether it is an OS_AF_INET  address or an
+ * OS_AF_INET6  address.  You can check this will a call to @ref hysock_getaddrinfo_family.  Therefore you
+ * should either check the family type before preallocating the "address" or define it as 16 bytes.
+ *
+ * @param[in]   portLibrary The port library.
+ * @param[in]   handle The result structure returned by @ref hysock_getaddrinfo.
+ * @param[out] address The address at "index" in a preallocated buffer.
+ * @param[in]   index The address index into the structure returned by @ref hysock_getaddrinfo.
+ * @param[out] scope_id  The scope id associated with the address if applicable
+ *
+ * @return	
+ * \arg 0, if no errors occurred, otherwise the (negative) error code
+ * \arg HYPORT_ERROR_SOCKET_VALUE_NULL when we have have the old IPv4 gethostbyname call and the address indexed is out
+ * of range.  This is because the address list and the host alias list are not the same length.  Just skip this entry.
+ *
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_getaddrinfo_address (struct HyPortLibrary * portLibrary,
+			    hyaddrinfo_t handle, U_8 * address, int index,
+			    U_32 * scope_id)
+{
+  I_32 rc = 0;
+  OSADDRINFO *addr;
+  void *sock_addr;
+
+  char **addr_list;
+  int i;
+
+  /* If we have the IPv6 functions available we cast to an OSADDRINFO structure otherwise a OSHOSTENET structure */
+  if (PPG_sock_IPv6_FUNCTION_SUPPORT)
+    {
+      addr = (OSADDRINFO *) handle->addr_info;
+      for (i = 0; i < index; i++)
+	{
+	  addr = addr->ai_next;
+	}
+      if (addr->ai_family == OS_AF_INET6)
+	{
+	  sock_addr = ((OSSOCKADDR_IN6 *) addr->ai_addr)->sin6_addr.s6_addr;
+	  memcpy (address, sock_addr, 16);
+	  *scope_id = ((OSSOCKADDR_IN6 *) addr->ai_addr)->sin6_scope_id;
+	}
+      else
+	{
+	  sock_addr = &((OSSOCKADDR *) addr->ai_addr)->sin_addr.S_un.S_un_b;
+	  memcpy (address, sock_addr, 4);
+	  *scope_id = 0;
+	}
+    }
+  else
+    {
+      /* initialize the scope id */
+      *scope_id = 0;
+
+      addr_list = ((OSHOSTENT *) handle->addr_info)->h_addr_list;
+      for (i = 0; i < index; i++)
+	{
+	  if (addr_list[i] == NULL)
+	    {
+	      return HYPORT_ERROR_SOCKET_VALUE_NULL;
+	    }
+	}
+      memcpy (address, addr_list[index], 4);
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getaddrinfo_create_hints
+/**
+ * Answers a hints structure as an opaque pointer in "result".
+ * 
+ * This hints structure is used to modify the results returned by a call to @ref hysock_getaddrinfo.  There is one of
+ * these structures per thread, so subsequent calls to this function will overwrite the same structure in memory.
+ * The structure is cached in ptBuffers and is cleared when a call to @ref hyport_free_ptBuffer is made.
+ *
+ * This function is only works on IPv6 supported OS's.  If it is called on an OS that does not support IPv6 then
+ * it essentially returns a NULL pointer, meaning it will have no effect on the call to @ref hysock_getaddrinfo.
+ *
+ * See man pages, or MSDN doc on getaddrinfo for information on how the hints structure works.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[out] result The filled in (per thread) hints structure
+ * @param[in] family A address family type
+ * @param[in] socktype A socket type
+ * @param[in] protocol A protocol family
+ * @param[in] flags Flags for modifying the result
+ *
+ * @return
+ * \arg 0, if no errors occurred, otherwise the (negative) error code
+ * \arg HYPORT_ERROR_SOCKET_SYSTEMFULL -- when we can't allocate memory for the ptBuffers, or the hints structure
+ *
+ * @note current supported family types are:
+ * \arg HYADDR_FAMILY_UNSPEC
+ * \arg HYADDR_FAMILY_AFINET4
+ * \arg HYADDR_FAMILY_AFINET6
+ *
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_getaddrinfo_create_hints (struct HyPortLibrary * portLibrary,
+				 hyaddrinfo_t * result, I_16 family,
+				 I_32 socktype, I_32 protocol, I_32 flags)
+{
+  I_32 rc = 0;
+  OSADDRINFO *addrinfo;
+  PortlibPTBuffers_t ptBuffers;
+  *result = NULL;
+
+#define addrinfohints (ptBuffers->addr_info_hints).addr_info
+  /* If we have the IPv6 functions available we fill in the structure, otherwise it is null */
+  if (PPG_sock_IPv6_FUNCTION_SUPPORT)
+    {
+      ptBuffers = hyport_tls_get (portLibrary);
+      if (NULL == ptBuffers)
+	{
+	  return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+	}
+      if (!addrinfohints)
+	{
+	  addrinfohints =
+	    portLibrary->mem_allocate_memory (portLibrary,
+					      sizeof (OSADDRINFO));
+	  if (!addrinfohints)
+	    {
+	      return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+	    }
+	}
+      memset (addrinfohints, 0, sizeof (OSADDRINFO));
+      addrinfo = (OSADDRINFO *) addrinfohints;
+      addrinfo->ai_flags = flags;
+      addrinfo->ai_family = map_addr_family_Hy_to_OS (family);
+      addrinfo->ai_socktype = map_sockettype_Hy_to_OS (socktype);
+      addrinfo->ai_protocol = map_protocol_family_Hy_to_OS (protocol);
+      *result = &ptBuffers->addr_info_hints;
+    }
+#undef addrinfohints
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getaddrinfo_family
+/**
+ * Answers the family type of the address at "index" in the structure returned from
+ * @ref hysock_getaddrinfo, indexed starting at 0.
+ *
+ * Currently the family types we support are HYSOCK_AFINET and HYSOCK_AFINET6.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle The result structure returned by @ref hysock_getaddrinfo.
+ * @param[out] family The family at "index".
+ * @param[in] index The address index into the structure returned by @ref hysock_getaddrinfo.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ *
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_getaddrinfo_family (struct HyPortLibrary * portLibrary,
+			   hyaddrinfo_t handle, I_32 * family, int index)
+{
+  I_32 rc = 0;
+  OSADDRINFO *addr;
+  int i;
+
+  /* If we have the IPv6 functions then we'll cast to a OSADDRINFO othewise we have a hostent */
+  if (PPG_sock_IPv6_FUNCTION_SUPPORT)
+    {
+      addr = (OSADDRINFO *) handle->addr_info;
+      for (i = 0; i < index; i++)
+	{
+	  addr = addr->ai_next;
+	}
+      if (addr->ai_family == OS_AF_INET4)
+	{
+	  *family = HYADDR_FAMILY_AFINET4;
+	}
+      else
+	{
+	  *family = HYADDR_FAMILY_AFINET6;
+	}
+    }
+  else
+    {
+      *family = HYADDR_FAMILY_AFINET4;
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getaddrinfo_length
+/**
+ * Answers the number of results returned from @ref hysock_getaddrinfo.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle The result structure returned by @ref hysock_getaddrinfo.
+ * @param[out] length The number of results.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ *
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_getaddrinfo_length (struct HyPortLibrary * portLibrary,
+			   hyaddrinfo_t handle, I_32 * length)
+{
+  *length = handle->length;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getaddrinfo_name
+/**
+ * Answers the cannon name of the address at "index" in the structure returned from
+ *  @ref hysock_getaddrinfo, indexed starting at 0.
+ * 
+ * The preallocated buffer for "name" should be the size of the maximum host name: OSNIMAXHOST.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle The result structure returned by @ref hysock_getaddrinfo.
+ * @param[out] name The name of the address at "index" in a preallocated buffer.
+ * @param[in] index The address index into the structure returned by @ref hysock_getaddrinfo.
+ *
+ * @return
+ * \arg 0, if no errors occurred, otherwise the (negative) error code.
+ * \arg HYPORT_ERROR_SOCKET_VALUE_NULL when we have have the old IPv4 gethostbyname call and the name indexed is out
+ * of range.  This is because the address list and the host alias list are not the same length.  Just skip this entry.
+ *
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_getaddrinfo_name (struct HyPortLibrary * portLibrary,
+			 hyaddrinfo_t handle, char *name, int index)
+{
+  I_32 rc = 0;
+  char **alias_list;
+  int i;
+  OSADDRINFO *addr;
+
+  /* If we have the IPv6 functions available we cast to an OSADDRINFO structure otherwise a OSHOSTENET structure */
+  if (PPG_sock_IPv6_FUNCTION_SUPPORT)
+    {
+      addr = (OSADDRINFO *) handle->addr_info;
+      for (i = 0; i < index; i++)
+	{
+	  addr = addr->ai_next;
+	}
+      if (addr->ai_canonname == NULL)
+	{
+	  name[0] = 0;
+	}
+      else
+	{
+	  strcpy (name, addr->ai_canonname);
+	}
+    }
+  else
+    {
+      alias_list = ((OSHOSTENT *) handle->addr_info)->h_aliases;
+      for (i = 0; i < index; i++)
+	{
+	  if (alias_list[i] == NULL)
+	    {
+	      return HYPORT_ERROR_SOCKET_VALUE_NULL;
+	    }
+	}
+      if (alias_list[index] == NULL)
+	{
+	  name[0] = 0;
+	}
+      else
+	{
+	  strcpy (name, alias_list[index]);
+	}
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_gethostbyaddr
+/**
+ * Answer information on the host referred to by the address.  The information includes name, aliases and
+ * addresses for the nominated host (the latter being relevant on multi-homed hosts).
+ * This call has only been tested for addresses of type AF_INET.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] addr Pointer to the binary-format (not null-terminated) address, in network byte order.
+ * @param[in] length Length of the addr.
+ * @param[in] type The type of the addr.
+ * @param[out] handle Pointer to the hyhostent_struct, to be linked to the per thread platform hostent struct.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_gethostbyaddr (struct HyPortLibrary * portLibrary, char *addr,
+		      I_32 length, I_32 type, hyhostent_t handle)
+{
+  OSHOSTENT *result;
+
+  result = gethostbyaddr (addr, length, type);
+  if (result == 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+
+      HYSOCKDEBUG ("<gethostbyaddr failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+  else
+    {
+      memset (handle, 0, sizeof (struct hyhostent_struct));
+      handle->entity = result;
+    }
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_gethostbyname
+/**
+ * Answer information on the host, specified by name.  The information includes host name,
+ * aliases and addresses.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] name The host name string.
+ * @param[out] handle Pointer to the hyhostent_struct (to be linked to the per thread platform hostent struct).
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_gethostbyname (struct HyPortLibrary * portLibrary, char *name,
+		      hyhostent_t handle)
+{
+  OSHOSTENT *result;
+
+  result = gethostbyname (name);
+  if (result == 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+      HYSOCKDEBUG ("<gethostbyname failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+  else
+    {
+      memset (handle, 0, sizeof (struct hyhostent_struct));
+      handle->entity = result;
+    }
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_gethostname
+/**
+ * Answer the name of the local host machine.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in,out] buffer The string buffer to receive the name
+ * @param[in] length The length of the buffer
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code
+ */
+I_32 VMCALL
+hysock_gethostname (struct HyPortLibrary * portLibrary, char *buffer,
+		    I_32 length)
+{
+  if ((gethostname (buffer, length)) != 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+
+      HYSOCKDEBUG ("<gethostname failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getnameinfo
+/**
+ * Answers the host name of the "in_addr" in a preallocated buffer.
+ *
+ * The preallocated buffer for "name" should be the size of the maximum host name: OSNIMAXHOST.
+ * Currently only AF_INET and AF_INET6 are supported.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] in_addr The address we want to do a name lookup on
+ * @param[in] sockaddr_size The size of "in_addr"
+ * @param[out] name The hostname of the passed address in a preallocated buffer.
+ * @param[in] name_length The length of the buffer pointed to by name
+ * @param[in] flags Flags on how to form the repsonse (see man pages or doc for getnameinfo)
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code
+ *
+ * @note Added for IPv6 support.
+ * @note "flags" do not affect results on OS's that do not support the IPv6 calls.
+ */
+I_32 VMCALL
+hysock_getnameinfo (struct HyPortLibrary * portLibrary, hysockaddr_t in_addr,
+		    I_32 sockaddr_size, char *name, I_32 name_length,
+		    int flags)
+{
+  OSHOSTENT *result;
+  OSSOCKADDR *addr;
+  int size;
+  int rc = 0;
+
+  /* If we have the IPv6 functions available we will call them, otherwise we'll call the IPv4 function */
+  if (PPG_sock_IPv6_FUNCTION_SUPPORT)
+    {
+      /* Windows code requires that the sockaddr structure be of the right type, rather than
+       * just checking to see if it is large enough */
+      addr = (OSSOCKADDR *) & in_addr->addr;
+      if (addr->sin_family == OS_AF_INET4)
+	{
+	  sockaddr_size = sizeof (OSSOCKADDR);
+	}
+      else
+	{
+	  sockaddr_size = sizeof (OSSOCKADDR_IN6);
+	}
+      rc =
+	getnameinfo ((OSADDR *) & in_addr->addr, sockaddr_size, name,
+		     name_length, NULL, 0, flags);
+      if (rc != 0)
+	{
+	  I_32 errorCode = WSAGetLastError ();
+	  HYSOCKDEBUG ("<gethostbyaddr failed, err=%d>\n", errorCode);
+	  return portLibrary->error_set_last_error (portLibrary, errorCode,
+						    findError (errorCode));
+	}
+    }
+  else
+    {				/* IPv4 call */
+      addr = (OSSOCKADDR *) & in_addr->addr;
+      if (addr->sin_family == OS_AF_INET4)
+	{
+	  size = 4;
+	}
+      else
+	{
+	  size = 16;
+	}
+
+      result =
+	gethostbyaddr ((char *) &addr->sin_addr, size, addr->sin_family);
+      if (result == 0)
+	{
+	  I_32 errorCode = WSAGetLastError ();
+
+	  HYSOCKDEBUG ("<gethostbyaddr failed, err=%d>\n", errorCode);
+	  return portLibrary->error_set_last_error (portLibrary, errorCode,
+						    findError (errorCode));
+	}
+      else
+	{
+	  strcpy (name, result->h_name);
+	}
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getopt_bool
+/**
+ * Answer the value of the nominated boolean socket option.
+ * Refer to the private platformSocketLevel & platformSocketOption functions for details of the options
+ * supported.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] socketP Pointer to the socket to query for the option value.
+ * @param[in] optlevel	 The level within the IP stack at which the option is defined.
+ * @param[in] optname The name of the option to retrieve.
+ * @param[out] optval Pointer to the boolean to update with the option value.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_getopt_bool (struct HyPortLibrary * portLibrary, hysocket_t socketP,
+		    I_32 optlevel, I_32 optname, BOOLEAN * optval)
+{
+  I_32 platformLevel = platformSocketLevel (optlevel);
+  I_32 platformOption = platformSocketOption (optname);
+  BOOL option;
+  I_32 optlen = sizeof (option);
+  I_32 rc = 0;
+
+  if (0 > platformLevel)
+    {
+      return platformLevel;
+    }
+  if (0 > platformOption)
+    {
+      return platformOption;
+    }
+
+  /* If both sockets are open we only need to query the IPv4 option as will both be set to the same value */
+
+  if (socketP->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      rc =
+	getsockopt (socketP->ipv4, platformLevel, platformOption,
+		    (char *) &option, &optlen);
+    }
+  else if (socketP->flags & SOCKET_IPV6_OPEN_MASK)
+    {
+      if (platformOption == IP_MULTICAST_LOOP)
+	{
+	  platformLevel = IPPROTO_IPV6;
+	  platformOption = IPV6_MULTICAST_LOOP;
+	}
+      rc =
+	getsockopt (socketP->ipv6, platformLevel, platformOption,
+		    (char *) &option, &optlen);
+    }
+
+  if (rc != 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+
+      HYSOCKDEBUG ("<getsockopt (for bool) failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+  *optval = (BOOLEAN) option;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getopt_byte
+/**
+ * Answer the value of the nominated byte socket option.
+ * Refer to the private platformSocketLevel & platformSocketOption functions for details of the options
+ * supported.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] socketP Pointer to the socket to query for the option value.
+ * @param[in] optlevel	 The level within the IP stack at which the option is defined.
+ * @param[in] optname The name of the option to retrieve.
+ * @param[out] optval Pointer to the byte to update with the option value.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_getopt_byte (struct HyPortLibrary * portLibrary, hysocket_t socketP,
+		    I_32 optlevel, I_32 optname, U_8 * optval)
+{
+  I_32 platformLevel = platformSocketLevel (optlevel);
+  I_32 platformOption = platformSocketOption (optname);
+  U_32 optTemp = 0;
+  I_32 optlen = sizeof (optTemp);
+  I_32 rc = 0;
+
+  if (0 > platformLevel)
+    {
+      return platformLevel;
+    }
+  if (0 > platformOption)
+    {
+      return platformOption;
+    }
+
+  /* If both sockets are open we only need to query the IPv4 option as will both be set to the same value */
+
+  if (socketP->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      rc =
+	getsockopt (socketP->ipv4, platformLevel, platformOption,
+		    (char *) &optTemp, &optlen);
+    }
+  else if (socketP->flags & SOCKET_IPV6_OPEN_MASK)
+    {
+      if (platformOption == IP_MULTICAST_TTL)
+	{
+	  platformLevel = IPPROTO_IPV6;
+	  platformOption = IPV6_MULTICAST_HOPS;
+	}
+      rc =
+	getsockopt (socketP->ipv6, platformLevel, platformOption,
+		    (char *) &optTemp, &optlen);
+    }
+
+  if (rc != 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+
+      HYSOCKDEBUG ("<getsockopt (for byte) failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+  else
+    {
+      *optval = (0xFF & optTemp);
+    }
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getopt_int
+/**
+ * Answer the value of the nominated integer socket option.
+ * Refer to the private platformSocketLevel & platformSocketOption functions for details of the options
+ * supported.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] socketP Pointer to the socket to query for the option value.
+ * @param[in] optlevel The level within the IP stack at which the option is defined.
+ * @param[in] optname The name of the option to retrieve.
+ * @param[out] optval Pointer to the integer to update with the option value.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_getopt_int (struct HyPortLibrary * portLibrary, hysocket_t socketP,
+		   I_32 optlevel, I_32 optname, I_32 * optval)
+{
+  I_32 platformLevel = platformSocketLevel (optlevel);
+  I_32 platformOption = platformSocketOption (optname);
+  I_32 optlen = sizeof (*optval);
+  I_32 rc = 0;
+
+  if (0 > platformLevel)
+    {
+      return platformLevel;
+    }
+  if (0 > platformOption)
+    {
+      return platformOption;
+    }
+
+  /* If both sockets are open we only need to query the IPv4 option as will both be set to the same value */
+  /* unless the option is at the IPV6 proto level in which case we have to look at the IPV6 socket */
+  if ((socketP->flags & SOCKET_IPV4_OPEN_MASK)
+      && (platformLevel != OS_IPPROTO_IPV6))
+    {
+      rc =
+	getsockopt (socketP->ipv4, platformLevel, platformOption,
+		    (char *) optval, &optlen);
+    }
+  else if (socketP->flags & SOCKET_IPV6_OPEN_MASK)
+    {
+      rc =
+	getsockopt (socketP->ipv6, platformLevel, platformOption,
+		    (char *) optval, &optlen);
+    }
+  if (rc != 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+      HYSOCKDEBUG ("<getsockopt (for int) failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getopt_linger
+
+/**
+ * Answer the value of the socket linger option.
+ * See the @ref hysock_linger_init for details of the linger behavior.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] socketP Pointer to the socket to query for the option value
+ * @param[in] optlevel The level within the IP stack at which the option is defined
+ * @param[in] optname The name of the option to retrieve
+ * @param[out] optval Pointer to the linger struct to update with the option value
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code
+ */
+I_32 VMCALL
+hysock_getopt_linger (struct HyPortLibrary * portLibrary, hysocket_t socketP,
+		      I_32 optlevel, I_32 optname, hylinger_t optval)
+{
+  I_32 platformLevel = platformSocketLevel (optlevel);
+  I_32 platformOption = platformSocketOption (optname);
+  I_32 optlen = sizeof (optval->linger);
+  I_32 rc = 0;
+
+  if (0 > platformLevel)
+    {
+      return platformLevel;
+    }
+  if (0 > platformOption)
+    {
+      return platformOption;
+    }
+
+  /* If both sockets are open we only need to query the IPv4 option as will both be set to the same value */
+
+  if (socketP->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      rc =
+	getsockopt (socketP->ipv4, platformLevel, platformOption,
+		    (char *) (&optval->linger), &optlen);
+    }
+  else if (socketP->flags & SOCKET_IPV6_OPEN_MASK)
+    {
+      rc =
+	getsockopt (socketP->ipv6, platformLevel, platformOption,
+		    (char *) (&optval->linger), &optlen);
+    }
+  if (rc != 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+
+      HYSOCKDEBUG ("<getsockopt (for linger) failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getopt_sockaddr
+/**
+ * Answer the value of the socket option, an address struct.
+ * Currently only used to retrieve the interface of multicast sockets, 
+ * but the more general call style has been used.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] socketP Pointer to the socket to query for the option value.
+ * @param[in] optlevel	 The level within the IP stack at which the option is defined.
+ * @param[in] optname The name of the option to retrieve.
+ * @param[out] optval Pointer to the sockaddr struct to update with the option value.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_getopt_sockaddr (struct HyPortLibrary * portLibrary,
+			hysocket_t socketP, I_32 optlevel, I_32 optname,
+			hysockaddr_t optval)
+{
+  I_32 platformLevel = platformSocketLevel (optlevel);
+  I_32 platformOption = platformSocketOption (optname);
+  I_32 optlen = sizeof (((OSSOCKADDR *) & optval->addr)->sin_addr);
+  I_32 rc = 0;
+
+  if (0 > platformLevel)
+    {
+      return platformLevel;
+    }
+  if (0 > platformOption)
+    {
+      return platformOption;
+    }
+
+  /* If both sockets are open we only need to query the IPv4 option as will both be set to the same value */
+  if (socketP->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      rc =
+	getsockopt (socketP->ipv4, platformLevel, platformOption,
+		    (char *) &((OSSOCKADDR *) & optval->addr)->sin_addr,
+		    &optlen);
+    }
+  else if (socketP->flags & SOCKET_IPV6_OPEN_MASK)
+    {
+      rc =
+	getsockopt (socketP->ipv6, platformLevel, platformOption,
+		    (char *) &((OSSOCKADDR *) & optval->addr)->sin_addr,
+		    &optlen);
+    }
+
+  if (rc != 0)
+    {
+      I_32 errorCode = WSAGetLastError ();
+
+      HYSOCKDEBUG ("<getsockopt (for sockaddr) failed, err=%d>\n", errorCode);
+      return portLibrary->error_set_last_error (portLibrary, errorCode,
+						findError (errorCode));
+    }
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getpeername
+/**
+ * Answer the remote name for the socket.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the socket to get the address of.
+ * @param[out] addrHandle Pointer to the sockaddr struct to update with the address.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_getpeername (struct HyPortLibrary * portLibrary, hysocket_t handle,
+		    hysockaddr_t addrHandle)
+{
+  I_32 rc = 0;
+  I_32 addrlen = sizeof (addrHandle->addr);
+
+  if (handle->flags & SOCKET_IPV4_OPEN_MASK
+      || !(handle->flags & SOCKET_IPV6_OPEN_MASK))
+    {
+      rc =
+	getpeername (handle->ipv4, (struct sockaddr *) &addrHandle->addr,
+		     &addrlen);
+    }
+  else
+    {
+      rc =
+	getpeername (handle->ipv6, (struct sockaddr *) &addrHandle->addr,
+		     &addrlen);
+    }
+
+  if (rc != 0)
+    {
+      rc = WSAGetLastError ();
+      HYSOCKDEBUG ("<getpeername failed, err=%d>\n", rc);
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_NOTBOUND);
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_getsockname
+/**
+ * Answer the local name for the socket.  Note, the stack getsockname function
+ * actually answers a sockaddr structure, not a string name as the function name
+ * might imply.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the socket to get the address of.
+ * @param[out] addrHandle Pointer to the sockaddr struct to update with the address.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_getsockname (struct HyPortLibrary * portLibrary, hysocket_t handle,
+		    hysockaddr_t addrHandle)
+{
+  I_32 rc = 0;
+  I_32 addrlen = sizeof (addrHandle->addr);
+
+  if (handle->flags & SOCKET_IPV4_OPEN_MASK
+      || !(handle->flags & SOCKET_IPV6_OPEN_MASK))
+    {
+      rc =
+	getsockname (handle->ipv4, (struct sockaddr *) &addrHandle->addr,
+		     &addrlen);
+    }
+  else
+    {
+      rc =
+	getsockname (handle->ipv6, (struct sockaddr *) &addrHandle->addr,
+		     &addrlen);
+    }
+
+  if (rc != 0)
+    {
+      rc = WSAGetLastError ();
+      HYSOCKDEBUG ("<getsockname failed, err=%d>\n", rc);
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_NOTBOUND);
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+
+  /* if both sockets are open we cannot retun the address for either one as whichever one we return it is wrong in some 
+     cases. Therefore,  we reset the address to the ANY address and leave the port as is as it should be the same
+     for both sockets (bind makes sure that when we open the two sockets we use the same port */
+  if ((handle->flags & SOCKET_IPV4_OPEN_MASK)
+      && (handle->flags & SOCKET_IPV6_OPEN_MASK))
+    {
+      /* we know the address is any IPv4 as the IPv4 socket was used if both were open */
+      ((struct sockaddr_in *) &addrHandle->addr)->sin_addr.S_un.S_addr = 0;
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_hostent_addrlist
+/**
+ * Answer the nominated element of the address list within the argument hostent struct.
+ * The address is in network order.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the hostent struct, in which to access the addr_list.
+ * @param[in] index The index of the element within the addr_list to retrieve.
+ *
+ * @return	the address, in network order.
+ */
+I_32 VMCALL
+hysock_hostent_addrlist (struct HyPortLibrary * portLibrary,
+			 hyhostent_t handle, U_32 index)
+{
+  return *((I_32 *) handle->entity->h_addr_list[index]);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_hostent_aliaslist
+/**
+ * Answer a reference to the list of alternative names for the host within the argument hostent struct.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the hostent struct, in which to access the addr_list
+ * @param[out] aliasList Pointer to the list of alternative names, to be updated 
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code
+ */
+I_32 VMCALL
+hysock_hostent_aliaslist (struct HyPortLibrary * portLibrary,
+			  hyhostent_t handle, char ***aliasList)
+{
+  *aliasList = handle->entity->h_addr_list;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_hostent_hostname
+/**
+ * Answer the host name (string) within the argument hostent struct.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the hostent struct, in which to access the hostName.
+ * @param[out] hostName Host name string.
+ *
+ * @return	0, the function does not validate the name access.
+ */
+I_32 VMCALL
+hysock_hostent_hostname (struct HyPortLibrary * portLibrary,
+			 hyhostent_t handle, char **hostName)
+{
+  *hostName = handle->entity->h_name;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_htonl
+/**
+ * Answer the 32 bit host ordered argument, in network byte order.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] val The 32 bit host ordered number.
+ *
+ * @return	the 32 bit network ordered number.
+ */
+I_32 VMCALL
+hysock_htonl (struct HyPortLibrary * portLibrary, I_32 val)
+{
+  return htonl (val);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_htons
+/**
+ * Answer the 16 bit host ordered argument, in network byte order.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] val The 16 bit host ordered number.
+ *
+ * @return	the 16 bit network ordered number.
+ */
+U_16 VMCALL
+hysock_htons (struct HyPortLibrary * portLibrary, U_16 val)
+{
+  return htons (val);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_inetaddr
+/**
+ * Answer the dotted IP string as an Internet address.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[out] addrStr The dotted IP string.
+ * @param[in] addr Pointer to the Internet address.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_inetaddr (struct HyPortLibrary * portLibrary, char *addrStr,
+		 U_32 * addr)
+{
+  I_32 rc = 0;
+  U_32 val;
+
+  val = inet_addr (addrStr);
+  if (INADDR_NONE == val)
+    {
+      HYSOCKDEBUGPRINT ("<inet_addr failed>\n");
+      rc = HYPORT_ERROR_SOCKET_ADDRNOTAVAIL;
+    }
+  else
+    {
+      *addr = val;
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_inetntoa
+/**
+ * Answer the Internet address as a dotted IP string.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[out] addrStr The dotted IP string.
+ * @param[in] nipAddr The Internet address.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_inetntoa (struct HyPortLibrary * portLibrary, char **addrStr,
+		 U_32 nipAddr)
+{
+  I_32 rc = 0;
+  char *val;
+  struct in_addr addr;
+  addr.s_addr = nipAddr;
+  val = inet_ntoa (addr);
+  if (NULL == val)
+    {
+      HYSOCKDEBUGPRINT ("<inet_ntoa failed>\n");
+      rc = HYPORT_ERROR_SOCKET_ADDRNOTAVAIL;
+    }
+  else
+    {
+      *addrStr = val;
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_ipmreq_init
+/**
+ * Initializes a new multicast membership structure.  The membership structure is used to join & leave
+ * multicast groups @see hysock_setopt_ipmreq.  The group may be joined using 0 (HYSOCK_INADDR_ANY)
+ * as the local interface, in which case the default local address will be used.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[out] handle Pointer to the multicast membership struct.
+ * @param[in] nipmcast The address, in network order, of the multicast group to join.
+ * @param[in] nipinterface The address, in network order, of the local machine interface to join on.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_ipmreq_init (struct HyPortLibrary * portLibrary, hyipmreq_t handle,
+		    U_32 nipmcast, U_32 nipinterface)
+{
+  memset (handle, 0, sizeof (struct hyipmreq_struct));
+  handle->addrpair.imr_multiaddr.s_addr = nipmcast;
+  handle->addrpair.imr_interface.s_addr = nipinterface;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_ipv6_mreq_init
+/**
+ * Fills in a preallocated hyipv6_mreq_struct
+ *
+ * @param[in] portLibrary The port library.
+ * @param[out] handle A pointer to the hyipv6_mreq_struct to populate.
+ * @param[in] ipmcast_addr The ip mulitcast address.
+ * @param[in] ipv6mr_interface The ip mulitcast inteface.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ *
+ * @note Added for IPv6 support.
+ */
+I_32 VMCALL
+hysock_ipv6_mreq_init (struct HyPortLibrary * portLibrary,
+		       hyipv6_mreq_t handle, U_8 * ipmcast_addr,
+		       U_32 ipv6mr_interface)
+{
+  memset (handle, 0, sizeof (struct hyipmreq_struct));
+  memcpy (handle->mreq.ipv6mr_multiaddr.u.Byte, ipmcast_addr, 16);
+  handle->mreq.ipv6mr_interface = ipv6mr_interface;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_linger_enabled
+/**
+ * Answer true if the linger is enabled in the argument linger struct.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the linger struct to be accessed.
+ * @param[out] enabled Pointer to the boolean to be updated with the linger status.
+ *
+ * @return	0, the function does not validate the access.
+ */
+I_32 VMCALL
+hysock_linger_enabled (struct HyPortLibrary * portLibrary, hylinger_t handle,
+		       BOOLEAN * enabled)
+{
+  *enabled = (BOOLEAN) (handle->linger.l_onoff);
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_linger_init
+/**
+ * Initializes a new linger structure, enabled or disabled, with the timeout as specified.
+ * Linger defines the behavior when unsent messages exist for a socket that has been sent close.
+ * If linger is disabled, the default, close returns immediately and the stack attempts to deliver unsent messages.
+ * If linger is enabled:
+ * \arg if the timeout is 0, the close will block indefinitely until the messages are sent
+ * \arg if the timeout is set, the close will return after the messages are sent or the timeout period expired
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the linger struct to be accessed.
+ * @param[in] enabled Aero to disable, a non-zero value to enable linger.
+ * @param[in] timeout	 0 to linger indefinitely or a positive timeout value (in seconds).
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+I_32 VMCALL
+hysock_linger_init (struct HyPortLibrary * portLibrary, hylinger_t handle,
+		    I_32 enabled, U_16 timeout)
+{
+  memset (handle, 0, sizeof (struct hylinger_struct));
+  handle->linger.l_onoff = enabled;
+  handle->linger.l_linger = timeout;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_linger_linger
+/**
+ * Answer the linger timeout value in the argument linger struct.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Pointer to the linger struct to be accessed.
+ * @param[out] linger Pointer to the integer, to be updated with the linger value (in seconds).
+ *
+ * @return	0, the function does not validate the access.
+ */
+I_32 VMCALL
+hysock_linger_linger (struct HyPortLibrary * portLibrary, hylinger_t handle,
+		      U_16 * linger)
+{
+  *linger = handle->linger.l_linger;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_listen
+/**
+ * Set the socket to listen for incoming connection requests.  This call is made prior to accepting requests,
+ * via the @ref hysock_accept function.  The backlog specifies the maximum length of the queue of pending connections,
+ * after which further requests are rejected.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] sock Pointer to the socket to modify.
+ * @param[in] backlog The maximum number of queued requests.
+ *
+ * @return	0, if no errors occurred, otherwise the (negative) error code.
+ */
+/*IPv6 - If both the IPv4 and IPv6 sockets are still open, then we need to listen on both of them.  
+ */
+I_32 VMCALL
+hysock_listen (struct HyPortLibrary * portLibrary, hysocket_t sock,
+	       I_32 backlog)
+{
+  I_32 rc = 0;
+
+  /* Listen on the IPv4 socket */
+  if (sock->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      if (listen (sock->ipv4, backlog) == SOCKET_ERROR)
+	{
+	  rc = WSAGetLastError ();
+	  HYSOCKDEBUG ("<listen failed, err=%d>\n", rc);
+	  switch (rc)
+	    {
+	    case WSAEINVAL:
+	      rc =
+		portLibrary->error_set_last_error (portLibrary, rc,
+						   HYPORT_ERROR_SOCKET_BOUNDORCONN);
+	      break;
+	    default:
+	      rc =
+		portLibrary->error_set_last_error (portLibrary, rc,
+						   findError (rc));
+	    }
+	}
+    }
+
+  /* Listen on the IPv6 socket providing our return code is good */
+  if (sock->flags & SOCKET_IPV6_OPEN_MASK && rc == 0)
+    {
+      if (listen (sock->ipv6, backlog) == SOCKET_ERROR)
+	{
+	  rc = WSAGetLastError ();
+	  HYSOCKDEBUG ("<listen failed, err=%d>\n", rc);
+	  switch (rc)
+	    {
+	    case WSAEINVAL:
+	      rc =
+		portLibrary->error_set_last_error (portLibrary, rc,
+						   HYPORT_ERROR_SOCKET_BOUNDORCONN);
+	      break;
+	    default:
+	      rc =
+		portLibrary->error_set_last_error (portLibrary, rc,
+						   findError (rc));
+	    }
+	}
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_ntohl
+/**
+ * Answer the 32 bit network ordered argument, in host byte order.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] val The 32 bit network ordered number.
+ *
+ * @return	the 32 bit host ordered number.
+ */
+I_32 VMCALL
+hysock_ntohl (struct HyPortLibrary * portLibrary, I_32 val)
+{
+  return ntohl (val);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_ntohs
+/**
+ * Answer the 16-bit network ordered argument, in host byte order.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] val The 16-bit network ordered number.
+ *
+ * @return	the 16-bit host ordered number.
+ */
+U_16 VMCALL
+hysock_ntohs (struct HyPortLibrary * portLibrary, U_16 val)
+{
+  return ntohs (val);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_read
+/**
+ * The read function receives data from a connected socket.  Calling read will return as much 
+ *	information as is currently available up to the size of the buffer supplied. If no incoming 
+ * data is available at the socket, the read call blocks and waits for data to arrive.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] sock Pointer to the socket to read on
+ * @param[out] buf Pointer to the buffer where input bytes are written
+ * @param[in] nbyte The length of buf
+ * @param[in] flags The flags, to influence this read (in addition to the socket options)
+ *
+ * @return
+ * \arg If no error occurs, return the number of bytes received.
+ * \arg If the connection has been gracefully closed, return 0.
+ * \arg Otherwise return the (negative) error code.
+ */
+I_32 VMCALL
+hysock_read (struct HyPortLibrary * portLibrary, hysocket_t sock, U_8 * buf,
+	     I_32 nbyte, I_32 flags)
+{
+  I_32 rc = 0;
+  I_32 bytesRec = 0;
+  int socketTypeLen = sizeof (DWORD);
+
+  if (sock->flags & SOCKET_USE_IPV4_MASK
+      || !(sock->flags & SOCKET_IPV6_OPEN_MASK))
+    {
+      bytesRec = recv (sock->ipv4, (char *) buf, nbyte, flags);
+    }
+  else
+    {				/* If IPv6 is open */
+      bytesRec = recv (sock->ipv6, (char *) buf, nbyte, flags);
+    }
+
+  if (SOCKET_ERROR == bytesRec)
+    {
+      rc = WSAGetLastError ();
+      HYSOCKDEBUG ("<recv failed, err=%d>\n", rc);
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_NOTBOUND);
+	case WSAEMSGSIZE:
+	  rc =
+	    portLibrary->error_set_last_error (portLibrary, rc, WSAEMSGSIZE);
+	  if (flags == MSG_PEEK)
+	    {
+	      return nbyte;
+	    }
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+  else
+    {
+      rc = bytesRec;
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_readfrom
+/**
+ * The read function receives data from a possibly connected socket.  Calling read will return as much 
+ * information as is currently available up to the size of the buffer supplied.  If the information is too large
+ * for the buffer, the excess will be discarded.  If no incoming  data is available at the socket, the read call 
+ * blocks and waits for data to arrive.  It the address argument is not null, the address will be updated with
+ * address of the message sender.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] sock Pointer to the socket to read on.
+ * @param[out] buf Pointer to the buffer where input bytes are written.
+ * @param[in] nbyte The length of buf.
+ * @param[in] flags Tthe flags, to influence this read.
+ * @param[out] addrHandle	if provided, the address to be updated with the sender information.
+ *
+ * @return
+ * \arg If no error occurs, return the number of bytes received.
+ * \arg If the connection has been gracefully closed, return 0.
+ * \arg Otherwise return the (negative) error code.
+ */
+I_32 VMCALL
+hysock_readfrom (struct HyPortLibrary * portLibrary, hysocket_t sock,
+		 U_8 * buf, I_32 nbyte, I_32 flags, hysockaddr_t addrHandle)
+{
+  I_32 rc = 0;
+  I_32 bytesRec = 0;
+  I_32 addrlen;
+  if (NULL == addrHandle)
+    {
+      addrlen = sizeof (*addrHandle);
+
+      if (sock->flags & SOCKET_USE_IPV4_MASK
+	  || !(sock->flags & SOCKET_IPV6_OPEN_MASK))
+	{
+	  bytesRec =
+	    recvfrom (sock->ipv4, (char *) buf, nbyte, flags,
+		      (struct sockaddr *) NULL, &addrlen);
+	}
+      else
+	{			/* If IPv6 is open */
+	  bytesRec =
+	    recvfrom (sock->ipv6, (char *) buf, nbyte, flags,
+		      (struct sockaddr *) NULL, &addrlen);
+	}
+    }
+  else
+    {
+      addrlen = sizeof (addrHandle->addr);
+      if (sock->flags & SOCKET_USE_IPV4_MASK
+	  || !(sock->flags & SOCKET_IPV6_OPEN_MASK))
+	{
+	  ((OSSOCKADDR *) & addrHandle->addr)->sin_family = OS_AF_INET4;
+	  bytesRec =
+	    recvfrom (sock->ipv4, (char *) buf, nbyte, flags,
+		      (struct sockaddr *) &addrHandle->addr, &addrlen);
+	}
+      else
+	{			/* If IPv6 is open */
+	  ((OSSOCKADDR *) & addrHandle->addr)->sin_family = OS_AF_INET6;
+	  bytesRec =
+	    recvfrom (sock->ipv6, (char *) buf, nbyte, flags,
+		      (struct sockaddr *) &addrHandle->addr, &addrlen);
+	}
+    }
+  if (SOCKET_ERROR == bytesRec)
+    {
+      rc = WSAGetLastError ();
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_NOTBOUND);
+	case WSAEMSGSIZE:
+	  rc =
+	    portLibrary->error_set_last_error (portLibrary, rc, WSAEMSGSIZE);
+	  return nbyte;
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+  else
+    {
+      rc = bytesRec;
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_select
+/**
+ * The select function allows the state of sockets for read & write operations and exceptional conditions to be tested.
+ * The function is used prior to a hysock_read/readfrom, to control the period the operation may block for.
+ * Depending upon the timeout specified:
+ * \arg 0, return immediately with the status of the descriptors
+ * \arg timeout, return when one of the descriptors is ready or after the timeout period has expired
+ * \arg null, block indefinitely for a ready descriptor
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] nfds Maximum number of file descriptors to be tested.
+ * @param[in] readfds Tthe set of descriptors to be checked if ready for read operations.
+ * @param[in] writefds The set of descriptors to be checked if ready for write operations.
+ * @param[in] exceptfds The set of descriptors to be checked for exceptional conditions.
+ * @param[in] timeout Pointer to the timeout (a hytimeval struct).
+ *
+ * @return	0 if no error occurs, otherwise return the (negative) error code.
+ */
+I_32 VMCALL
+hysock_select (struct HyPortLibrary * portLibrary, I_32 nfds,
+	       hyfdset_t readfds, hyfdset_t writefds, hyfdset_t exceptfds,
+	       hytimeval_t timeout)
+{
+  I_32 rc = 0;
+  I_32 result = 0;
+
+  if (NULL == timeout)
+    {
+      result =
+	select (nfds, &readfds->handle, &writefds->handle, &exceptfds->handle,
+		NULL);
+    }
+  else
+    {
+      result =
+	select (nfds, &readfds->handle, &writefds->handle, &exceptfds->handle,
+		&timeout->time);
+    }
+  if (SOCKET_ERROR == result)
+    {
+      rc = WSAGetLastError ();
+      HYSOCKDEBUG ("<select failed, err=%d>\n", rc);
+      switch (rc)
+	{
+	case WSAEINVAL:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    HYPORT_ERROR_SOCKET_INVALIDTIMEOUT);
+	default:
+	  return portLibrary->error_set_last_error (portLibrary, rc,
+						    findError (rc));
+	}
+    }
+  else
+    {
+      if (0 == result)
+	{
+	  rc = HYPORT_ERROR_SOCKET_TIMEOUT;
+	}
+      else
+	{
+	  rc = result;
+	}
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_select_read
+/**
+ * A helper method, to ensure a read operation can be performed without blocking.
+ * The portable version of a read operation is a blocking call (will wait indefinitely for data).
+ * This function should be called prior to a read operation, to provide a read timeout.
+ * If the result is 1, the caller is guaranteed to be able to complete a read on the socket without blocking.
+ * The actual contents of the fdset are not available for inspection (as provided in the more general 'select' function).
+ * The timeout is specified in seconds and microseconds.
+ * If the timeout is 0, skip this function (and thus the caller of a subsequent read operation may block).
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] hysocketP Pointer to the hysocket to query for available read data.
+ * @param[in] secTime The integer component of the timeout periond, in seconds.
+ * @param[in] uSecTime The fractional component of the timeout period, in microSeconds.
+ * @param[in] accept Set to true when called for an accept(), false when called for a read()
+ *
+ * @return
+ * \arg 1, if there is data available to read at the socket
+ * \arg HYPORT_ERROR_SOCKET_TIMEOUT if the call timed out
+ * \arg otherwise return the (negative) error code.
+ */
+/* IPv6 - If both IPv4 and IPv6 sockets are open, the call to this function will alternate selecting between the sockets.
+ */
+I_32 VMCALL
+hysock_select_read (struct HyPortLibrary * portLibrary, hysocket_t hysocketP,
+		    I_32 secTime, I_32 uSecTime, BOOLEAN accept)
+{
+  hytimeval_struct timeP;
+  I_32 result = 0;
+  I_32 size = 0;
+  PortlibPTBuffers_t ptBuffers;
+
+  ptBuffers = hyport_tls_get (portLibrary);
+  if (NULL == ptBuffers)
+    {
+      return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+    }
+
+/* The max fdset size per process is always expected to be less than a 32bit integer value.
+ * Is this valid on a 64bit platform?
+ */
+
+  if (0 == secTime && 0 == uSecTime)
+    {
+      /* add these checks, so that if only one socket is open return right away and avoid the loop below */
+      if (((hysocketP->flags & SOCKET_IPV4_OPEN_MASK) != 0)
+	  && ((hysocketP->flags & SOCKET_IPV6_OPEN_MASK) == 0))
+	{
+	  hysocketP->flags = hysocketP->flags | SOCKET_USE_IPV4_MASK;
+	  /* return value of 1 means there is data to be read */
+	  return 1;
+	}
+      else if (((hysocketP->flags & SOCKET_IPV6_OPEN_MASK) != 0)
+	       && ((hysocketP->flags & SOCKET_IPV4_OPEN_MASK) == 0))
+	{
+	  hysocketP->flags = hysocketP->flags & ~SOCKET_USE_IPV4_MASK;
+	  /* return value of 1 means there is data to be read */
+	  return 1;
+	}
+      /* poll every 100 ms */
+      hysock_timeval_init (portLibrary, 0, 100 * 1000, &timeP);
+    }
+  else
+    {
+      hysock_timeval_init (portLibrary, secTime, uSecTime, &timeP);
+    }
+
+  while (0 == 0)
+    {
+      result = hysock_fdset_init (portLibrary, hysocketP);
+      if (0 != result)
+	{
+	  return result;
+	}
+      size = hysock_fdset_size (portLibrary, hysocketP);
+      if (0 > size)
+	{
+	  result = HYPORT_ERROR_SOCKET_FDSET_SIZEBAD;
+	}
+      else
+	{
+	  result =
+	    hysock_select (portLibrary, size, ptBuffers->fdset, NULL, NULL,
+			   &timeP);
+	}
+      /* break out of the loop if we should not be looping (timeout is zero) or
+       * if an error occured or data ready to be read */
+      if ((HYPORT_ERROR_SOCKET_TIMEOUT != result) || (0 != secTime)
+	  || (0 != uSecTime))
+	{
+	  /* check which socket has activity after select call and set the appropriate flags */
+	  if (FD_ISSET (hysocketP->ipv6, ptBuffers->fdset))
+	    {
+	      hysocketP->flags = hysocketP->flags & ~SOCKET_USE_IPV4_MASK;
+	    }
+	  /* update IPv4 last, so it will be used in the event both sockets had activity */
+	  if (FD_ISSET (hysocketP->ipv4, ptBuffers->fdset))
+	    {
+	      hysocketP->flags = hysocketP->flags | SOCKET_USE_IPV4_MASK;
+	    }
+
+	  break;
+	}
+    }
+  return result;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysock_set_nonblocking
+/**
+ * Set the nonblocking state of the socket.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] socketP Pointer to the socket to read on
+ * @param[in] nonblocking Set true for nonblocking, false for blocking
+ *
+ * @return	0 if no error occurs, otherwise return the (negative) error code.
+ */
+I_32 VMCALL
+hysock_set_nonblocking (struct HyPortLibrary * portLibrary,
+			hysocket_t socketP, BOOLEAN nonblocking)
+{
+  I_32 rc;
+  U_32 param = nonblocking;
+
+  /* If both the IPv4 and IPv6 socket are open then we want to set the option on both.  If only one is open,
+     then we set it just on that one.  */
+
+  if (socketP->flags & SOCKET_IPV4_OPEN_MASK)
+    {
+      rc = ioctlsocket (socketP->ipv4, FIONBIO, &param);
+    }
+

[... 2267 lines stripped ...]