annotate src/solaris/native/sun/nio/ch/Net.c @ 0:37a05a11f281

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children 939fd6c3984a 8bb706922a08
rev   line source
duke@0 1 /*
duke@0 2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
duke@0 7 * published by the Free Software Foundation. Sun designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
duke@0 9 * by Sun in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
duke@0 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@0 22 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@0 23 * have any questions.
duke@0 24 */
duke@0 25
duke@0 26 #include <sys/types.h>
duke@0 27 #include <sys/socket.h>
duke@0 28 #include <string.h>
duke@0 29 #include <netinet/in.h>
duke@0 30 #include <netinet/tcp.h>
duke@0 31
duke@0 32 #include "jni.h"
duke@0 33 #include "jni_util.h"
duke@0 34 #include "jvm.h"
duke@0 35 #include "jlong.h"
duke@0 36 #include "sun_nio_ch_Net.h"
duke@0 37 #include "net_util.h"
duke@0 38 #include "net_util_md.h"
duke@0 39 #include "nio_util.h"
duke@0 40 #include "java_net_SocketOptions.h"
duke@0 41 #include "nio.h"
duke@0 42
duke@0 43 #ifdef __linux__
duke@0 44 #include <sys/utsname.h>
duke@0 45
duke@0 46 #define IPV6_MULTICAST_IF 17
duke@0 47 #ifndef SO_BSDCOMPAT
duke@0 48 #define SO_BSDCOMPAT 14
duke@0 49 #endif
duke@0 50 #endif
duke@0 51
duke@0 52 JNIEXPORT void JNICALL
duke@0 53 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
duke@0 54 {
duke@0 55 /* Here because Windows native code does need to init IDs */
duke@0 56 }
duke@0 57
duke@0 58 JNIEXPORT int JNICALL
duke@0 59 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
duke@0 60 jboolean reuse)
duke@0 61 {
duke@0 62 int fd;
duke@0 63
duke@0 64 #ifdef AF_INET6
duke@0 65 if (ipv6_available())
duke@0 66 fd = socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
duke@0 67 else
duke@0 68 #endif /* AF_INET6 */
duke@0 69 fd = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
duke@0 70
duke@0 71 if (fd < 0) {
duke@0 72 return handleSocketError(env, errno);
duke@0 73 }
duke@0 74 if (reuse) {
duke@0 75 int arg = 1;
duke@0 76 if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
duke@0 77 sizeof(arg)) < 0) {
duke@0 78 JNU_ThrowByNameWithLastError(env,
duke@0 79 JNU_JAVANETPKG "SocketException",
duke@0 80 "sun.nio.ch.Net.setIntOption");
duke@0 81 }
duke@0 82 }
duke@0 83 return fd;
duke@0 84 }
duke@0 85
duke@0 86 JNIEXPORT void JNICALL
duke@0 87 Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk */
duke@0 88 jobject fdo, jobject ia, int port)
duke@0 89 {
duke@0 90 SOCKADDR sa;
duke@0 91 int sa_len = SOCKADDR_LEN;
duke@0 92 int rv = 0;
duke@0 93
duke@0 94 if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) {
duke@0 95 return;
duke@0 96 }
duke@0 97
duke@0 98 rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
duke@0 99 if (rv != 0) {
duke@0 100 handleSocketError(env, errno);
duke@0 101 }
duke@0 102 }
duke@0 103
duke@0 104 JNIEXPORT jint JNICALL
duke@0 105 Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz,
duke@0 106 jobject fdo, jobject iao, jint port,
duke@0 107 jint trafficClass)
duke@0 108 {
duke@0 109 SOCKADDR sa;
duke@0 110 int sa_len = SOCKADDR_LEN;
duke@0 111 int rv;
duke@0 112
duke@0 113 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len, JNI_TRUE) != 0) {
duke@0 114 return IOS_THROWN;
duke@0 115 }
duke@0 116
duke@0 117 #ifdef AF_INET6
duke@0 118 #if 0
duke@0 119 if (trafficClass != 0 && ipv6_available()) { /* ## FIX */
duke@0 120 NET_SetTrafficClass((struct sockaddr *)&sa, trafficClass);
duke@0 121 }
duke@0 122 #endif
duke@0 123 #endif
duke@0 124
duke@0 125 rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
duke@0 126 if (rv != 0) {
duke@0 127 if (errno == EINPROGRESS) {
duke@0 128 return IOS_UNAVAILABLE;
duke@0 129 } else if (errno == EINTR) {
duke@0 130 return IOS_INTERRUPTED;
duke@0 131 }
duke@0 132 return handleSocketError(env, errno);
duke@0 133 }
duke@0 134 return 1;
duke@0 135 }
duke@0 136
duke@0 137 JNIEXPORT jint JNICALL
duke@0 138 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
duke@0 139 {
duke@0 140 SOCKADDR sa;
duke@0 141 int sa_len = SOCKADDR_LEN;
duke@0 142 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
duke@0 143 handleSocketError(env, errno);
duke@0 144 return -1;
duke@0 145 }
duke@0 146 return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
duke@0 147 }
duke@0 148
duke@0 149 JNIEXPORT jobject JNICALL
duke@0 150 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
duke@0 151 {
duke@0 152 SOCKADDR sa;
duke@0 153 int sa_len = SOCKADDR_LEN;
duke@0 154 int port;
duke@0 155 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
duke@0 156 handleSocketError(env, errno);
duke@0 157 return NULL;
duke@0 158 }
duke@0 159 return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
duke@0 160 }
duke@0 161
duke@0 162
duke@0 163 #ifdef NEEDED
duke@0 164
duke@0 165 /* ## This is gross. We should generate platform-specific constant
duke@0 166 * ## definitions into a .java file and use those directly.
duke@0 167 */
duke@0 168
duke@0 169 static int
duke@0 170 mapOption(JNIEnv *env, int opt, int *klevel, int *kopt)
duke@0 171 {
duke@0 172
duke@0 173 switch (opt) {
duke@0 174
duke@0 175 case java_net_SocketOptions_IP_TOS:
duke@0 176 *klevel = IPPROTO_IP;
duke@0 177 *kopt = IP_TOS;
duke@0 178 break;
duke@0 179
duke@0 180 case java_net_SocketOptions_SO_BROADCAST:
duke@0 181 case java_net_SocketOptions_SO_KEEPALIVE:
duke@0 182 case java_net_SocketOptions_SO_LINGER:
duke@0 183 case java_net_SocketOptions_SO_OOBINLINE:
duke@0 184 case java_net_SocketOptions_SO_RCVBUF:
duke@0 185 case java_net_SocketOptions_SO_REUSEADDR:
duke@0 186 case java_net_SocketOptions_SO_SNDBUF:
duke@0 187 *klevel = SOL_SOCKET;
duke@0 188 break;
duke@0 189
duke@0 190 case java_net_SocketOptions_TCP_NODELAY:
duke@0 191 *klevel = IPPROTO_IP;
duke@0 192 *kopt = TCP_NODELAY;
duke@0 193 return 0;
duke@0 194
duke@0 195 default:
duke@0 196 JNU_ThrowByName(env, "java/lang/IllegalArgumentException", NULL);
duke@0 197 return -1;
duke@0 198 }
duke@0 199
duke@0 200 switch (opt) {
duke@0 201
duke@0 202 case java_net_SocketOptions_SO_BROADCAST: *kopt = SO_BROADCAST; break;
duke@0 203 case java_net_SocketOptions_SO_KEEPALIVE: *kopt = SO_KEEPALIVE; break;
duke@0 204 case java_net_SocketOptions_SO_LINGER: *kopt = SO_LINGER; break;
duke@0 205 case java_net_SocketOptions_SO_OOBINLINE: *kopt = SO_OOBINLINE; break;
duke@0 206 case java_net_SocketOptions_SO_RCVBUF: *kopt = SO_RCVBUF; break;
duke@0 207 case java_net_SocketOptions_SO_REUSEADDR: *kopt = SO_REUSEADDR; break;
duke@0 208 case java_net_SocketOptions_SO_SNDBUF: *kopt = SO_SNDBUF; break;
duke@0 209
duke@0 210 default:
duke@0 211 return -1;
duke@0 212 }
duke@0 213
duke@0 214 return 0;
duke@0 215 }
duke@0 216 #endif
duke@0 217
duke@0 218
duke@0 219 JNIEXPORT jint JNICALL
duke@0 220 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
duke@0 221 jobject fdo, jint opt)
duke@0 222 {
duke@0 223 int klevel, kopt;
duke@0 224 int result;
duke@0 225 struct linger linger;
duke@0 226 void *arg;
duke@0 227 int arglen;
duke@0 228
duke@0 229 if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
duke@0 230 JNU_ThrowByNameWithLastError(env,
duke@0 231 JNU_JAVANETPKG "SocketException",
duke@0 232 "Unsupported socket option");
duke@0 233 return -1;
duke@0 234 }
duke@0 235
duke@0 236 if (opt == java_net_SocketOptions_SO_LINGER) {
duke@0 237 arg = (void *)&linger;
duke@0 238 arglen = sizeof(linger);
duke@0 239 } else {
duke@0 240 arg = (void *)&result;
duke@0 241 arglen = sizeof(result);
duke@0 242 }
duke@0 243
duke@0 244 if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) {
duke@0 245 JNU_ThrowByNameWithLastError(env,
duke@0 246 JNU_JAVANETPKG "SocketException",
duke@0 247 "sun.nio.ch.Net.getIntOption");
duke@0 248 return -1;
duke@0 249 }
duke@0 250
duke@0 251 if (opt == java_net_SocketOptions_SO_LINGER)
duke@0 252 return linger.l_onoff ? linger.l_linger : -1;
duke@0 253 else
duke@0 254 return result;
duke@0 255 }
duke@0 256
duke@0 257 JNIEXPORT void JNICALL
duke@0 258 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
duke@0 259 jobject fdo, jint opt, jint arg)
duke@0 260 {
duke@0 261 int klevel, kopt;
duke@0 262 int result;
duke@0 263 struct linger linger;
duke@0 264 void *parg;
duke@0 265 int arglen;
duke@0 266
duke@0 267 if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
duke@0 268 JNU_ThrowByNameWithLastError(env,
duke@0 269 JNU_JAVANETPKG "SocketException",
duke@0 270 "Unsupported socket option");
duke@0 271 return;
duke@0 272 }
duke@0 273
duke@0 274 if (opt == java_net_SocketOptions_SO_LINGER) {
duke@0 275 parg = (void *)&linger;
duke@0 276 arglen = sizeof(linger);
duke@0 277 if (arg >= 0) {
duke@0 278 linger.l_onoff = 1;
duke@0 279 linger.l_linger = arg;
duke@0 280 } else {
duke@0 281 linger.l_onoff = 0;
duke@0 282 linger.l_linger = 0;
duke@0 283 }
duke@0 284 } else {
duke@0 285 parg = (void *)&arg;
duke@0 286 arglen = sizeof(arg);
duke@0 287 }
duke@0 288
duke@0 289 if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
duke@0 290 JNU_ThrowByNameWithLastError(env,
duke@0 291 JNU_JAVANETPKG "SocketException",
duke@0 292 "sun.nio.ch.Net.setIntOption");
duke@0 293 }
duke@0 294 }
duke@0 295
duke@0 296
duke@0 297
duke@0 298 /* Declared in nio_util.h */
duke@0 299
duke@0 300 jint
duke@0 301 handleSocketError(JNIEnv *env, jint errorValue)
duke@0 302 {
duke@0 303 char *xn;
duke@0 304 switch (errorValue) {
duke@0 305 case EINPROGRESS: /* Non-blocking connect */
duke@0 306 return 0;
duke@0 307 case EPROTO:
duke@0 308 xn = JNU_JAVANETPKG "ProtocolException";
duke@0 309 break;
duke@0 310 case ECONNREFUSED:
duke@0 311 xn = JNU_JAVANETPKG "ConnectException";
duke@0 312 break;
duke@0 313 case ETIMEDOUT:
duke@0 314 xn = JNU_JAVANETPKG "ConnectException";
duke@0 315 break;
duke@0 316 case EHOSTUNREACH:
duke@0 317 xn = JNU_JAVANETPKG "NoRouteToHostException";
duke@0 318 break;
duke@0 319 case EADDRINUSE: /* Fall through */
duke@0 320 case EADDRNOTAVAIL:
duke@0 321 xn = JNU_JAVANETPKG "BindException";
duke@0 322 break;
duke@0 323 default:
duke@0 324 xn = JNU_JAVANETPKG "SocketException";
duke@0 325 break;
duke@0 326 }
duke@0 327 errno = errorValue;
duke@0 328 JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
duke@0 329 return IOS_THROWN;
duke@0 330 }