1/* 2 * Copyright (c) 2000, 2016, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26#include <stdlib.h> 27#include <netdb.h> 28#include <sys/types.h> 29#include <sys/socket.h> 30 31#if __linux__ 32#include <netinet/in.h> 33#endif 34 35#if defined(__solaris__) && !defined(_SOCKLEN_T) 36typedef size_t socklen_t; /* New in SunOS 5.7, so need this for 5.6 */ 37#endif 38 39#include "jni.h" 40#include "jni_util.h" 41#include "net_util.h" 42#include "jvm.h" 43#include "jlong.h" 44#include "sun_nio_ch_ServerSocketChannelImpl.h" 45#include "nio.h" 46#include "nio_util.h" 47 48 49static jfieldID fd_fdID; /* java.io.FileDescriptor.fd */ 50static jclass isa_class; /* java.net.InetSocketAddress */ 51static jmethodID isa_ctorID; /* .InetSocketAddress(InetAddress, int) */ 52 53 54JNIEXPORT void JNICALL 55Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv *env, jclass c) 56{ 57 jclass cls; 58 59 cls = (*env)->FindClass(env, "java/io/FileDescriptor"); 60 CHECK_NULL(cls); 61 fd_fdID = (*env)->GetFieldID(env, cls, "fd", "I"); 62 CHECK_NULL(fd_fdID); 63 64 cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); 65 CHECK_NULL(cls); 66 isa_class = (*env)->NewGlobalRef(env, cls); 67 if (isa_class == NULL) { 68 JNU_ThrowOutOfMemoryError(env, NULL); 69 return; 70 } 71 isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", 72 "(Ljava/net/InetAddress;I)V"); 73 CHECK_NULL(isa_ctorID); 74} 75 76JNIEXPORT jint JNICALL 77Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this, 78 jobject ssfdo, jobject newfdo, 79 jobjectArray isaa) 80{ 81 jint ssfd = (*env)->GetIntField(env, ssfdo, fd_fdID); 82 jint newfd; 83 SOCKETADDRESS sa; 84 socklen_t sa_len = sizeof(SOCKETADDRESS); 85 jobject remote_ia = 0; 86 jobject isa; 87 jint remote_port = 0; 88 89 /* 90 * accept connection but ignore ECONNABORTED indicating that 91 * a connection was eagerly accepted but was reset before 92 * accept() was called. 93 */ 94 for (;;) { 95 newfd = accept(ssfd, &sa.sa, &sa_len); 96 if (newfd >= 0) { 97 break; 98 } 99 if (errno != ECONNABORTED) { 100 break; 101 } 102 /* ECONNABORTED => restart accept */ 103 } 104 105 if (newfd < 0) { 106 if (errno == EAGAIN) 107 return IOS_UNAVAILABLE; 108 if (errno == EINTR) 109 return IOS_INTERRUPTED; 110 JNU_ThrowIOExceptionWithLastError(env, "Accept failed"); 111 return IOS_THROWN; 112 } 113 114 (*env)->SetIntField(env, newfdo, fd_fdID, newfd); 115 remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); 116 CHECK_NULL_RETURN(remote_ia, IOS_THROWN); 117 isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port); 118 CHECK_NULL_RETURN(isa, IOS_THROWN); 119 (*env)->SetObjectArrayElement(env, isaa, 0, isa); 120 return 1; 121} 122