picoview.collectd.CollectClient.java Source code

Java tutorial

Introduction

Here is the source code for picoview.collectd.CollectClient.java

Source

/*
 * Copyright (c) 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 picoview.collectd;

import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.hashvoid.crossbinder.hod.Configuration;
import com.hashvoid.crossbinder.hod.Initializable;
import com.hashvoid.crossbinder.hod.Inject;
import com.hashvoid.crossbinder.hod.Singleton;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ChannelFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.channel.socket.nio.NioDatagramChannel;
import picoview.collectd.data.CollectDataHandler;
import picoview.collectd.data.support.PacketImpl;
import picoview.collectd.reader.PacketReader;
import picoview.collectd.reader.Part;

/**
 * @author randondiesel
 *
 */

@Singleton
public class CollectClient implements ICollectClient, Initializable {

    @Configuration(name = "collectd.nic", required = false)
    private String nicName;

    @Configuration(name = "collectd.multicast-host", required = false)
    private String multicastHost;

    @Configuration(name = "collectd.multicast-port", required = false)
    private int multicastPort;

    @Inject(name = CollectDataHandler.COMPONENT_NAME, optional = true)
    private CollectDataHandler dataHandler;

    @Override
    public void initialize() throws RuntimeException {
        NetworkInterface nic;
        try {
            if (StringUtils.isBlank(nicName)) {
                nic = NetworkInterface.getByIndex(0);
            } else {
                nic = NetworkInterface.getByName(nicName);
            }
        } catch (SocketException exep) {
            throw new RuntimeException("unable to determine network interface to use", exep);
        }

        Bootstrap bs = new Bootstrap();
        bs.option(ChannelOption.SO_BROADCAST, true);
        bs.option(ChannelOption.SO_REUSEADDR, true);
        bs.option(ChannelOption.IP_MULTICAST_LOOP_DISABLED, false);
        bs.option(ChannelOption.SO_RCVBUF, 2048);
        bs.option(ChannelOption.IP_MULTICAST_TTL, 255);

        bs.group(new NioEventLoopGroup());

        bs.channelFactory(new ChannelFactory<Channel>() {
            public Channel newChannel() {
                return new NioDatagramChannel(InternetProtocolFamily.IPv4);
            }
        });
        bs.handler(new ChannelInitializer<DatagramChannel>() {
            @Override
            public void initChannel(DatagramChannel channel) throws Exception {
                channel.pipeline().addLast(new CollectChannelHandler());
            }
        });

        if (StringUtils.isBlank(multicastHost)) {
            multicastHost = "239.192.74.66";
        }
        if (multicastPort <= 0) {
            multicastPort = 25826;
        }

        try {
            DatagramChannel dch = (DatagramChannel) bs.bind(multicastPort).sync().channel();
            ChannelFuture cf = dch.joinGroup(new InetSocketAddress(multicastHost, multicastPort), nic).sync();
            if (!cf.isSuccess()) {
                throw new RuntimeException("unable to join multicast group");
            }
        } catch (InterruptedException exep) {
            throw new RuntimeException("unable to setup network for collect client", exep);
        }
    }

    class CollectChannelHandler extends SimpleChannelInboundHandler<DatagramPacket> {

        @Override
        public void channelRead0(ChannelHandlerContext ctxt, DatagramPacket msg) throws Exception {
            ByteBuf buffer = msg.content();
            byte[] data = new byte[buffer.capacity()];
            buffer.getBytes(0, data);

            PacketReader preader = new PacketReader(data);
            List<Part> parts = new ArrayList<>();
            Part part;
            while ((part = preader.read()) != null) {
                parts.add(part);
            }

            PacketImpl packet = null;
            try {
                packet = new PacketImpl(msg.sender().getHostString(), parts);
            } catch (Exception exep) {
                exep.printStackTrace();
                for (Part part1 : parts) {
                    System.out.println(part1);
                }
            }
            if (packet != null && dataHandler != null) {
                dataHandler.processPacket(packet);
            }
        }
    }
}