public void run() {

      try {
         BufferedReader in          = new BufferedReader(new InputStreamReader(client.getInputStream()));
         DataInputStream in_binary  = new DataInputStream(new BufferedInputStream(client.getInputStream()));
         
         handshake( in );

         while ( true) {
            
            byte[] theBytes = new byte[4096];               // the whole message (type, length, mask, message)
            byte[] mask = new byte[4];                      // stores our bitmask 
            int numBytesRead = in_binary.read(theBytes);    // read from our socket
            int indexToMask = 2;                            // index into 'theBytes' where the mask starts (default is 2)
            int indexToData = 6;                            // index into 'theBytes' where the data starts (defualt is 6)
            
            
            int length = theBytes[1] & 0x7F; // the the length (by masking out the left most bit)
            
            // There are two special cases for length 126 and 127 (after masking).
            //  126 means the next two bytes are for length   (because the length wouldn't fit in one byte)
            //  127 meant the next eight bytes are for length (becuase the length wouldn't fit in two bytes)
            // With this in mind we now find the index into the data
            if ( length == 126 ) {
               indexToMask = 4;
               indexToData = 8;
            }
            if ( length == 127 ) {
               indexToMask = 10;
               indexToData = 14;
            }
            
            if ( DEBUG ) {
               System.out.println("Read in " + numBytesRead + " byte(s)" );
               System.out.println("The value of the first byte was " + theBytes[0] );  // should be -127 (129)
               System.out.println("The second byte (which is the length) is " + length );
            }
            
            mask[0] = theBytes[indexToMask];
            mask[1] = theBytes[indexToMask+1];
            mask[2] = theBytes[indexToMask+2];
            mask[3] = theBytes[indexToMask+3];
            
            String message = "";
            // now we XOR the mask and data to get the decoded message 
            for( int i = 0; i < (numBytesRead - indexToData); ++i ) {
               
               // what we really want to do is make a new 'byte[]' that size is 'numBytesRead - indexToData'
               // and fill it with the new data
               message = message + String.valueOf( Character.toChars( theBytes[indexToData + i] ^ mask[ i % 4 ] ) );    
            }
            
               System.out.println(message);
               // invoke the interpreter
               String value = Interpreter.getInstance().interp(message, t.getName() );
               System.out.println("Evaluated to " + value);
         }
      }
      catch ( IOException e ) {
         System.err.println("WSSClientConnection.run(): Error with client thread");
      }
      catch ( NoSuchAlgorithmException e ) {
         System.err.println("HandShake Failed: NoSuchAlgorithmException");
      }
      
   }