1 /*
2 * Copyright 1996-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 package java.net;
26
27 import java.io.FileDescriptor;
28 import java.io.IOException;
29 import java.io.InterruptedIOException;
30 import java.util.Enumeration;
31
32 /**
33 * Abstract datagram and multicast socket implementation base class.
34 * Note: This is not a public class, so that applets cannot call
35 * into the implementation directly and hence cannot bypass the
36 * security checks present in the DatagramSocket and MulticastSocket
37 * classes.
38 *
39 * @author Pavani Diwanji
40 */
41
42 abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
43 {
44 /* timeout value for receive() */
45 int timeout = 0;
46 boolean connected = false;
47 private int trafficClass = 0;
48 private InetAddress connectedAddress = null;
49 private int connectedPort = -1;
50
51 /* cached socket options */
52 private int multicastInterface = 0;
53 private boolean loopbackMode = true;
54 private int ttl = -1;
55
56 /**
57 * Load net library into runtime.
58 */
59 static {
60 java.security.AccessController.doPrivileged(
61 new sun.security.action.LoadLibraryAction("net"));
62 }
63
64 /**
65 * Creates a datagram socket
66 */
67 protected synchronized void create() throws SocketException {
68 fd = new FileDescriptor();
69 datagramSocketCreate();
70 }
71
72 /**
73 * Binds a datagram socket to a local port.
74 */
75 protected synchronized void bind(int lport, InetAddress laddr)
76 throws SocketException {
77 bind0(lport, laddr);
78 }
79
80 protected abstract void bind0(int lport, InetAddress laddr)
81 throws SocketException;
82
83 /**
84 * Sends a datagram packet. The packet contains the data and the
85 * destination address to send the packet to.
86 * @param packet to be sent.
87 */
88 protected abstract void send(DatagramPacket p) throws IOException;
89
90 /**
91 * Connects a datagram socket to a remote destination. This associates the remote
92 * address with the local socket so that datagrams may only be sent to this destination
93 * and received from this destination.
94 * @param address the remote InetAddress to connect to
95 * @param port the remote port number
96 */
97 protected void connect(InetAddress address, int port) throws SocketException {
98 connect0(address, port);
99 connectedAddress = address;
100 connectedPort = port;
101 connected = true;
102 }
103
104 /**
105 * Disconnects a previously connected socket. Does nothing if the socket was
106 * not connected already.
107 */
108 protected void disconnect() {
109 disconnect0(connectedAddress.family);
110 connected = false;
111 connectedAddress = null;
112 connectedPort = -1;
113 }
114
115 /**
116 * Peek at the packet to see who it is from.
117 * @param return the address which the packet came from.
118 */
119 protected abstract int peek(InetAddress i) throws IOException;
120 protected abstract int peekData(DatagramPacket p) throws IOException;
121 /**
122 * Receive the datagram packet.
123 * @param Packet Received.
124 */
125 protected synchronized void receive(DatagramPacket p)
126 throws IOException {
127 receive0(p);
128 }
129
130 protected abstract void receive0(DatagramPacket p)
131 throws IOException;
132
133 /**
134 * Set the TTL (time-to-live) option.
135 * @param TTL to be set.
136 */
137 protected abstract void setTimeToLive(int ttl) throws IOException;
138
139 /**
140 * Get the TTL (time-to-live) option.
141 */
142 protected abstract int getTimeToLive() throws IOException;
143
144 /**
145 * Set the TTL (time-to-live) option.
146 * @param TTL to be set.
147 */
148 protected abstract void setTTL(byte ttl) throws IOException;
149
150 /**
151 * Get the TTL (time-to-live) option.
152 */
153 protected abstract byte getTTL() throws IOException;
154
155 /**
156 * Join the multicast group.
157 * @param multicast address to join.
158 */
159 protected void join(InetAddress inetaddr) throws IOException {
160 join(inetaddr, null);
161 }
162
163 /**
164 * Leave the multicast group.
165 * @param multicast address to leave.
166 */
167 protected void leave(InetAddress inetaddr) throws IOException {
168 leave(inetaddr, null);
169 }
170 /**
171 * Join the multicast group.
172 * @param multicast address to join.
173 * @param netIf specifies the local interface to receive multicast
174 * datagram packets
175 * @throws IllegalArgumentException if mcastaddr is null or is a
176 * SocketAddress subclass not supported by this socket
177 * @since 1.4
178 */
179
180 protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
181 throws IOException {
182 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
183 throw new IllegalArgumentException("Unsupported address type");
184 join(((InetSocketAddress)mcastaddr).getAddress(), netIf);
185 }
186
187 protected abstract void join(InetAddress inetaddr, NetworkInterface netIf)
188 throws IOException;
189
190 /**
191 * Leave the multicast group.
192 * @param multicast address to leave.
193 * @param netIf specified the local interface to leave the group at
194 * @throws IllegalArgumentException if mcastaddr is null or is a
195 * SocketAddress subclass not supported by this socket
196 * @since 1.4
197 */
198 protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
199 throws IOException {
200 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
201 throw new IllegalArgumentException("Unsupported address type");
202 leave(((InetSocketAddress)mcastaddr).getAddress(), netIf);
203 }
204
205 protected abstract void leave(InetAddress inetaddr, NetworkInterface netIf)
206 throws IOException;
207
208 /**
209 * Close the socket.
210 */
211 protected void close() {
212 if (fd != null) {
213 datagramSocketClose();
214 fd = null;
215 }
216 }
217
218 protected boolean isClosed() {
219 return (fd == null) ? true : false;
220 }
221
222 protected void finalize() {
223 close();
224 }
225
226 /**
227 * set a value - since we only support (setting) binary options
228 * here, o must be a Boolean
229 */
230
231 public void setOption(int optID, Object o) throws SocketException {
232 if (isClosed()) {
233 throw new SocketException("Socket Closed");
234 }
235 switch (optID) {
236 /* check type safety b4 going native. These should never
237 * fail, since only java.Socket* has access to
238 * PlainSocketImpl.setOption().
239 */
240 case SO_TIMEOUT:
241 if (o == null || !(o instanceof Integer)) {
242 throw new SocketException("bad argument for SO_TIMEOUT");
243 }
244 int tmp = ((Integer) o).intValue();
245 if (tmp < 0)
246 throw new IllegalArgumentException("timeout < 0");
247 timeout = tmp;
248 return;
249 case IP_TOS:
250 if (o == null || !(o instanceof Integer)) {
251 throw new SocketException("bad argument for IP_TOS");
252 }
253 trafficClass = ((Integer)o).intValue();
254 break;
255 case SO_REUSEADDR:
256 if (o == null || !(o instanceof Boolean)) {
257 throw new SocketException("bad argument for SO_REUSEADDR");
258 }
259 break;
260 case SO_BROADCAST:
261 if (o == null || !(o instanceof Boolean)) {
262 throw new SocketException("bad argument for SO_BROADCAST");
263 }
264 break;
265 case SO_BINDADDR:
266 throw new SocketException("Cannot re-bind Socket");
267 case SO_RCVBUF:
268 case SO_SNDBUF:
269 if (o == null || !(o instanceof Integer) ||
270 ((Integer)o).intValue() < 0) {
271 throw new SocketException("bad argument for SO_SNDBUF or " +
272 "SO_RCVBUF");
273 }
274 break;
275 case IP_MULTICAST_IF:
276 if (o == null || !(o instanceof InetAddress))
277 throw new SocketException("bad argument for IP_MULTICAST_IF");
278 break;
279 case IP_MULTICAST_IF2:
280 if (o == null || !(o instanceof NetworkInterface))
281 throw new SocketException("bad argument for IP_MULTICAST_IF2");
282 break;
283 case IP_MULTICAST_LOOP:
284 if (o == null || !(o instanceof Boolean))
285 throw new SocketException("bad argument for IP_MULTICAST_LOOP");
286 break;
287 default:
288 throw new SocketException("invalid option: " + optID);
289 }
290 socketSetOption(optID, o);
291 }
292
293 /*
294 * get option's state - set or not
295 */
296
297 public Object getOption(int optID) throws SocketException {
298 if (isClosed()) {
299 throw new SocketException("Socket Closed");
300 }
301
302 Object result;
303
304 switch (optID) {
305 case SO_TIMEOUT:
306 result = new Integer(timeout);
307 break;
308
309 case IP_TOS:
310 result = socketGetOption(optID);
311 if ( ((Integer)result).intValue() == -1) {
312 result = new Integer(trafficClass);
313 }
314 break;
315
316 case SO_BINDADDR:
317 case IP_MULTICAST_IF:
318 case IP_MULTICAST_IF2:
319 case SO_RCVBUF:
320 case SO_SNDBUF:
321 case IP_MULTICAST_LOOP:
322 case SO_REUSEADDR:
323 case SO_BROADCAST:
324 result = socketGetOption(optID);
325 break;
326
327 default:
328 throw new SocketException("invalid option: " + optID);
329 }
330
331 return result;
332 }
333
334 protected abstract void datagramSocketCreate() throws SocketException;
335 protected abstract void datagramSocketClose();
336 protected abstract void socketSetOption(int opt, Object val)
337 throws SocketException;
338 protected abstract Object socketGetOption(int opt) throws SocketException;
339
340 protected abstract void connect0(InetAddress address, int port) throws SocketException;
341 protected abstract void disconnect0(int family);
342
343 }