75 DWORD bytesReturned = 0; |
75 DWORD bytesReturned = 0; |
76 WSAIoctl(s, SIO_UDP_CONNRESET, &enable, sizeof(enable), |
76 WSAIoctl(s, SIO_UDP_CONNRESET, &enable, sizeof(enable), |
77 NULL, 0, &bytesReturned, NULL, NULL); |
77 NULL, 0, &bytesReturned, NULL, NULL); |
78 } |
78 } |
79 |
79 |
80 jint handleSocketError(JNIEnv *env, int errorValue) |
80 JNIEXPORT jint JNICALL |
|
81 handleSocketError(JNIEnv *env, int errorValue) |
81 { |
82 { |
82 NET_ThrowNew(env, errorValue, NULL); |
83 NET_ThrowNew(env, errorValue, NULL); |
83 return IOS_THROWN; |
84 return IOS_THROWN; |
84 } |
85 } |
85 |
86 |
86 static jclass isa_class; /* java.net.InetSocketAddress */ |
87 static jclass isa_class; /* java.net.InetSocketAddress */ |
87 static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */ |
88 static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */ |
|
89 |
|
90 extern jclass udsa_class; |
|
91 extern jmethodID udsa_ctorID; |
|
92 extern jfieldID udsa_pathID; |
|
93 extern jfieldID udsa_isAbstractID; |
|
94 |
|
95 JNIEXPORT jobject JNICALL |
|
96 NET_SockaddrToUnixAddress(JNIEnv *env, SOCKETADDRESS *sa) { |
|
97 jboolean isAbstract; |
|
98 |
|
99 if (sa->sa.sa_family == AF_UNIX) { |
|
100 char *name = sa->saun.sun_path; |
|
101 |
|
102 #ifdef NOTDEF |
|
103 /* check for abstract name */ |
|
104 if (name[0] == 0) { |
|
105 isAbstract = 1; |
|
106 name++; // skip the zero byte |
|
107 } else |
|
108 #endif |
|
109 isAbstract = 0; |
|
110 jstring nstr = JNU_NewStringPlatform(env, name); |
|
111 return (*env)->NewObject(env, udsa_class, udsa_ctorID, nstr); |
|
112 } |
|
113 return NULL; |
|
114 } |
|
115 |
|
116 JNIEXPORT jint JNICALL |
|
117 NET_UnixSocketAddressToSockaddr(JNIEnv *env, jobject uaddr, SOCKETADDRESS *sa, int *len) |
|
118 { |
|
119 jstring path = (*env)->GetObjectField(env, uaddr, udsa_pathID); |
|
120 jboolean isCopy; |
|
121 //jboolean isAbstract = (*env)->GetBooleanField(env, uaddr, udsa_isAbstractID); |
|
122 int ret; |
|
123 const char* pname = JNU_GetStringPlatformChars(env, path, &isCopy); |
|
124 memset(sa, 0, sizeof(SOCKETADDRESS)); |
|
125 sa->saun.sun_family = AF_UNIX; |
|
126 size_t name_len = strlen(pname)+1; |
|
127 if (name_len > MAX_UNIX_DOMAIN_PATH_LEN) { |
|
128 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "unix domain path too long"); |
|
129 ret = 1; |
|
130 goto finish; |
|
131 } |
|
132 #ifdef NOTDEF |
|
133 if (isAbstract) { |
|
134 strncpy(&sa->saun.sun_path[1], pname, name_len); |
|
135 sa->saun.sun_path[0] = 0; |
|
136 name_len++; |
|
137 } else |
|
138 #endif |
|
139 { |
|
140 strncpy(sa->saun.sun_path, pname, name_len); |
|
141 } |
|
142 *len = (int)(offsetof(struct sockaddr_un, sun_path) + name_len); |
|
143 ret = 0; |
|
144 finish: |
|
145 if (isCopy) |
|
146 JNU_ReleaseStringPlatformChars(env, path, pname); |
|
147 return ret; |
|
148 } |
|
149 |
|
150 JNIEXPORT jboolean JNICALL |
|
151 Java_sun_nio_ch_Net_unixDomainSocketSupported(JNIEnv *env, jclass cl) |
|
152 { |
|
153 SOCKET fd = socket(PF_UNIX, SOCK_STREAM, 0); |
|
154 if (fd < 0) { |
|
155 return JNI_FALSE; |
|
156 } |
|
157 closesocket(fd); |
|
158 return JNI_TRUE; |
|
159 } |
|
160 |
|
161 JNIEXPORT jint JNICALL |
|
162 Java_sun_nio_ch_Net_unixDomainSocket0(JNIEnv *env, jclass cl) |
|
163 { |
|
164 SOCKET fd = socket(PF_UNIX, SOCK_STREAM, 0); |
|
165 if (fd < 0) { |
|
166 return handleSocketError(env, errno); |
|
167 } |
|
168 return (int)fd; |
|
169 } |
|
170 |
|
171 JNIEXPORT void JNICALL |
|
172 Java_sun_nio_ch_Net_unixDomainBind(JNIEnv *env, jclass clazz, jobject fdo, jobject uaddr) |
|
173 { |
|
174 SOCKETADDRESS sa; |
|
175 int sa_len = 0; |
|
176 int rv = 0; |
|
177 |
|
178 if (NET_UnixSocketAddressToSockaddr(env, uaddr, &sa, &sa_len) != 0) |
|
179 return; |
|
180 |
|
181 int fd = fdval(env, fdo); |
|
182 |
|
183 rv = NET_Bind(fdval(env, fdo), &sa, sa_len); |
|
184 if (rv != 0) { |
|
185 int err = WSAGetLastError(); |
|
186 NET_ThrowNew(env, err, "bind"); |
|
187 } |
|
188 } |
|
189 |
|
190 JNIEXPORT jint JNICALL |
|
191 Java_sun_nio_ch_Net_unixDomainConnect(JNIEnv *env, jclass clazz, jobject fdo, jobject usa) |
|
192 { |
|
193 SOCKETADDRESS sa; |
|
194 int sa_len = 0; |
|
195 int rv; |
|
196 |
|
197 if (NET_UnixSocketAddressToSockaddr(env, usa, &sa, &sa_len) != 0) { |
|
198 return IOS_THROWN; |
|
199 } |
|
200 |
|
201 rv = connect(fdval(env, fdo), (const struct sockaddr *)&sa.saun, sa_len); |
|
202 if (rv != 0) { |
|
203 int err = WSAGetLastError(); |
|
204 if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) { |
|
205 return IOS_UNAVAILABLE; |
|
206 } |
|
207 NET_ThrowNew(env, err, "connect"); |
|
208 return IOS_THROWN; |
|
209 } |
|
210 return 1; |
|
211 } |
|
212 |
|
213 JNIEXPORT jint JNICALL |
|
214 Java_sun_nio_ch_Net_unixDomainAccept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo, |
|
215 jobjectArray usaa) |
|
216 { |
|
217 jint fd = fdval(env, fdo); |
|
218 jint newfd; |
|
219 SOCKETADDRESS sa; |
|
220 socklen_t sa_len = sizeof(SOCKETADDRESS); |
|
221 jobject usa; |
|
222 |
|
223 /* accept connection but ignore ECONNABORTED */ |
|
224 for (;;) { |
|
225 newfd = (jint)accept(fd, &sa.sa, &sa_len); |
|
226 if (newfd >= 0) { |
|
227 break; |
|
228 } |
|
229 if (errno != ECONNABORTED) { |
|
230 break; |
|
231 } |
|
232 /* ECONNABORTED => restart accept */ |
|
233 } |
|
234 |
|
235 if (newfd < 0) { |
|
236 if (errno == EAGAIN || errno == EWOULDBLOCK) |
|
237 return IOS_UNAVAILABLE; |
|
238 if (errno == EINTR) |
|
239 return IOS_INTERRUPTED; |
|
240 JNU_ThrowIOExceptionWithLastError(env, "Accept failed"); |
|
241 return IOS_THROWN; |
|
242 } |
|
243 |
|
244 setfdval(env, newfdo, newfd); |
|
245 |
|
246 usa = NET_SockaddrToUnixAddress(env, &sa); |
|
247 CHECK_NULL_RETURN(usa, IOS_THROWN); |
|
248 |
|
249 (*env)->SetObjectArrayElement(env, usaa, 0, usa); |
|
250 |
|
251 return 1; |
|
252 } |
|
253 |
|
254 JNIEXPORT jobject JNICALL |
|
255 Java_sun_nio_ch_Net_localUnixAddress(JNIEnv *env, jclass clazz, jobject fdo) |
|
256 { |
|
257 SOCKETADDRESS sa; |
|
258 socklen_t sa_len = sizeof(SOCKETADDRESS); |
|
259 if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) { |
|
260 handleSocketError(env, errno); |
|
261 return NULL; |
|
262 } |
|
263 return NET_SockaddrToUnixAddress(env, &sa); |
|
264 } |
88 |
265 |
89 JNIEXPORT void JNICALL |
266 JNIEXPORT void JNICALL |
90 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) |
267 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) |
91 { |
268 { |
92 jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); |
269 jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); |