You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
4.6 KiB
194 lines
4.6 KiB
18 years ago
|
//
|
||
|
// Copyright (C) 2002 Constantin Kaplinsky. 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.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// SessionRecorder is a class to write FBS (FrameBuffer Stream) files.
|
||
|
// FBS files are used to save RFB sessions for later playback.
|
||
|
//
|
||
|
|
||
|
import java.io.*;
|
||
|
|
||
|
class SessionRecorder {
|
||
|
|
||
|
protected FileOutputStream f;
|
||
|
protected DataOutputStream df;
|
||
|
protected long startTime, lastTimeOffset;
|
||
|
|
||
|
protected byte[] buffer;
|
||
|
protected int bufferSize;
|
||
|
protected int bufferBytes;
|
||
|
|
||
|
public SessionRecorder(String name, int bufsize) throws IOException {
|
||
|
f = new FileOutputStream(name);
|
||
|
df = new DataOutputStream(f);
|
||
|
startTime = System.currentTimeMillis();
|
||
|
lastTimeOffset = 0;
|
||
|
|
||
|
bufferSize = bufsize;
|
||
|
bufferBytes = 0;
|
||
|
buffer = new byte[bufferSize];
|
||
|
}
|
||
|
|
||
|
public SessionRecorder(String name) throws IOException {
|
||
|
this(name, 65536);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Close the file, free resources.
|
||
|
//
|
||
|
|
||
|
public void close() throws IOException {
|
||
|
try {
|
||
|
flush();
|
||
|
} catch (IOException e) {
|
||
|
}
|
||
|
|
||
|
df = null;
|
||
|
f.close();
|
||
|
f = null;
|
||
|
buffer = null;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write the FBS file header as defined in the rfbproxy utility.
|
||
|
//
|
||
|
|
||
|
public void writeHeader() throws IOException {
|
||
|
df.write("FBS 001.000\n".getBytes());
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write one byte.
|
||
|
//
|
||
|
|
||
|
public void writeByte(int b) throws IOException {
|
||
|
prepareWriting();
|
||
|
buffer[bufferBytes++] = (byte)b;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write 16-bit value, big-endian.
|
||
|
//
|
||
|
|
||
|
public void writeShortBE(int v) throws IOException {
|
||
|
prepareWriting();
|
||
|
buffer[bufferBytes++] = (byte)(v >> 8);
|
||
|
buffer[bufferBytes++] = (byte)v;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write 32-bit value, big-endian.
|
||
|
//
|
||
|
|
||
|
public void writeIntBE(int v) throws IOException {
|
||
|
prepareWriting();
|
||
|
buffer[bufferBytes] = (byte)(v >> 24);
|
||
|
buffer[bufferBytes + 1] = (byte)(v >> 16);
|
||
|
buffer[bufferBytes + 2] = (byte)(v >> 8);
|
||
|
buffer[bufferBytes + 3] = (byte)v;
|
||
|
bufferBytes += 4;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write 16-bit value, little-endian.
|
||
|
//
|
||
|
|
||
|
public void writeShortLE(int v) throws IOException {
|
||
|
prepareWriting();
|
||
|
buffer[bufferBytes++] = (byte)v;
|
||
|
buffer[bufferBytes++] = (byte)(v >> 8);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write 32-bit value, little-endian.
|
||
|
//
|
||
|
|
||
|
public void writeIntLE(int v) throws IOException {
|
||
|
prepareWriting();
|
||
|
buffer[bufferBytes] = (byte)v;
|
||
|
buffer[bufferBytes + 1] = (byte)(v >> 8);
|
||
|
buffer[bufferBytes + 2] = (byte)(v >> 16);
|
||
|
buffer[bufferBytes + 3] = (byte)(v >> 24);
|
||
|
bufferBytes += 4;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write byte arrays.
|
||
|
//
|
||
|
|
||
|
public void write(byte b[], int off, int len) throws IOException {
|
||
|
prepareWriting();
|
||
|
while (len > 0) {
|
||
|
if (bufferBytes > bufferSize - 4)
|
||
|
flush(false);
|
||
|
|
||
|
int partLen;
|
||
|
if (bufferBytes + len > bufferSize) {
|
||
|
partLen = bufferSize - bufferBytes;
|
||
|
} else {
|
||
|
partLen = len;
|
||
|
}
|
||
|
System.arraycopy(b, off, buffer, bufferBytes, partLen);
|
||
|
bufferBytes += partLen;
|
||
|
off += partLen;
|
||
|
len -= partLen;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void write(byte b[]) throws IOException {
|
||
|
write(b, 0, b.length);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Flush the output. This method saves buffered data in the
|
||
|
// underlying file object adding data sizes and timestamps. If the
|
||
|
// updateTimeOffset is set to false, then the current time offset
|
||
|
// will not be changed for next write operation.
|
||
|
//
|
||
|
|
||
|
public void flush(boolean updateTimeOffset) throws IOException {
|
||
|
if (bufferBytes > 0) {
|
||
|
df.writeInt(bufferBytes);
|
||
|
df.write(buffer, 0, (bufferBytes + 3) & 0x7FFFFFFC);
|
||
|
df.writeInt((int)lastTimeOffset);
|
||
|
bufferBytes = 0;
|
||
|
if (updateTimeOffset)
|
||
|
lastTimeOffset = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void flush() throws IOException {
|
||
|
flush(true);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Before writing any data, remember time offset and flush the
|
||
|
// buffer before it becomes full.
|
||
|
//
|
||
|
|
||
|
protected void prepareWriting() throws IOException {
|
||
|
if (lastTimeOffset == -1)
|
||
|
lastTimeOffset = System.currentTimeMillis() - startTime;
|
||
|
if (bufferBytes > bufferSize - 4)
|
||
|
flush(false);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|