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     // BEGIN Android-changed: Rewrote on top of Libcore.io.
     99     protected synchronized void bind0(int lport, InetAddress laddr) throws SocketException {
    100         if (isClosed()) {
    101             throw new SocketException("Socket closed");
    102         }
    103 
    104         IoBridge.bind(fd, laddr, lport);
    105 
    106         if (lport == 0) {
    107             // Now that we're a connected socket, let's extract the port number that the system
    108             // chose for us and store it in the Socket object.
    109             localPort = IoBridge.getLocalInetSocketAddress(fd).getPort();
    110         } else {
    111             localPort = lport;
    112         }
    113     }
    114 
    115     protected void send(DatagramPacket p) throws IOException {
    116         if (isClosed()) {
    117             throw new SocketException("Socket closed");
    118         }
    119         if (p.getData() == null || p.getAddress() == null) {
    120             throw new NullPointerException("null buffer || null address");
    121         }
    122 
    123         int port = connected ? 0 : p.getPort();
    124         InetAddress address = connected ? null : p.getAddress();
    125         IoBridge.sendto(fd, p.getData(), p.getOffset(), p.getLength(), 0, address, port);
    126     }
    127 
    128     protected synchronized int peek(InetAddress i) throws IOException {
    129         DatagramPacket p = new DatagramPacket(EmptyArray.BYTE, 0);
    130         doRecv(p, MSG_PEEK);
    131         i.holder().address = p.getAddress().holder().address;
    132         return p.getPort();
    133     }
    134 
    135     protected synchronized int peekData(DatagramPacket p) throws IOException {
    136         doRecv(p, MSG_PEEK);
    137         return p.getPort();
    138     }
    139 
    140     protected synchronized void receive0(DatagramPacket p) throws IOException {
    141         doRecv(p, 0);
    142     }
    143 
    144     private void doRecv(DatagramPacket p, int flags) throws IOException {
    145         if (isClosed()) {
    146             throw new SocketException("Socket closed");
    147         }
    148 
    149         if (timeout != 0) {
    150             IoBridge.poll(fd, POLLIN | POLLERR, timeout);
    151         }
    152 
    153         IoBridge.recvfrom(false, fd, p.getData(), p.getOffset(), p.bufLength, flags, p,
    154                 connected);
    155     }
    156 
    157     protected void setTimeToLive(int ttl) throws IOException {
    158         IoBridge.setSocketOption(fd, JAVA_IP_MULTICAST_TTL, ttl);
    159     }
    160 
    161     protected int getTimeToLive() throws IOException {
    162         return (Integer) IoBridge.getSocketOption(fd, JAVA_IP_MULTICAST_TTL);
    163     }
    164 
    165     protected void setTTL(byte ttl) throws IOException {
    166         setTimeToLive((int) ttl & 0xff);
    167     }
    168 
    169     protected byte getTTL() throws IOException {
    170         return (byte) getTimeToLive();
    171     }
    172 
    173     private static StructGroupReq makeGroupReq(InetAddress gr_group,
    174             NetworkInterface networkInterface) {
    175         int gr_interface = (networkInterface != null) ? networkInterface.getIndex() : 0;
    176         return new StructGroupReq(gr_interface, gr_group);
    177     }
    178 
    179     protected void join(InetAddress inetaddr, NetworkInterface netIf) throws IOException {
    180         if (isClosed()) {
    181             throw new SocketException("Socket closed");
    182         }
    183 
    184         IoBridge.setSocketOption(fd, JAVA_MCAST_JOIN_GROUP, makeGroupReq(inetaddr, netIf));
    185     }
    186 
    187     protected void leave(InetAddress inetaddr, NetworkInterface netIf)
    188         throws IOException {
    189         if (isClosed()) {
    190             throw new SocketException("Socket closed");
    191         }
    192 
    193         IoBridge.setSocketOption(fd, JAVA_MCAST_LEAVE_GROUP, makeGroupReq(inetaddr, netIf));
    194     }
    195 
    196     protected void datagramSocketCreate() throws SocketException {
    197         fd = IoBridge.socket(AF_INET6, SOCK_DGRAM, 0);
    198         IoBridge.setSocketOption(fd, SO_BROADCAST, true);
    199 
    200         try {
    201             Libcore.os.setsockoptInt(fd, IPPROTO_IP, IP_MULTICAST_ALL, 0);
    202         } catch (ErrnoException errnoException) {
    203             throw errnoException.rethrowAsSocketException();
    204         }
    205     }
    206 
    207     protected void datagramSocketClose() {
    208         try {
    209             IoBridge.closeAndSignalBlockedThreads(fd);
    210         } catch (IOException ignored) { }
    211     }
    212 
    213     protected void socketSetOption0(int opt, Object val) throws SocketException {
    214         if (isClosed()) {
    215             throw new SocketException("Socket closed");
    216         }
    217 
    218         IoBridge.setSocketOption(fd, opt, val);
    219     }
    220 
    221     protected Object socketGetOption(int opt) throws SocketException {
    222         if (isClosed()) {
    223             throw new SocketException("Socket closed");
    224         }
    225 
    226         return IoBridge.getSocketOption(fd, opt);
    227     }
    228 
    229     protected void connect0(InetAddress address, int port) throws SocketException {
    230         if (isClosed()) {
    231             throw new SocketException("Socket closed");
    232         }
    233 
    234         IoBridge.connect(fd, address, port);
    235     }
    236 
    237     protected void disconnect0(int family) {
    238         if (isClosed()) {
    239             return;
    240         }
    241 
    242         InetAddress inetAddressUnspec = new InetAddress();
    243         inetAddressUnspec.holder().family = AF_UNSPEC;
    244 
    245         try {
    246             IoBridge.connect(fd, inetAddressUnspec, 0);
    247         } catch (SocketException ignored) { }
    248     }
    249     // END Android-changed: Rewrote on top of Libcore.io.
    250 
    251     // Android-removed: JNI has been removed
    252     // /**
    253     //  * Perform class load-time initializations.
    254     //  */
    255     // private native static void init();
    256 }
    257