package net.bakingpowder.jspl.tcprelay.distributed.recieveRelay;

import java.net.Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

/**
 * @author Tomoo D. Mizukami/JAIST/Softbank Publishing Inc.
 * 
 * This Class is a multi thread class for controling trafic between
 * InputStream/OutputStream and buffer-interchange-function
 */
public class RecieveConnectControl implements Runnable {
	private boolean connectionClosed = false;
	private InputStream destIn, srcIn;
	private OutputStream srcOut, destOut;

	private RecieveInput2Output src2dst, dst2src;
	private Socket srcSocket, destSocket;

	private String destHost;
	private int destPort;
	

	public RecieveConnectControl(Socket ss) {
		srcSocket = ss;

		try {
			srcIn = ss.getInputStream();
			srcOut = ss.getOutputStream();
			
			int destAddressLength;
			byte[] destAddressByte;
			destAddressByte = new byte[30];
			
			destAddressLength = srcIn.read();
			srcIn.read(destAddressByte,0,destAddressLength);
			destHost = new String(destAddressByte);
			destHost = destHost.substring(0,destAddressLength);
			
			int destPortLength;
			byte[] destPortByte;
			destPortByte = new byte[6];
			
			destPortLength = srcIn.read();
			srcIn.read(destPortByte,0,destPortLength);
			String destPortString = new String(destPortByte);
			destPortString = destPortString.substring(0,destPortLength);
			destPort = Integer.parseInt(destPortString);
			

			System.out.println("Address:" + destHost);
			System.out.println("Port:" + destPort);
			
			
			Socket ds = new Socket(destHost,destPort);

			
			destIn = ds.getInputStream();
			destOut = ds.getOutputStream();

			
			Thread t = new Thread(this);
			t.start();
		} catch (IOException e) {
			System.err.println("[Proxy Connection Error]");
			e.printStackTrace();
		} catch (java.lang.StringIndexOutOfBoundsException e) {
			this.errOr = true;
			this.closeSrc();
		}
	}

	private boolean errOr = false;
	
	
	public synchronized void ThreadArrivedEnd(RecieveInput2Output a) {
		if (connectionClosed)
			return;

		this.closeSrc();
		this.closeDest();

		connectionClosed = true;
	}

	private void closeDest() {
		try {
			destIn.close();
			destOut.close();
			destSocket.close();
		} catch (Exception e) {
		}
	}

	private void closeSrc() {
		try {
			srcIn.close();
			srcOut.close();
			srcSocket.close();
		} catch (Exception e) {
		}
	}

	public void stopd() {
		if (src2dst == null) {
			src2dst.stopd();
		}
		if (dst2src == null) {
			dst2src.stopd();
		}
	}

	public void run() {
		if (!this.errOr){
				src2dst = new RecieveInput2Output(srcIn, destOut, this);
				dst2src = new RecieveInput2Output(destIn, srcOut, this);
		}
	}
}