1 /*
   2  * Copyright (c) 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 "jdk_internal_net_rdma_RdmaSocketChannelImpl.h"
  27 #include "nio_util.h"
  28 #include "nio.h"
  29 #include <Rsocket.h>
  30 
  31 static jfieldID fd_fdID;
  32 
  33 JNIEXPORT void JNICALL
  34 Java_jdk_internal_net_rdma_RdmaSocketChannelImpl_initIDs(JNIEnv *env,
  35         jclass clazz) {
  36     loadRdmaFuncs(env);
  37     CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor"));
  38     CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I"));
  39 }
  40 
  41 jint fdVal(JNIEnv *env, jobject fdo) {
  42     return (*env)->GetIntField(env, fdo, fd_fdID);
  43 }
  44 
  45 JNIEXPORT jint JNICALL
  46 Java_jdk_internal_net_rdma_RdmaSocketChannelImpl_checkConnect(JNIEnv *env,
  47         jobject this, jobject fdo, jboolean block) {
  48     int error = 0;
  49     socklen_t n = sizeof(int);
  50     jint fd = fdVal(env, fdo);
  51     int result = 0;
  52     struct pollfd poller;
  53 
  54     poller.fd = fd;
  55     poller.events = POLLOUT;
  56     poller.revents = 0;
  57     result = rs_poll(&poller, 1, block ? -1 : 0);
  58 
  59     if (result < 0) {
  60         if (errno == EINTR) {
  61             return IOS_INTERRUPTED;
  62         } else {
  63             JNU_ThrowIOExceptionWithLastError(env, "poll failed");
  64             return IOS_THROWN;
  65         }
  66     }
  67     if (!block && (result == 0))
  68         return IOS_UNAVAILABLE;
  69 
  70     if (result > 0) {
  71         errno = 0;
  72         result = rs_getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n);
  73         if (result < 0) {
  74             return handleSocketError(env, errno);
  75         } else if (error) {
  76             return handleSocketError(env, error);
  77         } else if ((poller.revents & POLLHUP) != 0) {
  78             return handleSocketError(env, ENOTCONN);
  79         }
  80         // connected
  81         return 1;
  82     }
  83     return 0;
  84 }
  85 
  86 JNIEXPORT jint JNICALL
  87 Java_jdk_internal_net_rdma_RdmaSocketChannelImpl_sendOutOfBandData(JNIEnv* env,
  88         jclass this, jobject fdo, jbyte b) {
  89     int n = rs_send(fdVal(env, fdo), (const void*)&b, 1, MSG_OOB);
  90     return convertReturnVal(env, n, JNI_FALSE);
  91 }