/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.harmony.luni.net;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.DatagramPacket;
import java.net.DatagramSocketImpl;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketOptions;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.security.AccessController;

import org.apache.harmony.luni.platform.INetworkSystem;
import org.apache.harmony.luni.platform.Platform;
import org.apache.harmony.luni.util.Msg;
import org.apache.harmony.luni.util.PriviAction;

/**
 * The default, concrete instance of datagram sockets. This class does not
 * support security checks. Alternative types of DatagramSocketImpl's may be
 * used by setting the <code>impl.prefix</code> system property.
 */
public class PlainDatagramSocketImpl extends DatagramSocketImpl {

    static final int MULTICAST_IF = 1;

    static final int MULTICAST_TTL = 2;

    static final int TCP_NODELAY = 4;

    static final int FLAG_SHUTDOWN = 8;

    private final static int SO_BROADCAST = 32;

    final static int IP_MULTICAST_ADD = 19;

    final static int IP_MULTICAST_DROP = 20;

    final static int IP_MULTICAST_TTL = 17;

    /**
     * for datagram and multicast sockets we have to set REUSEADDR and REUSEPORT
     * when REUSEADDR is set for other types of sockets we need to just set
     * REUSEADDR therefore we have this other option which sets both if
     * supported by the platform. this cannot be in SOCKET_OPTIONS because since
     * it is a public interface it ends up being public even if it is not
     * declared public
     */
    static final int REUSEADDR_AND_REUSEPORT = 10001;

    // Ignored in native code
    private boolean bindToDevice = false;

    private byte[] ipaddress = { 0, 0, 0, 0 };

    private int ttl = 1;

    private INetworkSystem netImpl = Platform.getNetworkSystem();

    private volatile boolean isNativeConnected;

    public int receiveTimeout;

    public boolean streaming = true;

    public boolean shutdownInput;

    /**
     * used to keep address to which the socket was connected to at the native
     * level
     */
    private InetAddress connectedAddress;

    private int connectedPort = -1;

    /**
     * used to store the trafficClass value which is simply returned as the
     * value that was set. We also need it to pass it to methods that specify an
     * address packets are going to be sent to
     */
    private int trafficClass;

    public PlainDatagramSocketImpl(FileDescriptor fd, int localPort) {
        super();
        this.fd = fd;
        this.localPort = localPort;
    }

    public PlainDatagramSocketImpl() {
        super();
        fd = new FileDescriptor();
    }

    @Override
    public void bind(int port, InetAddress addr) throws SocketException {
        String prop = AccessController.doPrivileged(new PriviAction<String>("bindToDevice")); //$NON-NLS-1$
        boolean useBindToDevice = prop != null && prop.toLowerCase().equals("true"); //$NON-NLS-1$
        netImpl.bind(fd, addr, port);
        if (0 != port) {
            localPort = port;
        } else {
            localPort = netImpl.getSocketLocalPort(fd, NetUtil.preferIPv6Addresses());
        }

        try {
            // Ignore failures
            setOption(SO_BROADCAST, Boolean.TRUE);
        } catch (IOException e) {
        }
    }

    @Override
    public void close() {
        synchronized (fd) {
            if (fd.valid()) {
                try {
                    netImpl.socketClose(fd);
                } catch (IOException e) {
                }
                fd = new FileDescriptor();
            }
        }
    }

    @Override
    public void create() throws SocketException {
        netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
    }

    @Override
    protected void finalize() {
        close();
    }

    public Object getOption(int optID) throws SocketException {
        if (optID == SocketOptions.SO_TIMEOUT) {
            return Integer.valueOf(receiveTimeout);
        } else if (optID == SocketOptions.IP_TOS) {
            return Integer.valueOf(trafficClass);
        } else {
            // Call the native first so there will be
            // an exception if the socket if closed.
            Object result = netImpl.getSocketOption(fd, optID);
            if (optID == SocketOptions.IP_MULTICAST_IF
                    && (netImpl.getSocketFlags() & MULTICAST_IF) != 0) {
                try {
                    return InetAddress.getByAddress(ipaddress);
                } catch (UnknownHostException e) {
                    return null;
                }
            }
            return result;
        }
    }

    @Override
    public int getTimeToLive() throws IOException {
        // Call the native first so there will be an exception if the socket if
        // closed.
        int result = (((Byte) getOption(IP_MULTICAST_TTL)).byteValue()) & 0xFF;
        if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
            return ttl;
        }
        return result;
    }

    @Override
    public byte getTTL() throws IOException {
        // Call the native first so there will be an exception if the socket if
        // closed.
        byte result = ((Byte) getOption(IP_MULTICAST_TTL)).byteValue();
        if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
            return (byte) ttl;
        }
        return result;
    }

    @Override
    public void join(InetAddress addr) throws IOException {
        setOption(IP_MULTICAST_ADD, new GenericIPMreq(addr));
    }

    @Override
    public void joinGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {
        if (addr instanceof InetSocketAddress) {
            InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
            setOption(IP_MULTICAST_ADD, new GenericIPMreq(groupAddr, netInterface));
        }
    }

    @Override
    public void leave(InetAddress addr) throws IOException {
        setOption(IP_MULTICAST_DROP, new GenericIPMreq(addr));
    }

    @Override
    public void leaveGroup(SocketAddress addr, NetworkInterface netInterface)
            throws IOException {
        if (addr instanceof InetSocketAddress) {
            InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
            setOption(IP_MULTICAST_DROP, new GenericIPMreq(groupAddr, netInterface));
        }
    }

    @Override
    protected int peek(InetAddress sender) throws IOException {
        if (isNativeConnected) {
            /*
             * in this case we know the port and address from which the data
             * must have be been received as the socket is connected. However,
             * we still need to do the receive in order to know that there was
             * data received. We use a short buffer as we don't actually need
             * the packet, only the knowledge that it is there
             */
            byte[] storageArray = new byte[10];
            DatagramPacket pack = new DatagramPacket(storageArray, storageArray.length);
            netImpl.recvConnectedDatagram(fd, pack, pack.getData(), pack.getOffset(), pack
                    .getLength(), receiveTimeout, true); // peek
            // to set the sender ,we now use a native function
            // sender.ipaddress = connectedAddress.getAddress();
            netImpl.setInetAddress(sender, connectedAddress.getAddress());
            return connectedPort;
        }
        return netImpl.peekDatagram(fd, sender, receiveTimeout);
    }

    @Override
    public void receive(DatagramPacket pack) throws java.io.IOException {
        try {
            if (isNativeConnected) {
                // do not peek
                netImpl.recvConnectedDatagram(fd, pack, pack.getData(), pack.getOffset(), pack
                        .getLength(), receiveTimeout, false);
                updatePacketRecvAddress(pack);
            } else {
                // receiveDatagramImpl2
                netImpl.receiveDatagram(fd, pack, pack.getData(), pack.getOffset(), pack
                        .getLength(), receiveTimeout, false);
            }
        } catch (InterruptedIOException e) {
            throw new SocketTimeoutException(e.getMessage());
        }
    }

    @Override
    public void send(DatagramPacket packet) throws IOException {

        if (isNativeConnected) {
            netImpl.sendConnectedDatagram(fd, packet.getData(), packet.getOffset(), packet
                    .getLength(), bindToDevice);
        } else {
            // sendDatagramImpl2
            netImpl.sendDatagram(fd, packet.getData(), packet.getOffset(), packet.getLength(),
                    packet.getPort(), bindToDevice, trafficClass, packet.getAddress());
        }
    }

    /**
     * Set the nominated socket option. As the timeouts are not set as options
     * in the IP stack, the value is stored in an instance field.
     * 
     * @throws SocketException thrown if the option value is unsupported or
     *         invalid
     */
    public void setOption(int optID, Object val) throws SocketException {
        /*
         * for datagram sockets on some platforms we have to set both the
         * REUSEADDR AND REUSEPORT so for REUSEADDR set this option option which
         * tells the VM to set the two values as appropriate for the platform
         */
        if (optID == SocketOptions.SO_REUSEADDR) {
            optID = REUSEADDR_AND_REUSEPORT;
        }

        if (optID == SocketOptions.SO_TIMEOUT) {
            receiveTimeout = ((Integer) val).intValue();
        } else {
            int flags = netImpl.getSocketFlags();
            try {
                netImpl.setSocketOption(fd, optID | (flags << 16), val);
            } catch (SocketException e) {
                // we don't throw an exception for IP_TOS even if the platform
                // won't let us set the requested value
                if (optID != SocketOptions.IP_TOS) {
                    throw e;
                }
            }
            if (optID == SocketOptions.IP_MULTICAST_IF && (flags & MULTICAST_IF) != 0) {
                InetAddress inet = (InetAddress) val;
                if (NetUtil.bytesToInt(inet.getAddress(), 0) == 0 || inet.isLoopbackAddress()) {
                    ipaddress = ((InetAddress) val).getAddress();
                } else {
                    InetAddress local = null;
                    try {
                        local = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        throw new SocketException("getLocalHost(): " + e.toString());
                    }
                    if (inet.equals(local)) {
                        ipaddress = ((InetAddress) val).getAddress();
                    } else {
                        throw new SocketException(val + " != getLocalHost(): " + local);
                    }
                }
            }
            /*
             * save this value as it is actually used differently for IPv4 and
             * IPv6 so we cannot get the value using the getOption. The option
             * is actually only set for IPv4 and a masked version of the value
             * will be set as only a subset of the values are allowed on the
             * socket. Therefore we need to retain it to return the value that
             * was set. We also need the value to be passed into a number of
             * natives so that it can be used properly with IPv6
             */
            if (optID == SocketOptions.IP_TOS) {
                trafficClass = ((Integer) val).intValue();
            }
        }
    }

    @Override
    public void setTimeToLive(int ttl) throws java.io.IOException {
        setOption(IP_MULTICAST_TTL, Byte.valueOf((byte) (ttl & 0xFF)));
        if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
            this.ttl = ttl;
        }
    }

    @Override
    public void setTTL(byte ttl) throws java.io.IOException {
        setOption(IP_MULTICAST_TTL, Byte.valueOf(ttl));
        if ((netImpl.getSocketFlags() & MULTICAST_TTL) != 0) {
            this.ttl = ttl;
        }
    }

    @Override
    public void connect(InetAddress inetAddr, int port) throws SocketException {

        // connectDatagram impl2
        netImpl.connectDatagram(fd, port, trafficClass, inetAddr);

        // if we get here then we are connected at the native level
        try {
            connectedAddress = InetAddress.getByAddress(inetAddr.getAddress());
        } catch (UnknownHostException e) {
            // this is never expected to happen as we should not have gotten
            // here if the address is not resolvable
            throw new SocketException(Msg.getString("K0317", inetAddr.getHostName())); //$NON-NLS-1$
        }
        connectedPort = port;
        isNativeConnected = true;
    }

    @Override
    public void disconnect() {
        try {
            netImpl.disconnectDatagram(fd);
        } catch (Exception e) {
            // there is currently no way to return an error so just eat any
            // exception
        }
        connectedPort = -1;
        connectedAddress = null;
        isNativeConnected = false;
    }

    @Override
    public int peekData(DatagramPacket pack) throws IOException {
        try {
            if (isNativeConnected) {
                netImpl.recvConnectedDatagram(fd, pack, pack.getData(), pack.getOffset(), pack
                        .getLength(), receiveTimeout, true); // peek
                updatePacketRecvAddress(pack);
            } else {
                // receiveDatagram 2
                netImpl.receiveDatagram(fd, pack, pack.getData(), pack.getOffset(), pack
                        .getLength(), receiveTimeout, true); // peek
            }
        } catch (InterruptedIOException e) {
            throw new SocketTimeoutException(e.toString());
        }
        return pack.getPort();
    }

    /**
     * Set the received address and port in the packet. We do this when the
     * Datagram socket is connected at the native level and the
     * recvConnnectedDatagramImpl does not update the packet with address from
     * which the packet was received
     * 
     * @param packet
     *            the packet to be updated
     */
    private void updatePacketRecvAddress(DatagramPacket packet) {
        packet.setAddress(connectedAddress);
        packet.setPort(connectedPort);
    }
}
