/**
* Copyright 2013-2015 Seagate Technology LLC.
*
* This Source Code Form is subject to the terms of the Mozilla
* Public License, v. 2.0. If a copy of the MPL was not
* distributed with this file, You can obtain one at
* https://mozilla.org/MP:/2.0/.
*
* This program is distributed in the hope that it will be useful,
* but is provided AS-IS, WITHOUT ANY WARRANTY; including without
* the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or
* FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public
* License for more details.
*
* See www.openkinetic.org for more project information
*/
package com.seagate.kinetic.monitor;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.seagate.kinetic.common.lib.NetUtil;
/**
*
* Kinetic applications may start an instance of this class and set a message
* listener to it.
* <p>
* The {@link HeartbeatListener#onMessage(byte[])} will be invoked for each
* message received by the subscriber.
*
* @author chiaming
*
*/
public class HeartbeatListener implements Runnable {
private final static Logger logger = Logger
.getLogger(HeartbeatListener.class.getName());
// multicast socket
private MulticastSocket mcastSocket = null;
private InetAddress mcastAddress = null;
private String mcastDestination = "239.1.2.3";
// destination port
private int mcastPort = 8123;
private boolean isClosed = false;
private Thread thread = null;
// net interface name
private String interfaceName = null;
/**
* Construct a heartbeat consumer with default address and port.
*
* @throws IOException
*/
public HeartbeatListener() throws IOException {
this.init();
}
/**
* Construct a heartbeat listener with the specified network interface name.
*
* @param netInterfaceName
* @throws IOException
*/
public HeartbeatListener(String netInterfaceName) throws IOException {
this.interfaceName = netInterfaceName;
this.init();
}
public HeartbeatListener(String address, int port) throws IOException {
this.mcastDestination = address;
this.mcastPort = port;
this.init();
}
private void init() throws IOException {
// network interface
NetworkInterface ni = null;
if (this.interfaceName != null) {
ni = NetworkInterface.getByName(interfaceName);
} else {
ni = NetUtil.findMulticastNetworkInterface();
}
// my multicast listening address
mcastAddress = InetAddress.getByName(mcastDestination);
// msocket
mcastSocket = new MulticastSocket(mcastPort);
// only set it if we are allowed to search
if (ni != null) {
logger.info("using network interface: " + ni.getDisplayName());
mcastSocket.setNetworkInterface(ni);
}
// join the m group
this.mcastSocket.joinGroup(mcastAddress);
// listen in the background
this.thread = new Thread(this);
thread.start();
}
public void close() {
this.isClosed = true;
this.mcastSocket.close();
}
@Override
public void run() {
logger.info("Heart beat listener is ready on address: "
+ this.mcastDestination + ":" + this.mcastPort);
while (isClosed == false) {
try {
byte[] data = new byte[64 * 1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
this.mcastSocket.receive(packet);
// deliver
onMessage(packet.getData());
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
}
}
}
/**
* Applications override this method to receive heart beat messages.
*
* @param data
* UTF8 encoded heart beat message.
*/
public void onMessage(byte[] data) {
try {
logger.info("received heart beat: " + new String(data, "UTF-8"));
} catch (UnsupportedEncodingException e) {
logger.warning(e.getMessage());
}
}
public static void main(String[] args) throws IOException {
@SuppressWarnings("unused")
HeartbeatListener listener = new HeartbeatListener();
}
}