Add fragmentation support to NetMarshalClient, fix up NetMarshalClient.
This commit is contained in:
parent
b49dfa0938
commit
41ed32f3af
@ -0,0 +1,74 @@
|
||||
package com.captainalm.lib.calmnet.marshal;
|
||||
|
||||
import com.captainalm.lib.calmnet.packet.fragment.FragmentReceiver;
|
||||
import com.captainalm.lib.calmnet.packet.fragment.FragmentSender;
|
||||
|
||||
/**
|
||||
* This class provides fragmentation options for using {@link FragmentSender}s and
|
||||
* {@link FragmentReceiver}s in this package.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
public final class FragmentationOptions {
|
||||
/**
|
||||
* The maximum age of fragments for a specified packet in seconds before those fragments are purged.
|
||||
*/
|
||||
public int maximumFragmentAge = 30;
|
||||
/**
|
||||
* See:
|
||||
* {@link FragmentSender#setSplitSize(int)}
|
||||
*/
|
||||
public int fragmentationSplitSize = 496;
|
||||
/**
|
||||
* See:
|
||||
* {@link FragmentReceiver#setNumberOfEmptySendsTillForcedCompleteOrResend(int)}
|
||||
*/
|
||||
public int emptySendsTillForced = 2;
|
||||
/**
|
||||
* See:
|
||||
* {@link FragmentSender#setResponseVerification(boolean)} ,
|
||||
* {@link FragmentReceiver#setResponseVerification(boolean)}
|
||||
*/
|
||||
public boolean verifyFragments = false;
|
||||
/**
|
||||
* See:
|
||||
* {@link FragmentSender#setSentDataWillBeAllVerified(boolean)} ,
|
||||
* {@link FragmentReceiver#setSentDataWillBeAllVerified(boolean)}
|
||||
*/
|
||||
public boolean equalityVerifyFragments = false;
|
||||
|
||||
/**
|
||||
* Validates the parameters within this structure.
|
||||
*
|
||||
* @throws IllegalArgumentException maximumFragmentAge is less than 2, fragmentationSplitSize is less than 1 or emptySendsTillForced is less than 1.
|
||||
*/
|
||||
public void validate() {
|
||||
if (maximumFragmentAge < 2) throw new IllegalArgumentException("maximumFragmentAge is less than 2");
|
||||
if (fragmentationSplitSize < 1) throw new IllegalArgumentException("fragmentationSplitSize is less than 1");
|
||||
if (emptySendsTillForced < 1) throw new IllegalArgumentException("emptySendsTillForced is less than 1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets-up the provided {@link FragmentSender} with parameters.
|
||||
*
|
||||
* @param sender The sender to set up.
|
||||
* @throws IllegalArgumentException A parameter is incorrect.
|
||||
*/
|
||||
public void setupSender(FragmentSender sender) {
|
||||
sender.setSplitSize(fragmentationSplitSize);
|
||||
sender.setResponseVerification(verifyFragments);
|
||||
sender.setSentDataWillBeAllVerified(equalityVerifyFragments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets-up the provided {@link FragmentReceiver} with parameters.
|
||||
*
|
||||
* @param receiver The receiver to set up.
|
||||
* @throws IllegalArgumentException A parameter is incorrect.
|
||||
*/
|
||||
public void setupReceiver(FragmentReceiver receiver) {
|
||||
receiver.setNumberOfEmptySendsTillForcedCompleteOrResend(emptySendsTillForced);
|
||||
receiver.setResponseVerification(verifyFragments);
|
||||
receiver.setSentDataWillBeAllVerified(equalityVerifyFragments);
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import com.captainalm.lib.calmnet.packet.IPacket;
|
||||
import com.captainalm.lib.calmnet.packet.PacketException;
|
||||
import com.captainalm.lib.calmnet.packet.PacketLoader;
|
||||
import com.captainalm.lib.calmnet.packet.factory.IPacketFactory;
|
||||
import com.captainalm.lib.calmnet.packet.fragment.*;
|
||||
import com.captainalm.lib.calmnet.ssl.SSLUtilities;
|
||||
import com.captainalm.lib.calmnet.ssl.SSLUtilityException;
|
||||
import com.captainalm.lib.calmnet.stream.NetworkInputStream;
|
||||
@ -16,9 +17,12 @@ import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.Socket;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* This class provides a managed way of networking on the client side.
|
||||
@ -27,7 +31,7 @@ import java.util.function.BiConsumer;
|
||||
* @author Captain ALM
|
||||
*/
|
||||
public class NetMarshalClient implements Closeable {
|
||||
protected boolean running = true;
|
||||
protected boolean running;
|
||||
|
||||
protected Socket socket;
|
||||
protected DatagramSocket dsocket;
|
||||
@ -37,6 +41,7 @@ public class NetMarshalClient implements Closeable {
|
||||
protected OutputStream rootOutputStream;
|
||||
protected BiConsumer<IPacket, NetMarshalClient> receiveBiConsumer;
|
||||
protected BiConsumer<Exception, NetMarshalClient> receiveExceptionBiConsumer;
|
||||
protected Consumer<NetMarshalClient> closedConsumer;
|
||||
protected final Object slockPacketRead = new Object();
|
||||
protected boolean disablePacketReading;
|
||||
|
||||
@ -50,7 +55,16 @@ public class NetMarshalClient implements Closeable {
|
||||
protected final Queue<IPacket> receivedPackets = new LinkedList<>();
|
||||
protected final Object slockReceive = new Object();
|
||||
|
||||
private NetMarshalClient(InetAddress remoteAddress, int remotePort, IPacketFactory factory, PacketLoader loader, boolean isMulticast, boolean isSocketNull) {
|
||||
protected final FragmentationOptions fragmentationOptions;
|
||||
protected final FragmentReceiver fragmentReceiver;
|
||||
protected final HashMap<Integer, LocalDateTime> fragmentRMM;
|
||||
protected final FragmentSender fragmentSender;
|
||||
protected final HashMap<Integer, LocalDateTime> fragmentSMM;
|
||||
protected final Thread fragmentMonitorThread;
|
||||
protected final Thread fragmentFinishReceiveMonitorThread;
|
||||
protected final Thread fragmentFinishSendMonitorThread;
|
||||
|
||||
private NetMarshalClient(InetAddress remoteAddress, int remotePort, IPacketFactory factory, PacketLoader loader, boolean isMulticast, boolean isSocketNull, FragmentationOptions fragmentationOptions) {
|
||||
if (isSocketNull) throw new NullPointerException("socketIn is null");
|
||||
if (remoteAddress == null) throw new NullPointerException(((isMulticast) ? "multicastGroupAddress" : "remoteAddress") + " is null");
|
||||
this.remoteAddress = remoteAddress;
|
||||
@ -61,27 +75,102 @@ public class NetMarshalClient implements Closeable {
|
||||
this.factory = factory;
|
||||
if (loader == null) throw new NullPointerException("loader is null");
|
||||
this.loader = loader;
|
||||
this.fragmentationOptions = fragmentationOptions;
|
||||
if (fragmentationOptions == null) {
|
||||
fragmentReceiver = null;
|
||||
fragmentRMM = null;
|
||||
fragmentSender = null;
|
||||
fragmentSMM = null;
|
||||
fragmentMonitorThread = null;
|
||||
fragmentFinishReceiveMonitorThread = null;
|
||||
fragmentFinishSendMonitorThread = null;
|
||||
receiveThread = new Thread(() -> {
|
||||
while (running) receiveThreadExecuted();
|
||||
}, "thread_receive_" + remoteAddress.getHostAddress() + ":" + remotePort);
|
||||
} else {
|
||||
fragmentationOptions.validate();
|
||||
fragmentReceiver = new FragmentReceiver(loader, factory);
|
||||
fragmentationOptions.setupReceiver(fragmentReceiver);
|
||||
fragmentRMM = new HashMap<>();
|
||||
fragmentSender = new FragmentSender(loader);
|
||||
fragmentationOptions.setupSender(fragmentSender);
|
||||
fragmentSMM = new HashMap<>();
|
||||
fragmentMonitorThread = new Thread(() -> {
|
||||
int ageCheckTime = this.fragmentationOptions.maximumFragmentAge - 1;
|
||||
while (running) {
|
||||
int id = -1;
|
||||
synchronized (this.fragmentationOptions) {
|
||||
for (int c : fragmentRMM.keySet()) {
|
||||
if (!fragmentRMM.get(c).plusSeconds(ageCheckTime).isAfter(LocalDateTime.now())) {
|
||||
fragmentRMM.remove(id);
|
||||
fragmentReceiver.deletePacketFromRegistry(c);
|
||||
}
|
||||
}
|
||||
for (int c : fragmentSMM.keySet()) {
|
||||
if (!fragmentSMM.get(c).plusSeconds(ageCheckTime).isAfter(LocalDateTime.now())) {
|
||||
fragmentSMM.remove(id);
|
||||
fragmentSender.deletePacketFromRegistry(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(this.fragmentationOptions.maximumFragmentAge);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
fragmentReceiver.clearRegistry();
|
||||
fragmentSender.clearRegistry();
|
||||
}, "thread_frag_monitor_" + remoteAddress.getHostAddress() + ":" + remotePort);
|
||||
fragmentFinishReceiveMonitorThread = new Thread(() -> {
|
||||
while (running) {
|
||||
int id = -1;
|
||||
try {
|
||||
while ((id = fragmentReceiver.getLastIDFinished()) != -1) synchronized (this.fragmentationOptions) {
|
||||
fragmentRMM.remove(id);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
fragmentReceiver.clearLastIDFinished();
|
||||
}, "thread_frag_fin_recv_monitor_" + remoteAddress.getHostAddress() + ":" + remotePort);
|
||||
fragmentFinishSendMonitorThread = new Thread(() -> {
|
||||
while (running) {
|
||||
int id = -1;
|
||||
try {
|
||||
while ((id = fragmentSender.getLastIDFinished()) != -1) synchronized (this.fragmentationOptions) {
|
||||
fragmentSMM.remove(id);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
fragmentSender.clearLastIDFinished();
|
||||
}, "thread_frag_fin_recv_monitor_" + remoteAddress.getHostAddress() + ":" + remotePort);
|
||||
receiveThread = new Thread(() -> {
|
||||
while (running) receiveThreadExecutedWithFragmentation();
|
||||
fragmentReceiver.clearWaitingPackets();
|
||||
fragmentSender.clearWaitingPackets();
|
||||
}, "thread_receive_" + remoteAddress.getHostAddress() + ":" + remotePort);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NetMarshalClient with the specified {@link Socket}, {@link IPacketFactory} and {@link PacketLoader}.
|
||||
* Constructs a new NetMarshalClient with the specified {@link Socket}, {@link IPacketFactory}, {@link PacketLoader} and {@link FragmentationOptions}.
|
||||
*
|
||||
* @param socketIn The socket to use.
|
||||
* @param factory The packet factory to use.
|
||||
* @param loader The packet loader to use.
|
||||
* @param fragmentationOptions The fragmentation options, null to disable fragmentation.
|
||||
* @throws NullPointerException socketIn, factory or loader is null.
|
||||
* @throws IllegalArgumentException Fragmentation options failed validation.
|
||||
*/
|
||||
public NetMarshalClient(Socket socketIn, IPacketFactory factory, PacketLoader loader) {
|
||||
this((socketIn == null) ? null : socketIn.getInetAddress(), (socketIn == null) ? -1 : socketIn.getPort(), factory, loader, false, socketIn == null);
|
||||
public NetMarshalClient(Socket socketIn, IPacketFactory factory, PacketLoader loader, FragmentationOptions fragmentationOptions) {
|
||||
this((socketIn == null) ? null : socketIn.getInetAddress(), (socketIn == null) ? -1 : socketIn.getPort(), factory, loader, false, socketIn == null, fragmentationOptions);
|
||||
socket = socketIn;
|
||||
setStreams(new NetworkInputStream(socketIn), new NetworkOutputStream(socketIn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NetMarshalClient with the specified {@link MulticastSocket}, multicast group {@link InetAddress}, multicast port, {@link IPacketFactory} and {@link PacketLoader}.
|
||||
* Constructs a new NetMarshalClient with the specified {@link MulticastSocket}, multicast group {@link InetAddress}, multicast port, {@link IPacketFactory}, {@link PacketLoader} and {@link FragmentationOptions}.
|
||||
* The {@link MulticastSocket} will join the multicast group.
|
||||
*
|
||||
* @param socketIn The multicast socket to use.
|
||||
@ -89,12 +178,13 @@ public class NetMarshalClient implements Closeable {
|
||||
* @param multicastGroupPort The multicast group port.
|
||||
* @param factory The packet factory to use.
|
||||
* @param loader The packet loader to use.
|
||||
* @param fragmentationOptions The fragmentation options, null to disable fragmentation.
|
||||
* @throws IOException There is an error joining or multicastGroupAddress is not a multicast address.
|
||||
* @throws NullPointerException socketIn, multicastGroupAddress, factory or loader is null.
|
||||
* @throws IllegalArgumentException multicastGroupPort is less than 0 or greater than 65535.
|
||||
* @throws IllegalArgumentException multicastGroupPort is less than 0 or greater than 65535 or fragmentation options failed validation.
|
||||
*/
|
||||
public NetMarshalClient(MulticastSocket socketIn, InetAddress multicastGroupAddress, int multicastGroupPort, IPacketFactory factory, PacketLoader loader) throws IOException {
|
||||
this(multicastGroupAddress, multicastGroupPort, factory, loader, true, socketIn == null);
|
||||
public NetMarshalClient(MulticastSocket socketIn, InetAddress multicastGroupAddress, int multicastGroupPort, IPacketFactory factory, PacketLoader loader, FragmentationOptions fragmentationOptions) throws IOException {
|
||||
this(multicastGroupAddress, multicastGroupPort, factory, loader, true, socketIn == null, fragmentationOptions);
|
||||
socketIn.joinGroup(multicastGroupAddress);
|
||||
NetworkOutputStream netOut = new NetworkOutputStream(socketIn, 65535);
|
||||
netOut.setDatagramTarget(multicastGroupAddress, multicastGroupPort);
|
||||
@ -102,7 +192,7 @@ public class NetMarshalClient implements Closeable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NetMarshalClient with the specified {@link DatagramSocket}, remote {@link InetAddress}, remote port, {@link IPacketFactory} and {@link PacketLoader}.
|
||||
* Constructs a new NetMarshalClient with the specified {@link DatagramSocket}, remote {@link InetAddress}, remote port, {@link IPacketFactory}, {@link PacketLoader} and {@link FragmentationOptions}.
|
||||
*
|
||||
* @param socketIn The datagram socket to use.
|
||||
* @param remoteAddress The remote address to send data to.
|
||||
@ -110,13 +200,14 @@ public class NetMarshalClient implements Closeable {
|
||||
* @param inputStream The receiving input stream.
|
||||
* @param factory The packet factory to use.
|
||||
* @param loader The loader to use.
|
||||
* @param fragmentationOptions The fragmentation options, null to disable fragmentation.
|
||||
* @throws NullPointerException socketIn, remoteAddress, inputStream, factory or loader is null.
|
||||
* @throws IllegalArgumentException remotePort is less than 0 or greater than 65535.
|
||||
* @throws IllegalArgumentException remotePort is less than 0 or greater than 65535 or fragmentation options failed validation.
|
||||
*/
|
||||
public NetMarshalClient(DatagramSocket socketIn, InetAddress remoteAddress, int remotePort, InputStream inputStream, IPacketFactory factory, PacketLoader loader) {
|
||||
this(remoteAddress, remotePort, factory, loader, false, socketIn == null);
|
||||
public NetMarshalClient(DatagramSocket socketIn, InetAddress remoteAddress, int remotePort, InputStream inputStream, IPacketFactory factory, PacketLoader loader, FragmentationOptions fragmentationOptions) {
|
||||
this(remoteAddress, remotePort, factory, loader, false, socketIn == null, fragmentationOptions);
|
||||
if (inputStream == null) throw new NullPointerException("inputStream is null");
|
||||
setStreams(null, new NetworkOutputStream(socketIn, 65535));
|
||||
setStreams(null, new NetworkOutputStream(socketIn, 65535, remoteAddress, remotePort));
|
||||
rootInputStream = inputStream;
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
@ -128,6 +219,45 @@ public class NetMarshalClient implements Closeable {
|
||||
this.outputStream = rootOutputStream;
|
||||
}
|
||||
|
||||
protected void updateMState(HashMap<Integer, LocalDateTime> mm, IPacket packet) {
|
||||
if (packet == null || !packet.isValid()) return;
|
||||
synchronized (fragmentationOptions) {
|
||||
if (packet instanceof FragmentAllocationPacket) {
|
||||
mm.put(((FragmentAllocationPacket) packet).getPacketID(), LocalDateTime.now());
|
||||
} else if (packet instanceof FragmentPIDPacket && !(packet instanceof FragmentSendStopPacket)) {
|
||||
if (mm.containsKey(((FragmentPIDPacket) packet).getPacketID()))
|
||||
mm.put(((FragmentPIDPacket) packet).getPacketID(), LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendFragmentData() throws PacketException, IOException {
|
||||
IPacket[] packets = fragmentSender.sendPacket();
|
||||
for (IPacket c : packets) if (c != null) {
|
||||
updateMState(fragmentSMM, c);
|
||||
loader.writePacket(outputStream, c, true);
|
||||
}
|
||||
packets = fragmentReceiver.sendPacket();
|
||||
for (IPacket c : packets) if (c != null) {
|
||||
updateMState(fragmentRMM, c);
|
||||
loader.writePacket(outputStream, c, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the marshal.
|
||||
*/
|
||||
public synchronized final void open() {
|
||||
if (running) return;
|
||||
running = true;
|
||||
if (fragmentationOptions != null) {
|
||||
fragmentMonitorThread.start();
|
||||
fragmentFinishReceiveMonitorThread.start();
|
||||
fragmentFinishSendMonitorThread.start();
|
||||
}
|
||||
receiveThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the input stream.
|
||||
*
|
||||
@ -209,6 +339,15 @@ public class NetMarshalClient implements Closeable {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link FragmentationOptions} of the client.
|
||||
*
|
||||
* @return The fragmentation options or null if fragmentation is disabled.
|
||||
*/
|
||||
public FragmentationOptions getFragmentationOptions() {
|
||||
return fragmentationOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the marshal is ssl upgraded.
|
||||
*
|
||||
@ -223,14 +362,20 @@ public class NetMarshalClient implements Closeable {
|
||||
* Sends a {@link IPacket}.
|
||||
*
|
||||
* @param packetIn The packet to send.
|
||||
* @param directSend Whether the packet should be sent directly or through the fragmentation system.
|
||||
* @throws IOException A stream exception has occurred.
|
||||
* @throws PacketException An exception has occurred.
|
||||
* @throws NullPointerException packetIn is null.
|
||||
*/
|
||||
public synchronized final void sendPacket(IPacket packetIn) throws IOException, PacketException {
|
||||
public synchronized final void sendPacket(IPacket packetIn, boolean directSend) throws IOException, PacketException {
|
||||
if (packetIn == null) throw new NullPointerException("packetIn is null");
|
||||
synchronized ((socket == null) ? dsocket : socket) {
|
||||
if (fragmentationOptions == null || directSend) {
|
||||
loader.writePacket(outputStream, packetIn, true);
|
||||
} else {
|
||||
fragmentSender.sendPacket(packetIn);
|
||||
}
|
||||
if (fragmentationOptions != null) sendFragmentData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,6 +526,26 @@ public class NetMarshalClient implements Closeable {
|
||||
receiveExceptionBiConsumer = consumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Consumer} closed consumer.
|
||||
*
|
||||
* @return The closed or null.
|
||||
*/
|
||||
public Consumer<NetMarshalClient> getClosedConsumer() {
|
||||
return closedConsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Consumer} closed consumer.
|
||||
*
|
||||
* @param consumer The new closed consumer.
|
||||
* @throws NullPointerException consumer is null.
|
||||
*/
|
||||
public void setClosedConsumer(Consumer<NetMarshalClient> consumer) {
|
||||
if (consumer == null) throw new NullPointerException("consumer is null");
|
||||
closedConsumer = consumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the marshal, closing all its streams.
|
||||
*
|
||||
@ -391,11 +556,23 @@ public class NetMarshalClient implements Closeable {
|
||||
if (running) {
|
||||
running = false;
|
||||
if (Thread.currentThread() != receiveThread) receiveThread.interrupt();
|
||||
if (fragmentationOptions != null) {
|
||||
fragmentMonitorThread.interrupt();
|
||||
fragmentFinishReceiveMonitorThread.interrupt();
|
||||
fragmentFinishSendMonitorThread.interrupt();
|
||||
}
|
||||
receivedPackets.clear();
|
||||
try {
|
||||
inputStream.close();
|
||||
} finally {
|
||||
try {
|
||||
outputStream.close();
|
||||
} finally {
|
||||
socket = null;
|
||||
dsocket = null;
|
||||
if (closedConsumer != null) closedConsumer.accept(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,4 +600,48 @@ public class NetMarshalClient implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void receiveThreadExecutedWithFragmentation() {
|
||||
try {
|
||||
synchronized (slockPacketRead) {
|
||||
while (disablePacketReading) slockPacketRead.wait();
|
||||
}
|
||||
IPacket packet = loader.readStreamedPacket(inputStream, factory, null);
|
||||
synchronized (slockPacketRead) {
|
||||
if (packet == null || !packet.isValid()) return;
|
||||
updateMState(fragmentRMM, packet);
|
||||
boolean packetUsed = fragmentReceiver.receivePacket(packet);
|
||||
updateMState(fragmentSMM, packet);
|
||||
packetUsed = fragmentSender.receivePacket(packet) || packetUsed;
|
||||
if (packetUsed) {
|
||||
while (fragmentReceiver.arePacketsWaiting()) {
|
||||
packet = fragmentReceiver.receivePacketPolling();
|
||||
if (packet == null || !packet.isValid()) continue;
|
||||
if (receiveBiConsumer != null) receiveBiConsumer.accept(packet, this);
|
||||
synchronized (slockReceive) {
|
||||
receivedPackets.add(packet);
|
||||
slockReceive.notify();
|
||||
}
|
||||
}
|
||||
synchronized ((socket == null) ? dsocket : socket) {
|
||||
sendFragmentData();
|
||||
}
|
||||
} else {
|
||||
if (receiveBiConsumer != null) receiveBiConsumer.accept(packet, this);
|
||||
synchronized (slockReceive) {
|
||||
receivedPackets.add(packet);
|
||||
slockReceive.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException | InterruptedIOException e) {
|
||||
} catch (PacketException | IOException e) {
|
||||
if (receiveExceptionBiConsumer != null) receiveExceptionBiConsumer.accept(e, this);
|
||||
try {
|
||||
close();
|
||||
} catch (IOException ex) {
|
||||
if (receiveExceptionBiConsumer != null) receiveExceptionBiConsumer.accept(ex, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,24 +25,26 @@ public class NetMarshalClientWrapped extends NetMarshalClient {
|
||||
|
||||
/**
|
||||
* Constructs a new NetMarshalClientWrapped with the specified {@link Socket}, {@link IPacketFactory},
|
||||
* {@link PacketLoader}, {@link Function} for wrapping the input stream and the {@link Function} for wrapping the output stream.
|
||||
* {@link PacketLoader}, {@link FragmentationOptions}, {@link Function} for wrapping the input stream and the {@link Function} for wrapping the output stream.
|
||||
* Wrapped streams should close the underlying stream when closed.
|
||||
*
|
||||
* @param socketIn The socket to use.
|
||||
* @param factory The packet factory to use.
|
||||
* @param loader The packet loader to use.
|
||||
* @param fragmentationOptions The fragmentation options, null to disable fragmentation.
|
||||
* @param inputStreamWrapper The input stream wrapper to use (Can be null).
|
||||
* @param outputStreamWrapper The output stream wrapper to use (Can be null).
|
||||
* @throws NullPointerException socketIn, factory or loader is null.
|
||||
* @throws IllegalArgumentException Fragmentation options failed validation.
|
||||
*/
|
||||
public NetMarshalClientWrapped(Socket socketIn, IPacketFactory factory, PacketLoader loader, Function<InputStream, InputStream> inputStreamWrapper, Function<OutputStream, OutputStream> outputStreamWrapper) {
|
||||
super(socketIn, factory, loader);
|
||||
public NetMarshalClientWrapped(Socket socketIn, IPacketFactory factory, PacketLoader loader, FragmentationOptions fragmentationOptions, Function<InputStream, InputStream> inputStreamWrapper, Function<OutputStream, OutputStream> outputStreamWrapper) {
|
||||
super(socketIn, factory, loader, fragmentationOptions);
|
||||
setupWrappers(inputStreamWrapper, outputStreamWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NetMarshalClientWrapped with the specified {@link MulticastSocket}, multicast group {@link InetAddress}, multicast port, {@link IPacketFactory},
|
||||
* {@link PacketLoader}, {@link Function} for wrapping the input stream and the {@link Function} for wrapping the output stream.
|
||||
* {@link PacketLoader}, {@link FragmentationOptions}, {@link Function} for wrapping the input stream and the {@link Function} for wrapping the output stream.
|
||||
* The {@link MulticastSocket} will join the multicast group.
|
||||
* Wrapped streams should close the underlying stream when closed.
|
||||
*
|
||||
@ -51,20 +53,21 @@ public class NetMarshalClientWrapped extends NetMarshalClient {
|
||||
* @param multicastGroupPort The multicast group port.
|
||||
* @param factory The packet factory to use.
|
||||
* @param loader The packet loader to use.
|
||||
* @param fragmentationOptions The fragmentation options, null to disable fragmentation.
|
||||
* @param inputStreamWrapper The input stream wrapper to use (Can be null).
|
||||
* @param outputStreamWrapper The output stream wrapper to use (Can be null).
|
||||
* @throws IOException There is an error joining or multicastGroupAddress is not a multicast address.
|
||||
* @throws NullPointerException socketIn, multicastGroupAddress, factory or loader is null.
|
||||
* @throws IllegalArgumentException multicastGroupPort is less than 0 or greater than 65535.
|
||||
* @throws IllegalArgumentException multicastGroupPort is less than 0 or greater than 65535 or fragmentation options failed validation.
|
||||
*/
|
||||
public NetMarshalClientWrapped(MulticastSocket socketIn, InetAddress multicastGroupAddress, int multicastGroupPort, IPacketFactory factory, PacketLoader loader, Function<InputStream, InputStream> inputStreamWrapper, Function<OutputStream, OutputStream> outputStreamWrapper) throws IOException {
|
||||
super(socketIn, multicastGroupAddress, multicastGroupPort, factory, loader);
|
||||
public NetMarshalClientWrapped(MulticastSocket socketIn, InetAddress multicastGroupAddress, int multicastGroupPort, IPacketFactory factory, PacketLoader loader, FragmentationOptions fragmentationOptions, Function<InputStream, InputStream> inputStreamWrapper, Function<OutputStream, OutputStream> outputStreamWrapper) throws IOException {
|
||||
super(socketIn, multicastGroupAddress, multicastGroupPort, factory, loader, fragmentationOptions);
|
||||
setupWrappers(inputStreamWrapper, outputStreamWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NetMarshalClientWrapped with the specified {@link DatagramSocket}, remote {@link InetAddress}, remote port, {@link IPacketFactory},
|
||||
* {@link PacketLoader}, {@link Function} for wrapping the input stream and the {@link Function} for wrapping the output stream.
|
||||
* {@link PacketLoader}, {@link FragmentationOptions}, {@link Function} for wrapping the input stream and the {@link Function} for wrapping the output stream.
|
||||
* Wrapped streams should close the underlying stream when closed.
|
||||
*
|
||||
* @param socketIn The datagram socket to use.
|
||||
@ -73,13 +76,14 @@ public class NetMarshalClientWrapped extends NetMarshalClient {
|
||||
* @param inputStream The receiving input stream.
|
||||
* @param factory The packet factory to use.
|
||||
* @param loader The loader to use.
|
||||
* @param fragmentationOptions The fragmentation options, null to disable fragmentation.
|
||||
* @param inputStreamWrapper The input stream wrapper to use (Can be null).
|
||||
* @param outputStreamWrapper The output stream wrapper to use (Can be null).
|
||||
* @throws NullPointerException socketIn, remoteAddress, inputStream, factory or loader is null.
|
||||
* @throws IllegalArgumentException remotePort is less than 0 or greater than 65535.
|
||||
* @throws IllegalArgumentException remotePort is less than 0 or greater than 65535 or fragmentation options failed validation.
|
||||
*/
|
||||
public NetMarshalClientWrapped(DatagramSocket socketIn, InetAddress remoteAddress, int remotePort, InputStream inputStream, IPacketFactory factory, PacketLoader loader, Function<InputStream, InputStream> inputStreamWrapper, Function<OutputStream, OutputStream> outputStreamWrapper) {
|
||||
super(socketIn, remoteAddress, remotePort, inputStream, factory,loader);
|
||||
public NetMarshalClientWrapped(DatagramSocket socketIn, InetAddress remoteAddress, int remotePort, InputStream inputStream, IPacketFactory factory, PacketLoader loader, FragmentationOptions fragmentationOptions, Function<InputStream, InputStream> inputStreamWrapper, Function<OutputStream, OutputStream> outputStreamWrapper) {
|
||||
super(socketIn, remoteAddress, remotePort, inputStream, factory, loader, fragmentationOptions);
|
||||
setupWrappers(inputStreamWrapper, outputStreamWrapper);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
package com.captainalm.lib.calmnet.marshal;
|
||||
/*TODO:
|
||||
NetMarshalClient(Wrapped) - Fragmentation processing support
|
||||
NetMarshalServer - Has a thread for UDP receiving and has a dictionary of input streams (final, created in constructor)
|
||||
NetMarshalServerWrapped - Constructs NetMarshalClientWrapped instead of NetMarshalClient, stream wrapping support
|
||||
*/
|
@ -56,6 +56,17 @@ public final class FragmentReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a {@link IPacket} from the FragmentReceiver.
|
||||
*
|
||||
* @return The received packet or null.
|
||||
*/
|
||||
public IPacket receivePacketPolling() {
|
||||
synchronized (slockqueue) {
|
||||
return outputQueue.poll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the current {@link IPacket}s from the FragmentReceiver.
|
||||
*
|
||||
@ -206,6 +217,18 @@ public final class FragmentReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the last finished packet ID.
|
||||
*
|
||||
* @return The last finished packet ID.
|
||||
*/
|
||||
public Integer pollLastIDFinished() {
|
||||
synchronized (slockfinish) {
|
||||
Integer polled = finishedIDs.poll();
|
||||
return (polled == null) ? -1 : polled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the last finished packet IDs.
|
||||
*/
|
||||
|
@ -179,6 +179,18 @@ public final class FragmentSender {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the last finished packet ID.
|
||||
*
|
||||
* @return The last finished packet ID.
|
||||
*/
|
||||
public Integer pollLastIDFinished() {
|
||||
synchronized (slockfinish) {
|
||||
Integer polled = finishedIDs.poll();
|
||||
return (polled == null) ? -1 : polled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the last finished packet IDs.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user