src/solaris/native/java/net/SocketOutputStream.c
author ohair
Tue May 25 15:58:33 2010 -0700 (24 months ago)
changeset 2361 00cd9dc3c2b5
parent 59414f50aee4989
permissions -rw-r--r--
6943119: Rebrand source copyright notices
Reviewed-by: darcy, weijun
        1 /*
        2  * Copyright (c) 1997, 2008, 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 <errno.h>
       28 #include <string.h>
       29 #include <sys/types.h>
       30 #include <sys/socket.h>
       31 
       32 #include "jni_util.h"
       33 #include "jvm.h"
       34 #include "net_util.h"
       35 
       36 #include "java_net_SocketOutputStream.h"
       37 
       38 #define min(a, b)       ((a) < (b) ? (a) : (b))
       39 
       40 /*
       41  * SocketOutputStream
       42  */
       43 
       44 static jfieldID IO_fd_fdID;
       45 
       46 /*
       47  * Class:     java_net_SocketOutputStream
       48  * Method:    init
       49  * Signature: ()V
       50  */
       51 JNIEXPORT void JNICALL
       52 Java_java_net_SocketOutputStream_init(JNIEnv *env, jclass cls) {
       53     IO_fd_fdID = NET_GetFileDescriptorID(env);
       54 }
       55 
       56 /*
       57  * Class:     java_net_SocketOutputStream
       58  * Method:    socketWrite0
       59  * Signature: (Ljava/io/FileDescriptor;[BII)V
       60  */
       61 JNIEXPORT void JNICALL
       62 Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
       63                                               jobject fdObj,
       64                                               jbyteArray data,
       65                                               jint off, jint len) {
       66     char *bufP;
       67     char BUF[MAX_BUFFER_LEN];
       68     int buflen;
       69     int fd;
       70 
       71     if (IS_NULL(fdObj)) {
       72         JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
       73         return;
       74     } else {
       75         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
       76         /* Bug 4086704 - If the Socket associated with this file descriptor
       77          * was closed (sysCloseFD), the the file descriptor is set to -1.
       78          */
       79         if (fd == -1) {
       80             JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
       81             return;
       82         }
       83 
       84     }
       85 
       86     if (len <= MAX_BUFFER_LEN) {
       87         bufP = BUF;
       88         buflen = MAX_BUFFER_LEN;
       89     } else {
       90         buflen = min(MAX_HEAP_BUFFER_LEN, len);
       91         bufP = (char *)malloc((size_t)buflen);
       92 
       93         /* if heap exhausted resort to stack buffer */
       94         if (bufP == NULL) {
       95             bufP = BUF;
       96             buflen = MAX_BUFFER_LEN;
       97         }
       98     }
       99 
      100     while(len > 0) {
      101         int loff = 0;
      102         int chunkLen = min(buflen, len);
      103         int llen = chunkLen;
      104         (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
      105 
      106         while(llen > 0) {
      107             int n = NET_Send(fd, bufP + loff, llen, 0);
      108             if (n > 0) {
      109                 llen -= n;
      110                 loff += n;
      111                 continue;
      112             }
      113             if (n == JVM_IO_INTR) {
      114                 JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
      115             } else {
      116                 if (errno == ECONNRESET) {
      117                     JNU_ThrowByName(env, "sun/net/ConnectionResetException",
      118                         "Connection reset");
      119                 } else {
      120                     NET_ThrowByNameWithLastError(env, "java/net/SocketException",
      121                         "Write failed");
      122                 }
      123             }
      124             if (bufP != BUF) {
      125                 free(bufP);
      126             }
      127             return;
      128         }
      129         len -= chunkLen;
      130         off += chunkLen;
      131     }
      132 
      133     if (bufP != BUF) {
      134         free(bufP);
      135     }
      136 }