?? rfbproto.java
字號:
// 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.
//
// 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.util.*;
import java.util.zip.*;
class RfbProto {
final String versionMsg = "RFB 003.003\n";
final static int ConnFailed = 0, NoAuth = 1, VncAuth = 2, MsLogon = 0xfffffffa;
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,
EncodingPointerPos = 0xFFFFFF18, // marscha - PointerPos
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;
//
// Constructor. Make TCP connection to RFB server.
//
RfbProto(String h, int p, VncViewer v) throws IOException {
viewer = v;
host = h;
port = p;
sock = new Socket(host, port);
is =
new DataInputStream(
new BufferedInputStream(sock.getInputStream(), 16384));
os = sock.getOutputStream();
osw = new OutputStreamWriter(sock.getOutputStream());
inDirectory2 = false;
a = new ArrayList();
// sf@2004
remoteDirsList = new ArrayList();
remoteFilesList = new ArrayList();
sendFileSource = "";
}
void close() {
try {
sock.close();
if (rec != null) {
rec.close();
rec = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
//
// Read server's protocol version message
//
int serverMajor, serverMinor;
void readVersionMsg() throws Exception {
byte[] b = new byte[12];
is.readFully(b);
if ((b[0] != 'R')
|| (b[1] != 'F')
|| (b[2] != 'B')
|| (b[3] != ' ')
|| (b[4] < '0')
|| (b[4] > '9')
|| (b[5] < '0')
|| (b[5] > '9')
|| (b[6] < '0')
|| (b[6] > '9')
|| (b[7] != '.')
|| (b[8] < '0')
|| (b[8] > '9')
|| (b[9] < '0')
|| (b[9] > '9')
|| (b[10] < '0')
|| (b[10] > '9')
|| (b[11] != '\n')) {
throw new Exception(
"Host " + host + " port " + port + " is not an RFB server");
}
serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
}
//
// Write our protocol version message
//
void writeVersionMsg() throws IOException {
os.write(versionMsg.getBytes());
}
//
// Find out the authentication scheme.
//
int readAuthScheme() throws Exception {
int authScheme = is.readInt();
switch (authScheme) {
case ConnFailed :
int reasonLen = is.readInt();
byte[] reason = new byte[reasonLen];
is.readFully(reason);
throw new Exception(new String(reason));
case NoAuth :
case VncAuth :
case MsLogon:
return authScheme;
default :
throw new Exception(
"Unknown authentication scheme from RFB server: "
+ authScheme);
}
}
//
// Write the client initialisation message
//
void writeClientInit() throws IOException {
if (viewer.options.shareDesktop) {
os.write(1);
} else {
os.write(0);
}
viewer.options.disableShareDesktop();
}
//
// Read the server initialisation message
//
String desktopName;
int framebufferWidth, framebufferHeight;
int bitsPerPixel, depth;
boolean bigEndian, trueColour;
int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
void readServerInit() throws IOException {
framebufferWidth = is.readUnsignedShort();
framebufferHeight = is.readUnsignedShort();
bitsPerPixel = is.readUnsignedByte();
depth = is.readUnsignedByte();
bigEndian = (is.readUnsignedByte() != 0);
trueColour = (is.readUnsignedByte() != 0);
redMax = is.readUnsignedShort();
greenMax = is.readUnsignedShort();
blueMax = is.readUnsignedShort();
redShift = is.readUnsignedByte();
greenShift = is.readUnsignedByte();
blueShift = is.readUnsignedByte();
byte[] pad = new byte[3];
is.readFully(pad);
int nameLength = is.readInt();
byte[] name = new byte[nameLength];
is.readFully(name);
desktopName = new String(name);
inNormalProtocol = true;
}
//
// Create session file and write initial protocol messages into it.
//
void startSession(String fname) throws IOException {
rec = new SessionRecorder(fname);
rec.writeHeader();
rec.write(versionMsg.getBytes());
rec.writeIntBE(NoAuth);
rec.writeShortBE(framebufferWidth);
rec.writeShortBE(framebufferHeight);
byte[] fbsServerInitMsg =
{
32,
24,
0,
1,
0,
(byte) 0xFF,
0,
(byte) 0xFF,
0,
(byte) 0xFF,
16,
8,
0,
0,
0,
0 };
rec.write(fbsServerInitMsg);
rec.writeIntBE(desktopName.length());
rec.write(desktopName.getBytes());
numUpdatesInSession = 0;
if (wereZlibUpdates)
recordFromBeginning = false;
zlibWarningShown = false;
tightWarningShown = false;
}
//
// Close session file.
//
void closeSession() throws IOException {
if (rec != null) {
rec.close();
rec = null;
}
}
//
// Set new framebuffer size
//
void setFramebufferSize(int width, int height) {
framebufferWidth = width;
framebufferHeight = height;
}
//
// Read the server message type
//
int readServerMessageType() throws IOException {
int msgType = is.readUnsignedByte();
// If the session is being recorded:
if (rec != null) {
if (msgType == Bell) { // Save Bell messages in session files.
rec.writeByte(msgType);
if (numUpdatesInSession > 0)
rec.flush();
}
}
return msgType;
}
//
// Read a FramebufferUpdate message
//
int updateNRects;
void readFramebufferUpdate() throws IOException {
is.readByte();
updateNRects = is.readUnsignedShort();
// If the session is being recorded:
if (rec != null) {
rec.writeByte(FramebufferUpdate);
rec.writeByte(0);
rec.writeShortBE(updateNRects);
}
numUpdatesInSession++;
}
// Read a FramebufferUpdate rectangle header
int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
void readFramebufferUpdateRectHdr() throws Exception {
updateRectX = is.readUnsignedShort();
updateRectY = is.readUnsignedShort();
updateRectW = is.readUnsignedShort();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -