I_32 hysock_select_read (hysocket_t hysocketP, I_32 secTime, I_32 uSecTime, BOOLEAN accept) { // Current implementation uses poll() system routine since select() // has issues if fd_num is greater than FD_SETSIZE. See HARMONY-4077. int poll_timeout; I_32 result = 0; I_32 rc = 0; struct pollfd my_pollfd; my_pollfd.fd = SOCKET_CAST(hysocketP); my_pollfd.events = POLLIN | POLLPRI; my_pollfd.revents = 0; poll_timeout = TO_MILLIS(secTime, uSecTime); result = poll(&my_pollfd, 1, poll_timeout); if (result == -1) { HYSOCKDEBUG ("<poll failed, err=%d>\n", errno); if (errno == EINTR) { rc = hyerror_set_last_error(rc, HYPORT_ERROR_SOCKET_INTERRUPTED); } else { rc = hyerror_set_last_error(rc, HYPORT_ERROR_SOCKET_OPFAILED); } } else { if (result || poll_timeout == 0) { rc = result; } else { rc = HYPORT_ERROR_SOCKET_TIMEOUT; } } return rc; }
I_32 hysock_fdset_init (hysocket_t socketP) { PortlibPTBuffers_t ptBuffers; hyfdset_t fdset; ptBuffers = hyport_tls_get (); if (NULL == ptBuffers) { return HYPORT_ERROR_SOCKET_SYSTEMFULL; } if (NULL == ptBuffers->fdset) { ptBuffers->fdset = XMLVM_ATOMIC_MALLOC(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; }
I_32 hysock_accept (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 = hyerror_set_last_error(rc, HYPORT_ERROR_SOCKET_ADDRNOTAVAIL); } if (rc == 0) { //*sockHandle = portLibrary->mem_allocate_memory (portLibrary, sizeof (struct hysocket_struct)); *sockHandle = XMLVM_ATOMIC_MALLOC(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; }
I_32 hysock_listen (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 = hyerror_set_last_error(rc, HYPORT_ERROR_SOCKET_OPFAILED); } return rc; }
I_32 hysock_read (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; return hyerror_set_last_error(err, findError(err)); } else { return bytesRec; } }
I_32 hysock_connect (hysocket_t sock, hysockaddr_t addr) { I_32 rc = 0; I_32 length = getAddrLength(addr); if (connect (SOCKET_CAST (sock), (struct sockaddr *) &addr->addr, length) < 0) { rc = errno; rc = hyerror_set_last_error(rc, HYPORT_ERROR_SOCKET_OPFAILED); } return rc; }
I_32 hysock_getsockname (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; return hyerror_set_last_error(err, findError(err)); } return 0; }
I_32 hysock_bind (hysocket_t sock, hysockaddr_t addr) { I_32 rc = 0; I_32 length = getAddrLength(addr); if (bind (SOCKET_CAST (sock), (struct sockaddr *) &addr->addr, length) < 0) { rc = errno; rc = hyerror_set_last_error(rc, HYPORT_ERROR_SOCKET_ADDRNOTAVAIL); } return rc; }
I_32 hysock_close (hysocket_t * sock) { I_32 rc = 0; if (*sock == INVALID_SOCKET) { return hyerror_set_last_error(HYPORT_ERROR_SOCKET_UNIX_EBADF, HYPORT_ERROR_SOCKET_BADSOCKET); } if (close (SOCKET_CAST (*sock)) < 0) { rc = errno; rc = hyerror_set_last_error(rc, HYPORT_ERROR_SOCKET_BADSOCKET); } *sock = INVALID_SOCKET; return rc; }
I_32 hysock_write (hysocket_t sock, U_8 * buf, I_32 nbyte, I_32 flags) { I_32 bytesSent = 0; bytesSent = send (SOCKET_CAST (sock), buf, nbyte, flags); if (-1 == bytesSent) { I_32 err = errno; return hyerror_set_last_error(err, findError(err)); } else { return bytesSent; } }
/* * Class: org_apache_harmony_nio_AddressUtil * Method: getFDAddress * Signature: (Ljava/io/FileDescriptor;)J */ JNIEXPORT jlong JNICALL Java_org_apache_harmony_nio_AddressUtil_getFDAddress (JNIEnv * env, jclass clz, jobject fd){ jclass descriptorCLS; jfieldID descriptorFID; hysocket_t hysocketP; //TODO add to cache descriptorCLS = (*env)->FindClass (env, "java/io/FileDescriptor"); if (NULL == descriptorCLS){ return 0; } descriptorFID = (*env)->GetFieldID (env, descriptorCLS, "descriptor", "J"); if (NULL == descriptorFID){ return 0; } hysocketP = (hysocket_t) ((IDATA)((*env)->GetLongField (env, fd, descriptorFID))); return SOCKET_CAST(hysocketP); }
/* * Internal helper function. * * Get the file descriptor. */ static jint getFd(JNIEnv* env, jclass clazz, jobject fd) { jclass descriptorCLS; jfieldID descriptorFID; hysocket_t* hysocketP; descriptorCLS = env->FindClass("java/io/FileDescriptor"); if (NULL == descriptorCLS){ return 0; } descriptorFID = env->GetFieldID(descriptorCLS, "descriptor", "I"); if (NULL == descriptorFID){ return 0; } jint result = env->GetIntField(fd, descriptorFID); hysocketP = (hysocket_t*) (result); return SOCKET_CAST(hysocketP); }
I_32 hysock_setopt_bool (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 = *optval; if (0 > platformLevel) { return platformLevel; } if (0 > platformOption) { return platformOption; } if (OS_MCAST_LOOP == platformOption) { /* most options are set using an 32 bit int which matches the definition of BOOLEAN. Howerver, for unix platforms this option is set 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 set 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 */ if (0 != setsockopt (SOCKET_CAST (socketP), platformLevel, platformOption, &uCharOptval, sizeof (uCharOptval))) { I_32 err = errno; HYSOCKDEBUG ("<setsockopt (for bool) failed, err=%d>\n", err); return hyerror_set_last_error(err, findError (err)); } } else { if (0 != setsockopt (SOCKET_CAST (socketP), platformLevel, platformOption, (void *) optval, optlen)) { I_32 err = errno; HYSOCKDEBUG ("<setsockopt (for bool) failed, err=%d>\n", err); return hyerror_set_last_error(err, findError (err)); } } #if defined(IPV6_FUNCTION_SUPPORT) /* there separate socket options for IPv4/IPv6 for ttl, the IPv6 one also needs to be set */ if (platformOption == IP_MULTICAST_LOOP) { platformLevel = IPPROTO_IPV6; platformOption = IPV6_MULTICAST_LOOP; if (0 != setsockopt (SOCKET_CAST (socketP), platformLevel, platformOption, (void *) optval, optlen)) { HYSOCKDEBUG ("<setsockopt (for bool) failed, err=%d>\n"); return hyerror_set_last_error(err, findError (errno)); } } #endif return 0; }
I_32 hysock_fdset_size (hysocket_t handle) { return SOCKET_CAST (handle) + 1; }