1. /*
  2. * @(#)PlainDatagramSocketImpl.java 1.37 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.net;
  8. import java.io.FileDescriptor;
  9. import java.io.IOException;
  10. import java.io.InterruptedIOException;
  11. import java.util.Enumeration;
  12. /**
  13. * Concrete datagram and multicast socket implementation base class.
  14. * Note: This is not a public class, so that applets cannot call
  15. * into the implementation directly and hence cannot bypass the
  16. * security checks present in the DatagramSocket and MulticastSocket
  17. * classes.
  18. *
  19. * @author Pavani Diwanji
  20. */
  21. class PlainDatagramSocketImpl extends DatagramSocketImpl
  22. {
  23. /* timeout value for receive() */
  24. private int timeout = 0;
  25. private int trafficClass = 0;
  26. private boolean connected = false;
  27. private InetAddress connectedAddress = null;
  28. private int connectedPort = -1;
  29. /* cached socket options */
  30. private int multicastInterface = 0;
  31. private boolean loopbackMode = true;
  32. private int ttl = -1;
  33. /**
  34. * Load net library into runtime.
  35. */
  36. static {
  37. java.security.AccessController.doPrivileged(
  38. new sun.security.action.LoadLibraryAction("net"));
  39. init();
  40. }
  41. /**
  42. * Creates a datagram socket
  43. */
  44. protected synchronized void create() throws SocketException {
  45. fd = new FileDescriptor();
  46. datagramSocketCreate();
  47. }
  48. /**
  49. * Binds a datagram socket to a local port.
  50. */
  51. protected synchronized native void bind(int lport, InetAddress laddr)
  52. throws SocketException;
  53. /**
  54. * Sends a datagram packet. The packet contains the data and the
  55. * destination address to send the packet to.
  56. * @param packet to be sent.
  57. */
  58. protected native void send(DatagramPacket p) throws IOException;
  59. /**
  60. * Connects a datagram socket to a remote destination. This associates the remote
  61. * address with the local socket so that datagrams may only be sent to this destination
  62. * and received from this destination.
  63. * @param address the remote InetAddress to connect to
  64. * @param port the remote port number
  65. */
  66. protected void connect(InetAddress address, int port) throws SocketException {
  67. connect0(address, port);
  68. connectedAddress = address;
  69. connectedPort = port;
  70. connected = true;
  71. }
  72. /**
  73. * Disconnects a previously connected socket. Does nothing if the socket was
  74. * not connected already.
  75. */
  76. protected void disconnect() {
  77. disconnect0();
  78. connected = false;
  79. connectedAddress = null;
  80. connectedPort = -1;
  81. }
  82. /**
  83. * Peek at the packet to see who it is from.
  84. * @param return the address which the packet came from.
  85. */
  86. protected synchronized native int peek(InetAddress i) throws IOException;
  87. protected synchronized native int peekData(DatagramPacket p) throws IOException;
  88. /**
  89. * Receive the datagram packet.
  90. * @param Packet Received.
  91. */
  92. protected synchronized native void receive(DatagramPacket p)
  93. throws IOException;
  94. /**
  95. * Set the TTL (time-to-live) option.
  96. * @param TTL to be set.
  97. */
  98. protected native void setTimeToLive(int ttl) throws IOException;
  99. /**
  100. * Get the TTL (time-to-live) option.
  101. */
  102. protected native int getTimeToLive() throws IOException;
  103. /**
  104. * Set the TTL (time-to-live) option.
  105. * @param TTL to be set.
  106. */
  107. protected native void setTTL(byte ttl) throws IOException;
  108. /**
  109. * Get the TTL (time-to-live) option.
  110. */
  111. protected native byte getTTL() throws IOException;
  112. /**
  113. * Join the multicast group.
  114. * @param multicast address to join.
  115. */
  116. protected void join(InetAddress inetaddr) throws IOException {
  117. join(inetaddr, null);
  118. }
  119. /**
  120. * Leave the multicast group.
  121. * @param multicast address to leave.
  122. */
  123. protected void leave(InetAddress inetaddr) throws IOException {
  124. leave(inetaddr, null);
  125. }
  126. /**
  127. * Join the multicast group.
  128. * @param multicast address to join.
  129. * @param netIf specifies the local interface to receive multicast
  130. * datagram packets
  131. * @throws IllegalArgumentException if mcastaddr is null or is a
  132. * SocketAddress subclass not supported by this socket
  133. * @since 1.4
  134. */
  135. protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
  136. throws IOException {
  137. if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
  138. throw new IllegalArgumentException("Unsupported address type");
  139. join(((InetSocketAddress)mcastaddr).getAddress(), netIf);
  140. }
  141. private native void join(InetAddress inetaddr, NetworkInterface netIf)
  142. throws IOException;
  143. /**
  144. * Leave the multicast group.
  145. * @param multicast address to leave.
  146. * @param netIf specified the local interface to leave the group at
  147. * @throws IllegalArgumentException if mcastaddr is null or is a
  148. * SocketAddress subclass not supported by this socket
  149. * @since 1.4
  150. */
  151. protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
  152. throws IOException {
  153. if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
  154. throw new IllegalArgumentException("Unsupported address type");
  155. leave(((InetSocketAddress)mcastaddr).getAddress(), netIf);
  156. }
  157. private native void leave(InetAddress inetaddr, NetworkInterface netIf)
  158. throws IOException;
  159. /**
  160. * Close the socket.
  161. */
  162. protected void close() {
  163. if (fd != null) {
  164. datagramSocketClose();
  165. fd = null;
  166. }
  167. }
  168. protected void finalize() {
  169. close();
  170. }
  171. /**
  172. * set a value - since we only support (setting) binary options
  173. * here, o must be a Boolean
  174. */
  175. public void setOption(int optID, Object o) throws SocketException {
  176. if (fd == null) {
  177. throw new SocketException("Socket Closed");
  178. }
  179. switch (optID) {
  180. /* check type safety b4 going native. These should never
  181. * fail, since only java.Socket* has access to
  182. * PlainSocketImpl.setOption().
  183. */
  184. case SO_TIMEOUT:
  185. if (o == null || !(o instanceof Integer)) {
  186. throw new SocketException("bad argument for SO_TIMEOUT");
  187. }
  188. int tmp = ((Integer) o).intValue();
  189. if (tmp < 0)
  190. throw new IllegalArgumentException("timeout < 0");
  191. timeout = tmp;
  192. return;
  193. case IP_TOS:
  194. if (o == null || !(o instanceof Integer)) {
  195. throw new SocketException("bad argument for IP_TOS");
  196. }
  197. trafficClass = ((Integer)o).intValue();
  198. break;
  199. case SO_REUSEADDR:
  200. if (o == null || !(o instanceof Boolean)) {
  201. throw new SocketException("bad argument for SO_REUSEADDR");
  202. }
  203. break;
  204. case SO_BROADCAST:
  205. if (o == null || !(o instanceof Boolean)) {
  206. throw new SocketException("bad argument for SO_BROADCAST");
  207. }
  208. break;
  209. case SO_BINDADDR:
  210. throw new SocketException("Cannot re-bind Socket");
  211. case SO_RCVBUF:
  212. case SO_SNDBUF:
  213. if (o == null || !(o instanceof Integer) ||
  214. ((Integer)o).intValue() < 0) {
  215. throw new SocketException("bad argument for SO_SNDBUF or " +
  216. "SO_RCVBUF");
  217. }
  218. break;
  219. case IP_MULTICAST_IF:
  220. if (o == null || !(o instanceof InetAddress))
  221. throw new SocketException("bad argument for IP_MULTICAST_IF");
  222. break;
  223. case IP_MULTICAST_IF2:
  224. if (o == null || !(o instanceof NetworkInterface))
  225. throw new SocketException("bad argument for IP_MULTICAST_IF2");
  226. break;
  227. case IP_MULTICAST_LOOP:
  228. if (o == null || !(o instanceof Boolean))
  229. throw new SocketException("bad argument for IP_MULTICAST_LOOP");
  230. break;
  231. default:
  232. throw new SocketException("invalid option: " + optID);
  233. }
  234. socketSetOption(optID, o);
  235. }
  236. /*
  237. * get option's state - set or not
  238. */
  239. public Object getOption(int optID) throws SocketException {
  240. if (fd == null) {
  241. throw new SocketException("Socket Closed");
  242. }
  243. Object result;
  244. switch (optID) {
  245. case SO_TIMEOUT:
  246. result = new Integer(timeout);
  247. break;
  248. case IP_TOS:
  249. result = socketGetOption(optID);
  250. if ( ((Integer)result).intValue() == -1) {
  251. result = new Integer(trafficClass);
  252. }
  253. break;
  254. case SO_BINDADDR:
  255. case IP_MULTICAST_IF:
  256. case IP_MULTICAST_IF2:
  257. case SO_RCVBUF:
  258. case SO_SNDBUF:
  259. case IP_MULTICAST_LOOP:
  260. case SO_REUSEADDR:
  261. case SO_BROADCAST:
  262. result = socketGetOption(optID);
  263. break;
  264. default:
  265. throw new SocketException("invalid option: " + optID);
  266. }
  267. return result;
  268. }
  269. private native void datagramSocketCreate() throws SocketException;
  270. private native void datagramSocketClose();
  271. private native void socketSetOption(int opt, Object val)
  272. throws SocketException;
  273. private native Object socketGetOption(int opt) throws SocketException;
  274. private native void connect0(InetAddress address, int port) throws SocketException;
  275. private native void disconnect0();
  276. /**
  277. * Perform class load-time initializations.
  278. */
  279. private native static void init();
  280. }