1 /*
   2  * Copyright (c) 2014, 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 <windows.h>
  27 #include <winsock2.h>
  28 
  29 #include "jvm.h"
  30 #include "jni_util.h"
  31 #include "net_util.h"
  32 
  33 #include "java_net_AbstractPlainDatagramSocketImpl.h"
  34 
  35 static jfieldID IO_fd_fdID = NULL;
  36 static jfieldID apdsi_fdID = NULL;
  37 
  38 static jfieldID apdsi_fd1ID = NULL;
  39 static jclass two_stacks_clazz = NULL;
  40 
  41 
  42 /*
  43  * Class:     java_net_AbstractPlainDatagramSocketImpl
  44  * Method:    init
  45  * Signature: ()V
  46  */
  47 JNIEXPORT void JNICALL
  48 Java_java_net_AbstractPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
  49 
  50     apdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
  51                                    "Ljava/io/FileDescriptor;");
  52     CHECK_NULL(apdsi_fdID);
  53     IO_fd_fdID = NET_GetFileDescriptorID(env);
  54     CHECK_NULL(IO_fd_fdID);
  55 
  56     two_stacks_clazz = (*env)->FindClass(env, "java/net/TwoStacksPlainDatagramSocketImpl");
  57     CHECK_NULL(two_stacks_clazz);
  58 
  59     /* Handle both TwoStacks and DualStack here */
  60 
  61     if (JNU_Equals(env, cls, two_stacks_clazz)) {
  62         /* fd1 present only in TwoStack.. */
  63         apdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1",
  64                                    "Ljava/io/FileDescriptor;");
  65         CHECK_NULL(apdsi_fd1ID);
  66     }
  67 
  68     JNU_CHECK_EXCEPTION(env);
  69 }
  70 
  71 /*
  72  * Class:     java_net_AbstractPlainDatagramSocketImpl
  73  * Method:    dataAvailable
  74  * Signature: ()I
  75  */
  76 JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable
  77 (JNIEnv *env, jobject this) {
  78     SOCKET fd;
  79     SOCKET fd1;
  80     int  rv = -1, rv1 = -1;
  81     jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID);
  82 
  83     if (!IS_NULL(fdObj)) {
  84         int retval = 0;
  85         fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID);
  86         rv = ioctlsocket(fd, FIONREAD, &retval);
  87         if (retval > 0) {
  88             return retval;
  89         }
  90     }
  91 
  92     if (!IS_NULL(apdsi_fd1ID)) {
  93         /* TwoStacks */
  94         jobject fd1Obj = (*env)->GetObjectField(env, this, apdsi_fd1ID);
  95         if (!IS_NULL(fd1Obj)) {
  96             int retval = 0;
  97             fd1 = (SOCKET)(*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
  98             rv1 = ioctlsocket(fd1, FIONREAD, &retval);
  99             if (retval > 0) {
 100                 return retval;
 101             }
 102         }
 103     }
 104 
 105     if (rv < 0 && rv1 < 0) {
 106         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 107                             "Socket closed");
 108         return -1;
 109     }
 110 
 111     return 0;
 112 }
 113