diff --git a/src/com/captainalm/lib/calmnet/marshal/NetMarshalClient.java b/src/com/captainalm/lib/calmnet/marshal/NetMarshalClient.java index a5c97d0..af7c950 100644 --- a/src/com/captainalm/lib/calmnet/marshal/NetMarshalClient.java +++ b/src/com/captainalm/lib/calmnet/marshal/NetMarshalClient.java @@ -50,7 +50,7 @@ public class NetMarshalClient implements Closeable { protected final Queue receivedPackets = new LinkedList<>(); protected final Object slockReceive = new Object(); - protected NetMarshalClient(InetAddress remoteAddress, int remotePort, IPacketFactory factory, PacketLoader loader, boolean isMulticast, boolean isSocketNull) { + private NetMarshalClient(InetAddress remoteAddress, int remotePort, IPacketFactory factory, PacketLoader loader, boolean isMulticast, boolean isSocketNull) { if (isSocketNull) throw new NullPointerException("socketIn is null"); if (remoteAddress == null) throw new NullPointerException(((isMulticast) ? "multicastGroupAddress" : "remoteAddress") + " is null"); this.remoteAddress = remoteAddress; @@ -205,7 +205,7 @@ public class NetMarshalClient implements Closeable { * * @return If the marshal is running. */ - public synchronized boolean isRunning() { + public synchronized final boolean isRunning() { return running; } @@ -214,7 +214,7 @@ public class NetMarshalClient implements Closeable { * * @return Is the marshal ssl upgraded. */ - public synchronized boolean isSSLUpgraded() { + public synchronized final boolean isSSLUpgraded() { if (!running) return false; return socket instanceof SSLSocket; } @@ -227,7 +227,7 @@ public class NetMarshalClient implements Closeable { * @throws PacketException An exception has occurred. * @throws NullPointerException packetIn is null. */ - public synchronized void sendPacket(IPacket packetIn) throws IOException, PacketException { + public synchronized final void sendPacket(IPacket packetIn) throws IOException, PacketException { if (packetIn == null) throw new NullPointerException("packetIn is null"); synchronized ((socket == null) ? dsocket : socket) { loader.writePacket(outputStream, packetIn, true); @@ -315,7 +315,7 @@ public class NetMarshalClient implements Closeable { sslUpgrade(context, remoteHostName); } - protected synchronized void sslUpgrade(SSLContext context, String remoteHostName) throws SSLUtilityException, IOException { + protected synchronized final void sslUpgrade(SSLContext context, String remoteHostName) throws SSLUtilityException, IOException { if (!running || socket == null || socket instanceof SSLSocket) return; if (context == null) throw new NullPointerException("context is null"); if (!disablePacketReading && Thread.currentThread() != receiveThread) throw new IllegalStateException("sslUpgrade methods should be called in a BiConsumer (for setReceiveBiConsumer) within the target NetMarshalClient" + @@ -387,7 +387,7 @@ public class NetMarshalClient implements Closeable { * @throws IOException An I/O Exception has occurred. */ @Override - public synchronized void close() throws IOException { + public synchronized final void close() throws IOException { if (running) { running = false; if (Thread.currentThread() != receiveThread) receiveThread.interrupt(); diff --git a/src/com/captainalm/lib/calmnet/marshal/NetMarshalClientWrapped.java b/src/com/captainalm/lib/calmnet/marshal/NetMarshalClientWrapped.java new file mode 100644 index 0000000..b45a084 --- /dev/null +++ b/src/com/captainalm/lib/calmnet/marshal/NetMarshalClientWrapped.java @@ -0,0 +1,110 @@ +package com.captainalm.lib.calmnet.marshal; + +import com.captainalm.lib.calmnet.packet.PacketLoader; +import com.captainalm.lib.calmnet.packet.factory.IPacketFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.MulticastSocket; +import java.net.Socket; +import java.util.function.Function; + +/** + * This class provides a managed way of networking on the client side, allows stream wrapping. + * Wrapped streams should close the underlying stream when closed. + * NOTE: Methods that are synchronised are used here, do NOT use instances of these classes as monitors. + * + * @author Captain ALM + */ +public class NetMarshalClientWrapped extends NetMarshalClient { + protected Function wrapperInputStream; + protected Function wrapperOutputStream; + + /** + * 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. + * 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 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. + */ + public NetMarshalClientWrapped(Socket socketIn, IPacketFactory factory, PacketLoader loader, Function inputStreamWrapper, Function outputStreamWrapper) { + super(socketIn, factory, loader); + 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. + * The {@link MulticastSocket} will join the multicast group. + * Wrapped streams should close the underlying stream when closed. + * + * @param socketIn The multicast socket to use. + * @param multicastGroupAddress The multicast group address. + * @param multicastGroupPort The multicast group port. + * @param factory The packet factory to use. + * @param loader The packet loader to use. + * @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. + */ + public NetMarshalClientWrapped(MulticastSocket socketIn, InetAddress multicastGroupAddress, int multicastGroupPort, IPacketFactory factory, PacketLoader loader, Function inputStreamWrapper, Function outputStreamWrapper) throws IOException { + super(socketIn, multicastGroupAddress, multicastGroupPort, factory, loader); + 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. + * Wrapped streams should close the underlying stream when closed. + * + * @param socketIn The datagram socket to use. + * @param remoteAddress The remote address to send data to. + * @param remotePort The remote port to send data to. + * @param inputStream The receiving input stream. + * @param factory The packet factory to use. + * @param loader The loader to use. + * @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. + */ + public NetMarshalClientWrapped(DatagramSocket socketIn, InetAddress remoteAddress, int remotePort, InputStream inputStream, IPacketFactory factory, PacketLoader loader, Function inputStreamWrapper, Function outputStreamWrapper) { + super(socketIn, remoteAddress, remotePort, inputStream, factory,loader); + setupWrappers(inputStreamWrapper, outputStreamWrapper); + } + + protected void setupWrappers(Function inputStreamWrapper, Function outputStreamWrapper) { + wrapperInputStream = inputStreamWrapper; + if (wrapperInputStream != null) inputStream = wrapperInputStream.apply(rootInputStream); + wrapperOutputStream = outputStreamWrapper; + if (wrapperOutputStream != null) outputStream = wrapperOutputStream.apply(rootOutputStream); + } + + /** + * Gets the {@link Function} input stream wrapper function. + * + * @return The input stream wrapper function or null. + */ + public Function getWrapperInputStream() { + return wrapperInputStream; + } + + /** + * Gets the {@link Function} output stream wrapper function. + * + * @return The output stream wrapper function or null. + */ + public Function getWrapperOutputStream() { + return wrapperOutputStream; + } +}