extracted helper methods for creating the key and determining the key length, correected key calculation in MessageMap::findAll

This commit is contained in:
john30
2016-11-20 16:07:41 +01:00
parent 5b88c67451
commit 54e3ad872b
2 changed files with 105 additions and 37 deletions
+74 -37
View File
@@ -35,12 +35,18 @@ using namespace std;
/** the bit mask of the source master number in the message key. */
#define ID_SOURCE_MASK (0x1fLL << (8 * 7))
/** the bit mask for the ID length and combined ID bytes in the message key. */
#define ID_LENGTH_AND_IDS_MASK ((7LL<<(8 * 7 + 5)) | 0xffffffffLL)
/** the bits in the @a ID_SOURCE_MASK for arbitrary source and active read message. */
#define ID_SOURCE_ACTIVE_WRITE (0x1fLL << (8 * 7))
/** the bits in the @a ID_SOURCE_MASK for arbitrary source and active write message. */
#define ID_SOURCE_ACTIVE_READ (0x1eLL << (8 * 7))
/** special value for invalid message key. */
#define INVALID_KEY 0xffffffffffffffffLL
/** the maximum poll priority for a @a Message referred to by a @a Condition. */
#define POLL_PRIORITY_CONDITION 5
@@ -61,19 +67,7 @@ Message::Message(const string circuit, const string name,
m_usedByCondition(false), m_isScanMessage(false), m_condition(condition),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0)
{
unsigned long long key = (unsigned long long)(id.size()-2) << (8 * 7 + 5);
if (isPassive)
key |= (unsigned long long)getMasterNumber(srcAddress) << (8 * 7); // 0..25
else
key |= (isWrite ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
key |= (unsigned long long)dstAddress << (8 * 6);
int exp = 5;
for (vector<unsigned char>::const_iterator it = id.begin(); it < id.end(); it++) {
key ^= (unsigned long long)*it << (8 * exp--);
if (exp == 0)
exp = 3;
}
m_key = key;
m_key = createKey(id, isWrite, isPassive, srcAddress, dstAddress);
if (circuit=="scan") {
setScanMessage();
m_pollPriority = 0;
@@ -95,8 +89,9 @@ Message::Message(const string circuit, const string name,
m_id.push_back(pb);
m_id.push_back(sb);
unsigned long long key = 0;
if (!isPassive)
if (!isPassive) {
key |= (isWrite ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
}
key |= (unsigned long long)SYN << (8 * 6);
key |= (unsigned long long)pb << (8 * 5);
key |= (unsigned long long)sb << (8 * 4);
@@ -136,6 +131,53 @@ string getDefault(const string value, vector<string>* defaults, size_t pos, bool
return defaultStr.substr(0, insertPos)+value+defaultStr.substr(insertPos+1);
}
unsigned long long Message::createKey(const vector<unsigned char> id,
const bool isWrite, const bool isPassive,
const unsigned char srcAddress, const unsigned char dstAddress)
{
unsigned long long key = (unsigned long long)(id.size()-2) << (8 * 7 + 5);
if (isPassive) {
key |= (unsigned long long)getMasterNumber(srcAddress) << (8 * 7); // 0..25
} else {
key |= (isWrite ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
}
key |= (unsigned long long)dstAddress << (8 * 6);
int exp = 5;
for (vector<unsigned char>::const_iterator it = id.begin(); it < id.end(); it++) {
key ^= (unsigned long long)*it << (8 * exp--);
if (exp == 0) {
exp = 3;
}
}
return key;
}
unsigned long long Message::createKey(SymbolString& master, unsigned char maxIdLength, bool anyDestination) {
if (master.size() < 5) {
return INVALID_KEY;
}
unsigned char idLength = master[4];
if (maxIdLength < idLength) {
idLength = maxIdLength;
}
if (master.size() < 5+idLength) {
return INVALID_KEY;
}
unsigned long long key = (unsigned long long)idLength << (8 * 7 + 5);
key |= (unsigned long long)getMasterNumber(master[0]) << (8 * 7); // QQ address for passive message
key |= (unsigned long long)(anyDestination ? SYN : master[1]) << (8 * 6); // ZZ address
key |= (unsigned long long)master[2] << (8 * 5); // PB
key |= (unsigned long long)master[3] << (8 * 4); // SB
int exp = 3;
for (unsigned char i = 0; i < idLength; i++) {
key ^= (unsigned long long)master[5 + i] << (8 * exp--);
if (exp == 0) {
exp = 3;
}
}
return key;
}
result_t Message::parseId(string input, vector<unsigned char>& id)
{
istringstream in(input);
@@ -1879,33 +1921,28 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
Message* MessageMap::find(SymbolString& master, bool anyDestination,
const bool withRead, const bool withWrite, const bool withPassive)
{
if (master.size() < 5) {
return NULL;
}
unsigned char maxIdLength = master[4];
if (maxIdLength > m_maxIdLength) {
maxIdLength = m_maxIdLength;
}
if (master.size() < 5+maxIdLength) {
return NULL;
}
if (maxIdLength == 0 && anyDestination && master[2] == 0x07 && master[3] == 0x04) {
if (master.size() >= 5 && master[4] == 0 && anyDestination && master[2] == 0x07 && master[3] == 0x04) {
return m_scanMessage;
}
unsigned long long baseKey = (unsigned long long)getMasterNumber(master[0]) << (8 * 7); // QQ address for passive message
baseKey |= (unsigned long long)(anyDestination ? SYN : master[1]) << (8 * 6); // ZZ address
baseKey |= (unsigned long long)master[2] << (8 * 5); // PB
baseKey |= (unsigned long long)master[3] << (8 * 4); // SB
unsigned long long baseKey = Message::createKey(master, m_maxIdLength, anyDestination);
if (baseKey==INVALID_KEY) {
return NULL;
}
unsigned char maxIdLength = Message::getKeyLength(baseKey);
for (unsigned char idLength = maxIdLength; true; idLength--) {
unsigned long long key = (unsigned long long)idLength << (8 * 7 + 5);
key |= baseKey;
int exp = 3;
for (unsigned char i = 0; i < idLength; i++) {
key |= (unsigned long long)master[5 + i] << (8 * exp--);
if (exp == 0)
exp = 3;
unsigned long long key = baseKey;
if (idLength==maxIdLength) {
baseKey &= ~ID_LENGTH_AND_IDS_MASK;
} else {
key |= (unsigned long long)idLength << (8 * 7 + 5);
int exp = 3;
for (unsigned char i = 0; i < idLength; i++) {
key ^= (unsigned long long)master[5 + i] << (8 * exp--);
if (exp == 0) {
exp = 3;
}
}
}
map<unsigned long long , vector<Message*> >::iterator it;
if (withPassive) {
it = m_messagesByKey.find(key);
+31
View File
@@ -117,6 +117,37 @@ public:
*/
virtual ~Message() { if (m_deleteData) delete m_data; }
/**
* Calculate the key for the ID.
* @param id the primary, secondary, and optional further ID bytes.
* @param isWrite whether this is a write message.
* @param isPassive true if message can only be initiated by a participant other than us,
* false if message can be initiated by any participant.
* @param srcAddress the source address, or @a SYN for any (only relevant if passive).
* @param dstAddress the destination address, or @a SYN for any (set later).
* @return the key for the ID.
*/
static unsigned long long createKey(const vector<unsigned char> id,
const bool isWrite, const bool isPassive,
const unsigned char srcAddress, const unsigned char dstAddress);
/**
* Calculate the key for the master @a SymbolString.
* @param master the master @a SymbolString.
* @param maxIdLength the maximum ID length to use
* @param anyDestination @p true to use the special @a SYN as destination address in the key.
* @return the key for the ID, or -1LL if the data is invalid.
*/
static unsigned long long createKey(SymbolString& master,
unsigned char maxIdLength, bool anyDestination=false);
/**
* Get the length field from the key.
* @param key the key.
* @return the length field from the key.
*/
static unsigned char getKeyLength(unsigned long long key) { return (unsigned char)(key >> (8 * 7 + 5)); }
/**
* Parse an ID part from the input @a string.
* @param input the input @a string, hex digits optionally separated by space.