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 [159/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/linux.IA32/port/hysock.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysock.c?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysock.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysock.c Wed Nov 30 21:29:27 2005
@@ -0,0 +1,5209 @@
+/* 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 "hymutex.h"
+#include "portpriv.h"
+#include "hyportptb.h"
+#include <fcntl.h>
+#include <string.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h> /* for struct in_addr */
+#include <sys/ioctl.h>
+#include <net/if.h> /* for struct ifconf */
+
+#if defined(LINUX)
+#define IPV6_FLOWINFO_SEND 33
+#if defined(HARDHAT)
+#else
+#define HAS_RTNETLINK 1
+#endif
+#endif
+
+#if defined(HAS_RTNETLINK)
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+typedef struct linkReq_struct
+{
+ struct nlmsghdr netlinkHeader;
+ struct ifinfomsg msg;
+} linkReq_struct;
+typedef struct addrReq_struct
+{
+ struct nlmsghdr netlinkHeader;
+ struct ifaddrmsg msg;
+} addrReq_struct;
+#define NETLINK_DATA_BUFFER_SIZE 1024
+#define NETLINK_READTIMEOUT_SECS 20
+typedef struct netlinkContext_struct
+{
+ int netlinkSocketHandle;
+ char buffer[NETLINK_DATA_BUFFER_SIZE];
+ struct nlmsghdr *netlinkHeader;
+ U_32 remainingLength;
+ U_32 done;
+} netlinkContext_struct;
+#else
+/* need something so that functions still compile */
+typedef struct netlinkContext_struct
+{
+ int netlinkSocketHandle;
+} netlinkContext_struct;
+typedef struct nlmsghdr
+{
+ int length;
+};
+#endif
+
+#define INVALID_SOCKET (hysocket_t) -1
+
+/* these platforms include a colon in aliases so additional tests are required */
+
+/* The platforms that do not define the standard type socklen_t seem to all want an int in the socket calls */
+
+/*the number of times to retry a gethostby* call if the return code is TRYAGAIN*/
+#define MAX_RETRIES 50
+
+#if NO_R
+/*use a mutex if the gethostbyaddr, gethostbyname calls are not threadsafe*/
+MUTEX hostentLock = PTHREAD_MUTEX_INITIALIZER;
+#endif /*NO_R */
+
+#define VALIDATE_ALLOCATIONS 1
+
+/* needed for connect_with_timeout */
+typedef struct selectFDSet_struct
+{
+ int nfds;
+ int sock;
+ fd_set writeSet;
+ fd_set readSet;
+ fd_set exceptionSet;
+} selectFDSet_strut;
+
+#define CDEV_CURRENT_FUNCTION _prototypes_private
+
+I_32 platformSocketOption (I_32 portableSocketOption);
+
+I_32 initNetlinkContext (struct HyPortLibrary *portLibrary,
+ I_32 netlinkSocketHandle,
+ struct netlinkContext_struct *netlinkContext);
+
+I_32 getNextNetlinkMsg (struct HyPortLibrary *portLibrary,
+ struct netlinkContext_struct *netlinkContext,
+ struct nlmsghdr **nextMessage);
+
+static I_32 copy_hostent (struct HyPortLibrary *portLibrary,
+ OSHOSTENT * source, PortlibPTBuffers_t * ptBuffers);
+
+I_32 platformSocketLevel (I_32 portableSocketLevel);
+
+static I_32 findError (I_32 errorCode);
+
+I_32 map_protocol_family_Hy_to_OS (I_32 addr_family);
+
+I_32 map_addr_family_Hy_to_OS (I_32 addr_family);
+
+I_32 map_sockettype_Hy_to_OS (I_32 socket_type);
+
+static I_32 findHostError (int herr);
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION copy_hostent
+
+static I_32
+copy_hostent (struct HyPortLibrary *portLibrary, OSHOSTENT * source,
+ PortlibPTBuffers_t * ptBuffers)
+{
+#if NO_R
+ int h_len = strlen (source->h_name);
+ int total = 0;
+ int i = 0;
+ char *buffer;
+ OSHOSTENT *dest = &(*ptBuffers)->hostent;
+ /* add trailing NULL, and round off to nearest pointer size */
+ h_len = (h_len + 1 + sizeof (void *)) & ~(sizeof (void *) - 1);
+ while (source->h_addr_list[i])
+ i++;
+ total = h_len + ((i + 2) * sizeof (void *)) + (i * sizeof (U_32));
+ if (!(*ptBuffers)->gethostBuffer || (*ptBuffers)->gethostBufferSize < total)
+ {
+ (*ptBuffers)->gethostBuffer =
+ portLibrary->mem_allocate_memory (portLibrary, total);
+ if (!(*ptBuffers)->gethostBuffer)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ (*ptBuffers)->gethostBufferSize = total;
+ }
+ buffer = (*ptBuffers)->gethostBuffer;
+ dest->h_name = buffer;
+ strcpy (buffer, source->h_name);
+ buffer += h_len;
+ dest->h_aliases = (void *) buffer;
+ *((void **) buffer) = NULL;
+ buffer += sizeof (void *);
+ dest->h_addrtype = source->h_addrtype;
+ dest->h_length = source->h_length;
+ dest->h_addr_list = (void *) buffer;
+ buffer += (i + 1) * sizeof (void *);
+ i = 0;
+ while (source->h_addr_list[i])
+ {
+ dest->h_addr_list[i] = (void *) buffer;
+ *((U_32 *) buffer) = *((U_32 *) source->h_addr_list[i]);
+ buffer += sizeof (U_32);
+ i++;
+ }
+ dest->h_addr_list[i] = NULL;
+
+#endif
+
+ 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 HYPORT_ERROR_SOCKET_UNIX_EBADF:
+ return HYPORT_ERROR_SOCKET_BADDESC;
+ case HYPORT_ERROR_SOCKET_UNIX_ENOBUFS:
+ return HYPORT_ERROR_SOCKET_NOBUFFERS;
+ case HYPORT_ERROR_SOCKET_UNIX_EOPNOTSUP:
+ return HYPORT_ERROR_SOCKET_OPNOTSUPP;
+ case HYPORT_ERROR_SOCKET_UNIX_ENOPROTOOPT:
+ return HYPORT_ERROR_SOCKET_OPTUNSUPP;
+ case HYPORT_ERROR_SOCKET_UNIX_EINVAL:
+ return HYPORT_ERROR_SOCKET_SOCKLEVELINVALID;
+ case HYPORT_ERROR_SOCKET_UNIX_ENOTSOCK:
+ return HYPORT_ERROR_SOCKET_NOTSOCK;
+ case HYPORT_ERROR_SOCKET_UNIX_EINTR:
+ return HYPORT_ERROR_SOCKET_INTERRUPTED;
+ case HYPORT_ERROR_SOCKET_UNIX_ENOTCONN:
+ return HYPORT_ERROR_SOCKET_NOTCONNECTED;
+ case HYPORT_ERROR_SOCKET_UNIX_EAFNOSUPPORT:
+ return HYPORT_ERROR_SOCKET_BADAF;
+ /* note: HYPORT_ERROR_SOCKET_UNIX_ECONNRESET not included because it has the same
+ * value as HYPORT_ERROR_SOCKET_UNIX_CONNRESET and they both map to HYPORT_ERROR_SOCKET_CONNRESET */
+ case HYPORT_ERROR_SOCKET_UNIX_CONNRESET:
+ return HYPORT_ERROR_SOCKET_CONNRESET;
+ case HYPORT_ERROR_SOCKET_UNIX_EAGAIN:
+ return HYPORT_ERROR_SOCKET_WOULDBLOCK;
+ case HYPORT_ERROR_SOCKET_UNIX_EPROTONOSUPPORT:
+ return HYPORT_ERROR_SOCKET_BADPROTO;
+ case HYPORT_ERROR_SOCKET_UNIX_EFAULT:
+ return HYPORT_ERROR_SOCKET_ARGSINVALID;
+ case HYPORT_ERROR_SOCKET_UNIX_ETIMEDOUT:
+ return HYPORT_ERROR_SOCKET_TIMEOUT;
+ case HYPORT_ERROR_SOCKET_UNIX_CONNREFUSED:
+ return HYPORT_ERROR_SOCKET_CONNECTION_REFUSED;
+ case HYPORT_ERROR_SOCKET_UNIX_ENETUNREACH:
+ return HYPORT_ERROR_SOCKET_ENETUNREACH;
+ case HYPORT_ERROR_SOCKET_UNIX_EACCES:
+ return HYPORT_ERROR_SOCKET_EACCES;
+ default:
+ return HYPORT_ERROR_SOCKET_OPFAILED;
+ }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION findHostError
+
+/**
+ * @internal Determines the proper portable error code to return given a native host error code
+ *
+ * @return the (negative) error code
+ */
+static I_32
+findHostError (int herr)
+{
+ switch (herr)
+ {
+ case HYPORT_ERROR_SOCKET_UNIX_NORECOVERY:
+ return HYPORT_ERROR_SOCKET_NORECOVERY;
+ case HYPORT_ERROR_SOCKET_UNIX_HOSTNOTFOUND:
+ return HYPORT_ERROR_SOCKET_HOSTNOTFOUND;
+ case HYPORT_ERROR_SOCKET_UNIX_NODATA:
+ return HYPORT_ERROR_SOCKET_NODATA;
+ case HYPORT_ERROR_SOCKET_UNIX_TRYAGAIN:
+ return HYPORT_ERROR_SOCKET_INTERRUPTED;
+ default:
+ return HYPORT_ERROR_SOCKET_BADSOCKET;
+ }
+}
+
+#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 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 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 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.
+ */
+/**
+ * @internal Map the portable to the platform socket level. Used to resolve the arguments of socket option functions.
+ * Levels currently in use are:
+ * SOL_SOCKET, for most options
+ * IPPROTO_TCP, for the TCP noDelay option
+ * IPPROTO_IP, for the option operations associated with multicast (join, drop, interface)
+ *
+ * @param portlib pointer to the VM port library
+ * @param portableSocketLevel the portable socket level to convert
+ *
+ * @return the platform socket level or an error 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;
+#if defined(IPv6_FUNCTION_SUPPORT)
+ case HY_IPPROTO_IPV6:
+ return OS_IPPROTO_IPV6;
+#endif
+
+ }
+ 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.
+ */
+/**
+ * @internal Map the portable to the platform socket options. Used to resolve the arguments of socket option functions.
+ * Options currently in supported are:
+ * SOL_LINGER, the linger timeout
+ * TCP_NODELAY, the buffering scheme implementing Nagle's algorithm
+ * IP_MULTICAST_TTL, the packet Time-To-Live
+ * IP_ADD_MEMBERSHIP, to join a multicast group
+ * IP_DROP_MEMBERSHIP, to leave a multicast group
+ * IP_MULTICAST_IF, the multicast interface
+ *
+ * @param portlib pointer to the VM port library
+ * @param portableSocketOption the portable socket option to convert
+ *
+ * @return the platform socket option or an error if no equivalent option exists
+ */
+/* Support datagram broadcasts */
+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_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;
+#if defined(IPv6_FUNCTION_SUPPORT)
+ 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;
+#endif
+
+ }
+ return HYPORT_ERROR_SOCKET_OPTUNSUPP;
+}
+
+#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.,
+ */
+I_32 VMCALL
+hysock_accept (struct HyPortLibrary * portLibrary, hysocket_t serverSock,
+ hysockaddr_t addrHandle, hysocket_t * sockHandle)
+{
+#if defined(LINUX)
+#define ACCEPTCAST (socklen_t *)
+#else
+#define ACCEPTCAST
+#endif
+
+ I_32 rc = 0;
+ int sc;
+ socklen_t fromlen = sizeof (addrHandle->addr);
+
+ *sockHandle = INVALID_SOCKET;
+
+ sc =
+ accept (SOCKET_CAST (serverSock), (struct sockaddr *) &addrHandle->addr,
+ ACCEPTCAST & fromlen);
+ if (sc < 0)
+ {
+ rc = errno;
+ HYSOCKDEBUG ("<accept failed, err=%d>\n", rc);
+ rc =
+ portLibrary->error_set_last_error (portLibrary, rc,
+ HYPORT_ERROR_SOCKET_ADDRNOTAVAIL);
+ }
+
+ if (rc == 0)
+ {
+ *sockHandle =
+ portLibrary->mem_allocate_memory (portLibrary,
+ sizeof (struct hysocket_struct));
+#if (defined(VALIDATE_ALLOCATIONS))
+ if (*sockHandle == NULL)
+ {
+ close (sc);
+ *sockHandle = INVALID_SOCKET;
+ return HYPORT_ERROR_SOCKET_NOBUFFERS;
+ }
+#endif
+
+ SOCKET_CAST (*sockHandle) = sc;
+ (*sockHandle)->family = serverSock->family;
+ }
+ return rc;
+}
+
+#undef ACCEPTCAST
+
+#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,
+ */
+I_32 VMCALL
+hysock_bind (struct HyPortLibrary * portLibrary, hysocket_t sock,
+ hysockaddr_t addr)
+{
+ I_32 rc = 0;
+ I_32 length = sizeof (addr->addr);
+
+#if defined(SIN6_LEN)
+ length = sizeof (struct sockaddr_storage);
+#if defined(IPv6_FUNCTION_SUPPORT)
+ if (((OSSOCKADDR *) & addr->addr)->sin_family == OS_AF_INET6)
+ {
+ length = ((OSSOCKADDR_IN6 *) & addr->addr)->sin6_len;
+ }
+#endif
+#endif
+
+ if (bind
+ (SOCKET_CAST (sock), (struct sockaddr *) &addr->addr,
+ sizeof (addr->addr)) < 0)
+ {
+ rc = errno;
+ HYSOCKDEBUG ("<bind failed, err=%d>\n", rc);
+ rc =
+ portLibrary->error_set_last_error (portLibrary, rc,
+ HYPORT_ERROR_SOCKET_ADDRNOTAVAIL);
+ }
+ 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 rc = 0;
+
+ if ((*sock == INVALID_SOCKET) || (close (SOCKET_CAST (*sock)) < 0))
+ {
+ rc = errno;
+ HYSOCKDEBUG ("<closesocket failed, err=%d>\n", rc);
+ rc =
+ portLibrary->error_set_last_error (portLibrary, rc,
+ HYPORT_ERROR_SOCKET_BADSOCKET);
+ }
+
+ if (*sock != INVALID_SOCKET)
+ {
+ portLibrary->mem_free_memory (portLibrary, *sock);
+ }
+ *sock = INVALID_SOCKET;
+ return rc;
+}
+
+#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.
+ */
+I_32 VMCALL
+hysock_connect (struct HyPortLibrary * portLibrary, hysocket_t sock,
+ hysockaddr_t addr)
+{
+ I_32 rc = 0;
+
+ if (connect
+ (SOCKET_CAST (sock), (struct sockaddr *) &addr->addr,
+ sizeof (addr->addr)) < 0)
+ {
+ rc = errno;
+ HYSOCKDEBUG ("<connect failed, err=%d>\n", rc);
+ rc =
+ portLibrary->error_set_last_error (portLibrary, rc,
+ HYPORT_ERROR_SOCKET_OPFAILED);
+ }
+ 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);
+ FD_SET (SOCKET_CAST (socketP), &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)
+{
+ return SOCKET_CAST (handle) + 1;
+}
+
+#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 defined(IPv6_FUNCTION_SUPPORT)
+ freeaddrinfo ((OSADDRINFO *) handle->addr_info);
+#endif
+
+ handle->addr_info = NULL;
+ handle->length = 0;
+
+ return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION 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)
+{
+ /* If we have the IPv6 functions available we will call them, otherwise we'll call the IPv4 function */
+#if defined(IPv6_FUNCTION_SUPPORT)
+ OSADDRINFO *ipv6_result;
+ OSADDRINFO *addr_info_hints = NULL;
+ int count = 0;
+ if (hints != NULL)
+ {
+ addr_info_hints = (OSADDRINFO *) hints->addr_info;
+ }
+ if (0 != getaddrinfo (name, NULL, addr_info_hints, &ipv6_result))
+ {
+ I_32 errorCode = errno;
+ HYSOCKDEBUG ("<getaddrinfo failed, err=%d>\n", errorCode);
+ return portLibrary->error_set_last_error (portLibrary, errorCode,
+ findError (errorCode));
+ }
+ 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 */
+
+ return 0;
+#else /* IPv6_FUNCTION_SUPPORT */
+ I_32 rc = 0;
+ U_32 addr = 0;
+ U_32 count = 0;
+ struct hyhostent_struct hyhostent;
+ 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)))
+ {
+ 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;
+#endif /* IPv6_FUNCTION_SUPPORT */
+
+}
+
+#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 defined(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_addr;
+ memcpy (address, sock_addr, 4);
+ }
+#else
+ 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);
+#endif
+
+ 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;
+#if defined(IPv6_FUNCTION_SUPPORT)
+ OSADDRINFO *addrinfo;
+ PortlibPTBuffers_t ptBuffers;
+#endif /* IPv6_FUNCTION_SUPPORT */
+
+ *result = NULL;
+
+ /* If we have the IPv6 functions available we fill in the structure, otherwise it is null */
+#if defined(IPv6_FUNCTION_SUPPORT)
+#define addrinfohints (ptBuffers->addr_info_hints).addr_info
+ /* Initialized the pt buffers if necessary */
+ 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
+#endif /*IPv6_FUNCTION_SUPPORT */
+
+ 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 defined(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;
+#endif
+
+ 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 defined(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]);
+ }
+#endif
+
+ 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)
+{
+#if !HOSTENT_DATA_R
+ OSHOSTENT *result;
+#endif
+
+#if GLIBC_R||OTHER_R
+ BOOLEAN allocBuffer = FALSE;
+#endif
+
+ int herr = 0;
+ int i = 0;
+
+#if HOSTENT_DATA_R||GLIBC_R||OTHER_R||NO_R
+ PortlibPTBuffers_t ptBuffers;
+ ptBuffers = hyport_tls_get (portLibrary);
+ if (NULL == ptBuffers)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+#define hostentBuffer (&ptBuffers->hostent)
+#endif /*HOSTENT_DATA_R || GLIBC_R || OTHER_R */
+
+/* one of several threadsafe gethostbyaddr calls must be made depending on the current platform */
+/* if there is a transient error (HYPORT_ERROR_SOCKET_UNIX_TRYAGAIN), try making the call again */
+ for (i = 0; i < MAX_RETRIES; i++)
+ {
+#if HOSTENT_DATA_R
+#define dataBuffer (ptBuffers->hostent_data)
+ if (NULL == dataBuffer)
+ {
+ dataBuffer =
+ portLibrary->mem_allocate_memory (portLibrary,
+ sizeof (OSHOSTENT_DATA));
+ if (NULL == dataBuffer)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ }
+ herr = gethostbyaddr_r (addr, length, type, hostentBuffer, dataBuffer);
+#undef dataBuffer
+#elif ORIGINAL_R || NO_R
+#if NO_R
+ MUTEX_ENTER (hostentLock);
+#endif
+ result = gethostbyaddr (addr, length, type);
+#if NO_R
+ if (result)
+ {
+ herr = copy_hostent (portLibrary, result, &ptBuffers);
+ }
+ MUTEX_EXIT (hostentLock);
+ if (herr != 0)
+ {
+ return herr;
+ }
+#endif
+ herr = h_errno;
+#elif GLIBC_R || OTHER_R
+#define buffer (ptBuffers->gethostBuffer)
+#define bufferSize (ptBuffers->gethostBufferSize)
+ if (NULL == buffer)
+ {
+ bufferSize = GET_HOST_BUFFER_SIZE;
+ }
+ while (TRUE)
+ {
+ if (allocBuffer == TRUE || (NULL == buffer))
+ {
+ /* The buffer is allocated bufferSize + EXTRA_SPACE, while gethostby*_r is only aware of bufferSize
+ * because there seems to be a bug on Linux 386 where gethostbyname_r writes past the end of the
+ * buffer. This bug has not been observed on other platforms, but EXTRA_SPACE is added anyway as a precaution.*/
+ buffer =
+ portLibrary->mem_allocate_memory (portLibrary,
+ bufferSize + EXTRA_SPACE);
+ if (NULL == buffer)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ allocBuffer = FALSE;
+ }
+#if GLIBC_R
+ gethostbyaddr_r (addr, length, type, hostentBuffer, buffer,
+ bufferSize, &result, &herr);
+#elif OTHER_R
+ result =
+ gethostbyaddr_r (addr, length, type, hostentBuffer, buffer,
+ bufferSize, &herr);
+#endif /* GLIBC_R */
+/* allocate more space if the buffer is too small */
+ if (errno == ERANGE || herr == ERANGE)
+ {
+ portLibrary->mem_free_memory (portLibrary, buffer);
+ bufferSize *= 2;
+ allocBuffer = TRUE;
+ }
+ else
+ {
+ break;
+ }
+ }
+#undef buffer
+#undef bufferSize
+#endif
+
+ if (herr != HYPORT_ERROR_SOCKET_UNIX_TRYAGAIN)
+ {
+ break;
+ }
+ }
+
+#if HOSTENT_DATA_R
+ if (herr != 0)
+ {
+ herr = h_errno;
+ HYSOCKDEBUGH ("<gethostbyaddr failed, err=%d>\n", herr);
+ return portLibrary->error_set_last_error (portLibrary, herr,
+ findHostError (herr));
+ }
+#else
+ if (result == NULL)
+ {
+ HYSOCKDEBUGH ("<gethostbyaddr failed, err=%d>\n", herr);
+ return portLibrary->error_set_last_error (portLibrary, herr,
+ findHostError (herr));
+ }
+#endif
+
+ else
+ {
+ memset (handle, 0, sizeof (struct hyhostent_struct));
+#if HOSTENT_DATA_R||NO_R
+ handle->entity = hostentBuffer;
+#else
+ handle->entity = result;
+#endif
+
+ }
+#if HOSTENT_DATA_R||GLIBC_R||OTHER_R
+#undef hostentBuffer
+#endif /*HOSTENT_DATA_R || GLIBC_R || OTHER_R */
+
+ 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)
+{
+#if !HOSTENT_DATA_R
+ OSHOSTENT *result;
+#endif
+
+#if GLIBC_R||OTHER_R
+ BOOLEAN allocBuffer = FALSE;
+#endif
+
+ int herr = 0;
+ int i = 0;
+
+#if HOSTENT_DATA_R||GLIBC_R||OTHER_R||NO_R
+ PortlibPTBuffers_t ptBuffers;
+ ptBuffers = hyport_tls_get (portLibrary);
+ if (NULL == ptBuffers)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+#define hostentBuffer (&ptBuffers->hostent)
+#endif /*HOSTENT_DATA_R || GLIBC_R || OTHER_R */
+
+/* one of several threadsafe gethostbyname calls must be made depending on the current platform */
+/* if there is a transient error (HYPORT_ERROR_SOCKET_UNIX_TRYAGAIN), try making the call again */
+ for (i = 0; i < MAX_RETRIES; i++)
+ {
+#if HOSTENT_DATA_R
+#define dataBuffer (ptBuffers->hostent_data)
+ if (!dataBuffer)
+ {
+ dataBuffer =
+ portLibrary->mem_allocate_memory (portLibrary,
+ sizeof (OSHOSTENT_DATA));
+ if (!dataBuffer)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ }
+ herr = gethostbyname_r (name, hostentBuffer, dataBuffer);
+#undef dataBuffer
+#elif ORIGINAL_R || NO_R
+#if NO_R
+ MUTEX_ENTER (hostentLock);
+#endif
+ result = gethostbyname (name);
+#if NO_R
+ if (result)
+ {
+ herr = copy_hostent (portLibrary, result, &ptBuffers);
+ }
+ MUTEX_EXIT (hostentLock);
+ if (herr != 0)
+ {
+ return herr;
+ }
+#endif
+ herr = h_errno;
+#elif GLIBC_R || OTHER_R
+#define buffer (ptBuffers->gethostBuffer)
+#define bufferSize (ptBuffers->gethostBufferSize)
+ if (!buffer)
+ {
+ bufferSize = GET_HOST_BUFFER_SIZE;
+ }
+ while (TRUE)
+ {
+ if (allocBuffer == TRUE || !buffer)
+ {
+ /* The buffer is allocated bufferSize + EXTRA_SPACE, while gethostby*_r is only aware of bufferSize
+ * because there seems to be a bug on Linux 386 where gethostbyname_r writes past the end of the
+ * buffer. This bug has not been observed on other platforms, but EXTRA_SPACE is added anyway as a precaution.*/
+ buffer =
+ portLibrary->mem_allocate_memory (portLibrary,
+ bufferSize + EXTRA_SPACE);
+ if (!buffer)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ allocBuffer = FALSE;
+ }
+#if GLIBC_R
+ gethostbyname_r (name, hostentBuffer, buffer, bufferSize, &result,
+ &herr);
+#elif OTHER_R
+ result =
+ gethostbyname_r (name, hostentBuffer, buffer, bufferSize, &herr);
+#endif /* GLIBC_R */
+/* allocate more space if the buffer is too small */
+ if (errno == ERANGE || herr == ERANGE)
+ {
+ portLibrary->mem_free_memory (portLibrary, buffer);
+ bufferSize *= 2;
+ allocBuffer = TRUE;
+ }
+ else
+ {
+ break;
+ }
+ }
+#undef buffer
+#undef bufferSize
+#endif
+
+ if (herr != HYPORT_ERROR_SOCKET_UNIX_TRYAGAIN)
+ {
+ break;
+ }
+ }
+
+#if HOSTENT_DATA_R
+ if (herr != 0)
+ {
+ herr = h_errno;
+ HYSOCKDEBUGH ("<gethostbyaddr failed, err=%d>\n", herr);
+ return portLibrary->error_set_last_error (portLibrary, herr,
+ findHostError (herr));
+ }
+#else
+ if (result == NULL)
+ {
+ HYSOCKDEBUGH ("<gethostbyaddr failed, err=%d>\n", herr);
+ return portLibrary->error_set_last_error (portLibrary, herr,
+ findHostError (herr));
+ }
+#endif
+
+ else
+ {
+ memset (handle, 0, sizeof (struct hyhostent_struct));
+#if HOSTENT_DATA_R||NO_R
+ handle->entity = hostentBuffer;
+#else
+ handle->entity = result;
+#endif
+
+ }
+#if HOSTENT_DATA_R||GLIBC_R||OTHER_R
+#undef hostentBuffer
+#endif /*HOSTENT_DATA_R || GLIBC_R || OTHER_R */
+
+ 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 err = errno;
+ HYSOCKDEBUG ("<gethostname failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ 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)
+{
+
+/* If we have the IPv6 functions available we will call them, otherwise we'll call the IPv4 function */
+#if defined(IPv6_FUNCTION_SUPPORT)
+ OSSOCKADDR *addr;
+ int size;
+ int rc = 0;
+ rc =
+ getnameinfo ((OSADDR *) & in_addr->addr, sizeof (in_addr->addr), name,
+ name_length, NULL, 0, flags);
+ if (rc != 0)
+ {
+ rc = errno;
+ HYSOCKDEBUG ("<gethostbyaddr failed, err=%d>\n", rc);
+ return portLibrary->error_set_last_error (portLibrary, rc,
+ findError (rc));
+ }
+ return 0;
+#else /* IPv6_FUNCTION_SUPPORT */
+#if !HOSTENT_DATA_R
+ OSHOSTENT *result;
+#endif
+
+#if GLIBC_R||OTHER_R
+ BOOLEAN allocBuffer = FALSE;
+#endif
+ int herr = 0;
+ int i = 0;
+ int rc = 0;
+ int length;
+ OSSOCKADDR *addr;
+#if HOSTENT_DATA_R||GLIBC_R||OTHER_R||NO_R
+ PortlibPTBuffers_t ptBuffers;
+#endif /* HOSTENT_DATA_R || GLIBC_R || OTHER_R || NO_R */
+ addr = (OSSOCKADDR *) & in_addr->addr;
+ if (addr->sin_family == OS_AF_INET4)
+ {
+ length = 4;
+ }
+ else
+ {
+ length = 16;
+ }
+#if HOSTENT_DATA_R||GLIBC_R||OTHER_R||NO_R
+ ptBuffers = hyport_tls_get (portLibrary);
+ if (NULL == ptBuffers)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+#define hostentBuffer (&ptBuffers->hostent)
+#endif /* HOSTENT_DATA_R || GLIBC_R || OTHER_R || NO_R */
+/* one of several threadsafe gethostbyaddr calls must be made depending on the current platform */
+/* if there is a transient error (HYPORT_ERROR_SOCKET_UNIX_TRYAGAIN), try making the call again */
+ for (i = 0; i < MAX_RETRIES; i++)
+ {
+#if HOSTENT_DATA_R
+#define dataBuffer (ptBuffers->hostent_data)
+ if (!dataBuffer)
+ {
+ dataBuffer =
+ portLibrary->mem_allocate_memory (portLibrary,
+ sizeof (OSHOSTENT_DATA));
+ if (!dataBuffer)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ }
+ herr =
+ gethostbyaddr_r (&addr->sin_addr, length, addr->sin_family,
+ hostentBuffer, dataBuffer);
+#undef dataBuffer
+#elif ORIGINAL_R || NO_R
+#if NO_R
+ MUTEX_ENTER (hostentLock);
+#endif
+ result = gethostbyaddr (&addr->sin_addr, length, addr->sin_family);
+#if NO_R
+ if (result)
+ {
+ herr = copy_hostent (portLibrary, result, &ptBuffers);
+ }
+ MUTEX_EXIT (hostentLock);
+ if (herr != 0)
+ {
+ return herr;
+ }
+#endif
+ herr = h_errno;
+#elif GLIBC_R || OTHER_R
+#define buffer (ptBuffers->gethostBuffer)
+#define bufferSize (ptBuffers->gethostBufferSize)
+ if (!buffer)
+ {
+ bufferSize = GET_HOST_BUFFER_SIZE;
+ }
+ while (TRUE)
+ {
+ if (allocBuffer == TRUE || !buffer)
+ {
+ /* The buffer is allocated bufferSize + EXTRA_SPACE, while gethostby*_r is only aware of bufferSize
+ * because there seems to be a bug on Linux 386 where gethostbyname_r writes past the end of the
+ * buffer. This bug has not been observed on other platforms, but EXTRA_SPACE is added anyway as a precaution.*/
+ buffer =
+ portLibrary->mem_allocate_memory (portLibrary,
+ bufferSize + EXTRA_SPACE);
+ if (!buffer)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ allocBuffer = FALSE;
+ }
+#if GLIBC_R
+ gethostbyaddr_r ((char *) &addr->sin_addr, length, addr->sin_family,
+ hostentBuffer, buffer, bufferSize, &result, &herr);
+#elif OTHER_R
+ result =
+ gethostbyaddr_r ((char *) &addr->sin_addr, length,
+ addr->sin_family, hostentBuffer, buffer,
+ bufferSize, &herr);
+#endif /* GLIBC_R */
+/* allocate more space if the buffer is too small */
+ if (errno == ERANGE || herr == ERANGE)
+ {
+ portLibrary->mem_free_memory (portLibrary, buffer);
+ bufferSize *= 2;
+ allocBuffer = TRUE;
+ }
+ else
+ {
+ break;
+ }
+ }
+#undef buffer
+#undef bufferSize
+#endif
+ if (herr != HYPORT_ERROR_SOCKET_UNIX_TRYAGAIN)
+ {
+ break;
+ }
+ }
+#if HOSTENT_DATA_R
+ if (herr != 0)
+ {
+ herr = h_errno;
+ HYSOCKDEBUGH ("<gethostbyaddr failed, err=%d>\n", herr);
+ return portLibrary->error_set_last_error (portLibrary, herr,
+ findHostError (herr));
+ }
+#else
+ if (result == NULL)
+ {
+ HYSOCKDEBUGH ("<gethostbyaddr failed, err=%d>\n", herr);
+ return portLibrary->error_set_last_error (portLibrary, herr,
+ findHostError (herr));
+ }
+#endif
+ else
+ {
+ memset (name, 0, sizeof (char) * name_length);
+#if HOSTENT_DATA_R||NO_R
+ strcpy (name, hostentBuffer->h_name);
+#else
+ strcpy (name, result->h_name);
+#endif
+ }
+#if HOSTENT_DATA_R||GLIBC_R||OTHER_R
+#undef hostentBuffer
+#endif /*HOSTENT_DATA_R || GLIBC_R || OTHER_R */
+ return 0;
+#endif /* IPv6_FUNCTION_SUPPORT */
+
+}
+
+#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);
+ socklen_t optlen = sizeof (*optval);
+ U_8 uCharOptval = 0;
+
+ if (0 > platformLevel)
+ {
+ return platformLevel;
+ }
+ if (0 > platformOption)
+ {
+ return platformOption;
+ }
+
+ if (OS_MCAST_LOOP == platformOption)
+ {
+ /* most options are gotten using an 32 bit int which matches the definition of BOOLEAN. Howerver, for unix
+ platforms this option is gotten with a unsighed char. Some platforms accept both but some such as AIX
+ and false return an EINVAL if we try to set with an int instead of a unsigned char. For windows platforms
+ the spec indicates that it is get with a DWORD which seems to match the BOOLEAN. Therefore since this
+ is a platform specific case for a boolean option we handle it as a special case within this method */
+ optlen = sizeof (uCharOptval);
+ if (0 !=
+ getsockopt (SOCKET_CAST (socketP), platformLevel, platformOption,
+ (void *) &uCharOptval, &optlen))
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getsockopt (for bool) failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ *optval = uCharOptval;
+ }
+ else
+ {
+ if (0 !=
+ getsockopt (SOCKET_CAST (socketP), platformLevel, platformOption,
+ (void *) optval, &optlen))
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getsockopt (for bool) failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ }
+ /* 0 indicates the option is disabled, while non-zero indicates that the option is enabled. The caller
+ of this method assumes that the value returned is 1 if the option is enabled. For many platforms
+ but on some platforms it is not the case for some boolean options (ex AIX for SO_OOBINLINE).
+ Therefore, make sure we return 1 if the value is non zero */
+ if (*optval != 0)
+ {
+ *optval = 1;
+ }
+ 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);
+ socklen_t optlen = sizeof (*optval);
+
+ if (0 > platformLevel)
+ {
+ return platformLevel;
+ }
+ if (0 > platformOption)
+ {
+ return platformOption;
+ }
+
+ if (0 !=
+ getsockopt (SOCKET_CAST (socketP), platformLevel, platformOption,
+ (void *) optval, &optlen))
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getsockopt (for byte) failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ 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);
+ socklen_t optlen = sizeof (*optval);
+
+ if (0 > platformLevel)
+ {
+ return platformLevel;
+ }
+ if (0 > platformOption)
+ {
+ return platformOption;
+ }
+
+ if (0 !=
+ getsockopt (SOCKET_CAST (socketP), platformLevel, platformOption,
+ (void *) optval, &optlen))
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getsockopt (for int) failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ 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);
+ socklen_t optlen = sizeof (optval->linger);
+
+ if (0 > platformLevel)
+ {
+ return platformLevel;
+ }
+ if (0 > platformOption)
+ {
+ return platformOption;
+ }
+
+ if (0 !=
+ getsockopt (SOCKET_CAST (socketP), platformLevel, platformOption,
+ (char *) (&optval->linger), &optlen))
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getsockopt (for linger) failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ 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);
+ U_32 val[3];
+ socklen_t optlen = sizeof (val);
+ OSSOCKADDR *sockaddr;
+
+ if (0 > platformLevel)
+ {
+ return platformLevel;
+ }
+ if (0 > platformOption)
+ {
+ return platformOption;
+ }
+
+ if (0 !=
+ getsockopt (SOCKET_CAST (socketP), platformLevel, platformOption,
+ (char *) val, &optlen))
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getsockopt (for sockaddr) failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ sockaddr = (OSSOCKADDR *) & optval->addr;
+ if (optlen == 4)
+ {
+ sockaddr->sin_addr.s_addr = val[0]; /* false */
+ }
+ else
+ { /*Linux */
+ sockaddr->sin_addr.s_addr = val[1];
+ sockaddr->sin_port = val[2];
+ }
+
+ /* A temporary fix as Linux false (maybe others) returns 0 for the family. Maybe there is a way to get it to return the
+ right family. However we now depend on the family to be set correctly to determine whether or not we have an
+ IPv6 address or not. For now, we'll assume that this function will only be called for IPv4 multicast sockets */
+ sockaddr->sin_family = OS_AF_INET4;
+
+ 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)
+{
+ socklen_t addrlen = sizeof (addrHandle->addr);
+
+ if (getpeername
+ (SOCKET_CAST (handle), (struct sockaddr *) &addrHandle->addr,
+ &addrlen) != 0)
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getpeername failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ return 0;
+}
+
+#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)
+{
+ socklen_t addrlen = sizeof (addrHandle->addr);
+
+ if (getsockname
+ (SOCKET_CAST (handle), (struct sockaddr *) &addrHandle->addr,
+ &addrlen) != 0)
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<getsockname failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ return 0;
+}
+
+#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 (val == -1)
+ {
+ 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)
+{
+ U_8 *addr = (U_8 *) & nipAddr;
+ PortlibPTBuffers_t ptBuffers;
+
+ ptBuffers = hyport_tls_get (portLibrary);
+ if (NULL == ptBuffers)
+ {
+ return HYPORT_ERROR_SOCKET_SYSTEMFULL;
+ }
+ portLibrary->str_printf (portLibrary, ptBuffers->ntoa, NTOA_SIZE,
+ "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
+ *addrStr = ptBuffers->ntoa;
+ return 0;
+}
+
+#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)
+{
+#if defined(IPv6_FUNCTION_SUPPORT)
+ memset (handle, 0, sizeof (struct hyipmreq_struct));
+ memcpy (handle->mreq.ipv6mr_multiaddr.s6_addr, ipmcast_addr, 16);
+ handle->mreq.ipv6mr_interface = ipv6mr_interface;
+#endif
+
+ 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 = (I_32) 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 = (U_16) (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.
+ */
+I_32 VMCALL
+hysock_listen (struct HyPortLibrary * portLibrary, hysocket_t sock,
+ I_32 backlog)
+{
+ I_32 rc = 0;
+
+ if (listen (SOCKET_CAST (sock), backlog) < 0)
+ {
+ rc = errno;
+ HYSOCKDEBUG ("<listen failed, err=%d>\n", rc);
+ rc =
+ portLibrary->error_set_last_error (portLibrary, rc,
+ HYPORT_ERROR_SOCKET_OPFAILED);
+ }
+ 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 bytesRec = 0;
+
+ bytesRec = recv (SOCKET_CAST (sock), buf, nbyte, flags);
+ if (-1 == bytesRec)
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<recv failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ else
+ {
+ return bytesRec;
+ }
+}
+
+#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 bytesRec = 0;
+ socklen_t addrlen;
+
+ if (NULL == addrHandle)
+ {
+ addrlen = sizeof (*addrHandle);
+ bytesRec =
+ recvfrom (SOCKET_CAST (sock), buf, nbyte, flags, NULL, &addrlen);
+ }
+ else
+ {
+ addrlen = sizeof (addrHandle->addr);
+ bytesRec =
+ recvfrom (SOCKET_CAST (sock), buf, nbyte, flags,
+ (struct sockaddr *) &addrHandle->addr, &addrlen);
+ }
+ if (bytesRec == -1)
+ {
+ I_32 err = errno;
+ HYSOCKDEBUG ("<recvfrom failed, err=%d>\n", err);
+ return portLibrary->error_set_last_error (portLibrary, err,
+ findError (err));
+ }
+ else
+ {
+ return bytesRec;
+ }
+}
+
+#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;
+
+ result =
+ select (nfds, readfds == NULL ? NULL : &readfds->handle,
+ writefds == NULL ? NULL : &writefds->handle,
+ exceptfds == NULL ? NULL : &exceptfds->handle,
+ timeout == NULL ? NULL : &timeout->time);
+ if (result == -1)
+ {
+ rc = errno;
+ HYSOCKDEBUG ("<select failed, err=%d>\n", rc);
+ rc =
+ portLibrary->error_set_last_error (portLibrary, rc,
+ HYPORT_ERROR_SOCKET_OPFAILED);
+ }
+ else
+ {
+ if (result)
+ {
+ rc = result;
+ }
+ else
+ {
+ rc = HYPORT_ERROR_SOCKET_TIMEOUT;
+ }
+ }
+ 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.
+ */
+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, flags = 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?
+ */
+
+ /* Removed check for zero timeout */
+
+ result = hysock_fdset_init (portLibrary, hysocketP);
+ if (0 != result)
+ {
+ return result;
+ }
+
+ hysock_timeval_init (portLibrary, secTime, uSecTime, &timeP);
+ 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);
+ }
+ 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.
[... 2538 lines stripped ...]