001: /*
002: * @(#)PlainDatagramSocketImpl.java 1.30 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.net;
029:
030: import java.io.FileDescriptor;
031: import java.io.IOException;
032: import java.io.InterruptedIOException;
033: import java.util.Enumeration;
034:
035: /**
036: * Concrete datagram and multicast socket implementation base class.
037: * Note: This is not a public class, so that applets cannot call
038: * into the implementation directly and hence cannot bypass the
039: * security checks present in the DatagramSocket and MulticastSocket
040: * classes.
041: *
042: * @author Pavani Diwanji
043: */
044:
045: class PlainDatagramSocketImpl extends DatagramSocketImpl {
046: /* timeout value for receive() */
047: private int timeout = 0;
048: private int trafficClass = 0;
049: private boolean connected = false;
050: private InetAddress connectedAddress = null;
051: private int connectedPort = -1;
052:
053: /* cached socket options */
054: private int multicastInterface = 0;
055: private boolean loopbackMode = true;
056: private int ttl = -1;
057:
058: /**
059: * Load net library into runtime.
060: */
061: static {
062: java.security.AccessController
063: .doPrivileged(new sun.security.action.LoadLibraryAction(
064: "net"));
065: java.security.AccessController
066: .doPrivileged(new java.security.PrivilegedAction() {
067: public Object run() {
068: init();
069: return null;
070: }
071: });
072: }
073:
074: /**
075: * Creates a datagram socket
076: */
077: protected synchronized void create() throws SocketException {
078: fd = new FileDescriptor();
079: datagramSocketCreate();
080: }
081:
082: /**
083: * Binds a datagram socket to a local port.
084: */
085: protected synchronized native void bind(int lport, InetAddress laddr)
086: throws SocketException;
087:
088: /**
089: * Sends a datagram packet. The packet contains the data and the
090: * destination address to send the packet to.
091: * @param packet to be sent.
092: */
093: protected native void send(DatagramPacket p) throws IOException;
094:
095: /**
096: * Connects a datagram socket to a remote destination. This associates the remote
097: * address with the local socket so that datagrams may only be sent to this destination
098: * and received from this destination.
099: * @param address the remote InetAddress to connect to
100: * @param port the remote port number
101: */
102: protected void connect(InetAddress address, int port)
103: throws SocketException {
104: connect0(address, port);
105: connectedAddress = address;
106: connectedPort = port;
107: connected = true;
108: }
109:
110: /**
111: * Disconnects a previously connected socket. Does nothing if the socket was
112: * not connected already.
113: */
114: protected void disconnect() {
115: disconnect0();
116: connected = false;
117: connectedAddress = null;
118: connectedPort = -1;
119: }
120:
121: /**
122: * Peek at the packet to see who it is from.
123: * @param return the address which the packet came from.
124: */
125: protected synchronized native int peek(InetAddress i)
126: throws IOException;
127:
128: protected synchronized native int peekData(DatagramPacket p)
129: throws IOException;
130:
131: /**
132: * Receive the datagram packet.
133: * @param Packet Received.
134: */
135: protected synchronized native void receive(DatagramPacket p)
136: throws IOException;
137:
138: /**
139: * Set the TTL (time-to-live) option.
140: * @param TTL to be set.
141: */
142: protected native void setTimeToLive(int ttl) throws IOException;
143:
144: /**
145: * Get the TTL (time-to-live) option.
146: */
147: protected native int getTimeToLive() throws IOException;
148:
149: /**
150: * Set the TTL (time-to-live) option.
151: * @param TTL to be set.
152: protected native void setTTL(byte ttl) throws IOException;
153: */
154:
155: /**
156: * Get the TTL (time-to-live) option.
157: protected native byte getTTL() throws IOException;
158: */
159:
160: /**
161: * Join the multicast group.
162: * @param multicast address to join.
163: */
164: protected void join(InetAddress inetaddr) throws IOException {
165: join(inetaddr, null);
166: }
167:
168: /**
169: * Leave the multicast group.
170: * @param multicast address to leave.
171: */
172: protected void leave(InetAddress inetaddr) throws IOException {
173: leave(inetaddr, null);
174: }
175:
176: /**
177: * Join the multicast group.
178: * @param multicast address to join.
179: * @param netIf specifies the local interface to receive multicast
180: * datagram packets
181: * @throws IllegalArgumentException if mcastaddr is null or is a
182: * SocketAddress subclass not supported by this socket
183: * @since 1.4
184: */
185:
186: protected void joinGroup(SocketAddress mcastaddr,
187: NetworkInterface netIf) throws IOException {
188: if (mcastaddr == null
189: || !(mcastaddr instanceof InetSocketAddress))
190: throw new IllegalArgumentException(
191: "Unsupported address type");
192: join(((InetSocketAddress) mcastaddr).getAddress(), netIf);
193: }
194:
195: private native void join(InetAddress inetaddr,
196: NetworkInterface netIf) throws IOException;
197:
198: /**
199: * Leave the multicast group.
200: * @param multicast address to leave.
201: * @param netIf specified the local interface to leave the group at
202: * @throws IllegalArgumentException if mcastaddr is null or is a
203: * SocketAddress subclass not supported by this socket
204: * @since 1.4
205: */
206: protected void leaveGroup(SocketAddress mcastaddr,
207: NetworkInterface netIf) throws IOException {
208: if (mcastaddr == null
209: || !(mcastaddr instanceof InetSocketAddress))
210: throw new IllegalArgumentException(
211: "Unsupported address type");
212: leave(((InetSocketAddress) mcastaddr).getAddress(), netIf);
213: }
214:
215: private native void leave(InetAddress inetaddr,
216: NetworkInterface netIf) throws IOException;
217:
218: /**
219: * Close the socket.
220: */
221: protected void close() {
222: if (fd != null) {
223: datagramSocketClose();
224: fd = null;
225: }
226: }
227:
228: protected void finalize() {
229: close();
230: }
231:
232: /**
233: * set a value - since we only support (setting) binary options
234: * here, o must be a Boolean
235: */
236:
237: public void setOption(int optID, Object o) throws SocketException {
238: if (fd == null) {
239: throw new SocketException("Socket Closed");
240: }
241: switch (optID) {
242: /* check type safety b4 going native. These should never
243: * fail, since only java.Socket* has access to
244: * PlainSocketImpl.setOption().
245: */
246: case SO_TIMEOUT:
247: if (o == null || !(o instanceof Integer)) {
248: throw new SocketException("bad argument for SO_TIMEOUT");
249: }
250: int tmp = ((Integer) o).intValue();
251: if (tmp < 0)
252: throw new IllegalArgumentException("timeout < 0");
253: timeout = tmp;
254: return;
255: case IP_TOS:
256: if (o == null || !(o instanceof Integer)) {
257: throw new SocketException("bad argument for IP_TOS");
258: }
259: trafficClass = ((Integer) o).intValue();
260: break;
261: case SO_REUSEADDR:
262: if (o == null || !(o instanceof Boolean)) {
263: throw new SocketException(
264: "bad argument for SO_REUSEADDR");
265: }
266: break;
267: case SO_BROADCAST:
268: if (o == null || !(o instanceof Boolean)) {
269: throw new SocketException(
270: "bad argument for SO_BROADCAST");
271: }
272: break;
273: case SO_BINDADDR:
274: throw new SocketException("Cannot re-bind Socket");
275: case SO_RCVBUF:
276: case SO_SNDBUF:
277: if (o == null || !(o instanceof Integer)
278: || ((Integer) o).intValue() < 0) {
279: throw new SocketException(
280: "bad argument for SO_SNDBUF or " + "SO_RCVBUF");
281: }
282: break;
283: case IP_MULTICAST_IF:
284: if (o == null || !(o instanceof InetAddress))
285: throw new SocketException(
286: "bad argument for IP_MULTICAST_IF");
287: break;
288: case IP_MULTICAST_IF2:
289: if (o == null || !(o instanceof NetworkInterface))
290: throw new SocketException(
291: "bad argument for IP_MULTICAST_IF2");
292: break;
293: case IP_MULTICAST_LOOP:
294: if (o == null || !(o instanceof Boolean))
295: throw new SocketException(
296: "bad argument for IP_MULTICAST_LOOP");
297: break;
298: default:
299: throw new SocketException("invalid option: " + optID);
300: }
301: socketSetOption(optID, o);
302: }
303:
304: /*
305: * get option's state - set or not
306: */
307:
308: public Object getOption(int optID) throws SocketException {
309: if (fd == null) {
310: throw new SocketException("Socket Closed");
311: }
312:
313: Object result;
314:
315: switch (optID) {
316: case SO_TIMEOUT:
317: result = new Integer(timeout);
318: break;
319:
320: case IP_TOS:
321: result = socketGetOption(optID);
322: if (((Integer) result).intValue() == -1) {
323: result = new Integer(trafficClass);
324: }
325: break;
326:
327: case SO_BINDADDR:
328: case IP_MULTICAST_IF:
329: case IP_MULTICAST_IF2:
330: case SO_RCVBUF:
331: case SO_SNDBUF:
332: case IP_MULTICAST_LOOP:
333: case SO_REUSEADDR:
334: case SO_BROADCAST:
335: result = socketGetOption(optID);
336: break;
337:
338: default:
339: throw new SocketException("invalid option: " + optID);
340: }
341:
342: return result;
343: }
344:
345: private native void datagramSocketCreate() throws SocketException;
346:
347: private native void datagramSocketClose();
348:
349: private native void socketSetOption(int opt, Object val)
350: throws SocketException;
351:
352: private native Object socketGetOption(int opt)
353: throws SocketException;
354:
355: private native void connect0(InetAddress address, int port)
356: throws SocketException;
357:
358: private native void disconnect0();
359:
360: /**
361: * Perform class load-time initializations.
362: */
363: private native static void init();
364:
365: }
|