Handle incorrect clock setting

This commit is contained in:
Niels Andriesse 2021-07-23 14:09:27 +10:00
parent 0131bc171a
commit 118447799a
5 changed files with 22 additions and 14 deletions

View File

@ -143,8 +143,8 @@ dependencies {
testImplementation 'org.robolectric:shadows-multidex:4.2' testImplementation 'org.robolectric:shadows-multidex:4.2'
} }
def canonicalVersionCode = 206 def canonicalVersionCode = 207
def canonicalVersionName = "1.11.5" def canonicalVersionName = "1.11.6"
def postFixSize = 10 def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1, def abiPostFix = ['armeabi-v7a' : 1,

View File

@ -95,7 +95,7 @@ object OpenGroupAPIV2 {
return RequestBody.create(MediaType.get("application/json"), parametersAsJSON) return RequestBody.create(MediaType.get("application/json"), parametersAsJSON)
} }
private fun send(request: Request, isJsonRequired: Boolean = true): Promise<Map<*, *>, Exception> { private fun send(request: Request): Promise<Map<*, *>, Exception> {
val url = HttpUrl.parse(request.server) ?: return Promise.ofFail(Error.InvalidURL) val url = HttpUrl.parse(request.server) ?: return Promise.ofFail(Error.InvalidURL)
val urlBuilder = HttpUrl.Builder() val urlBuilder = HttpUrl.Builder()
.scheme(url.scheme()) .scheme(url.scheme())
@ -127,7 +127,7 @@ object OpenGroupAPIV2 {
if (request.useOnionRouting) { if (request.useOnionRouting) {
val publicKey = MessagingModuleConfiguration.shared.storage.getOpenGroupPublicKey(request.server) val publicKey = MessagingModuleConfiguration.shared.storage.getOpenGroupPublicKey(request.server)
?: return Promise.ofFail(Error.NoPublicKey) ?: return Promise.ofFail(Error.NoPublicKey)
return OnionRequestAPI.sendOnionRequest(requestBuilder.build(), request.server, publicKey, isJSONRequired = isJsonRequired).fail { e -> return OnionRequestAPI.sendOnionRequest(requestBuilder.build(), request.server, publicKey).fail { e ->
// A 401 means that we didn't provide a (valid) auth token for a route that required one. We use this as an // A 401 means that we didn't provide a (valid) auth token for a route that required one. We use this as an
// indication that the token we're using has expired. Note that a 403 has a different meaning; it means that // indication that the token we're using has expired. Note that a 403 has a different meaning; it means that
// we provided a valid token but it doesn't have a high enough permission level for the route in question. // we provided a valid token but it doesn't have a high enough permission level for the route in question.

View File

@ -146,7 +146,8 @@ object MessageSender {
} }
val base64EncodedData = Base64.encodeBytes(wrappedMessage) val base64EncodedData = Base64.encodeBytes(wrappedMessage)
// Send the result // Send the result
val snodeMessage = SnodeMessage(message.recipient!!, base64EncodedData, message.ttl, message.sentTimestamp!!) val timestamp = message.sentTimestamp!! + SnodeAPI.clockOffset
val snodeMessage = SnodeMessage(message.recipient!!, base64EncodedData, message.ttl, timestamp)
if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) { if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) {
SnodeModule.shared.broadcaster.broadcast("sendingMessage", message.sentTimestamp!!) SnodeModule.shared.broadcaster.broadcast("sendingMessage", message.sentTimestamp!!)
} }

View File

@ -20,6 +20,8 @@ import org.session.libsignal.crypto.getRandomElementOrNull
import org.session.libsignal.utilities.Broadcaster import org.session.libsignal.utilities.Broadcaster
import org.session.libsignal.utilities.HTTP import org.session.libsignal.utilities.HTTP
import org.session.libsignal.database.LokiAPIDatabaseProtocol import org.session.libsignal.database.LokiAPIDatabaseProtocol
import java.util.*
import kotlin.math.abs
private typealias Path = List<Snode> private typealias Path = List<Snode>
@ -306,7 +308,7 @@ object OnionRequestAPI {
/** /**
* Sends an onion request to `destination`. Builds new paths as needed. * Sends an onion request to `destination`. Builds new paths as needed.
*/ */
private fun sendOnionRequest(destination: Destination, payload: Map<*, *>, isJSONRequired: Boolean = true): Promise<Map<*, *>, Exception> { private fun sendOnionRequest(destination: Destination, payload: Map<*, *>): Promise<Map<*, *>, Exception> {
val deferred = deferred<Map<*, *>, Exception>() val deferred = deferred<Map<*, *>, Exception>()
lateinit var guardSnode: Snode lateinit var guardSnode: Snode
buildOnionForDestination(payload, destination).success { result -> buildOnionForDestination(payload, destination).success { result ->
@ -347,11 +349,12 @@ object OnionRequestAPI {
body = json["body"] as Map<*, *> body = json["body"] as Map<*, *>
} else { } else {
val bodyAsString = json["body"] as String val bodyAsString = json["body"] as String
if (!isJSONRequired) { body = JsonUtil.fromJson(bodyAsString, Map::class.java)
body = mapOf( "result" to bodyAsString ) }
} else { if (body["t"] != null) {
body = JsonUtil.fromJson(bodyAsString, Map::class.java) val timestamp = body["t"] as Long
} val offset = timestamp - Date().time
SnodeAPI.clockOffset = offset
} }
if (statusCode != 200) { if (statusCode != 200) {
val exception = HTTPRequestFailedAtDestinationException(statusCode, body, destination.description) val exception = HTTPRequestFailedAtDestinationException(statusCode, body, destination.description)
@ -455,7 +458,7 @@ object OnionRequestAPI {
* *
* `publicKey` is the hex encoded public key of the user the call is associated with. This is needed for swarm cache maintenance. * `publicKey` is the hex encoded public key of the user the call is associated with. This is needed for swarm cache maintenance.
*/ */
fun sendOnionRequest(request: Request, server: String, x25519PublicKey: String, target: String = "/loki/v3/lsrpc", isJSONRequired: Boolean = true): Promise<Map<*, *>, Exception> { fun sendOnionRequest(request: Request, server: String, x25519PublicKey: String, target: String = "/loki/v3/lsrpc"): Promise<Map<*, *>, Exception> {
val headers = request.getHeadersForOnionRequest() val headers = request.getHeadersForOnionRequest()
val url = request.url() val url = request.url()
val urlAsString = url.toString() val urlAsString = url.toString()
@ -472,7 +475,7 @@ object OnionRequestAPI {
"headers" to headers "headers" to headers
) )
val destination = Destination.Server(host, target, x25519PublicKey, url.scheme(), url.port()) val destination = Destination.Server(host, target, x25519PublicKey, url.scheme(), url.port())
return sendOnionRequest(destination, payload, isJSONRequired).recover { exception -> return sendOnionRequest(destination, payload).recover { exception ->
Log.d("Loki", "Couldn't reach server: $urlAsString due to error: $exception.") Log.d("Loki", "Couldn't reach server: $urlAsString due to error: $exception.")
throw exception throw exception
} }

View File

@ -28,7 +28,6 @@ import kotlin.Pair
object SnodeAPI { object SnodeAPI {
private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) } private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) }
private val database: LokiAPIDatabaseProtocol private val database: LokiAPIDatabaseProtocol
get() = SnodeModule.shared.storage get() = SnodeModule.shared.storage
private val broadcaster: Broadcaster private val broadcaster: Broadcaster
@ -38,6 +37,11 @@ object SnodeAPI {
internal var snodePool: Set<Snode> internal var snodePool: Set<Snode>
get() = database.getSnodePool() get() = database.getSnodePool()
set(newValue) { database.setSnodePool(newValue) } set(newValue) { database.setSnodePool(newValue) }
/**
* The offset between the user's clock and the Service Node's clock. Used in cases where the
* user's clock is incorrect.
*/
internal var clockOffset = 0L
// Settings // Settings
private val maxRetryCount = 6 private val maxRetryCount = 6