package org.freertr.pack; import org.freertr.addr.addrIPv4; import org.freertr.util.bits; /** * network time protocol (rfc5905) packet * * @author matecsaba */ public class packNtp { /** * create instance */ public packNtp() { } /** * port number to use */ public final static int port = 123; /** * size of packet */ public final static int size = 48; /** * time difference */ public final static long timDif = 2208988800000L; /** * leap indicator */ public int leap; /** * version number */ public int ver; /** * mode */ public int mode; /** * stratum */ public int stratum; /** * poll */ public int poll; /** * precision */ public int precise; /** * root delay */ public int rotDel; /** * root dispersion */ public int rotDis; /** * reference id */ public addrIPv4 refId = new addrIPv4(); /** * reference time */ public long refTime; /** * origination time */ public long origTime; /** * receive time */ public long recvTime; /** * transmit time */ public long sendTime; /** * symmetric active */ public final static int modSymAct = 1; /** * symmetric passive */ public final static int modSymPsv = 2; /** * client */ public final static int modClnt = 3; /** * server */ public final static int modServ = 4; /** * broadcast */ public final static int modBcst = 5; /** * convert mode to string * * @param i mode * @return string */ public static String mode2str(int i) { switch (i) { case modSymAct: return "symmetricActive"; case modSymPsv: return "symmetricPassive"; case modClnt: return "client"; case modServ: return "server"; case modBcst: return "broadcast"; default: return "unknown=" + i; } } private final static long base0 = 2085978496000L; private final static long base1 = -2208988800000L; /** * decode ntp time * * @param tim time * @return decoded */ public static long decode(long tim) { long sec = (tim >>> 32) & 0xffffffffL; long frc = tim & 0xffffffffL; frc = (1000L * frc) / 0x100000000L; if ((sec & 0x80000000L) == 0) { return base0 + (sec * 1000) + frc; } else { return base1 + (sec * 1000) + frc; } } /** * encode ntp time * * @param tim time * @return encoded */ public static long encode(long tim) { boolean msb = tim < base0; long base; if (msb) { base = tim - base1; } else { base = tim - base0; } long sec = base / 1000; long frc = ((base % 1000) * 0x100000000L) / 1000; if (msb) { sec |= 0x80000000L; } return sec << 32 | frc; } public String toString() { return "ver=" + ver + " mode=" + mode2str(mode) + " str=" + stratum + " ref=" + refId + " ref=" + bits.time2str(null, decode(refTime), 3) + " orig=" + bits.time2str(null, decode(origTime), 3) + " rx=" + bits.time2str(null, decode(recvTime), 3) + " tx=" + bits.time2str(null, decode(sendTime), 3); } private long getTime(packHolder pck) { long tim = pck.msbGetQ(0); pck.getSkip(8); return tim; } private void putTime(packHolder pck, long tim) { pck.msbPutQ(0, tim); pck.putSkip(8); } /** * parse one packet * * @param pck packet to read * @return false on success, true on error */ public boolean parsePacket(packHolder pck) { if (pck.dataSize() < size) { return true; } mode = pck.getByte(0); leap = mode >>> 6; ver = (mode >>> 3) & 7; mode &= 7; stratum = pck.getByte(1); poll = pck.getByte(2); precise = pck.getByte(3); rotDel = pck.msbGetD(4); rotDis = pck.msbGetD(8); pck.getAddr(refId, 12); pck.getSkip(16); refTime = getTime(pck); origTime = getTime(pck); recvTime = getTime(pck); sendTime = getTime(pck); return false; } /** * create one packet * * @param pck packet to write */ public void createPacket(packHolder pck) { pck.putByte(0, (leap << 6) | (ver << 3) | mode); pck.putByte(1, stratum); pck.putByte(2, poll); pck.putByte(3, precise); pck.msbPutD(4, rotDel); pck.msbPutD(8, rotDis); pck.putAddr(12, refId); pck.putSkip(16); putTime(pck, refTime); putTime(pck, origTime); putTime(pck, recvTime); putTime(pck, sendTime); pck.merge2beg(); } }