package com.limegroup.gnutella.util; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; /** * Returns two sockets A and B, so that the input of A is connected to * the output of B and vice versa. Typical use: * <pre> * PipedSocketFactory factory=new PipedSocketFactory("1.1.1.1", "2.2.2.2"); * Connection cA=new Connection(factory.getSocketA()); * Connection cB=new Connection(factory.getSocketB()); * cA.send(m1); * cB.receive(); * cB.send(m2); * cA.receive(); * </pre> */ public class PipedSocketFactory { OutputStream _aOut; InputStream _aIn; OutputStream _bOut; InputStream _bIn; InetAddress _hostA; InetAddress _hostB; boolean aOutClosed; boolean bOutClosed; boolean aInClosed; boolean bInClosed; /** * @param hostA the address to use for socket A * @param hostB the address to use for socket B */ public PipedSocketFactory(String hostA, String hostB) throws IOException, UnknownHostException { PipedOutputStream aOut=new PipedOutputStream() { public void close() throws IOException { super.close(); aOutClosed = true; PipedSocketFactory.this.close(); } }; PipedInputStream bIn=new PipedInputStream(aOut) { public void close() throws IOException { super.close(); bInClosed = true; PipedSocketFactory.this.close(); } }; PipedOutputStream bOut=new PipedOutputStream() { public void close() throws IOException { super.close(); bOutClosed = true; PipedSocketFactory.this.close(); } }; PipedInputStream aIn=new PipedInputStream(bOut) { public void close() throws IOException { super.close(); aInClosed = true; PipedSocketFactory.this.close(); } }; _aIn=aIn; _bIn=bIn; _aOut = aOut; _bOut = bOut; _hostA=InetAddress.getByName(hostA); _hostB=InetAddress.getByName(hostB); } private void close() throws IOException { if(!aInClosed) _aIn.close(); if(!bInClosed) _bIn.close(); if(!aOutClosed) _aOut.close(); if(!bOutClosed) _bOut.close(); } public Socket getSocketA() { return new Socket() { public InetAddress getInetAddress() { return _hostB; } public InetAddress getLocalAddress() { return _hostA; } public InputStream getInputStream() { return _aIn; } public OutputStream getOutputStream() { return _aOut; } public void close() throws IOException { PipedSocketFactory.this.close(); } }; } public Socket getSocketB() { return new Socket() { public InetAddress getInetAddress() { return _hostA; } public InetAddress getLocalAddress() { return _hostB; } public InputStream getInputStream() { return _bIn; } public OutputStream getOutputStream() { return _bOut; } public void close() throws IOException { PipedSocketFactory.this.close(); } }; } }