blob: b9fac794e45d19835e972b642e84b866e5832022 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include <windows.h>
27#include <winsock2.h>
28#include "jni.h"
29#include "jni_util.h"
30#include "jvm.h"
31#include "jlong.h"
32
33#include "nio.h"
34#include "nio_util.h"
35#include "net_util.h"
36
37#include "sun_nio_ch_Net.h"
38
39
40static jfieldID ia_addrID;
41static jclass ia_class;
42static jmethodID ia_ctorID;
43static jfieldID ia_famID;
44
45/**************************************************************
46 * static method to store field IDs in initializers
47 */
48
49JNIEXPORT void JNICALL
50Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
51{
52 clazz = (*env)->FindClass(env, "java/net/Inet4Address");
53 ia_class = (*env)->NewGlobalRef(env, clazz);
54 ia_addrID = (*env)->GetFieldID(env, clazz, "address", "I");
55 ia_famID = (*env)->GetFieldID(env, clazz, "family", "I");
56 ia_ctorID = (*env)->GetMethodID(env, clazz, "<init>", "()V");
57}
58
59
60JNIEXPORT jint JNICALL
61Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
62 jboolean reuse)
63{
64 SOCKET s;
65
66 s = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
67 if (s != INVALID_SOCKET) {
68 SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
69 } else {
70 NET_ThrowNew(env, WSAGetLastError(), "socket");
71 }
72 return (jint)s;
73}
74
75JNIEXPORT void JNICALL
76Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz,
77 jobject fdo, jobject iao, jint port)
78{
79 SOCKETADDRESS sa;
80 int rv;
81 int sa_len = sizeof(sa);
82
83 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) {
84 return;
85 }
86
87 rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
88 if (rv == SOCKET_ERROR)
89 NET_ThrowNew(env, WSAGetLastError(), "bind");
90}
91
92JNIEXPORT jint JNICALL
93Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz, jobject fdo, jobject iao,
94 jint port, jint trafficClass)
95{
96 SOCKETADDRESS sa;
97 int rv;
98 int sa_len = sizeof(sa);
99
100 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) {
101 return IOS_THROWN;
102 }
103
104 rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
105 if (rv != 0) {
106 int err = WSAGetLastError();
107 if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) {
108 return IOS_UNAVAILABLE;
109 }
110 NET_ThrowNew(env, err, "connect");
111 return IOS_THROWN;
112 }
113 return 1;
114}
115
116JNIEXPORT jint JNICALL
117Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
118{
119 struct sockaddr_in sa;
120 int sa_len = sizeof(sa);
121
122 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
123 int error = WSAGetLastError();
124 if (error == WSAEINVAL) {
125 return 0;
126 }
127 NET_ThrowNew(env, error, "getsockname");
128 return IOS_THROWN;
129 }
130 return (jint)ntohs(sa.sin_port);
131}
132
133JNIEXPORT jobject JNICALL
134Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
135{
136 struct sockaddr_in sa;
137 int sa_len = sizeof(sa);
138 jobject iao;
139
140 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
141 NET_ThrowNew(env, WSAGetLastError(), "getsockname");
142 return NULL;
143 }
144
145 iao = (*env)->NewObject(env, ia_class, ia_ctorID);
146 if (iao == NULL) {
147 JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
148 } else {
149 (*env)->SetIntField(env, iao, ia_addrID, ntohl(sa.sin_addr.s_addr));
150 }
151
152 return iao;
153}
154
155
156JNIEXPORT jint JNICALL
157Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
158 jobject fdo, jint opt)
159{
160 int klevel, kopt;
161 int result;
162 struct linger linger;
163 char *arg;
164 int arglen;
165
166 if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
167 JNU_ThrowByNameWithLastError(env,
168 JNU_JAVANETPKG "SocketException",
169 "Unsupported socket option");
170 return IOS_THROWN;
171 }
172
173 if (opt == java_net_SocketOptions_SO_LINGER) {
174 arg = (char *)&linger;
175 arglen = sizeof(linger);
176 } else {
177 arg = (char *)&result;
178 arglen = sizeof(result);
179 }
180
181 if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) {
182 NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption");
183 return IOS_THROWN;
184 }
185
186 if (opt == java_net_SocketOptions_SO_LINGER)
187 return linger.l_onoff ? linger.l_linger : -1;
188 else
189 return result;
190}
191
192JNIEXPORT void JNICALL
193Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
194 jobject fdo, jint opt, jint arg)
195{
196 int klevel, kopt;
197 struct linger linger;
198 char *parg;
199 int arglen;
200
201 if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
202 JNU_ThrowByNameWithLastError(env,
203 JNU_JAVANETPKG "SocketException",
204 "Unsupported socket option");
205 return;
206 }
207
208 if (opt == java_net_SocketOptions_SO_LINGER) {
209 parg = (char *)&linger;
210 arglen = sizeof(linger);
211 if (arg >= 0) {
212 linger.l_onoff = 1;
213 linger.l_linger = (unsigned short)arg;
214 } else {
215 linger.l_onoff = 0;
216 linger.l_linger = 0;
217 }
218 } else {
219 parg = (char *)&arg;
220 arglen = sizeof(arg);
221 }
222
223 if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
224 NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption");
225 }
226}