📄 rfbproto.java
字号:
//
// 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
//
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.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;
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;
String host;
int port;
Socket sock;
DataInputStream is;
OutputStream os;
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();
//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();
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 (),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -