⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfbproto.java

📁 teamviewer source code vc++
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
//  Copyright (C) 2006 Teamviewer GmbH.  All Rights Reserved.
//  Copyright (C) 2002-2004 Ultr@VNC Team.  All Rights Reserved.
//  Copyright (C) 2004 Kenn Min Chong, John Witchel.  All Rights Reserved.
//  Copyright (C) 2001,2002 HorizonLive.com, Inc.  All Rights Reserved.
//  Copyright (C) 2001,2002 Constantin Kaplinsky.  All Rights Reserved.
//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
//  Copyright (C) 2003 Helmut Eller <helmut@online-marketwatch.com>
//
//  This is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This software is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this software; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
//  USA.
//

//
// RfbProto.java
//4/19/04

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.zip.*;

class TunnelReader extends InputStream {
    URL url;
    InputStream tunnel;

    TunnelReader (URL url) throws IOException {
	this.url = url;
	this.tunnel = connect (url);
    }
    
    InputStream getInputStream () throws IOException {
	return this;
	// return connect (url);
    }

    private final static void trace (String string) {
	// System.err.println ("Reader: " + string);
    }
    
    InputStream connect (URL url) throws IOException {
	trace ("connect");
	URLConnection get = url.openConnection();
	get.setDoOutput (false);
	get.setDoInput (true);
	get.setUseCaches (false);	
	get.setRequestProperty("X-Agent","DynGate");
	get.connect ();
	return get.getInputStream ();
    }

    void reconnect () throws IOException {
	tunnel = connect (url);
    }

    synchronized public int read () throws IOException {
	trace ("read");
	for (;;) {
	    int n = tunnel.read ();
	    if (n >= 0) {
		// trace ("read: " + " -> " + n);
		return n;
	    } else 
		reconnect ();
	}
    }
    
    synchronized public int read (byte[] bytes) throws IOException  {
	trace ("read");
	for (;;) {
	    int n = tunnel.read (bytes);
	    if (n >= 0) {
		// trace ("read: " + " -> " + n);
		return n;
	    } else 
		reconnect ();
	}
    }

    synchronized public int read (byte[] bytes, int offset, int length) 
	throws IOException {
	trace ("read");
	for (;;) {
	    int n = tunnel.read (bytes, offset, length);
	    if (n >= 0) {
		// trace ("read: " + " -> " + n);
		return n;
	    } else 
		reconnect ();
	}
    }

    public long skip (long n) throws IOException {
	trace ("skip ...");
	return tunnel.skip (n);
    }

    synchronized public int available () throws IOException {
	trace ("available");
	int n = tunnel.available ();
	// trace ("available: -> " + n);
	return n;
    }
    
    public void close () throws IOException {
	trace ("Reader close ...");
	tunnel.close ();
	tunnel = null;
	url = null;
    }
    
    public void mark (int readlimit) {
	trace ("Reader mark ...");
	tunnel.mark (readlimit);
    }
    
    public void reset () throws IOException {
	trace ("Reader reset ...");
	tunnel.reset ();
    }

    public boolean markSupported () {
	trace ("markSupported ...");
	return tunnel.markSupported ();
    }
}

class TunnelWriter extends OutputStream {
    URL url;
    URLConnection post;
    OutputStream out;

    TunnelWriter (URL url) throws IOException {
	this.url = url;
	// connect ();
    }

    OutputStream getOutputStream () {
	return this;
    }

    private final static void trace (String string) {
	// System.err.println ("Writer: " + string);
    }
    
    void connect () throws IOException {
	trace ("connect");
	URLConnection post = url.openConnection();
	post.setDoOutput (true);
	post.setDoInput (true);
	post.setUseCaches (false);
	post.setRequestProperty("X-Agent","DynGate");
	out = post.getOutputStream ();
	this.post = post;
    }

    void forceOutput () throws IOException {
	trace ("flush");
	out.flush ();
	out.close ();
	InputStream in = post.getInputStream ();
	// Commented code is for crappy Netscape4.
	try { 
	    int b = in.read ();  // needed for Explorer
	    // trace ("read -> 1 [" + b + "]");
	    // in.close ();
	} catch (Exception e) {
	    // e.printStackTrace ();
	    // System.err.println (e.getMessage ());
	}
    }
    
    synchronized public void flush () throws IOException {
	forceOutput ();
    }

    synchronized public void write (int b) throws IOException  {
	trace ("write");
	connect ();
	out.write (b);
	forceOutput ();
	// trace ("write <- 1");
    }

    synchronized public void write (byte[] b) throws IOException {
	trace ("write");
	connect ();
	out.write (b);
	forceOutput ();
	// trace ("write <- " + b.length);
    }

    synchronized public void write (byte[] b, int offset, int length) 
	throws IOException {
	trace ("write");
	connect ();
	out.write (b, offset, length);
	forceOutput ();
	// trace ("write <- " + length);
    }
    
    public void close () throws IOException {
	trace ("close");
	flush ();
	post = null;
	out = null;
    }
}

class RfbProto {

 	final String versionMsg = "RFB 003.003\n";
	final static int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
	final static int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;

	final static int FramebufferUpdate = 0,
		SetColourMapEntries = 1,
		Bell = 2,
		ServerCutText = 3,
		rfbFileTransfer = 7;

	final int SetPixelFormat = 0,
		FixColourMapEntries = 1,
		SetEncodings = 2,
		FramebufferUpdateRequest = 3,
		KeyboardEvent = 4,
		PointerEvent = 5,
		ClientCutText = 6;

	final static int EncodingRaw = 0,
		EncodingCopyRect = 1,
		EncodingRRE = 2,
		EncodingCoRRE = 4,
		EncodingHextile = 5,
		EncodingZlib = 6,
		EncodingTight = 7,
		EncodingCompressLevel0 = 0xFFFFFF00,
		EncodingQualityLevel0 = 0xFFFFFFE0,
		EncodingXCursor = 0xFFFFFF10,
		EncodingRichCursor = 0xFFFFFF11,
		EncodingLastRect = 0xFFFFFF20,
		EncodingNewFBSize = 0xFFFFFF21;

	final int HextileRaw = (1 << 0);
	final int HextileBackgroundSpecified = (1 << 1);
	final int HextileForegroundSpecified = (1 << 2);
	final int HextileAnySubrects = (1 << 3);
	final int HextileSubrectsColoured = (1 << 4);

	final static int TightExplicitFilter = 0x04;
	final static int TightFill = 0x08;
	final static int TightJpeg = 0x09;
	final static int TightMaxSubencoding = 0x09;
	final static int TightFilterCopy = 0x00;
	final static int TightFilterPalette = 0x01;
	final static int TightFilterGradient = 0x02;

	final static int TightMinToCompress = 12;

	// sf@2004 - FileTransfer part
	ArrayList remoteDirsList;
	ArrayList remoteFilesList;
	ArrayList a;
	boolean fFTInit = true; // sf@2004
	boolean fFTAllowed = true;
	boolean fAbort = false;
	boolean fFileReceptionError = false;
	boolean fFileReceptionRunning = false;
	boolean inDirectory2;
	FileOutputStream fos;
	FileInputStream fis;
	String sendFileSource;
	String receivePath;
	long fileSize;
	long receiveFileSize;
	long fileChunkCounter;

	final static int sz_rfbFileTransferMsg = 12,
	// FileTransfer Content types and Params defines
	rfbDirContentRequest = 1,
	// Client asks for the content of a given Server directory
	rfbDirPacket = 2, // Full directory name or full file name.
	// Null content means end of Directory
	rfbFileTransferRequest = 3,
	// Client asks the server for the tranfer of a given file
	rfbFileHeader = 4,
	// First packet of a file transfer, containing file's features
	rfbFilePacket = 5, // One slice of the file
	rfbEndOfFile = 6,
	// End of file transfer (the file has been received or error)
	rfbAbortFileTransfer = 7,
	// The file transfer must be aborted, whatever the state
	rfbFileTransferOffer = 8,
	// The client offers to send a file to the server
	rfbFileAcceptHeader = 9, // The server accepts or rejects the file
	rfbCommand = 10,
	// The Client sends a simple command (File Delete, Dir create etc...)
	rfbCommandReturn = 11,
	//	New FT Protocole (V2) The zipped checksums of the destination file (Delta Transfer)
	rfbFileChecksums = 12,
	// The Client receives the server's answer about a simple command
	// rfbDirContentRequest client Request - content params 
	rfbRDirContent = 1, // Request a Server Directory contents
	rfbRDrivesList = 2, // Request the server's drives list
	
	// rfbDirPacket & rfbCommandReturn  server Answer - content params
	rfbADirectory = 1, // Reception of a directory name
	rfbAFile = 2, // Reception of a file name 
	rfbADrivesList = 3, // Reception of a list of drives
	rfbADirCreate = 4, // Response to a create dir command 
	rfbADirDelete = 5, // Response to a delete dir command 
	rfbAFileCreate = 6, // Response to a create file command 
	rfbAFileDelete = 7, // Response to a delete file command
	
	// rfbCommand Command - content params
	rfbCDirCreate = 1, // Request the server to create the given directory
	rfbCDirDelete = 2, // Request the server to delete the given directory
	rfbCFileCreate = 3, // Request the server to create the given file
	rfbCFileDelete = 4, // Request the server to delete the given file
	
	// Errors - content params or "size" field
	rfbRErrorUnknownCmd = 1, // Unknown FileTransfer command.
	rfbRErrorCmd = 0xFFFFFFFF,
	
	// Error when a command fails on remote side (ret in "size" field)
	sz_rfbBlockSize = 8192, // new FT protocole (v2)
	
	// Size of a File Transfer packet (before compression)
	sz_rfbZipDirectoryPrefix = 9;

	String rfbZipDirectoryPrefix = "!UVNCDIR-\0";
	// Transfered directory are zipped in a file with this prefix. Must end with "-"
	
	// End of FileTransfer part 
	
	String host;
	int port;
	Socket sock;
	DataInputStream is;
	OutputStream os;
	OutputStreamWriter osw;

	SessionRecorder rec;
	boolean inNormalProtocol = false;
	VncViewer viewer;

	// Java on UNIX does not call keyPressed() on some keys, for example
	// swedish keys To prevent our workaround to produce duplicate
	// keypresses on JVMs that actually works, keep track of if
	// keyPressed() for a "broken" key was called or not. 
	boolean brokenKeyPressed = false;

	// This will be set to true on the first framebuffer update
	// containing Zlib- or Tight-encoded data.
	boolean wereZlibUpdates = false;

	// This will be set to false if the startSession() was called after
	// we have received at least one Zlib- or Tight-encoded framebuffer
	// update.
	boolean recordFromBeginning = true;

	// This fields are needed to show warnings about inefficiently saved
	// sessions only once per each saved session file.
	boolean zlibWarningShown;
	boolean tightWarningShown;

	// Before starting to record each saved session, we set this field
	// to 0, and increment on each framebuffer update. We don't flush
	// the SessionRecorder data into the file before the second update. 
	// This allows us to write initial framebuffer update with zero
	// timestamp, to let the player show initial desktop before
	// playback.
	int numUpdatesInSession;



    int makeSessionIDRequest (URL url) throws IOException {
	URLConnection c = url.openConnection();
	System.err.println ("UrlConnection.class: " 
			    + c.getClass ());
	c.setDoInput (true);
	c.setUseCaches (false);
	c.connect ();
	InputStream in = c.getInputStream ();
	byte[] headdata = new byte[2];
	int count = in.read (headdata);

	byte[] buffer = new byte[8];	
	count = in.read (buffer);
	System.err.println ("buffer: <<" 
			    + new String (buffer) + ">>");
	if (count != 8)
	    throw new IOException ("Couldn't read session id.");
	int id = (buffer[0] - 48) * 10000000
			+ (buffer[1] - 48) * 1000000
			+ (buffer[2] - 48) * 100000
			+ (buffer[3] - 48) * 10000
			+ (buffer[4] - 48) * 1000
			+ (buffer[5] - 48) * 100
			+ (buffer[6] - 48) * 10
			+ (buffer[7] - 48);
	System.err.println ("session-id: " + id);
	return id;
    }

    int getSessionID (URL url) throws IOException {
	final int OPEN_STATE_PENDING = 1;
	final int OPEN_STATE_OK = 2;
	final int OPEN_STATE_FAILED = 3;
	class Opener extends Thread  {
	    URL url;
	    int id;
	    IOException error;
	    int openState = OPEN_STATE_PENDING;
	    Opener (URL u) { url = u ;}
	    public void run () {
		synchronized (this) {
		    try {
			id = makeSessionIDRequest (url);
			openState = OPEN_STATE_OK;
		    } catch (IOException e) {
			error = e;
			openState = OPEN_STATE_FAILED;
		    }
		    this.notifyAll ();
		}
	    }
	}
	Opener o = new Opener (url);
	o.start ();
	synchronized (o) {
	    long end = System.currentTimeMillis () + (15 * 1000);
	    do {
		try { o.wait (end - System.currentTimeMillis ()); } 
		catch (InterruptedException e) {}
	    } while (o.openState == OPEN_STATE_PENDING
		     && ((end - System.currentTimeMillis ()) > 0));
	    switch (o.openState)  {
	    case OPEN_STATE_PENDING: throw new IOException ("timeout");
	    case OPEN_STATE_FAILED: throw o.error;
	    case OPEN_STATE_OK: return o.id;
	    default: throw new Error ("Bug");
	    }
	}
    }
	
    void initHttp (String host, int port, int DynGateID) 
	throws IOException {
		int sid = 0;
		try
		{
			sid = getSessionID (new URL ("http", host, port,"/din.aspx?s=00000000&client=DynGate"));		
		} catch (IOException e) {
			System.err.println ("Tunnel-connection failed: "
					+ e.getMessage () + "\n");
			throw e;
		}
		URL wurl = new URL("http", host, port, "/dout.aspx?s=" + sid + "&client=DynGate");
		URL rurl = new URL("http", host, port, "/din.aspx?s=" + sid + "&client=DynGate");
	
		os = new TunnelWriter (wurl).getOutputStream();
		is = new DataInputStream 
			(new BufferedInputStream 
			(new TunnelReader (rurl).getInputStream (),
			 16384));
    }

    void initTcp (String host, int port) throws IOException {
	sock = new Socket (host, port);
	is = new DataInputStream 
	    (new BufferedInputStream (sock.getInputStream (),
				      16384));
	os = sock.getOutputStream ();
    }

    // Constructor. Make a TCP connection to the RFB server.
    RfbProto(String h, int p, VncViewer v) throws IOException {
	viewer = v;
	host = h;
	port = p;
	initTcp (h, p);
    }

    /* Try to establish a direct TCP socket connection to port p.  If
       that fails, fallback to a HTTP-tunnel to port tunnelPort.  p ==
       -1 enforces HTTP-tunneling. */
    RfbProto(String h, int p, int tunnelPort, int DynGateID, VncViewer v)
	throws IOException {
	viewer = v;
	host = h;
	port = p;
	if (port == -1) 
	    initHttp (h, tunnelPort, DynGateID);
	else 
	    try {
		initTcp (h, p);
	    } catch (Exception e) {
		System.err.println ("Socket-connection failed: " 
				    + e.getMessage () + "\n"
				    + "Trying HTTP tunnel...");
		initHttp (h, tunnelPort, DynGateID);
	    }
		//Dump DynGate init header
		byte[] inbuf = new byte[25];
		is.readFully(inbuf);
	
		//Send our connection-request
		byte[] auth = new byte[9];
		auth[0] = 23;
		auth[1] = 36;
		auth[2] = 26;
		auth[3] = 4;
		auth[4] = 0;
		auth[5] = (byte)(DynGateID);
		auth[6] = (byte)(DynGateID >> 8);
		auth[7] = (byte)(DynGateID >> 16);
		auth[8] = (byte)(DynGateID >> 24);
		os.write(auth);
		os.flush();
    }

    void close() {
	try {
	    if (sock != null)
			sock.close();
	    if (rec != null) {
			rec.close();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -