Home | History | Annotate | Download | only in net
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    134     protected synchronized int peekData(DatagramPacket p) throws IOException {
    135         doRecv(p, MSG_PEEK);
    136         return p.getPort();
    137     }
    138 
    139     protected synchronized void receive0(DatagramPacket p) throws IOException {
    140         doRecv(p, 0);
    141     }
    142 
    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 
    156     protected void setTimeToLive(int ttl) throws IOException {
    157         IoBridge.setSocketOption(fd, JAVA_IP_MULTICAST_TTL, ttl);
    158     }
    159 
    160     protected int getTimeToLive() throws IOException {
    161         return (Integer) IoBridge.getSocketOption(fd, JAVA_IP_MULTICAST_TTL);
    162     }
    163 
    164     protected void setTTL(byte ttl) throws IOException {
    165         setTimeToLive((int) ttl & 0xff);
    166     }
    167 
    168     protected byte getTTL() throws IOException {
    169         return (byte) getTimeToLive();
    170     }
    171 
    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 
    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 
    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 
    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 
    206     protected void datagramSocketClose() {
    207         try {
    208             IoBridge.closeAndSignalBlockedThreads(fd);
    209         } catch (IOException ignored) { }
    210     }
    211 
    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 
    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 
    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 
    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