/*
 * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
 * Please refer to the LICENSE.txt for licensing details.
 */
package ch.ethz.ssh2.channel;

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

import ch.ethz.ssh2.log.Logger;
import ch.ethz.ssh2.util.StringEncoder;

/**
 * RemoteX11AcceptThread.
 *
 * @author Christian Plattner
 * @version $Id: RemoteX11AcceptThread.java 41 2011-06-02 10:36:41Z dkocher@sudo.ch $
 */
public class RemoteX11AcceptThread extends Thread
{
	private static final Logger log = Logger.getLogger(RemoteX11AcceptThread.class);

	Channel c;

	String remoteOriginatorAddress;
	int remoteOriginatorPort;

	Socket s;

	public RemoteX11AcceptThread(Channel c, String remoteOriginatorAddress, int remoteOriginatorPort)
	{
		this.c = c;
		this.remoteOriginatorAddress = remoteOriginatorAddress;
		this.remoteOriginatorPort = remoteOriginatorPort;
	}

	@Override
	public void run()
	{
		try
		{
			/* Send Open Confirmation */

			c.cm.sendOpenConfirmation(c);

			/* Read startup packet from client */

			OutputStream remote_os = c.getStdinStream();
			InputStream remote_is = c.getStdoutStream();

			/* The following code is based on the protocol description given in:
			 * Scheifler/Gettys,
			 * X Windows System: Core and Extension Protocols:
			 * X Version 11, Releases 6 and 6.1 ISBN 1-55558-148-X
			 * (from the ETH library - after being here for almost ten
			 * years one of the few books I borrowed... sad but true =)
			 */

			/*
			 * Client startup:
			 * 
			 * 1 0X42 MSB first/0x6c lSB first - byteorder
			 * 1 - unused
			 * 2 card16 - protocol-major-version
			 * 2 card16 - protocol-minor-version
			 * 2 n - lenght of authorization-protocol-name
			 * 2 d - lenght of authorization-protocol-data
			 * 2 - unused
			 * string8 - authorization-protocol-name
			 * p - unused, p=pad(n)
			 * string8 - authorization-protocol-data
			 * q - unused, q=pad(d)
			 * 
			 * pad(X) = (4 - (X mod 4)) mod 4
			 * 
			 * Server response:
			 * 
			 * 1 (0 failed, 2 authenticate, 1 success)
			 * ...
			 * 
			 */

			/* Later on we will simply forward the first 6 header bytes to the "real" X11 server */

			byte[] header = new byte[6];

			if (remote_is.read(header) != 6)
				throw new IOException("Unexpected EOF on X11 startup!");

			if ((header[0] != 0x42) && (header[0] != 0x6c)) // 0x42 MSB first, 0x6C LSB first
				throw new IOException("Unknown endian format in X11 message!");

			/* Yes, I came up with this myself - shall I file an application for a patent? =) */

			int idxMSB = (header[0] == 0x42) ? 0 : 1;

			/* Read authorization data header */

			byte[] auth_buff = new byte[6];

			if (remote_is.read(auth_buff) != 6)
				throw new IOException("Unexpected EOF on X11 startup!");

			int authProtocolNameLength = ((auth_buff[idxMSB] & 0xff) << 8) | (auth_buff[1 - idxMSB] & 0xff);
			int authProtocolDataLength = ((auth_buff[2 + idxMSB] & 0xff) << 8) | (auth_buff[3 - idxMSB] & 0xff);

			if ((authProtocolNameLength > 256) || (authProtocolDataLength > 256))
				throw new IOException("Buggy X11 authorization data");

			int authProtocolNamePadding = ((4 - (authProtocolNameLength % 4)) % 4);
			int authProtocolDataPadding = ((4 - (authProtocolDataLength % 4)) % 4);

			byte[] authProtocolName = new byte[authProtocolNameLength];
			byte[] authProtocolData = new byte[authProtocolDataLength];

			byte[] paddingBuffer = new byte[4];

			if (remote_is.read(authProtocolName) != authProtocolNameLength)
				throw new IOException("Unexpected EOF on X11 startup! (authProtocolName)");

			if (remote_is.read(paddingBuffer, 0, authProtocolNamePadding) != authProtocolNamePadding)
				throw new IOException("Unexpected EOF on X11 startup! (authProtocolNamePadding)");

			if (remote_is.read(authProtocolData) != authProtocolDataLength)
				throw new IOException("Unexpected EOF on X11 startup! (authProtocolData)");

			if (remote_is.read(paddingBuffer, 0, authProtocolDataPadding) != authProtocolDataPadding)
				throw new IOException("Unexpected EOF on X11 startup! (authProtocolDataPadding)");

			if ("MIT-MAGIC-COOKIE-1".equals(StringEncoder.GetString(authProtocolName)) == false)
				throw new IOException("Unknown X11 authorization protocol!");

			if (authProtocolDataLength != 16)
				throw new IOException("Wrong data length for X11 authorization data!");

			StringBuilder tmp = new StringBuilder(32);
			for (int i = 0; i < authProtocolData.length; i++)
			{
				String digit2 = Integer.toHexString(authProtocolData[i] & 0xff);
				tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2);
			}
			String hexEncodedFakeCookie = tmp.toString();

			/* Order is very important here - it may be that a certain x11 forwarding
			 * gets disabled right in the moment when we check and register our connection
			 * */

			synchronized (c)
			{
				/* Please read the comment in Channel.java */
				c.hexX11FakeCookie = hexEncodedFakeCookie;
			}

			/* Now check our fake cookie directory to see if we produced this cookie */

			X11ServerData sd = c.cm.checkX11Cookie(hexEncodedFakeCookie);

			if (sd == null)
				throw new IOException("Invalid X11 cookie received.");

			/* If the session which corresponds to this cookie is closed then we will
			 * detect this: the session's close code will close all channels
			 * with the session's assigned x11 fake cookie.
			 */

			s = new Socket(sd.hostname, sd.port);

			OutputStream x11_os = s.getOutputStream();
			InputStream x11_is = s.getInputStream();

			/* Now we are sending the startup packet to the real X11 server */

			x11_os.write(header);

			if (sd.x11_magic_cookie == null)
			{
				byte[] emptyAuthData = new byte[6];
				/* empty auth data, hopefully you are connecting to localhost =) */
				x11_os.write(emptyAuthData);
			}
			else
			{
				if (sd.x11_magic_cookie.length != 16)
					throw new IOException("The real X11 cookie has an invalid length!");

				/* send X11 cookie specified by client */
				x11_os.write(auth_buff);
				x11_os.write(authProtocolName); /* re-use */
				x11_os.write(paddingBuffer, 0, authProtocolNamePadding);
				x11_os.write(sd.x11_magic_cookie);
				x11_os.write(paddingBuffer, 0, authProtocolDataPadding);
			}

			x11_os.flush();

			/* Start forwarding traffic */

			StreamForwarder r2l = new StreamForwarder(c, null, null, remote_is, x11_os, "RemoteToX11");
			StreamForwarder l2r = new StreamForwarder(c, null, null, x11_is, remote_os, "X11ToRemote");

			/* No need to start two threads, one can be executed in the current thread */

			r2l.setDaemon(true);
			r2l.start();
			l2r.run();

			while (r2l.isAlive())
			{
				try
				{
					r2l.join();
				}
				catch (InterruptedException ignored)
				{
				}
			}

			/* If the channel is already closed, then this is a no-op */

			c.cm.closeChannel(c, "EOF on both X11 streams reached.", true);
			s.close();
		}
		catch (IOException e)
		{
			log.warning("IOException in X11 proxy code: " + e.getMessage());

			try
			{
				c.cm.closeChannel(c, "IOException in X11 proxy code (" + e.getMessage() + ")", true);
			}
			catch (IOException ignored)
			{
			}
			try
			{
				if (s != null)
					s.close();
			}
			catch (IOException ignored)
			{
			}
		}
	}
}
