/*
 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


import java.nio.channels.*;
import java.nio.charset.*;
import java.nio.ByteBuffer;
import java.net.*;
import java.io.IOException;
import java.util.*;

public class Reader {

    static void usage() {
        System.err.println("usage: java Reader group:port@interf [-only source...] [-block source...]");
        System.exit(-1);
    }

    static void printDatagram(SocketAddress sa, ByteBuffer buf) {
        System.out.format("-- datagram from %s --\n",
            ((InetSocketAddress)sa).getAddress().getHostAddress());
        System.out.println(Charset.defaultCharset().decode(buf));
    }

    static void parseAddessList(String s, List<InetAddress> list)
        throws UnknownHostException
    {
        String[] sources = s.split(",");
        for (int i=0; i<sources.length; i++) {
            list.add(InetAddress.getByName(sources[i]));
        }
    }

    public static void main(String[] args) throws IOException {
        if (args.length == 0)
            usage();

        // first parameter is the multicast address (interface required)
        MulticastAddress target = MulticastAddress.parse(args[0]);
        if (target.interf() == null)
            usage();

        // addition arguments are source addresses to include or exclude
        List<InetAddress> includeList = new ArrayList<InetAddress>();
        List<InetAddress> excludeList = new ArrayList<InetAddress>();
        int argc = 1;
        while (argc < args.length) {
            String option = args[argc++];
            if (argc >= args.length)
                usage();
            String value = args[argc++];
            if (option.equals("-only")) {
                 parseAddessList(value, includeList);
                continue;
            }
            if (option.equals("-block")) {
                parseAddessList(value, excludeList);
                continue;
            }
            usage();
        }
        if (!includeList.isEmpty() && !excludeList.isEmpty()) {
            usage();
        }

        // create and bind socket
        ProtocolFamily family = StandardProtocolFamily.INET;
        if (target.group() instanceof Inet6Address) {
            family = StandardProtocolFamily.INET6;
        }
        DatagramChannel dc = DatagramChannel.open(family)
            .setOption(StandardSocketOptions.SO_REUSEADDR, true)
            .bind(new InetSocketAddress(target.port()));

        if (includeList.isEmpty()) {
            // join group and block addresses on the exclude list
            MembershipKey key = dc.join(target.group(), target.interf());
            for (InetAddress source: excludeList) {
                key.block(source);
            }
        } else {
            // join with source-specific membership for each source
            for (InetAddress source: includeList) {
                dc.join(target.group(), target.interf(), source);
            }
        }

        // register socket with Selector
        Selector sel = Selector.open();
        dc.configureBlocking(false);
        dc.register(sel, SelectionKey.OP_READ);

        // print out each datagram that we receive
        ByteBuffer buf = ByteBuffer.allocateDirect(4096);
        for (;;) {
            int updated = sel.select();
            if (updated > 0) {
                Iterator<SelectionKey> iter = sel.selectedKeys().iterator();
                while (iter.hasNext()) {
                    SelectionKey sk = iter.next();
                    iter.remove();

                    DatagramChannel ch = (DatagramChannel)sk.channel();
                    SocketAddress sa = ch.receive(buf);
                    if (sa != null) {
                        buf.flip();
                        printDatagram(sa, buf);
                        buf.rewind();
                        buf.limit(buf.capacity());
                    }
                }
            }
        }
    }
}
