mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
1331 lines
34 KiB
C
1331 lines
34 KiB
C
/*
|
|
* @(#) $(JCGO)/native/jcgonet.c --
|
|
* a part of the JCGO native layer library (network I/O impl).
|
|
**
|
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
|
* Copyright (C) 2001-2013 Ivan Maidanski <ivmai@mail.ru>
|
|
* All rights reserved.
|
|
*/
|
|
|
|
/*
|
|
* Used control macros: JCGO_INET, JCGO_UNIX.
|
|
* Macros for tuning: CLIBDECL, STATIC.
|
|
*/
|
|
|
|
/*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
**
|
|
* This software is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License (GPL) for more details.
|
|
**
|
|
* Linking this library statically or dynamically with other modules is
|
|
* making a combined work based on this library. Thus, the terms and
|
|
* conditions of the GNU General Public License cover the whole
|
|
* combination.
|
|
**
|
|
* As a special exception, the copyright holders of this library give you
|
|
* permission to link this library with independent modules to produce an
|
|
* executable, regardless of the license terms of these independent
|
|
* modules, and to copy and distribute the resulting executable under
|
|
* terms of your choice, provided that you also meet, for each linked
|
|
* independent module, the terms and conditions of the license of that
|
|
* module. An independent module is a module which is not derived from
|
|
* or based on this library. If you modify this library, you may extend
|
|
* this exception to your version of the library, but you are not
|
|
* obligated to do so. If you do not wish to do so, delete this
|
|
* exception statement from your version.
|
|
*/
|
|
|
|
#ifndef JCGO_BUILDING_JNU
|
|
#include "jcgojnu.h"
|
|
#endif
|
|
|
|
#ifdef JCGO_VER
|
|
|
|
#ifdef JCGO_INET
|
|
|
|
#include "jcgonet.h"
|
|
|
|
#define JCGO_JSOCKOPT_NODELAY 0x1
|
|
#define JCGO_JSOCKOPT_TOS 0x3
|
|
#define JCGO_JSOCKOPT_REUSEADDR 0x4
|
|
#define JCGO_JSOCKOPT_KEEPALIVE 0x8
|
|
#define JCGO_JSOCKOPT_LOOP 0x12
|
|
#define JCGO_JSOCKOPT_BROADCAST 0x20
|
|
#define JCGO_JSOCKOPT_LINGER 0x80
|
|
#define JCGO_JSOCKOPT_SNDBUF 0x1001
|
|
#define JCGO_JSOCKOPT_RCVBUF 0x1002
|
|
#define JCGO_JSOCKOPT_OOBINLINE 0x1003
|
|
#define JCGO_JSOCKOPT_TTL 0x1e61
|
|
|
|
#ifndef STATIC
|
|
#define STATIC static
|
|
#endif
|
|
|
|
union jcgo_sockaddr_u
|
|
{
|
|
struct sockaddr_in in;
|
|
#ifdef JCGO_IPV6_PRESENT
|
|
struct sockaddr_in6 in6;
|
|
#endif
|
|
};
|
|
|
|
#ifdef JCGO_SOCK_CLEANUP
|
|
|
|
#ifndef CLIBDECL
|
|
#ifdef __CLIB
|
|
#define CLIBDECL __CLIB
|
|
#else
|
|
#ifdef _USERENTRY
|
|
#define CLIBDECL _USERENTRY
|
|
#else
|
|
#ifdef _RTL_FUNC
|
|
#define CLIBDECL _RTL_FUNC
|
|
#else
|
|
#ifdef JCGO_UNIX
|
|
#define CLIBDECL /* empty */
|
|
#else
|
|
#define CLIBDECL __cdecl
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
STATIC void CLIBDECL jcgo_sockCleanup(void)
|
|
{
|
|
JCGO_SOCK_CLEANUP(0);
|
|
}
|
|
|
|
#endif /* JCGO_SOCK_CLEANUP */
|
|
|
|
STATIC int jcgo_sockAddrFill( union jcgo_sockaddr_u *psaddr, char *address,
|
|
int iplen, unsigned short port )
|
|
{
|
|
int i;
|
|
if ((unsigned)iplen == sizeof(psaddr->in.sin_addr))
|
|
{
|
|
i = (int)sizeof(psaddr->in);
|
|
while (i-- > 0)
|
|
*((volatile char *)psaddr + i) = '\0';
|
|
psaddr->in.sin_family = AF_INET;
|
|
psaddr->in.sin_port = htons(port);
|
|
i = (int)sizeof(psaddr->in.sin_addr);
|
|
while (i-- > 0)
|
|
*((volatile char *)&psaddr->in.sin_addr + i) = *(address + i);
|
|
return (int)sizeof(psaddr->in);
|
|
}
|
|
#ifdef JCGO_IPV6_PRESENT
|
|
if ((unsigned)iplen == sizeof(psaddr->in6.sin6_addr))
|
|
{
|
|
i = (int)sizeof(psaddr->in6);
|
|
while (i-- > 0)
|
|
*((volatile char *)psaddr + i) = '\0';
|
|
psaddr->in6.sin6_family = AF_INET6;
|
|
psaddr->in6.sin6_port = htons(port);
|
|
i = (int)sizeof(psaddr->in6.sin6_addr);
|
|
while (i-- > 0)
|
|
*((volatile char *)&psaddr->in6.sin6_addr + i) = *(address + i);
|
|
return (int)sizeof(psaddr->in6);
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
STATIC int jcgo_sockAddrDecode( union jcgo_sockaddr_u *psaddr, char *address,
|
|
int ipmaxlen, unsigned short *pport )
|
|
{
|
|
int i;
|
|
if (psaddr->in.sin_family == AF_INET)
|
|
{
|
|
*pport = (unsigned short)ntohs(psaddr->in.sin_port);
|
|
i = (int)sizeof(psaddr->in.sin_addr);
|
|
if (i >= ipmaxlen)
|
|
i = ipmaxlen;
|
|
while (i-- > 0)
|
|
*(address + i) = *((volatile char *)&psaddr->in.sin_addr + i);
|
|
return (int)sizeof(psaddr->in.sin_addr);
|
|
}
|
|
#ifdef JCGO_IPV6_PRESENT
|
|
if (psaddr->in6.sin6_family == AF_INET6)
|
|
{
|
|
*pport = (unsigned short)ntohs(psaddr->in6.sin6_port);
|
|
i = (int)sizeof(psaddr->in6.sin6_addr);
|
|
if (i >= ipmaxlen)
|
|
i = ipmaxlen;
|
|
while (i-- > 0)
|
|
*(address + i) = *((volatile char *)&psaddr->in6.sin6_addr + i);
|
|
return (int)sizeof(psaddr->in6.sin6_addr);
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
#endif /* JCGO_INET */
|
|
|
|
#ifndef NOJAVA_java_net_VMInetAddress_lookupInaddrAny0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_java_net_VMInetAddress_lookupInaddrAny0)( JNIEnv *pJniEnv, jclass This )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (jint)INADDR_ANY;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_java_net_VMInetAddress_getLocalHostname0
|
|
JCGO_JNI_EXPF(jstring,
|
|
Java_java_net_VMInetAddress_getLocalHostname0)( JNIEnv *pJniEnv, jclass This )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
char cbuf[JCGO_SOCKHOSTNAME_MAXSIZE];
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_GETHOSTNAME(cbuf, sizeof(cbuf) - 1);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
cbuf[res != -1 ? sizeof(cbuf) - 1 : 0] = '\0';
|
|
return jcgo_JnuNewStringPlatform(pJniEnv, cbuf);
|
|
#else
|
|
JCGO_UNUSED_VAR(This);
|
|
return jcgo_JnuNewStringPlatform(pJniEnv, "");
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketsInit0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketsInit0)( JNIEnv *pJniEnv,
|
|
jclass This )
|
|
{
|
|
#ifdef JCGO_INET
|
|
#ifdef JCGO_SOCK_INIT
|
|
int res;
|
|
JCGO_SOCKINIT_T data;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_INIT(&data);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res)
|
|
return -1;
|
|
#endif
|
|
#endif
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrAddrNotAvail0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrAddrNotAvail0)(
|
|
JNIEnv *pJniEnv, jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCEACCES || (int)res == -SOCEADDRINUSE ||
|
|
(int)res == -SOCEADDRNOTAVAIL ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrConnInProgress0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrConnInProgress0)(
|
|
JNIEnv *pJniEnv, jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCEALREADY || (int)res == -SOCEINPROGRESS ||
|
|
(int)res == -SOCEWOULDBLOCK ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrConnRefused0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrConnRefused0)( JNIEnv *pJniEnv,
|
|
jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCECONNREFUSED || (int)res == -SOCEHOSTDOWN ||
|
|
(int)res == -SOCETIMEDOUT ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrConnected0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrConnected0)( JNIEnv *pJniEnv,
|
|
jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCEISCONN ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrHostUnreach0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrHostUnreach0)( JNIEnv *pJniEnv,
|
|
jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCEHOSTUNREACH || (int)res == -SOCENETDOWN ||
|
|
(int)res == -SOCENETUNREACH ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrInterrupted0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrInterrupted0)( JNIEnv *pJniEnv,
|
|
jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCEINTR || (int)res == -SOCEINPROGRESS ||
|
|
(int)res == -SOCEWOULDBLOCK ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrNoResources0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrNoResources0)( JNIEnv *pJniEnv,
|
|
jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCEADDRINUSE || (int)res == -SOCEMFILE ||
|
|
(int)res == -SOCENOBUFS || (int)res == -SOCETOOMANYREFS ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_isSocketErrResetConn0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_isSocketErrResetConn0)( JNIEnv *pJniEnv,
|
|
jclass This, jint res )
|
|
{
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
#ifdef JCGO_INET
|
|
return (int)res == -SOCECONNRESET ? 1 : 0;
|
|
#else
|
|
JCGO_UNUSED_VAR(res);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_getSocketErrorMsg0
|
|
JCGO_JNI_EXPF(jstring,
|
|
Java_gnu_java_net_VMPlainSocketImpl_getSocketErrorMsg0)( JNIEnv *pJniEnv,
|
|
jclass This, jint res )
|
|
{
|
|
#ifdef JCGO_INET
|
|
#ifdef JCGO_SOCKGETERR_NOTERRNO
|
|
char *cstr = NULL;
|
|
switch (-(int)res)
|
|
{
|
|
case SOCEACCES:
|
|
cstr = "Permission denied";
|
|
break;
|
|
case SOCEADDRINUSE:
|
|
cstr = "Address already in use";
|
|
break;
|
|
case SOCEADDRNOTAVAIL:
|
|
cstr = "Cannot assign requested address";
|
|
break;
|
|
case SOCEAFNOSUPPORT:
|
|
cstr = "Address family not supported by protocol family";
|
|
break;
|
|
case SOCEALREADY:
|
|
cstr = "Connection operation already in progress";
|
|
break;
|
|
case SOCEBADF:
|
|
cstr = "Socket closed";
|
|
break;
|
|
case SOCECONNABORTED:
|
|
cstr = "Software caused connection abort";
|
|
break;
|
|
case SOCECONNREFUSED:
|
|
cstr = "Connection refused";
|
|
break;
|
|
case SOCECONNRESET:
|
|
cstr = "Connection reset by peer";
|
|
break;
|
|
case SOCEDESTADDRREQ:
|
|
cstr = "Destination address required";
|
|
break;
|
|
case SOCEHOSTDOWN:
|
|
cstr = "Host is down";
|
|
break;
|
|
case SOCEHOSTUNREACH:
|
|
cstr = "No route to host";
|
|
break;
|
|
case SOCEINPROGRESS:
|
|
cstr = "Blocking operation is in progress now";
|
|
break;
|
|
case SOCEINTR:
|
|
cstr = "Operation is canceled";
|
|
break;
|
|
case SOCEINVAL:
|
|
cstr = "Invalid function argument";
|
|
break;
|
|
case SOCEISCONN:
|
|
cstr = "Socket is already connected";
|
|
break;
|
|
case SOCEMFILE:
|
|
cstr = "Too many open sockets";
|
|
break;
|
|
case SOCEMSGSIZE:
|
|
cstr = "Message too long";
|
|
break;
|
|
case SOCENETDOWN:
|
|
cstr = "Network interface is not configured";
|
|
break;
|
|
case SOCENETRESET:
|
|
cstr = "Network dropped connection on reset";
|
|
break;
|
|
case SOCENETUNREACH:
|
|
cstr = "Network is unreachable";
|
|
break;
|
|
case SOCENOBUFS:
|
|
cstr = "No buffer space available";
|
|
break;
|
|
case SOCENOPROTOOPT:
|
|
cstr = "Bad protocol option";
|
|
break;
|
|
case SOCENOTCONN:
|
|
cstr = "Socket is not connected";
|
|
break;
|
|
case SOCENOTSOCK:
|
|
cstr = "Not a socket";
|
|
break;
|
|
case SOCEOPNOTSUPP:
|
|
cstr = "Operation not supported on transport endpoint";
|
|
break;
|
|
case SOCEPFNOSUPPORT:
|
|
cstr = "Protocol family not supported";
|
|
break;
|
|
case SOCEPROTONOSUPPORT:
|
|
cstr = "Protocol not supported";
|
|
break;
|
|
case SOCEPROTOTYPE:
|
|
cstr = "Protocol wrong type for socket";
|
|
break;
|
|
case SOCESHUTDOWN:
|
|
cstr = "Cannot send after socket shutdown";
|
|
break;
|
|
case SOCESOCKTNOSUPPORT:
|
|
cstr = "Socket type not supported";
|
|
break;
|
|
case SOCETIMEDOUT:
|
|
cstr = "Connection timed out";
|
|
break;
|
|
case SOCETOOMANYREFS:
|
|
cstr = "Too many references to some kernel resource";
|
|
break;
|
|
case SOCEWOULDBLOCK:
|
|
cstr = "Operation would block";
|
|
break;
|
|
}
|
|
#else
|
|
char *cstr = (int)res != -SOCEBADF ? strerror(-(int)res) : "Socket closed";
|
|
#endif
|
|
JCGO_UNUSED_VAR(This);
|
|
return jcgo_JnuNewStringPlatform(pJniEnv, cstr != NULL ? cstr : "");
|
|
#else
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(res);
|
|
return jcgo_JnuNewStringPlatform(pJniEnv, "Sockets not supported");
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketCreate0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketCreate0)( JNIEnv *pJniEnv,
|
|
jclass This, jintArray resArr, jint stream )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode;
|
|
#ifdef SO_NOSIGPIPE
|
|
int optval = 1;
|
|
#endif
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SOCKET(AF_INET, (int)stream ? SOCK_STREAM : SOCK_DGRAM, 0,
|
|
&errcode);
|
|
#ifdef SO_NOSIGPIPE
|
|
if (res != -1)
|
|
(void)JCGO_SOCK_SETSOCKOPT(res, SOL_SOCKET, SO_NOSIGPIPE, &optval,
|
|
sizeof(optval), &errcode);
|
|
#endif
|
|
(void)JCGO_SOCK_SETCLOEXEC(res);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res != -1)
|
|
{
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, resArr, 0, 0);
|
|
return (jint)((unsigned)res);
|
|
}
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, resArr, 0, (jint)-errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(stream);
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, resArr, 0, -1);
|
|
#endif
|
|
JCGO_UNUSED_VAR(This);
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketBind0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketBind0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray ip, jint iplen, jint port )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
char *address;
|
|
union jcgo_sockaddr_u saddr;
|
|
JCGO_UNUSED_VAR(This);
|
|
address = (char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, iplen);
|
|
if (address == NULL)
|
|
return 0;
|
|
res = 0;
|
|
if ((int)iplen != 4 || (*(unsigned char *)address & 0x7f) != 0x7f ||
|
|
*((unsigned char *)address + 3) != 0xff)
|
|
res = jcgo_sockAddrFill(&saddr, address, (int)iplen, (unsigned short)port);
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
if (!res)
|
|
return -SOCEAFNOSUPPORT;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_BIND((int)fd, &saddr, (unsigned)res, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
return (jint)(res >= 0 ? res : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(iplen);
|
|
JCGO_UNUSED_VAR(port);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketDisconnect0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketDisconnect0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
struct sockaddr_in saddr;
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
saddr.sin_family = AF_UNSPEC;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_CONNECT((int)fd, &saddr, sizeof(saddr), &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
return (jint)(res >= 0 ? res : errcode != SOCEAFNOSUPPORT ? -errcode : 0);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketConnect0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketConnect0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray ip, jint iplen, jint port )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
char *address;
|
|
union jcgo_sockaddr_u saddr;
|
|
JCGO_UNUSED_VAR(This);
|
|
address = (char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, iplen);
|
|
if (address == NULL)
|
|
return 0;
|
|
res = jcgo_sockAddrFill(&saddr, address, (int)iplen, (unsigned short)port);
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
if (!res)
|
|
return -SOCEAFNOSUPPORT;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_CONNECT((int)fd, &saddr, (unsigned)res, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
return (jint)(res >= 0 ? res : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(iplen);
|
|
JCGO_UNUSED_VAR(port);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketSendTo0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketSendTo0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray buffer, jint off, jint len, jint urgent,
|
|
jbyteArray ip, jint iplen, jint port )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode;
|
|
unsigned buflen;
|
|
char *buf =
|
|
(char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, buffer, off, len);
|
|
char *address;
|
|
union jcgo_sockaddr_u saddr;
|
|
JCGO_UNUSED_VAR(This);
|
|
if (buf == NULL)
|
|
return 0;
|
|
res = 0;
|
|
if (iplen > 0)
|
|
{
|
|
address = (char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, iplen);
|
|
if (address == NULL)
|
|
{
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, buffer, (jbyte *)buf, off);
|
|
return 0;
|
|
}
|
|
res = jcgo_sockAddrFill(&saddr, address, (int)iplen, (unsigned short)port);
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
if (!res)
|
|
{
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, buffer, (jbyte *)buf, off);
|
|
return -SOCEAFNOSUPPORT;
|
|
}
|
|
}
|
|
buflen = ((unsigned)-1) >> 1;
|
|
if ((jint)buflen >= len)
|
|
buflen = (unsigned)len;
|
|
errcode = -(int)((volatile char *)buf - (volatile char *)NULL);
|
|
if (errcode > 0 && (int)buflen > errcode)
|
|
{
|
|
if (off > 0)
|
|
{
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, buffer, (jbyte *)buf, off);
|
|
return 0;
|
|
}
|
|
buflen = (unsigned)errcode;
|
|
}
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SENDTO((int)fd, buf, buflen, (int)urgent ? MSG_OOB : 0,
|
|
iplen > 0 ? &saddr : NULL, (unsigned)res, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, buffer, (jbyte *)buf, off);
|
|
return (jint)(res >= 0 ? res : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(buffer);
|
|
JCGO_UNUSED_VAR(off);
|
|
JCGO_UNUSED_VAR(len);
|
|
JCGO_UNUSED_VAR(urgent);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(iplen);
|
|
JCGO_UNUSED_VAR(port);
|
|
return -1;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketRecvFrom0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketRecvFrom0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray buffer, jint off, jint len, jint urgent,
|
|
jint peek, jbyteArray ip, jint ipmaxlen, jintArray iplenPortArr )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res = (int)(((unsigned)-1) >> 1);
|
|
int errcode;
|
|
unsigned short port = 0;
|
|
char *buf =
|
|
(char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, buffer, off, len);
|
|
char *address;
|
|
union jcgo_sockaddr_u saddr;
|
|
JCGO_UNUSED_VAR(This);
|
|
if (buf == NULL)
|
|
return 0;
|
|
if ((jint)res >= len)
|
|
res = (int)len;
|
|
errcode = -(int)((volatile char *)buf - (volatile char *)NULL);
|
|
if (errcode > 0 && res > errcode)
|
|
{
|
|
if (off > 0 && (int)ipmaxlen)
|
|
{
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, buffer, (jbyte *)buf, off);
|
|
return 0;
|
|
}
|
|
res = errcode;
|
|
}
|
|
address = (char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0,
|
|
(int)ipmaxlen > 0 ? ipmaxlen : 0);
|
|
if (address == NULL)
|
|
{
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, buffer, (jbyte *)buf, off);
|
|
return 0;
|
|
}
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_RECVFROM((int)fd, buf, (unsigned)res,
|
|
((int)urgent ? MSG_OOB : 0) | ((int)peek ? MSG_PEEK : 0),
|
|
(int)ipmaxlen ? &saddr : NULL, (int)ipmaxlen ? sizeof(saddr) : 0,
|
|
&errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res == -1 && errcode == SOCEMSGSIZE)
|
|
res = (int)len;
|
|
if (res >= 0)
|
|
{
|
|
if ((int)ipmaxlen > 0)
|
|
{
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, iplenPortArr, 0,
|
|
(jint)jcgo_sockAddrDecode(&saddr, address, (int)ipmaxlen, &port));
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, iplenPortArr, 1, (jint)port);
|
|
}
|
|
}
|
|
else res = -errcode;
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, buffer, (jbyte *)buf, off);
|
|
return (jint)res;
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(buffer);
|
|
JCGO_UNUSED_VAR(off);
|
|
JCGO_UNUSED_VAR(len);
|
|
JCGO_UNUSED_VAR(urgent);
|
|
JCGO_UNUSED_VAR(peek);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(ipmaxlen);
|
|
JCGO_UNUSED_VAR(iplenPortArr);
|
|
return -1;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketAccept0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketAccept0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray ip, jint ipmaxlen, jintArray iplenPortArr )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode;
|
|
#ifdef SO_NOSIGPIPE
|
|
int optval = 1;
|
|
#endif
|
|
unsigned short port = 0;
|
|
char *address =
|
|
(char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, ipmaxlen);
|
|
union jcgo_sockaddr_u saddr;
|
|
if (address == NULL)
|
|
return -1;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_ACCEPT((int)fd, saddr, &errcode);
|
|
#ifdef SO_NOSIGPIPE
|
|
if (res != -1)
|
|
(void)JCGO_SOCK_SETSOCKOPT(res, SOL_SOCKET, SO_NOSIGPIPE, &optval,
|
|
sizeof(optval), &errcode);
|
|
#endif
|
|
(void)JCGO_SOCK_SETCLOEXEC(res);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res != -1)
|
|
{
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, iplenPortArr, 0,
|
|
(jint)jcgo_sockAddrDecode(&saddr, address, (int)ipmaxlen, &port));
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, iplenPortArr, 1, (jint)port);
|
|
}
|
|
else jcgo_JnuSetIntArrayElement(pJniEnv, iplenPortArr, 0, (jint)-errcode);
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
if (res != -1)
|
|
return (jint)((unsigned)res);
|
|
#else
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(ipmaxlen);
|
|
JCGO_UNUSED_VAR(iplenPortArr);
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, iplenPortArr, 0, -1);
|
|
#endif
|
|
JCGO_UNUSED_VAR(This);
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketGetLocalAddrPort0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketGetLocalAddrPort0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray ip, jint ipmaxlen, jintArray portArr )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode;
|
|
unsigned short port = 0;
|
|
char *address =
|
|
(char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, ipmaxlen);
|
|
union jcgo_sockaddr_u saddr;
|
|
JCGO_UNUSED_VAR(This);
|
|
if (address == NULL)
|
|
return 0;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_GETSOCKNAME((int)fd, saddr, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res >= 0)
|
|
{
|
|
res = jcgo_sockAddrDecode(&saddr, address, (int)ipmaxlen, &port);
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, portArr, 0, (jint)port);
|
|
}
|
|
else res = -errcode;
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
return (jint)res;
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(ipmaxlen);
|
|
JCGO_UNUSED_VAR(portArr);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketSelect0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketSelect0)( JNIEnv *pJniEnv,
|
|
jclass This, jintArray readFDs, jint readFDsLen, jintArray writeFDs,
|
|
jint writeFDsLen, jintArray exceptFDs, jint exceptFDsLen, jint timeout )
|
|
{
|
|
#ifdef JCGO_INET
|
|
#ifdef FD_SET
|
|
jint fd;
|
|
int res;
|
|
int errcode;
|
|
int i;
|
|
int maxfd = 0;
|
|
struct timeval tv;
|
|
fd_set fdsread;
|
|
fd_set fdswrite;
|
|
fd_set fdsexcept;
|
|
FD_ZERO(&fdsread);
|
|
FD_ZERO(&fdswrite);
|
|
FD_ZERO(&fdsexcept);
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 0;
|
|
for (i = 0; i < (int)readFDsLen; i++)
|
|
{
|
|
fd = jcgo_JnuGetIntArrayElement(pJniEnv, readFDs, i);
|
|
if (fd != -1)
|
|
{
|
|
FD_SET((unsigned)fd, &fdsread);
|
|
if (maxfd <= (int)fd)
|
|
maxfd = (int)fd;
|
|
}
|
|
}
|
|
for (i = 0; i < (int)writeFDsLen; i++)
|
|
{
|
|
fd = jcgo_JnuGetIntArrayElement(pJniEnv, writeFDs, i);
|
|
if (fd != -1)
|
|
{
|
|
FD_SET((unsigned)fd, &fdswrite);
|
|
if (maxfd <= (int)fd)
|
|
maxfd = (int)fd;
|
|
}
|
|
}
|
|
for (i = 0; i < (int)exceptFDsLen; i++)
|
|
{
|
|
fd = jcgo_JnuGetIntArrayElement(pJniEnv, exceptFDs, i);
|
|
if (fd != -1)
|
|
{
|
|
FD_SET((unsigned)fd, &fdsexcept);
|
|
if (maxfd <= (int)fd)
|
|
maxfd = (int)fd;
|
|
}
|
|
}
|
|
if (timeout > 0)
|
|
{
|
|
tv.tv_sec = (JCGO_SOCKTVSEC_T)(timeout / (jint)1000L);
|
|
tv.tv_usec = (JCGO_TVSUSECONDS_T)(timeout % (jint)1000L) *
|
|
(JCGO_TVSUSECONDS_T)1000L;
|
|
}
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SELECT(maxfd + 1, &fdsread, &fdswrite, &fdsexcept,
|
|
timeout >= 0 ? (void *)&tv : NULL, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res <= 0)
|
|
return (jint)(res < 0 ? -errcode : 0);
|
|
for (i = 0; i < (int)readFDsLen; i++)
|
|
{
|
|
fd = jcgo_JnuGetIntArrayElement(pJniEnv, readFDs, i);
|
|
if (fd != -1 && !FD_ISSET((unsigned)fd, &fdsread))
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, readFDs, i, -1);
|
|
}
|
|
for (i = 0; i < (int)writeFDsLen; i++)
|
|
{
|
|
fd = jcgo_JnuGetIntArrayElement(pJniEnv, writeFDs, i);
|
|
if (fd != -1 && !FD_ISSET((unsigned)fd, &fdswrite))
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, writeFDs, i, -1);
|
|
}
|
|
for (i = 0; i < (int)exceptFDsLen; i++)
|
|
{
|
|
fd = jcgo_JnuGetIntArrayElement(pJniEnv, exceptFDs, i);
|
|
if (fd != -1 && !FD_ISSET((unsigned)fd, &fdsexcept))
|
|
jcgo_JnuSetIntArrayElement(pJniEnv, exceptFDs, i, -1);
|
|
}
|
|
#endif
|
|
#endif
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(readFDs);
|
|
JCGO_UNUSED_VAR(readFDsLen);
|
|
JCGO_UNUSED_VAR(writeFDs);
|
|
JCGO_UNUSED_VAR(writeFDsLen);
|
|
JCGO_UNUSED_VAR(exceptFDs);
|
|
JCGO_UNUSED_VAR(exceptFDsLen);
|
|
JCGO_UNUSED_VAR(timeout);
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketSetNonBlocking0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketSetNonBlocking0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jint on )
|
|
{
|
|
#ifdef JCGO_INET
|
|
#ifdef FIONBIO
|
|
JCGO_SOCKFIONBIO_T value = 0;
|
|
int res;
|
|
int errcode = 0;
|
|
if ((int)on)
|
|
value++;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_IOCTL((int)fd, FIONBIO, value, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res)
|
|
return (jint)(res >= 0 ? res : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(on);
|
|
#endif
|
|
#else
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(on);
|
|
#endif
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketAvailable0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketAvailable0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd )
|
|
{
|
|
#ifdef JCGO_INET
|
|
#ifdef FIONREAD
|
|
JCGO_SOCKFIONREAD_T value = 0;
|
|
int res;
|
|
int errcode = 0;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_IOCTL((int)fd, FIONREAD, value, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res < 0)
|
|
return (jint)-errcode;
|
|
if ((jint)value > 0)
|
|
return (jint)value;
|
|
#else
|
|
JCGO_UNUSED_VAR(fd);
|
|
#endif
|
|
#else
|
|
JCGO_UNUSED_VAR(fd);
|
|
#endif
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketListen0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketListen0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jint backlog )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_LISTEN((int)fd, backlog < (jint)(((unsigned)-1) >> 1) ?
|
|
(int)backlog : (int)(((unsigned)-1) >> 1) - 1, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
return (jint)(res >= 0 ? res : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(backlog);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketGetSetOption0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketGetSetOption0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jint optionId, jint optval )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
int optionid;
|
|
int level = (int)SOL_SOCKET;
|
|
struct linger lingval;
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
switch ((int)optionId)
|
|
{
|
|
case JCGO_JSOCKOPT_NODELAY:
|
|
level = IPPROTO_TCP;
|
|
optionid = TCP_NODELAY;
|
|
break;
|
|
case JCGO_JSOCKOPT_TOS:
|
|
level = IPPROTO_IP;
|
|
optionid = IP_TOS;
|
|
break;
|
|
case JCGO_JSOCKOPT_REUSEADDR:
|
|
optionid = SO_REUSEADDR;
|
|
break;
|
|
case JCGO_JSOCKOPT_KEEPALIVE:
|
|
optionid = SO_KEEPALIVE;
|
|
break;
|
|
case JCGO_JSOCKOPT_LOOP:
|
|
level = IPPROTO_IP;
|
|
optionid = IP_MULTICAST_LOOP;
|
|
break;
|
|
case JCGO_JSOCKOPT_BROADCAST:
|
|
optionid = SO_BROADCAST;
|
|
break;
|
|
case JCGO_JSOCKOPT_LINGER:
|
|
optionid = SO_LINGER;
|
|
break;
|
|
case JCGO_JSOCKOPT_SNDBUF:
|
|
optionid = SO_SNDBUF;
|
|
break;
|
|
case JCGO_JSOCKOPT_RCVBUF:
|
|
optionid = SO_RCVBUF;
|
|
break;
|
|
case JCGO_JSOCKOPT_OOBINLINE:
|
|
optionid = SO_OOBINLINE;
|
|
break;
|
|
case JCGO_JSOCKOPT_TTL:
|
|
level = IPPROTO_IP;
|
|
optionid = IP_MULTICAST_TTL;
|
|
break;
|
|
default:
|
|
return -SOCEINVAL;
|
|
}
|
|
if (optval >= 0)
|
|
{
|
|
if ((int)optionId == JCGO_JSOCKOPT_LINGER)
|
|
{
|
|
res = (int)sizeof(lingval);
|
|
while (res-- > 0)
|
|
*((volatile char *)&lingval + res) = '\0';
|
|
if (optval > 0)
|
|
{
|
|
lingval.l_onoff = (unsigned char)1;
|
|
lingval.l_linger = (JCGO_SOCKLLINGER_T)(optval - 1);
|
|
}
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SETSOCKOPT((int)fd, level, optionid, &lingval,
|
|
sizeof(lingval), &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
}
|
|
else
|
|
{
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SETSOCKOPT((int)fd, level, optionid, &optval,
|
|
sizeof(optval), &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res < 0 && ((errcode == SOCEINVAL &&
|
|
(int)optionId == JCGO_JSOCKOPT_TOS) ||
|
|
(errcode == SOCENOPROTOOPT && ((int)optionId == JCGO_JSOCKOPT_TOS ||
|
|
(int)optionId == JCGO_JSOCKOPT_LOOP))))
|
|
res = 0;
|
|
}
|
|
optval = (jint)res;
|
|
}
|
|
else
|
|
{
|
|
optval = 0;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
if ((int)optionId == JCGO_JSOCKOPT_LINGER)
|
|
{
|
|
res = JCGO_SOCK_GETSOCKOPT((int)fd, level, optionid, &lingval,
|
|
sizeof(lingval), &errcode);
|
|
if (lingval.l_onoff)
|
|
optval = (jint)lingval.l_linger + 1;
|
|
}
|
|
else res = JCGO_SOCK_GETSOCKOPT((int)fd, level, optionid, &optval,
|
|
sizeof(optval), &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res < 0 && errcode == SOCENOPROTOOPT &&
|
|
(int)optionId == JCGO_JSOCKOPT_TOS)
|
|
res = 0;
|
|
if (optval <= 0)
|
|
optval = 0;
|
|
}
|
|
return res >= 0 ? optval : (jint)-errcode;
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(optionId);
|
|
JCGO_UNUSED_VAR(optval);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketSetMulticastAddr0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketSetMulticastAddr0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray ip, jint iplen )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
int level = IPPROTO_IP;
|
|
int optionid = IP_MULTICAST_IF;
|
|
char *address =
|
|
(char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, iplen);
|
|
JCGO_UNUSED_VAR(This);
|
|
if (address == NULL)
|
|
return 0;
|
|
#ifdef JCGO_IPV6_PRESENT
|
|
if ((int)iplen == 16)
|
|
{
|
|
level = IPPROTO_IPV6;
|
|
optionid = IPV6_MULTICAST_IF;
|
|
}
|
|
#endif
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SETSOCKOPT((int)fd, level, optionid, address,
|
|
(unsigned)iplen, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
return (jint)(res >= 0 ? res : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(iplen);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketGetMulticastAddr0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketGetMulticastAddr0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray ip, jint ipmaxlen )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode;
|
|
char *address =
|
|
(char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, ipmaxlen);
|
|
JCGO_UNUSED_VAR(This);
|
|
if (address == NULL)
|
|
return 0;
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_GETSOCKOPT((int)fd, IPPROTO_IP, IP_MULTICAST_IF, address,
|
|
(unsigned)ipmaxlen, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
return (jint)(res >= 0 ? errcode : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(ipmaxlen);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketMulticastGroup0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketMulticastGroup0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jbyteArray ip, jint iplen, jbyteArray ipNetIf,
|
|
jint iplenNetIf, jint join )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res = -SOCEAFNOSUPPORT;
|
|
int errcode = 0;
|
|
int level = IPPROTO_IP;
|
|
int optionid;
|
|
int i;
|
|
char *address;
|
|
struct ip_mreq mreq;
|
|
JCGO_UNUSED_VAR(This);
|
|
if (iplen <= (jint)sizeof(mreq.imr_multiaddr) &&
|
|
iplenNetIf <= (jint)sizeof(mreq.imr_interface))
|
|
{
|
|
address = (char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ip, 0, iplen);
|
|
if (address == NULL)
|
|
return 0;
|
|
i = (int)iplen;
|
|
while (i-- > 0)
|
|
*((volatile char *)&mreq.imr_multiaddr + i) = *(address + i);
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ip, (jbyte *)address, 0);
|
|
address =
|
|
(char *)jcgo_JnuGetByteArrayElemsRegion(pJniEnv, ipNetIf, 0, iplenNetIf);
|
|
if (address == NULL)
|
|
return 0;
|
|
i = (int)iplenNetIf;
|
|
while (i-- > 0)
|
|
*((volatile char *)&mreq.imr_interface + i) = *(address + i);
|
|
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, ipNetIf, (jbyte *)address, 0);
|
|
optionid = (int)join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
|
|
#ifdef JCGO_IPV6_PRESENT
|
|
if ((int)iplen == 16)
|
|
{
|
|
level = IPPROTO_IPV6;
|
|
optionid = (int)join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP;
|
|
}
|
|
#endif
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SETSOCKOPT((int)fd, level, optionid, &mreq, sizeof(mreq),
|
|
&errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
if (res < 0)
|
|
res = -errcode;
|
|
}
|
|
return (jint)res;
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(ip);
|
|
JCGO_UNUSED_VAR(iplen);
|
|
JCGO_UNUSED_VAR(ipNetIf);
|
|
JCGO_UNUSED_VAR(iplenNetIf);
|
|
JCGO_UNUSED_VAR(join);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketShutdown0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketShutdown0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd, jint input, jint output )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_SHUTDOWN((int)fd, (int)input ?
|
|
((int)output ? SD_BOTH : SD_RECEIVE) : SD_SEND, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
return (jint)(res >= 0 ? res : -errcode);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
JCGO_UNUSED_VAR(input);
|
|
JCGO_UNUSED_VAR(output);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef NOJAVA_gnu_java_net_VMPlainSocketImpl_socketClose0
|
|
JCGO_JNI_EXPF(jint,
|
|
Java_gnu_java_net_VMPlainSocketImpl_socketClose0)( JNIEnv *pJniEnv,
|
|
jclass This, jint fd )
|
|
{
|
|
#ifdef JCGO_INET
|
|
int res;
|
|
int errcode = 0;
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_SOCKCALL_BEGIN(pJniEnv)
|
|
res = JCGO_SOCK_CLOSE((int)fd, &errcode);
|
|
JCGO_SOCKCALL_END(pJniEnv)
|
|
return (jint)(res < 0 && errcode != SOCEBADF && errcode != SOCECONNRESET &&
|
|
errcode != SOCENOTCONN ? -errcode : 0);
|
|
#else
|
|
JCGO_UNUSED_VAR(pJniEnv);
|
|
JCGO_UNUSED_VAR(This);
|
|
JCGO_UNUSED_VAR(fd);
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#endif
|