Advertisement
Chiddix

BufferedConnection

Jun 13th, 2013
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.65 KB | None | 0 0
  1. package com.runescape.net;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.OutputStream;
  6. import java.net.Socket;
  7.  
  8. import com.runescape.GameShell;
  9.  
  10. /**
  11.  *
  12.  * @author Ryan Greene
  13.  *
  14.  */
  15. public class BufferedConnection implements Runnable {
  16.  
  17.     /**
  18.      * The input stream.
  19.      */
  20.     public InputStream inputStream;
  21.    
  22.     /**
  23.      * The output stream.
  24.      */
  25.     public OutputStream outputStream;
  26.    
  27.     /**
  28.      * The socket.
  29.      */
  30.     public Socket socket;
  31.    
  32.     /**
  33.      * The closing flag.
  34.      */
  35.     public boolean closing;
  36.    
  37.     /**
  38.      * The game shell.
  39.      */
  40.     public GameShell gameShell;
  41.    
  42.     /**
  43.      * The buffer.
  44.      */
  45.     public byte buffer[];
  46.    
  47.     /**
  48.      * The t cycle.
  49.      */
  50.     public int tcycl;
  51.    
  52.     /**
  53.      * The t number.
  54.      */
  55.     public int tnum;
  56.    
  57.     /**
  58.      * The writer flag.
  59.      */
  60.     public boolean writer;
  61.    
  62.     /**
  63.      * The writing flag.
  64.      */
  65.     public boolean writing;
  66.  
  67.     /**
  68.      * Creates a new buffered connection with the specified socket and game
  69.      * shell.
  70.      *
  71.      * @param socket
  72.      *            The socket.
  73.      * @param gameShell
  74.      *            The game shell.
  75.      * @throws IOException
  76.      *             If an I/O error occurs.
  77.      */
  78.     public BufferedConnection(Socket socket, GameShell gameShell)
  79.             throws IOException {
  80.         closing = false;
  81.         writer = false;
  82.         writing = false;
  83.         this.gameShell = gameShell;
  84.         this.socket = socket;
  85.         this.socket.setSoTimeout(30000);
  86.         this.socket.setTcpNoDelay(true);
  87.         inputStream = socket.getInputStream();
  88.         outputStream = socket.getOutputStream();
  89.     }
  90.  
  91.     /**
  92.      * Closes this buffered connection and releases any system resources
  93.      * associated with the stream.
  94.      */
  95.     public void close() {
  96.         closing = true;
  97.         try {
  98.             if (inputStream != null) {
  99.                 inputStream.close();
  100.             }
  101.             if (outputStream != null) {
  102.                 outputStream.close();
  103.             }
  104.             if (socket != null) {
  105.                 socket.close();
  106.             }
  107.         } catch (IOException e) {
  108.             System.out.println("Error closing stream");
  109.         }
  110.         writer = false;
  111.         synchronized (this) {
  112.             notify();
  113.         }
  114.         buffer = null;
  115.     }
  116.  
  117.     /**
  118.      * Reads the next byte of data from the input stream. The value byte is
  119.      * returned as an int in the range 0 to 255. If no byte is available because
  120.      * the end of the stream has been reached, the value -1 is returned. This
  121.      * method blocks until input data is available, the end of the stream is
  122.      * detected, or an exception is thrown. A subclass must provide an
  123.      * implementation of this method.
  124.      *
  125.      * @return The next byte of data, or -1 if the end of the stream is reached.
  126.      * @throws IOException
  127.      *             If an I/O error occurs.
  128.      */
  129.     public int read() throws IOException {
  130.         if (closing) {
  131.             return 0;
  132.         } else {
  133.             return inputStream.read();
  134.         }
  135.     }
  136.  
  137.     /**
  138.      * Returns an estimate of the number of bytes that can be read (or skipped
  139.      * over) from this input stream without blocking by the next invocation of a
  140.      * method for this input stream. The next invocation might be the same
  141.      * thread or another thread. A single read or skip of this many bytes will
  142.      * not block, but may read or skip fewer bytes. Note that while some
  143.      * implementations of InputStream will return the total number of bytes in
  144.      * the stream, many will not. It is never correct to use the return value of
  145.      * this method to allocate a buffer intended to hold all data in this
  146.      * stream.
  147.      *
  148.      * A subclass' implementation of this method may choose to throw an
  149.      * IOException if this input stream has been closed by invoking the close()
  150.      * method.
  151.      *
  152.      * The available method for class InputStream always returns 0.
  153.      *
  154.      * This method should be overridden by subclasses.
  155.      *
  156.      * @return an estimate of the number of bytes that can be read (or skipped
  157.      *         over) from this input stream without blocking or 0 when it
  158.      *         reaches the end of the input stream.
  159.      * @throws IOException
  160.      *             If an I/O error occurs.
  161.      */
  162.     public int available() throws IOException {
  163.         if (closing) {
  164.             return 0;
  165.         } else {
  166.             return inputStream.available();
  167.         }
  168.     }
  169.  
  170.     /**
  171.      * Reads up to len bytes of data from the input stream into an array of
  172.      * bytes. An attempt is made to read as many as length bytes, but a smaller
  173.      * number may be read. The number of bytes actually read is returned as an
  174.      * integer.
  175.      *
  176.      * @param src
  177.      *            The buffer into which the data is read.
  178.      * @param offset
  179.      *            The start offset in array b at which the data is written.
  180.      * @param length
  181.      *            The maximum number of bytes to read.
  182.      * @throws IOException
  183.      *             If an I/O error occurs.
  184.      */
  185.     public void read(byte src[], int offset, int length) throws IOException {
  186.         if (closing) {
  187.             return;
  188.         }
  189.         int bytes;
  190.         for (; length > 0; length -= bytes) {
  191.             bytes = inputStream.read(src, offset, length);
  192.             if (bytes <= 0) {
  193.                 throw new IOException("EOF");
  194.             }
  195.             offset += bytes;
  196.         }
  197.  
  198.     }
  199.  
  200.     /**
  201.      * Writes length bytes from the specified byte array starting at offset off
  202.      * to this output stream. The general contract for write(src, offset,
  203.      * length) is that some of the bytes in the array b are written to the
  204.      * output stream in order; element src[offset] is the first byte written and
  205.      * b[offset+length-1] is the last byte written by this operation. The write
  206.      * method of OutputStream calls the write method of one argument on each of
  207.      * the bytes to be written out. Subclasses are encouraged to override this
  208.      * method and provide a more efficient implementation.
  209.      *
  210.      * If src is null, a NullPointerException is thrown.
  211.      *
  212.      * If offset is negative, or length is negative, or offset+length is greater
  213.      * than the length of the array src, then an IndexOutOfBoundsException is
  214.      * thrown.
  215.      *
  216.      * @param src
  217.      *            The data.
  218.      * @param offset
  219.      *            The start offset in the data.
  220.      * @param length
  221.      *            The number of bytes to write.
  222.      * @throws IOException
  223.      *             If an I/O error occurs.
  224.      */
  225.     public void write(byte src[], int offset, int length) throws IOException {
  226.         if (closing) {
  227.             return;
  228.         }
  229.         if (writing) {
  230.             writing = false;
  231.             throw new IOException("Error in writer thread");
  232.         }
  233.         if (buffer == null) {
  234.             buffer = new byte[5000];
  235.         }
  236.         synchronized (this) {
  237.             for (int pointer = 0; pointer < offset; pointer++) {
  238.                 buffer[tnum] = src[pointer + length];
  239.                 tnum = (tnum + 1) % 5000;
  240.                 if (tnum == (tcycl + 4900) % 5000) {
  241.                     throw new IOException("buffer overflow");
  242.                 }
  243.             }
  244.  
  245.             if (!writer) {
  246.                 writer = true;
  247.                 gameShell.method12(this, 3);
  248.             }
  249.             notify();
  250.         }
  251.     }
  252.  
  253.     @Override
  254.     public void run() {
  255.         while (writer) {
  256.             int length;
  257.             int offset;
  258.             synchronized (this) {
  259.                 if (tnum == tcycl) {
  260.                     try {
  261.                         wait();
  262.                     } catch (InterruptedException e) {
  263.                     }
  264.                 }
  265.                 if (!writer) {
  266.                     return;
  267.                 }
  268.                 offset = tcycl;
  269.                 if (tnum >= tcycl) {
  270.                     length = tnum - tcycl;
  271.                 } else {
  272.                     length = 5000 - tcycl;
  273.                 }
  274.             }
  275.             if (length > 0) {
  276.                 try {
  277.                     outputStream.write(buffer, offset, length);
  278.                 } catch (IOException e) {
  279.                     writing = true;
  280.                 }
  281.                 tcycl = (tcycl + length) % 5000;
  282.                 try {
  283.                     if (tnum == tcycl) {
  284.                         outputStream.flush();
  285.                     }
  286.                 } catch (IOException e) {
  287.                     writing = true;
  288.                 }
  289.             }
  290.         }
  291.     }
  292.  
  293.     /**
  294.      * Dumps information related to the buffered connection.
  295.      */
  296.     public void dump() {
  297.         try {
  298.             System.out.println("dummy:" + closing);
  299.             System.out.println("tcycl:" + tcycl);
  300.             System.out.println("tnum:" + tnum);
  301.             System.out.println("writer:" + writer);
  302.             System.out.println("ioerror:" + writing);
  303.             System.out.println("available:" + available());
  304.         } catch (IOException e) {
  305.             return;
  306.         }
  307.     }
  308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement