package uc.protocols; import helpers.GH; import java.io.Closeable; import java.io.IOException; import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.ByteChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Enumeration; import logger.LoggerFactory; import org.apache.log4j.Level; import org.apache.log4j.Logger; import uc.ICryptoManager; import uc.PI; /** * base class for all connections.. * * @author Quicksilver * */ public abstract class AbstractConnection implements Closeable, IConnection { private static Logger logger = LoggerFactory.make(Level.DEBUG); protected final ConnectionProtocol cp; //our Connection protocol.. // protected volatile CharsetDecoder charsetDecoder; // protected volatile CharsetEncoder charsetEncoder; protected final ICryptoManager cryptoManager; public AbstractConnection(ICryptoManager cryptoManager,ConnectionProtocol cp) { this.cryptoManager = cryptoManager; this.cp = cp; } protected InetSocketAddress addytransformation(String addy){ //transforms an url string to ip/dns and port int pos = addy.lastIndexOf(':'); if (pos == -1) { return new InetSocketAddress(addy, cp.defaultPort); } else { return new InetSocketAddress(addy.substring(0, pos), Integer.parseInt(addy.substring(pos+1)) ); } } /* (non-Javadoc) * @see uc.protocols.IConnection#start() */ public abstract void start(); // /* (non-Javadoc) // * @see uc.protocols.IConnection#send(java.lang.String) // */ // public abstract void send(String toSend) throws IOException ; /* (non-Javadoc) * @see uc.protocols.IConnection#send(java.nio.ByteBuffer) */ public abstract void send(ByteBuffer toSend) throws IOException ; /* (non-Javadoc) * @see uc.protocols.IConnection#reset(java.nio.channels.SocketChannel) */ public abstract void reset(SocketChannel soChan); /* (non-Javadoc) * @see uc.protocols.IConnection#reset(java.net.InetSocketAddress) */ public abstract void reset(InetSocketAddress addy); /* (non-Javadoc) * @see uc.protocols.IConnection#reset(java.lang.String) */ public void reset(String addy) { reset(addytransformation(addy)); } /* (non-Javadoc) * @see uc.protocols.IConnection#close() */ public abstract void close(); /* (non-Javadoc) * @see uc.protocols.IConnection#getInetSocketAddress() */ public abstract InetSocketAddress getInetSocketAddress(); /* (non-Javadoc) * @see uc.protocols.IConnection#isLocal() */ public boolean isLocal(){ InetAddress ia= getInetSocketAddress().getAddress(); return GH.isLocaladdress(ia); } /* (non-Javadoc) * @see uc.protocols.IConnection#retrieveChannel() */ public abstract ByteChannel retrieveChannel() throws IOException; /* (non-Javadoc) * @see uc.protocols.IConnection#returnChannel(java.nio.channels.ByteChannel) */ public abstract boolean returnChannel(ByteChannel sochan); /* (non-Javadoc) * @see uc.protocols.IConnection#flush(int) */ // public abstract boolean flush(int miliseconds); /* (non-Javadoc) * @see uc.protocols.IConnection#setIncomingDecompression(uc.protocols.Compression) */ public abstract void setIncomingDecompression(Compression comp) throws IOException; // /* (non-Javadoc) // * @see uc.protocols.IConnection#refreshCharsetCoders() // */ // public void refreshCharsetCoders() { // charsetDecoder = cp.getCharset().newDecoder(); // charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE); // charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE); // charsetEncoder = cp.getCharset().newEncoder(); // charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPLACE); // charsetEncoder.onMalformedInput(CodingErrorAction.REPLACE); // } /* (non-Javadoc) * @see uc.protocols.IConnection#usesEncryption() */ public abstract boolean usesEncryption(); /** * binds an InetSocketChannel to the given interface name... * or doesn't bind it if name could not be found .. * * @param interfacename - which interface to bind to .. * @param sochan - which socket channel to bind * @param bindPort - 0 for system decision otherwise 1-65k */ public static void bindSocket(String inetaddress,SocketChannel sochan) throws IOException { bindSocket(inetaddress, sochan,0); } public static void bindSocket(SocketChannel sochan) throws IOException { bindSocket(PI.get(PI.bindAddress),sochan); } private static volatile String unresolveableBindAddrees; /** * * @return currently set bind address... null if none... */ public static InetAddress getBindAddress(String bindAddressString) throws SocketException { if (GH.isNullOrEmpty(bindAddressString)) { return null; } logger.trace("Trying to resolve: "+bindAddressString); NetworkInterface ni = NetworkInterface.getByName(bindAddressString); if (ni != null) { Enumeration<InetAddress> ias = ni.getInetAddresses(); while (ias.hasMoreElements()) { InetAddress ia = ias.nextElement(); if (!ia.isLoopbackAddress() && ia instanceof Inet4Address) { logger.trace("NI: "+ia); unresolveableBindAddrees = null; return ia; } } } else { try { InetAddress ina = InetAddress.getByName(bindAddressString); logger.trace("inet address: "+ina); if (NetworkInterface.getByInetAddress(ina) != null) { unresolveableBindAddrees = null; return ina; } } catch(UnknownHostException uhe) { if (!bindAddressString.equals(unresolveableBindAddrees)) { logger.warn("Bind address could not be resolved: "+bindAddressString,uhe); unresolveableBindAddrees = bindAddressString; } } } return null; } public static void bindSocket(String inetaddress,ServerSocketChannel sochan,int bindPort) throws IOException { bindSocket(inetaddress, (Object)sochan,bindPort); if (!sochan.socket().isBound()) { sochan.socket().bind(new InetSocketAddress(bindPort)); } } public static void bindSocket(ServerSocketChannel sochan, int bindPort) throws IOException { bindSocket(PI.get(PI.bindAddress), sochan,bindPort); } private static void bindSocket(String bindAddressString,Object sochan,int bindPort) throws IOException { InetAddress ia = getBindAddress(bindAddressString); if (ia != null) { InetSocketAddress isa = new InetSocketAddress(ia, bindPort); if (sochan instanceof SocketChannel) { ((SocketChannel)sochan).socket().bind(isa); } else if (sochan instanceof ServerSocketChannel) { ((ServerSocketChannel)sochan).socket().bind(isa); } } } }