Skip to content

Commit

Permalink
Add improved error logging for SSE issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
greyson-signal committed Aug 17, 2023
1 parent 51602ed commit 635987a
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,16 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
return results
}

/** A function that's just to help with some temporary bug investigation. */
private fun getAllPnis(): Set<PNI> {
return readableDatabase
.select(PNI_COLUMN)
.from(TABLE_NAME)
.where("$PNI NOT NULL")
.run()
.readToSet { PNI.parseOrThrow(it.requireString(PNI_COLUMN)) }
}

/**
* Gives you all of the recipientIds of possibly-registered users (i.e. REGISTERED or UNKNOWN) that can be found by the set of
* provided E164s.
Expand Down Expand Up @@ -2413,9 +2423,50 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
try {
SignalDatabase.messages.insertSessionSwitchoverEvent(operation.recipientId, threadId, event)
} catch (e: Exception) {
// TODO do different stuff based on whether a PNI session exists
Log.e(TAG, "About to crash! Breadcrumbs: ${changeSet.breadCrumbs}, Operations: ${changeSet.operations}, ID: ${changeSet.id}")
throw e

val allPnis: Set<PNI> = getAllPnis()
val pnisWithSessions: Set<PNI> = sessions.findAllThatHaveAnySession(allPnis)
Log.e(TAG, "We know of ${allPnis.size} PNIs, and there are sessions with ${pnisWithSessions.size} of them.")

val record = getRecord(operation.recipientId)
Log.e(TAG, "ID: ${record.id}, E164: ${record.e164}, ACI: ${record.aci}, PNI: ${record.pni}, Registered: ${record.registered}")

if (record.aci != null && record.aci == SignalStore.account().aci) {
if (pnisWithSessions.contains(SignalStore.account().pni!!)) {
throw SseWithSelfAci(e)
} else {
throw SseWithSelfAciNoSession(e)
}
}

if (record.pni != null && record.pni == SignalStore.account().pni) {
if (pnisWithSessions.contains(SignalStore.account().pni!!)) {
throw SseWithSelfPni(e)
} else {
throw SseWithSelfPniNoSession(e)
}
}

if (record.e164 != null && record.e164 == SignalStore.account().e164) {
if (pnisWithSessions.contains(SignalStore.account().pni!!)) {
throw SseWithSelfE164(e)
} else {
throw SseWithSelfE164NoSession(e)
}
}

if (pnisWithSessions.isEmpty()) {
throw SseWithNoPniSessionsException(e)
} else if (pnisWithSessions.size == 1) {
if (pnisWithSessions.first() == SignalStore.account().pni) {
throw SseWithASinglePniSessionForSelfException(e)
} else {
throw SseWithASinglePniSessionException(e)
}
} else {
throw SseWithMultiplePniSessionsException(e)
}
}
}
}
Expand Down Expand Up @@ -4599,4 +4650,15 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
val operations: List<PnpOperation>,
val breadCrumbs: List<String>
)

class SseWithSelfAci(cause: Exception) : IllegalStateException(cause)
class SseWithSelfAciNoSession(cause: Exception) : IllegalStateException(cause)
class SseWithSelfPni(cause: Exception) : IllegalStateException(cause)
class SseWithSelfPniNoSession(cause: Exception) : IllegalStateException(cause)
class SseWithSelfE164(cause: Exception) : IllegalStateException(cause)
class SseWithSelfE164NoSession(cause: Exception) : IllegalStateException(cause)
class SseWithNoPniSessionsException(cause: Exception) : IllegalStateException(cause)
class SseWithASinglePniSessionForSelfException(cause: Exception) : IllegalStateException(cause)
class SseWithASinglePniSessionException(cause: Exception) : IllegalStateException(cause)
class SseWithMultiplePniSessionsException(cause: Exception) : IllegalStateException(cause)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import android.content.Context
import org.signal.core.util.CursorUtil
import org.signal.core.util.SqlUtil
import org.signal.core.util.logging.Log
import org.signal.core.util.readToSet
import org.signal.core.util.requireInt
import org.signal.core.util.requireNonNullBlob
import org.signal.core.util.requireNonNullString
import org.signal.core.util.requireString
import org.signal.core.util.select
import org.signal.libsignal.protocol.SignalProtocolAddress
import org.signal.libsignal.protocol.state.SessionRecord
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceId.PNI
import org.whispersystems.signalservice.api.push.SignalServiceAddress
import java.io.IOException
import java.util.LinkedList
Expand Down Expand Up @@ -210,5 +213,25 @@ class SessionTable(context: Context, databaseHelper: SignalDatabase) : DatabaseT
}
}

/**
* Given a set of serviceIds, this will give you back a filtered set of those ids that have any session with any of your identities.
*
* This was created for getting more debug info for a specific issue.
*/
fun findAllThatHaveAnySession(serviceIds: Set<PNI>): Set<PNI> {
val output: MutableSet<PNI> = mutableSetOf()

for (query in SqlUtil.buildCollectionQuery(ADDRESS, serviceIds.map { it.toString() })) {
output += readableDatabase
.select(ADDRESS)
.from(TABLE_NAME)
.where(query.where, query.whereArgs)
.run()
.readToSet { PNI.parseOrThrow(it.requireString(ADDRESS)) }
}

return output
}

class SessionRow(val address: String, val deviceId: Int, val record: SessionRecord)
}

0 comments on commit 635987a

Please sign in to comment.