code: def read_message(self):
          
          opcode = None
          message = None
          while True:
              header, payload = self.read_frame()
              f_opcode = header.opcode
              if f_opcode in (self.OPCODE_TEXT, self.OPCODE_BINARY):
                  # a new frame
                  if opcode:
                      raise WebSocketError("The opcode in non-fin frame is expected to be zero, got {0!r}".format(f_opcode))
                  # Start reading a new message, reset the validator
                  self.utf8validator.reset()
                  self.utf8validate_last = (True, True, 0, 0)
                  opcode = f_opcode
              elif f_opcode == self.OPCODE_CONTINUATION:
                  if not opcode:
                      raise WebSocketError("Unexpected frame with opcode=0")
              elif f_opcode == self.OPCODE_PING:
                  self.handle_ping(header, payload)
                  continue
              elif f_opcode == self.OPCODE_PONG:
                  self.handle_pong(header, payload)
                  continue
              elif f_opcode == self.OPCODE_CLOSE:
                  self.handle_close(header, payload)
                  return
              else:
                  raise WebSocketError("Unexpected opcode={0!r}".format(f_opcode))
              if opcode == self.OPCODE_TEXT:
                  self.validate_utf8(payload)
                  if six.PY3:
                      payload = payload.decode()
              if message is None:
                  message = six.text_type() if opcode == self.OPCODE_TEXT else six.binary_type()
              message += payload
              if header.fin:
                  break
          if opcode == self.OPCODE_TEXT:
              if six.PY2:
                  self.validate_utf8(message)
              else:
                  self.validate_utf8(message.encode())
              return message
          else:
              return bytearray(message)
docs: Return the next text or binary message from the socket.
  
          This is an internal method as calling this will not cleanup correctly
          if an exception is called. Use `receive` instead.