Finish implementing fragment verification.
This commit is contained in:
parent
96c9864092
commit
fcd985b570
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -25,6 +25,7 @@ public final class FragmentReceiver {
|
|||||||
private PacketLoader packetLoader;
|
private PacketLoader packetLoader;
|
||||||
private IPacketFactory packetFactory;
|
private IPacketFactory packetFactory;
|
||||||
private boolean verifyResponses = false;
|
private boolean verifyResponses = false;
|
||||||
|
private boolean makeSureSendDataVerified = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new FragmentReceiver with the specified {@link PacketLoader} and {@link IPacketFactory}.
|
* Constructs a new FragmentReceiver with the specified {@link PacketLoader} and {@link IPacketFactory}.
|
||||||
@ -262,12 +263,36 @@ public final class FragmentReceiver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether responses should be verified.
|
* Sets whether responses should be verified.
|
||||||
|
* If set to false, {@link #setSentDataWillBeAllVerified(boolean)} will be set to false too.
|
||||||
*
|
*
|
||||||
* @param state If responses should be verified.
|
* @param state If responses should be verified.
|
||||||
*/
|
*/
|
||||||
public void setResponseVerification(boolean state) {
|
public void setResponseVerification(boolean state) {
|
||||||
synchronized (slock) {
|
synchronized (slock) {
|
||||||
verifyResponses = state;
|
verifyResponses = state;
|
||||||
|
if (makeSureSendDataVerified && !state) makeSureSendDataVerified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether all sent fragments are verified to be equal.
|
||||||
|
*
|
||||||
|
* @return If all sent fragments will be verified to be equal.
|
||||||
|
*/
|
||||||
|
public boolean shouldSentDataBeAllVerified() {
|
||||||
|
return makeSureSendDataVerified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether all sent fragments are verified to be equal.
|
||||||
|
* Requires {@link #setResponseVerification(boolean)} set to true.
|
||||||
|
*
|
||||||
|
* @param state If all sent fragments will be verified to be equal.
|
||||||
|
*/
|
||||||
|
public void setSentDataWillBeAllVerified(boolean state) {
|
||||||
|
synchronized (slock) {
|
||||||
|
if (!verifyResponses) return;
|
||||||
|
makeSureSendDataVerified = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +301,7 @@ public final class FragmentReceiver {
|
|||||||
* the {@link FragmentSendCompletePacket} or {@link FragmentRetrySendPacket} packets are sent.
|
* the {@link FragmentSendCompletePacket} or {@link FragmentRetrySendPacket} packets are sent.
|
||||||
* A {@link FragmentSendCompletePacket} is sent if completely received and a
|
* A {@link FragmentSendCompletePacket} is sent if completely received and a
|
||||||
* {@link FragmentRetrySendPacket} is sent if not completely received.
|
* {@link FragmentRetrySendPacket} is sent if not completely received.
|
||||||
|
* This excludes empty packets due to {@link #shouldSentDataBeAllVerified()}.
|
||||||
*
|
*
|
||||||
* @return The number of send packet calls before a completion or restart is forced.
|
* @return The number of send packet calls before a completion or restart is forced.
|
||||||
*/
|
*/
|
||||||
@ -288,6 +314,7 @@ public final class FragmentReceiver {
|
|||||||
* the {@link FragmentSendCompletePacket} or {@link FragmentRetrySendPacket} packets are sent.
|
* the {@link FragmentSendCompletePacket} or {@link FragmentRetrySendPacket} packets are sent.
|
||||||
* A {@link FragmentSendCompletePacket} is sent if completely received and a
|
* A {@link FragmentSendCompletePacket} is sent if completely received and a
|
||||||
* {@link FragmentRetrySendPacket} is sent if not completely received.
|
* {@link FragmentRetrySendPacket} is sent if not completely received.
|
||||||
|
* This excludes empty packets due to {@link #shouldSentDataBeAllVerified()}.
|
||||||
*
|
*
|
||||||
* @param numberOfEmptySends The number of empty sends to allow.
|
* @param numberOfEmptySends The number of empty sends to allow.
|
||||||
* @throws IllegalArgumentException numberOfEmptySends is less than 1.
|
* @throws IllegalArgumentException numberOfEmptySends is less than 1.
|
||||||
@ -297,6 +324,28 @@ public final class FragmentReceiver {
|
|||||||
numberOfEmptySendsTillForced = numberOfEmptySends;
|
numberOfEmptySendsTillForced = numberOfEmptySends;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops data verification for the specified Packet ID when {@link #shouldSentDataBeAllVerified()} is true.
|
||||||
|
*
|
||||||
|
* @param id The PacketID to act on.
|
||||||
|
*/
|
||||||
|
public void stopDataVerificationAndCompleteReceive(int id) {
|
||||||
|
synchronized (slock) {
|
||||||
|
if (!makeSureSendDataVerified) return;
|
||||||
|
FragmentInput input = registry.get(id);
|
||||||
|
if (input != null) input.verifyReceived = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops data verification for all packets being received when {@link #shouldSentDataBeAllVerified()} is true.
|
||||||
|
*/
|
||||||
|
public void stopAllDataVerificationAndCompleteReceive() {
|
||||||
|
synchronized (slock) {
|
||||||
|
for (int c : registry.keySet()) registry.get(c).verifyReceived = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides the ability to store allocated responses to be sent back.
|
* This class provides the ability to store allocated responses to be sent back.
|
||||||
*
|
*
|
||||||
@ -334,6 +383,7 @@ public final class FragmentReceiver {
|
|||||||
private int sendsTillCompleteForced;
|
private int sendsTillCompleteForced;
|
||||||
private boolean fsendActive = false;
|
private boolean fsendActive = false;
|
||||||
private final FragmentMessagePacket[] messagePackets;
|
private final FragmentMessagePacket[] messagePackets;
|
||||||
|
public boolean verifyReceived = false;
|
||||||
|
|
||||||
public FragmentInput(int id, int count, UUID aid) {
|
public FragmentInput(int id, int count, UUID aid) {
|
||||||
packetID = id;
|
packetID = id;
|
||||||
@ -355,12 +405,16 @@ public final class FragmentReceiver {
|
|||||||
if (fsendActive) {
|
if (fsendActive) {
|
||||||
if (sendsTillCompleteForced > 0) sendsTillCompleteForced--;
|
if (sendsTillCompleteForced > 0) sendsTillCompleteForced--;
|
||||||
} else fsendActive = true;
|
} else fsendActive = true;
|
||||||
if (sendsTillCompleteForced == 0) return (idsToReceive.size() < 1) ? new FragmentSendCompletePacket(packetID, true) : new FragmentRetrySendPacket(packetID, false);
|
if (sendsTillCompleteForced == 0 && !(makeSureSendDataVerified && !verifyReceived)) return (idsToReceive.size() < 1) ? new FragmentSendCompletePacket(packetID, true) : new FragmentRetrySendPacket(packetID, false);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receivePacket(IPacket packetIn) {
|
public void receivePacket(IPacket packetIn) {
|
||||||
if ((packetIn instanceof FragmentSendCompletePacket && !((FragmentSendCompletePacket) packetIn).isAcknowledgement())) sendsTillCompleteForced = 0;
|
if ((packetIn instanceof FragmentSendCompletePacket && !((FragmentSendCompletePacket) packetIn).isAcknowledgement())) sendsTillCompleteForced = 0;
|
||||||
|
if (packetIn instanceof FragmentSendVerifyCompletePacket) {
|
||||||
|
sendsTillCompleteForced = 0;
|
||||||
|
verifyReceived = true;
|
||||||
|
}
|
||||||
if ((packetIn instanceof FragmentRetrySendPacket && ((FragmentRetrySendPacket) packetIn).isAcknowledgement())) sendsTillCompleteForced = numberOfEmptySendsTillForced + 1;
|
if ((packetIn instanceof FragmentRetrySendPacket && ((FragmentRetrySendPacket) packetIn).isAcknowledgement())) sendsTillCompleteForced = numberOfEmptySendsTillForced + 1;
|
||||||
if (packetIn instanceof FragmentMessagePacket) {
|
if (packetIn instanceof FragmentMessagePacket) {
|
||||||
FragmentMessagePacket messagePacket = (FragmentMessagePacket) packetIn;
|
FragmentMessagePacket messagePacket = (FragmentMessagePacket) packetIn;
|
||||||
@ -371,7 +425,7 @@ public final class FragmentReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IPacket consume() throws PacketException {
|
public IPacket consume() throws PacketException {
|
||||||
if (consumeDone || idsToReceive.size() > 0 || messagePackets.length < 1) return null;
|
if (consumeDone || idsToReceive.size() > 0 || messagePackets.length < 1 || (makeSureSendDataVerified && !verifyReceived)) return null;
|
||||||
ByteArrayOutputStream packetStream = new ByteArrayOutputStream(messagePackets[0].getFragmentMessage().length);
|
ByteArrayOutputStream packetStream = new ByteArrayOutputStream(messagePackets[0].getFragmentMessage().length);
|
||||||
for (FragmentMessagePacket messagePacket : messagePackets) {
|
for (FragmentMessagePacket messagePacket : messagePackets) {
|
||||||
try {
|
try {
|
||||||
|
@ -19,6 +19,7 @@ public final class FragmentSender {
|
|||||||
private int splitSize = 496;
|
private int splitSize = 496;
|
||||||
private PacketLoader packetLoader;
|
private PacketLoader packetLoader;
|
||||||
private boolean verifyResponses = false;
|
private boolean verifyResponses = false;
|
||||||
|
private boolean makeSureSendDataVerified = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new FragmentSender with the specified {@link PacketLoader}.
|
* Constructs a new FragmentSender with the specified {@link PacketLoader}.
|
||||||
@ -241,12 +242,58 @@ public final class FragmentSender {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether responses should be verified.
|
* Sets whether responses should be verified.
|
||||||
|
* If set to false, {@link #setSentDataWillBeAllVerified(boolean)} will be set to false too.
|
||||||
*
|
*
|
||||||
* @param state If responses should be verified.
|
* @param state If responses should be verified.
|
||||||
*/
|
*/
|
||||||
public void setResponseVerification(boolean state) {
|
public void setResponseVerification(boolean state) {
|
||||||
synchronized (slock) {
|
synchronized (slock) {
|
||||||
verifyResponses = state;
|
verifyResponses = state;
|
||||||
|
if (makeSureSendDataVerified && !state) makeSureSendDataVerified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether all sent fragments are verified to be equal.
|
||||||
|
*
|
||||||
|
* @return If all sent fragments will be verified to be equal.
|
||||||
|
*/
|
||||||
|
public boolean shouldSentDataBeAllVerified() {
|
||||||
|
return makeSureSendDataVerified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether all sent fragments are verified to be equal.
|
||||||
|
* Requires {@link #setResponseVerification(boolean)} set to true.
|
||||||
|
*
|
||||||
|
* @param state If all sent fragments will be verified to be equal.
|
||||||
|
*/
|
||||||
|
public void setSentDataWillBeAllVerified(boolean state) {
|
||||||
|
synchronized (slock) {
|
||||||
|
if (!verifyResponses) return;
|
||||||
|
makeSureSendDataVerified = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops data verification for the specified Packet ID when {@link #shouldSentDataBeAllVerified()} is true.
|
||||||
|
*
|
||||||
|
* @param id The PacketID to act on.
|
||||||
|
*/
|
||||||
|
public void stopDataVerificationAndCompleteSend(int id) {
|
||||||
|
synchronized (slock) {
|
||||||
|
if (!makeSureSendDataVerified) return;
|
||||||
|
FragmentOutput output = registry.get(id);
|
||||||
|
if (output != null) output.forceDataVerifiedSendStop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops data verification for all packets being sent when {@link #shouldSentDataBeAllVerified()} is true.
|
||||||
|
*/
|
||||||
|
public void stopAllDataVerificationAndCompleteSend() {
|
||||||
|
synchronized (slock) {
|
||||||
|
for (int c : registry.keySet()) registry.get(c).forceDataVerifiedSendStop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,6 +310,7 @@ public final class FragmentSender {
|
|||||||
private final ArrayList<Integer> msgToResendCurrent = new ArrayList<>();
|
private final ArrayList<Integer> msgToResendCurrent = new ArrayList<>();
|
||||||
private int msgPacketIndex = 0;
|
private int msgPacketIndex = 0;
|
||||||
public boolean isResending = false;
|
public boolean isResending = false;
|
||||||
|
public boolean forceDataVerifiedSendStop = false;
|
||||||
|
|
||||||
public FragmentOutput(int id, byte[] toSplit) {
|
public FragmentOutput(int id, byte[] toSplit) {
|
||||||
packetID = id;
|
packetID = id;
|
||||||
@ -282,12 +330,14 @@ public final class FragmentSender {
|
|||||||
msgPacketIndex = 0;
|
msgPacketIndex = 0;
|
||||||
return new FragmentRetrySendPacket(packetID, true);
|
return new FragmentRetrySendPacket(packetID, true);
|
||||||
}
|
}
|
||||||
|
if (!isResending && makeSureSendDataVerified && msgPacketIndex >= messagePackets.length && !forceDataVerifiedSendStop) setResendingOn(true);
|
||||||
if (isResending) {
|
if (isResending) {
|
||||||
|
if (makeSureSendDataVerified && msgPacketIndex >= msgToResendCurrent.size() && !forceDataVerifiedSendStop) setResendingOn(true);
|
||||||
if (msgPacketIndex < msgToResendCurrent.size()) return messagePackets[msgToResendCurrent.get(msgPacketIndex++)];
|
if (msgPacketIndex < msgToResendCurrent.size()) return messagePackets[msgToResendCurrent.get(msgPacketIndex++)];
|
||||||
} else {
|
} else {
|
||||||
if (msgPacketIndex < messagePackets.length) return messagePackets[msgPacketIndex++];
|
if (msgPacketIndex < messagePackets.length) return messagePackets[msgPacketIndex++];
|
||||||
}
|
}
|
||||||
return new FragmentSendCompletePacket(packetID, false);
|
return (makeSureSendDataVerified && (msgToResend.size() < 1 || forceDataVerifiedSendStop)) ? new FragmentSendVerifyCompletePacket(packetID) : new FragmentSendCompletePacket(packetID, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldBeRemovedReceivePacket(IPacket packetIn) {
|
public boolean shouldBeRemovedReceivePacket(IPacket packetIn) {
|
||||||
@ -300,14 +350,16 @@ public final class FragmentSender {
|
|||||||
if (!verifyResponses || compareData(responsePacket.getFragmentMessage(), messagePackets[responsePacket.getFragmentID()].getFragmentMessage()))
|
if (!verifyResponses || compareData(responsePacket.getFragmentMessage(), messagePackets[responsePacket.getFragmentID()].getFragmentMessage()))
|
||||||
msgToResend.remove(responsePacket.getFragmentID());
|
msgToResend.remove(responsePacket.getFragmentID());
|
||||||
}
|
}
|
||||||
if (packetIn instanceof FragmentRetrySendPacket && !((FragmentRetrySendPacket) packetIn).isAcknowledgement()) {
|
if (packetIn instanceof FragmentRetrySendPacket && !((FragmentRetrySendPacket) packetIn).isAcknowledgement()) setResendingOn(false);
|
||||||
msgPacketIndex = -1;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setResendingOn(boolean zeroIndex) {
|
||||||
|
msgPacketIndex = (zeroIndex) ? 0 : -1;
|
||||||
isResending = true;
|
isResending = true;
|
||||||
msgToResendCurrent.clear();
|
msgToResendCurrent.clear();
|
||||||
msgToResendCurrent.addAll(msgToResend);
|
msgToResendCurrent.addAll(msgToResend);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean compareData(byte[] data1, byte[] data2) {
|
private boolean compareData(byte[] data1, byte[] data2) {
|
||||||
if ((data1 == null && data2 != null) || (data1 != null && data2 == null)) return false;
|
if ((data1 == null && data2 != null) || (data1 != null && data2 == null)) return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user