1 /* 2 * Copyright (c) 2007,2011, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.net; 26 27 import android.system.ErrnoException; 28 import android.system.StructGroupReq; 29 30 import java.io.IOException; 31 import libcore.io.IoBridge; 32 import libcore.io.Libcore; 33 import libcore.util.EmptyArray; 34 35 import jdk.net.*; 36 37 import static android.system.OsConstants.AF_INET6; 38 import static android.system.OsConstants.AF_UNSPEC; 39 import static android.system.OsConstants.IPPROTO_IP; 40 import static android.system.OsConstants.IP_MULTICAST_ALL; 41 import static android.system.OsConstants.MSG_PEEK; 42 import static android.system.OsConstants.POLLERR; 43 import static android.system.OsConstants.POLLIN; 44 import static android.system.OsConstants.SOCK_DGRAM; 45 import static libcore.io.IoBridge.JAVA_IP_MULTICAST_TTL; 46 import static libcore.io.IoBridge.JAVA_MCAST_JOIN_GROUP; 47 import static libcore.io.IoBridge.JAVA_MCAST_LEAVE_GROUP; 48 import static sun.net.ExtendedOptionsImpl.*; 49 50 /* 51 * On Unix systems we simply delegate to native methods. 52 * 53 * @author Chris Hegarty 54 */ 55 56 class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl 57 { 58 // Android-removed: init method has been removed 59 // static { 60 // init(); 61 // } 62 setOption(SocketOption<T> name, T value)63 protected <T> void setOption(SocketOption<T> name, T value) throws IOException { 64 if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { 65 super.setOption(name, value); 66 } else { 67 if (isClosed()) { 68 throw new SocketException("Socket closed"); 69 } 70 checkSetOptionPermission(name); 71 checkValueType(value, SocketFlow.class); 72 setFlowOption(getFileDescriptor(), (SocketFlow)value); 73 } 74 } 75 getOption(SocketOption<T> name)76 protected <T> T getOption(SocketOption<T> name) throws IOException { 77 if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { 78 return super.getOption(name); 79 } 80 if (isClosed()) { 81 throw new SocketException("Socket closed"); 82 } 83 checkGetOptionPermission(name); 84 SocketFlow flow = SocketFlow.create(); 85 getFlowOption(getFileDescriptor(), flow); 86 return (T)flow; 87 } 88 socketSetOption(int opt, Object val)89 protected void socketSetOption(int opt, Object val) throws SocketException { 90 try { 91 socketSetOption0(opt, val); 92 } catch (SocketException se) { 93 if (!connected) 94 throw se; 95 } 96 } 97 bind0(int lport, InetAddress laddr)98 protected synchronized void bind0(int lport, InetAddress laddr) throws SocketException { 99 if (isClosed()) { 100 throw new SocketException("Socket closed"); 101 } 102 103 IoBridge.bind(fd, laddr, lport); 104 105 if (lport == 0) { 106 // Now that we're a connected socket, let's extract the port number that the system 107 // chose for us and store it in the Socket object. 108 localPort = IoBridge.getLocalInetSocketAddress(fd).getPort(); 109 } else { 110 localPort = lport; 111 } 112 } 113 send(DatagramPacket p)114 protected void send(DatagramPacket p) throws IOException { 115 if (isClosed()) { 116 throw new SocketException("Socket closed"); 117 } 118 if (p.getData() == null || p.getAddress() == null) { 119 throw new NullPointerException("null buffer || null address"); 120 } 121 122 int port = connected ? 0 : p.getPort(); 123 InetAddress address = connected ? null : p.getAddress(); 124 IoBridge.sendto(fd, p.getData(), p.getOffset(), p.getLength(), 0, address, port); 125 } 126 peek(InetAddress i)127 protected synchronized int peek(InetAddress i) throws IOException { 128 DatagramPacket p = new DatagramPacket(EmptyArray.BYTE, 0); 129 doRecv(p, MSG_PEEK); 130 i.holder().address = p.getAddress().holder().address; 131 return p.getPort(); 132 } 133 peekData(DatagramPacket p)134 protected synchronized int peekData(DatagramPacket p) throws IOException { 135 doRecv(p, MSG_PEEK); 136 return p.getPort(); 137 } 138 receive0(DatagramPacket p)139 protected synchronized void receive0(DatagramPacket p) throws IOException { 140 doRecv(p, 0); 141 } 142 doRecv(DatagramPacket p, int flags)143 private void doRecv(DatagramPacket p, int flags) throws IOException { 144 if (isClosed()) { 145 throw new SocketException("Socket closed"); 146 } 147 148 if (timeout != 0) { 149 IoBridge.poll(fd, POLLIN | POLLERR, timeout); 150 } 151 152 IoBridge.recvfrom(false, fd, p.getData(), p.getOffset(), p.bufLength, flags, p, 153 connected); 154 } 155 setTimeToLive(int ttl)156 protected void setTimeToLive(int ttl) throws IOException { 157 IoBridge.setSocketOption(fd, JAVA_IP_MULTICAST_TTL, ttl); 158 } 159 getTimeToLive()160 protected int getTimeToLive() throws IOException { 161 return (Integer) IoBridge.getSocketOption(fd, JAVA_IP_MULTICAST_TTL); 162 } 163 setTTL(byte ttl)164 protected void setTTL(byte ttl) throws IOException { 165 setTimeToLive((int) ttl & 0xff); 166 } 167 getTTL()168 protected byte getTTL() throws IOException { 169 return (byte) getTimeToLive(); 170 } 171 makeGroupReq(InetAddress gr_group, NetworkInterface networkInterface)172 private static StructGroupReq makeGroupReq(InetAddress gr_group, 173 NetworkInterface networkInterface) { 174 int gr_interface = (networkInterface != null) ? networkInterface.getIndex() : 0; 175 return new StructGroupReq(gr_interface, gr_group); 176 } 177 join(InetAddress inetaddr, NetworkInterface netIf)178 protected void join(InetAddress inetaddr, NetworkInterface netIf) throws IOException { 179 if (isClosed()) { 180 throw new SocketException("Socket closed"); 181 } 182 183 IoBridge.setSocketOption(fd, JAVA_MCAST_JOIN_GROUP, makeGroupReq(inetaddr, netIf)); 184 } 185 leave(InetAddress inetaddr, NetworkInterface netIf)186 protected void leave(InetAddress inetaddr, NetworkInterface netIf) 187 throws IOException { 188 if (isClosed()) { 189 throw new SocketException("Socket closed"); 190 } 191 192 IoBridge.setSocketOption(fd, JAVA_MCAST_LEAVE_GROUP, makeGroupReq(inetaddr, netIf)); 193 } 194 datagramSocketCreate()195 protected void datagramSocketCreate() throws SocketException { 196 fd = IoBridge.socket(AF_INET6, SOCK_DGRAM, 0); 197 IoBridge.setSocketOption(fd, SO_BROADCAST, true); 198 199 try { 200 Libcore.os.setsockoptInt(fd, IPPROTO_IP, IP_MULTICAST_ALL, 0); 201 } catch (ErrnoException errnoException) { 202 throw errnoException.rethrowAsSocketException(); 203 } 204 } 205 datagramSocketClose()206 protected void datagramSocketClose() { 207 try { 208 IoBridge.closeAndSignalBlockedThreads(fd); 209 } catch (IOException ignored) { } 210 } 211 socketSetOption0(int opt, Object val)212 protected void socketSetOption0(int opt, Object val) throws SocketException { 213 if (isClosed()) { 214 throw new SocketException("Socket closed"); 215 } 216 217 IoBridge.setSocketOption(fd, opt, val); 218 } 219 socketGetOption(int opt)220 protected Object socketGetOption(int opt) throws SocketException { 221 if (isClosed()) { 222 throw new SocketException("Socket closed"); 223 } 224 225 return IoBridge.getSocketOption(fd, opt); 226 } 227 connect0(InetAddress address, int port)228 protected void connect0(InetAddress address, int port) throws SocketException { 229 if (isClosed()) { 230 throw new SocketException("Socket closed"); 231 } 232 233 IoBridge.connect(fd, address, port); 234 } 235 disconnect0(int family)236 protected void disconnect0(int family) { 237 if (isClosed()) { 238 return; 239 } 240 241 InetAddress inetAddressUnspec = new InetAddress(); 242 inetAddressUnspec.holder().family = AF_UNSPEC; 243 244 try { 245 IoBridge.connect(fd, inetAddressUnspec, 0); 246 } catch (SocketException ignored) { } 247 } 248 249 // Android-removed: JNI has been removed 250 // /** 251 // * Perform class load-time initializations. 252 // */ 253 // private native static void init(); 254 } 255