package hudson.plugins.pxe;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import org.jvnet.hudson.proxy_dhcp.ProxyDhcpService;
import org.jvnet.hudson.proxy_dhcp.DHCPPacket;
import org.jvnet.hudson.tftpd.PathResolver;
import org.jvnet.hudson.tftpd.TFTPServer;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.DatagramPacket;
import java.util.logging.Logger;
/**
* This runs DHCP proxy service and TFTP service in a separate JVM that has the higher priviledge.
* This callable blocks forever.
*
* @author Kohsuke Kawaguchi
*/
public class PXEBootProcess implements Callable<DaemonService, IOException> {
private final PathResolver resolver;
private final DHCPPacketFilter dhcpFilter;
private final String tftpAddress;
public PXEBootProcess(PathResolver resolver, DHCPPacketFilter dhcpFilter, String tftpAddress) {
this.resolver = resolver;
this.dhcpFilter = dhcpFilter;
this.tftpAddress = tftpAddress;
}
public DaemonService call() throws IOException {
// has to bind to the "any address" to receive packets, at least on Ubuntu
LOGGER.info("Starting a DHCP proxy service");
final Thread dhcp = start(new ProxyDhcpService((Inet4Address)InetAddress.getByName(tftpAddress),"pxelinux.0") {
@Override
protected boolean shallWeRespond(DatagramPacket datagram, DHCPPacket packet) {
return dhcpFilter.shallWeRespond(packet.chaddr);
}
});
// serve up resources
LOGGER.info("Starting a TFTP service");
final Thread tftp = start(new TFTPServer(resolver));
LOGGER.info("All services ready");
return Channel.current().export(DaemonService.class,new DaemonService() {
public boolean isDHCPProxyAlive() {
return dhcp.isAlive();
}
public boolean isTFTPAlive() {
return tftp.isAlive();
}
});
}
private Thread start(Runnable task) {
Thread t = new Thread(task);
t.setDaemon(true);
t.start();
return t;
}
private static final Logger LOGGER = Logger.getLogger(PXEBootProcess.class.getName());
}