package com.netifera.platform.net.internal.sniffing.stream;
import com.netifera.platform.net.packets.tcpip.IP;
import com.netifera.platform.net.packets.tcpip.TCP;
import com.netifera.platform.net.sniffing.stream.ISessionKey;
import com.netifera.platform.util.addresses.inet.InternetAddress;
public class TCPSessionKey implements ISessionKey {
/* Immutable! */
private final InternetAddress clientAddress;
private final InternetAddress serverAddress;
private final int clientPort;
private final int serverPort;
private final boolean isSYN;
public TCPSessionKey(IP ip, TCP tcp) {
final InternetAddress sourceAddress = ip.getSourceAddress();
final InternetAddress destinationAddress = ip.getDestinationAddress();
final int sourcePort = tcp.getSourcePort();
final int destinationPort = tcp.getDestinationPort();
/*
* The following logic is used to decide which side of a newly
* discovered connection is the client and which side is the
* server. The first rule that matches is used:
*
* 1) SYN + ACK flags both set --> Server to Client
* 2) SYN flag set (but not ACK) --> Client to Server
* 3) Source Port < Destination Port --> Server to Client
* 4) Otherwise: --> Client to Server
*/
if((tcp.getSYN() && tcp.getACK()) ||
(!tcp.getSYN() && (destinationPort > sourcePort))) {
clientAddress = destinationAddress;
serverAddress = sourceAddress;
clientPort = destinationPort;
serverPort = sourcePort;
} else {
clientAddress = sourceAddress;
serverAddress = destinationAddress;
clientPort = sourcePort;
serverPort = destinationPort;
}
isSYN = tcp.getSYN();
}
public InternetAddress getServerAddress() {
return serverAddress;
}
public InternetAddress getClientAddress() {
return clientAddress;
}
public int getServerPort() {
return serverPort;
}
public int getClientPort() {
return clientPort;
}
public boolean isSYN() {
return isSYN;
}
@Override
public boolean equals(Object o) {
if(!(o instanceof TCPSessionKey)) {
return false;
}
TCPSessionKey key = (TCPSessionKey) o;
if( (this.clientPort == key.clientPort) &&
(this.serverPort == key.serverPort) &&
(this.clientAddress.equals(key.clientAddress)) &&
(this.serverAddress.equals(key.serverAddress))
) {
return true;
}
if( (this.clientPort == key.serverPort) &&
(this.serverPort == key.clientPort) &&
(this.clientAddress.equals(key.serverAddress)) &&
(this.serverAddress.equals(key.clientAddress))
) {
return true;
}
return false;
}
@Override
public int hashCode() {
/* Include only the address of the lowest port. If the ports are the same, don't include an address */
if(clientPort < serverPort) {
return ((clientPort << 16) | serverPort) ^ clientAddress.hashCode();
} else if (clientPort > serverPort) {
return ((serverPort << 16) | clientPort) ^ serverAddress.hashCode();
} else {
return ((serverPort << 16) | clientPort);
}
}
@Override
public String toString() {
return clientAddress.toString() + ":" + clientPort +
" -> " + serverAddress + ":" + serverPort;
}
public boolean isClientToServer(IP packet) {
return clientAddress.equals(packet.getSourceAddress()) &&
clientPort == ((TCP)packet.getNextHeader()).getSourcePort();
}
}