-
-
Notifications
You must be signed in to change notification settings - Fork 618
Use the last olm session that got a message #776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
28540ad
37f0a9a
2a6a67c
fcadf6e
e17a39d
a30845f
5bc68c0
408407b
3c85bd5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
language: node_js | ||
node_js: | ||
- node # Latest stable version of nodejs. | ||
- "10.11.0" | ||
script: | ||
- ./travis.sh |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -295,8 +295,8 @@ OlmDevice.prototype._storeAccount = function(txn, account) { | |
*/ | ||
OlmDevice.prototype._getSession = function(deviceKey, sessionId, txn, func) { | ||
this._cryptoStore.getEndToEndSession( | ||
deviceKey, sessionId, txn, (pickledSession) => { | ||
this._unpickleSession(pickledSession, func); | ||
deviceKey, sessionId, txn, (sessionInfo) => { | ||
this._unpickleSession(sessionInfo, func); | ||
}, | ||
); | ||
}; | ||
|
@@ -306,15 +306,17 @@ OlmDevice.prototype._getSession = function(deviceKey, sessionId, txn, func) { | |
* function with it. The session object is destroyed once the function | ||
* returns. | ||
* | ||
* @param {string} pickledSession | ||
* @param {object} sessionInfo | ||
* @param {function} func | ||
* @private | ||
*/ | ||
OlmDevice.prototype._unpickleSession = function(pickledSession, func) { | ||
OlmDevice.prototype._unpickleSession = function(sessionInfo, func) { | ||
const session = new global.Olm.Session(); | ||
try { | ||
session.unpickle(this._pickleKey, pickledSession); | ||
func(session); | ||
session.unpickle(this._pickleKey, sessionInfo.session); | ||
const unpickledSessInfo = Object.assign({}, sessionInfo, {session}); | ||
|
||
func(unpickledSessInfo); | ||
} finally { | ||
session.free(); | ||
} | ||
|
@@ -324,14 +326,17 @@ OlmDevice.prototype._unpickleSession = function(pickledSession, func) { | |
* store our OlmSession in the session store | ||
* | ||
* @param {string} deviceKey | ||
* @param {OlmSession} session | ||
* @param {object} sessionInfo {session: OlmSession, lastReceivedMessageTs: int} | ||
* @param {*} txn Opaque transaction object from cryptoStore.doTxn() | ||
* @private | ||
*/ | ||
OlmDevice.prototype._saveSession = function(deviceKey, session, txn) { | ||
const pickledSession = session.pickle(this._pickleKey); | ||
OlmDevice.prototype._saveSession = function(deviceKey, sessionInfo, txn) { | ||
const sessionId = sessionInfo.session.session_id(); | ||
const pickledSessionInfo = Object.assign(sessionInfo, { | ||
session: sessionInfo.session.pickle(this._pickleKey), | ||
}); | ||
this._cryptoStore.storeEndToEndSession( | ||
deviceKey, session.session_id(), pickledSession, txn, | ||
deviceKey, sessionId, pickledSessionInfo, txn, | ||
); | ||
}; | ||
|
||
|
@@ -461,7 +466,15 @@ OlmDevice.prototype.createOutboundSession = async function( | |
session.create_outbound(account, theirIdentityKey, theirOneTimeKey); | ||
newSessionId = session.session_id(); | ||
this._storeAccount(txn, account); | ||
this._saveSession(theirIdentityKey, session, txn); | ||
const sessionInfo = { | ||
session, | ||
// Pretend we've received a message at this point, otherwise | ||
// if we try to send a message to the device, it won't use | ||
// this session (storing the creation time separately would | ||
// make the pickle longer and would not be useful otherwise). | ||
lastReceivedMessageTs: Date.now(), | ||
}; | ||
this._saveSession(theirIdentityKey, sessionInfo, txn); | ||
} finally { | ||
session.free(); | ||
} | ||
|
@@ -510,7 +523,13 @@ OlmDevice.prototype.createInboundSession = async function( | |
|
||
const payloadString = session.decrypt(messageType, ciphertext); | ||
|
||
this._saveSession(theirDeviceIdentityKey, session, txn); | ||
const sessionInfo = { | ||
session, | ||
// this counts as an received message: set last received message time | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/an/a/ |
||
// to now | ||
lastReceivedMessageTs: Date.now(), | ||
}; | ||
this._saveSession(theirDeviceIdentityKey, sessionInfo, txn); | ||
|
||
result = { | ||
payload: payloadString, | ||
|
@@ -558,13 +577,20 @@ OlmDevice.prototype.getSessionIdsForDevice = async function(theirDeviceIdentityK | |
* @return {Promise<?string>} session id, or null if no established session | ||
*/ | ||
OlmDevice.prototype.getSessionIdForDevice = async function(theirDeviceIdentityKey) { | ||
const sessionIds = await this.getSessionIdsForDevice(theirDeviceIdentityKey); | ||
if (sessionIds.length === 0) { | ||
const sessionInfos = await this.getSessionInfoForDevice(theirDeviceIdentityKey); | ||
if (sessionInfos.length === 0) { | ||
return null; | ||
} | ||
// Use the session with the lowest ID. | ||
sessionIds.sort(); | ||
return sessionIds[0]; | ||
// Use the session that has most recently received a message | ||
sessionInfos.sort((a, b) => { | ||
if (a.lastReceivedMessageTs !== b.lastReceivedMessageTs) { | ||
return a.lastReceivedMessageTs - b.lastReceivedMessageTs; | ||
} else { | ||
if (a.sessionId === b.sessionId) return 0; | ||
return a.sessionId < b.sessionId ? -1 : 1; | ||
} | ||
}); | ||
return sessionInfos[sessionInfos.length - 1].sessionId; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looping through the sessionInfos array, and keeping track of the sessionId with the smallest timestamp/sessionId is approximately the same number of lines of code, and faster (O(n) rather than O(n log n)). i.e. let idxOfMin = 0;
for (i = 1; i < sessionInfos.length; i++) {
if (sessionInfos[i].lastReceivedMessageTs < sessionInfos[idxOfMin].lastReceiveMessageTs
|| (sessionInfos[i].lastReceivedMessageTs === sessionInfos[idxOfMin].lastReceiveMessageTs
&& sessionInfos[i].sessionId < sessinInfos[idxOfMin].sessionId)) {
idxOfMin = i;
}
return sessionInfos[idxOfMin].sessionId; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I was reluctant to bother changing it since it was already a sort, but fair enough |
||
}; | ||
|
||
/** | ||
|
@@ -587,9 +613,10 @@ OlmDevice.prototype.getSessionInfoForDevice = async function(deviceIdentityKey) | |
this._cryptoStore.getEndToEndSessions(deviceIdentityKey, txn, (sessions) => { | ||
const sessionIds = Object.keys(sessions).sort(); | ||
for (const sessionId of sessionIds) { | ||
this._unpickleSession(sessions[sessionId], (session) => { | ||
this._unpickleSession(sessions[sessionId], (sessInfo) => { | ||
info.push({ | ||
hasReceivedMessage: session.has_received_message(), | ||
lastReceivedMessageTs: sessInfo.lastReceivedMessageTs, | ||
hasReceivedMessage: sessInfo.session.has_received_message(), | ||
sessionId: sessionId, | ||
}); | ||
}); | ||
|
@@ -620,9 +647,9 @@ OlmDevice.prototype.encryptMessage = async function( | |
await this._cryptoStore.doTxn( | ||
'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS], | ||
(txn) => { | ||
this._getSession(theirDeviceIdentityKey, sessionId, txn, (session) => { | ||
res = session.encrypt(payloadString); | ||
this._saveSession(theirDeviceIdentityKey, session, txn); | ||
this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => { | ||
res = sessionInfo.session.encrypt(payloadString); | ||
this._saveSession(theirDeviceIdentityKey, sessionInfo, txn); | ||
}); | ||
}, | ||
); | ||
|
@@ -647,9 +674,10 @@ OlmDevice.prototype.decryptMessage = async function( | |
await this._cryptoStore.doTxn( | ||
'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS], | ||
(txn) => { | ||
this._getSession(theirDeviceIdentityKey, sessionId, txn, (session) => { | ||
payloadString = session.decrypt(messageType, ciphertext); | ||
this._saveSession(theirDeviceIdentityKey, session, txn); | ||
this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => { | ||
payloadString = sessionInfo.session.decrypt(messageType, ciphertext); | ||
sessionInfo.lastReceivedMessageTs = Date.now(); | ||
this._saveSession(theirDeviceIdentityKey, sessionInfo, txn); | ||
}); | ||
}, | ||
); | ||
|
@@ -679,8 +707,8 @@ OlmDevice.prototype.matchesSession = async function( | |
await this._cryptoStore.doTxn( | ||
'readonly', [IndexedDBCryptoStore.STORE_SESSIONS], | ||
(txn) => { | ||
this._getSession(theirDeviceIdentityKey, sessionId, txn, (session) => { | ||
matches = session.matches_inbound(ciphertext); | ||
this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => { | ||
matches = sessionInfo.session.matches_inbound(ciphertext); | ||
}); | ||
}, | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -314,7 +314,10 @@ export class Backend { | |
getReq.onsuccess = function() { | ||
const cursor = getReq.result; | ||
if (cursor) { | ||
results[cursor.value.sessionId] = cursor.value.session; | ||
results[cursor.value.sessionId] = { | ||
session: cursor.value.session, | ||
lastReceivedMessagets: cursor.value.lastReceivedMessageTs, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the case changed here (lastReceivedMessagets vs lastReceivedmessageTs)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, good spot |
||
}; | ||
cursor.continue(); | ||
} else { | ||
try { | ||
|
@@ -332,7 +335,10 @@ export class Backend { | |
getReq.onsuccess = function() { | ||
try { | ||
if (getReq.result) { | ||
func(getReq.result.session); | ||
func({ | ||
session: getReq.result.session, | ||
lastReceivedMessagets: getReq.result.lastReceivedMessageTs, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
}); | ||
} else { | ||
func(null); | ||
} | ||
|
@@ -342,9 +348,14 @@ export class Backend { | |
}; | ||
} | ||
|
||
storeEndToEndSession(deviceKey, sessionId, session, txn) { | ||
storeEndToEndSession(deviceKey, sessionId, sessionInfo, txn) { | ||
const objectStore = txn.objectStore("sessions"); | ||
objectStore.put({deviceKey, sessionId, session}); | ||
objectStore.put({ | ||
deviceKey, | ||
sessionId, | ||
session: sessionInfo.session, | ||
lastReceivedMessageTs: sessionInfo.lastReceivedMessageTs, | ||
}); | ||
} | ||
|
||
// Inbound group sessions | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not stored in the pickle any more
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooh, yep