/**
* 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.simulator.heartbeat.provider;
import java.net.DatagramPacket;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import kinetic.simulator.SimulatorConfiguration;
import com.google.gson.Gson;
import com.seagate.kinetic.common.lib.NetUtil;
import com.seagate.kinetic.heartbeat.HeartbeatMessage;
import com.seagate.kinetic.heartbeat.KineticNetworkInterface;
import com.seagate.kinetic.simulator.heartbeat.HeartbeatProvider;
/**
*
* Multicast heartbeat provider.
*
* @author chiaming
*
*/
public class MulticastHeartbeatProvider implements HeartbeatProvider {
private final static Logger logger = Logger
.getLogger(MulticastHeartbeatProvider.class.getName());
// simulator configuration
private SimulatorConfiguration config = null;
// multicast socket
private MulticastSocket mcastSocket = null;
// inetaddress
private InetAddress mcastAddress = null;
// multicast address
private final String mcastDestination = "239.1.2.3";
// destination port
private int mcastPort = 8123;
// host ip
// private String thisHostIp = "127.0.0.1";
// host port
// private String thisHostPort = thisHostIp + ":8123";
// gson instance
private static Gson gson = new Gson();
// current engine instance
// private final SimulatorEngine engine = null;
// heart beat message
private final HeartbeatMessage heartbeatMessage = new HeartbeatMessage();
// heartbeat message in string format
private String heartbeatMessageStr = null;
// heart beat packet
private DatagramPacket packet = null;
public MulticastHeartbeatProvider() {
// TODO Auto-generated constructor stub
}
@Override
public void init(SimulatorConfiguration config) {
// my config
this.config = config;
// initilize
this.doInit();
}
@Override
public void sendHeartbeat() {
try {
// send heart beat
this.mcastSocket.send(packet);
// logger.info("sent heartbeat message: " +
// this.heartbeatMessageStr);
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
}
}
@Override
public void close() {
// close mcast socket
this.mcastSocket.close();
logger.info("multicast heartbeat stopped");
}
/**
* Initialize heart beat destination, message, etc.
*/
private void doInit() {
try {
// multicast socket
mcastSocket = new MulticastSocket();
NetworkInterface mni = NetUtil.findMulticastNetworkInterface();
if (mni != null) {
mcastSocket.setNetworkInterface(mni);
}
// multicast group address
mcastAddress = InetAddress.getByName(mcastDestination);
// multicast listener port
this.mcastPort = config.getHeartbeatPort();
// init heart beat message
this.initHeartbeatMessage();
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
}
}
/**
* initialize heart beat message
*/
public void initHeartbeatMessage() {
try {
// protocol_version
this.heartbeatMessage.setProtocolVersion(SimulatorConfiguration
.getProtocolVersion());
this.heartbeatMessage.setFirmwareVersion(SimulatorConfiguration
.getSimulatorVersion());
this.heartbeatMessage
.setManufacturer(SimulatorConfiguration.VENDER);
this.heartbeatMessage.setModel(SimulatorConfiguration.MODEL);
this.heartbeatMessage.setSerialNumber(config.getSerialNumber());
this.heartbeatMessage.setWorldWideName(config.getWorldWideName());
// set port to heart beat message
this.heartbeatMessage.setPort(config.getPort());
// set tls port to heart beat message
this.heartbeatMessage.setTlsPort(config.getSslPort());
// get all network interfaces on this machine
Enumeration<NetworkInterface> netInterfaces = NetworkInterface
.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
// get next interface
NetworkInterface ni = netInterfaces.nextElement();
// my network interface
KineticNetworkInterface knetInterface = new KineticNetworkInterface();
// set kinetic NI display name
knetInterface.setName(ni.getDisplayName());
// set mac addr
byte[] mac = ni.getHardwareAddress();
if (mac != null) {
knetInterface.setMacAddress(bytesToStringMac(mac));
}
// get inet addresses on this interface
Enumeration<InetAddress> addresses = ni.getInetAddresses();
while (addresses.hasMoreElements()) {
// get next inet addr
InetAddress addr2 = addresses.nextElement();
// get string address
String addrString = addr2.getHostAddress();
if (addr2 instanceof Inet6Address) {
knetInterface.setIpV6Address(addrString);
} else {
knetInterface.setIpV4Address(addrString);
}
}
// add my network interface to heart beat
this.heartbeatMessage.getNetworkInterfaces().add(knetInterface);
}
// heart beat message string
this.heartbeatMessageStr = gson.toJson(this.heartbeatMessage,
HeartbeatMessage.class);
// heart beat message byte[]
byte[] data = heartbeatMessageStr.getBytes("UTF-8");
// heart beat packet
packet = new DatagramPacket(data, data.length, this.mcastAddress,
this.mcastPort);
logger.info("heart beat message initialized., msg="
+ heartbeatMessageStr);
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
}
}
public static String bytesToStringMac(byte[] mac) {
StringBuilder sb = new StringBuilder(18);
for (byte b : mac) {
if (sb.length() > 0) {
sb.append(':');
}
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}