jdk/src/windows/native/java/net/SocketOutputStream.c
author ohair
Tue, 25 Mar 2008 14:38:56 -0700
changeset 20 41658053480c
parent 2 90ce3da70b43
child 910 1f53246fb014
permissions -rw-r--r--
6623832: Cleanup old j2se makefile targets Summary: Just removing unneeded makefile rules and 'control' logic. Reviewed-by: xdono
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 1997-2003 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
#include <windows.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
#include <winsock2.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
#include <ctype.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
#include <stdio.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
#include <stdlib.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
#include <malloc.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
#include <sys/types.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
#include "java_net_SocketOutputStream.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
#include "net_util.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
#include "jni_util.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
/************************************************************************
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * SocketOutputStream
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
static jfieldID IO_fd_fdID;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * Class:     java_net_SocketOutputStream
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * Method:    init
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * Signature: ()V
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
JNIEXPORT void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
Java_java_net_SocketOutputStream_init(JNIEnv *env, jclass cls) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    IO_fd_fdID = NET_GetFileDescriptorID(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * Class:     java_net_SocketOutputStream
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * Method:    socketWrite
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * Signature: (Ljava/io/FileDescriptor;[BII)V
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
JNIEXPORT void JNICALL
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
                                              jobject fdObj, jbyteArray data,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
                                              jint off, jint len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    char *bufP;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    char BUF[MAX_BUFFER_LEN];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    int buflen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    int fd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    jint n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    if (IS_NULL(fdObj)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
        fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    if (IS_NULL(data)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
        JNU_ThrowNullPointerException(env, "data argument");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
     * Use stack allocate buffer if possible. For large sizes we allocate
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
     * an intermediate buffer from the heap (up to a maximum). If heap is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
     * unavailable just use our stack buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    if (len <= MAX_BUFFER_LEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        bufP = BUF;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        buflen = MAX_BUFFER_LEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        buflen = min(MAX_HEAP_BUFFER_LEN, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        bufP = (char *)malloc((size_t)buflen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        if (bufP == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
            bufP = BUF;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
            buflen = MAX_BUFFER_LEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    while(len > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        int loff = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
        int chunkLen = min(buflen, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        int llen = chunkLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
        int retry = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        while(llen > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
            int n = send(fd, bufP + loff, llen, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
            if (n > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
                llen -= n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
                loff += n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
             * Due to a bug in Windows Sockets (observed on NT and Windows
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
             * 2000) it may be necessary to retry the send. The issue is that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
             * on blocking sockets send/WSASend is supposed to block if there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
             * is insufficient buffer space available. If there are a large
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
             * number of threads blocked on write due to congestion then it's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
             * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
             * The workaround we use is to retry the send. If we have a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
             * large buffer to send (>2k) then we retry with a maximum of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
             * 2k buffer. If we hit the issue with <=2k buffer then we backoff
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
             * for 1 second and retry again. We repeat this up to a reasonable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
             * limit before bailing out and throwing an exception. In load
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
             * conditions we've observed that the send will succeed after 2-3
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
             * attempts but this depends on network buffers associated with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
             * other sockets draining.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
            if (WSAGetLastError() == WSAENOBUFS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                if (llen > MAX_BUFFER_LEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
                    buflen = MAX_BUFFER_LEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
                    chunkLen = MAX_BUFFER_LEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                    llen = MAX_BUFFER_LEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
                    continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                if (retry >= 30) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                        "No buffer space available - exhausted attempts to queue buffer");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                    if (bufP != BUF) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                        free(bufP);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
                Sleep(1000);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                retry++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
             * Send failed - can be caused by close or write error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
            if (WSAGetLastError() == WSAENOTSOCK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
                NET_ThrowCurrent(env, "socket write error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            if (bufP != BUF) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                free(bufP);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        len -= chunkLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        off += chunkLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    if (bufP != BUF) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        free(bufP);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
}