Package org.rioproject.util

Source Code of org.rioproject.util.MulticastStatus

/*
* Copyright to the original author or authors.
*
* Licensed 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.rioproject.util;

import java.io.InterruptedIOException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
import java.net.DatagramPacket;

/**
* Class which can be used to determine whether multicast is available. Credit
* goes to Alexander V. Konstantinou
*/
public class MulticastStatus {
    private static final Object lock = new Object();
    /**
     * Determines if a multicast socket can be created and a Request
     * announcement can be sent. Note that it is still possible that multicast
     * does not work outside the host.
     *
     * @param timeout The timeout to use when checking the status
     *
     * @throws IOException If there are errors interfacing ith the network
     * @throws IllegalArgumentException if the timeout is < 0
     */
    public static void checkMulticast(final int timeout) throws IOException {
        if(timeout < 0)
            throw new IllegalArgumentException("Invalid timeout = " + timeout);
        /** Use Jini's multicast group */
        final InetAddress group = net.jini.discovery.Constants.getRequestAddress();
        /** Use a different port from Jini discovery */
        final short port = net.jini.discovery.Constants.discoveryPort + 1;
        final long endMillis = System.currentTimeMillis() + timeout;
        final MulticastSocket msocket = new MulticastSocket(port);
        msocket.setTimeToLive(1); // XXX - could it be 0 ?
        msocket.joinGroup(group);
        msocket.setSoTimeout(timeout);
        StringBuilder builder = new StringBuilder();
        builder.append(MulticastStatus.class.getName()).append(".ping(").append(System.currentTimeMillis()).append(")");
        final byte[] messageBytes = builder.toString().getBytes();
        DatagramPacket packet = new DatagramPacket(messageBytes, messageBytes.length, group, port);

        final Boolean[] received = new Boolean[]{Boolean.FALSE};
        /**
         * Receive thread waits for msocket SOTIMEOUT to receive a packet. The
         * exception catching code is needed to handle Java multicast exceptions
         * caused by bug 4190513.
         */
        Thread receiveThread = new Thread("MulticastStatus") {
            public void run() {
                byte[] buf = new byte[1024];
                DatagramPacket recv = new DatagramPacket(buf, buf.length);
                do {
                    try {
                        msocket.receive(recv);
                        synchronized(lock) {
                            received[0] = Boolean.TRUE;
                        }
                        return;
                    } catch(InterruptedIOException e) {
                        return;
                    } catch(Throwable e) {
                        long remainingMillis = endMillis
                                               - System.currentTimeMillis();
                        if(remainingMillis <= 0) {
                            return;
                        } else {
                            try {
                                msocket.setSoTimeout((int)remainingMillis);
                            } catch(SocketException e2) {
                                return;
                            }
                        }
                    }
                } while (true);
            }
        };
        receiveThread.start();
        // Start sending packets every 500 msec until the timeout expires
        // or a packet is received
        do {
            try {
                msocket.send(packet);
                synchronized(lock) {
                    if(received[0]) {
                        msocket.leaveGroup(group);
                        msocket.close();
                        return;
                    }
                }
                try {
                    Thread.sleep(500);
                } catch(InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                throw new IOException("Problem creating or sending multicast packets", e);
            } finally {
                msocket.leaveGroup(group);
                msocket.close();
            }
        } while (System.currentTimeMillis() < endMillis);

        throw new IOException("Multicast packets were not received in the allotted time");
    }

    public static void main(String[] args) {
        try {
            checkMulticast(1000 * 5);
            System.out.println("======================\nMulticast check successful\n======================");
        } catch(IOException ioe) {
            System.out.println("======================\nMulticast check FAILED\n======================");
            ioe.printStackTrace();
        }
    }
}
TOP

Related Classes of org.rioproject.util.MulticastStatus

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.