mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-17 12:08:26 +00:00
sync update of android-service to libsignal
This commit is contained in:
parent
ef2380da76
commit
1f1ffdafdd
@ -6,6 +6,7 @@ import org.session.libsignal.libsignal.logging.Log
|
|||||||
import org.session.libsignal.service.internal.util.Base64
|
import org.session.libsignal.service.internal.util.Base64
|
||||||
import org.session.libsignal.service.loki.api.crypto.ProofOfWork
|
import org.session.libsignal.service.loki.api.crypto.ProofOfWork
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
||||||
|
import org.session.libsignal.service.loki.utilities.ThreadUtils
|
||||||
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
||||||
|
|
||||||
internal data class LokiMessage(
|
internal data class LokiMessage(
|
||||||
@ -60,7 +61,7 @@ internal data class LokiMessage(
|
|||||||
internal fun calculatePoW(): Promise<LokiMessage, Exception> {
|
internal fun calculatePoW(): Promise<LokiMessage, Exception> {
|
||||||
val deferred = deferred<LokiMessage, Exception>()
|
val deferred = deferred<LokiMessage, Exception>()
|
||||||
// Run PoW in a background thread
|
// Run PoW in a background thread
|
||||||
Thread {
|
ThreadUtils.queue {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
val nonce = ProofOfWork.calculate(data, recipientPublicKey, now, ttl)
|
val nonce = ProofOfWork.calculate(data, recipientPublicKey, now, ttl)
|
||||||
if (nonce != null ) {
|
if (nonce != null ) {
|
||||||
@ -68,7 +69,7 @@ internal data class LokiMessage(
|
|||||||
} else {
|
} else {
|
||||||
deferred.reject(SnodeAPI.Error.ProofOfWorkCalculationFailed)
|
deferred.reject(SnodeAPI.Error.ProofOfWorkCalculationFailed)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,22 +12,19 @@ import org.session.libsignal.service.internal.util.Base64
|
|||||||
import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI
|
import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI
|
||||||
import org.session.libsignal.service.loki.api.utilities.HTTP
|
import org.session.libsignal.service.loki.api.utilities.HTTP
|
||||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
||||||
import org.session.libsignal.service.loki.utilities.Broadcaster
|
import org.session.libsignal.service.loki.utilities.*
|
||||||
import org.session.libsignal.service.loki.utilities.createContext
|
|
||||||
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
|
||||||
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
|
||||||
import java.net.ConnectException
|
import java.net.ConnectException
|
||||||
import java.net.SocketTimeoutException
|
import java.net.SocketTimeoutException
|
||||||
|
|
||||||
class SnodeAPI private constructor(public var userPublicKey: String, public val database: LokiAPIDatabaseProtocol, public val broadcaster: Broadcaster) {
|
class SnodeAPI private constructor(public var userPublicKey: String, public val database: LokiAPIDatabaseProtocol, public val broadcaster: Broadcaster) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val messageSendingContext = Kovenant.createContext("LokiAPIMessageSendingContext")
|
val messageSendingContext = Kovenant.createContext()
|
||||||
val messagePollingContext = Kovenant.createContext("LokiAPIMessagePollingContext")
|
val messagePollingContext = Kovenant.createContext()
|
||||||
/**
|
/**
|
||||||
* For operations that are shared between message sending and message polling.
|
* For operations that are shared between message sending and message polling.
|
||||||
*/
|
*/
|
||||||
val sharedContext = Kovenant.createContext("LokiAPISharedContext")
|
val sharedContext = Kovenant.createContext()
|
||||||
|
|
||||||
// region Initialization
|
// region Initialization
|
||||||
lateinit var shared: SnodeAPI
|
lateinit var shared: SnodeAPI
|
||||||
@ -75,7 +72,7 @@ class SnodeAPI private constructor(public var userPublicKey: String, public val
|
|||||||
return OnionRequestAPI.sendOnionRequest(method, parameters, snode, publicKey)
|
return OnionRequestAPI.sendOnionRequest(method, parameters, snode, publicKey)
|
||||||
} else {
|
} else {
|
||||||
val deferred = deferred<Map<*, *>, Exception>()
|
val deferred = deferred<Map<*, *>, Exception>()
|
||||||
Thread {
|
ThreadUtils.queue {
|
||||||
val payload = mapOf( "method" to method.rawValue, "params" to parameters )
|
val payload = mapOf( "method" to method.rawValue, "params" to parameters )
|
||||||
try {
|
try {
|
||||||
val json = HTTP.execute(HTTP.Verb.POST, url, payload)
|
val json = HTTP.execute(HTTP.Verb.POST, url, payload)
|
||||||
@ -87,13 +84,13 @@ class SnodeAPI private constructor(public var userPublicKey: String, public val
|
|||||||
val httpRequestFailedException = exception as? HTTP.HTTPRequestFailedException
|
val httpRequestFailedException = exception as? HTTP.HTTPRequestFailedException
|
||||||
if (httpRequestFailedException != null) {
|
if (httpRequestFailedException != null) {
|
||||||
@Suppress("NAME_SHADOWING") val exception = handleSnodeError(httpRequestFailedException.statusCode, httpRequestFailedException.json, snode, publicKey)
|
@Suppress("NAME_SHADOWING") val exception = handleSnodeError(httpRequestFailedException.statusCode, httpRequestFailedException.json, snode, publicKey)
|
||||||
return@Thread deferred.reject(exception)
|
return@queue deferred.reject(exception)
|
||||||
}
|
}
|
||||||
Log.d("Loki", "Unhandled exception: $exception.")
|
Log.d("Loki", "Unhandled exception: $exception.")
|
||||||
}
|
}
|
||||||
deferred.reject(exception)
|
deferred.reject(exception)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import nl.komponents.kovenant.task
|
|||||||
import org.session.libsignal.libsignal.logging.Log
|
import org.session.libsignal.libsignal.logging.Log
|
||||||
import org.session.libsignal.service.loki.api.utilities.HTTP
|
import org.session.libsignal.service.loki.api.utilities.HTTP
|
||||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
||||||
|
import org.session.libsignal.service.loki.utilities.ThreadUtils
|
||||||
import org.session.libsignal.service.loki.utilities.getRandomElement
|
import org.session.libsignal.service.loki.utilities.getRandomElement
|
||||||
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
||||||
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
||||||
@ -67,7 +68,7 @@ class SwarmAPI private constructor(private val database: LokiAPIDatabaseProtocol
|
|||||||
)
|
)
|
||||||
val deferred = deferred<Snode, Exception>()
|
val deferred = deferred<Snode, Exception>()
|
||||||
deferred<Snode, Exception>(SnodeAPI.sharedContext)
|
deferred<Snode, Exception>(SnodeAPI.sharedContext)
|
||||||
Thread {
|
ThreadUtils.queue {
|
||||||
try {
|
try {
|
||||||
val json = HTTP.execute(HTTP.Verb.POST, url, parameters, useSeedNodeConnection = true)
|
val json = HTTP.execute(HTTP.Verb.POST, url, parameters, useSeedNodeConnection = true)
|
||||||
val intermediate = json["result"] as? Map<*, *>
|
val intermediate = json["result"] as? Map<*, *>
|
||||||
@ -101,7 +102,7 @@ class SwarmAPI private constructor(private val database: LokiAPIDatabaseProtocol
|
|||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
deferred.reject(exception)
|
deferred.reject(exception)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
} else {
|
} else {
|
||||||
return Promise.of(snodePool.getRandomElement())
|
return Promise.of(snodePool.getRandomElement())
|
||||||
|
@ -82,12 +82,12 @@ public object OnionRequestAPI {
|
|||||||
*/
|
*/
|
||||||
private fun testSnode(snode: Snode): Promise<Unit, Exception> {
|
private fun testSnode(snode: Snode): Promise<Unit, Exception> {
|
||||||
val deferred = deferred<Unit, Exception>()
|
val deferred = deferred<Unit, Exception>()
|
||||||
Thread { // No need to block the shared context for this
|
ThreadUtils.queue { // No need to block the shared context for this
|
||||||
val url = "${snode.address}:${snode.port}/get_stats/v1"
|
val url = "${snode.address}:${snode.port}/get_stats/v1"
|
||||||
try {
|
try {
|
||||||
val json = HTTP.execute(HTTP.Verb.GET, url)
|
val json = HTTP.execute(HTTP.Verb.GET, url)
|
||||||
val version = json["version"] as? String
|
val version = json["version"] as? String
|
||||||
if (version == null) { deferred.reject(Exception("Missing snode version.")); return@Thread }
|
if (version == null) { deferred.reject(Exception("Missing snode version.")); return@queue }
|
||||||
if (version >= "2.0.7") {
|
if (version >= "2.0.7") {
|
||||||
deferred.resolve(Unit)
|
deferred.resolve(Unit)
|
||||||
} else {
|
} else {
|
||||||
@ -98,7 +98,7 @@ public object OnionRequestAPI {
|
|||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
deferred.reject(exception)
|
deferred.reject(exception)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,10 +312,10 @@ public object OnionRequestAPI {
|
|||||||
return@success deferred.reject(exception)
|
return@success deferred.reject(exception)
|
||||||
}
|
}
|
||||||
val destinationSymmetricKey = result.destinationSymmetricKey
|
val destinationSymmetricKey = result.destinationSymmetricKey
|
||||||
Thread {
|
ThreadUtils.queue {
|
||||||
try {
|
try {
|
||||||
val json = HTTP.execute(HTTP.Verb.POST, url, body)
|
val json = HTTP.execute(HTTP.Verb.POST, url, body)
|
||||||
val base64EncodedIVAndCiphertext = json["result"] as? String ?: return@Thread deferred.reject(Exception("Invalid JSON"))
|
val base64EncodedIVAndCiphertext = json["result"] as? String ?: return@queue deferred.reject(Exception("Invalid JSON"))
|
||||||
val ivAndCiphertext = Base64.decode(base64EncodedIVAndCiphertext)
|
val ivAndCiphertext = Base64.decode(base64EncodedIVAndCiphertext)
|
||||||
try {
|
try {
|
||||||
val plaintext = DecryptionUtilities.decryptUsingAESGCM(ivAndCiphertext, destinationSymmetricKey)
|
val plaintext = DecryptionUtilities.decryptUsingAESGCM(ivAndCiphertext, destinationSymmetricKey)
|
||||||
@ -325,7 +325,7 @@ public object OnionRequestAPI {
|
|||||||
if (statusCode == 406) {
|
if (statusCode == 406) {
|
||||||
@Suppress("NAME_SHADOWING") val body = mapOf( "result" to "Your clock is out of sync with the service node network." )
|
@Suppress("NAME_SHADOWING") val body = mapOf( "result" to "Your clock is out of sync with the service node network." )
|
||||||
val exception = HTTPRequestFailedAtDestinationException(statusCode, body)
|
val exception = HTTPRequestFailedAtDestinationException(statusCode, body)
|
||||||
return@Thread deferred.reject(exception)
|
return@queue deferred.reject(exception)
|
||||||
} else if (json["body"] != null) {
|
} else if (json["body"] != null) {
|
||||||
@Suppress("NAME_SHADOWING") val body: Map<*, *>
|
@Suppress("NAME_SHADOWING") val body: Map<*, *>
|
||||||
if (json["body"] is Map<*, *>) {
|
if (json["body"] is Map<*, *>) {
|
||||||
@ -340,13 +340,13 @@ public object OnionRequestAPI {
|
|||||||
}
|
}
|
||||||
if (statusCode != 200) {
|
if (statusCode != 200) {
|
||||||
val exception = HTTPRequestFailedAtDestinationException(statusCode, body)
|
val exception = HTTPRequestFailedAtDestinationException(statusCode, body)
|
||||||
return@Thread deferred.reject(exception)
|
return@queue deferred.reject(exception)
|
||||||
}
|
}
|
||||||
deferred.resolve(body)
|
deferred.resolve(body)
|
||||||
} else {
|
} else {
|
||||||
if (statusCode != 200) {
|
if (statusCode != 200) {
|
||||||
val exception = HTTPRequestFailedAtDestinationException(statusCode, json)
|
val exception = HTTPRequestFailedAtDestinationException(statusCode, json)
|
||||||
return@Thread deferred.reject(exception)
|
return@queue deferred.reject(exception)
|
||||||
}
|
}
|
||||||
deferred.resolve(json)
|
deferred.resolve(json)
|
||||||
}
|
}
|
||||||
@ -359,7 +359,7 @@ public object OnionRequestAPI {
|
|||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
deferred.reject(exception)
|
deferred.reject(exception)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
}.fail { exception ->
|
}.fail { exception ->
|
||||||
deferred.reject(exception)
|
deferred.reject(exception)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import nl.komponents.kovenant.deferred
|
|||||||
import org.session.libsignal.service.internal.util.JsonUtil
|
import org.session.libsignal.service.internal.util.JsonUtil
|
||||||
import org.session.libsignal.service.loki.api.utilities.EncryptionResult
|
import org.session.libsignal.service.loki.api.utilities.EncryptionResult
|
||||||
import org.session.libsignal.service.loki.api.utilities.EncryptionUtilities
|
import org.session.libsignal.service.loki.api.utilities.EncryptionUtilities
|
||||||
|
import org.session.libsignal.service.loki.utilities.ThreadUtils
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
import org.session.libsignal.service.loki.utilities.toHexString
|
||||||
import java.nio.Buffer
|
import java.nio.Buffer
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
@ -32,7 +33,7 @@ object OnionRequestEncryption {
|
|||||||
*/
|
*/
|
||||||
internal fun encryptPayloadForDestination(payload: Map<*, *>, destination: OnionRequestAPI.Destination): Promise<EncryptionResult, Exception> {
|
internal fun encryptPayloadForDestination(payload: Map<*, *>, destination: OnionRequestAPI.Destination): Promise<EncryptionResult, Exception> {
|
||||||
val deferred = deferred<EncryptionResult, Exception>()
|
val deferred = deferred<EncryptionResult, Exception>()
|
||||||
Thread {
|
ThreadUtils.queue {
|
||||||
try {
|
try {
|
||||||
// Wrapping isn't needed for file server or open group onion requests
|
// Wrapping isn't needed for file server or open group onion requests
|
||||||
when (destination) {
|
when (destination) {
|
||||||
@ -52,7 +53,7 @@ object OnionRequestEncryption {
|
|||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
deferred.reject(exception)
|
deferred.reject(exception)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ object OnionRequestEncryption {
|
|||||||
*/
|
*/
|
||||||
internal fun encryptHop(lhs: OnionRequestAPI.Destination, rhs: OnionRequestAPI.Destination, previousEncryptionResult: EncryptionResult): Promise<EncryptionResult, Exception> {
|
internal fun encryptHop(lhs: OnionRequestAPI.Destination, rhs: OnionRequestAPI.Destination, previousEncryptionResult: EncryptionResult): Promise<EncryptionResult, Exception> {
|
||||||
val deferred = deferred<EncryptionResult, Exception>()
|
val deferred = deferred<EncryptionResult, Exception>()
|
||||||
Thread {
|
ThreadUtils.queue {
|
||||||
try {
|
try {
|
||||||
val payload: MutableMap<String, Any>
|
val payload: MutableMap<String, Any>
|
||||||
when (rhs) {
|
when (rhs) {
|
||||||
@ -88,7 +89,7 @@ object OnionRequestEncryption {
|
|||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
deferred.reject(exception)
|
deferred.reject(exception)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
|||||||
import org.session.libsignal.service.loki.database.LokiOpenGroupDatabaseProtocol
|
import org.session.libsignal.service.loki.database.LokiOpenGroupDatabaseProtocol
|
||||||
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol
|
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol
|
||||||
import org.session.libsignal.service.loki.utilities.DownloadUtilities
|
import org.session.libsignal.service.loki.utilities.DownloadUtilities
|
||||||
|
import org.session.libsignal.service.loki.utilities.ThreadUtils
|
||||||
import org.session.libsignal.service.loki.utilities.createContext
|
import org.session.libsignal.service.loki.utilities.createContext
|
||||||
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
@ -27,7 +28,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val moderators: HashMap<String, HashMap<Long, Set<String>>> = hashMapOf() // Server URL to (channel ID to set of moderator IDs)
|
private val moderators: HashMap<String, HashMap<Long, Set<String>>> = hashMapOf() // Server URL to (channel ID to set of moderator IDs)
|
||||||
val sharedContext = Kovenant.createContext("LokiPublicChatAPISharedContext")
|
val sharedContext = Kovenant.createContext()
|
||||||
|
|
||||||
// region Settings
|
// region Settings
|
||||||
private val fallbackBatchCount = 64
|
private val fallbackBatchCount = 64
|
||||||
@ -38,15 +39,15 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
private val channelInfoType = "net.patter-app.settings"
|
private val channelInfoType = "net.patter-app.settings"
|
||||||
private val attachmentType = "net.app.core.oembed"
|
private val attachmentType = "net.app.core.oembed"
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public val publicChatMessageType = "network.loki.messenger.publicChat"
|
val publicChatMessageType = "network.loki.messenger.publicChat"
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public val profilePictureType = "network.loki.messenger.avatar"
|
val profilePictureType = "network.loki.messenger.avatar"
|
||||||
|
|
||||||
fun getDefaultChats(): List<PublicChat> {
|
fun getDefaultChats(): List<PublicChat> {
|
||||||
return listOf() // Don't auto-join any open groups right now
|
return listOf() // Don't auto-join any open groups right now
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun isUserModerator(hexEncodedPublicKey: String, channel: Long, server: String): Boolean {
|
fun isUserModerator(hexEncodedPublicKey: String, channel: Long, server: String): Boolean {
|
||||||
if (moderators[server] != null && moderators[server]!![channel] != null) {
|
if (moderators[server] != null && moderators[server]!![channel] != null) {
|
||||||
return moderators[server]!![channel]!!.contains(hexEncodedPublicKey)
|
return moderators[server]!![channel]!!.contains(hexEncodedPublicKey)
|
||||||
}
|
}
|
||||||
@ -56,7 +57,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region Public API
|
// region Public API
|
||||||
public fun getMessages(channel: Long, server: String): Promise<List<PublicChatMessage>, Exception> {
|
fun getMessages(channel: Long, server: String): Promise<List<PublicChatMessage>, Exception> {
|
||||||
Log.d("Loki", "Getting messages for open group with ID: $channel on server: $server.")
|
Log.d("Loki", "Getting messages for open group with ID: $channel on server: $server.")
|
||||||
val parameters = mutableMapOf<String, Any>( "include_annotations" to 1 )
|
val parameters = mutableMapOf<String, Any>( "include_annotations" to 1 )
|
||||||
val lastMessageServerID = apiDatabase.getLastMessageServerID(channel, server)
|
val lastMessageServerID = apiDatabase.getLastMessageServerID(channel, server)
|
||||||
@ -160,7 +161,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getDeletedMessageServerIDs(channel: Long, server: String): Promise<List<Long>, Exception> {
|
fun getDeletedMessageServerIDs(channel: Long, server: String): Promise<List<Long>, Exception> {
|
||||||
Log.d("Loki", "Getting deleted messages for open group with ID: $channel on server: $server.")
|
Log.d("Loki", "Getting deleted messages for open group with ID: $channel on server: $server.")
|
||||||
val parameters = mutableMapOf<String, Any>()
|
val parameters = mutableMapOf<String, Any>()
|
||||||
val lastDeletionServerID = apiDatabase.getLastDeletionServerID(channel, server)
|
val lastDeletionServerID = apiDatabase.getLastDeletionServerID(channel, server)
|
||||||
@ -191,9 +192,9 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun sendMessage(message: PublicChatMessage, channel: Long, server: String): Promise<PublicChatMessage, Exception> {
|
fun sendMessage(message: PublicChatMessage, channel: Long, server: String): Promise<PublicChatMessage, Exception> {
|
||||||
val deferred = deferred<PublicChatMessage, Exception>()
|
val deferred = deferred<PublicChatMessage, Exception>()
|
||||||
Thread {
|
ThreadUtils.queue {
|
||||||
val signedMessage = message.sign(userPrivateKey)
|
val signedMessage = message.sign(userPrivateKey)
|
||||||
if (signedMessage == null) {
|
if (signedMessage == null) {
|
||||||
deferred.reject(SnodeAPI.Error.MessageSigningFailed)
|
deferred.reject(SnodeAPI.Error.MessageSigningFailed)
|
||||||
@ -224,11 +225,11 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
deferred.reject(it)
|
deferred.reject(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun deleteMessage(messageServerID: Long, channel: Long, server: String, isSentByUser: Boolean): Promise<Long, Exception> {
|
fun deleteMessage(messageServerID: Long, channel: Long, server: String, isSentByUser: Boolean): Promise<Long, Exception> {
|
||||||
return retryIfNeeded(maxRetryCount) {
|
return retryIfNeeded(maxRetryCount) {
|
||||||
val isModerationRequest = !isSentByUser
|
val isModerationRequest = !isSentByUser
|
||||||
Log.d("Loki", "Deleting message with ID: $messageServerID from open group with ID: $channel on server: $server (isModerationRequest = $isModerationRequest).")
|
Log.d("Loki", "Deleting message with ID: $messageServerID from open group with ID: $channel on server: $server (isModerationRequest = $isModerationRequest).")
|
||||||
@ -240,7 +241,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun deleteMessages(messageServerIDs: List<Long>, channel: Long, server: String, isSentByUser: Boolean): Promise<List<Long>, Exception> {
|
fun deleteMessages(messageServerIDs: List<Long>, channel: Long, server: String, isSentByUser: Boolean): Promise<List<Long>, Exception> {
|
||||||
return retryIfNeeded(maxRetryCount) {
|
return retryIfNeeded(maxRetryCount) {
|
||||||
val isModerationRequest = !isSentByUser
|
val isModerationRequest = !isSentByUser
|
||||||
val parameters = mapOf( "ids" to messageServerIDs.joinToString(",") )
|
val parameters = mapOf( "ids" to messageServerIDs.joinToString(",") )
|
||||||
@ -253,7 +254,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getModerators(channel: Long, server: String): Promise<Set<String>, Exception> {
|
fun getModerators(channel: Long, server: String): Promise<Set<String>, Exception> {
|
||||||
return execute(HTTPVerb.GET, server, "loki/v1/channel/$channel/get_moderators").then(sharedContext) { json ->
|
return execute(HTTPVerb.GET, server, "loki/v1/channel/$channel/get_moderators").then(sharedContext) { json ->
|
||||||
try {
|
try {
|
||||||
@Suppress("UNCHECKED_CAST") val moderators = json["moderators"] as? List<String>
|
@Suppress("UNCHECKED_CAST") val moderators = json["moderators"] as? List<String>
|
||||||
@ -271,7 +272,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getChannelInfo(channel: Long, server: String): Promise<PublicChatInfo, Exception> {
|
fun getChannelInfo(channel: Long, server: String): Promise<PublicChatInfo, Exception> {
|
||||||
return retryIfNeeded(maxRetryCount) {
|
return retryIfNeeded(maxRetryCount) {
|
||||||
val parameters = mapOf( "include_annotations" to 1 )
|
val parameters = mapOf( "include_annotations" to 1 )
|
||||||
execute(HTTPVerb.GET, server, "/channels/$channel", parameters = parameters).then(sharedContext) { json ->
|
execute(HTTPVerb.GET, server, "/channels/$channel", parameters = parameters).then(sharedContext) { json ->
|
||||||
@ -295,7 +296,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun updateProfileIfNeeded(channel: Long, server: String, groupID: String, info: PublicChatInfo, isForcedUpdate: Boolean) {
|
fun updateProfileIfNeeded(channel: Long, server: String, groupID: String, info: PublicChatInfo, isForcedUpdate: Boolean) {
|
||||||
apiDatabase.setUserCount(channel, server, info.memberCount)
|
apiDatabase.setUserCount(channel, server, info.memberCount)
|
||||||
openGroupDatabase.updateTitle(groupID, info.displayName)
|
openGroupDatabase.updateTitle(groupID, info.displayName)
|
||||||
// Download and update profile picture if needed
|
// Download and update profile picture if needed
|
||||||
@ -307,7 +308,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun downloadOpenGroupProfilePicture(server: String, endpoint: String): ByteArray? {
|
fun downloadOpenGroupProfilePicture(server: String, endpoint: String): ByteArray? {
|
||||||
val url = "${server.removeSuffix("/")}/${endpoint.removePrefix("/")}"
|
val url = "${server.removeSuffix("/")}/${endpoint.removePrefix("/")}"
|
||||||
Log.d("Loki", "Downloading open group profile picture from \"$url\".")
|
Log.d("Loki", "Downloading open group profile picture from \"$url\".")
|
||||||
val outputStream = ByteArrayOutputStream()
|
val outputStream = ByteArrayOutputStream()
|
||||||
@ -323,7 +324,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun join(channel: Long, server: String): Promise<Unit, Exception> {
|
fun join(channel: Long, server: String): Promise<Unit, Exception> {
|
||||||
return retryIfNeeded(maxRetryCount) {
|
return retryIfNeeded(maxRetryCount) {
|
||||||
execute(HTTPVerb.POST, server, "/channels/$channel/subscribe").then {
|
execute(HTTPVerb.POST, server, "/channels/$channel/subscribe").then {
|
||||||
Log.d("Loki", "Joined channel with ID: $channel on server: $server.")
|
Log.d("Loki", "Joined channel with ID: $channel on server: $server.")
|
||||||
@ -331,7 +332,7 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun leave(channel: Long, server: String): Promise<Unit, Exception> {
|
fun leave(channel: Long, server: String): Promise<Unit, Exception> {
|
||||||
return retryIfNeeded(maxRetryCount) {
|
return retryIfNeeded(maxRetryCount) {
|
||||||
execute(HTTPVerb.DELETE, server, "/channels/$channel/subscribe").then {
|
execute(HTTPVerb.DELETE, server, "/channels/$channel/subscribe").then {
|
||||||
Log.d("Loki", "Left channel with ID: $channel on server: $server.")
|
Log.d("Loki", "Left channel with ID: $channel on server: $server.")
|
||||||
@ -339,7 +340,15 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getDisplayNames(publicKeys: Set<String>, server: String): Promise<Map<String, String>, Exception> {
|
fun ban(publicKey: String, server: String): Promise<Unit,Exception> {
|
||||||
|
return retryIfNeeded(maxRetryCount) {
|
||||||
|
execute(HTTPVerb.POST, server, "/loki/v1/moderation/blacklist/@$publicKey").then {
|
||||||
|
Log.d("Loki", "Banned user with ID: $publicKey from $server")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDisplayNames(publicKeys: Set<String>, server: String): Promise<Map<String, String>, Exception> {
|
||||||
return getUserProfiles(publicKeys, server, false).map(sharedContext) { json ->
|
return getUserProfiles(publicKeys, server, false).map(sharedContext) { json ->
|
||||||
val mapping = mutableMapOf<String, String>()
|
val mapping = mutableMapOf<String, String>()
|
||||||
for (user in json) {
|
for (user in json) {
|
||||||
@ -353,17 +362,17 @@ class PublicChatAPI(userPublicKey: String, private val userPrivateKey: ByteArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun setDisplayName(newDisplayName: String?, server: String): Promise<Unit, Exception> {
|
fun setDisplayName(newDisplayName: String?, server: String): Promise<Unit, Exception> {
|
||||||
Log.d("Loki", "Updating display name on server: $server.")
|
Log.d("Loki", "Updating display name on server: $server.")
|
||||||
val parameters = mapOf( "name" to (newDisplayName ?: "") )
|
val parameters = mapOf( "name" to (newDisplayName ?: "") )
|
||||||
return execute(HTTPVerb.PATCH, server, "users/me", parameters = parameters).map { Unit }
|
return execute(HTTPVerb.PATCH, server, "users/me", parameters = parameters).map { Unit }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun setProfilePicture(server: String, profileKey: ByteArray, url: String?): Promise<Unit, Exception> {
|
fun setProfilePicture(server: String, profileKey: ByteArray, url: String?): Promise<Unit, Exception> {
|
||||||
return setProfilePicture(server, Base64.encodeBytes(profileKey), url)
|
return setProfilePicture(server, Base64.encodeBytes(profileKey), url)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun setProfilePicture(server: String, profileKey: String, url: String?): Promise<Unit, Exception> {
|
fun setProfilePicture(server: String, profileKey: String, url: String?): Promise<Unit, Exception> {
|
||||||
Log.d("Loki", "Updating profile picture on server: $server.")
|
Log.d("Loki", "Updating profile picture on server: $server.")
|
||||||
val value = when (url) {
|
val value = when (url) {
|
||||||
null -> null
|
null -> null
|
||||||
|
@ -2,25 +2,14 @@
|
|||||||
package org.session.libsignal.service.loki.utilities
|
package org.session.libsignal.service.loki.utilities
|
||||||
|
|
||||||
import nl.komponents.kovenant.*
|
import nl.komponents.kovenant.*
|
||||||
|
import nl.komponents.kovenant.jvm.asDispatcher
|
||||||
import org.session.libsignal.libsignal.logging.Log
|
import org.session.libsignal.libsignal.logging.Log
|
||||||
import kotlin.math.max
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
// Try to use all available threads minus one for the callback
|
fun Kovenant.createContext(): Context {
|
||||||
private val recommendedThreadCount: Int
|
|
||||||
get() = Runtime.getRuntime().availableProcessors() - 1
|
|
||||||
|
|
||||||
fun Kovenant.createContext(contextName: String, threadCount: Int = max(recommendedThreadCount, 1)): Context {
|
|
||||||
return createContext {
|
return createContext {
|
||||||
callbackContext.dispatcher = buildDispatcher {
|
callbackContext.dispatcher = Executors.newSingleThreadExecutor().asDispatcher()
|
||||||
name = "${contextName}CallbackDispatcher"
|
workerContext.dispatcher = ThreadUtils.executorPool.asDispatcher()
|
||||||
// Ref: http://kovenant.komponents.nl/api/core_usage/#execution-order
|
|
||||||
// Having 1 concurrent task ensures we have in-order callback handling
|
|
||||||
concurrentTasks = 1
|
|
||||||
}
|
|
||||||
workerContext.dispatcher = buildDispatcher {
|
|
||||||
name = "${contextName}WorkerDispatcher"
|
|
||||||
concurrentTasks = threadCount
|
|
||||||
}
|
|
||||||
multipleCompletion = { v1, v2 ->
|
multipleCompletion = { v1, v2 ->
|
||||||
Log.d("Loki", "Promise resolved more than once (first with $v1, then with $v2); ignoring $v2.")
|
Log.d("Loki", "Promise resolved more than once (first with $v1, then with $v2); ignoring $v2.")
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.session.libsignal.service.loki.utilities
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
object ThreadUtils {
|
||||||
|
|
||||||
|
internal val executorPool = Executors.newCachedThreadPool()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun queue(target: Runnable) {
|
||||||
|
executorPool.execute(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun queue(target: ()->Unit) {
|
||||||
|
executorPool.execute(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user