37
#include "java_net_InetAddress.h"
38
#include "sun_nio_ch_Net.h"
39
#include "sun_nio_ch_PollArrayWrapper.h"
42
static GUID MS_PROVIDER_ID = {0xA00943D9,0x9C2E,0x4633,{0x9B,0x59,0,0x57,0xA3,0x16,0x09,0x94}};
44
jbyteArray sockaddrToUnixAddressBytes(JNIEnv *env, struct sockaddr_un *sa, socklen_t len)
46
if (sa->sun_family == AF_UNIX) {
47
int namelen = (int)strlen(sa->sun_path);
48
jbyteArray name = (*env)->NewByteArray(env, namelen);
50
(*env)->SetByteArrayRegion(env, name, 0, namelen, (jbyte*)sa->sun_path);
51
if ((*env)->ExceptionOccurred(env)) {
60
jint unixSocketAddressToSockaddr(JNIEnv *env, jbyteArray addr, struct sockaddr_un *sa, int *len)
62
memset(sa, 0, sizeof(struct sockaddr_un));
63
sa->sun_family = AF_UNIX;
66
*len = (int)(offsetof(struct sockaddr_un, sun_path));
71
char *pname = (*env)->GetByteArrayElements(env, addr, &isCopy);
73
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unix domain path not present");
77
size_t name_len = (size_t)(*env)->GetArrayLength(env, addr);
78
if (name_len > MAX_UNIX_DOMAIN_PATH_LEN) {
79
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unix domain path too long");
82
strncpy(sa->sun_path, pname, name_len);
83
*len = (int)(offsetof(struct sockaddr_un, sun_path) + name_len);
86
(*env)->ReleaseByteArrayElements(env, addr, pname, JNI_ABORT);
90
static int cmpGuid(GUID *g1, GUID *g2) {
91
if (g1->Data1 != g2->Data1)
93
if (g1->Data2 != g2->Data2)
95
if (g1->Data3 != g2->Data3)
97
for (int i=0; i<8; i++) {
98
if (g1->Data4[i] != g2->Data4[i])
104
static WSAPROTOCOL_INFOW provider;
106
JNIEXPORT jboolean JNICALL
107
Java_sun_nio_ch_UnixDomainSockets_init(JNIEnv *env, jclass cl)
109
WSAPROTOCOL_INFOW info[5];
110
LPWSAPROTOCOL_INFOW infoPtr = &info[0];
111
DWORD len = sizeof(info);
112
jboolean found = JNI_FALSE;
117
int result = WSAEnumProtocolsW(0, infoPtr, &len);
118
if (result == SOCKET_ERROR) {
119
if (GetLastError() == WSAENOBUFS) {
120
infoPtr = (LPWSAPROTOCOL_INFOW)malloc(len);
121
if (infoPtr == NULL) {
124
result = WSAEnumProtocolsW(0, infoPtr, &len);
125
if (result == SOCKET_ERROR) {
133
for (int i=0; i<result; i++) {
134
if (infoPtr[i].iAddressFamily == AF_UNIX) {
135
GUID g = infoPtr[i].ProviderId;
136
if (cmpGuid(&g, &MS_PROVIDER_ID)) {
138
provider = infoPtr[i];
143
if (infoPtr != &info[0]) {
150
SOCKET s = WSASocketW(PF_UNIX, SOCK_STREAM, 0, &provider, 0, WSA_FLAG_OVERLAPPED);
151
if (s == INVALID_SOCKET) {
159
JNIEXPORT jint JNICALL
160
Java_sun_nio_ch_UnixDomainSockets_socket0(JNIEnv *env, jclass cl)
162
SOCKET s = WSASocketW(PF_UNIX, SOCK_STREAM, 0, &provider, 0, WSA_FLAG_OVERLAPPED);
163
if (s == INVALID_SOCKET) {
164
NET_ThrowNew(env, WSAGetLastError(), "WSASocketW");
167
SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
175
JNIEXPORT void JNICALL
176
Java_sun_nio_ch_UnixDomainSockets_bind0(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray addr)
178
struct sockaddr_un sa;
182
if (unixSocketAddressToSockaddr(env, addr, &sa, &sa_len) != 0)
185
rv = bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
186
if (rv == SOCKET_ERROR) {
187
int err = WSAGetLastError();
188
NET_ThrowNew(env, err, "bind");
192
JNIEXPORT jint JNICALL
193
Java_sun_nio_ch_UnixDomainSockets_connect0(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray addr)
195
struct sockaddr_un sa;
199
if (unixSocketAddressToSockaddr(env, addr, &sa, &sa_len) != 0) {
203
rv = connect(fdval(env, fdo), (const struct sockaddr *)&sa, sa_len);
205
int err = WSAGetLastError();
206
if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) {
207
return IOS_UNAVAILABLE;
209
NET_ThrowNew(env, err, "connect");
215
JNIEXPORT jint JNICALL
216
Java_sun_nio_ch_UnixDomainSockets_accept0(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo,
219
jint fd = fdval(env, fdo);
221
struct sockaddr_un sa;
222
socklen_t sa_len = sizeof(sa);
225
memset((char *)&sa, 0, sizeof(sa));
226
newfd = (jint) accept(fd, (struct sockaddr *)&sa, &sa_len);
227
if (newfd == INVALID_SOCKET) {
228
int theErr = (jint)WSAGetLastError();
229
if (theErr == WSAEWOULDBLOCK) {
230
return IOS_UNAVAILABLE;
232
JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
236
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
237
setfdval(env, newfdo, newfd);
239
address = sockaddrToUnixAddressBytes(env, &sa, sa_len);
240
CHECK_NULL_RETURN(address, IOS_THROWN);
241
(*env)->SetObjectArrayElement(env, array, 0, address);
246
JNIEXPORT jbyteArray JNICALL
247
Java_sun_nio_ch_UnixDomainSockets_localAddress0(JNIEnv *env, jclass clazz, jobject fdo)
249
struct sockaddr_un sa;
250
int sa_len = sizeof(sa);
252
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) == SOCKET_ERROR) {
253
JNU_ThrowIOExceptionWithLastError(env, "getsockname");
256
return sockaddrToUnixAddressBytes(env, &sa, sa_len);