1 /*
2 * Copyright (c) 2008, 2009, 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 "jni.h"
30 #include "jni_util.h"
31 #include "jlong.h"
32 #include "nio.h"
33 #include "nio_util.h"
34 #include "net_util.h"
35
36 #include "sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl.h"
37
38
39 #ifndef WSAID_ACCEPTEX
40 #define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
41 #endif
42
43 #ifndef SO_UPDATE_ACCEPT_CONTEXT
44 #define SO_UPDATE_ACCEPT_CONTEXT 0x700B
45 #endif
46
47
48 typedef BOOL (*AcceptEx_t)
49 (
50 SOCKET sListenSocket,
51 SOCKET sAcceptSocket,
52 PVOID lpOutputBuffer,
53 DWORD dwReceiveDataLength,
54 DWORD dwLocalAddressLength,
55 DWORD dwRemoteAddressLength,
56 LPDWORD lpdwBytesReceived,
57 LPOVERLAPPED lpOverlapped
58 );
59
60
61 static AcceptEx_t AcceptEx_func;
62
63
64 JNIEXPORT void JNICALL
Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_initIDs(JNIEnv * env,jclass this)65 Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_initIDs(JNIEnv* env, jclass this) {
66 GUID GuidAcceptEx = WSAID_ACCEPTEX;
67 SOCKET s;
68 int rv;
69 DWORD dwBytes;
70
71 s = socket(AF_INET, SOCK_STREAM, 0);
72 if (s == INVALID_SOCKET) {
73 JNU_ThrowIOExceptionWithLastError(env, "socket failed");
74 return;
75 }
76 rv = WSAIoctl(s,
77 SIO_GET_EXTENSION_FUNCTION_POINTER,
78 (LPVOID)&GuidAcceptEx,
79 sizeof(GuidAcceptEx),
80 &AcceptEx_func,
81 sizeof(AcceptEx_func),
82 &dwBytes,
83 NULL,
84 NULL);
85 if (rv != 0)
86 JNU_ThrowIOExceptionWithLastError(env, "WSAIoctl failed");
87 closesocket(s);
88 }
89
90 JNIEXPORT jint JNICALL
Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_accept0(JNIEnv * env,jclass this,jlong listenSocket,jlong acceptSocket,jlong ov,jlong buf)91 Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_accept0(JNIEnv* env, jclass this,
92 jlong listenSocket, jlong acceptSocket, jlong ov, jlong buf)
93 {
94 BOOL res;
95 SOCKET s1 = (SOCKET)jlong_to_ptr(listenSocket);
96 SOCKET s2 = (SOCKET)jlong_to_ptr(acceptSocket);
97 PVOID outputBuffer = (PVOID)jlong_to_ptr(buf);
98
99 DWORD nread = 0;
100 OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov);
101 ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
102
103 res = (*AcceptEx_func)(s1,
104 s2,
105 outputBuffer,
106 0,
107 sizeof(SOCKETADDRESS)+16,
108 sizeof(SOCKETADDRESS)+16,
109 &nread,
110 lpOverlapped);
111 if (res == 0) {
112 int error = WSAGetLastError();
113 if (error == ERROR_IO_PENDING) {
114 return IOS_UNAVAILABLE;
115 }
116 JNU_ThrowIOExceptionWithLastError(env, "AcceptEx failed");
117 return IOS_THROWN;
118 }
119
120 return 0;
121 }
122
123 JNIEXPORT void JNICALL
Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_updateAcceptContext(JNIEnv * env,jclass this,jlong listenSocket,jlong acceptSocket)124 Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_updateAcceptContext(JNIEnv* env, jclass this,
125 jlong listenSocket, jlong acceptSocket)
126 {
127 SOCKET s1 = (SOCKET)jlong_to_ptr(listenSocket);
128 SOCKET s2 = (SOCKET)jlong_to_ptr(acceptSocket);
129
130 setsockopt(s2, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&s1, sizeof(s1));
131 }
132
133
134 JNIEXPORT void JNICALL
Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_closesocket0(JNIEnv * env,jclass this,jlong socket)135 Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_closesocket0(JNIEnv* env, jclass this,
136 jlong socket)
137 {
138 SOCKET s = (SOCKET)jlong_to_ptr(socket);
139
140 if (closesocket(s) == SOCKET_ERROR)
141 JNU_ThrowIOExceptionWithLastError(env, "closesocket failed");
142 }
143