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