package org.webpieces.nio.api.channels; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import org.webpieces.nio.api.handlers.DataListener; /** * * TCPServerChannel - RegisterableChannel * TCPChannel - Channel - RegisterableChannel * UDPChannel - Channel - RegisterableChannel * DatagramChannel - RegisterableChannel * * This is the superclass for UDPChannel and TCPChannel * <pre> * TCPServerChannel and TCPChannel have similar functions like * 1. bind * 2. isBound * * TCPChannel and UDPChannel have similar functions like * 1. registerForRead * 2. connect (in java, udp has a connect for better point to point performance) * 3. bind * 4. isBound * * This implies the superinterface of UDPChannel and TCPChannel share the * same superinterface as TCPServerChannel * * TCPServerChannel - RegisterableChannel * TCPChannel - Channel - RegisterableChannel * UDPChannel - Channel - RegisterableChannel * DatagramChannel - RegisterableChannel * </pre> * * @author Dean Hiller */ public interface Channel extends RegisterableChannel { /** * Connects and registers a DataListener that will be notified of all incoming data. * * NOTE: We do not have a CompletableFuture read() as that can cause result in new gen objects that should * never end up in old gen being pulled to old gen. You can backpressure incoming data using unregisterForReads() * and registerForReads() such that data is not read from the socket anymore if you desire on that specific * channel * * ie. the Following scenario * 1. you read() and then add your listener. The Future has been created * 2. no data comes in for a bit for this read * 3. the Future moves to old gen * 4. Finally, data comes in and invokes the Future so Future.complete(xxx) is called * 5. Now, since the Future is in old gen, it will pull xxx and everything else into old gen along with * it which you should not do causing a very hard to figure out memory issue * * @param addr The address to connect to * @param listener Once connected, this is the listener that will start receiving data * @return */ public CompletableFuture<Channel> connect(SocketAddress addr, DataListener listener); public CompletableFuture<Channel> write(ByteBuffer b); public CompletableFuture<Channel> close(); /** * After you are connected, you are automatically registered for reads but if you want * to apply back pressure down the channel to the client/server that is sending you data, * you can call unregisterForReads and reads stop until you call unregisterForReads */ public CompletableFuture<Channel> registerForReads(); /** * Stop reading from the nic buffer for this channel such that the downstream client/server * process will eventually block on sending you data. It is a way to backpressure a specific * channel safely to not overload your server when needed and when systems you are talking * to take too long to respond * */ public CompletableFuture<Channel> unregisterForReads(); public boolean isRegisteredForReads(); /** * Gets the remote address the channel is communicating with. * * @return the remote address the channel is communicating with. */ public InetSocketAddress getRemoteAddress(); /** * Returns whether or not the channel is connected. * @return whether or not the channel is connected. */ public boolean isConnected(); /** * Each Channel has a ChannelSession where you can store state. IF you have one client per Socket, then you can * easily store client state in the Channel itself so instead of passing around a Session in your code, you can pass * around a Channel that has a ChannelSession. * * @return client's Session object */ public ChannelSession getSession(); /** * It is important if far end stops reading that we only backup writes to a certain point and then * fail so you don't blow your RAM and keep trying to write. The default will be set to 500_000 bytes. * * Something similar to slowloris https://en.wikipedia.org/wiki/Slowloris_(computer_security) but with * the tweak that one could simply not read responses as the client */ public void setMaxBytesWriteBackupSize(int maxBytesBackup); public int getMaxBytesBackupSize(); public boolean isSslChannel(); }