SessionRecorder.java 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. //
  2. // Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved.
  3. //
  4. // This is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This software is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this software; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. // USA.
  18. //
  19. //
  20. // SessionRecorder is a class to write FBS (FrameBuffer Stream) files.
  21. // FBS files are used to save RFB sessions for later playback.
  22. //
  23. import java.io.*;
  24. class SessionRecorder {
  25. protected FileOutputStream f;
  26. protected DataOutputStream df;
  27. protected long startTime, lastTimeOffset;
  28. protected byte[] buffer;
  29. protected int bufferSize;
  30. protected int bufferBytes;
  31. public SessionRecorder(String name, int bufsize) throws IOException {
  32. f = new FileOutputStream(name);
  33. df = new DataOutputStream(f);
  34. startTime = System.currentTimeMillis();
  35. lastTimeOffset = 0;
  36. bufferSize = bufsize;
  37. bufferBytes = 0;
  38. buffer = new byte[bufferSize];
  39. }
  40. public SessionRecorder(String name) throws IOException {
  41. this(name, 65536);
  42. }
  43. //
  44. // Close the file, free resources.
  45. //
  46. public void close() throws IOException {
  47. try {
  48. flush();
  49. } catch (IOException e) {
  50. }
  51. df = null;
  52. f.close();
  53. f = null;
  54. buffer = null;
  55. }
  56. //
  57. // Write the FBS file header as defined in the rfbproxy utility.
  58. //
  59. public void writeHeader() throws IOException {
  60. df.write("FBS 001.000\n".getBytes());
  61. }
  62. //
  63. // Write one byte.
  64. //
  65. public void writeByte(int b) throws IOException {
  66. prepareWriting();
  67. buffer[bufferBytes++] = (byte)b;
  68. }
  69. //
  70. // Write 16-bit value, big-endian.
  71. //
  72. public void writeShortBE(int v) throws IOException {
  73. prepareWriting();
  74. buffer[bufferBytes++] = (byte)(v >> 8);
  75. buffer[bufferBytes++] = (byte)v;
  76. }
  77. //
  78. // Write 32-bit value, big-endian.
  79. //
  80. public void writeIntBE(int v) throws IOException {
  81. prepareWriting();
  82. buffer[bufferBytes] = (byte)(v >> 24);
  83. buffer[bufferBytes + 1] = (byte)(v >> 16);
  84. buffer[bufferBytes + 2] = (byte)(v >> 8);
  85. buffer[bufferBytes + 3] = (byte)v;
  86. bufferBytes += 4;
  87. }
  88. //
  89. // Write 16-bit value, little-endian.
  90. //
  91. public void writeShortLE(int v) throws IOException {
  92. prepareWriting();
  93. buffer[bufferBytes++] = (byte)v;
  94. buffer[bufferBytes++] = (byte)(v >> 8);
  95. }
  96. //
  97. // Write 32-bit value, little-endian.
  98. //
  99. public void writeIntLE(int v) throws IOException {
  100. prepareWriting();
  101. buffer[bufferBytes] = (byte)v;
  102. buffer[bufferBytes + 1] = (byte)(v >> 8);
  103. buffer[bufferBytes + 2] = (byte)(v >> 16);
  104. buffer[bufferBytes + 3] = (byte)(v >> 24);
  105. bufferBytes += 4;
  106. }
  107. //
  108. // Write byte arrays.
  109. //
  110. public void write(byte b[], int off, int len) throws IOException {
  111. prepareWriting();
  112. while (len > 0) {
  113. if (bufferBytes > bufferSize - 4)
  114. flush(false);
  115. int partLen;
  116. if (bufferBytes + len > bufferSize) {
  117. partLen = bufferSize - bufferBytes;
  118. } else {
  119. partLen = len;
  120. }
  121. System.arraycopy(b, off, buffer, bufferBytes, partLen);
  122. bufferBytes += partLen;
  123. off += partLen;
  124. len -= partLen;
  125. }
  126. }
  127. public void write(byte b[]) throws IOException {
  128. write(b, 0, b.length);
  129. }
  130. //
  131. // Flush the output. This method saves buffered data in the
  132. // underlying file object adding data sizes and timestamps. If the
  133. // updateTimeOffset is set to false, then the current time offset
  134. // will not be changed for next write operation.
  135. //
  136. public void flush(boolean updateTimeOffset) throws IOException {
  137. if (bufferBytes > 0) {
  138. df.writeInt(bufferBytes);
  139. df.write(buffer, 0, (bufferBytes + 3) & 0x7FFFFFFC);
  140. df.writeInt((int)lastTimeOffset);
  141. bufferBytes = 0;
  142. if (updateTimeOffset)
  143. lastTimeOffset = -1;
  144. }
  145. }
  146. public void flush() throws IOException {
  147. flush(true);
  148. }
  149. //
  150. // Before writing any data, remember time offset and flush the
  151. // buffer before it becomes full.
  152. //
  153. protected void prepareWriting() throws IOException {
  154. if (lastTimeOffset == -1)
  155. lastTimeOffset = System.currentTimeMillis() - startTime;
  156. if (bufferBytes > bufferSize - 4)
  157. flush(false);
  158. }
  159. }