Read a message from IXXAT device.

def _recv_internal(self, timeout):
        """ Read a message from IXXAT device. """

        # TODO: handling CAN error messages?
        data_received = False

        if timeout == 0:
            # Peek without waiting
            try:
                _canlib.canChannelPeekMessage(self._channel_handle, ctypes.byref(self._message))
            except (VCITimeout, VCIRxQueueEmptyError):
                return None, True
            else:
                if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA:
                    data_received = True
        else:
            # Wait if no message available
            if timeout is None or timeout < 0:
                remaining_ms = constants.INFINITE
                t0 = None
            else:
                timeout_ms = int(timeout * 1000)
                remaining_ms = timeout_ms
                t0 = _timer_function()

            while True:
                try:
                    _canlib.canChannelReadMessage(self._channel_handle, remaining_ms, ctypes.byref(self._message))
                except (VCITimeout, VCIRxQueueEmptyError):
                    # Ignore the 2 errors, the timeout is handled manually with the _timer_function()
                    pass
                else:
                    # See if we got a data or info/error messages
                    if self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_DATA:
                        data_received = True
                        break

                    elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_INFO:
                        log.info(CAN_INFO_MESSAGES.get(self._message.abData[0], "Unknown CAN info message code {}".format(self._message.abData[0])))

                    elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_ERROR:
                        log.warning(CAN_ERROR_MESSAGES.get(self._message.abData[0], "Unknown CAN error message code {}".format(self._message.abData[0])))

                    elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_TIMEOVR:
                        pass
                    else:
                        log.warn("Unexpected message info type")

                if t0 is not None:
                    remaining_ms = timeout_ms - int((_timer_function() - t0) * 1000)
                    if remaining_ms < 0:
                        break

        if not data_received:
            # Timed out / can message type is not DATA
            return None, True

        # The _message.dwTime is a 32bit tick value and will overrun,
        # so expect to see the value restarting from 0
        rx_msg = Message(
            timestamp=self._message.dwTime / self._tick_resolution,  # Relative time in s
            is_remote_frame=True if self._message.uMsgInfo.Bits.rtr else False,
            is_extended_id=True if self._message.uMsgInfo.Bits.ext else False,
            arbitration_id=self._message.dwMsgId,
            dlc=self._message.uMsgInfo.Bits.dlc,
            data=self._message.abData[:self._message.uMsgInfo.Bits.dlc],
            channel=self.channel
        )

        return rx_msg, True