/** /** * @copyright 2013 Computer Science Department, Recursive InterNetworking Architecture (RINA) laboratory, Boston University. * All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation * for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all * copies and that both the copyright notice and this permission notice appear in supporting documentation. * The RINA laboratory of the Computer Science Department at Boston University makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * */ package rina.tcp; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import rina.tcp.util.Varint; import rina.util.MessageQueue; /** * TCP flow * @author Yuefeng Wang. Computer Science Department, Boston University * @version 1.0 */ public class TCPFlow { private Log log = LogFactory.getLog(TCPFlow.class); /** * source address */ private byte[] addr; /** * Internet address */ private InetAddress inetAddr; /** * destination port */ private int dstPort; /** * destination address */ private byte[] dnsAddr; /** * TCP socket */ private Socket socket; /** * TCP server socket */ private ServerSocket serverSocket; /** * local port */ private int localPort; /** * URL or IP address of dst */ private String dstURL; /** * This one is used for possible use for flow allocator (TCP Manager) */ private int flowID; private String srcName; private String dstName; private MessageQueue msgQueue = null; /** * Dummy Constructor */ public TCPFlow() { this.msgQueue = new MessageQueue(); } /** * Constructor * create a local tcp flow listening to a certain port * @param local Port * @throws Exception */ public TCPFlow(int localPort) throws Exception { this.localPort = localPort; this.msgQueue = new MessageQueue(); this.serverSocket = new ServerSocket(this.localPort); } /** * Constructor * @param dstURL * @param port * @throws Exception * @throws Exception */ public TCPFlow(String dstURL, int dstPort) throws Exception { this.dstURL = dstURL; this.dstPort = dstPort; this.msgQueue = new MessageQueue(); inetAddr = InetAddress.getByName(this.dstURL); socket = new Socket(inetAddr, this.dstPort); } public synchronized void send( byte[] message) throws Exception { OutputStream out = socket.getOutputStream(); DataOutputStream dos = new DataOutputStream(out); int len = message.length; byte[] varByteArray = Varint.writeVarint(len); if(len <= Integer.MAX_VALUE) { for(int i = 0; i< varByteArray.length; i++) { dos.writeByte(varByteArray[i]); } dos.write(message, 0, len); }else { this.log.error("Message too large, fragment it first"); } // this.log.debug(" Msg sent out with length " + len + " to dstName " + this.dstName+ ", IP address " + this.dstURL ); } /** * receive a message from the tcp socket * @return the array of byte received over the TCP socket * @throws Exception * @throws Exception */ public byte[] receive() throws Exception { byte[] data = null; InputStream in = socket.getInputStream(); DataInputStream dis = new DataInputStream(in); int length = 0 ; int value = 0; int b; int i = 0; while (((b = dis.readByte()) & 0x80) != 0) { value |= (b & 0x7F) << i; i+= 7; } length = value | (b << i); // this.log.debug("msg received length is " + length); data = new byte[length]; dis.readFully(data, 0 , length); return data; } /** * accept an incoming client socket * @return a listening TCP flow */ public TCPFlow accept() { TCPFlow ListeningTcpFlow = new TCPFlow(); try { ListeningTcpFlow.socket = serverSocket.accept(); } catch (IOException e) { this.log.warn("Exception: " +e); e.printStackTrace(); } return ListeningTcpFlow; } public void close() { if(serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { this.log.warn("Exception: " + e); e.printStackTrace(); } } if(socket != null){ try { socket .close(); } catch (IOException e) { this.log.warn("Exception: " + e); e.printStackTrace(); } } } /** * * @return destination port */ public int getDstport() { return dstPort; } /** * * @param destination port */ public void setDstport(int dstPort) { this.dstPort = dstPort; } /** * * @param localPort */ public void setLocalPort(int localPort) { this.localPort = localPort; } /** * getUrl * @return dstURL */ public String getUrl() { return dstURL; } /** * setUrl * @param dstURL */ public void setUrl(String dstURL) { this.dstURL = dstURL; } /** * getAddr * @return addr */ public byte[] getAddr() { return addr; } /** * setAddr * @param addr */ public void setAddr(byte[] addr) { this.addr = addr; } /** * getInetAddr * @return inetAddr */ public InetAddress getInetAddr() { return inetAddr; } /** * setInetAddr * @param inetAddr */ public void setInetAddr(InetAddress inetAddr) { this.inetAddr = inetAddr; } /** * getPort * @return port */ public int getDstPort() { return dstPort; } /** * setPort * @param port */ public void setDstPort(int port) { this.dstPort = port; } /** * getDnsAddr * @return dnsAddr */ public byte[] getDnsAddr() { return dnsAddr; } /** * setDnsAddr * @param dnsAddr */ public void setDnsAddr(byte[] dnsAddr) { this.dnsAddr = dnsAddr; } /** * getSocket * @return socket */ public Socket getSocket() { return socket; } /** * setSocket * @param socket */ public void setSocket(Socket socket) { this.socket = socket; } /** * getServerSocket * @return serverSocket */ public ServerSocket getServerSocket() { return serverSocket; } /** * setServerSocket * @param ServerSocket serverSocket */ public void setServerSocket(ServerSocket serverSocket) { this.serverSocket = serverSocket; } /** * getlocalPort * @return localPort */ public int getLocalPort() { return localPort; } /** * setlocalPort * @param localPort */ public void setlocalPort(int localPort) { this.localPort = localPort; } public synchronized String getDstURL() { return dstURL; } public synchronized void setDstURL(String dstURL) { this.dstURL = dstURL; } public synchronized int getFlowID() { return flowID; } /** * Set the flow ID for the TCP flow, also attach the msg queue with this flow ID * @param flowID */ public synchronized void setFlowID(int flowID) { this.flowID = flowID; this.msgQueue.setFlowID(flowID); } public synchronized String getSrcName() { return srcName; } public synchronized void setSrcName(String srcName) { this.srcName = srcName; } public synchronized String getDstName() { return dstName; } public synchronized void setDstName(String dstName) { this.dstName = dstName; } public synchronized MessageQueue getMsgQueue() { return msgQueue; } public synchronized void setMsgQueue(MessageQueue msgQueue) { this.msgQueue = msgQueue; } } //end of class