Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Session.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8568,7 +8568,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
COMPILE_LIB_SESSION = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 678;
CURRENT_PROJECT_VERSION = 680;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -8649,7 +8649,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Distribution";
COMPILE_LIB_SESSION = "";
CURRENT_PROJECT_VERSION = 678;
CURRENT_PROJECT_VERSION = 680;
ENABLE_BITCODE = NO;
ENABLE_MODULE_VERIFIER = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
Expand Down Expand Up @@ -9349,7 +9349,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
COMPILE_LIB_SESSION = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 678;
CURRENT_PROJECT_VERSION = 680;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -9938,7 +9938,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Distribution";
COMPILE_LIB_SESSION = YES;
CURRENT_PROJECT_VERSION = 678;
CURRENT_PROJECT_VERSION = 680;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
Expand Down
6 changes: 6 additions & 0 deletions Session/Meta/Translations/InfoPlist.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,12 @@
"value" : "Session necesita acceso a la red local para realizar llamadas de voz y video."
}
},
"fi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Session tarvitsee pääsyn paikalliseen verkkoon soittaakseen ääni- ja videopuheluja."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
Expand Down
119 changes: 38 additions & 81 deletions Session/Utilities/IP2Country.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,16 @@ fileprivate class IP2Country: IP2CountryCacheType {
/// We found a separator so create a string from the bytes we just passed
let length: Int = (i - (lastIndex - contentData.startIndex))

if length > 0 {
let dataChunk: Data = Data(
bytes: baseAddress.advanced(by: lastIndex - contentData.startIndex),
count: length
)

if let stringValue: String = String(data: dataChunk, encoding: .utf8) {
result.append(stringValue)
}
let dataChunk: Data = Data(
bytes: baseAddress.advanced(by: lastIndex - contentData.startIndex),
count: length
)

if let stringValue: String = String(data: dataChunk, encoding: .utf8) {
result.append(stringValue)
}
else {
result.append("") /// Need to insert empty entries as well to ensure the indexes are correct
}

/// Move past the separator
Expand Down Expand Up @@ -214,87 +215,43 @@ fileprivate class IP2Country: IP2CountryCacheType {

init(using dependencies: Dependencies) {
/// Ensure the lookup tables get loaded in the background
DispatchQueue.global(qos: .utility).async { [weak self] in
Task.detached(priority: .utility) { [weak self] in
_ = self?.cache

/// Then register for path change callbacks which will be used to update the country name cache
self?.registerNetworkObservables(using: dependencies)
self?._cacheLoaded.send(true)
Log.info(.ip2Country, "IP2Country cache loaded.")
}
}

// MARK: - Functions

private func registerNetworkObservables(using dependencies: Dependencies) {
/// Register for path change callbacks which will be used to update the country name cache
dependencies[cache: .libSessionNetwork].paths
.subscribe(on: DispatchQueue.global(qos: .utility), using: dependencies)
.receive(on: DispatchQueue.global(qos: .utility), using: dependencies)
.sink(
receiveCompletion: { [weak self] _ in
/// If the stream completes it means the network cache was reset in which case we want to
/// re-register for updates in the next run loop (as the new cache should be created by then)
DispatchQueue.global(qos: .background).async {
self?.registerNetworkObservables(using: dependencies)
}
},
receiveValue: { [weak self] paths in
dependencies.mutate(cache: .ip2Country) { _ in
self?.populateCacheIfNeeded(paths: paths)
}
}
)
.store(in: &disposables)
}

private func populateCacheIfNeeded(paths: [[LibSession.Snode]]) {
guard !paths.isEmpty else { return }

paths.forEach { path in
path.forEach { snode in
self.cacheCountry(for: snode.ip, inCache: &countryNamesCache)
}
}

self._cacheLoaded.send(true)
Log.info(.ip2Country, "Update onion request path countries.")
}

private func cacheCountry(for ip: String, inCache nameCache: inout [String: String]) {
let currentLocale: String = self.currentLocale // Store local copy for efficiency

guard nameCache["\(ip)-\(currentLocale)"] == nil else { return }

/// Code block checks if IP passed is unknown, not supported or blocked
guard
let ipAsInt: Int64 = IPv4.toInt(ip),
let countryBlockGeonameIdIndex: Int = cache.countryBlocksIPInt.firstIndex(where: { $0 > ipAsInt }).map({ $0 - 1 })
else { return }

/// Get local index for the current locale
/// When index is not found it should fallback to english
var validLocaleStartIndex: Int? {
cache.countryLocationsLocaleCode.firstIndex(of: currentLocale)
?? cache.countryLocationsLocaleCode.firstIndex(of: "en")
}

guard
let localeStartIndex: Int = validLocaleStartIndex,
let countryNameIndex: Int = Array(cache.countryLocationsGeonameId[localeStartIndex...]).firstIndex(where: { geonameId in
geonameId == cache.countryBlocksGeonameId[countryBlockGeonameIdIndex]
}),
(localeStartIndex + countryNameIndex) < cache.countryLocationsCountryName.count
else { return }

let result: String = cache.countryLocationsCountryName[localeStartIndex + countryNameIndex]
nameCache["\(ip)-\(currentLocale)"] = result
}

// MARK: - Functions

public func country(for ip: String) -> String {
guard _cacheLoaded.value else { return "resolving".localized() }

return (countryNamesCache["\(ip)-\(currentLocale)"] ?? "onionRoutingPathUnknownCountry".localized())
/// Get local index for the current locale (when index is not found it should fallback to english)
let validLocaleStartIndex: Int? = (
cache.countryLocationsLocaleCode.firstIndex(of: currentLocale) ??
cache.countryLocationsLocaleCode.firstIndex(of: "en")
)
let key: String = "\(ip)-\(currentLocale)"

switch countryNamesCache[key] {
case .some(let value): return value
case .none:
guard
let ipAsInt: Int64 = IPv4.toInt(ip),
let countryBlockGeonameIdIndex: Int = cache.countryBlocksIPInt.firstIndex(where: { $0 > ipAsInt }).map({ $0 - 1 }),
let localeStartIndex: Int = validLocaleStartIndex,
let countryNameIndex: Int = Array(cache.countryLocationsGeonameId[localeStartIndex...]).firstIndex(where: { geonameId in
geonameId == cache.countryBlocksGeonameId[countryBlockGeonameIdIndex]
}),
(localeStartIndex + countryNameIndex) < cache.countryLocationsCountryName.count
else { return "onionRoutingPathUnknownCountry".localized() }

let result: String = cache.countryLocationsCountryName[localeStartIndex + countryNameIndex]
countryNamesCache[key] = result

return result
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1052,15 +1052,19 @@ public extension SessionThreadViewModel {

return SQL("""
(IFNULL(\(thread[.pinnedPriority]), 0) > 0) DESC,
IFNULL(\(interaction[.timestampMs]), (\(thread[.creationDateTimestamp]) * 1000)) DESC
IFNULL(\(interaction[.timestampMs]), (\(thread[.creationDateTimestamp]) * 1000)) DESC,
\(thread[.id]) DESC
""")
}()

static let messageRequestsOrderSQL: SQL = {
let thread: TypedTableAlias<SessionThread> = TypedTableAlias()
let interaction: TypedTableAlias<Interaction> = TypedTableAlias()

return SQL("IFNULL(\(interaction[.timestampMs]), (\(thread[.creationDateTimestamp]) * 1000)) DESC")
return SQL("""
IFNULL(\(interaction[.timestampMs]), (\(thread[.creationDateTimestamp]) * 1000)) DESC,
\(thread[.id]) DESC
""")
}()
}

Expand Down