package se.unlogic.eagledns;
import org.apache.log4j.Logger;
import org.xbill.DNS.DClass;
import org.xbill.DNS.Record;
import org.xbill.DNS.Zone;
import org.xbill.DNS.ZoneTransferException;
import org.xbill.DNS.ZoneTransferIn;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
public class CachedSecondaryZone {
private Logger log = Logger.getLogger(this.getClass());
protected ZoneProvider zoneProvider;
private SecondaryZone secondaryZone;
public CachedSecondaryZone(ZoneProvider zoneProvider, SecondaryZone secondaryZone) {
this.zoneProvider = zoneProvider;
this.secondaryZone = secondaryZone;
//this.update();
if(this.secondaryZone.getZoneCopy() != null){
log.info("Using stored zone data for sedondary zone " + this.secondaryZone.getZoneName());
}
}
public SecondaryZone getSecondaryZone() {
return secondaryZone;
}
public void setSecondaryZone(SecondaryZone secondaryZone) {
this.secondaryZone = secondaryZone;
}
/**
* Updates this secondary zone from the primary zone
* @param axfrTimeout
*/
public void update(int axfrTimeout) {
try {
ZoneTransferIn xfrin = ZoneTransferIn.newAXFR(this.secondaryZone.getZoneName(), this.secondaryZone.getRemoteServerAddress(), null);
xfrin.setDClass(DClass.value(this.secondaryZone.getDclass()));
xfrin.setTimeout(axfrTimeout);
List<?> records = xfrin.run();
if (!xfrin.isAXFR()) {
log.warn("Unable to transfer zone " + this.secondaryZone.getZoneName() + " from server " + this.secondaryZone.getRemoteServerAddress() + ", response is not a valid AXFR!");
return;
}
Zone axfrZone = new Zone(this.secondaryZone.getZoneName(),records.toArray(new Record[records.size()]));
log.debug("Zone " + this.secondaryZone.getZoneName() + " successfully transfered from server " + this.secondaryZone.getRemoteServerAddress());
if(!axfrZone.getSOA().getName().equals(this.secondaryZone.getZoneName())){
log.warn("Invalid AXFR zone name in response when updating secondary zone " + this.secondaryZone.getZoneName() + ". Got zone name " + axfrZone.getSOA().getName() + " in respons.");
}
if(this.secondaryZone.getZoneCopy() == null || this.secondaryZone.getZoneCopy().getSOA().getSerial() != axfrZone.getSOA().getSerial()){
this.secondaryZone.setZoneCopy(axfrZone);
this.secondaryZone.setDownloaded(new Timestamp(System.currentTimeMillis()));
this.zoneProvider.zoneUpdated(this.secondaryZone);
log.info("Zone " + this.secondaryZone.getZoneName() + " successfully updated from server " + this.secondaryZone.getRemoteServerAddress());
}else{
log.info("Zone " + this.secondaryZone.getZoneName() + " is already up to date with serial " + axfrZone.getSOA().getSerial());
this.zoneProvider.zoneChecked(secondaryZone);
}
} catch (IOException e) {
log.warn("Unable to transfer zone " + this.secondaryZone.getZoneName() + " from server " + this.secondaryZone.getRemoteServerAddress() + ", " + e);
checkExpired();
} catch (ZoneTransferException e) {
log.warn("Unable to transfer zone " + this.secondaryZone.getZoneName() + " from server " + this.secondaryZone.getRemoteServerAddress() + ", " + e);
checkExpired();
}catch (RuntimeException e) {
log.warn("Unable to transfer zone " + this.secondaryZone.getZoneName() + " from server " + this.secondaryZone.getRemoteServerAddress() + ", " + e);
checkExpired();
}finally{
this.secondaryZone.setDownloaded(new Timestamp(System.currentTimeMillis()));
}
}
private void checkExpired() {
if(this.secondaryZone.getZoneCopy() != null && (System.currentTimeMillis() - this.secondaryZone.getDownloaded().getTime()) > (this.secondaryZone.getZoneCopy().getSOA().getExpire() * 1000)){
log.warn("AXFR copy of secondary zone " + secondaryZone.getZoneName() + " has expired, deleting zone data...");
this.secondaryZone.setZoneCopy(null);
this.secondaryZone.setDownloaded(null);
this.zoneProvider.zoneUpdated(this.secondaryZone);
}
}
}