/* *Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * *WSO2 Inc. licenses this file to you under the Apache License, *Version 2.0 (the "License"); you may not use this file except *in compliance with the License. *You may obtain a copy of the License at * *http://www.apache.org/licenses/LICENSE-2.0 * *Unless required by applicable law or agreed to in writing, *software distributed under the License is distributed on an *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *KIND, either express or implied. See the License for the *specific language governing permissions and limitations *under the License. */ package org.wso2.carbon.automation.test.utils.tcpmon.client; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.Socket; import java.net.URL; import java.nio.charset.Charset; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; /** * A connection listens to a single current connection */ class Connection extends Thread { private static final Log log = LogFactory.getLog(Connection.class); private TCPMonListener listener; private boolean active; private String fromHost; private String time; private StringBuffer inputText = null; private StringBuffer outputText = null; private Socket inSocket = null; private Socket outSocket = null; private SocketRR rr1 = null; private SocketRR rr2 = null; private InputStream inputStream = null; private String HTTPProxyHost = null; private int HTTPProxyPort = 80; private SlowLinkSimulator slowLink; public Connection(TCPMonListener listener) { this.listener = listener; HTTPProxyHost = listener.getHTTPProxyHost(); HTTPProxyPort = listener.getHTTPProxyPort(); slowLink = listener.getSlowLink(); } public Connection(TCPMonListener listener, Socket socket) { this(listener); inSocket = socket; start(); } public Connection(TCPMonListener listener, InputStream in) { this(listener); inputStream = in; start(); } /** * Method run */ public void run() { try { active = true; HTTPProxyHost = System.getProperty("http.proxyHost"); if ((HTTPProxyHost != null) && HTTPProxyHost.equals("")) { HTTPProxyHost = null; } if (HTTPProxyHost != null) { String tmp = System.getProperty("http.proxyPort"); if ((tmp != null) && tmp.equals("")) { tmp = null; } if (tmp == null) { HTTPProxyPort = 80; } else { HTTPProxyPort = Integer.parseInt(tmp); } } if (inSocket != null) { fromHost = (inSocket.getInetAddress()).getHostName(); } else { fromHost = "resend"; } String dateformat = "yyyy-MM-dd HH:mm:ss"; DateFormat df = new SimpleDateFormat(dateformat); time = df.format(new Date()); int count = listener.getConnections().size(); listener.getConnectionData().put(count + 1, new ConnectionData("Active", time, fromHost, listener.getTargetHost(), "", "") ); listener.getConnections().add(this); inputText = new StringBuffer(); outputText = new StringBuffer(); String targetHost = listener.getTargetHost(); int targetPort = listener.getTargetPort(); int listenPort = listener.getListenPort(); InputStream tmpIn1 = inputStream; OutputStream tmpOut1 = null; InputStream tmpIn2 = null; OutputStream tmpOut2 = null; if (tmpIn1 == null) { tmpIn1 = inSocket.getInputStream(); } if (inSocket != null) { tmpOut1 = inSocket.getOutputStream(); } String bufferedData = null; StringBuffer buf = null; int index = listener.getConnections().indexOf(this); listener.getConnectionData().get(index + 1).setInputText(inputText); listener.getConnectionData().get(index + 1).setOutputText(outputText); if (listener.isProxy() || (HTTPProxyHost != null)) { // Check if we're a proxy byte[] b = new byte[1]; buf = new StringBuffer(); String s; for (; ; ) { int len; len = tmpIn1.read(b, 0, 1); if (len == -1) { break; } s = new String(b, Charset.defaultCharset()); buf.append(s); if (b[0] != '\n') { continue; } break; } bufferedData = buf.toString(); inputText.append(bufferedData); if (bufferedData.startsWith("GET ") || bufferedData.startsWith("POST ") || bufferedData.startsWith("PUT ") || bufferedData.startsWith("DELETE ")) { int start, end; URL url; start = bufferedData.indexOf(' ') + 1; while (bufferedData.charAt(start) == ' ') { start++; } end = bufferedData.indexOf(' ', start); String urlString = bufferedData.substring(start, end); if (urlString.charAt(0) == '/') { urlString = urlString.substring(1); } if (listener.isProxy()) { url = new URL(urlString); targetHost = url.getHost(); targetPort = url.getPort(); if (targetPort == -1) { targetPort = 80; } listener.getConnectionData().get(index + 1).setTargetHost(targetHost); bufferedData = bufferedData.substring(0, start) + url.getFile() + bufferedData.substring(end); } else { url = new URL("http://" + targetHost + ":" + targetPort + "/" + urlString); listener.getConnectionData().get(index + 1).setTargetHost(targetHost); bufferedData = bufferedData.substring(0, start) + url.toExternalForm() + bufferedData.substring(end); targetHost = HTTPProxyHost; targetPort = HTTPProxyPort; } } } else { // // Change Host: header to point to correct host // byte[] b1 = new byte[1]; buf = new StringBuffer(); String s1; String lastLine = null; for (; ; ) { int len; len = tmpIn1.read(b1, 0, 1); if (len == -1) { break; } s1 = new String(b1, Charset.defaultCharset() ); buf.append(s1); if (b1[0] != '\n') { continue; } // we have a complete line String line = buf.toString(); buf.setLength(0); // check to see if we have found Host: header if (line.startsWith("Host: ")) { // we need to update the hostname to target host String newHost = "Host: " + targetHost + ":" + listenPort + "\r\n"; bufferedData = bufferedData.concat(newHost); break; } // add it to our headers so far if (bufferedData == null) { bufferedData = line; } else { bufferedData = bufferedData.concat(line); } // failsafe if (line.equals("\r\n")) { break; } if ("\n".equals(lastLine) && line.equals("\n")) { break; } lastLine = line; } if (bufferedData != null) { inputText.append(bufferedData); int idx = (bufferedData.length() < 50) ? bufferedData.length() : 50; s1 = bufferedData.substring(0, idx); int i = s1.indexOf('\n'); if (i > 0) { s1 = s1.substring(0, i - 1); } s1 = s1 + " " + " "; s1 = s1.substring(0, 51); listener.getConnectionData().get(index + 1).setRequest(s1); } } if (targetPort == -1) { targetPort = 80; } outSocket = new Socket(targetHost, targetPort); tmpIn2 = outSocket.getInputStream(); tmpOut2 = outSocket.getOutputStream(); if (bufferedData != null) { byte[] b = bufferedData.getBytes(Charset.defaultCharset()); tmpOut2.write(b); slowLink.pump(b.length); } boolean format = listener.isXmlFormatBox(); // this is the channel to the endpoint rr1 = new SocketRR(this, inSocket, tmpIn1, outSocket, tmpOut2, inputText, format, listener.getConnectionData(), index + 1, "request:", slowLink); // create the response slow link from the inbound slow link SlowLinkSimulator responseLink = new SlowLinkSimulator(slowLink); // this is the channel from the endpoint rr2 = new SocketRR(this, outSocket, tmpIn2, inSocket, tmpOut1, outputText, format, null, 0, "response:", responseLink); while ((rr1 != null) || (rr2 != null)) { if (rr2 != null) { listener.getConnectionData().get(1 + index).setElapsedTime(rr2.getElapsed()); } // Only loop as long as the connection to the target // machine is available - once that's gone we can stop. // The old way, loop until both are closed, left us // looping forever since no one closed the 1st one. if ((null != rr1) && rr1.isDone()) { if ((index >= 0) && (rr2 != null)) { listener.getConnectionData().get(1 + index).setState("Resp"); } rr1 = null; } if ((null != rr2) && rr2.isDone()) { if ((index >= 0) && (rr1 != null)) { listener.getConnectionData().get(1 + index).setState("Req"); } rr2 = null; } synchronized (this) { this.wait(100); // Safety just incase we're not told to wake up. } } active = false; if (index >= 0) { listener.getConnectionData().get(1 + index).setState("Done"); } } catch (RuntimeException e) { throw e; } catch (Exception e) { StringWriter st = new StringWriter(); PrintWriter wr = new PrintWriter(st); int index = listener.getConnections().indexOf(this); if (index >= 0) { listener.getConnectionData().get(1 + index).setState("Error"); } e.printStackTrace(wr); wr.close(); if (outputText != null) { outputText.append(st.toString()); } else { // something went wrong before we had the output area log.error("Something went wring : " + st.toString()); } halt(); } } /** * Connection wakeUp */ synchronized void wakeUp() { this.notifyAll(); } /** * Connection halt */ public void halt() { try { if (rr1 != null) { rr1.halt(); } if (rr2 != null) { rr2.halt(); } if (inSocket != null) { inSocket.close(); } inSocket = null; if (outSocket != null) { outSocket.close(); } outSocket = null; } catch (Exception e) { log.error("Error while closing connection : " + e.getMessage()); } } }