1 /* 2 * Copyright (c) 2000, 2018, 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 <netdb.h> 27 #include <sys/types.h> 28 #include <rdma/rsocket.h> 29 #include <stdlib.h> 30 #include <errno.h> 31 #include <string.h> 32 #include <poll.h> 33 34 #include <netinet/in.h> 35 36 #include "jni.h" 37 #include "jni_util.h" 38 #include "net_util.h" 39 #include "jvm.h" 40 #include "jlong.h" 41 #include "rdma_ch_RdmaSocketChannelImpl.h" 42 #include "nio_util.h" 43 #include "nio.h" 44 45 static jfieldID fd_fdID; 46 47 JNIEXPORT void JNICALL 48 Java_rdma_ch_RdmaSocketChannelImpl_initIDs(JNIEnv *env, jclass clazz) 49 { 50 CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); 51 CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); 52 } 53 54 jint fdVal(JNIEnv *env, jobject fdo) 55 { 56 return (*env)->GetIntField(env, fdo, fd_fdID); 57 } 58 59 JNIEXPORT jint JNICALL 60 Java_rdma_ch_RdmaSocketChannelImpl_checkConnect(JNIEnv *env, jobject this, 61 jobject fdo, jboolean block) 62 { 63 int error = 0; 64 socklen_t n = sizeof(int); 65 jint fd = fdVal(env, fdo); 66 int result = 0; 67 struct pollfd poller; 68 69 poller.fd = fd; 70 poller.events = POLLOUT; 71 poller.revents = 0; 72 result = rpoll(&poller, 1, block ? -1 : 0); 73 74 if (result < 0) { 75 if (errno == EINTR) { 76 return IOS_INTERRUPTED; 77 } else { 78 JNU_ThrowIOExceptionWithLastError(env, "poll failed"); 79 return IOS_THROWN; 80 } 81 } 82 if (!block && (result == 0)) 83 return IOS_UNAVAILABLE; 84 85 if (result > 0) { 86 errno = 0; 87 result = rgetsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n); 88 if (result < 0) { 89 return handleSocketError(env, errno); 90 } else if (error) { 91 return handleSocketError(env, error); 92 } else if ((poller.revents & POLLHUP) != 0) { 93 return handleSocketError(env, ENOTCONN); 94 } 95 // connected 96 return 1; 97 } 98 return 0; 99 } 100 101 JNIEXPORT jint JNICALL 102 Java_rdma_ch_RdmaSocketChannelImpl_sendOutOfBandData(JNIEnv* env, jclass this, 103 jobject fdo, jbyte b) 104 { 105 int n = rsend(fdVal(env, fdo), (const void*)&b, 1, MSG_OOB); 106 return convertReturnVal(env, n, JNI_FALSE); 107 }