code: protected DownstreamMessage receiveMessage ()
          throws IOException
      {
          // read in the next message frame (readFrame() can return false meaning it only read part
          // of the frame from the network, in which case we simply call it again because we can't do
          // anything until it has a whole frame; it will throw an exception if it hits EOF or if
          // something goes awry)
          while (!readFrame()) {
              // noop!
          }
  
          if (_oin == null) {
              // Our object input stream was taken away from us before we could do anything with the
              //  frame, this is equivalent to being interrupted mid-frame, so indicate that.
              throw new InterruptedIOException();
          }
  
          try {
              int size = _fin.available();
              DownstreamMessage msg = (DownstreamMessage)_oin.readObject();
              if (debugLogMessages()) {
                  log.info("RECEIVE " + msg);
              }
              _client.getMessageTracker().messageReceived(false, size, msg, 0);
              return msg;
  
          } catch (ClassNotFoundException cnfe) {
              throw (IOException) new IOException(
                  "Unable to decode incoming message.").initCause(cnfe);
          }
      }
docs: Reads a new message from the socket (blocking until a message has arrived).