package com.intrbiz.bergamot.nrpe;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import org.apache.log4j.Logger;
import com.intrbiz.bergamot.nrpe.model.NRPEPacket;
import com.intrbiz.bergamot.nrpe.model.NRPEResponse;
/**
* <p>
* Query an NRPE daemon from Java
* </p>
* <p>
* You should use the NRPE client, inside a try-with-resources statement, as follows:
* </p>
*
* <pre>
* <code>
* try (NRPEClient client = new NRPEClient("127.0.0.1"))
* {
* System.out.println("NRPE Daemon Version: " + client.hello().getOutput());
* }
* catch (IOException e)
* {
* e.printStackTrace();
* }
* </code>
* </pre>
* <p>
* Note: currently *ONLY* SSL is supported
* </p>
*/
public class NRPEClient implements AutoCloseable
{
public static final String[] CIPHERS = new String[] { "TLS_DH_anon_WITH_AES_128_CBC_SHA" };
public static final String[] PROTOCOLS = new String[] { "TLSv1" };
private static final SSLSocketFactory FACTORY = (SSLSocketFactory) SSLSocketFactory.getDefault();
private Logger logger = Logger.getLogger(NRPEClient.class);
private SocketAddress address;
private SSLSocket socket;
public NRPEClient(String host, int port, int connectTimeout) throws IOException
{
super();
this.address = new InetSocketAddress(host, port);
this.socket = (SSLSocket) FACTORY.createSocket();
this.socket.setEnabledProtocols(PROTOCOLS);
this.socket.setEnabledCipherSuites(CIPHERS);
this.socket.connect(this.address, connectTimeout);
}
public NRPEClient(String host) throws IOException
{
this(host, 5666, 2_500);
}
/**
* Send an arbitrary NRPE packet
*
* @param packet
* @return
* @throws IOException
*/
public NRPEPacket send(NRPEPacket packet) throws IOException
{
try
{
InputStream in = this.socket.getInputStream();
OutputStream out = this.socket.getOutputStream();
// send the query
long start = System.nanoTime();
out.write(packet.encodePacket());
out.flush();
// read the response
byte[] response = new byte[2048];
int read = in.read(response);
// validate the read
if (read <= 0)
{
logger.warn("The NRPE daemon returned 0 bytes, check the daemon logs on " + this.address.toString());
throw new IOException("The NRPE daemon returned 0 bytes");
}
// parse the response
NRPEPacket responsePacket = NRPEPacket.parse(response, 0, read);
long end = System.nanoTime();
responsePacket.setRuntime(((double) (end - start)) / 1_000_000D);
return responsePacket;
}
catch (SSLHandshakeException e)
{
logger.warn("Failed to perform SSL handshake, check allowed_hosts and the daemon logs on " + this.address.toString());
throw new IOException("Failed to perform SSL handshake, check allowed_hosts", e);
}
}
/**
* Execute the NRPE hello command, this will return the NRPE daemon version
*
* @return
* @throws IOException
*/
public NRPEResponse hello() throws IOException
{
NRPEPacket response = this.send(new NRPEPacket().version2().hello());
return new NRPEResponse(response.getOutput(), response.getResponseCode(), response.getRuntime());
}
/**
* Execute the given NRPE command
*
* @param command
* @return
* @throws IOException
*/
public NRPEResponse command(String command) throws IOException
{
if (command == null) throw new IllegalArgumentException("The command cannot be null");
NRPEPacket response = this.send(new NRPEPacket().version2().command(command));
return new NRPEResponse(response.getOutput(), response.getResponseCode(), response.getRuntime());
}
/**
* Execute the given NRPE command with the given arguments
*
* @param command
* @param args
* @return
* @throws IOException
*/
public NRPEResponse command(String command, String... args) throws IOException
{
if (command == null) throw new IllegalArgumentException("The command cannot be null");
NRPEPacket response = this.send(new NRPEPacket().version2().command(command, args));
return new NRPEResponse(response.getOutput(), response.getResponseCode(), response.getRuntime());
}
/**
* Execute the given NRPE command with the given arguments (as a List)
*
* @param command
* @param args
* @return
* @throws IOException
*/
public NRPEResponse command(String command, List<String> args) throws IOException
{
if (command == null) throw new IllegalArgumentException("The command cannot be null");
NRPEPacket response = this.send(new NRPEPacket().version2().command(command, args));
return new NRPEResponse(response.getOutput(), response.getResponseCode(), response.getRuntime());
}
/**
* Close this connection
*/
public void close() throws IOException
{
this.socket.close();
}
}