/*
 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 * @bug 4927640
 * @summary Tests the SCTP protocol implementation
 * @author chegar
 */

import java.net.*;
import java.io.*;
import java.util.List;
import java.util.Set;
import java.util.Iterator;
import java.nio.ByteBuffer;
import java.nio.channels.AlreadyBoundException;
import java.nio.channels.AlreadyConnectedException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.UnsupportedAddressTypeException;
import com.sun.nio.sctp.AssociationChangeNotification;
import com.sun.nio.sctp.AbstractNotificationHandler;
import com.sun.nio.sctp.HandlerResult;
import com.sun.nio.sctp.IllegalUnbindException;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.PeerAddressChangeNotification;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;
import com.sun.nio.sctp.ShutdownNotification;
import static java.lang.System.out;

/**
 * Tests bind, bindAddress, unbindAddress, getLocalAddress, and
 * getAllLocalAddresses.
 */
public class Bind {
     void test(String[] args) {
        if (!Util.isSCTPSupported()) {
            out.println("SCTP protocol is not supported");
            out.println("Test cannot be run");
            return;
        }

        /* Simply bind tests */
        testBind();

        /* Test unconnected */
        testBindUnbind(false);

        /* Test connected */
        /* Adding/Removing addresses from a connected association is optional.
         * This test can be run on systems that support dynamic address
         * reconfiguration */
        //testBindUnbind(true);
    }

    void testBind() {
        SctpChannel channel = null;
        try {
            channel = SctpChannel.open();

            /* TEST 1: empty set if channel is not bound */
            check(channel.getAllLocalAddresses().isEmpty(),
                    "getAllLocalAddresses returned non empty set for unbound channel");

            /* TEST 2: null to bind the channel to an automatically assigned
             *         socket address */
            channel.bind(null);

            /* TEST 3: non empty set if the channel is bound */
            check(!channel.getAllLocalAddresses().isEmpty(),
                    "getAllLocalAddresses returned empty set for bound channel");
            debug("getAllLocalAddresses on channel bound to the wildcard:\n"
                    + channel.getAllLocalAddresses());

            /* TEST 4: AlreadyBoundException if this channel is already bound */
            try { channel.bind(null); }
            catch (AlreadyBoundException unused) { pass(); }
            catch (IOException ioe) { unexpected(ioe); }

            /* TEST 5: UnsupportedAddressTypeException */
            try {
                channel.close();  /* open a new unbound channel for test */
                channel = SctpChannel.open();
                channel.bind(new UnsupportedSocketAddress());
                fail("UnsupportedSocketAddress expected");
            } catch (UnsupportedAddressTypeException unused) { pass();
            } catch (IOException ioe) { unexpected(ioe); }

            /* TEST 6: AlreadyConnectedException */
            try {
                channel.close();  /* open a new unbound channel for test */
                channel = SctpChannel.open();
                connectChannel(channel);
                channel.bind(null);
                fail("AlreadyConnectedException expected");
            } catch (AlreadyConnectedException unused) { pass();
            } catch (IOException ioe) { unexpected(ioe); }

            /* TEST 7: ClosedChannelException - If this channel is closed */
            try {
                channel.close();  /* open a new unbound channel for test */
                channel = SctpChannel.open();
                channel.close();
                channel.bind(null);
                fail("ClosedChannelException expected");
            } catch (ClosedChannelException unused) { pass();
            } catch (IOException ioe) { unexpected(ioe); }

            /* TEST 8: ClosedChannelException if channel is closed */
            try {
                channel.getAllLocalAddresses();
                fail("should have thrown ClosedChannelException");
            } catch (ClosedChannelException cce) {
               pass();
            } catch (Exception ioe) {
                unexpected(ioe);
            }
        } catch (IOException ioe) {
            unexpected(ioe);
        } finally {
            try { channel.close(); }
            catch (IOException ioe) { unexpected(ioe); }
        }
    }

    void testBindUnbind(boolean connected) {
        SctpChannel channel = null;
        SctpChannel peerChannel = null;

        debug("testBindUnbind, connected: " + connected);
        try {
            channel = SctpChannel.open();

            List<InetAddress> addresses = Util.getAddresses(true, false);
            Iterator iterator = addresses.iterator();
            InetSocketAddress a = new InetSocketAddress((InetAddress)iterator.next(), 0);
            debug("channel.bind( " + a + ")");
            channel.bind(a);
            while (iterator.hasNext()) {
                InetAddress ia = (InetAddress)iterator.next();
                debug("channel.bindAddress(" + ia + ")");
                channel.bindAddress(ia);
            }
            if (debug) {Util.dumpAddresses(channel, out);}

            if (connected) {
                /* Test with connected channel */
                peerChannel = connectChannel(channel);
            }

            /* TEST 1: bind/unbindAddresses on the system addresses */
            debug("bind/unbindAddresses on the system addresses");
            List<InetAddress> addrs = Util.getAddresses(true, false);
            for (InetAddress addr : addrs) {
                try {
                    debug("unbindAddress: " + addr);
                    check(boundAddress(channel, addr), "trying to remove address that is not bound");
                    channel.unbindAddress(addr);
                    if (debug) {Util.dumpAddresses(channel, out);}
                    check(!boundAddress(channel, addr), "address was not removed");

                    debug("bindAddress: " + addr);
                    channel.bindAddress(addr);
                    if (debug) {Util.dumpAddresses(channel, out);}
                    check(boundAddress(channel, addr), "address is not bound");
                } catch (IOException ioe) {
                    unexpected(ioe);
                }
            }

            /* TEST 2: bindAddress - already bound address. */
            InetAddress againAddress = addrs.get(0);
            try {
                debug("bind already bound address " + againAddress);
                channel.bindAddress(againAddress);
            } catch (AlreadyBoundException unused) {
                debug("Caught AlreadyBoundException - OK");
                pass();
            } catch (IOException ioe) {
                unexpected(ioe);
            }

            /* TEST 3: bind non local address */
            try {
                InetAddress nla = InetAddress.getByName("123.123.123.123");
                debug("bind non local address " + nla);
                channel.bindAddress(nla);
            } catch (IOException ioe) {
                debug("Informative only " + ioe);
            }

            /* TEST 4: unbind address that is not bound */
            try {
                debug("unbind address that is not bound " + againAddress);
                /* remove address first then again */
                channel.unbindAddress(againAddress);
                channel.unbindAddress(againAddress);
            } catch (IllegalUnbindException unused) {
                debug("Caught IllegalUnbindException - OK");
                pass();
            } catch (IOException ioe) {
                unexpected(ioe);
            }

            /* TEST 5: unbind address that is not bound */
            try {
                InetAddress nla = InetAddress.getByName("123.123.123.123");
                debug("unbind address that is not bound " + nla);
                channel.unbindAddress(nla);

            } catch (IllegalUnbindException unused) {
                debug("Caught IllegalUnbindException - OK");
                pass();
            } catch (IOException ioe) {
                unexpected(ioe);
            }

            if (connected) {
                channel.shutdown();

                BindNotificationHandler handler = new BindNotificationHandler();
                ByteBuffer buffer = ByteBuffer.allocate(10);
                MessageInfo info;
                while((info = peerChannel.receive(buffer, null, handler)) != null) {
                    if (info != null) {
                        if (info.bytes() == -1) {
                            debug("peerChannel Reached EOF");
                            break;
                        }
                    }
                }

                while((info = channel.receive(buffer, null, handler)) != null) {
                    if (info != null) {
                        if (info.bytes() == -1) {
                            debug("channel Reached EOF");
                            break;
                        }
                    }
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            try { if (channel != null) channel.close(); }
            catch (IOException ioe) { unexpected(ioe); }
        }
    }

    boolean boundAddress(SctpChannel channel, InetAddress addr)
        throws IOException {
        for (SocketAddress boundAddr : channel.getAllLocalAddresses()) {
            if (((InetSocketAddress) boundAddr).getAddress().equals(addr))
                return true;
        }
        return false;
    }

    SctpChannel connectChannel(SctpChannel channel)
        throws IOException {
        debug("connecting channel...");
        try {
            SctpServerChannel ssc = SctpServerChannel.open();
            ssc.bind(null);
            Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
            Iterator<SocketAddress> iterator = addrs.iterator();
            SocketAddress addr = iterator.next();
            debug("using " + addr + "...");
            channel.connect(addr);
            SctpChannel peerChannel = ssc.accept();
            ssc.close();
            debug("connected");
            return peerChannel;
        } catch (IOException ioe) {
            debug("Cannot connect channel");
            unexpected(ioe);
            throw ioe;
        }
    }

    class BindNotificationHandler extends AbstractNotificationHandler<Object>
    {
        @Override
        public HandlerResult handleNotification(
                AssociationChangeNotification acn, Object unused)
        {
            debug("AssociationChangeNotification: " +  acn);
            return HandlerResult.CONTINUE;
        }

        @Override
        public HandlerResult handleNotification(
                PeerAddressChangeNotification pacn, Object unused)
        {
            debug("PeerAddressChangeNotification: " +  pacn);
            return HandlerResult.CONTINUE;
        }

        @Override
        public HandlerResult handleNotification(
                ShutdownNotification sn, Object unused)
        {
            debug("ShutdownNotification: " +  sn);
            return HandlerResult.CONTINUE;
        }
    }

    class UnsupportedSocketAddress extends SocketAddress { }

    //--------------------- Infrastructure ---------------------------
    boolean debug = true;
    volatile int passed = 0, failed = 0;
    void pass() {passed++;}
    void fail() {failed++; Thread.dumpStack();}
    void fail(String msg) {System.err.println(msg); fail();}
    void unexpected(Throwable t) {failed++; t.printStackTrace();}
    void check(boolean cond) {if (cond) pass(); else fail();}
    void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
    void debug(String message) {if(debug) { System.out.println(message); }  }
    public static void main(String[] args) throws Throwable {
        Class<?> k = new Object(){}.getClass().getEnclosingClass();
        try {k.getMethod("instanceMain",String[].class)
                .invoke( k.newInstance(), (Object) args);}
        catch (Throwable e) {throw e.getCause();}}
    public void instanceMain(String[] args) throws Throwable {
        try {test(args);} catch (Throwable t) {unexpected(t);}
        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
        if (failed > 0) throw new AssertionError("Some tests failed");}

}
