2
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
27
import java.io.IOException;
28
import java.io.FileDescriptor;
29
import sun.net.ResourceManager;
32
* This class defines the plain DatagramSocketImpl that is used for all
33
* Windows versions lower than Vista. It adds support for IPv6 on
34
* these platforms where available.
36
* For backward compatibility windows platforms that do not have IPv6
37
* support also use this implementation, and fd1 gets set to null
38
* during socket creation.
40
* @author Chris Hegarty
41
* @author Jeroen Frijters
44
class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
46
/* Used for IPv6 on Windows only */
50
* Needed for ipv6 on windows because we need to know
51
* if the socket was bound to ::0 or 0.0.0.0, when a caller
52
* asks for it. In this case, both sockets are used, but we
53
* don't know whether the caller requested ::0 or 0.0.0.0
54
* and need to remember it here.
56
private InetAddress anyLocalBoundAddr=null;
58
cli.System.Net.Sockets.Socket fduse=null; /* saved between peek() and receive() calls */
60
/* saved between successive calls to receive, if data is detected
61
* on both sockets at same time. To ensure that one socket is not
62
* starved, they rotate using this field
64
cli.System.Net.Sockets.Socket lastfd=null;
66
protected synchronized void create() throws SocketException {
67
fd1 = new FileDescriptor();
70
} catch (SocketException e) {
76
protected synchronized void bind(int lport, InetAddress laddr)
77
throws SocketException {
78
super.bind(lport, laddr);
79
if (laddr.isAnyLocalAddress()) {
80
anyLocalBoundAddr = laddr;
84
protected synchronized void receive(DatagramPacket p)
93
public Object getOption(int optID) throws SocketException {
95
throw new SocketException("Socket Closed");
98
if (optID == SO_BINDADDR) {
99
if (fd != null && fd1 != null) {
100
return anyLocalBoundAddr;
102
return socketGetOption(optID);
104
return super.getOption(optID);
107
protected boolean isClosed() {
108
return (fd == null && fd1 == null) ? true : false;
111
protected void close() {
112
if (fd != null || fd1 != null) {
113
datagramSocketClose();
114
ResourceManager.afterUdpClose();
122
protected synchronized void bind0(int lport, InetAddress laddr) throws SocketException {
123
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
124
TwoStacksPlainDatagramSocketImpl_c.bind0(env, this, lport, laddr);
125
env.ThrowPendingException();
128
protected void send(DatagramPacket packet) throws IOException {
129
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
130
TwoStacksPlainDatagramSocketImpl_c.send(env, this, packet);
131
env.ThrowPendingException();
134
protected synchronized int peek(InetAddress addressObj) throws IOException {
135
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
136
int ret = TwoStacksPlainDatagramSocketImpl_c.peek(env, this, addressObj);
137
env.ThrowPendingException();
141
protected synchronized int peekData(DatagramPacket p) throws IOException {
142
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
143
int ret = TwoStacksPlainDatagramSocketImpl_c.peekData(env, this, p);
144
env.ThrowPendingException();
148
protected synchronized void receive0(DatagramPacket packet) throws IOException {
149
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
150
TwoStacksPlainDatagramSocketImpl_c.receive0(env, this, packet);
151
env.ThrowPendingException();
154
protected void setTimeToLive(int ttl) throws IOException {
155
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
156
TwoStacksPlainDatagramSocketImpl_c.setTimeToLive(env, this, ttl);
157
env.ThrowPendingException();
160
protected int getTimeToLive() throws IOException {
161
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
162
int ret = TwoStacksPlainDatagramSocketImpl_c.getTimeToLive(env, this);
163
env.ThrowPendingException();
167
protected void setTTL(byte ttl) throws IOException {
168
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
169
TwoStacksPlainDatagramSocketImpl_c.setTTL(env, this, ttl);
170
env.ThrowPendingException();
173
protected byte getTTL() throws IOException {
174
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
175
byte ret = TwoStacksPlainDatagramSocketImpl_c.getTTL(env, this);
176
env.ThrowPendingException();
180
protected void join(InetAddress inetaddr, NetworkInterface netIf) throws IOException {
181
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
182
TwoStacksPlainDatagramSocketImpl_c.join(env, this, inetaddr, netIf);
183
env.ThrowPendingException();
186
protected void leave(InetAddress inetaddr, NetworkInterface netIf) throws IOException {
187
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
188
TwoStacksPlainDatagramSocketImpl_c.leave(env, this, inetaddr, netIf);
189
env.ThrowPendingException();
192
protected void datagramSocketCreate() throws SocketException {
193
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
194
TwoStacksPlainDatagramSocketImpl_c.datagramSocketCreate(env, this);
195
env.ThrowPendingException();
198
protected void datagramSocketClose() {
199
TwoStacksPlainDatagramSocketImpl_c.datagramSocketClose(this);
202
protected void socketSetOption(int opt, Object val) throws SocketException {
203
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
204
TwoStacksPlainDatagramSocketImpl_c.socketSetOption(env, this, opt, val);
205
env.ThrowPendingException();
208
protected Object socketGetOption(int opt) throws SocketException {
209
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
210
Object ret = TwoStacksPlainDatagramSocketImpl_c.socketGetOption(env, this, opt);
211
env.ThrowPendingException();
215
protected void connect0(InetAddress address, int port) throws SocketException {
216
if (ikvm.internal.Util.MONO) {
217
// MONOBUG Mono doesn't allow Socket.Connect(IPAddress.Any, 0) to disconnect a datagram socket,
218
// so we throw a SocketException, this will cause DatagramSocket to emulate connectedness
219
throw new SocketException("connected datagram sockets not supported on Mono");
221
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
222
TwoStacksPlainDatagramSocketImpl_c.connect0(env, this, address, port);
223
env.ThrowPendingException();
226
protected void disconnect0(int family) {
227
TwoStacksPlainDatagramSocketImpl_c.disconnect0(this, family);