Author: mturk
Date: Mon Jul 18 05:39:30 2011
New Revision: 1147750
URL: http://svn.apache.org/viewvc?rev=1147750&view=rev
Log:
Implement basic Win32 accept/connect natives
Modified:
commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c
commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c
Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c?rev=1147750&r1=1147749&r2=1147750&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c Mon Jul 18
05:39:30 2011
@@ -273,7 +273,7 @@ ACR_NET_EXPORT(jint, SocketServerEndpoin
jbyteArray ba,
jint backlog)
{
- static char any[16] = { 0 }; /* big enough for IPv4 or IPv6 */
+ static char any[16] = { 0 }; /* big enough for IPv4 or IPv6 */
int rc = 0;
int on = 1;
acr_sockaddr_t *aa = SOCKADDR_CAST(ba);
@@ -336,6 +336,10 @@ ACR_NET_EXPORT(jlong, SocketServerEndpoi
#endif
} while (sd == -1 && errno == EINTR);
if (AcrSdRelease(fd) == 0 && sd != -1) {
+ /* SocketServerEndpoint was closed although
+ * the socket was accepted.
+ */
+ r_close(sd);
sd = -1;
errno = ENOTSOCK;
}
@@ -431,7 +435,7 @@ ACR_NET_EXPORT(jlong, SocketServerEndpoi
#if defined(DEBUG) || defined(_DEBUG)
if (aa.addrlen != (int)aalen) {
ACR_DEBUG_TRACE("Address length missmatch. Expected %d, found %d\n",
aa.addrlen, (int)aalen);
- }
+ }
#endif
aa.salen = aa.iplen;
aa.family = aa.sa.sin.sin_family;
@@ -454,8 +458,10 @@ ACR_NET_EXPORT(jint, SocketEndpoint, con
if (timeout > 0 && !ACR_HASFLAG(fd, ACR_SO_NONBLOCK)) {
/* Turn the socket to non-blocking mode
*/
- if ((rc = AcrNonblock(sd, 1)) != 0)
+ if ((rc = AcrNonblock(sd, 1)) != 0) {
+ SOCKADDR_RELEASE(cb, ca);
goto finally;
+ }
}
do {
/* Restartable connect */
@@ -471,11 +477,11 @@ ACR_NET_EXPORT(jint, SocketEndpoint, con
rc = AcrWaitIO(fd->s, timeout, POLLOUT);
#if defined(SO_ERROR)
if (rc == 0) {
- int err;
+ int err = 0;
socklen_t len = sizeof(err);
- if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&err,
&len) == -1);
+ if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&err,
&len) == -1)
rc = errno;
- if (err != 0)
+ else if (err != 0)
rc = err;
}
#endif
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c?rev=1147750&r1=1147749&r2=1147750&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c Mon Jul
18 05:39:30 2011
@@ -16,6 +16,7 @@
#include "acr/jnitypes.h"
#include "acr/error.h"
+#include "acr/debug.h"
#include "acr/memory.h"
#include "acr/netapi.h"
#include "acr/unsafe.h"
@@ -247,3 +248,199 @@ ACR_NET_EXPORT(jlong, SocketDescriptor,
}
return P2J(sp);
}
+
+ACR_NET_EXPORT(jint, SocketServerEndpoint, bind0)(JNI_STDARGS, jlong fp,
+ jbyteArray ba,
+ jint backlog)
+{
+ static char any[16] = { 0 }; /* big enough for IPv4 or IPv6 */
+ int rc = 0;
+ int on = 1;
+ acr_sockaddr_t *aa = SOCKADDR_CAST(ba);
+ acr_sd_t *fd = J2P(fp, acr_sd_t *);
+
+ if (bind(fd->s, (const struct sockaddr *)&aa->sa, aa->salen) == -1) {
+ /* bind failed.
+ */
+ rc = ACR_GET_NETOS_ERROR();
+ goto finally;
+ }
+ /* Check for ephemeral port and "any" address.
+ * The provided byte array is duplicate of the original
+ * so it can be modified.
+ */
+ if (aa->port == 0 || memcmp(&aa->sa.sin.sin_addr, any, aa->iplen) == 0) {
+ /* Get the real address for the bound socket.
+ */
+ if ((rc = AcrGetLocalAddr(fd, aa)) != 0)
+ goto finally;
+ }
+ if (listen(fd->s, backlog) == -1) {
+ rc = ACR_GET_NETOS_ERROR();
+ goto finally;
+ }
+ /* We need to set the SO_REUSEADDR after listen call.
+ */
+ if (setsockopt(fd->s, SOL_SOCKET, SO_REUSEADDR, (void *)&on, SSIZEOF(int))
!= 0)
+ rc = ACR_GET_NETOS_ERROR();
+finally:
+ SOCKADDR_RELEASE(ba, aa);
+ return rc;
+}
+
+ACR_NET_EXPORT(jlong, SocketServerEndpoint, accept0)(JNI_STDARGS, jlong fp,
+ jbyteArray ra,
+ jboolean block)
+{
+ SOCKET ad;
+ SOCKET sd;
+ int rc;
+ acr_sockaddr_t aa;
+ socklen_t aalen;
+ acr_sd_t *fd = J2P(fp, acr_sd_t *);
+ acr_sd_t *sp;
+
+ memset(&aa, 0, sizeof(aa));
+ aalen = SSIZEOF(acr_sockaddr_t);
+
+ ad = AcrSdRetain(fd);
+ sd = accept(ad, (struct sockaddr *)&aa.sa, &aalen);
+ if (AcrSdRelease(fd) == 0 && sd != INVALID_SOCKET) {
+ /* SocketServerEndpoint was closed although
+ * the socket was accepted.
+ */
+ closesocket(sd);
+ sd = INVALID_SOCKET;
+ ACR_SET_NETOS_ERROR(ACR_ENOTSOCK);
+ }
+ if (sd == INVALID_SOCKET) {
+ ACR_THROW_NET_ERRNO();
+ return 0;
+ }
+ if (ACR_HASFLAG(fd, ACR_TCP_NODELAY)) {
+ int on = 1;
+ if (setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&on,
SSIZEOF(int)) != 0) {
+ rc = ACR_GET_NETOS_ERROR();
+ closesocket(sd);
+ ACR_THROW_NET_ERROR(rc);
+ return 0;
+ }
+ }
+ if (block == JNI_FALSE) {
+ rc = 0;
+ if (!ACR_HASFLAG(fd, ACR_SO_NONBLOCK))
+ rc = AcrNonblock(sd, 1);
+ if (rc != 0) {
+ closesocket(sd);
+ ACR_THROW_NET_ERROR(rc);
+ return 0;
+ }
+ }
+ else if (ACR_HASFLAG(fd, ACR_SO_NONBLOCK)) {
+ /* We have nonblocking acceptor and need
+ * blocking socket
+ */
+ rc = AcrNonblock(sd, 0);
+ if (rc != 0) {
+ closesocket(sd);
+ ACR_THROW_NET_ERROR(rc);
+ return 0;
+ }
+ }
+ if ((sp = ACR_TALLOC(acr_sd_t)) == 0) {
+ closesocket(sd);
+ return 0;
+ }
+ sp->type = ACR_DT_SOCKET;
+ /* Inherit nodelay flag.
+ * It's always valid cause we either inherit or explicitly set that flag.
+ */
+ sp->flags = fd->flags & ACR_TCP_NODELAY;
+ /* Inherit timeout */
+ sp->timeout = fd->timeout;
+ sp->refs = 1;
+ sp->s = sd;
+ if (block == JNI_FALSE) {
+ ACR_SETFLAG(sp, ACR_SO_NONBLOCK);
+ if (sp->timeout < 0)
+ sp->timeout = 0;
+ }
+ else {
+ ACR_CLRFLAG(sp, ACR_SO_NONBLOCK);
+ if (sp->timeout == 0)
+ sp->timeout = -1;
+ }
+ switch (aa.sa.sin.sin_family) {
+ case AF_INET:
+ aa.addrlen = 16;
+ aa.iplen = ISIZEOF(struct in_addr);
+ break;
+ case AF_INET6:
+ aa.addrlen = 46;
+ aa.iplen = ISIZEOF(struct in6_addr);
+ default:
+#if defined(DEBUG) || defined(_DEBUG)
+ ACR_DEBUG_TRACE("Unexpected address family %d\n", aa.family);
+#endif
+ break;
+ }
+#if defined(DEBUG) || defined(_DEBUG)
+ if (aa.addrlen != (int)aalen) {
+ ACR_DEBUG_TRACE("Address length missmatch. Expected %d, found %d\n",
aa.addrlen, (int)aalen);
+ }
+#endif
+ aa.salen = aa.iplen;
+ aa.family = aa.sa.sin.sin_family;
+ aa.port = ntohs(aa.sa.sin.sin_port);
+ (*env)->SetByteArrayRegion(env, ra, 0, ISIZEOF(acr_sockaddr_t), (jbyte
*)&aa);
+ return P2J(sp);
+}
+
+ACR_NET_EXPORT(jint, SocketEndpoint, connect0)(JNI_STDARGS, jlong fp,
+ jbyteArray cb, jint timeout)
+{
+ int rc;
+ SOCKET sd;
+ acr_sockaddr_t *ca = SOCKADDR_CAST(cb);
+ acr_sd_t *fd = J2P(fp, acr_sd_t *);
+
+ if (timeout == 0)
+ timeout = fd->timeout;
+ sd = AcrSdRetain(fd);
+ if (timeout > 0 && !ACR_HASFLAG(fd, ACR_SO_NONBLOCK)) {
+ /* Turn the socket to non-blocking mode
+ * for the duration of the connect call.
+ */
+ if ((rc = AcrNonblock(sd, 1)) != 0) {
+ SOCKADDR_RELEASE(cb, ca);
+ goto finally;
+ }
+ }
+ rc = connect(sd, (const struct sockaddr *)&ca->sa.sin, ca->salen);
+ if (rc == SOCKET_ERROR)
+ rc = ACR_GET_NETOS_ERROR();
+ SOCKADDR_RELEASE(cb, ca);
+ if (rc != 0) {
+ if (timeout > 0) {
+ if (rc == WSAEINPROGRESS || rc == WSAEALREADY || rc ==
WSAEWOULDBLOCK) {
+ rc = AcrWaitIO(sd, timeout, FD_CONNECT);
+#if 0
+ /* We have already check the error in AcrWaitIo call. */
+ if (rc == 0) {
+ int err = 0;
+ int len = ISIZEOF(err);
+ if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&err,
&len) == -1)
+ rc = ACR_GET_NETOS_ERROR();
+ else if (err != 0)
+ rc = err;
+ }
+#endif
+ }
+ if (!ACR_HASFLAG(fd, ACR_SO_NONBLOCK))
+ AcrNonblock(sd, 0);
+ }
+ }
+finally:
+ AcrSdRelease(fd);
+ return rc;
+}
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c?rev=1147750&r1=1147749&r2=1147750&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c Mon Jul 18
05:39:30 2011
@@ -497,30 +497,44 @@ AcrDrainSocket(SOCKET sd)
int
AcrWaitIO(SOCKET sd, int timeout, int events)
{
- int rc;
+ int rc;
struct timeval tv;
struct timeval *tp = 0;
- fd_set rdset, wrset;
+ fd_set rdset, wrset, exset;
FD_ZERO(&rdset);
FD_ZERO(&wrset);
+ FD_ZERO(&exset);
if (events & FD_READ) {
FD_SET(sd, &rdset);
}
- if (events & FD_WRITE) {
+ if (events & (FD_WRITE | FD_CONNECT)) {
FD_SET(sd, &wrset);
}
+ if (events & FD_CONNECT) {
+ FD_SET(sd, &exset);
+ }
if (timeout > 0) {
tp = &tv;
tp->tv_sec = (long)(timeout / 1000);
tp->tv_usec = (long)(timeout % 1000) * 1000;
}
- rc = select(1, &rdset, &wrset, 0, tp);
+ rc = select(1, &rdset, &wrset, &exset, tp);
if (rc == SOCKET_ERROR)
return ACR_GET_NETOS_ERROR();
else if (rc == 0)
return ACR_TIMEUP;
+ else {
+ if ((events & FD_CONNECT) != 0 && FD_ISSET(sd, &exset)) {
+ int err = 0;
+ int len = ISIZEOF(err);
+ if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&err, &len) == -1)
+ rc = ACR_GET_NETOS_ERROR();
+ else if (err != 0)
+ rc = err;
+ }
+ }
return 0;
}
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c?rev=1147750&r1=1147749&r2=1147750&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c Mon Jul 18
05:39:30 2011
@@ -189,7 +189,7 @@ inet_ntop6(const unsigned char *src, cha
/*
* Check for overflow, copy, and we're done.
*/
- if (strlcpy(dst, tmp, size) >= size) {
+ if (size < (int)strlcpy(dst, tmp, size)) {
ACR_SET_OS_ERROR(ACR_ENOSPC);
return 0;
}