PageRenderTime 107ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 1ms

/luni/src/main/java/java/net/PlainDatagramSocketImpl.java

https://bitbucket.org/aways/android_libcore
Java | 240 lines | 171 code | 32 blank | 37 comment | 10 complexity | 4e0b127a3f2c2e565edfde8d964e91ab MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package java.net;
  18. import dalvik.system.CloseGuard;
  19. import java.io.FileDescriptor;
  20. import java.io.IOException;
  21. import java.net.DatagramPacket;
  22. import java.net.DatagramSocketImpl;
  23. import java.net.InetAddress;
  24. import java.net.InetSocketAddress;
  25. import java.net.NetworkInterface;
  26. import java.net.SocketAddress;
  27. import java.net.SocketException;
  28. import java.net.UnknownHostException;
  29. import libcore.io.ErrnoException;
  30. import libcore.io.IoBridge;
  31. import libcore.io.Libcore;
  32. import libcore.io.StructGroupReq;
  33. import libcore.util.EmptyArray;
  34. import static libcore.io.OsConstants.*;
  35. /**
  36. * @hide used in java.nio.
  37. */
  38. public class PlainDatagramSocketImpl extends DatagramSocketImpl {
  39. private volatile boolean isNativeConnected;
  40. private final CloseGuard guard = CloseGuard.get();
  41. /**
  42. * used to keep address to which the socket was connected to at the native
  43. * level
  44. */
  45. private InetAddress connectedAddress;
  46. private int connectedPort = -1;
  47. public PlainDatagramSocketImpl(FileDescriptor fd, int localPort) {
  48. this.fd = fd;
  49. this.localPort = localPort;
  50. if (fd.valid()) {
  51. guard.open("close");
  52. }
  53. }
  54. public PlainDatagramSocketImpl() {
  55. fd = new FileDescriptor();
  56. }
  57. @Override public void bind(int port, InetAddress address) throws SocketException {
  58. IoBridge.bind(fd, address, port);
  59. if (port != 0) {
  60. localPort = port;
  61. } else {
  62. localPort = IoBridge.getSocketLocalPort(fd);
  63. }
  64. try {
  65. setOption(SocketOptions.SO_BROADCAST, Boolean.TRUE);
  66. } catch (IOException ignored) {
  67. }
  68. }
  69. @Override
  70. public synchronized void close() {
  71. guard.close();
  72. try {
  73. IoBridge.closeSocket(fd);
  74. } catch (IOException ignored) {
  75. }
  76. }
  77. @Override
  78. public void create() throws SocketException {
  79. this.fd = IoBridge.socket(false);
  80. }
  81. @Override protected void finalize() throws Throwable {
  82. try {
  83. if (guard != null) {
  84. guard.warnIfOpen();
  85. }
  86. close();
  87. } finally {
  88. super.finalize();
  89. }
  90. }
  91. @Override public Object getOption(int option) throws SocketException {
  92. return IoBridge.getSocketOption(fd, option);
  93. }
  94. @Override
  95. public int getTimeToLive() throws IOException {
  96. return (Integer) getOption(IoBridge.JAVA_IP_MULTICAST_TTL);
  97. }
  98. @Override
  99. public byte getTTL() throws IOException {
  100. return (byte) getTimeToLive();
  101. }
  102. private static StructGroupReq makeGroupReq(InetAddress gr_group, NetworkInterface networkInterface) {
  103. int gr_interface = (networkInterface != null) ? networkInterface.getIndex() : 0;
  104. return new StructGroupReq(gr_interface, gr_group);
  105. }
  106. @Override
  107. public void join(InetAddress addr) throws IOException {
  108. setOption(IoBridge.JAVA_MCAST_JOIN_GROUP, makeGroupReq(addr, null));
  109. }
  110. @Override
  111. public void joinGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {
  112. if (addr instanceof InetSocketAddress) {
  113. InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
  114. setOption(IoBridge.JAVA_MCAST_JOIN_GROUP, makeGroupReq(groupAddr, netInterface));
  115. }
  116. }
  117. @Override
  118. public void leave(InetAddress addr) throws IOException {
  119. setOption(IoBridge.JAVA_MCAST_LEAVE_GROUP, makeGroupReq(addr, null));
  120. }
  121. @Override
  122. public void leaveGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {
  123. if (addr instanceof InetSocketAddress) {
  124. InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
  125. setOption(IoBridge.JAVA_MCAST_LEAVE_GROUP, makeGroupReq(groupAddr, netInterface));
  126. }
  127. }
  128. @Override
  129. protected int peek(InetAddress sender) throws IOException {
  130. // We don't actually want the data: we just want the DatagramPacket's filled-in address.
  131. DatagramPacket packet = new DatagramPacket(EmptyArray.BYTE, 0);
  132. int result = peekData(packet);
  133. // Note: evil side-effect on InetAddress! This method should have returned InetSocketAddress!
  134. sender.ipaddress = packet.getAddress().getAddress();
  135. return result;
  136. }
  137. private void doRecv(DatagramPacket pack, int flags) throws IOException {
  138. IoBridge.recvfrom(false, fd, pack.getData(), pack.getOffset(), pack.getLength(), flags, pack, isNativeConnected);
  139. if (isNativeConnected) {
  140. updatePacketRecvAddress(pack);
  141. }
  142. }
  143. @Override
  144. public void receive(DatagramPacket pack) throws IOException {
  145. doRecv(pack, 0);
  146. }
  147. @Override
  148. public int peekData(DatagramPacket pack) throws IOException {
  149. doRecv(pack, MSG_PEEK);
  150. return pack.getPort();
  151. }
  152. @Override
  153. public void send(DatagramPacket packet) throws IOException {
  154. int port = isNativeConnected ? 0 : packet.getPort();
  155. InetAddress address = isNativeConnected ? null : packet.getAddress();
  156. IoBridge.sendto(fd, packet.getData(), packet.getOffset(), packet.getLength(), 0, address, port);
  157. }
  158. public void setOption(int option, Object value) throws SocketException {
  159. IoBridge.setSocketOption(fd, option, value);
  160. }
  161. @Override
  162. public void setTimeToLive(int ttl) throws IOException {
  163. setOption(IoBridge.JAVA_IP_MULTICAST_TTL, Integer.valueOf(ttl));
  164. }
  165. @Override
  166. public void setTTL(byte ttl) throws IOException {
  167. setTimeToLive((int) ttl & 0xff); // Avoid sign extension.
  168. }
  169. @Override
  170. public void connect(InetAddress inetAddr, int port) throws SocketException {
  171. IoBridge.connect(fd, inetAddr, port); // Throws on failure.
  172. try {
  173. connectedAddress = InetAddress.getByAddress(inetAddr.getAddress());
  174. } catch (UnknownHostException e) {
  175. // this is never expected to happen as we should not have gotten
  176. // here if the address is not resolvable
  177. throw new SocketException("Host is unresolved: " + inetAddr.getHostName());
  178. }
  179. connectedPort = port;
  180. isNativeConnected = true;
  181. }
  182. @Override
  183. public void disconnect() {
  184. try {
  185. Libcore.os.connect(fd, InetAddress.UNSPECIFIED, 0);
  186. } catch (ErrnoException errnoException) {
  187. throw new AssertionError(errnoException);
  188. } catch (SocketException ignored) {
  189. // Thrown if the socket has already been closed, but this method can't throw anything.
  190. }
  191. connectedPort = -1;
  192. connectedAddress = null;
  193. isNativeConnected = false;
  194. }
  195. /**
  196. * Set the received address and port in the packet. We do this when the
  197. * Datagram socket is connected at the native level and the
  198. * recvConnnectedDatagramImpl does not update the packet with address from
  199. * which the packet was received
  200. *
  201. * @param packet
  202. * the packet to be updated
  203. */
  204. private void updatePacketRecvAddress(DatagramPacket packet) {
  205. packet.setAddress(connectedAddress);
  206. packet.setPort(connectedPort);
  207. }
  208. }