package com.netifera.platform.net.packets.tcpip;
import java.nio.ByteBuffer;
import com.netifera.platform.net.packets.AbstractPacket;
import com.netifera.platform.net.packets.IPacketHeader;
import com.netifera.platform.net.packets.PacketException;
import com.netifera.platform.net.packets.PacketPayload;
import com.netifera.platform.util.NetworkConstants;
public class UDP extends AbstractPacket implements IPseudoHeaderClient, IPv4Encapsulable, IPv6Encapsulable {
private int sourcePort;
private int destinationPort;
private int length;
private int checksum;
/**
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source | Destination |
| Port | Port |
+--------+--------+--------+--------+
| | |
| Length | Checksum |
+--------+--------+--------+--------+
|
| data octets ...
+---------------- ...
User Datagram Header Format
*/
@Override
protected void packHeader() {
pack16(sourcePort);
pack16(destinationPort);
pack16(length);
pack16(checksum);
}
@Override
protected void unpackHeader() {
sourcePort = unpack16();
destinationPort = unpack16();
length = unpack16();
checksum = unpack16();
}
@Override
protected boolean hasPayload() {
return true;
}
private boolean lengthSet;
private boolean checksumSet;
private ByteBuffer pseudoHeader;
public UDP() {}
public UDP(IPacketHeader payload) {
super(payload);
}
public int protocolOverIPv4() {
return NetworkConstants.IPPROTO_UDP;
}
public int protocolOverIPv6() {
return NetworkConstants.IPPROTO_UDP;
}
@Override
public int minimumHeaderLength() {
return 8;
}
public int getSourcePort() {
return sourcePort;
}
public void setSourcePort(int value) {
verifyMaximum(value, 0xFFFF);
sourcePort = value;
}
public int getDestinationPort() {
return sourcePort;
}
public void setDestinationPort(int value) {
verifyMaximum(value, 0xFFFF);
destinationPort = value;
}
public void setLength(int value) {
verifyMaximum(value, 0xFFFF);
length = value;
lengthSet = true;
}
public void setChecksum(int value) {
verifyMaximum(value, 0xFFFF);
checksum = value;
checksumSet = true;
}
public void setPseudoHeader(ByteBuffer pseudoHeader) {
this.pseudoHeader = pseudoHeader;
}
@Override
protected void populateGeneratedFields() {
if(!lengthSet) {
length = getLength();
}
if(!checksumSet) {
checksum = 0;
}
}
@Override
protected void calculateChecksum() {
if(checksumSet) return;
if(pseudoHeader == null) {
throw new PacketException("Cannot calculate UDP checksum because parent has not sent pseudoheader");
}
int sum = generateChecksumWithPseudo(length, pseudoHeader);
pack16(sum, 6);
}
@Override
public String toString() {
return "UDP " + sourcePort + " -> " + destinationPort;
}
@Override
public PacketPayload payload() {
return getNextHeader() == null ? PacketPayload.EMPTY_PAYLOAD : (PacketPayload) getNextHeader();
}
}